Tora is a cute little ๐ automatic transpiler for PyTorch function definition to proprietary C++ code with bindings to the libtorch C++ API functions.
- Reads PyTorch
native_functions.yaml - Parses function schemas into typed IR
- Filters by a file-based allowlist
- Emits C++ node definition files with deterministic IDs
src/cli.ts- CLI entrypointsrc/generator.ts- end-to-end generation pipelinesrc/schemaParser.ts-func:schema parsersrc/subset.ts- subset filtering logicsrc/templates.ts- per-argument/return template mappingsrc/renderer.ts- C++ node renderingsrc/naming.ts- naming + deterministic UUID generation
npm install
npm run genDefault output: extensions/GF.Extensions.PyTorch/generated/nodes/*.hpp + extensions/GF.Extensions.PyTorch/generated/manifest.txt
To download libtorch headers, run:
Invoke-WebRequest https://download.pytorch.org/libtorch/cu126/libtorch-win-shared-with-deps-2.12.1%2Bcu126.zip -OutFile libtorch.zip
Extract-Archive libtorch.zip -DestinationPath libtorchCurrently the path to the libtorch headers is hardcoded in the vcxproj file as C:/GitHub/libtorch.
npm run gen -- --source <url_or_file> --out <dir> --allowlist <file> --max <n> --include <regex>Example command which was ran:
npm run gen -- --max 200Flags:
--include-internal--include-inplace--include-out--include-methods
Example (small focused subset):
npm run gen -- --max 30 --include "^(add|sub|mul|div|matmul)$"- function selection is controlled by
config/operations.yaml - operations are keyed by exact name:
oporop.overload - each overload is configured independently; a bare base name does not select all overloads
- comments allowed via
#; setenabled: falseor remove an operation to exclude it - generated order follows source YAML order
- all matching entries are generated by default;
--maxoptionally caps the generated count
Default allowlist path is set in src/config.ts.
The catalog contains all 2,590 operations in the PyTorch main schema snapshot
downloaded on 2026-09-18. The original 50 operations have initial categories;
the remaining entries use PyTorch::Uncategorized for manual classification.
The catalog is a snapshot, so new upstream operations must be added explicitly.
version: 1
defaults:
namespace: PyTorch::Uncategorized
operations:
add.Tensor:
namespace: PyTorch::BasicOperators
conv2d:
namespace: PyTorch::Convolution
relu:
namespace: PyTorch::Activation
displayName: ReLU
description: Replace negative values with zero and retain nonnegative values.
sigmoid:
enabled: false
reason: Disabled in this extension
tanh: {} # Included, using the default namespaceNamespaces use identifier segments separated by ::, with no spaces (use
BasicOperators, not Basic Operators). Each operation is a mapping; use {}
to inherit defaults. The optional defaults.namespace falls back to
PyTorch::Uncategorized. Operation namespaces override that default.
Supported operation fields are namespace, displayName, description, enabled (a boolean,
defaulting to true), and reason (a non-empty explanatory string, not emitted
into C++). displayName overrides the node's visible name without changing its
implementation ID. description supplies the node's user-facing help text;
without it the generator falls back to the PyTorch schema description. Both
strings are escaped when emitted into C++. Other exception fields must be implemented in the generator
before use: unknown fields, invalid values, and duplicate keys are rejected.
Validation errors identify the file and configuration path; YAML syntax and
duplicate-key errors also include source locations.
The former pipe-separated text format has been replaced by YAML. The --allowlist
option still accepts a custom path, now to a YAML file:
npm run gen -- --allowlist config/operations.yamlGenerated nodes expose create_metadata() and call
AddNamespace<"PyTorch::Convolution">(metadata) using the configured value.
This requires an SDK with the AddNamespace bridge helper. Namespace changes do
not change implementation IDs. The host UI must interpret [Namespace] values
to display the hierarchy.
Generated class names and filenames include a stable signature UUID suffix to
keep operations such as add and add_ distinct, including on Windows.
Catalog inclusion does not guarantee that every schema compiles with the current
C++ type mappings or installed libtorch version. Use a matching --source, edit
the allowlist, or use --include/--max to select the operations you need.
Run npm test to check allowlist parsing and namespace generation.
scripts/review-operations.mjs is a local batch workflow. It makes no network or
model API calls: Codex reads its output using the terminal tool, writes decisions
to a JSON file, and submits that file back to the program. It does not invoke or
schedule Codex itself; ask Codex to work through the batches in an active session.
npm.cmd run review:operations -- init --source _build/native_functions.yaml
node scripts/review-operations.mjs next --size 100
node scripts/review-operations.mjs inspect --id 0
node scripts/review-operations.mjs apply --answers _build/answers.json
node scripts/review-operations.mjs status
# After all batches are reviewed:
node scripts/review-operations.mjs finishUse the native_functions.yaml matching the catalog. init reads that local
file; it does not download it. It groups overloads and in-place counterparts
into families to reduce review tokens, retaining exact signatures for inspect.
Decisions use compact groups of family IDs from the current batch:
[
{ "namespace": "PyTorch::Activation", "ids": [0, 1] },
{ "namespace": "PyTorch::Internal", "ids": [2], "reason": "Internal helper; omit from the node palette." }
]Every batch ID must occur exactly once. A group reason disables that family;
otherwise per-overload schema checks determine eligibility. These checks exclude
internal and backward operators, in-place/output-buffer mutations, method-only
schemas, no-return operations, list-valued ports, optional returns, and argument
types without a corresponding bridge conversion. This is a conservative
forward-processing palette, not a claim that those PyTorch operations are bad.
Even ordinary convolution and pooling nodes may be disabled until list-valued
ports are implemented. Remaining enabled nodes are candidates, not proof of
C++ compilation or runtime compatibility.
Checkpoints and decisions live in _build/operation-review (override with
--work). next repeats the pending batch after an interruption; apply saves
progress. init resets the checkpoint, so do not rerun it to resume. Only
finish updates the catalog; it requires a complete review and an unchanged
source catalog, and saves operations.before.yaml plus summary.json in the
checkpoint directory. Comments, display names, existing non-default namespaces,
and prior exclusions are preserved. Every disabled operation receives a reason.
To reconsider a node later, edit its enabled and reason fields directly.
The generator obeys the YAML; it does not rerun the review exclusions.
To review display text, initialize a separate checkpoint in labels mode:
npm.cmd run review:operations -- init --mode labels --work _build/label-review --source _build/native_functions.yaml
node scripts/review-operations.mjs next --size 80 --work _build/label-review
node scripts/review-operations.mjs apply --answers _build/labels.json --work _build/label-review
node scripts/review-operations.mjs finish --work _build/label-reviewThis mode lists only enabled entries, one exact overload per ID, together with
its signature. Answer every batch with objects containing ids, displayName,
and description. For example:
[
{
"ids": [0],
"displayName": "Add Tensors",
"description": "Add two tensors elementwise, broadcasting compatible shapes."
}
]Use revisit --id <id> to correct a completed item before finishing. Display-text
review changes only the two text fields; categories, enabled flags, exclusion
reasons, and disabled nodes stay unchanged. All 651 currently enabled operations
have reviewed display text. Exact schemas remain available in the generated
manifest for technical reference.
Reference documentation for text review: PyTorch operations, linear algebra, and special functions.
Implementation IDs are generated from the canonical parsed signature (schemaSignature) using SHA-1-derived UUID bytes, then emitted in your Core::Uuid(...) constructor format.
- Add exclude list support