用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/AndrewSmigaj/OpenLLMRI --skill temporal命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | temporal |
| description | Run temporal basin captures — single runs, paired batches, and verification |
Run temporal capture experiments that measure how MoE routing basins persist or shift as context changes. Each run processes an ordered sequence of sentences (basin A then basin B) and records the model's routing at each step.
| Constant | Value |
|---|---|
| Capture endpoint | POST http://localhost:8000/api/experiments/temporal-capture |
| List runs | GET http://localhost:8000/api/experiments/temporal-runs/{session_id} |
| Lag data | POST http://localhost:8000/api/experiments/temporal-lag-data |
| Python | /mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/.venv/bin/python |
| Lake path | /mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/data/lake |
NEVER use bare python3 — always use the full venv path above.
The UI generates a copy-paste instruction. Parse it to extract parameters:
Run temporal capture on session {session_id}: basin_a={id} ({label}), basin_b={id} ({label}), layer={N}, schema={name}, {mode}, {N}/block
Extracted parameters: session_id, basin_a_cluster_id, basin_b_cluster_id, basin_layer, clustering_schema, processing_mode, sentences_per_block.
| Parameter | Default | Notes |
|---|---|---|
generate_output | false | Always false for temporal. Generation adds 50 autoregressive forward passes per position — hours of unnecessary compute. Temporal only needs routing data. |
sequence_config | block_ab | A sentences first, then B. Use block_ba for reverse direction. |
custom_sentences | null | Pass explicit sentence list instead of random sampling. Used for sentence pairing. |
custom_regime_boundary | null | Override auto-detection of regime boundary. Set to sentences_per_block (e.g., 20) when using custom_sentences. |
custom_target_word | null | Target word for custom_sentences mode. Required when using custom_sentences. |
With generate_output: false (the default for temporal):
| Mode | Per run | 10 runs |
|---|---|---|
expanding_cache_on | ~35 sec | ~6 min |
expanding_cache_off | ~35 sec | ~6 min |
With generate_output: true (NOT recommended — adds 50 autoregressive steps per position):
| Mode | Per run | 10 runs |
|---|---|---|
expanding_cache_on | ~1 min | ~10 min |
expanding_cache_off | ~15 min | ~2.5 hours |
Cache_off recomputes the full forward pass from scratch at each position with growing cumulative text (quadratic attention cost), but with generate_output: false the difference is minimal since the forward pass is fast on its own.
Each operation is a self-contained block. Replace {placeholders} with actual values.
Run N captures sequentially with the same parameters. Each run randomly samples sentences from the basins. Run with run_in_background: true for large batches.
PY=/mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/.venv/bin/python
for i in $(seq 1 {N}); do
echo "=== {label} run $i/{N} ==="
curl -s -X POST http://localhost:8000/api/experiments/temporal-capture \
-H "Content-Type: application/json" \
-d '{
"session_id": "{session_id}",
"basin_a_cluster_id": {basin_a},
"basin_b_cluster_id": {basin_b},
"basin_layer": {basin_layer},
"clustering_schema": "{schema}",
"sentences_per_block": {sentences_per_block},
"processing_mode": "{mode}",
"sequence_config": "{block_ab_or_ba}",
"generate_output": false
}' | $PY -c "
import json, sys
d = json.load(sys.stdin)
if 'temporal_run_id' in d:
print(f' OK: {d[\"temporal_run_id\"]} ({d[\"sequence_positions\"]} pos)')
else:
print(f' ERROR: {json.dumps(d, indent=2)}')
sys.exit(1)
" || { echo "ABORTING"; break; }
done
echo "=== Done ==="
Run cache_off captures using the same sentences as existing cache_on runs. This ensures valid ΔPersistence comparison. Run with run_in_background: true — cache_off is slow (~15 min/run).
Prerequisite: cache_on runs must already exist (from OP-1).
PY=/mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/.venv/bin/python
LAKE=/mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/data/lake
# Generate one curl command per unpaired cache_on run, then execute each
$PY -c "
import json
runs = json.load(open('$LAKE/{session_id}/temporal_runs.json'))
cache_on = [r for r in runs if r['processing_mode'] == 'expanding_cache_on']
cache_off_count = len([r for r in runs if r['processing_mode'] == 'expanding_cache_off'])
todo = cache_on[cache_off_count:] # skip already-paired
print(f'TOTAL={len(todo)}')
for i, run in enumerate(todo):
sents = [run['sentence_texts'][str(j)] for j in range(run['sequence_positions'])]
payload = json.dumps({
'session_id': '{session_id}',
'basin_a_cluster_id': run['basin_a_cluster_id'],
'basin_b_cluster_id': run['basin_b_cluster_id'],
'basin_layer': run['basin_layer'],
'processing_mode': 'expanding_cache_off',
'sequence_config': run['sequence_config'],
'clustering_schema': run['clustering_schema'],
'generate_output': False,
'custom_sentences': sents,
'custom_target_word': '{target_word}',
'custom_regime_boundary': run['regime_boundary'],
})
print(payload)
" | {
read -r HEADER
TOTAL=\${HEADER#TOTAL=}
N=0
while read -r PAYLOAD; do
N=\$((N + 1))
echo "=== cache_off \$N/\$TOTAL ==="
echo "\$PAYLOAD" | curl -s -X POST http://localhost:8000/api/experiments/temporal-capture \
-H "Content-Type: application/json" -d @- | $PY -c "
import json, sys
d = json.load(sys.stdin)
if 'temporal_run_id' in d:
print(f' OK: {d[\"temporal_run_id\"]} ({d[\"sequence_positions\"]} pos)')
else:
print(f' ERROR: {json.dumps(d, indent=2)}')
sys.exit(1)
" || { echo "ABORTING"; break; }
done
echo "=== Done ==="
}
Replace {session_id} and {target_word} with actual values (e.g., session_1434a9be and tank).
Resumable: If interrupted, re-running the same command skips already-completed cache_off runs.
Show runs grouped by mode × direction.
PY=/mnt/c/Users/emily/OpenAIHackathon-ConceptMRI/.venv/bin/python
$PY -c "
import json
from collections import Counter
runs = json.load(open('data/lake/{session_id}/temporal_runs.json'))
counts = Counter((r['processing_mode'], r.get('sequence_config', '?')) for r in runs)
for k, v in sorted(counts.items()):
print(f' {k}: {v} runs')
print(f'Total: {len(runs)}')
"
Expected for a complete experiment (40 runs per probe):
('expanding_cache_off', 'block_ab'): 10 runs
('expanding_cache_off', 'block_ba'): 10 runs
('expanding_cache_on', 'block_ab'): 10 runs
('expanding_cache_on', 'block_ba'): 10 runs
Total: 40
| Mode | Input per step | Cache | Speed |
|---|---|---|---|
expanding_cache_on | Single sentence | KV cache chains forward | Fast (~1 min/run) |
expanding_cache_off | All sentences concatenated | No cache, full recompute | Slow (~15 min/run) |
ΔPersistence = lag(cache_on) − lag(cache_off)
If ΔPersistence > 0, the KV cache creates extra routing persistence beyond what the text context alone produces.
The standard 2×2 factorial design: cache_on/off × A→B/B→A × 10 reps.
/health for model_loaded: trueexpanding_cache_on, block_ab (~10 min)expanding_cache_on, block_ba (~10 min)To add N more runs to an existing condition:
Cache_on and cache_off must process the same sentences in the same order for ΔPersistence to be valid. Without pairing, differences could be due to different sentence content rather than cache effects.
OP-1 (cache_on) randomly samples sentences and stores them in temporal_runs.json → sentence_texts. OP-2 reads those sentences and passes them back as custom_sentences for the cache_off run. The custom_regime_boundary parameter ensures the regime split is at the correct position (e.g., 20).
Each temporal position gets a scalar value: 0.0 = at basin A centroid, 1.0 = at basin B centroid. Computed as Fisher's Linear Discriminant on raw residual stream vectors (no reducer needed, ~0.03s for 400 probes).
generate_output: false always — temporal doesn't need generated text. With true, each position runs 50 autoregressive forward passes (adds hours per run)./health for model_loaded: true.python3 — always the full venv path.