biosim / scripts /run_research_generate_agent.py
arminfg's picture
SimLab: lab automation RL env, OpenEnv adapter, Training UI, agents
da63ca8
#!/usr/bin/env python3
"""
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()