File size: 12,929 Bytes
c311f46 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | # Reason-First Program
**Concept-Guided Program Space Exploration**
When an LLM fills a stub function, there exists a *possible program space* of valid implementations. Any implementation that satisfies the spec, the formal constraints, and the observable effects is "aligned" β its exact shape shouldn't matter. What *does* matter is the set of **concepts** that characterize distinct regions of that space.
This framework discovers those concepts, projects programs into a concept-guided embedding space, and provides a query language for steering generation.
## Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β @reason_first(spec="...") β
β def process(items): ... β
β ββββββββββββ β
β β STUB β β
β ββββββ¬ββββββ β
β β β
β βββββββββββββββββΌββββββββββββββββ β
β βΌ βΌ βΌ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Model A β β Model B β β Model C β Stage 1 β
β β T=0.2..1.2 β β T=0.2..1.2 β β T=0.2..1.2 β Sampling β
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β ββββββββββββββββββΌβββββββββββββββββ β
β βΌ β
β βββββββββββββββββββββββββββ β
β β PROGRAM SPACE β β
β β (valid implementations)β β
β β DA@K diversity metrics β β
β ββββββββββββββ¬βββββββββββββ β
β β β
β βββββββββββββββββΌββββββββββββββββ β
β βΌ βΌ βΌ β
β βββββββββββββββ ββββββββββββββββ βββββββββββββββ β
β β Behavioral β β SAE-Based β β Abstraction β Stage 2 β
β β (execution) β β(hidden state)β β (AST frag.) β Discovery β
β ββββββββ¬βββββββ ββββββββ¬ββββββββ ββββββββ¬βββββββ β
β βββββββββββββββββΌβββββββββββββββββ β
β βΌ β
β ββββββββββββββββββββββββββββ β
β β CONCEPT SET β β
β β {recursive, mutation, β β
β β hash_based, sorting, β β
β β fast_execution, ...} β β
β ββββββββββββββ¬ββββββββββββββ β
β β β
β ββββββββββββββΌβββββββββββββ β
β βΌ βΌ βΌ β
β ββββββββββββββββ βββββββββββ ββββββββββββ β
β β CB-AE β β GCAV β β MSRS β Stage 3 β
β β Bottleneck β β Vectors β β Orthog. β Embedding β
β ββββββββ¬ββββββββ ββββββ¬βββββ ββββββ¬ββββββ β
β ββββββββββββββββΌββββββββββββ β
β βΌ β
β ββββββββββββββββββββββββββββ β
β β CONCEPT EMBEDDING SPACE β β
β β (interpretable axes, β β
β β verifiable alignment) β β
β ββββββββββββββ¬ββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββ β
β β QUERY LANGUAGE β Stage 4 β
β β recursive=0.8, β Steering β
β β mutation=-0.5, β β
β β fast_execution=0.7 β β
β ββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Quick Start
```python
from reason_first_program import (
ProgramSpace, Program, UnifiedConceptDiscovery, SteeringEngine
)
from reason_first_program.stub import Stub, StubConstraints
from reason_first_program.program_space import execute_program
# 1. Define a stub
stub = Stub(
name="two_sum",
source='def two_sum(nums: list[int], target: int) -> list[int]:\n ...',
signature="(nums: list[int], target: int) -> list[int]",
constraints=StubConstraints(decorator_spec="Find two indices that sum to target"),
test_inputs=[{"nums": [2, 7, 11, 15], "target": 9}],
)
# 2. Build program space (add implementations)
space = ProgramSpace(stub)
for src in implementations:
p = Program(source=src, full_source=src, stub_id=stub.stub_id)
p = execute_program(p, stub, stub.test_inputs)
space.add(p)
# 3. Discover concepts
discovery = UnifiedConceptDiscovery()
concepts = discovery.discover(space)
# 4. Query & steer
engine = SteeringEngine(concepts)
results = engine.select(space, "uses_dict=1.0, uses_mutation=-1.0", top_k=3)
```
## Using the @reason_first Decorator
```python
from reason_first_program import reason_first
@reason_first(
spec="Sort items by priority, breaking ties by recency",
postconditions=["output is sorted", "all input items present in output"],
)
def process_queue(items: list) -> list:
#> stable sort; O(n log n); must preserve Item identity
...
```
## Concept Discovery Methods
### 1. Behavioral Concepts (AST + Execution)
Discovers concepts from code structure and execution traces:
- **Algorithmic patterns**: `uses_recursion`, `uses_iteration`, `uses_list_comprehension`
- **Data structure usage**: `uses_dict`, `uses_set`, `uses_heap`
- **Control flow**: `uses_early_return`, `single_return`, `uses_generator`
- **Mutation pattern**: `uses_mutation` (in-place) vs immutable
- **Performance**: `fast_execution` (below-median execution time)
### 2. SAE-Based Concepts (Hidden States)
Trains a Sparse Autoencoder on code LLM hidden states (requires GPU):
- Based on [CB-SAE](https://arxiv.org/abs/2512.10805) and [DN-CBM](https://arxiv.org/abs/2407.14499)
- Auto-names neurons against a code concept vocabulary
- Discovers implicit representational concepts the LLM uses internally
### 3. Structural Abstraction Concepts (AST Fragments)
Finds common program fragments across implementations:
- Based on [LILO](https://arxiv.org/abs/2310.19791) / [ReGAL](https://arxiv.org/abs/2401.16467)
- Patterns like `for_range`, `for_enumerate`, `while_loop`, `nested_function`
## Diversity Metrics
```python
report = space.diversity_report()
# {
# "total_programs": 10,
# "valid_programs": 10,
# "functionally_unique_clusters": 3,
# "da_at_5": 2.8, # Expected distinct algorithms in 5 samples
# "entropy_diversity": 2.1, # Entropy-based diversity index
# }
```
From [AlgoDiv (2503.00691)](https://arxiv.org/abs/2503.00691): `DA@K = Ξ£_m (1 - C(N-s_m, K) / C(N, K))`
## Embedding & Steering
### GCAV Concept Vectors
Based on [GCAV (2501.05764)](https://arxiv.org/abs/2501.05764): `e' = e + Ξ΅ Β· v_concept`
```python
from reason_first_program.embeddings import GCAVEmbedding
gcav = GCAVEmbedding()
gcav.train_all(concepts, features, programs)
steered = gcav.multi_steer(features, {
"uses_recursion": 0.8, "fast_execution": 0.6, "uses_mutation": -0.3
})
```
### MSRS Orthogonal Steering
Based on [MSRS (2508.10599)](https://arxiv.org/abs/2508.10599): orthogonal subspaces prevent concept interference.
## Query Language
```python
engine = SteeringEngine(concepts)
# Weight-based queries
results = engine.select(space, "uses_recursion=0.8, uses_mutation=-0.5")
# Constraint queries
results = engine.select(space, "uses_dict > 0.5 AND fast_execution > 0.7")
# Concept negation
results = engine.select(space, "NOT uses_mutation")
# Programmatic
query = engine.query_language.build(uses_recursion=0.8, fast_execution=0.6)
results = engine.select(space, query)
```
## Concept Lattice (FCA)
Builds a [Formal Concept Analysis](https://en.wikipedia.org/wiki/Formal_concept_analysis) lattice:
- **Extent**: set of programs sharing certain properties
- **Intent**: set of concepts shared by those programs
```python
lattice = concepts.concept_lattice()
for extent, intent in lattice[:5]:
print(f"Concepts {sorted(intent)} β {len(extent)} programs")
```
## Theoretical Foundations
| Method | Paper | Key Contribution |
|--------|-------|-----------------|
| Program space diversity | [AlgoDiv](https://arxiv.org/abs/2503.00691) | DA@K metric, AlgoSim clustering |
| SFS scattering | [SFS](https://arxiv.org/abs/2411.05010) | Diverse algorithmic direction discovery |
| SAE concept discovery | [CB-SAE](https://arxiv.org/abs/2512.10805) | Concept Bottleneck Sparse Autoencoders |
| Concept naming | [DN-CBM](https://arxiv.org/abs/2407.14499) | Discover-then-Name concept pipeline |
| Concept vectors | [GCAV](https://arxiv.org/abs/2501.05764) | Concept Activation Vectors for steering |
| Multi-concept steering | [MSRS](https://arxiv.org/abs/2508.10599) | Orthogonal subspace steering |
| Execution semantics | [TRACED](https://arxiv.org/abs/2306.07487) | Execution-trace-aware representations |
| Library learning | [DreamCoder](https://arxiv.org/abs/2006.08381) / [LILO](https://arxiv.org/abs/2310.19791) | Abstraction discovery from program corpora |
| Latent program space | [LPN](https://arxiv.org/abs/2411.08706) | Continuous latent program representations |
| Typed holes | [Hazel](https://arxiv.org/abs/2409.00921) | Spec-constrained completion spaces |
## Running the Experiment
```bash
pip install -e .
python -m reason_first_program.experiment
```
Demonstrates the full pipeline on hand-crafted `two_sum` and `flatten` implementations:
1. Program space construction & diversity metrics
2. Behavioral + structural concept discovery (31 concepts for two_sum, 30 for flatten)
3. Concept-guided embedding & alignment verification
4. Query language selection & concept boundary exploration
5. Formal concept lattice construction
## Installation
```bash
# Core (concept discovery + steering, no GPU needed)
pip install -e .
# With LLM sampling support
pip install -e ".[llm]"
# With SAE concept discovery (requires GPU)
pip install -e ".[sae]"
# Everything
pip install -e ".[all]"
```
## License
Apache 2.0
|