### Shell Command to View Environment Tools Source: https://github.com/future-house/aviary/blob/main/README.md Installs the necessary package and runs a command to start a server for viewing environment tools and their descriptions. This is useful for understanding agent interactions. ```shell pip install fhaviary[server] aviary tools [env name] ``` -------------------------------- ### Install HotPotQA Environment Source: https://github.com/future-house/aviary/blob/main/packages/hotpotqa/README.md Use this command to install the HotPotQA environment with all necessary dependencies for multi-hop question answering. ```bash pip install 'fhaviary[hotpotqa]' ``` -------------------------------- ### Install Aviary with LabBench Support Source: https://github.com/future-house/aviary/blob/main/packages/labbench/README.md Install the fhaviary package with the labbench extra to enable LAB-Bench environments. ```bash pip install 'fhaviary[labbench]' ``` -------------------------------- ### Install Aviary with Pip Source: https://github.com/future-house/aviary/blob/main/README.md Install the Aviary library using pip. This command installs the core package. ```bash pip install fhaviary ``` -------------------------------- ### Local Environment Client Example Source: https://context7.com/future-house/aviary/llms.txt Demonstrates creating and interacting with a local DummyEnv for testing purposes. It shows resetting the environment and printing initial observations and available tools. ```python import asyncio from aviary.core import ( TaskDatasetServer, EnvironmentClient, TaskDatasetClient, TaskEnvironmentClient, DummyEnv, DummyTaskDataset, ) # Local environment client example (for testing) async def local_client_example(): # Create a local environment env = DummyEnv(task="test task", end_immediately=False) # Reset and interact obs, tools = await env.reset() print(f"Initial observation: {obs[0].content}") print(f"Available tools: {[t.info.name for t in tools]}") # Get environment ID if available try: env_id = await env.get_id() print(f"Environment ID: {env_id}") except ValueError as e: print(f"No ID configured: {e}") asyncio.run(local_client_example()) ``` -------------------------------- ### Install Aviary with All Development Dependencies Source: https://context7.com/future-house/aviary/llms.txt Install Aviary along with all development-related dependencies for contributing or advanced usage. ```bash pip install 'fhaviary[dev]' ``` -------------------------------- ### Install Aviary and Dependencies Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a Custom Environment in Aviary.ipynb Install the necessary Aviary, LDP, and Pydantic packages using pip. Ensure you have these libraries before proceeding with the tutorial. ```python !pip install fhaviary ldp pydantic ``` -------------------------------- ### Install Aviary for Development Source: https://github.com/future-house/aviary/blob/main/README.md Install Aviary with development dependencies. This is typically used for local development and testing. ```bash pip install "fhaviary[dev]" ``` -------------------------------- ### Install Aviary Notebook Environment Source: https://github.com/future-house/aviary/blob/main/packages/notebook/README.md Install the notebook environment using pip. This command installs the necessary packages for the Jupyter notebook functionality within Aviary. ```bash pip install 'fhaviary[notebook]' ``` -------------------------------- ### Functional Environment API Setup Source: https://context7.com/future-house/aviary/llms.txt The `fenv` module provides a decorator-based approach (`@fenv.start`) for creating environments quickly without subclassing. It returns initial observations and a state dictionary. ```python from aviary.core import fenv @fenv.start(allow_concurrency=False) def story_env(topic: str, max_words: int = 100): """Create an environment for writing stories.""" return ( f"Write a story about {topic} in {max_words} words or less.", {"topic": topic, "max_words": max_words, "story_written": False} ) ``` -------------------------------- ### Install Aviary with LLM Support Source: https://context7.com/future-house/aviary/llms.txt Install Aviary with the necessary dependencies for Large Language Model (LLM) support. ```bash pip install 'fhaviary[llm]' ``` -------------------------------- ### GSM8K Calculator Environment Interaction Source: https://context7.com/future-house/aviary/llms.txt Demonstrates the setup and basic interaction with the `CalculatorEnv` for GSM8K problems. It shows how to reset the environment, get observations and tools, and print problem details. Requires `pip install fhaviary[gsm8k]`. ```python import asyncio from aviary.envs.gsm8k import CalculatorEnv, CalculatorEnvConfig, GSM8kDataset from aviary.core import ToolRequestMessage, ToolCall # This snippet is illustrative and assumes CalculatorEnv and related classes are available. # Actual instantiation and usage would typically follow dataset loading as shown previously. # Example of how one might instantiate and use the environment directly (if not using a dataset): # async def run_calculator_env(): # env_config = CalculatorEnvConfig(correct_reward=1.0) # env = CalculatorEnv(config=env_config, problem_id="example_problem_1") # obs, tools = await env.reset() # print(f"Problem: {obs[0].content}") # print(f"Tools: {[t.info.name for t in tools]}") # # ... further interaction logic ... # # asyncio.run(run_calculator_env()) ``` -------------------------------- ### Install GSM8k Environment Source: https://github.com/future-house/aviary/blob/main/packages/gsm8k/README.md Use this command to install the GSM8k environment with fhaviary. Ensure you have pip installed. ```bash pip install 'fhaviary[gsm8k]' ``` -------------------------------- ### Install Aviary with Environments Source: https://github.com/future-house/aviary/blob/main/README.md Install Aviary along with specific incumbent environments. This command includes support for gsm8k, hotpotqa, labbench, lfrqa, and notebook environments. ```bash pip install 'fhaviary[gsm8k,hotpotqa,labbench,lfrqa,notebook]' ``` -------------------------------- ### Example Interaction Trace Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a GSM8k Environment in Aviary.ipynb This output shows a detailed trace of the agent's interaction with the environment for solving a math word problem. It includes observations from the environment and the actions (tool calls) generated by the ToolSelector. ```text Output: Evaluating problem number 1: Observation is [Message(role='user', content='Weng earns $12 an hour for babysitting. Yesterday, she just did 50 minutes of babysitting. How much did she earn?')] Action is Tool request message '' for tool calls: calculator(expr='(50/60) * 12') [id=call_AmfsBdqTgU3jV9Ni3dWWDi7t] Observation is [ToolResponseMessage(role='tool', content='10', name='calculator', tool_call_id='call_AmfsBdqTgU3jV9Ni3dWWDi7t')] Action is Tool request message '' for tool calls: check_answer(answer='10') [id=call_1HKFkh8BhOs7BBPFAojuoAyE] Evaluating problem number 2: Observation is [Message(role='user', content='Betty is saving money for a new wallet which costs $100. Betty has only half of the money she needs. Her parents decided to give her $15 for that purpose, and her grandparents twice as much as her parents. How much more money does Betty need to buy the wallet?')] Action is Tool request message '' for tool calls: calculator(expr='100 / 2') [id=call_Ts9iE2ZZSjBVOTEFlqbJgBiP] Observation is [ToolResponseMessage(role='tool', content='50', name='calculator', tool_call_id='call_Ts9iE2ZZSjBVOTEFlqbJgBiP')] Action is Tool request message '' for tool calls: calculator(expr='15 * 2') [id=call_ItKmh0TKIvaIHMPlcfwFJdXb]; calculator(expr='50 + 15') [id=call_4NY9WHLyGVQ010aZITQ06J6C] Observation is [ToolResponseMessage(role='tool', content='30', name='calculator', tool_call_id='call_ItKmh0TKIvaIHMPlcfwFJdXb'), ToolResponseMessage(role='tool', content='65', name='calculator', tool_call_id='call_4NY9WHLyGVQ010aZITQ06J6C')] Action is Tool request message '' for tool calls: calculator(expr='65 + 30') [id=call_EXhCQ1uYqrBuAnAGYviichyz] Observation is [ToolResponseMessage(role='tool', content='95', name='calculator', tool_call_id='call_EXhCQ1uYqrBuAnAGYviichyz')] Action is Tool request message '' for tool calls: calculator(expr='100 - 95') [id=call_fAODL0FzwXbevnMJCFWAumZ1] Observation is [ToolResponseMessage(role='tool', content='5', name='calculator', tool_call_id='call_fAODL0FzwXbevnMJCFWAumZ1')] Action is Tool request message '' for tool calls: check_answer(answer='5') [id=call_8epdwS5j4Nxw8UGDB05e2wRu] Evaluating problem number 3: Observation is [Message(role='user', content='Julie is reading a 120-page book. Yesterday, she was able to read 12 pages and today, she read twice as many pages as yesterday. If she wants to read half of the remaining pages tomorrow, how many pages should she read?')] Action is Tool request message '' for tool calls: calculator(expr='12 * 2') [id=call_MgQgHT6e9DpDCdzhb93YFGP7] Observation is [ToolResponseMessage(role='tool', content='24', name='calculator', tool_call_id='call_MgQgHT6e9DpDCdzhb93YFGP7')] Action is Tool request message '' for tool calls: calculator(expr='120 - (12 + 24)') [id=call_9Lv65NHAw9oWcASlZwVXdkeM] Observation is [ToolResponseMessage(role='tool', content='84', name='calculator', tool_call_id='call_9Lv65NHAw9oWcASlZwVXdkeM')] Action is Tool request message '' for tool calls: calculator(expr='84 / 2') [id=call_55MiSCqyuNQ2jbHiFE9cyazA] Observation is [ToolResponseMessage(role='tool', content='42', name='calculator', tool_call_id='call_55MiSCqyuNQ2jbHiFE9cyazA')] Action is Tool request message '' for tool calls: check_answer(answer='42') [id=call_bNdPTB23BD6fEQRnyaG5U6N0] Accuracy is 100.0% ``` -------------------------------- ### Install Aviary with LFRQA support Source: https://github.com/future-house/aviary/blob/main/packages/lfrqa/README.md Install the fhaviary package with the LFRQA extra to enable support for the LFRQA dataset. This command should be run in your terminal. ```bash pip install 'fhaviary[lfrqa]' ``` -------------------------------- ### Initialize and Reset Functional Environment Source: https://github.com/future-house/aviary/blob/main/README.md Instantiate the functional environment by calling it with necessary arguments and then reset it to get the initial observation and tools. ```python env = my_env(topic="foo") obs, tools = await env.reset() ``` -------------------------------- ### Document Environment Context with Tools Source: https://context7.com/future-house/aviary/llms.txt Defines a DocumentEnv that uses RefState and provides tools for document creation and word count. This setup is for an environment context. ```python import asyncio from aviary.core import RefState, create_document, get_word_count from aviary.env import Environment, Tool, Message, ToolRequestMessage, ToolCall # In an environment context class DocumentEnv(Environment[RefState]): async def reset(self): self.state = RefState() self.tools = [ Tool.from_function(create_document), Tool.from_function(get_word_count), ] return [Message(content="Create and analyze documents.")], self.tools async def step(self, action: ToolRequestMessage): if not isinstance(action, ToolRequestMessage): return self.default_no_tool_calls_response obs = await self.exec_tool_calls(action, state=self.state) return obs, 0.0, self.state.done, False async def run_document_env(): env = DocumentEnv() obs, tools = await env.reset() # Create a document action = ToolRequestMessage( tool_calls=[ToolCall.from_name("create_document", title="Test", content="This is a test document")] ) obs, _, _, _ = await env.step(action) print(f"Create result: {obs[0].content}") # The reference key is returned in the observation # Agent can now use this key in subsequent calls asyncio.run(run_document_env()) ``` -------------------------------- ### Evaluate Text-Based QA with PaperQA Source: https://github.com/future-house/aviary/blob/main/packages/labbench/README.md Example of setting up and running an evaluation for text-based question answering using PaperQA and Aviary's TaskDataset. Ensure the specified paper directory contains the necessary LitQA2 papers. ```python import os from ldp.agent import SimpleAgent from ldp.alg import Evaluator, EvaluatorConfig, MeanMetricsCallback from paperqa import Settings from aviary.env import TaskDataset async def evaluate(folder_of_litqa_v2_papers: str | os.PathLike) -> None: settings = Settings(paper_directory=folder_of_litqa_v2_papers) dataset = TaskDataset.from_name("litqa2", settings=settings) metrics_callback = MeanMetricsCallback(eval_dataset=dataset) evaluator = Evaluator( config=EvaluatorConfig(batch_size=3), agent=SimpleAgent(), dataset=dataset, callbacks=[metrics_callback], ) await evaluator.evaluate() print(metrics_callback.eval_means) ``` -------------------------------- ### Load and Use HotPotQADataset Source: https://context7.com/future-house/aviary/llms.txt Load the HotPotQA dataset using `HotPotQADataset`. Customize configurations with `HotPotQAEnvConfig`, including data fraction and shuffling. Requires `pip install fhaviary[hotpotqa]`. ```python # Load HotPotQA dataset (requires: pip install fhaviary[hotpotqa]) from aviary.envs.hotpotqa import HotPotQADataset, HotPotQAEnvConfig hotpot_config = HotPotQAEnvConfig( correct_reward=1.0, shuffle_data=True, data_fraction=0.1, # Use 10% of data ) hotpot_dataset = HotPotQADataset( split="validation", config=hotpot_config, ) print(f"HotPotQA dataset size: {len(hotpot_dataset)}") ``` -------------------------------- ### Load Problems from GSM8K Dataset Source: https://context7.com/future-house/aviary/llms.txt Shows how to load problems from the GSM8K dataset and get a new environment instance for the first problem. Requires importing GSM8kDataset and asyncio. ```python async def run_from_dataset(): dataset = GSM8kDataset(split="val") env = dataset.get_new_env_by_idx(0) obs, tools = await env.reset() print(f"\nDataset problem: {obs[0].content[:150]}...") # Get environment ID env_id = await env.get_id() print(f"Environment ID: {env_id}") asyncio.run(run_from_dataset()) ``` -------------------------------- ### Define a Custom Aviary Environment Source: https://github.com/future-house/aviary/blob/main/README.md Example of defining a custom environment in Aviary. This snippet shows the necessary imports for creating a custom environment with a counter. ```python from collections import namedtuple from aviary.core import Environment, Message, ToolRequestMessage, Tool ``` -------------------------------- ### Define a Custom Counter Environment in Aviary Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a Custom Environment in Aviary.ipynb Implement a custom Aviary environment with a stateful counter. This example includes methods for resetting the environment, stepping through actions, and defining increment/decrement tools. ```python from pydantic import BaseModel from aviary.core import Environment, Message, Tool, ToolRequestMessage # State in this example is simply a counter class CounterEnvState(BaseModel): count: int class CounterEnv(Environment[CounterEnvState]): """A simple environment that allows an agent to modify a counter.""" async def reset(self) -> tuple[list[Message], list[Tool]]: """Initialize the environment with a counter set to 0.""" self.state = CounterEnvState(count=0) # Target count self.target = 10 # Create tools allowing the agent to increment and decrement counter self.tools = [ Tool.from_function(self.incr), Tool.from_function(self.decr), ] # Return an observation message with the counter and available tools return [Message(content=f"Count to 10. counter={self.state.count}")], self.tools async def step( self, action: ToolRequestMessage ) -> tuple[list[Message], float, bool, bool]: """Executes the tool call requested by the agent.""" obs = await self.exec_tool_calls(action) reward = int(self.state.count == self.target) # Returns observations, reward, done, truncated return obs, reward, reward == 1, False def incr(self) -> str: """Increment the counter.""" self.state.count += 1 return f"counter={self.state.count}" def decr(self) -> str: """Decrement the counter.""" self.state.count -= 1 return f"counter={self.state.count}" ``` -------------------------------- ### Define a Custom Counter Environment Source: https://context7.com/future-house/aviary/llms.txt Implement a custom Gymnasium-compatible environment where a language agent interacts with tools to increment or decrement a counter to reach a target value. This example demonstrates the core `Environment` class, `reset` and `step` methods, and tool definition. ```python import asyncio from collections import namedtuple from aviary.core import Environment, Message, ToolRequestMessage, Tool, ToolCall # Define environment state as a simple container CounterEnvState = namedtuple("CounterEnvState", ["count"]) class CounterEnv(Environment[CounterEnvState]): """Environment where an agent increments/decrements a counter to reach a target.""" def __init__(self, target: int = 10): self.target = target async def reset(self): """Initialize environment and return initial observation with available tools.""" self.state = CounterEnvState(count=0) self.tools = [ Tool.from_function(self.incr), Tool.from_function(self.decr), ] return [Message(content=f"Count to {self.target}. Current counter={self.state.count}")], self.tools async def step(self, action: ToolRequestMessage): """Execute tool calls and return (observations, reward, done, truncated).""" if not isinstance(action, ToolRequestMessage): return self.default_no_tool_calls_response obs = await self.exec_tool_calls(action) reward = int(self.state.count == self.target) done = reward == 1 return obs, reward, done, False def incr(self): """Increment the counter by 1.""" self.state = CounterEnvState(count=self.state.count + 1) return f"counter={self.state.count}" def decr(self): """Decrement the counter by 1.""" self.state = CounterEnvState(count=self.state.count - 1) return f"counter={self.state.count}" # Usage example async def run_environment(): env = CounterEnv(target=3) obs, tools = await env.reset() print(f"Initial observation: {obs[0].content}") print(f"Available tools: {[t.info.name for t in tools]}") # Simulate agent making tool calls for _ in range(3): action = ToolRequestMessage( tool_calls=[ToolCall.from_name("incr")] ) obs, reward, done, truncated = await env.step(action) print(f"Observation: {obs[0].content}, Reward: {reward}, Done: {done}") if done: break asyncio.run(run_environment()) ``` -------------------------------- ### Load and Use GSM8kDataset Source: https://context7.com/future-house/aviary/llms.txt Load the GSM8K dataset for math word problems using `GSM8kDataset`. Customize environment configurations with `CalculatorEnvConfig` and access individual environments or iterate through batches for training. Requires `pip install fhaviary[gsm8k]`. ```python import asyncio from aviary.core import TaskDataset, TaskConfig # Load GSM8K math dataset (requires: pip install fhaviary[gsm8k]) from aviary.envs.gsm8k import GSM8kDataset, CalculatorEnvConfig # Create dataset with custom configuration config = CalculatorEnvConfig( correct_reward=1.0, incorrect_reward=0.0, tool_failure_reward=-0.5, ) dataset = GSM8kDataset( split="val", # Options: train, val, test, train_full config=config, ) print(f"Dataset size: {len(dataset)}") # Get environment by index env = dataset.get_new_env_by_idx(0) print(f"Problem ID: {env.problem_id}") async def solve_problem(): obs, tools = await env.reset() print(f"Problem: {obs[0].content[:100]}...") print(f"Tools: {[t.info.name for t in tools]}") asyncio.run(solve_problem()) # Iterate through batches for training for batch in dataset.iter_batches(batch_size=4, shuffle=True): print(f"Batch of {len(batch)} environments") break # Just show first batch ``` -------------------------------- ### Demonstrate Document Creation with References Source: https://context7.com/future-house/aviary/llms.txt Shows how to create documents and manage references using a state object. Ensure the asyncio event loop is running. ```python import asyncio from aviary.core import RefState, create_document, get_word_count async def demo_argref(): state = RefState() # Create first document - result is stored as reference result1 = create_document("Introduction", "Hello world", state=state) print(f"Created: {result1}") # Output: doc-abc12345 (dict): {'title': 'Introduction', ...} # Create second document result2 = create_document("Conclusion", "Goodbye world", state=state) print(f"Created: {result2}") # Get references from state print(f"References: {list(state.refs.keys())}") # Use reference by name (pass the key string) ref_key = list(state.refs.keys())[0] word_count = get_word_count(ref_key, state=state) print(f"Word count result: {word_count}") asyncio.run(demo_argref()) ``` -------------------------------- ### Create and Use Calculator Environment Source: https://context7.com/future-house/aviary/llms.txt Demonstrates setting up a custom calculator environment for a specific math problem and then solving it using available tools. Requires importing necessary classes and asyncio. ```python env = CalculatorEnv( problem_id="custom_1", problem="Janet has 3 apples. She buys 5 more apples. How many apples does Janet have in total?", answer=8.0, config=CalculatorEnvConfig( correct_reward=1.0, incorrect_reward=0.0, tool_failure_reward=-1.0, ) ) ``` ```python async def solve_math_problem(): # Reset environment obs, tools = await env.reset() print(f"Problem: {obs[0].content}") print(f"Available tools: {[t.info.name for t in tools]}") # Use calculator tool calc_action = ToolRequestMessage( tool_calls=[ToolCall.from_name("calculator", expr="3 + 5")] ) obs, reward, done, _ = await env.step(calc_action) print(f"Calculator result: {obs[0].content}") print(f"Reward: {reward}, Done: {done}") # Submit answer submit_action = ToolRequestMessage( tool_calls=[ToolCall.from_name("submit_answer", answer="8")] ) obs, reward, done, _ = await env.step(submit_action) print(f"Submission result: {obs[0].content}") print(f"Final reward: {reward}, Done: {done}") asyncio.run(solve_math_problem()) ``` -------------------------------- ### Create and Use HotPotQA Environment Source: https://context7.com/future-house/aviary/llms.txt Demonstrates setting up a HotPotQA environment for multi-hop question answering and solving a question using search, lookup, and submit_answer tools. Requires importing specific classes from aviary.envs.hotpotqa and aviary.core. ```python import asyncio from uuid import UUID from aviary.envs.hotpotqa import HotPotQAEnv, HotPotQADataset, HotPotQAEnvConfig from aviary.core import ToolRequestMessage, ToolCall, EvalAnswerMode # Create HotPotQA environment env = HotPotQAEnv( question_id=UUID("12345678-1234-1234-1234-123456789012"), question="What is the capital of the country where the Eiffel Tower is located?", correct_answer="Paris", correct_reward=1.0, incorrect_reward=0.0, evaluation_mode=EvalAnswerMode.CONTAINS, ) ``` ```python async def answer_question(): # Reset environment obs, tools = await env.reset() print(f"Question: {obs[0].content}") print(f"Available tools: {[t.info.name for t in tools]}") # Output: ['search', 'lookup', 'submit_answer'] # Search for relevant entity search_action = ToolRequestMessage( tool_calls=[ToolCall.from_name("search", entity="Eiffel Tower")] ) obs, reward, done, _ = await env.step(search_action) print(f"\nSearch result (truncated): {obs[0].content[:200]}...") # Lookup specific keyword in the page lookup_action = ToolRequestMessage( tool_calls=[ToolCall.from_name("lookup", keyword="Paris")] ) obs, reward, done, _ = await env.step(lookup_action) print(f"\nLookup result: {obs[0].content[:200]}...") # Submit final answer submit_action = ToolRequestMessage( tool_calls=[ToolCall.from_name("submit_answer", answer="Paris")] ) obs, reward, done, _ = await env.step(submit_action) print(f"\nSubmission: {obs[0].content}") print(f"Reward: {reward}, Done: {done}") asyncio.run(answer_question()) ``` -------------------------------- ### Python Task Dataset Initialization Source: https://github.com/future-house/aviary/blob/main/README.md Demonstrates how to instantiate a specific task dataset, such as HotPotQADataset, for use in training or evaluation. The dataset can be initialized with a specific split like 'dev'. ```python from aviary.envs.hotpotqa import HotPotQADataset dataset = HotPotQADataset(split="dev") ``` -------------------------------- ### Load HotPotQA Dataset with Filtering Source: https://context7.com/future-house/aviary/llms.txt Illustrates loading a subset of the HotPotQA dataset for quick testing using a configuration object. Requires importing HotPotQAEnvConfig, HotPotQADataset, and asyncio. ```python async def run_hotpotqa_dataset(): config = HotPotQAEnvConfig( correct_reward=1.0, shuffle_data=True, data_fraction=0.01, # Use 1% of data for quick testing ) dataset = HotPotQADataset(split="validation", config=config) print(f"Dataset size: {len(dataset)}") env = dataset.get_new_env_by_idx(0) obs, tools = await env.reset() print(f"Sample question: {obs[0].content}") asyncio.run(run_hotpotqa_dataset()) ``` -------------------------------- ### Get Dataset Length Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a GSM8k Environment in Aviary.ipynb Returns the total number of problems available in the dataset. ```python def __len__(self) -> int: """Returns the number of problems in the dataset.""" return len(self.src_df) ``` -------------------------------- ### Environment Reset and Step Methods in Python Source: https://github.com/future-house/aviary/blob/main/README.md Illustrates the core methods required for an environment in Aviary: `reset` to initialize the environment state and return initial observations and tools, and `step` to execute an action and return new observations, reward, and termination status. ```python obs_msgs, tools = await env.reset() new_obs_msgs, reward, done, truncated = await env.step(action_msg) ``` -------------------------------- ### Perform Rollouts with RolloutManager Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a Custom Environment in Aviary.ipynb Instantiate a SimpleAgent and use LDP's RolloutManager to sample trajectories from a given environment factory. Ensure the environment_factory is correctly defined. ```python agent: SimpleAgent = SimpleAgent() runner: RolloutManager = RolloutManager(agent=agent) trajectories: list[tuple] = await runner.sample_trajectories( environment_factory=CounterEnv, batch_size=2, ) ``` -------------------------------- ### Evaluate an Agent on a Custom Environment using LDP in Python Source: https://github.com/future-house/aviary/blob/main/README.md Demonstrates how to evaluate a language agent on a custom environment using the LDP library. It includes defining a simple agent and using RolloutManager to sample trajectories. ```python from ldp.agent import Agent from ldp.graph import LLMCallOp from ldp.alg import RolloutManager class AgentState: """A container for maintaining agent state across interactions.""" def __init__(self, messages, tools): self.messages = messages self.tools = tools class SimpleAgent(Agent): def __init__(self, **kwargs): self._llm_call_op = LLMCallOp(**kwargs) async def init_state(self, tools): return AgentState([], tools) async def get_asv(self, agent_state, obs): """Take an action, observe new state, return value""" action = await self._llm_call_op( config={"name": "gpt-4o", "temperature": 0.1}, msgs=agent_state.messages + obs, tools=agent_state.tools, ) new_state = AgentState( messages=agent_state.messages + obs + [action], tools=agent_state.tools, ) # Return action, state, value return action, new_state, 0.0 # Create a simple agent and perform rollouts on the environment # Endpoint can be model identifier e.g. "claude-3-opus" depending on service agent = SimpleAgent(config={"model": "my_llm_endpoint"}) runner = RolloutManager(agent=agent) trajectories = await runner.sample_trajectories( environment_factory=CounterEnv, batch_size=2, ) ``` -------------------------------- ### Build Aviary Notebook Docker Image Source: https://github.com/future-house/aviary/blob/main/packages/notebook/README.md Build the default Docker image for running notebooks in containerized sandboxes. Ensure you are in the 'docker/' directory before running this command. ```bash cd docker/ docker build -t aviary-notebook-env -f Dockerfile.pinned . ``` -------------------------------- ### Initialize ToolSelector Class Source: https://context7.com/future-house/aviary/llms.txt Shows the import statement for the ToolSelector class, which uses an LLM to select and call tools based on conversation context. Useful for autonomous agents. ```python import asyncio from aviary.core import ToolSelector, Tool, Message, ToolSelectorLedger ``` -------------------------------- ### Python Environment Reset Method Source: https://github.com/future-house/aviary/blob/main/README.md Initializes the tools for the environment and returns initial observations and tools. The method is async to support asynchronous operations like database interactions. ```python from aviary.core import Message, Tool async def reset(self): self.tools = [Tool.from_function(ExampleEnv.print_story)] start = Message(content="Write a 5 word story and call print") return [start], self.tools ``` -------------------------------- ### Implement Calculator Environment Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a GSM8k Environment in Aviary.ipynb An environment for solving math problems using calculator and check answer tools. It requires problem details and configuration. ```python class CalculatorEnv(Environment[None]): def __init__( self, problem_id: str, problem: str, answer: float, config: CalculatorEnvConfig | None = None, ): """An environment for solving simple math problems using a calculator tool and a check answer tool. Arguments: problem_id: The unique identifier for the problem (index in the GSM8K dataset) problem: The calculation problem in string format. answer: The ground truth (correct) answer to the calculation problem. config: Configuration for environment behavior and rewards. """ self.problem_id = problem_id self.problem = problem self.answer = float(answer) self.config = config or CalculatorEnvConfig() self.calc_tool = Tool.from_function(self.calculator) self.check_tool = Tool.from_function(self.check_answer) self.tools = [self.calc_tool, self.check_tool] async def reset(self) -> tuple[list[Message], list[Tool]]: """Resets the environment, returning the initial problem statement and available tools. Returns: A tuple containing: - A list with the problem message for the agent to view. - A list of tools available for the agent to interact with. """ self.state = None # this environment is effectively stateless return [Message(content=self.problem)], self.tools async def step( self, action: ToolRequestMessage ) -> tuple[list[Message], float, bool, bool]: """Processes an action (tool request) and returns the result. Args: action: The action message containing tool requests. Returns: A tuple containing: - A list of response messages from the tools e.g. the output of the calculator - The total reward accumulated from the tool calls. - A flag indicating if the episode is done (e.g., answer is correct or a tool failure). - Always False, as this environment does not use truncation. """ # We must use a tool at each step if not action.tool_calls: return ( [ Message( content="Must call one of the provided tools (calculator or check_answer)." ) ], self.config.tool_failure_reward, self.config.done_on_failure, ``` -------------------------------- ### Test Image-Based QA with PaperQA Source: https://github.com/future-house/aviary/blob/main/packages/labbench/README.md This test function demonstrates setting up and evaluating an ImageQAEnvironment for tasks like TableQA. It configures PaperQA settings, agent behavior, and uses callbacks to store trajectories and track metrics. Ensure litellm is configured for retries to mitigate connection issues. ```python from typing import cast import litellm import pytest from ldp.agent import Agent from ldp.alg import ( Evaluator, EvaluatorConfig, MeanMetricsCallback, StoreTrajectoriesCallback, ) from paperqa.settings import AgentSettings, IndexSettings from aviary.envs.labbench import ( ImageQAEnvironment, ImageQATaskDataset, LABBenchDatasets, ) @pytest.mark.asyncio async def test_image_qa(tmp_path) -> None: litellm.num_retries = 8 # Mitigate connection-related failures settings = ImageQAEnvironment.make_base_settings() settings.agent = AgentSettings( agent_type="ldp.agent.SimpleAgent", index=IndexSettings(paper_directory=tmp_path), # TODO: add image support for paper_search tool_names={"gather_evidence", "gen_answer", "complete", "reset"}, agent_evidence_n=3, # Bumped up to collect several perspectives ) dataset = ImageQATaskDataset(dataset=LABBenchDatasets.TABLE_QA, settings=settings) t_cb = StoreTrajectoriesCallback() m_cb = MeanMetricsCallback(eval_dataset=dataset, track_tool_usage=True) evaluator = Evaluator( config=EvaluatorConfig( batch_size=256, # Use batch size greater than FigQA size and TableQA size max_rollout_steps=18, # Match aviary paper's PaperQA setting ), agent=cast(Agent, await settings.make_ldp_agent(settings.agent.agent_type)), dataset=dataset, callbacks=[t_cb, m_cb], ) await evaluator.evaluate() print(m_cb.eval_means) ``` -------------------------------- ### Define and Use Custom Environment Tools Source: https://context7.com/future-house/aviary/llms.txt Decorate functions with `@story_env.tool()` to register them as tools within a custom environment. The `run_story_env` function demonstrates resetting the environment, interacting with tools like `get_word_count` and `write_story`, and observing the results. ```python import asyncio # Assume story_env is defined elsewhere # from aviary.core import Environment # story_env = Environment() @story_env.tool() def write_story(story: str, state) -> str: """Write and submit a story. Args: story: The story text to submit. """ word_count = len(story.split()) if word_count > state.extras["max_words"]: return f"Story too long! {word_count} words exceeds limit of {state.extras['max_words']}." state.extras["story_written"] = True state.reward = 1.0 state.done = True return f"Story submitted successfully! ({word_count} words)" @story_env.tool() def get_word_count(text: str) -> str: """Count words in the given text. Args: text: Text to count words in. """ return f"Word count: {len(text.split())}" # Use the environment async def run_story_env(): # Create environment instance with parameters env = story_env(topic="space exploration", max_words=50) # Reset returns observations and tools obs, tools = await env.reset() print(f"Observation: {obs[0].content}") print(f"Tools: {[t.info.name for t in tools]}") # Simulate agent interaction from aviary.core import ToolRequestMessage, ToolCall # First, check word count action = ToolRequestMessage( tool_calls=[ToolCall.from_name("get_word_count", text="A short story about Mars.")] ) obs, reward, done, _ = await env.step(action) print(f"Word count result: {obs[0].content}") # Then submit story action = ToolRequestMessage( tool_calls=[ToolCall.from_name("write_story", story="The astronaut gazed at Mars.")] ) obs, reward, done, _ = await env.step(action) print(f"Submit result: {obs[0].content}") print(f"Reward: {reward}, Done: {done}") asyncio.run(run_story_env()) ``` -------------------------------- ### Create a basic message Source: https://github.com/future-house/aviary/blob/main/README.md Instantiate a Message object with content and role. The content can be a string. ```python msg = Message(content="Hello, world!", role="assistant") ``` -------------------------------- ### Run Tool Selection with Required Tool Use Source: https://context7.com/future-house/aviary/llms.txt Prepare messages, including a system prompt and user query, then invoke the ToolSelector. Set `tool_choice` to `ToolSelector.TOOL_CHOICE_REQUIRED` to force the model to select a tool. ```python async def run_selector(): # Prepare messages messages = [ Message(content="You are a helpful assistant with access to tools.", role="system"), Message(content="What's the weather like in Tokyo?", role="user"), ] # Get tool selection from LLM tool_request = await selector( messages=messages, tools=tools, tool_choice=ToolSelector.TOOL_CHOICE_REQUIRED, # Force tool use ) print(f"Selected tool calls: {tool_request.tool_calls}") for tc in tool_request.tool_calls: print(f" - {tc.function.name}({tc.function.arguments})") ``` -------------------------------- ### Create Calculator Environment Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a GSM8k Environment in Aviary.ipynb Generates a new Calculator environment instance for a given problem index. Initializes the environment with problem ID, question, numerical answer, and configuration. ```python def get_new_env_by_idx(self, idx: int) -> CalculatorEnv: """Creates a new Calculator environment instance for a specific problem in the dataset. Args: idx: Index of the problem in the dataset. Returns: A new Calculator environment initialized with the problem ID, question, answer, and configuration. """ row = self.src_df.iloc[idx] return CalculatorEnv( problem_id=row["problem_id"], problem=row["question"], answer=row["answer_num"], config=self.config, ) ``` -------------------------------- ### Configure Datasets with TaskConfig Source: https://context7.com/future-house/aviary/llms.txt Use `TaskConfig` to create datasets programmatically. This allows for flexible configuration of task names, training arguments, and evaluation arguments, enabling dataset creation for different tasks like GSM8K. ```python # Use TaskConfig for configuration-driven dataset creation task_config = TaskConfig( name="gsm8k", task_kwargs={"config": {"correct_reward": 1.0}}, train_kwargs={"split": "train"}, eval_kwargs={"split": "val"}, ) train_dataset = task_config.make_dataset("train") eval_dataset = task_config.make_dataset("eval") ``` -------------------------------- ### Initialize and Use ToolSelectorLedger Source: https://context7.com/future-house/aviary/llms.txt Create an instance of ToolSelectorLedger to track messages and tools. Messages and tools can be appended or extended to the ledger's respective properties. ```python # Using ToolSelectorLedger for message tracking ledger = ToolSelectorLedger() ledger.messages.append(Message(content="Hello", role="user")) ledger.tools.extend(tools) print(f"Ledger messages: {len(ledger.messages)}") print(f"Ledger tools: {[t.info.name for t in ledger.tools]}") ``` -------------------------------- ### Create Tool from Function Source: https://context7.com/future-house/aviary/llms.txt Use `Tool.from_function` to create a tool where the function's docstring becomes the tool's description. Access tool information like name, description, and parameters. ```python from aviary.core import Tool def calculate(expression: str) -> str: """Evaluate a mathematical expression safely.""" return eval(expression) calc_tool = Tool.from_function(calculate) print(f"Tool name: {calc_tool.info.name}") print(f"Description: {calc_tool.info.description}") print(f"Parameters: {calc_tool.info.parameters}") ``` -------------------------------- ### Define a Functional Environment Source: https://github.com/future-house/aviary/blob/main/README.md Use the `@fenv.start()` decorator to begin defining a functional environment. The decorated function should return the initial observation and environment state. ```python from aviary.core import fenv @fenv.start() def my_env(topic): # return the first observation and starting environment state # (empty in this case) return f"Write a story about {topic}", {} ``` -------------------------------- ### Python Environment Step Method Source: https://github.com/future-house/aviary/blob/main/README.md Processes an action and returns the next observation, reward, and done status. It utilizes `exec_tool_calls` to handle tool execution based on the action. ```python from aviary.core import Message async def step(self, action: Message): msgs = await self.exec_tool_calls(action, state=self.state) return msgs, self.state.reward, self.state.done, False ``` -------------------------------- ### Implement SimpleAgent for LDP Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a Custom Environment in Aviary.ipynb A custom agent implementation inheriting from LDP's Agent. It uses an LLMCallOp for tool requests and manages agent state updates based on observations. ```python from ldp.agent import Agent from ldp.alg import RolloutManager from ldp.graph import LLMCallOp from aviary.core import ToolRequestMessage class SimpleAgent(Agent): def __init__(self, **kwargs: dict) -> None: self._llm_call_op = LLMCallOp(**kwargs) async def init_state(self, tools: list[Tool]) -> AgentState: return AgentState(tools=tools) async def get_asv( self, agent_state: AgentState, obs: list[Message] ) -> tuple[ToolRequestMessage, AgentState, float]: """Take an action, observe new state, return value.""" action: ToolRequestMessage = await self._llm_call_op( config={"name": "gpt-4o", "temperature": 0.1}, msgs=agent_state.messages + obs, tools=agent_state.tools, ) new_state: AgentState = AgentState( messages=agent_state.messages + obs + [action.value], tools=agent_state.tools, ) # Return action, state, value return action, new_state, 0.0 ``` -------------------------------- ### Initialize ToolSelector with Model and History Source: https://context7.com/future-house/aviary/llms.txt Instantiate ToolSelector with a specific model and enable message accumulation to maintain conversation history. Tools are provided as a list of Tool objects. ```python tools = [ Tool.from_function(get_weather), Tool.from_function(get_time), ] selector = ToolSelector( model_name="gpt-4o-mini", accum_messages=True, # Keep conversation history ) ``` -------------------------------- ### Evaluate Math Word Problems with ToolSelector Source: https://github.com/future-house/aviary/blob/main/tutorials/Building a GSM8k Environment in Aviary.ipynb This script evaluates math word problems using the ToolSelector agent. It iterates through a dataset, resets the environment for each problem, and uses the ToolSelector to generate tool calls until a solution is found or max steps are reached. Ensure 'dataset' and 'env' are properly initialized. ```python from aviary.core import ToolSelector dataset = GSM8kDataset(split="train") total_reward = 0 verbose = True # Whether to explicitly print the environment obserations and actions. n_questions = 3 max_steps = 5 # Maximum number of actions the agent can take. for i in range(n_questions): print(f"Evaluating problem number {i + 1}:\n") env = dataset.get_new_env_by_idx(i) obs, tools = await env.reset() tool_selector = ToolSelector(model_name="gpt-4o", accum_messages=True) for _ in range(max_steps): action = await tool_selector(obs, tools) if verbose: print(f"Observation is {obs}\n") print(f"Action is {action}\n") obs, reward, done, _ = await env.step(action) total_reward += reward print() if done: break print(f"Accuracy is {total_reward / n_questions * 100}%") ``` -------------------------------- ### Run GridGameEnv and Export Frames Source: https://context7.com/future-house/aviary/llms.txt Executes the `GridGameEnv` and demonstrates exporting frames at different stages of the game. This shows how to capture and inspect the environment's state over time. ```python async def run_with_frames(): env = GridGameEnv(grid_size=3, target=(2, 2)) obs, tools = await env.reset() # Export initial frame frame = env.export_frame() print(f"Initial state: {frame.state}") print(f"Environment info: {frame.info}") # Make some moves from aviary.core import ToolCall actions = ["move_right", "move_right", "move_up", "move_up"] for action_name in actions: action = ToolRequestMessage(tool_calls=[ToolCall.from_name(action_name)]) obs, reward, done, _ = await env.step(action) frame = env.export_frame() print(f"After {action_name}: position={frame.state['position']}, moves={frame.state['moves']}") if done: print(f"Reached target! Final reward: {reward}") break asyncio.run(run_with_frames()) ``` -------------------------------- ### Python Multiline Docstring with Excluded Info Source: https://github.com/future-house/aviary/blob/main/README.md Use a prefixed docstring with '\f' to separate descriptive information from implementation details. This is useful for tool descriptions where summary information should be visible but internal details should be hidden. ```python def print_story(story: str | bytes, state: ExampleState): r"""Print a story. Extra information that is part of the tool description. \f This sentence is excluded because it's an implementation detail. Args: story: Story to print, either as a string or bytes. state: Environment state. """ print(story) state.reward = 1 state.done = True ```