mirror of
https://github.com/langchain-ai/langgraph-codeact.git
synced 2026-07-18 18:34:31 -04:00
cr
This commit is contained in:
@@ -26,6 +26,8 @@ pip install langchain langchain-mcp-adapters langchain-anthropic
|
||||
|
||||
## Example
|
||||
|
||||
A full version of this in one file can be found [here](examples/math.py)
|
||||
|
||||
### 1. Define your tools
|
||||
|
||||
You can use any tools you want, including custom tools, LangChain tools, or MCP tools. In this example, we define a few simple math functions.
|
||||
@@ -117,7 +119,7 @@ import io
|
||||
def eval(code: str, _locals: dict) -> tuple:
|
||||
# Store original keys before execution
|
||||
original_keys = set(_locals.keys())
|
||||
|
||||
|
||||
try:
|
||||
with contextlib.redirect_stdout(io.StringIO()) as f:
|
||||
exec(code, builtins.__dict__, _locals)
|
||||
@@ -126,7 +128,7 @@ def eval(code: str, _locals: dict) -> tuple:
|
||||
result = "<code ran, no output printed to stdout>"
|
||||
except Exception as e:
|
||||
result = f"Error during execution: {repr(e)}"
|
||||
|
||||
|
||||
# Determine new variables created during execution
|
||||
new_keys = set(_locals.keys()) - original_keys
|
||||
new_vars = {key: _locals[key] for key in new_keys}
|
||||
@@ -144,7 +146,8 @@ from langgraph.checkpoint.memory import MemorySaver
|
||||
|
||||
model = init_chat_model("claude-3-7-sonnet-latest", model_provider="anthropic")
|
||||
|
||||
code_act = create_codeact(tools, model, eval, checkpointer=MemorySaver())
|
||||
code_act = create_codeact(model, tools, eval)
|
||||
agent = code_act.compile(checkpointer=MemorySaver())
|
||||
```
|
||||
|
||||
### 4. Run it!
|
||||
@@ -153,9 +156,14 @@ You can use the `.invoke()` method to get the final result, or the `.stream()` m
|
||||
|
||||
```py
|
||||
|
||||
for typ, chunk in code_act.stream(
|
||||
"A batter hits a baseball at 45.847 m/s at an angle of 23.474° above the horizontal. The outfielder, who starts facing the batter, picks up the baseball as it lands, then throws it back towards the batter at 24.12 m/s at an angle of 39.12 degrees. How far is the baseball from where the batter originally hit it? Assume zero air resistance.",
|
||||
messages = [{
|
||||
"role": "user",
|
||||
"content": "A batter hits a baseball at 45.847 m/s at an angle of 23.474° above the horizontal. The outfielder, who starts facing the batter, picks up the baseball as it lands, then throws it back towards the batter at 24.12 m/s at an angle of 39.12 degrees. How far is the baseball from where the batter originally hit it? Assume zero air resistance."
|
||||
}]
|
||||
for typ, chunk in agent.stream(
|
||||
{"messages": messages},
|
||||
stream_mode=["values", "messages"],
|
||||
config={"configurable": {"thread_id": 1}},
|
||||
):
|
||||
if typ == "messages":
|
||||
print(chunk[0].content, end="")
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import math
|
||||
|
||||
from langchain_core.tools import tool
|
||||
import builtins
|
||||
import contextlib
|
||||
import io
|
||||
|
||||
from langchain.chat_models import init_chat_model
|
||||
from langgraph_codeact import create_codeact
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
|
||||
|
||||
def eval(code: str, _locals: dict) -> tuple:
|
||||
# Store original keys before execution
|
||||
original_keys = set(_locals.keys())
|
||||
|
||||
try:
|
||||
with contextlib.redirect_stdout(io.StringIO()) as f:
|
||||
exec(code, builtins.__dict__, _locals)
|
||||
result = f.getvalue()
|
||||
if not result:
|
||||
result = "<code ran, no output printed to stdout>"
|
||||
except Exception as e:
|
||||
result = f"Error during execution: {repr(e)}"
|
||||
|
||||
# Determine new variables created during execution
|
||||
new_keys = set(_locals.keys()) - original_keys
|
||||
new_vars = {key: _locals[key] for key in new_keys}
|
||||
return result, new_vars
|
||||
@tool
|
||||
def add(a: float, b: float) -> float:
|
||||
"""Add two numbers together."""
|
||||
return a + b
|
||||
|
||||
@tool
|
||||
def multiply(a: float, b: float) -> float:
|
||||
"""Multiply two numbers together."""
|
||||
return a * b
|
||||
|
||||
@tool
|
||||
def divide(a: float, b: float) -> float:
|
||||
"""Divide two numbers."""
|
||||
return a / b
|
||||
|
||||
@tool
|
||||
def subtract(a: float, b: float) -> float:
|
||||
"""Subtract two numbers."""
|
||||
return a - b
|
||||
|
||||
@tool
|
||||
def sin(a: float) -> float:
|
||||
"""Take the sine of a number."""
|
||||
return math.sin(a)
|
||||
|
||||
@tool
|
||||
def cos(a: float) -> float:
|
||||
"""Take the cosine of a number."""
|
||||
return math.cos(a)
|
||||
|
||||
@tool
|
||||
def radians(a: float) -> float:
|
||||
"""Convert degrees to radians."""
|
||||
return math.radians(a)
|
||||
|
||||
@tool
|
||||
def exponentiation(a: float, b: float) -> float:
|
||||
"""Raise one number to the power of another."""
|
||||
return a**b
|
||||
|
||||
@tool
|
||||
def sqrt(a: float) -> float:
|
||||
"""Take the square root of a number."""
|
||||
return math.sqrt(a)
|
||||
|
||||
@tool
|
||||
def ceil(a: float) -> float:
|
||||
"""Round a number up to the nearest integer."""
|
||||
return math.ceil(a)
|
||||
|
||||
tools = [
|
||||
add,
|
||||
multiply,
|
||||
divide,
|
||||
subtract,
|
||||
sin,
|
||||
cos,
|
||||
radians,
|
||||
exponentiation,
|
||||
sqrt,
|
||||
ceil,
|
||||
]
|
||||
|
||||
model = init_chat_model("claude-3-7-sonnet-latest", model_provider="anthropic")
|
||||
|
||||
code_act = create_codeact(model, tools, eval)
|
||||
agent = code_act.compile(checkpointer=MemorySaver())
|
||||
|
||||
if __name__ == "__main__":
|
||||
messages = [{
|
||||
"role": "user",
|
||||
"content": "A batter hits a baseball at 45.847 m/s at an angle of 23.474° above the horizontal. The outfielder, who starts facing the batter, picks up the baseball as it lands, then throws it back towards the batter at 24.12 m/s at an angle of 39.12 degrees. How far is the baseball from where the batter originally hit it? Assume zero air resistance."
|
||||
}]
|
||||
for typ, chunk in agent.stream(
|
||||
{"messages": messages},
|
||||
stream_mode=["values", "messages"],
|
||||
config={"configurable": {"thread_id": 1}},
|
||||
):
|
||||
if typ == "messages":
|
||||
print(chunk[0].content, end="")
|
||||
elif typ == "values":
|
||||
print("\n\n---answer---\n\n", chunk)
|
||||
|
||||
|
||||
@@ -69,10 +69,11 @@ Reminder: use python code snippets to call tools"""
|
||||
|
||||
def sandbox(state: CodeActState):
|
||||
script = state["script"]
|
||||
context = state.get("context", {})
|
||||
old_context = state.get("context", {})
|
||||
context = {**old_context, **{tool.name: tool.func for tool in _tools}}
|
||||
# execute the script
|
||||
output, new_vars = eval_fn(script, context)
|
||||
new_context = {**context, **new_vars}
|
||||
new_context = {**old_context, **new_vars}
|
||||
return {"messages": [{"role": "user", "content": output}], "context": new_context}
|
||||
|
||||
agent = StateGraph(CodeActState)
|
||||
|
||||
Reference in New Issue
Block a user