| |
| """ |
| Run the Research & Generate agent: research → generate any protocol → run → learn from feedback. |
| |
| Uses env.run_assay_with_protocol() so the agent can try arbitrary parameter values |
| (not limited to presets). Feedback from each run is passed into the next trial. |
| Works with any spec that has evaluate_custom_protocol (PCR, ELISA, etc.). |
| |
| Requires: pip install openai, OPENAI_API_KEY set. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import sys |
| from pathlib import Path |
|
|
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) |
|
|
| from lab_env.env import LabEnv |
| from lab_env.spec import get_spec_for_workflow |
| from agents.research_generate_agent import ResearchGenerateAgent |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser( |
| description="Run Research & Generate agent (research → generate protocol → run → learn)" |
| ) |
| parser.add_argument( |
| "--episodes", |
| type=int, |
| default=5, |
| help="Number of episodes to run", |
| ) |
| parser.add_argument( |
| "--workflow", |
| type=str, |
| default="pcr-amplification", |
| choices=["pcr-amplification", "elisa-readout"], |
| help="Experiment type (uses spec with custom protocol support)", |
| ) |
| parser.add_argument( |
| "--max-trials", |
| type=int, |
| default=6, |
| help="Max protocol attempts per episode", |
| ) |
| parser.add_argument( |
| "--seed", |
| type=int, |
| default=42, |
| ) |
| parser.add_argument( |
| "--verbose", |
| action="store_true", |
| help="Print each trial's protocol and result", |
| ) |
| args = parser.parse_args() |
|
|
| spec = get_spec_for_workflow(args.workflow) |
| env = LabEnv(spec=spec) |
| agent = ResearchGenerateAgent(max_trials=args.max_trials) |
|
|
| print(f"Research & Generate agent — workflow={args.workflow}, episodes={args.episodes}") |
| print("(Research → generate protocol → run in lab → learn from feedback)\n") |
|
|
| results = [] |
| for ep in range(args.episodes): |
| seed = args.seed + ep * 1000 |
| if args.verbose: |
| print(f"--- Episode {ep + 1} (seed={seed}) ---") |
| out = agent.run_episode(env, seed=seed, verbose=args.verbose) |
| results.append(out) |
| if not args.verbose: |
| print( |
| f" Episode {ep + 1}: reward={out['reward']:.1f}, " |
| f"success={out['success']}, protocols_tried={out['num_protocols_tried']}" |
| ) |
|
|
| env.close() |
|
|
| n = len(results) |
| print("\n--- Summary ---") |
| print(f" Success rate: {sum(r['success'] for r in results) / n:.1%}") |
| print(f" Partial rate: {sum(r['partial'] for r in results) / n:.1%}") |
| print(f" Avg reward: {sum(r['reward'] for r in results) / n:.1f}") |
| print(f" Avg protocols: {sum(r['num_protocols_tried'] for r in results) / n:.1f} per episode") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|