Math via python code with a single agent

The point of this example is to illustrate that for agents that have an AgentExecutor (which most frameworks have apart from Autogen), the approach from MathChat can be done with a single agent, as the second conversation partner there just plays the role of an AgentExecutor.

[1]:
import os, sys
from pathlib import Path
from dotenv import load_dotenv

WORKING_DIR = Path(os.path.realpath("."))


try:
    from motleycrew import MotleyCrew
except ImportError:
    # if we are running this from source
    motleycrew_location = os.path.realpath( "..")
    sys.path.append(motleycrew_location)

from motleycrew import MotleyCrew
from motleycrew.agents.crewai import CrewAIMotleyAgent
from motleycrew.tools import PythonREPLTool
from motleycrew.common import configure_logging
from motleycrew.tasks import SimpleTask

configure_logging(verbose=True)
load_dotenv()
[1]:
True
[2]:
"""Main function of running the example."""
repl_tool = PythonREPLTool()

# Define your agents with roles and goals
solver = CrewAIMotleyAgent(
    role="High School Math Teacher",
    goal="Generate great solutions to math problems",
    backstory="""You are a high school math teacher with a passion for problem-solving.
To solve a math problem, you first reason about it, step by step, then generate the code to solve it exactly,
using sympy, then use the REPL tool to evaluate that code, and then
use the output to generate a human-readable solution in LaTeX format.
Don't use dashes to indicate bullet points, don't output any backticks, just the LaTeX""",
    verbose=True,
    delegation=False,
    tools=[repl_tool],
)

problems = [
    "If $725x + 727y = 1500$ and $729x+ 731y = 1508$, "
    "what are the values of $x$, $y$, and $x - y$ ?",
]

# Create tasks for your agents
crew = MotleyCrew()
task = SimpleTask(crew = crew,
    name="solve math problem",
    description=f"""Create a nice human-readable solution to the following problem:
    {problems[0]}""",
    additional_params={"expected_output": "human-readable solution in LaTeX format"},
    agent=solver,
)

# Get your crew to work!
crew.run()

display(task.output)
2024-05-24 11:28:55,150 - INFO - No db_path provided, creating temporary directory for database
2024-05-24 11:28:55,150 - INFO - Using Kuzu graph store with path: C:\Users\Egor\AppData\Local\Temp\tmpu9yewyeu\kuzu_db
2024-05-24 11:28:55,168 - INFO - Node table MotleyGraphNode does not exist in the database, creating
2024-05-24 11:28:55,180 - INFO - Relation table dummy from MotleyGraphNode to MotleyGraphNode does not exist in the database, creating
2024-05-24 11:28:55,192 - INFO - Node table TaskNode does not exist in the database, creating
2024-05-24 11:28:55,203 - INFO - Property name not present in table for label TaskNode, creating
2024-05-24 11:28:55,215 - INFO - Property done not present in table for label TaskNode, creating
2024-05-24 11:28:55,227 - INFO - Inserting new node with label TaskNode: name='solve math problem' done=False
2024-05-24 11:28:55,243 - INFO - Node created OK
2024-05-24 11:28:55,245 - INFO - Relation table task_is_upstream from TaskNode to TaskNode does not exist in the database, creating
2024-05-24 11:28:55,255 - WARNING - Multithreading is not implemented yet, will run in single thread
2024-05-24 11:28:55,277 - INFO - Available tasks: [SimpleTask(name=solve math problem, done=False)]
2024-05-24 11:28:55,277 - INFO - Processing task: SimpleTask(name=solve math problem, done=False)
2024-05-24 11:28:55,291 - INFO - Got a matching unit for task SimpleTask(name=solve math problem, done=False)
2024-05-24 11:28:55,292 - INFO - Processing task: TaskUnit(status=pending)
2024-05-24 11:28:55,293 - INFO - Assigned unit TaskUnit(status=pending) to agent Agent(name=High School Math Teacher), dispatching
2024-05-24 11:28:55,293 - INFO - Node TaskUnit(status=running) does not exist, creating
2024-05-24 11:28:55,294 - INFO - Node table SimpleTaskUnit does not exist in the database, creating
2024-05-24 11:28:55,305 - INFO - Property status not present in table for label SimpleTaskUnit, creating
2024-05-24 11:28:55,318 - INFO - Property output not present in table for label SimpleTaskUnit, creating
2024-05-24 11:28:55,318 - WARNING - No known Cypher type matching annotation typing.Optional[typing.Any], will use JSON string
2024-05-24 11:28:55,331 - INFO - Property name not present in table for label SimpleTaskUnit, creating
2024-05-24 11:28:55,344 - INFO - Property prompt not present in table for label SimpleTaskUnit, creating
2024-05-24 11:28:55,358 - INFO - Property message_history not present in table for label SimpleTaskUnit, creating
2024-05-24 11:28:55,359 - WARNING - No known Cypher type matching annotation typing.List[str], will use JSON string
2024-05-24 11:28:55,375 - INFO - Inserting new node with label SimpleTaskUnit: TaskUnit(status=running)
2024-05-24 11:28:55,376 - WARNING - No known Cypher type matching annotation typing.List[str], will use JSON string
2024-05-24 11:28:55,394 - INFO - Node created OK
2024-05-24 11:28:55,398 - INFO - Relation from TaskUnit(status=running) to name='solve math problem' done=False does not exist, creating
2024-05-24 11:28:55,401 - INFO - Relation table task_unit_belongs from SimpleTaskUnit to TaskNode does not exist in the database, creating
2024-05-24 11:28:55,411 - INFO - Creating relation task_unit_belongs from SimpleTaskUnit:0 to TaskNode:0
2024-05-24 11:28:55,429 - INFO - Relation created OK
2024-05-24 11:28:55,432 - WARNING - Lunary public key is not set, tracking will be disabled


