core[minor]: rename ToolMessage.raw_output -> artifact (#24185)

This commit is contained in:
Bagatur 2024-07-12 09:52:44 -07:00 committed by GitHub
parent d77d9bfc00
commit 6166ea67a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 144 additions and 106 deletions

View File

@ -21,8 +21,11 @@ class ToolMessage(BaseMessage):
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -36,7 +39,7 @@ class ToolMessage(BaseMessage):
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -54,12 +57,14 @@ class ToolMessage(BaseMessage):
type: Literal["tool"] = "tool"
"""The type of the message (used for serialization). Defaults to "tool"."""
raw_output: Any = None
"""The raw output of the tool.
artifact: Any = None
"""Artifact of the Tool execution which is not meant to be sent to the model.
**Not part of the payload sent to the model.** Should only be specified if it is
different from the message content, i.e. if only a subset of the full tool output
is being passed as message content.
Should only be specified if it is different from the message content, e.g. if only
a subset of the full tool output is being passed as message content but the full
output is needed in other parts of the code.
.. versionadded:: 0.2.17
"""
@classmethod
@ -106,7 +111,7 @@ class ToolMessageChunk(ToolMessage, BaseMessageChunk):
return self.__class__(
tool_call_id=self.tool_call_id,
content=merge_content(self.content, other.content),
raw_output=merge_obj(self.raw_output, other.raw_output),
artifact=merge_obj(self.artifact, other.artifact),
additional_kwargs=merge_dicts(
self.additional_kwargs, other.additional_kwargs
),

View File

@ -221,8 +221,8 @@ def _create_message_from_message_type(
elif message_type == "function":
message = FunctionMessage(content=content, **kwargs)
elif message_type == "tool":
raw_output = kwargs.get("additional_kwargs", {}).pop("raw_output", None)
message = ToolMessage(content=content, raw_output=raw_output, **kwargs)
artifact = kwargs.get("additional_kwargs", {}).pop("artifact", None)
message = ToolMessage(content=content, artifact=artifact, **kwargs)
elif message_type == "remove":
message = RemoveMessage(**kwargs)
else:

View File

@ -382,12 +382,12 @@ class ChildTool(BaseTool):
] = False
"""Handle the content of the ValidationError thrown."""
response_format: Literal["content", "content_and_raw_output"] = "content"
response_format: Literal["content", "content_and_artifact"] = "content"
"""The tool response format.
If "content" then the output of the tool is interpreted as the contents of a
ToolMessage. If "content_and_raw_output" then the output is expected to be a
two-tuple corresponding to the (content, raw_output) of a ToolMessage.
ToolMessage. If "content_and_artifact" then the output is expected to be a
two-tuple corresponding to the (content, artifact) of a ToolMessage.
"""
class Config(Serializable.Config):
@ -540,7 +540,7 @@ class ChildTool(BaseTool):
)
content = None
raw_output = None
artifact = None
error_to_raise: Union[Exception, KeyboardInterrupt, None] = None
try:
child_config = patch_config(config, callbacks=run_manager.get_child())
@ -553,15 +553,15 @@ class ChildTool(BaseTool):
if config_param := _get_runnable_config_param(self._run):
tool_kwargs[config_param] = config
response = context.run(self._run, *tool_args, **tool_kwargs)
if self.response_format == "content_and_raw_output":
if self.response_format == "content_and_artifact":
if not isinstance(response, tuple) or len(response) != 2:
raise ValueError(
"Since response_format='content_and_raw_output' "
"Since response_format='content_and_artifact' "
"a two-tuple of the message content and raw tool output is "
f"expected. Instead generated response of type: "
f"{type(response)}."
)
content, raw_output = response
content, artifact = response
else:
content = response
except ValidationError as e:
@ -580,7 +580,7 @@ class ChildTool(BaseTool):
if error_to_raise:
run_manager.on_tool_error(error_to_raise)
raise error_to_raise
output = _format_output(content, raw_output, tool_call_id)
output = _format_output(content, artifact, tool_call_id)
run_manager.on_tool_end(output, color=color, name=self.name, **kwargs)
return output
@ -624,7 +624,7 @@ class ChildTool(BaseTool):
**kwargs,
)
content = None
raw_output = None
artifact = None
error_to_raise: Optional[Union[Exception, KeyboardInterrupt]] = None
try:
tool_args, tool_kwargs = self._to_args_and_kwargs(tool_input)
@ -644,15 +644,15 @@ class ChildTool(BaseTool):
response = await asyncio.create_task(coro, context=context) # type: ignore
else:
response = await coro
if self.response_format == "content_and_raw_output":
if self.response_format == "content_and_artifact":
if not isinstance(response, tuple) or len(response) != 2:
raise ValueError(
"Since response_format='content_and_raw_output' "
"Since response_format='content_and_artifact' "
"a two-tuple of the message content and raw tool output is "
f"expected. Instead generated response of type: "
f"{type(response)}."
)
content, raw_output = response
content, artifact = response
else:
content = response
except ValidationError as e:
@ -672,7 +672,7 @@ class ChildTool(BaseTool):
await run_manager.on_tool_error(error_to_raise)
raise error_to_raise
output = _format_output(content, raw_output, tool_call_id)
output = _format_output(content, artifact, tool_call_id)
await run_manager.on_tool_end(output, color=color, name=self.name, **kwargs)
return output
@ -883,7 +883,7 @@ class StructuredTool(BaseTool):
args_schema: Optional[Type[BaseModel]] = None,
infer_schema: bool = True,
*,
response_format: Literal["content", "content_and_raw_output"] = "content",
response_format: Literal["content", "content_and_artifact"] = "content",
parse_docstring: bool = False,
error_on_invalid_docstring: bool = False,
**kwargs: Any,
@ -902,8 +902,8 @@ class StructuredTool(BaseTool):
infer_schema: Whether to infer the schema from the function's signature
response_format: The tool response format. If "content" then the output of
the tool is interpreted as the contents of a ToolMessage. If
"content_and_raw_output" then the output is expected to be a two-tuple
corresponding to the (content, raw_output) of a ToolMessage.
"content_and_artifact" then the output is expected to be a two-tuple
corresponding to the (content, artifact) of a ToolMessage.
parse_docstring: if ``infer_schema`` and ``parse_docstring``, will attempt
to parse parameter descriptions from Google Style function docstrings.
error_on_invalid_docstring: if ``parse_docstring`` is provided, configures
@ -980,7 +980,7 @@ def tool(
return_direct: bool = False,
args_schema: Optional[Type[BaseModel]] = None,
infer_schema: bool = True,
response_format: Literal["content", "content_and_raw_output"] = "content",
response_format: Literal["content", "content_and_artifact"] = "content",
parse_docstring: bool = False,
error_on_invalid_docstring: bool = True,
) -> Callable:
@ -996,8 +996,8 @@ def tool(
accept a dictionary input to its `run()` function.
response_format: The tool response format. If "content" then the output of
the tool is interpreted as the contents of a ToolMessage. If
"content_and_raw_output" then the output is expected to be a two-tuple
corresponding to the (content, raw_output) of a ToolMessage.
"content_and_artifact" then the output is expected to be a two-tuple
corresponding to the (content, artifact) of a ToolMessage.
parse_docstring: if ``infer_schema`` and ``parse_docstring``, will attempt to
parse parameter descriptions from Google Style function docstrings.
error_on_invalid_docstring: if ``parse_docstring`` is provided, configures
@ -1020,7 +1020,7 @@ def tool(
# Searches the API for the query.
return
@tool(response_format="content_and_raw_output")
@tool(response_format="content_and_artifact")
def search_api(query: str) -> Tuple[str, dict]:
return "partial json of results", {"full": "object of results"}
@ -1385,7 +1385,7 @@ def _prep_run_args(
def _format_output(
content: Any, raw_output: Any, tool_call_id: Optional[str]
content: Any, artifact: Any, tool_call_id: Optional[str]
) -> Union[ToolMessage, Any]:
if tool_call_id:
# NOTE: This will fail to stringify lists which aren't actually content blocks
@ -1397,7 +1397,7 @@ def _format_output(
and isinstance(content[0], (str, dict))
):
content = _stringify(content)
return ToolMessage(content, raw_output=raw_output, tool_call_id=tool_call_id)
return ToolMessage(content, artifact=artifact, tool_call_id=tool_call_id)
else:
return content

View File

@ -457,8 +457,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -472,7 +475,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -485,6 +488,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -514,9 +520,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -1062,8 +1065,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -1077,7 +1083,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -1090,6 +1096,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -1119,9 +1128,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',

View File

@ -813,8 +813,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -828,7 +831,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -841,6 +844,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -870,9 +876,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',

View File

@ -5739,8 +5739,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -5754,7 +5757,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -5767,6 +5770,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -5796,9 +5802,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -6413,8 +6416,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -6428,7 +6434,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -6441,6 +6447,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -6470,9 +6479,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -7002,8 +7008,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -7017,7 +7026,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -7030,6 +7039,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -7059,9 +7071,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -7648,8 +7657,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -7663,7 +7675,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -7676,6 +7688,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -7705,9 +7720,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -8297,8 +8309,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -8312,7 +8327,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -8325,6 +8340,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -8354,9 +8372,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -8893,8 +8908,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -8908,7 +8926,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -8921,6 +8939,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -8950,9 +8971,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -9462,8 +9480,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -9477,7 +9498,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -9490,6 +9511,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -9519,9 +9543,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',
@ -10140,8 +10161,11 @@
ToolMessage(content='42', tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL')
Example: A ToolMessage where only part of the tool output is sent to the model
and the full output is passed in to raw_output.
and the full output is passed in to artifact.
.. versionadded:: 0.2.17
.. code-block:: python
@ -10155,7 +10179,7 @@
ToolMessage(
content=tool_output["stdout"],
raw_output=tool_output,
artifact=tool_output,
tool_call_id='call_Jja7J89XsjrOLA5r!MEOW!SL',
)
@ -10168,6 +10192,9 @@
'title': 'Additional Kwargs',
'type': 'object',
}),
'artifact': dict({
'title': 'Artifact',
}),
'content': dict({
'anyOf': list([
dict({
@ -10197,9 +10224,6 @@
'title': 'Name',
'type': 'string',
}),
'raw_output': dict({
'title': 'Raw Output',
}),
'response_metadata': dict({
'title': 'Response Metadata',
'type': 'object',

View File

@ -662,7 +662,7 @@ def test_convert_to_messages() -> None:
"role": "tool",
"tool_call_id": "tool_id2",
"content": "Bye!",
"raw_output": {"foo": 123},
"artifact": {"foo": 123},
},
{"role": "remove", "id": "message_to_remove", "content": ""},
]
@ -685,7 +685,7 @@ def test_convert_to_messages() -> None:
tool_calls=[ToolCall(name="greet", args={"name": "Jane"}, id="tool_id")],
),
ToolMessage(tool_call_id="tool_id", content="Hi!"),
ToolMessage(tool_call_id="tool_id2", content="Bye!", raw_output={"foo": 123}),
ToolMessage(tool_call_id="tool_id2", content="Bye!", artifact={"foo": 123}),
RemoveMessage(id="message_to_remove"),
]
assert expected == actual
@ -787,7 +787,7 @@ def test_merge_tool_calls() -> None:
def test_tool_message_serdes() -> None:
message = ToolMessage("foo", raw_output={"bar": {"baz": 123}}, tool_call_id="1")
message = ToolMessage("foo", artifact={"bar": {"baz": 123}}, tool_call_id="1")
ser_message = {
"lc": 1,
"type": "constructor",
@ -796,7 +796,7 @@ def test_tool_message_serdes() -> None:
"content": "foo",
"type": "tool",
"tool_call_id": "1",
"raw_output": {"bar": {"baz": 123}},
"artifact": {"bar": {"baz": 123}},
},
}
assert dumpd(message) == ser_message
@ -809,7 +809,7 @@ class BadObject:
def test_tool_message_ser_non_serializable() -> None:
bad_obj = BadObject()
message = ToolMessage("foo", raw_output=bad_obj, tool_call_id="1")
message = ToolMessage("foo", artifact=bad_obj, tool_call_id="1")
ser_message = {
"lc": 1,
"type": "constructor",
@ -818,7 +818,7 @@ def test_tool_message_ser_non_serializable() -> None:
"content": "foo",
"type": "tool",
"tool_call_id": "1",
"raw_output": {
"artifact": {
"lc": 1,
"type": "not_implemented",
"id": ["tests", "unit_tests", "test_messages", "BadObject"],
@ -832,14 +832,14 @@ def test_tool_message_ser_non_serializable() -> None:
def test_tool_message_to_dict() -> None:
message = ToolMessage("foo", raw_output={"bar": {"baz": 123}}, tool_call_id="1")
message = ToolMessage("foo", artifact={"bar": {"baz": 123}}, tool_call_id="1")
expected = {
"type": "tool",
"data": {
"content": "foo",
"additional_kwargs": {},
"response_metadata": {},
"raw_output": {"bar": {"baz": 123}},
"artifact": {"bar": {"baz": 123}},
"type": "tool",
"name": None,
"id": None,
@ -851,16 +851,16 @@ def test_tool_message_to_dict() -> None:
def test_tool_message_repr() -> None:
message = ToolMessage("foo", raw_output={"bar": {"baz": 123}}, tool_call_id="1")
message = ToolMessage("foo", artifact={"bar": {"baz": 123}}, tool_call_id="1")
expected = (
"ToolMessage(content='foo', tool_call_id='1', raw_output={'bar': {'baz': 123}})"
"ToolMessage(content='foo', tool_call_id='1', artifact={'bar': {'baz': 123}})"
)
actual = repr(message)
assert expected == actual
def test_tool_message_str() -> None:
message = ToolMessage("foo", raw_output={"bar": {"baz": 123}}, tool_call_id="1")
expected = "content='foo' tool_call_id='1' raw_output={'bar': {'baz': 123}}"
message = ToolMessage("foo", artifact={"bar": {"baz": 123}}, tool_call_id="1")
expected = "content='foo' tool_call_id='1' artifact={'bar': {'baz': 123}}"
actual = str(message)
assert expected == actual

View File

@ -1150,7 +1150,7 @@ class _MockStructuredToolWithRawOutput(BaseTool):
name: str = "structured_api"
args_schema: Type[BaseModel] = _MockSchema
description: str = "A Structured Tool"
response_format: Literal["content_and_raw_output"] = "content_and_raw_output"
response_format: Literal["content_and_artifact"] = "content_and_artifact"
def _run(
self, arg1: int, arg2: bool, arg3: Optional[dict] = None
@ -1158,8 +1158,8 @@ class _MockStructuredToolWithRawOutput(BaseTool):
return f"{arg1} {arg2}", {"arg1": arg1, "arg2": arg2, "arg3": arg3}
@tool("structured_api", response_format="content_and_raw_output")
def _mock_structured_tool_with_raw_output(
@tool("structured_api", response_format="content_and_artifact")
def _mock_structured_tool_with_artifact(
arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> Tuple[str, dict]:
"""A Structured Tool"""
@ -1167,16 +1167,16 @@ def _mock_structured_tool_with_raw_output(
@pytest.mark.parametrize(
"tool", [_MockStructuredToolWithRawOutput(), _mock_structured_tool_with_raw_output]
"tool", [_MockStructuredToolWithRawOutput(), _mock_structured_tool_with_artifact]
)
def test_tool_call_input_tool_message_with_raw_output(tool: BaseTool) -> None:
def test_tool_call_input_tool_message_with_artifact(tool: BaseTool) -> None:
tool_call: Dict = {
"name": "structured_api",
"args": {"arg1": 1, "arg2": True, "arg3": {"img": "base64string..."}},
"id": "123",
"type": "tool_call",
}
expected = ToolMessage("1 True", raw_output=tool_call["args"], tool_call_id="123")
expected = ToolMessage("1 True", artifact=tool_call["args"], tool_call_id="123")
actual = tool.invoke(tool_call)
assert actual == expected

View File

@ -127,7 +127,7 @@ class SessionsPythonREPLTool(BaseTool):
session_id: str = str(uuid4())
"""The session ID to use for the code interpreter. Defaults to a random UUID."""
response_format: Literal["content_and_raw_output"] = "content_and_raw_output"
response_format: Literal["content_and_artifact"] = "content_and_artifact"
def _build_url(self, path: str) -> str:
pool_management_endpoint = self.pool_management_endpoint