Saplings

repository·master·Indexed 42 days ago

https://github.com/shobrook/saplings

A library that adds tree search capabilities, such as Monte Carlo Tree Search (MCTS) and A*, to LLM agents. Saplings enables agents to explore multiple tool-use trajectories and evaluate them to find optimal paths. It includes implementations like MonteCarloAgent, AStarAgent, GreedyAgent, and COTAgent, and utilizes LiteLLM for model integration and a customizable Evaluator to score trajectories.

Tokens
2.1K
Snippets
7
Records
10
Agent score
5%

What's inside Saplings

  1. Choose an Agent type based on search strategy

    master

    Saplings provides several agent implementations, each balancing speed, cost, and effectiveness differently:

    • GreedyAgent: Implements greedy best-first search. It is the fastest and cheapest but cannot backtrack, making it the least effective.
    • MonteCarloAgent: Implements Monte Carlo Tree Search (MCTS). It is the most effective as it balances exploration and exploitation, but it is the slowest and most expensive.
    • AStarAgent: Implements a variation of the A* pathfinding algorithm. It is a middle-ground option that can backtrack and recover from mistakes but does not update its strategy based on past trajectories.
    • COTAgent: A standard Chain-of-Thought agent. It does not implement any search; it simply calls tools sequentially. Use this as a baseline for comparison.
  2. Choose a search algorithm (Agent types)

    master

    Saplings provides several agent implementations depending on the desired reasoning strategy:

    • MonteCarloAgent: Implements Monte Carlo Tree Search (MCTS).
    • AStarAgent: Implements A* search.
    • GreedyAgent: Implements greedy best-first search.
    • COTAgent: Implements standard Chain-of-Thought (no tree search).
  3. Quickstart: Implement a Monte Carlo Tree Search (MCTS) agent

    master

    This example demonstrates the minimum setup required to create a search-enabled agent using a multiplication tool and the MonteCarloAgent algorithm. Saplings uses Model (a LiteLLM wrapper) and an Evaluator to guide the search process.

    from saplings.examples import MultiplicationTool
    from saplings import MonteCarloAgent, Evaluator, Model
    
    model = Model(model="openai/gpt-4o") # Wraps LiteLLM
    evaluator = Evaluator(model)
    tools = [MultiplicationTool()]
    
    agent = MonteCarloAgent(tools, model, evaluator)
    messages, _, _ = agent.run("Let x = 9418.343 * 8.11 and y = 2x. Calculate (xy)(x^2).")
  4. Create a custom tool by extending the Tool class

    master

    To create a tool for your agent, extend the saplings.abstract.Tool base class. You must define instance variables for the tool's metadata and implement an asynchronous run method for execution.

    Required Variables

    • name (str): Name of the tool.
    • description (str): Description of what the tool does and when to call it.
    • parameters (dict): Arguments for the tool defined as a JSON schema (OpenAI function calling style).
    • is_terminal (bool): If True, calling this tool terminates the search trajectory. Use this for tools that generate final answers.

    Required Method

    • async def run(self, **kwargs): Executes the tool logic. Arguments must match the keys defined in self.parameters.
    from saplings.abstract import Tool
    
    class MultiplicationTool(Tool):
       def __init__(self, **kwargs):
          self.name = "multiply"
          self.description = "Multiplies two numbers and returns the result number."
          self.parameters = {
             "type": "object",
             "properties": {
                "a": {
                   "type": "number",
                   "description": "The number to multiply."
                },
                "b": {
                   "type": "number",
                   "description": "The number to multiply by."
                }
             },
             "required": ["a", "b"],
             "additionalProperties": False
          }
          self.is_terminal = False
    
       async def run(self, a, b, **kwargs):
          return a * b
  5. Use and convert Message objects

    master

    Messages are the core data structure in Saplings, representing a search trajectory (a list of messages). They are compatible with OpenAI message formats (user input, tool calls, tool responses, assistant responses).

    Key features:

    • OpenAI Compatibility: Use .to_openai_message() (or .to_openai_response()) to convert Saplings messages to OpenAI-style dictionaries.
    • Raw Output: For tool responses, the raw_output property contains the original tool output, which may differ from the content property (the version shown to the model).

    When an agent runs, it returns a list of messages representing the best trajectory found.

    ```python
    # Running an agent and converting the trajectory to OpenAI format
    messages, _, _ = agent.run("This is my prompt!")
    openai_messages = [message.to_openai_response() for message in messages]
    
    print(openai_messages)
    # [{
  6. Set up an Evaluator to guide search

    master

    An Evaluator guides the search process by scoring trajectories. It takes a list of messages (a trajectory) and returns a score between 0 and 1. A score of 1.0 typically indicates the problem is solved.

    By default, Evaluator(model) uses the provided LLM to score trajectories. You can customize the system prompt and sampling rate via the Evaluator parameters, or implement a custom evaluator class.

    from saplings import Evaluator
    
    evaluator = Evaluator(model)
  7. Configure a Model using LiteLLM

    master

    Saplings uses the Model class to wrap LiteLLM, providing access to over 100 LLMs. You specify the model using a provider/model string (e.g., openai/gpt-4o). Any additional keyword arguments (kwargs) passed to the Model constructor are passed down to all LiteLLM completion calls.

    from saplings import Model
    
    model = Model("openai/gpt-4o")
  8. Run an agent and handle results

    master

    Once an agent is initialized with tools, a model, and an evaluator, you can execute it using .run() (synchronous) or .run_async() (asynchronous).

    Return Values

    The .run() method returns a tuple containing:

    1. messages: A list of Message objects representing the best tool-use trajectory.
    2. score: The final score of the trajectory as determined by the evaluator.
    3. is_solution: A boolean indicating if the search terminated because the evaluator deemed the trajectory a solution.
    # Synchronous
    messages, score, is_solution = agent.run("What's 2 * 2?")
    
    # Asynchronous
    # messages, score, is_solution = await agent.run_async("What's 2 * 2?")
  9. Configure Agent parameters

    master

    All agents in Saplings share a common set of parameters used to control their search behavior and LLM interaction.

    Common Parameters

    • tools (List[Tool]): The list of tools available to the agent.
    • model (Model): The LLM provider used for tool calling.
    • evaluator (BaseEvaluator): The function used to guide the search process.
    • prompt (str): The system prompt for the agent.
    • b_factor (int): The branching factor (number of potential next tool calls to evaluate). Note: This has no effect on COTAgent.
    • max_depth (int): The maximum depth of the search tree.
    • threshold (float): The cutoff score. If a trajectory's evaluation score $\ge$ threshold, the search terminates and the trajectory is accepted.
    • verbose (bool): Enables logging statements.
    • tool_choice ("auto" | "required"): Determines if the model must always call a tool ("required") or can generate a normal response ("auto").
    • parallel_tool_calls (bool): Allows the model to generate multiple tool calls in one request.

    Agent-Specific Parameters

    • MonteCarloAgent: Includes max_rollouts (int, default=10), which controls the maximum number of simulations performed.