mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-22 23:00:00 +00:00
core[patch]: support passing args_schema
through as_tool
(#24269)
Note: this allows the schema to be passed in positionally. ```python from langchain_core.pydantic_v1 import BaseModel, Field from langchain_core.runnables import RunnableLambda class Add(BaseModel): """Add two integers together.""" a: int = Field(..., description="First integer") b: int = Field(..., description="Second integer") def add(input: dict) -> int: return input["a"] + input["b"] runnable = RunnableLambda(add) as_tool = runnable.as_tool(Add) as_tool.args_schema.schema() ``` ``` {'title': 'Add', 'description': 'Add two integers together.', 'type': 'object', 'properties': {'a': {'title': 'A', 'description': 'First integer', 'type': 'integer'}, 'b': {'title': 'B', 'description': 'Second integer', 'type': 'integer'}}, 'required': ['a', 'b']} ```
This commit is contained in:
parent
ab2d7821a7
commit
888fbc07b5
@ -180,7 +180,7 @@
|
|||||||
"id": "32b1a992-8997-4c98-8eb2-c9fe9431b799",
|
"id": "32b1a992-8997-4c98-8eb2-c9fe9431b799",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"Alternatively, we can add typing information via [Runnable.with_types](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.Runnable.html#langchain_core.runnables.base.Runnable.with_types):"
|
"Alternatively, the schema can be fully specified by directly passing the desired [args_schema](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.BaseTool.html#langchain_core.tools.BaseTool.args_schema) for the tool:"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -190,10 +190,18 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"as_tool = runnable.with_types(input_type=Args).as_tool(\n",
|
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
|
||||||
" name=\"My tool\",\n",
|
"\n",
|
||||||
" description=\"Explanation of when to use tool.\",\n",
|
"\n",
|
||||||
")"
|
"class GSchema(BaseModel):\n",
|
||||||
|
" \"\"\"Apply a function to an integer and list of integers.\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
" a: int = Field(..., description=\"Integer\")\n",
|
||||||
|
" b: List[int] = Field(..., description=\"List of ints\")\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"runnable = RunnableLambda(g)\n",
|
||||||
|
"as_tool = runnable.as_tool(GSchema)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2150,6 +2150,7 @@ class Runnable(Generic[Input, Output], ABC):
|
|||||||
@beta_decorator.beta(message="This API is in beta and may change in the future.")
|
@beta_decorator.beta(message="This API is in beta and may change in the future.")
|
||||||
def as_tool(
|
def as_tool(
|
||||||
self,
|
self,
|
||||||
|
args_schema: Optional[Type[BaseModel]] = None,
|
||||||
*,
|
*,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
description: Optional[str] = None,
|
description: Optional[str] = None,
|
||||||
@ -2161,9 +2162,11 @@ class Runnable(Generic[Input, Output], ABC):
|
|||||||
``args_schema`` from a Runnable. Where possible, schemas are inferred
|
``args_schema`` from a Runnable. Where possible, schemas are inferred
|
||||||
from ``runnable.get_input_schema``. Alternatively (e.g., if the
|
from ``runnable.get_input_schema``. Alternatively (e.g., if the
|
||||||
Runnable takes a dict as input and the specific dict keys are not typed),
|
Runnable takes a dict as input and the specific dict keys are not typed),
|
||||||
pass ``arg_types`` to specify the required arguments.
|
the schema can be specified directly with ``args_schema``. You can also
|
||||||
|
pass ``arg_types`` to just specify the required arguments and their types.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
args_schema: The schema for the tool. Defaults to None.
|
||||||
name: The name of the tool. Defaults to None.
|
name: The name of the tool. Defaults to None.
|
||||||
description: The description of the tool. Defaults to None.
|
description: The description of the tool. Defaults to None.
|
||||||
arg_types: A dictionary of argument names to types. Defaults to None.
|
arg_types: A dictionary of argument names to types. Defaults to None.
|
||||||
@ -2190,7 +2193,28 @@ class Runnable(Generic[Input, Output], ABC):
|
|||||||
as_tool = runnable.as_tool()
|
as_tool = runnable.as_tool()
|
||||||
as_tool.invoke({"a": 3, "b": [1, 2]})
|
as_tool.invoke({"a": 3, "b": [1, 2]})
|
||||||
|
|
||||||
``dict`` input, specifying schema:
|
``dict`` input, specifying schema via ``args_schema``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||||
|
from langchain_core.runnables import RunnableLambda
|
||||||
|
|
||||||
|
def f(x: Dict[str, Any]) -> str:
|
||||||
|
return str(x["a"] * max(x["b"]))
|
||||||
|
|
||||||
|
class FSchema(BaseModel):
|
||||||
|
\"\"\"Apply a function to an integer and list of integers.\"\"\"
|
||||||
|
|
||||||
|
a: int = Field(..., description="Integer")
|
||||||
|
b: List[int] = Field(..., description="List of ints")
|
||||||
|
|
||||||
|
runnable = RunnableLambda(f)
|
||||||
|
as_tool = runnable.as_tool(FSchema)
|
||||||
|
as_tool.invoke({"a": 3, "b": [1, 2]})
|
||||||
|
|
||||||
|
``dict`` input, specifying schema via ``arg_types``:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -2226,7 +2250,11 @@ class Runnable(Generic[Input, Output], ABC):
|
|||||||
from langchain_core.tools import convert_runnable_to_tool
|
from langchain_core.tools import convert_runnable_to_tool
|
||||||
|
|
||||||
return convert_runnable_to_tool(
|
return convert_runnable_to_tool(
|
||||||
self, name=name, description=description, arg_types=arg_types
|
self,
|
||||||
|
args_schema=args_schema,
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
arg_types=arg_types,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1438,11 +1438,15 @@ def _get_schema_from_runnable_and_arg_types(
|
|||||||
|
|
||||||
def convert_runnable_to_tool(
|
def convert_runnable_to_tool(
|
||||||
runnable: Runnable,
|
runnable: Runnable,
|
||||||
|
args_schema: Optional[Type[BaseModel]] = None,
|
||||||
|
*,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
description: Optional[str] = None,
|
description: Optional[str] = None,
|
||||||
arg_types: Optional[Dict[str, Type]] = None,
|
arg_types: Optional[Dict[str, Type]] = None,
|
||||||
) -> BaseTool:
|
) -> BaseTool:
|
||||||
"""Convert a Runnable into a BaseTool."""
|
"""Convert a Runnable into a BaseTool."""
|
||||||
|
if args_schema:
|
||||||
|
runnable = runnable.with_types(input_type=args_schema)
|
||||||
description = description or _get_description_from_runnable(runnable)
|
description = description or _get_description_from_runnable(runnable)
|
||||||
name = name or runnable.get_name()
|
name = name or runnable.get_name()
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from langchain_core.callbacks import (
|
|||||||
CallbackManagerForToolRun,
|
CallbackManagerForToolRun,
|
||||||
)
|
)
|
||||||
from langchain_core.messages import ToolMessage
|
from langchain_core.messages import ToolMessage
|
||||||
from langchain_core.pydantic_v1 import BaseModel, ValidationError
|
from langchain_core.pydantic_v1 import BaseModel, Field, ValidationError
|
||||||
from langchain_core.runnables import (
|
from langchain_core.runnables import (
|
||||||
Runnable,
|
Runnable,
|
||||||
RunnableConfig,
|
RunnableConfig,
|
||||||
@ -1222,10 +1222,22 @@ def test_convert_from_runnable_dict() -> None:
|
|||||||
assert as_tool.name == "my tool"
|
assert as_tool.name == "my tool"
|
||||||
assert as_tool.description == "test description"
|
assert as_tool.description == "test description"
|
||||||
|
|
||||||
# Dict without typed input-- must supply arg types
|
# Dict without typed input-- must supply schema
|
||||||
def g(x: Dict[str, Any]) -> str:
|
def g(x: Dict[str, Any]) -> str:
|
||||||
return str(x["a"] * max(x["b"]))
|
return str(x["a"] * max(x["b"]))
|
||||||
|
|
||||||
|
# Specify via args_schema:
|
||||||
|
class GSchema(BaseModel):
|
||||||
|
"""Apply a function to an integer and list of integers."""
|
||||||
|
|
||||||
|
a: int = Field(..., description="Integer")
|
||||||
|
b: List[int] = Field(..., description="List of ints")
|
||||||
|
|
||||||
|
runnable = RunnableLambda(g)
|
||||||
|
as_tool = runnable.as_tool(GSchema)
|
||||||
|
as_tool.invoke({"a": 3, "b": [1, 2]})
|
||||||
|
|
||||||
|
# Specify via arg_types:
|
||||||
runnable = RunnableLambda(g)
|
runnable = RunnableLambda(g)
|
||||||
as_tool = runnable.as_tool(arg_types={"a": int, "b": List[int]})
|
as_tool = runnable.as_tool(arg_types={"a": int, "b": List[int]})
|
||||||
result = as_tool.invoke({"a": 3, "b": [1, 2]})
|
result = as_tool.invoke({"a": 3, "b": [1, 2]})
|
||||||
|
Loading…
Reference in New Issue
Block a user