> Entering new CrewAgentExecutor chain...
2024-05-24 11:28:56,705 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
To solve the system of equations given by:
1. \( 725x + 727y = 1500 \)
2. \( 729x + 731y = 1508 \)

We will use the method of elimination to find the values of \( x \) and \( y \). First, we will eliminate \( y \) by subtracting the first equation from the second. This will give us an equation in terms of \( x \) only.

Let's calculate the coefficients and constants after subtraction:
- Coefficient of \( x \): \( 729 - 725 \)
- Coefficient of \( y \): \( 731 - 727 \)
- Constant term: \( 1508 - 1500 \)

```
Use Tool: python_repl(command="print(729 - 725, 731 - 727, 1508 - 1500)")
```
2024-05-24 11:29:06,112 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
2024-05-24 11:29:06,115 - WARNING - Python REPL can execute arbitrary code. Use with caution.


4 4 8


2024-05-24 11:29:06,962 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
From the result of the subtraction, we have the simplified equation:
\[ 4x + 4y = 8 \]

To simplify further, we divide the entire equation by 4:
\[ x + y = 2 \]

Now, we have a new system of equations:
1. \( x + y = 2 \)
2. \( 725x + 727y = 1500 \)

We can solve this system using substitution or elimination. Let's use substitution. We express \( y \) in terms of \( x \) from the first equation:
\[ y = 2 - x \]

Substitute \( y = 2 - x \) into the second equation:
\[ 725x + 727(2 - x) = 1500 \]

Expanding and simplifying this equation will give us the value of \( x \). Let's calculate it:

