Reflexion

repository·main·Indexed 25 days ago

https://github.com/noahshinn/reflexion

A framework for Language Agents using Verbal Reinforcement Learning, enabling agents to improve performance through self-reflection and iterative reasoning. The repository includes implementations for reasoning experiments with HotPotQA, decision-making experiments with AlfWorld, and functional correctness evaluation for HumanEval samples.

Tokens
5K
Snippets
12
Records
21
Agent score
84%

What's inside reflexion

  1. Install the HumanEval evaluation harness

    main

    Ensure you are using Python 3.7 or later. It is recommended to use a conda environment for isolation.

    1. Create and activate a new conda environment:

      conda create -n codex python=3.7
      conda activate codex
    2. Clone and install the repository in editable mode:

      git clone https://github.com/openai/human-eval
      pip install -e human-eval
    conda create -n codex python=3.7
    conda activate codex
    git clone https://github.com/openai/human-eval
    pip install -e human-eval
  2. Generate HumanEval samples in JSONL format

    main

    To use the evaluation harness, you must first generate model completions and save them in a JSON Lines (.jsonl) format. Each line in the file must be a single JSON object with the following keys:

    • task_id: The corresponding HumanEval task ID.
    • completion: The model-generated code completion (without the prompt).

    Example format:

    {"task_id": "Corresponding HumanEval task ID", "completion": "Completion only without the prompt"}

    Security Warning: This program executes untrusted model-generated code. It is strongly recommended to run this within a robust security sandbox. You must manually enable execution in human_eval/execution.py as the execution call is commented out by default for safety.

    from human_eval.data import write_jsonl, read_problems
    
    problems = read_problems()
    
    num_samples_per_task = 200
    samples = [
        dict(task_id=task_id, completion=generate_one_completion(problems[task_id]["prompt"]))
        for task_id in problems
        for _ in range(num_samples_per_task)
    ]
    write_jsonl("samples.jsonl", samples)
  3. Run decision-making experiments (AlfWorld)

    main

    To run decision-making experiments using AlfWorld, navigate to the alfworld_runs directory and configure the parameters in ./run_reflexion.sh before execution.

    Configuration Parameters in ./run_reflexion.sh

    • num_trials: Number of iterative learning steps.
    • num_envs: Number of task-environment pairs per trial.
    • run_name: The name for this run.
    • use_memory: Whether to use persisting memory to store self-reflections (set to false for baseline runs).
    • is_resume: Whether to resume a previous run using the logging directory.
    • resume_dir: The logging directory from which to resume.
    • start_trial_num: The trial number to start from (if resuming).

    Execution

    Run the script:

    ./run_reflexion.sh

    Logs are saved to ./root/<run_name>.

    git clone https://github.com/noahshinn/reflexion && cd ./alfworld_runs
    ./run_reflexion.sh
  4. Setup reasoning experiments (HotPotQA)

    main

    To run reasoning experiments using the HotPotQA dataset, clone the repository, navigate to the hotpotqa_runs directory, install dependencies, and configure your OpenAI API key.

    1. Clone and enter the directory:
    git clone https://github.com/noahshinn/reflexion && cd ./hotpotqa_runs
    1. Install dependencies:
    pip install -r requirements.txt
    1. Set your OpenAI API key:
    export OPENAI_API_KEY=<your key>
    git clone https://github.com/noahshinn/reflexion && cd ./hotpotqa_runs
    pip install -r requirements.txt
    export OPENAI_API_KEY=<your key>
  5. Run ReAct experiments with ReflexionStrategy

    main

    To run ReAct (Reasoning and Acting) experiments using the Reflexion framework, you can use ReactReflectAgent combined with a ReflexionStrategy.

    1. Initialize Agents: Create a list of agents using ReactReflectAgent (if using a strategy) or ReactAgent (if no strategy is used), passing the question and the ground truth answer.
    2. Execute Trials: Iterate through trials. For agents that have not yet reached a correct answer (is_correct() == False), call agent.run(). If a ReflexionStrategy is selected, pass it to the reflect_strategy parameter.
    3. Log Results: Use log_react_trial to accumulate logs and summarize_react_trial to track the number of correct, incorrect, and halted agents.
    from agents import ReactReflectAgent, ReactAgent, ReflexionStrategy
    
    # Setup
    strategy = ReflexionStrategy.REFLEXION
    agent_cls = ReactReflectAgent if strategy != ReflexionStrategy.NONE else ReactAgent
    agents = [agent_cls(row['question'], row['answer']) for _, row in hotpot.iterrows()]
    
    # Run trials
    for i in range(n):
        for agent in [a for a in agents if not a.is_correct()]:
            if strategy != ReflexionStrategy.NONE:
                agent.run(reflect_strategy=strategy)
            else:
                agent.run()
  6. Resume WebShop experiments

    main

    To resume a run, use the --is_resume flag. You must provide the --resume_dir (the directory where previous logs exist) and the --start_trial_num (the index of the next trial to execute).

    Requirements for Resuming:

    1. The directory specified in --resume_dir must exist.
    2. The script expects an environment configuration file from the previous trial to exist at: {resume_dir}/env_results_trial_{start_trial_num - 1}.json.
  7. Run Chain-of-Thought experiments with Reflexion on HotPotQA

    main

    To run Chain-of-Thought (CoT) experiments without supporting context using the Reflexion framework, follow these steps:

    1. Load Data: Use joblib to load the HotPotQA sample dataset.
    2. Configure Strategy: Select a ReflexionStrategy (e.g., ReflexionStrategy.REFLEXION).
    3. Initialize Agents: Create CoTAgent instances for each question. You must provide the question, context (empty string for no-context experiments), the ground truth key, an agent_prompt, cot_examples, a reflect_prompt, and reflect_examples.
    4. Execute Trials: Iterate through multiple trials. For each trial, call agent.run(reflexion_strategy=strategy) on agents that have not yet produced a correct answer.
    5. Log and Save: Use log_trial and summarize_trial to track progress, and save_agents to persist the agent states.
    from agents import CoTAgent, ReflexionStrategy
    from prompts import cot_simple_reflect_agent_prompt, cot_simple_reflect_prompt, cot_simple_agent_prompt
    from fewshots import COTQA_SIMPLE6, COT_SIMPLE_REFLECTION
    import joblib
    
    # 1. Load data
    hotpot = joblib.load('../data/hotpot-qa-distractor-sample.joblib').reset_index(drop = True)
    
    # 2. Define strategy
    strategy = ReflexionStrategy.REFLEXION
    
    # 3. Initialize agents
    agents = [CoTAgent(
        question = row['question'],
        context = '',
        key = row['answer'],
        agent_prompt=cot_simple_agent_prompt if strategy == ReflexionStrategy.NONE else cot_simple_reflect_agent_prompt,
        cot_examples = COTQA_SIMPLE6,
        reflect_prompt = cot_simple_reflect_prompt,
        reflect_examples = COT_SIMPLE_REFLECTION,
    ) for _, row in hotpot.iterrows()]
    
    # 4. Run trials
    n = 5
    for i in range(n):
        for agent in [a for a in agents if not a.is_correct()]:
            agent.run(reflexion_strategy = strategy)
        # ... logging logic ...
  8. Configure HotPotQA Agent Types and Reflexion Strategies

    main

    Reasoning experiments are executed via notebooks located in ./hotpot_runs/notebooks. The behavior is determined by the selected Agent Type and Reflexion Strategy.

    Agent Types

    • ReAct: ReAct Agent
    • CoT_context: CoT Agent given supporting context about the question
    • CoT_no_context: CoT Agent given no supporting context about the question

    Reflexion Strategies

    Strategies are defined via ReflexionStrategy Enum:

    • ReflexionStrategy.NONE: No information about the last attempt is provided.
    • ReflexionStrategy.LAST_ATTEMPT: Provides the reasoning trace from the last attempt as context.
    • ReflexionStrategy.REFLEXION: Provides the self-reflection from the last attempt as context.
    • ReflexionStrategy.LAST_ATTEMPT_AND_REFLEXION: Provides both the reasoning trace and self-reflection from the last attempt as context.
  9. Save ReAct agent results and logs

    main

    After running experiments, you can persist the results using save_agents and standard file writing. The logs are typically generated using log_react_trial.

    # Save the text log
    with open(os.path.join(root, 'ReAct', strategy.value, f'{len(agents)}_questions_{trial}_trials.txt'), 'w') as f:
        f.write(log)
    
    # Save the agent objects
    save_agents(agents, os.path.join('ReAct', strategy.value, 'agents'))
  10. Save agent results and trial logs

    main

    After running trials, you can save the accumulated log string to a text file and use save_agents to persist the agent instances. The file path typically includes the strategy value and the number of questions/trials.

    # Save the text log
    with open(os.path.join(root, 'CoT', 'context', strategy.value, f'{len(agents)}_questions_{trial}_trials.txt'), 'w') as f:
        f.write(log)
    
    # Save the agent objects
    save_agents(agents, os.path.join(root, 'CoT', 'context', strategy.value, 'agents'))
  11. Run agent trials with ReflexionStrategy

    main

    Execute multiple trials for a set of agents. In each trial, iterate through agents that have not yet produced a correct answer and call agent.run(reflexion_strategy=strategy). Use log_trial and summarize_trial from the util module to track progress and correctness across trials.

    # n is the number of trials to run
    n = 5
    trial = 0
    log = ''
    
    for i in range(n):
        for agent in [a for a in agents if not a.is_correct()]:
            agent.run(reflexion_strategy = strategy)
            print(f'Answer: {agent.key}')
        trial += 1
        log += log_trial(agents, trial)
        correct, incorrect = summarize_trial(agents)
        print(f'Finished Trial {trial}, Correct: {len(correct)}, Incorrect: {len(incorrect)}')