[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71JK1CK5MS5KGJH0R98DN3H":3,"skill-same:01M71JK1CK5MS5KGJH0R98DN3H":101},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":54,"commitSha":55,"skillDirectory":5,"forksCount":14,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":58,"ownerDescription":59,"updatedAt":60,"install":61,"resources":74},"01M71JK1CK5MS5KGJH0R98DN3H","torch-geometric",null,"PyTorch Geometric (PyG) for graph neural networks — node\u002Flink\u002Fgraph classification, message passing (GCN, GAT, GraphSAGE, GIN), heterogeneous graphs, neighbor sampling, and custom datasets. Use when working with torch_geometric, not for general NetworkX analytics or non-graph PyTorch models.","agency-black\u002FSkills","agency-black","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F234862658?v=4","01M6HWVFPNGNR5N2CX9ECSAD57","agencia.black","01M719WF77BF3HN0N9FK1APEFY",0,"MIT","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"torch geometric","analytics","classification","general","python","networks","for","cluster","graph neural networks","graph","org","data","gin","node","lib","message","when","sampling","pytorch","neural networks","2026-11-10 10:12:30",false,"---\nname: torch-geometric\ndescription: PyTorch Geometric (PyG) for graph neural networks — node\u002Flink\u002Fgraph classification, message passing (GCN, GAT, GraphSAGE, GIN), heterogeneous graphs, neighbor sampling, and custom datasets. Use when working with torch_geometric, not for general NetworkX analytics or non-graph PyTorch models.\nlicense: MIT license\ncompatibility: Requires Python 3.10+, PyTorch 2.6+, and torch-geometric 2.7.x. Optional extension wheels (pyg-lib, torch-scatter, torch-sparse, torch-cluster) must match your PyTorch\u002FCUDA build from https:\u002F\u002Fdata.pyg.org\u002Fwhl.\nmetadata:\n  version: \"1.1\"\n  skill-author: K-Dense Inc.\n---\n\n# PyTorch Geometric (PyG)\n\nPyG is the standard library for Graph Neural Networks built on PyTorch. It provides data structures for graphs, 60+ GNN layer implementations, scalable mini-batch training, and support for heterogeneous graphs.\n\n## Installation\n\nTested against **torch-geometric 2.7.x** (Oct 2025). Requires **Python 3.10+** and **PyTorch 2.6+**.\n\n```bash\n# 1. Install PyTorch first (match your CUDA\u002FCPU setup — see https:\u002F\u002Fpytorch.org\u002Fget-started\u002Flocally\u002F)\nuv pip install torch\n\n# 2. Core PyG (no extension wheels required for basic usage)\nuv pip install torch_geometric\n```\n\nOptional accelerated ops (`pyg-lib`, `torch-scatter`, `torch-sparse`, `torch-cluster`) are **not required** for basic PyG usage (since PyG 2.3). Install version-matched wheels from the [PyG wheel index](https:\u002F\u002Fdata.pyg.org\u002Fwhl) after checking your PyTorch and CUDA versions:\n\n```bash\npython -c \"import torch; print(torch.__version__, torch.version.cuda)\"\n# Then install wheels for your torch+CUDA combo, e.g.:\nuv pip install pyg-lib torch-scatter torch-sparse torch-cluster \\\n  -f https:\u002F\u002Fdata.pyg.org\u002Fwhl\u002Ftorch-2.8.0+cu128.html\n```\n\nCheck your version:\n\n```python\nimport torch_geometric\nprint(torch_geometric.__version__)\n```\n\n**Conda:** the `pyg` conda channel is no longer maintained for PyTorch >2.5 — use `uv pip install` and the wheel index above instead.\n\n### PyG 2.7 notes\n\nPyG 2.7 dropped Python 3.9 and PyTorch ≤2.5. See the [2.7.0 release notes](https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\u002Freleases\u002Ftag\u002F2.7.0) for PyTorch 2.6–2.8 compatibility tables. `torch_geometric.distributed` is deprecated — use standard `torch.distributed` DDP (see `references\u002Fscaling.md`).\n\n## Core Concepts\n\n### Graph Data: `Data` and `HeteroData`\n\nA graph lives in a `Data` object. The key attributes:\n\n```python\nfrom torch_geometric.data import Data\n\ndata = Data(\n    x=node_features,          # [num_nodes, num_node_features]\n    edge_index=edge_index,     # [2, num_edges] — COO format, dtype=torch.long\n    edge_attr=edge_features,   # [num_edges, num_edge_features]\n    y=labels,                  # node-level [num_nodes, *] or graph-level [1, *]\n    pos=positions,             # [num_nodes, num_dimensions] (for point clouds\u002Fspatial)\n)\n```\n\n**`edge_index` format is critical**: it's a `[2, num_edges]` tensor where `edge_index[0]` = source nodes, `edge_index[1]` = target nodes. It is NOT a list of tuples. If you have edge pairs as rows, transpose and call `.contiguous()`:\n\n```python\n# If edges are [[src1, dst1], [src2, dst2], ...] — transpose first:\nedge_index = edge_pairs.t().contiguous()\n```\n\nFor undirected graphs, include both directions: edge (0,1) needs both `[0,1]` and `[1,0]` in edge_index.\n\nFor heterogeneous graphs, use `HeteroData` — see the Heterogeneous Graphs section below.\n\n### Datasets\n\nPyG bundles many standard datasets that auto-download and preprocess:\n\n```python\nfrom torch_geometric.datasets import Planetoid, TUDataset\n\n# Single-graph node classification (Cora, Citeseer, Pubmed)\ndataset = Planetoid(root='.\u002Fdata', name='Cora')\ndata = dataset[0]  # single graph with train\u002Fval\u002Ftest masks\n\n# Multi-graph classification (ENZYMES, MUTAG, IMDB-BINARY, etc.)\ndataset = TUDataset(root='.\u002Fdata', name='ENZYMES')\n# dataset[0], dataset[1], ... are individual graphs\n```\n\nCommon datasets by task:\n- **Node classification**: Planetoid (Cora\u002FCiteseer\u002FPubmed), OGB (ogbn-arxiv, ogbn-products, ogbn-mag)\n- **Graph classification**: TUDataset (MUTAG, ENZYMES, PROTEINS, IMDB-BINARY), OGB (ogbg-molhiv)\n- **Link prediction**: OGB (ogbl-collab, ogbl-citation2)\n- **Molecular**: QM7, QM9, MoleculeNet\n- **Point cloud\u002Fmesh**: ShapeNet, ModelNet10\u002F40, FAUST\n\n### Transforms\n\nTransforms preprocess or augment graph data, analogous to torchvision transforms:\n\n```python\nimport torch_geometric.transforms as T\n\n# Common transforms\nT.NormalizeFeatures()    # Row-normalize node features to sum to 1\nT.ToUndirected()         # Add reverse edges to make graph undirected\nT.AddSelfLoops()         # Add self-loop edges\nT.KNNGraph(k=6)          # Build k-NN graph from point cloud positions\nT.RandomJitter(0.01)     # Random noise augmentation on positions\nT.Compose([...])         # Chain multiple transforms\n\n# Apply as pre_transform (once, saved to disk) or transform (every access)\ndataset = ShapeNet(root='.\u002Fdata', pre_transform=T.KNNGraph(k=6),\n                   transform=T.RandomJitter(0.01))\n```\n\n## Building GNN Models\n\n### Quick Start: Using Built-in Layers\n\nThe fastest way to build a GNN — stack conv layers from `torch_geometric.nn`:\n\n```python\nimport torch\nimport torch.nn.functional as F\nfrom torch_geometric.nn import GCNConv\n\nclass GCN(torch.nn.Module):\n    def __init__(self, in_channels, hidden_channels, out_channels):\n        super().__init__()\n        self.conv1 = GCNConv(in_channels, hidden_channels)\n        self.conv2 = GCNConv(hidden_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        x = self.conv1(x, edge_index).relu()\n        x = F.dropout(x, p=0.5, training=self.training)\n        x = self.conv2(x, edge_index)\n        return x\n```\n\n**Important**: PyG conv layers do NOT include activation functions — apply them yourself after each layer. This is by design for flexibility.\n\n### Choosing a Conv Layer\n\nPick based on your task and graph structure:\n\n| Layer | Best for | Key idea |\n|-------|----------|----------|\n| `GCNConv` | Homogeneous, semi-supervised node classification | Spectral-inspired, degree-normalized aggregation |\n| `GATConv` \u002F `GATv2Conv` | When neighbor importance varies | Attention-weighted messages |\n| `SAGEConv` | Large graphs, inductive settings | Sampling-friendly, learnable aggregation |\n| `GINConv` | Graph classification, maximizing expressiveness | As powerful as WL test |\n| `TransformerConv` | Rich edge features, complex interactions | Multi-head attention with edge features |\n| `EdgeConv` | Point clouds, dynamic graphs | MLP on edge features (x_i, x_j - x_i) |\n| `RGCNConv` | Heterogeneous with many relation types | Relation-specific weight matrices |\n| `HGTConv` | Heterogeneous graphs | Type-specific attention |\n\nAll conv layers accept `(x, edge_index)` at minimum. Many also accept `edge_attr` for edge features.\n\n### Lazy Initialization\n\nUse `-1` for input channels to let PyG infer dimensions automatically — especially useful for heterogeneous models:\n\n```python\nconv = SAGEConv((-1, -1), 64)  # Input dims inferred on first forward pass\n# Initialize lazy modules:\nwith torch.no_grad():\n    out = model(data.x, data.edge_index)\n```\n\n### High-Level Model APIs\n\nFor common architectures, PyG provides ready-made model classes:\n\n```python\nfrom torch_geometric.nn import GraphSAGE, GCN, GAT, GIN\n\nmodel = GraphSAGE(\n    in_channels=dataset.num_features,\n    hidden_channels=64,\n    out_channels=dataset.num_classes,\n    num_layers=2,\n)\n```\n\n### Custom Layers via MessagePassing\n\nTo implement a novel GNN layer, subclass `MessagePassing`. The framework is:\n\n1. `propagate()` orchestrates the message passing\n2. `message()` defines what info flows along each edge (the phi function)\n3. `aggregate()` combines messages at each node (sum\u002Fmean\u002Fmax)\n4. `update()` transforms the aggregated result (the gamma function)\n\n```python\nfrom torch_geometric.nn import MessagePassing\nfrom torch_geometric.utils import add_self_loops, degree\n\nclass MyConv(MessagePassing):\n    def __init__(self, in_channels, out_channels):\n        super().__init__(aggr='add')  # \"add\", \"mean\", or \"max\"\n        self.lin = torch.nn.Linear(in_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        # Pre-processing before message passing\n        x = self.lin(x)\n        # Start message passing\n        return self.propagate(edge_index, x=x)\n\n    def message(self, x_j):\n        # x_j: features of source nodes for each edge [num_edges, features]\n        # The _j suffix auto-indexes source nodes, _i indexes target nodes\n        return x_j\n```\n\n**The `_i` \u002F `_j` convention**: any tensor passed to `propagate()` can be auto-indexed by appending `_i` (target\u002Fcentral node) or `_j` (source\u002Fneighbor node) in the `message()` signature. So if you pass `x=...` to propagate, you can access `x_i` and `x_j` in message().\n\nRead `references\u002Fmessage_passing.md` for the full GCN and EdgeConv implementation examples.\n\n## Task-Specific Patterns\n\n### Node Classification\n\n```python\n# Full-batch training on a single graph (e.g., Cora)\nmodel.train()\nfor epoch in range(200):\n    optimizer.zero_grad()\n    out = model(data.x, data.edge_index)\n    loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask])\n    loss.backward()\n    optimizer.step()\n\n# Evaluation — train(False) puts the model in inference mode (disables dropout\u002FBN)\nmodel.train(False)\npred = model(data.x, data.edge_index).argmax(dim=1)\nacc = (pred[data.test_mask] == data.y[data.test_mask]).float().mean()\n```\n\n### Graph Classification\n\nMultiple graphs — use `DataLoader` for mini-batching and global pooling to get graph-level representations:\n\n```python\nfrom torch_geometric.loader import DataLoader\nfrom torch_geometric.nn import GCNConv, global_mean_pool\n\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\n\nclass GraphClassifier(torch.nn.Module):\n    def __init__(self, in_ch, hidden_ch, out_ch):\n        super().__init__()\n        self.conv1 = GCNConv(in_ch, hidden_ch)\n        self.conv2 = GCNConv(hidden_ch, hidden_ch)\n        self.lin = torch.nn.Linear(hidden_ch, out_ch)\n\n    def forward(self, x, edge_index, batch):\n        x = self.conv1(x, edge_index).relu()\n        x = self.conv2(x, edge_index).relu()\n        x = global_mean_pool(x, batch)  # [num_graphs_in_batch, hidden_ch]\n        return self.lin(x)\n\n# Training loop\nfor data in loader:\n    out = model(data.x, data.edge_index, data.batch)\n    loss = F.cross_entropy(out, data.y)\n```\n\nPyG's `DataLoader` batches multiple graphs by creating block-diagonal adjacency matrices. The `batch` tensor maps each node to its graph index. Pooling ops (`global_mean_pool`, `global_max_pool`, `global_add_pool`) use this to aggregate per-graph.\n\n### Link Prediction\n\nSplit edges into train\u002Fval\u002Ftest, use negative sampling:\n\n```python\nfrom torch_geometric.transforms import RandomLinkSplit\n\ntransform = RandomLinkSplit(\n    num_val=0.1,\n    num_test=0.1,\n    is_undirected=True,\n    add_negative_train_samples=False,\n)\ntrain_data, val_data, test_data = transform(data)\n\n# Encode nodes, then score edges\nz = model.encode(train_data.x, train_data.edge_index)\n# Positive edges\npos_score = (z[train_data.edge_label_index[0]] * z[train_data.edge_label_index[1]]).sum(dim=1)\n```\n\nRead `references\u002Flink_prediction.md` for the complete link prediction guide: GAE\u002FVGAE autoencoders, full training loops, LinkNeighborLoader for large graphs, heterogeneous link prediction, and evaluation metrics.\n\n## Scaling to Large Graphs\n\nFor graphs that don't fit in GPU memory, use neighbor sampling via `NeighborLoader`:\n\n```python\nfrom torch_geometric.loader import NeighborLoader\n\ntrain_loader = NeighborLoader(\n    data,\n    num_neighbors=[15, 10],     # Sample 15 neighbors in hop 1, 10 in hop 2\n    batch_size=128,              # Number of seed nodes per batch\n    input_nodes=data.train_mask, # Which nodes to sample from\n    shuffle=True,\n)\n\nfor batch in train_loader:\n    batch = batch.to(device)\n    out = model(batch.x, batch.edge_index)\n    # Only use first batch_size nodes for loss (these are the seed nodes)\n    loss = F.cross_entropy(out[:batch.batch_size], batch.y[:batch.batch_size])\n```\n\n**Key points about NeighborLoader**:\n- `num_neighbors` list length should match GNN depth (number of message passing layers)\n- Seed nodes are always the first `batch.batch_size` nodes in the output\n- `batch.n_id` maps relabeled indices back to original node IDs\n- Works for both `Data` and `HeteroData`\n- For link prediction, use `LinkNeighborLoader` instead\n- Sampling more than 2-3 hops is generally infeasible (exponential blowup)\n\nOther scalability options: `ClusterLoader` (ClusterGCN), `GraphSAINTSampler`, `ShaDowKHopSampler`. For multi-GPU training, DDP, PyTorch Lightning integration, and `torch.compile` support, read `references\u002Fscaling.md`.\n\n## Heterogeneous Graphs\n\nFor graphs with multiple node and edge types (social networks, knowledge graphs, recommendation):\n\n```python\nfrom torch_geometric.data import HeteroData\n\ndata = HeteroData()\n\n# Node features — indexed by node type string\ndata['user'].x = torch.randn(1000, 64)\ndata['movie'].x = torch.randn(500, 128)\n\n# Edge indices — indexed by (src_type, edge_type, dst_type) triplet\ndata['user', 'rates', 'movie'].edge_index = torch.randint(0, 500, (2, 3000))\ndata['user', 'follows', 'user'].edge_index = torch.randint(0, 1000, (2, 5000))\n\n# Access convenience dicts\ndata.x_dict        # {'user': tensor, 'movie': tensor}\ndata.edge_index_dict  # {('user','rates','movie'): tensor, ...}\ndata.metadata()    # ([node_types], [edge_types])\n```\n\n### Three ways to build heterogeneous GNNs\n\n**1. Auto-convert with `to_hetero()`** — write a homogeneous model, convert automatically:\n\n```python\nfrom torch_geometric.nn import SAGEConv, to_hetero\n\nclass GNN(torch.nn.Module):\n    def __init__(self, hidden_channels, out_channels):\n        super().__init__()\n        self.conv1 = SAGEConv((-1, -1), hidden_channels)\n        self.conv2 = SAGEConv((-1, -1), out_channels)\n\n    def forward(self, x, edge_index):\n        x = self.conv1(x, edge_index).relu()\n        x = self.conv2(x, edge_index)\n        return x\n\nmodel = GNN(64, dataset.num_classes)\nmodel = to_hetero(model, data.metadata(), aggr='sum')\n\n# Now accepts dicts:\nout = model(data.x_dict, data.edge_index_dict)\n```\n\nUse `(-1, -1)` for bipartite input channels (source, target may differ). Lazy init handles the rest.\n\n**2. `HeteroConv` wrapper** — different conv per edge type:\n\n```python\nfrom torch_geometric.nn import HeteroConv, GCNConv, SAGEConv, GATConv\n\nconv = HeteroConv({\n    ('paper', 'cites', 'paper'): GCNConv(-1, 64),\n    ('author', 'writes', 'paper'): SAGEConv((-1, -1), 64),\n    ('paper', 'rev_writes', 'author'): GATConv((-1, -1), 64, add_self_loops=False),\n}, aggr='sum')\n```\n\n**3. Native heterogeneous operators** like `HGTConv`:\n\n```python\nfrom torch_geometric.nn import HGTConv\nconv = HGTConv(hidden_channels, hidden_channels, data.metadata(), num_heads=4)\n```\n\n**Important for heterogeneous graphs**:\n- Use `T.ToUndirected()` to add reverse edge types for bidirectional message flow\n- Disable `add_self_loops` in bipartite conv layers (different source\u002Fdest types) — use skip connections instead: `conv(x, edge_index) + lin(x)`\n- For NeighborLoader on HeteroData, specify `input_nodes` as `('node_type', mask)` tuple\n- `num_neighbors` can be a dict keyed by edge type for fine-grained control\n\nRead `references\u002Fheterogeneous.md` for complete examples including training loops and NeighborLoader usage with heterogeneous graphs.\n\n## Custom Datasets\n\nFor loading your own data into PyG:\n\n- **Quick (no class needed)**: Create `Data` objects directly and pass a list to `DataLoader`\n- **Reusable (fits in RAM)**: Subclass `InMemoryDataset` — override `raw_file_names`, `processed_file_names`, `download()`, `process()`\n- **Large (disk-backed)**: Subclass `Dataset` — also override `len()` and `get()`\n- **From CSV**: Load node\u002Fedge tables with pandas, build mappings to consecutive indices, assemble into `Data` or `HeteroData`\n- **From NetworkX**: `from_networkx(G)` converts a NetworkX graph directly\n- **From scipy sparse**: `from_scipy_sparse_matrix(adj)` extracts edge_index\n\nRead `references\u002Fcustom_datasets.md` for complete examples with all patterns, CSV loading with encoders, and the MovieLens walkthrough.\n\n## Explainability\n\nPyG provides `torch_geometric.explain` for interpreting GNN predictions:\n\n```python\nfrom torch_geometric.explain import Explainer, GNNExplainer\n\nexplainer = Explainer(\n    model=model,\n    algorithm=GNNExplainer(epochs=200),\n    explanation_type='model',\n    node_mask_type='attributes',\n    edge_mask_type='object',\n    model_config=dict(\n        mode='multiclass_classification',\n        task_level='node',\n        return_type='log_probs',\n    ),\n)\n\nexplanation = explainer(data.x, data.edge_index, index=10)\nexplanation.visualize_graph()           # Important subgraph\nexplanation.visualize_feature_importance(top_k=10)  # Feature importance\n```\n\nAvailable algorithms: `GNNExplainer` (optimization-based), `PGExplainer` (parametric, trained), `CaptumExplainer` (gradient-based via Captum), `AttentionExplainer` (attention weights). Works for both homogeneous and heterogeneous graphs.\n\nRead `references\u002Fexplainability.md` for all algorithms, heterogeneous explanations, evaluation metrics, and PGExplainer training.\n\n## Common Pitfalls\n\n1. **edge_index shape**: Must be `[2, num_edges]`, not `[num_edges, 2]`. Transpose if needed.\n2. **Forgetting activations**: Conv layers don't include ReLU\u002Fetc — add them manually.\n3. **Self-loops in hetero bipartite**: Don't use `add_self_loops=True` when source and dest node types differ. Use skip connections instead.\n4. **NeighborLoader slicing**: Only the first `batch.batch_size` nodes are your seed nodes. Slice predictions and labels accordingly.\n5. **Undirected graphs**: If your graph is undirected, include edges in both directions in `edge_index`, or use `T.ToUndirected()`.\n6. **Lazy init**: Models with `-1` input channels need one forward pass with `torch.no_grad()` before training to initialize parameters.\n7. **Global pooling for graph tasks**: Use `global_mean_pool(x, batch)` (not manual reshape) to aggregate node features to graph-level.\n8. **num_neighbors alignment**: Keep `len(num_neighbors)` equal to the number of GNN layers. More hops than layers wastes compute; fewer means wasted model capacity.\n","# PyTorch Geometric (PyG)\n\nPyG is the standard library for Graph Neural Networks built on PyTorch. It provides data structures for graphs, 60+ GNN layer implementations, scalable mini-batch training, and support for heterogeneous graphs.\n\n## Installation\n\nTested against **torch-geometric 2.7.x** (Oct 2025). Requires **Python 3.10+** and **PyTorch 2.6+**.\n\n```bash\n# 1. Install PyTorch first (match your CUDA\u002FCPU setup — see https:\u002F\u002Fpytorch.org\u002Fget-started\u002Flocally\u002F)\nuv pip install torch\n\n# 2. Core PyG (no extension wheels required for basic usage)\nuv pip install torch_geometric\n```\n\nOptional accelerated ops (`pyg-lib`, `torch-scatter`, `torch-sparse`, `torch-cluster`) are **not required** for basic PyG usage (since PyG 2.3). Install version-matched wheels from the [PyG wheel index](https:\u002F\u002Fdata.pyg.org\u002Fwhl) after checking your PyTorch and CUDA versions:\n\n```bash\npython -c \"import torch; print(torch.__version__, torch.version.cuda)\"\n# Then install wheels for your torch+CUDA combo, e.g.:\nuv pip install pyg-lib torch-scatter torch-sparse torch-cluster \\\n  -f https:\u002F\u002Fdata.pyg.org\u002Fwhl\u002Ftorch-2.8.0+cu128.html\n```\n\nCheck your version:\n\n```python\nimport torch_geometric\nprint(torch_geometric.__version__)\n```\n\n**Conda:** the `pyg` conda channel is no longer maintained for PyTorch >2.5 — use `uv pip install` and the wheel index above instead.\n\n### PyG 2.7 notes\n\nPyG 2.7 dropped Python 3.9 and PyTorch ≤2.5. See the [2.7.0 release notes](https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\u002Freleases\u002Ftag\u002F2.7.0) for PyTorch 2.6–2.8 compatibility tables. `torch_geometric.distributed` is deprecated — use standard `torch.distributed` DDP (see `references\u002Fscaling.md`).\n\n## Core Concepts\n\n### Graph Data: `Data` and `HeteroData`\n\nA graph lives in a `Data` object. The key attributes:\n\n```python\nfrom torch_geometric.data import Data\n\ndata = Data(\n    x=node_features,          # [num_nodes, num_node_features]\n    edge_index=edge_index,     # [2, num_edges] — COO format, dtype=torch.long\n    edge_attr=edge_features,   # [num_edges, num_edge_features]\n    y=labels,                  # node-level [num_nodes, *] or graph-level [1, *]\n    pos=positions,             # [num_nodes, num_dimensions] (for point clouds\u002Fspatial)\n)\n```\n\n**`edge_index` format is critical**: it's a `[2, num_edges]` tensor where `edge_index[0]` = source nodes, `edge_index[1]` = target nodes. It is NOT a list of tuples. If you have edge pairs as rows, transpose and call `.contiguous()`:\n\n```python\n# If edges are [[src1, dst1], [src2, dst2], ...] — transpose first:\nedge_index = edge_pairs.t().contiguous()\n```\n\nFor undirected graphs, include both directions: edge (0,1) needs both `[0,1]` and `[1,0]` in edge_index.\n\nFor heterogeneous graphs, use `HeteroData` — see the Heterogeneous Graphs section below.\n\n### Datasets\n\nPyG bundles many standard datasets that auto-download and preprocess:\n\n```python\nfrom torch_geometric.datasets import Planetoid, TUDataset\n\n# Single-graph node classification (Cora, Citeseer, Pubmed)\ndataset = Planetoid(root='.\u002Fdata', name='Cora')\ndata = dataset[0]  # single graph with train\u002Fval\u002Ftest masks\n\n# Multi-graph classification (ENZYMES, MUTAG, IMDB-BINARY, etc.)\ndataset = TUDataset(root='.\u002Fdata', name='ENZYMES')\n# dataset[0], dataset[1], ... are individual graphs\n```\n\nCommon datasets by task:\n- **Node classification**: Planetoid (Cora\u002FCiteseer\u002FPubmed), OGB (ogbn-arxiv, ogbn-products, ogbn-mag)\n- **Graph classification**: TUDataset (MUTAG, ENZYMES, PROTEINS, IMDB-BINARY), OGB (ogbg-molhiv)\n- **Link prediction**: OGB (ogbl-collab, ogbl-citation2)\n- **Molecular**: QM7, QM9, MoleculeNet\n- **Point cloud\u002Fmesh**: ShapeNet, ModelNet10\u002F40, FAUST\n\n### Transforms\n\nTransforms preprocess or augment graph data, analogous to torchvision transforms:\n\n```python\nimport torch_geometric.transforms as T\n\n# Common transforms\nT.NormalizeFeatures()    # Row-normalize node features to sum to 1\nT.ToUndirected()         # Add reverse edges to make graph undirected\nT.AddSelfLoops()         # Add self-loop edges\nT.KNNGraph(k=6)          # Build k-NN graph from point cloud positions\nT.RandomJitter(0.01)     # Random noise augmentation on positions\nT.Compose([...])         # Chain multiple transforms\n\n# Apply as pre_transform (once, saved to disk) or transform (every access)\ndataset = ShapeNet(root='.\u002Fdata', pre_transform=T.KNNGraph(k=6),\n                   transform=T.RandomJitter(0.01))\n```\n\n## Building GNN Models\n\n### Quick Start: Using Built-in Layers\n\nThe fastest way to build a GNN — stack conv layers from `torch_geometric.nn`:\n\n```python\nimport torch\nimport torch.nn.functional as F\nfrom torch_geometric.nn import GCNConv\n\nclass GCN(torch.nn.Module):\n    def __init__(self, in_channels, hidden_channels, out_channels):\n        super().__init__()\n        self.conv1 = GCNConv(in_channels, hidden_channels)\n        self.conv2 = GCNConv(hidden_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        x = self.conv1(x, edge_index).relu()\n        x = F.dropout(x, p=0.5, training=self.training)\n        x = self.conv2(x, edge_index)\n        return x\n```\n\n**Important**: PyG conv layers do NOT include activation functions — apply them yourself after each layer. This is by design for flexibility.\n\n### Choosing a Conv Layer\n\nPick based on your task and graph structure:\n\n| Layer | Best for | Key idea |\n|-------|----------|----------|\n| `GCNConv` | Homogeneous, semi-supervised node classification | Spectral-inspired, degree-normalized aggregation |\n| `GATConv` \u002F `GATv2Conv` | When neighbor importance varies | Attention-weighted messages |\n| `SAGEConv` | Large graphs, inductive settings | Sampling-friendly, learnable aggregation |\n| `GINConv` | Graph classification, maximizing expressiveness | As powerful as WL test |\n| `TransformerConv` | Rich edge features, complex interactions | Multi-head attention with edge features |\n| `EdgeConv` | Point clouds, dynamic graphs | MLP on edge features (x_i, x_j - x_i) |\n| `RGCNConv` | Heterogeneous with many relation types | Relation-specific weight matrices |\n| `HGTConv` | Heterogeneous graphs | Type-specific attention |\n\nAll conv layers accept `(x, edge_index)` at minimum. Many also accept `edge_attr` for edge features.\n\n### Lazy Initialization\n\nUse `-1` for input channels to let PyG infer dimensions automatically — especially useful for heterogeneous models:\n\n```python\nconv = SAGEConv((-1, -1), 64)  # Input dims inferred on first forward pass\n# Initialize lazy modules:\nwith torch.no_grad():\n    out = model(data.x, data.edge_index)\n```\n\n### High-Level Model APIs\n\nFor common architectures, PyG provides ready-made model classes:\n\n```python\nfrom torch_geometric.nn import GraphSAGE, GCN, GAT, GIN\n\nmodel = GraphSAGE(\n    in_channels=dataset.num_features,\n    hidden_channels=64,\n    out_channels=dataset.num_classes,\n    num_layers=2,\n)\n```\n\n### Custom Layers via MessagePassing\n\nTo implement a novel GNN layer, subclass `MessagePassing`. The framework is:\n\n1. `propagate()` orchestrates the message passing\n2. `message()` defines what info flows along each edge (the phi function)\n3. `aggregate()` combines messages at each node (sum\u002Fmean\u002Fmax)\n4. `update()` transforms the aggregated result (the gamma function)\n\n```python\nfrom torch_geometric.nn import MessagePassing\nfrom torch_geometric.utils import add_self_loops, degree\n\nclass MyConv(MessagePassing):\n    def __init__(self, in_channels, out_channels):\n        super().__init__(aggr='add')  # \"add\", \"mean\", or \"max\"\n        self.lin = torch.nn.Linear(in_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        # Pre-processing before message passing\n        x = self.lin(x)\n        # Start message passing\n        return self.propagate(edge_index, x=x)\n\n    def message(self, x_j):\n        # x_j: features of source nodes for each edge [num_edges, features]\n        # The _j suffix auto-indexes source nodes, _i indexes target nodes\n        return x_j\n```\n\n**The `_i` \u002F `_j` convention**: any tensor passed to `propagate()` can be auto-indexed by appending `_i` (target\u002Fcentral node) or `_j` (source\u002Fneighbor node) in the `message()` signature. So if you pass `x=...` to propagate, you can access `x_i` and `x_j` in message().\n\nRead `references\u002Fmessage_passing.md` for the full GCN and EdgeConv implementation examples.\n\n## Task-Specific Patterns\n\n### Node Classification\n\n```python\n# Full-batch training on a single graph (e.g., Cora)\nmodel.train()\nfor epoch in range(200):\n    optimizer.zero_grad()\n    out = model(data.x, data.edge_index)\n    loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask])\n    loss.backward()\n    optimizer.step()\n\n# Evaluation — train(False) puts the model in inference mode (disables dropout\u002FBN)\nmodel.train(False)\npred = model(data.x, data.edge_index).argmax(dim=1)\nacc = (pred[data.test_mask] == data.y[data.test_mask]).float().mean()\n```\n\n### Graph Classification\n\nMultiple graphs — use `DataLoader` for mini-batching and global pooling to get graph-level representations:\n\n```python\nfrom torch_geometric.loader import DataLoader\nfrom torch_geometric.nn import GCNConv, global_mean_pool\n\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\n\nclass GraphClassifier(torch.nn.Module):\n    def __init__(self, in_ch, hidden_ch, out_ch):\n        super().__init__()\n        self.conv1 = GCNConv(in_ch, hidden_ch)\n        self.conv2 = GCNConv(hidden_ch, hidden_ch)\n        self.lin = torch.nn.Linear(hidden_ch, out_ch)\n\n    def forward(self, x, edge_index, batch):\n        x = self.conv1(x, edge_index).relu()\n        x = self.conv2(x, edge_index).relu()\n        x = global_mean_pool(x, batch)  # [num_graphs_in_batch, hidden_ch]\n        return self.lin(x)\n\n# Training loop\nfor data in loader:\n    out = model(data.x, data.edge_index, data.batch)\n    loss = F.cross_entropy(out, data.y)\n```\n\nPyG's `DataLoader` batches multiple graphs by creating block-diagonal adjacency matrices. The `batch` tensor maps each node to its graph index. Pooling ops (`global_mean_pool`, `global_max_pool`, `global_add_pool`) use this to aggregate per-graph.\n\n### Link Prediction\n\nSplit edges into train\u002Fval\u002Ftest, use negative sampling:\n\n```python\nfrom torch_geometric.transforms import RandomLinkSplit\n\ntransform = RandomLinkSplit(\n    num_val=0.1,\n    num_test=0.1,\n    is_undirected=True,\n    add_negative_train_samples=False,\n)\ntrain_data, val_data, test_data = transform(data)\n\n# Encode nodes, then score edges\nz = model.encode(train_data.x, train_data.edge_index)\n# Positive edges\npos_score = (z[train_data.edge_label_index[0]] * z[train_data.edge_label_index[1]]).sum(dim=1)\n```\n\nRead `references\u002Flink_prediction.md` for the complete link prediction guide: GAE\u002FVGAE autoencoders, full training loops, LinkNeighborLoader for large graphs, heterogeneous link prediction, and evaluation metrics.\n\n## Scaling to Large Graphs\n\nFor graphs that don't fit in GPU memory, use neighbor sampling via `NeighborLoader`:\n\n```python\nfrom torch_geometric.loader import NeighborLoader\n\ntrain_loader = NeighborLoader(\n    data,\n    num_neighbors=[15, 10],     # Sample 15 neighbors in hop 1, 10 in hop 2\n    batch_size=128,              # Number of seed nodes per batch\n    input_nodes=data.train_mask, # Which nodes to sample from\n    shuffle=True,\n)\n\nfor batch in train_loader:\n    batch = batch.to(device)\n    out = model(batch.x, batch.edge_index)\n    # Only use first batch_size nodes for loss (these are the seed nodes)\n    loss = F.cross_entropy(out[:batch.batch_size], batch.y[:batch.batch_size])\n```\n\n**Key points about NeighborLoader**:\n- `num_neighbors` list length should match GNN depth (number of message passing layers)\n- Seed nodes are always the first `batch.batch_size` nodes in the output\n- `batch.n_id` maps relabeled indices back to original node IDs\n- Works for both `Data` and `HeteroData`\n- For link prediction, use `LinkNeighborLoader` instead\n- Sampling more than 2-3 hops is generally infeasible (exponential blowup)\n\nOther scalability options: `ClusterLoader` (ClusterGCN), `GraphSAINTSampler`, `ShaDowKHopSampler`. For multi-GPU training, DDP, PyTorch Lightning integration, and `torch.compile` support, read `references\u002Fscaling.md`.\n\n## Heterogeneous Graphs\n\nFor graphs with multiple node and edge types (social networks, knowledge graphs, recommendation):\n\n```python\nfrom torch_geometric.data import HeteroData\n\ndata = HeteroData()\n\n# Node features — indexed by node type string\ndata['user'].x = torch.randn(1000, 64)\ndata['movie'].x = torch.randn(500, 128)\n\n# Edge indices — indexed by (src_type, edge_type, dst_type) triplet\ndata['user', 'rates', 'movie'].edge_index = torch.randint(0, 500, (2, 3000))\ndata['user', 'follows', 'user'].edge_index = torch.randint(0, 1000, (2, 5000))\n\n# Access convenience dicts\ndata.x_dict        # {'user': tensor, 'movie': tensor}\ndata.edge_index_dict  # {('user','rates','movie'): tensor, ...}\ndata.metadata()    # ([node_types], [edge_types])\n```\n\n### Three ways to build heterogeneous GNNs\n\n**1. Auto-convert with `to_hetero()`** — write a homogeneous model, convert automatically:\n\n```python\nfrom torch_geometric.nn import SAGEConv, to_hetero\n\nclass GNN(torch.nn.Module):\n    def __init__(self, hidden_channels, out_channels):\n        super().__init__()\n        self.conv1 = SAGEConv((-1, -1), hidden_channels)\n        self.conv2 = SAGEConv((-1, -1), out_channels)\n\n    def forward(self, x, edge_index):\n        x = self.conv1(x, edge_index).relu()\n        x = self.conv2(x, edge_index)\n        return x\n\nmodel = GNN(64, dataset.num_classes)\nmodel = to_hetero(model, data.metadata(), aggr='sum')\n\n# Now accepts dicts:\nout = model(data.x_dict, data.edge_index_dict)\n```\n\nUse `(-1, -1)` for bipartite input channels (source, target may differ). Lazy init handles the rest.\n\n**2. `HeteroConv` wrapper** — different conv per edge type:\n\n```python\nfrom torch_geometric.nn import HeteroConv, GCNConv, SAGEConv, GATConv\n\nconv = HeteroConv({\n    ('paper', 'cites', 'paper'): GCNConv(-1, 64),\n    ('author', 'writes', 'paper'): SAGEConv((-1, -1), 64),\n    ('paper', 'rev_writes', 'author'): GATConv((-1, -1), 64, add_self_loops=False),\n}, aggr='sum')\n```\n\n**3. Native heterogeneous operators** like `HGTConv`:\n\n```python\nfrom torch_geometric.nn import HGTConv\nconv = HGTConv(hidden_channels, hidden_channels, data.metadata(), num_heads=4)\n```\n\n**Important for heterogeneous graphs**:\n- Use `T.ToUndirected()` to add reverse edge types for bidirectional message flow\n- Disable `add_self_loops` in bipartite conv layers (different source\u002Fdest types) — use skip connections instead: `conv(x, edge_index) + lin(x)`\n- For NeighborLoader on HeteroData, specify `input_nodes` as `('node_type', mask)` tuple\n- `num_neighbors` can be a dict keyed by edge type for fine-grained control\n\nRead `references\u002Fheterogeneous.md` for complete examples including training loops and NeighborLoader usage with heterogeneous graphs.\n\n## Custom Datasets\n\nFor loading your own data into PyG:\n\n- **Quick (no class needed)**: Create `Data` objects directly and pass a list to `DataLoader`\n- **Reusable (fits in RAM)**: Subclass `InMemoryDataset` — override `raw_file_names`, `processed_file_names`, `download()`, `process()`\n- **Large (disk-backed)**: Subclass `Dataset` — also override `len()` and `get()`\n- **From CSV**: Load node\u002Fedge tables with pandas, build mappings to consecutive indices, assemble into `Data` or `HeteroData`\n- **From NetworkX**: `from_networkx(G)` converts a NetworkX graph directly\n- **From scipy sparse**: `from_scipy_sparse_matrix(adj)` extracts edge_index\n\nRead `references\u002Fcustom_datasets.md` for complete examples with all patterns, CSV loading with encoders, and the MovieLens walkthrough.\n\n## Explainability\n\nPyG provides `torch_geometric.explain` for interpreting GNN predictions:\n\n```python\nfrom torch_geometric.explain import Explainer, GNNExplainer\n\nexplainer = Explainer(\n    model=model,\n    algorithm=GNNExplainer(epochs=200),\n    explanation_type='model',\n    node_mask_type='attributes',\n    edge_mask_type='object',\n    model_config=dict(\n        mode='multiclass_classification',\n        task_level='node',\n        return_type='log_probs',\n    ),\n)\n\nexplanation = explainer(data.x, data.edge_index, index=10)\nexplanation.visualize_graph()           # Important subgraph\nexplanation.visualize_feature_importance(top_k=10)  # Feature importance\n```\n\nAvailable algorithms: `GNNExplainer` (optimization-based), `PGExplainer` (parametric, trained), `CaptumExplainer` (gradient-based via Captum), `AttentionExplainer` (attention weights). Works for both homogeneous and heterogeneous graphs.\n\nRead `references\u002Fexplainability.md` for all algorithms, heterogeneous explanations, evaluation metrics, and PGExplainer training.\n\n## Common Pitfalls\n\n1. **edge_index shape**: Must be `[2, num_edges]`, not `[num_edges, 2]`. Transpose if needed.\n2. **Forgetting activations**: Conv layers don't include ReLU\u002Fetc — add them manually.\n3. **Self-loops in hetero bipartite**: Don't use `add_self_loops=True` when source and dest node types differ. Use skip connections instead.\n4. **NeighborLoader slicing**: Only the first `batch.batch_size` nodes are your seed nodes. Slice predictions and labels accordingly.\n5. **Undirected graphs**: If your graph is undirected, include edges in both directions in `edge_index`, or use `T.ToUndirected()`.\n6. **Lazy init**: Models with `-1` input channels need one forward pass with `torch.no_grad()` before training to initialize parameters.\n7. **Global pooling for graph tasks**: Use `global_mean_pool(x, batch)` (not manual reshape) to aggregate node features to graph-level.\n8. **num_neighbors alignment**: Keep `len(num_neighbors)` equal to the number of GNN layers. More hops than layers wastes compute; fewer means wasted model capacity.\n",{"name":5,"license":49,"metadata":50,"description":7,"compatibility":53},"MIT license",{"version":51,"skill-author":52},"1.1","K-Dense Inc.","Requires Python 3.10+, PyTorch 2.6+, and torch-geometric 2.7.x. Optional extension wheels (pyg-lib, torch-scatter, torch-sparse, torch-cluster) must match your PyTorch\u002FCUDA build from https:\u002F\u002Fdata.pyg.org\u002Fwhl.","main","681496e0662f4c45c4758fae9d4510ae87311bf2","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills","https:\u002F\u002Fgithub.com\u002Fagency-black","http:\u002F\u002Fwww.dogma.black","Las grandes ideas merecen una ejecución impecable. Construimos plataformas web, aplicaciones y ecosistemas digitales completos. Esta Trinidad es nuestro dogma.","2026-05-29 16:13:55",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add agency-black\u002FSkills --skill torch-geometric",{"tool":67,"command":68},"bunx","bunx skills add agency-black\u002FSkills --skill torch-geometric",{"tool":70,"command":71},"pnpm","pnpm dlx skills add agency-black\u002FSkills --skill torch-geometric","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002FSKILL.md",true,[75,81,85,89,93,97],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fcustom_datasets.md","REFERENCE","参考文档",7277,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Fcustom_datasets.md",{"path":82,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Fexplainability.md",6420,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Fexplainability.md",{"path":86,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":87,"sourceHtmlUrl":88},"references\u002Fheterogeneous.md",7935,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Fheterogeneous.md",{"path":90,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":91,"sourceHtmlUrl":92},"references\u002Flink_prediction.md",8386,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Flink_prediction.md",{"path":94,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":95,"sourceHtmlUrl":96},"references\u002Fmessage_passing.md",4266,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Fmessage_passing.md",{"path":98,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":99,"sourceHtmlUrl":100},"references\u002Fscaling.md",8688,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Ftorch-geometric\u002Freferences\u002Fscaling.md",[102,127,158,188,213,237],{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":108,"publishedAt":44},"01M71JZVZ0TVW7Z5DQBRWSBG8A","zarr-python","Chunked N-D arrays for cloud storage (Zarr-Python 3). Compressed arrays, parallel I\u002FO, S3\u002FGCS via fsspec, NumPy\u002FDask\u002FXarray compatible, for large-scale scientific computing pipelines.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fzarr-python\u002FSKILL.md",[],[109,28,110,111,112,113,114,115,116,117,118,119,120,30,121,122,123,124,125,126],"zarr python","zarr","arrays","Cloud Storage","remote","workflows","scientific","read","write","edit","parallel","dask","s3fs","use","numpy","s3","scientific computing","scale",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":131,"sourceHtmlUrl":132,"categories":133,"keywords":139,"publishedAt":44},"01M71JYXC5VAEJT8KXN5GRK32S","xvary-stock-research","Thesis-driven equity analysis from public SEC EDGAR and market data; \u002Fanalyze, \u002Fscore, \u002Fcompare workflows with bundled Python tools (Claude Code, Cursor, Codex).","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fxvary-stock-research\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fxvary-stock-research\u002FSKILL.md",[134],{"categoryNo":135,"categoryName":136,"taxonomyType":137,"taxonomyTypeDesc":138},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[140,141,142,143,144,145,146,28,147,114,148,149,150,151,152,153,154,155,156,157],"xvary","stock","research","xvary stock research","sec edgar","community","equity","thesis","analysis","code","Market","compare","market data","analyze","with","codex","cursor","2026",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":162,"licenseFileUrl":163,"sourceHtmlUrl":164,"categories":165,"keywords":172,"publishedAt":44},"01M71JVSDPDQ5040YBN6J1ASKY","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fwebapp-testing\u002FSKILL.md",[166,169],{"categoryNo":167,"categoryName":168,"taxonomyType":137,"taxonomyTypeDesc":138},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":170,"categoryName":171,"taxonomyType":137,"taxonomyTypeDesc":138},"01JBSEEDCAT000000000000009","前端开发",[173,174,175,30,176,177,178,179,180,181,182,154,183,184,185,186,187],"webapp","testing","webapp testing","applications","local","frontend","debugging","toolkit","logs","browser","playwright","web","behavior","ui","screenshots",{"skillNo":189,"name":190,"nameZh":6,"description":191,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":162,"licenseFileUrl":192,"sourceHtmlUrl":193,"categories":194,"keywords":196,"publishedAt":44},"01M71JV64CW7R6FYYK9JWWGW0X","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fweb-artifacts-builder\u002FSKILL.md",[195],{"categoryNo":170,"categoryName":171,"taxonomyType":137,"taxonomyTypeDesc":138},[197,198,199,184,200,201,202,30,203,204,178,205,122,206,207,208,209,210,211,212],"builder","artifacts builder","artifacts","web artifacts builder","single-file","css","Tailwind","ui components","single","file","components","react","multi","state","routing","state management",{"skillNo":214,"name":215,"nameZh":6,"description":216,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":217,"categories":218,"keywords":220,"publishedAt":44},"01M71JS4X2FRY41DE84DEP06MN","vercel-react-view-transitions","Guide for implementing smooth, native-feeling animations using React's View Transition API (`\u003CViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter\u002Fexit of components, animate list reorder, implement directional (forward\u002Fback) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view transitions, `startViewTransition`, `ViewTransition`, transition types, or asks about animating between UI states in React without third-party animation libraries.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fvercel-react-view-transitions\u002FSKILL.md",[219],{"categoryNo":170,"categoryName":171,"taxonomyType":137,"taxonomyTypeDesc":138},[208,221,222,223,224,225,226,227,228,202,229,230,231,232,40,207,233,234,235,236],"vercel react view transitions","view","react view transitions","vercel","transitions","shared","back","Animation","types","states","element","implementing","api","route","create","libraries",{"skillNo":238,"name":239,"nameZh":6,"description":240,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":241,"categories":242,"keywords":244,"publishedAt":44},"01M71JS1WZ1J4F9YVC2203JBJW","vercel-react-native-skills","React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fvercel-react-native-skills\u002FSKILL.md",[243],{"categoryNo":170,"categoryName":171,"taxonomyType":137,"taxonomyTypeDesc":138},[224,245,208,246,247,248,249,250,251,30,252,232,253,122,254,255,40,256,257,207],"vercel react native skills","react native","native","react native skills","modules","platform","animations","performance","triggers","react native components","apps","best practices","tasks"]