```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:17,493 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"




2024-05-24 11:29:19,615 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:24,848 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


I already used the python_repl tool with input from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq). So I already know that and must stop using it with same input.
I could give my best complete final answer if I'm ready, using exaclty the expected format bellow:

```
Final Answer: [my expected final answer, entire content of my most complete final answer goes here]
```
I MUST use these formats, my jobs depends on it!

2024-05-24 11:29:25,688 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:32,854 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


I already used the python_repl tool with input from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq). So I already know that and must stop using it with same input.
I could give my best complete final answer if I'm ready, using exaclty the expected format bellow:

```
Final Answer: [my expected final answer, entire content of my most complete final answer goes here]
```
I MUST use these formats, my jobs depends on it!

2024-05-24 11:29:33,853 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:38,556 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


I already used the python_repl tool with input from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq). So I already know that and must stop using it with same input.
I could give my best complete final answer if I'm ready, using exaclty the expected format bellow:

```
Final Answer: [my expected final answer, entire content of my most complete final answer goes here]
```
I MUST use these formats, my jobs depends on it!

2024-05-24 11:29:39,509 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:42,264 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


It seems we encountered an unexpected error while trying to use the tool. This was the error: PythonREPL.run() missing 1 required positional argument: 'command'

2024-05-24 11:29:43,180 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:48,477 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


I already used the python_repl tool with input from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq). So I already know that and must stop using it with same input.
I could give my best complete final answer if I'm ready, using exaclty the expected format bellow:

```
Final Answer: [my expected final answer, entire content of my most complete final answer goes here]
```
I MUST use these formats, my jobs depends on it!

2024-05-24 11:29:49,566 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
```
Use Tool: python_repl(command="from sympy import symbols, Eq, solve; x = symbols('x'); eq = Eq(725*x + 727*(2 - x), 1500); solve(eq)")
```
2024-05-24 11:29:54,281 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"


[-23]


2024-05-24 11:29:55,181 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
2024-05-24 11:30:04,021 - WARNING - No known Cypher type matching annotation typing.Optional[typing.Any], will use JSON string
2024-05-24 11:30:04,039 - INFO - Task unit TaskUnit(status=running) completed, marking as done
2024-05-24 11:30:04,077 - INFO - Available tasks: []
2024-05-24 11:30:04,077 - INFO - Nothing left to do, exiting
Final Answer: To solve the system of equations given by:
1. \( 725x + 727y = 1500 \)
2. \( 729x + 731y = 1508 \)

We first subtract the first equation from the second to eliminate \( y \), resulting in:
\[ 4x + 4y = 8 \]
which simplifies to:
\[ x + y = 2 \]

Using this in conjunction with the first equation, we substitute \( y = 2 - x \) into \( 725x + 727y = 1500 \) to get:
\[ 725x + 727(2 - x) = 1500 \]
Solving this equation gives \( x = -23 \).

Substituting \( x = -23 \) back into \( x + y = 2 \), we find:
\[ -23 + y = 2 \]
\[ y = 25 \]

Thus, the values are:
\[ x = -23, \quad y = 25, \quad x - y = -23 - 25 = -48 \]

Therefore, \( x = -23 \), \( y = 25 \), and \( x - y = -48 \).

> Finished chain.
'To solve the system of equations given by:\n1. \\( 725x + 727y = 1500 \\)\n2. \\( 729x + 731y = 1508 \\)\n\nWe first subtract the first equation from the second to eliminate \\( y \\), resulting in:\n\\[ 4x + 4y = 8 \\]\nwhich simplifies to:\n\\[ x + y = 2 \\]\n\nUsing this in conjunction with the first equation, we substitute \\( y = 2 - x \\) into \\( 725x + 727y = 1500 \\) to get:\n\\[ 725x + 727(2 - x) = 1500 \\]\nSolving this equation gives \\( x = -23 \\).\n\nSubstituting \\( x = -23 \\) back into \\( x + y = 2 \\), we find:\n\\[ -23 + y = 2 \\]\n\\[ y = 25 \\]\n\nThus, the values are:\n\\[ x = -23, \\quad y = 25, \\quad x - y = -23 - 25 = -48 \\]\n\nTherefore, \\( x = -23 \\), \\( y = 25 \\), and \\( x - y = -48 \\).'
[3]:
from IPython.display import display, Math, Latex
for line in task.output.split("\n"):
    display(Latex(line))
To solve the system of equations given by:
1. \( 725x + 727y = 1500 \)
2. \( 729x + 731y = 1508 \)
We first subtract the first equation from the second to eliminate \( y \), resulting in:
\[ 4x + 4y = 8 \]
which simplifies to:
\[ x + y = 2 \]
Using this in conjunction with the first equation, we substitute \( y = 2 - x \) into \( 725x + 727y = 1500 \) to get:
\[ 725x + 727(2 - x) = 1500 \]
Solving this equation gives \( x = -23 \).
Substituting \( x = -23 \) back into \( x + y = 2 \), we find:
\[ -23 + y = 2 \]
\[ y = 25 \]
Thus, the values are:
\[ x = -23, \quad y = 25, \quad x - y = -23 - 25 = -48 \]
Therefore, \( x = -23 \), \( y = 25 \), and \( x - y = -48 \).
[ ]:
final_result = task.output