Metadata-Version: 2.4
Name: actopo
Version: 0.1.0
Summary: Activation Topology — reproducible persistent-homology measurement of LLM activation manifolds
Project-URL: Homepage, https://github.com/linxuhao/actopo
Project-URL: Repository, https://github.com/linxuhao/actopo
Author: Lin Xuhao
License: MIT
License-File: LICENSE
Keywords: betti-numbers,interpretability,llm,persistent-homology,topological-data-analysis
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Requires-Dist: numpy>=1.23
Requires-Dist: persim>=0.3.1
Requires-Dist: ripser>=0.6.4
Requires-Dist: scikit-learn>=1.1
Provides-Extra: all
Requires-Dist: datasets>=2.14; extra == 'all'
Requires-Dist: gudhi>=3.8; extra == 'all'
Requires-Dist: pytest-cov; extra == 'all'
Requires-Dist: pytest>=7; extra == 'all'
Requires-Dist: ruff; extra == 'all'
Requires-Dist: torch>=2.0; extra == 'all'
Requires-Dist: tqdm>=4.65; extra == 'all'
Requires-Dist: transformers>=4.40; extra == 'all'
Provides-Extra: dev
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: extract
Requires-Dist: datasets>=2.14; extra == 'extract'
Requires-Dist: torch>=2.0; extra == 'extract'
Requires-Dist: tqdm>=4.65; extra == 'extract'
Requires-Dist: transformers>=4.40; extra == 'extract'
Provides-Extra: gpu-ripser
Requires-Dist: ripserplusplus>=1.1.2; extra == 'gpu-ripser'
Provides-Extra: gudhi
Requires-Dist: gudhi>=3.8; extra == 'gudhi'
Description-Content-Type: text/markdown

# actopo — Activation Topology

Reproducible persistent-homology measurement of LLM activation manifolds.

`actopo` provides **one** measurement protocol, **one** activation-extraction
function, and **one** topology implementation, so β₁ / survival / PHI numbers
stay consistent across every experiment. It is the tooling behind the
*Mathematical Life* paper, packaged so the experiments can be reproduced.

## Why

Re-implementing "compute β₁" in each analysis script lets the measurement
silently diverge (different ε thresholds, wrong last-token extraction, etc.).
`actopo` centralises the protocol in a single `ProtocolConfig` and stamps every
result with the exact config + version + git revision that produced it.

## Install

```bash
pip install actopo                 # topology layer (CPU only)
pip install "actopo[extract]"      # + activation extraction (torch/transformers)
pip install "actopo[all]"          # everything incl. dev/test
```

## Quickstart

The package ships a tiny real example: reasoning activations from
**Qwen2.5-0.5B (base)** vs **Qwen2.5-0.5B-Instruct** — the paper's core
base-vs-instruct comparison.

```python
from actopo import FROZEN_V5, measure
from actopo.metrics import union_test, center_distance
from actopo.data import load_example_cloud

base = load_example_cloud("base")        # (600, 896) reasoning activations
inst = load_example_cloud("instruct")

print(measure(base, FROZEN_V5).beta1)    # 12
print(measure(inst, FROZEN_V5).beta1)    # 50  → alignment EXPANDS β₁ here

# base and instruct occupy the SAME topological region (β₁ changes within it):
u = union_test(base, inst, FROZEN_V5, independent_eps=True)
print(u["verdict"])                      # SHARED
print(center_distance(base, inst))       # 0.62
```

### Extract your own activations (needs `actopo[extract]`)

```python
from actopo import FROZEN_V5, measure
from actopo.models import load_model
from actopo.extract import extract_activations

model, tok = load_model("Qwen/Qwen2.5-0.5B", FROZEN_V5)
acts = extract_activations(model, tok, my_prompts, FROZEN_V5)   # correct last-token
print(measure(acts, FROZEN_V5).beta1)
```

Every result can be stamped + verified against the frozen protocol:

```python
from actopo import save_result, verify, load_result, FROZEN_V5
save_result("out.json", {"beta1": 12}, FROZEN_V5)
assert verify(load_result("out.json"), FROZEN_V5) == []   # produced on-protocol
```

## The frozen protocol (`FROZEN_V5`)

| Parameter | Value |
|-----------|-------|
| β₁ threshold | lifetime > `0.03 × ε_max` |
| survival/PHI threshold | lifetime > `0.01 × ε_max` |
| layer | `L/2` |
| token | last (attention-mask based) |
| point cloud | 1319 prompts |
| PH backend | ripser, `maxdim=1`, euclidean |

See `actopo.protocol.ProtocolConfig` for the full, documented field set.

## License

MIT.
