AI Skill Report Card

Evolving Neural Architectures with LLM Tools

A-83·Sep 23, 2026·Source: Extension-page
14 / 15

Core principle: use the LLM as a tool for local, constrained decisions, never as an autonomous end-to-end generator. Wrap it inside an algorithmic scaffold that guarantees executability.

Minimal pipeline:

Python
# 1. Mine reusable modules from existing source code (rule-based, no LLM) module_db = mine_modules_from_source(codebase_paths) # AST-based extraction # 2. Represent architecture as a hierarchical tree (not a data-flow graph) tree = build_tree_from_module(base_model, module_db) # 3. Evolve: coarse decision by algorithm, fine decision by LLM for step in range(num_iterations): coarse_action = diversity_guided_planner(tree, history_db) # e.g. "swap backbone.stage2" candidate_tree = llm_resolve_transformation(tree, coarse_action, module_db) # LLM fills in details if is_executable(candidate_tree): score = train_and_eval(candidate_tree) history_db.add(candidate_tree, score)
Recommendation▾
Examples are somewhat abstract (describing structures rather than showing concrete code/tree output) — add a literal tree dump or JSON representation for at least one example
14 / 15

Progress:

  • Step 1: Mine module database from source code via AST parsing
  • Step 2: Convert candidate architectures into hierarchical tree representation
  • Step 3: Define coarse-level evolutionary operators (structural/topological choices)
  • Step 4: Delegate fine-grained parameter/module resolution to LLM
  • Step 5: Enforce executability checks before evaluation
  • Step 6: Update history database and Bayesian diversity model
  • Step 7: Repeat with exploitation/exploration balance

Step 1: Module Mining (Rule-Based, Not LLM)

  • Parse source into an Abstract Syntax Tree (AST); never use an LLM for extraction — it must be 100% correct, deterministic, and hallucination-free.
  • Identify all classes inheriting the framework's base module type (e.g., torch.nn.Module).
  • For each module, record:
    • Search space s_i: every constructor (__init__) argument becomes a tunable hyperparameter.
    • Metadata μ_i: default arg values, number of forward() inputs/outputs, and raw source snippet.
  • Store as D_M = {(m_i, s_i, μ_i)}. This database is the sole source of legal building blocks — no free-form code synthesis.

Step 2: Deploy-Friendly Tree Representation

  • Represent the full architecture as a tree, not a data-flow graph:
    • Root = model; children = conceptual sub-modules (backbone, neck, head); leaves = scalar hyperparameters (channels, kernel size, bias).
    • Intermediate nodes = modules (can be expanded further); leaf nodes = terminal hyperparameters.
    • Support list-typed nodes for variable-length structures (e.g., stacking N repeated layers).
  • This representation mirrors how humans structure code (nested modules), unlike data-flow graphs, making it directly compatible with reused source code and top-down refinement (start rough, add detail later).

Step 3–4: Coarse-to-Fine Evolution

  • Coarse level (algorithmic): decide what kind of structural change to make (e.g., replace a subtree, insert a stage, change list length). Governed by a diversity-guided algorithm using Bayesian modeling over historical outcomes (D_A = {(A_i, e_i)}) to balance exploration vs. exploitation.
  • Fine level (LLM): given the coarse directive and legal module choices from D_M, the LLM resolves remaining degrees of freedom — which specific module, what hyperparameter values, how to connect it — producing a concrete tree transformation.
  • Critically: the LLM operates on a constrained decision template, not open-ended code generation. Its output space is limited to valid tree edits using cataloged modules.

Step 5–7: Execution and Feedback Loop

  • Validate every candidate tree is executable (correct shapes, valid arg types) before spending compute on training.
  • Convert tree → runnable model code deterministically (tree structure maps directly to nested module instantiation).
  • Train/evaluate, then push (A_i, e_i) back into the architecture database to refine future Bayesian-guided coarse planning.
Recommendation▾
Quick Start code references undefined helper functions (diversity_guided_planner, llm_resolve_transformation) without showing their signatures or a toy concrete run, reducing immediate actionability
15 / 20

Example 1: Input: A codebase containing multiple custom PyTorch modules (ConvBlock, AttentionNeck, FPNHead). Output: A module database with entries like {"ConvBlock": {search_space: {kernel_size, stride, channels}, defaults: {...}, forward_io: (1,1)}}. Architecture tree has model → backbone (list of ConvBlock) → neck (AttentionNeck) → head (FPNHead), each hyperparameter as a leaf.

Example 2: Input: Coarse planner decides "insert an additional stage into backbone list." Output: LLM selects a specific module from D_M compatible with adjacent stage's input/output shapes, sets its hyperparameters (e.g., channels doubled from previous stage), and returns the tree-edit patch — not raw code.

Example 3: Input: Need to represent a complex, deeply nested model with variable number of repeated blocks. Output: Tree with a list-node under backbone.stages, whose length is itself a tunable coarse-level decision (evolutionary algorithm adds/removes list elements) while LLM fills in the content of newly added elements.

Recommendation▾
Consider adding a troubleshooting/failure-mode example showing a bad LLM output (e.g., hallucinated module) contrasted with the corrected constrained output
  • Never let the LLM generate free-form code for the full architecture — it biases toward training-corpus patterns and risks non-executable output. Confine LLM decisions to filling gaps in an already-valid tree structure.
  • Keep module mining 100% rule-based (AST-based) to guarantee correctness and enable instant reanalysis of large codebases.
  • Separate concerns by granularity: algorithm handles structural/topological breadth (diversity), LLM handles semantic plausibility of local choices (which module/values make sense together).
  • Always validate executability before training — cheap static checks (shape/type compatibility) save expensive wasted training runs.
  • Maintain a persistent history database of (architecture, score) pairs; use it for Bayesian-guided exploration so search doesn't repeat unproductive regions.
  • Prefer tree representation over data-flow graphs when architectures come from real nested-module source code — trees map naturally to how PyTorch/TF models are actually written, avoiding intrusive rewriting.
  • Support top-down refinement: allow coarse architecture skeletons to be proposed first, then progressively filled with details — this matches both human design workflows and LLM strengths (local reasoning) vs weaknesses (global consistency).
  • Do not treat the LLM as an autonomous agent that writes the entire model end-to-end — this reduces controllability and reliability, and biases discovery toward memorized patterns.
  • Do not use hand-crafted, narrow search spaces purely for safety — this defeats open-ended exploration; instead constrain via structure (tree) not via a small fixed operator set.
  • Do not use an LLM for module extraction/mining — deterministic AST parsing is strictly better (faster, error-free, no hallucination).
  • Do not conflate data-flow graph representations with deploy-ready code structure — data-flow graphs are hard to map back to nested module source code and complicate reuse of existing implementations.
  • Do not let list-structured (repeated-block) architectures be flattened into fixed-size graphs — this loses the natural variable-depth expressiveness needed for open-ended search.
  • Do not skip the executability check step — invalid trees wasted on full training runs are costly; always statically validate first.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
15/20
Completeness
18/20
Format
15/15
Conciseness
13/15