Spaces:
Running on Zero
Running on Zero
| from __future__ import annotations | |
| import argparse | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| from featurelens.config import SETTINGS | |
| ROOT = Path(__file__).resolve().parents[1] | |
| def parse_args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser(description='Run the full FeatureLens offline study.') | |
| parser.add_argument( | |
| '--resume', | |
| action='store_true', | |
| help='Skip stages whose expected outputs already exist.', | |
| ) | |
| parser.add_argument( | |
| '--activation-batch-size', | |
| type=int, | |
| default=16, | |
| help='Batch size used only by experiments.collect_activations.', | |
| ) | |
| parser.add_argument( | |
| '--activation-max-length', | |
| type=int, | |
| default=192, | |
| help='Maximum prompt length used only by experiments.collect_activations.', | |
| ) | |
| return parser.parse_args() | |
| def run( | |
| module: str, | |
| *, | |
| outputs: list[Path], | |
| resume: bool, | |
| extra_args: list[str] | None = None, | |
| ) -> None: | |
| if resume and outputs and all(path.exists() for path in outputs): | |
| print(f'\nSKIP {module}: expected outputs already exist.', flush=True) | |
| return | |
| command = [sys.executable, '-m', module, *(extra_args or [])] | |
| print('\n$', ' '.join(command), flush=True) | |
| subprocess.run(command, cwd=ROOT, check=True) | |
| def main() -> None: | |
| args = parse_args() | |
| artifact_dir = ROOT / 'artifacts' | |
| activation_dir = artifact_dir / 'activations' | |
| run( | |
| 'experiments.build_dataset', | |
| outputs=[ROOT / 'data' / 'prompts.jsonl', ROOT / 'data' / 'causal_tasks.jsonl'], | |
| resume=args.resume, | |
| ) | |
| run( | |
| 'experiments.collect_activations', | |
| outputs=[ | |
| activation_dir / 'metadata.json', | |
| *[activation_dir / f'features_layer{layer}.npz' for layer in SETTINGS.layers], | |
| *[activation_dir / f'features_final_layer{layer}.npz' for layer in SETTINGS.layers], | |
| ], | |
| resume=args.resume, | |
| extra_args=[ | |
| '--batch-size', str(args.activation_batch_size), | |
| '--max-length', str(args.activation_max_length), | |
| ], | |
| ) | |
| run( | |
| 'experiments.evaluate_features', | |
| outputs=[ | |
| artifact_dir / 'feature_catalog.csv', | |
| artifact_dir / 'layer_metrics.csv', | |
| artifact_dir / 'stability.csv', | |
| artifact_dir / 'split.json', | |
| ], | |
| resume=args.resume, | |
| ) | |
| final_output = artifact_dir / 'causal_results_final_token.csv' | |
| run( | |
| 'experiments.run_causal', | |
| outputs=[final_output, final_output.with_suffix(final_output.suffix + '.complete')], | |
| resume=args.resume, | |
| extra_args=[ | |
| '--position-policy', 'final_token', | |
| '--output', str(final_output), | |
| *(['--resume'] if args.resume else []), | |
| ], | |
| ) | |
| max_active_output = artifact_dir / 'causal_results_max_active.csv' | |
| run( | |
| 'experiments.run_causal', | |
| outputs=[ | |
| max_active_output, | |
| max_active_output.with_suffix(max_active_output.suffix + '.complete'), | |
| ], | |
| resume=args.resume, | |
| extra_args=[ | |
| '--position-policy', 'max_feature_activation', | |
| '--output', str(max_active_output), | |
| *(['--resume'] if args.resume else []), | |
| ], | |
| ) | |
| feature_set_output = artifact_dir / 'feature_set_results.csv' | |
| run( | |
| 'experiments.run_feature_sets', | |
| outputs=[ | |
| feature_set_output, | |
| feature_set_output.with_suffix(feature_set_output.suffix + '.complete'), | |
| ], | |
| resume=args.resume, | |
| extra_args=['--resume'] if args.resume else None, | |
| ) | |
| run( | |
| 'experiments.analyze_stability', | |
| outputs=[artifact_dir / 'selection_stability.csv'], | |
| resume=args.resume, | |
| ) | |
| run( | |
| 'experiments.analyze_study', | |
| outputs=[artifact_dir / 'study_feature_summary.csv', artifact_dir / 'study_summary.json'], | |
| resume=args.resume, | |
| ) | |
| run( | |
| 'experiments.make_report', | |
| outputs=[artifact_dir / 'summary.json', artifact_dir / 'report.md'], | |
| resume=args.resume, | |
| ) | |
| subprocess.run( | |
| [sys.executable, '-m', 'scripts.validate_artifacts'], | |
| cwd=ROOT, | |
| check=True, | |
| ) | |
| print('\nFeatureLens experiment pipeline complete. See artifacts/report.md') | |
| if __name__ == '__main__': | |
| main() | |