langgraph: bring back tool content stringify (#1114)

This commit is contained in:
Vadym Barda
2024-07-24 10:36:32 -04:00
committed by GitHub
parent 82cbe25be8
commit ca6aef4746
2 changed files with 55 additions and 2 deletions
+23 -2
View File
@@ -1,4 +1,5 @@
import asyncio
import json
from copy import copy
from typing import (
Any,
@@ -28,6 +29,16 @@ INVALID_TOOL_NAME_ERROR_TEMPLATE = (
TOOL_CALL_ERROR_TEMPLATE = "Error: {error}\n Please fix your mistakes."
def str_output(output: Any) -> str:
if isinstance(output, str):
return output
else:
try:
return json.dumps(output)
except Exception:
return str(output)
class ToolNode(RunnableCallable):
"""A node that runs the tools called in the last AIMessage.
@@ -94,7 +105,12 @@ class ToolNode(RunnableCallable):
try:
input = {**call, **{"type": "tool_call"}}
return self.tools_by_name[call["name"]].invoke(input, config)
tool_message: ToolMessage = self.tools_by_name[call["name"]].invoke(
input, config
)
# TODO: handle this properly in core
tool_message.content = str_output(tool_message.content)
return tool_message
except Exception as e:
if not self.handle_tool_errors:
raise e
@@ -106,7 +122,12 @@ class ToolNode(RunnableCallable):
return invalid_tool_message
try:
input = {**call, **{"type": "tool_call"}}
return await self.tools_by_name[call["name"]].ainvoke(input, config)
tool_message: ToolMessage = await self.tools_by_name[call["name"]].ainvoke(
input, config
)
# TODO: handle this properly in core
tool_message.content = str_output(tool_message.content)
return tool_message
except Exception as e:
if not self.handle_tool_errors:
raise e
+32
View File
@@ -267,6 +267,13 @@ async def test_tool_node():
raise ValueError("Test error")
return f"tool2: {some_val} - {some_other_val}"
async def tool3(some_val: int, some_other_val: str) -> str:
"""Tool 3 docstring."""
return [
{"key_1": some_val, "key_2": "foo"},
{"key_1": some_other_val, "key_2": "baz"},
]
result = ToolNode([tool1]).invoke(
{
"messages": [
@@ -377,6 +384,31 @@ async def test_tool_node():
)
assert tool_message.tool_call_id == "some 0"
# list of dicts tool content
result3 = await ToolNode([tool3]).ainvoke(
{
"messages": [
AIMessage(
"hi?",
tool_calls=[
{
"name": "tool3",
"args": {"some_val": 2, "some_other_val": "bar"},
"id": "some 0",
}
],
)
]
}
)
tool_message: ToolMessage = result3["messages"][-1]
assert tool_message.type == "tool"
assert (
tool_message.content
== '[{"key_1": 2, "key_2": "foo"}, {"key_1": "bar", "key_2": "baz"}]'
)
assert tool_message.tool_call_id == "some 0"
def my_function(some_val: int, some_other_val: str) -> str:
return f"{some_val} - {some_other_val}"