Skip to content

Commit ae3551c

Browse files
core[patch]: Correct type casting of annotations in _infer_arg_descriptions (#31181)
- **Description:** - In _infer_arg_descriptions, the annotations dictionary contains string representations of types instead of actual typing objects. This causes _is_annotated_type to fail, preventing the correct description from being generated. - This is a simple fix using the get_type_hints method, which resolves the annotations properly and is supported across all Python versions. - **Issue:** #31051 --------- Co-authored-by: Eugene Yurtsev <[email protected]>
1 parent dea4343 commit ae3551c

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

libs/core/langchain_core/tools/base.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import functools
66
import inspect
77
import json
8+
import typing
89
import warnings
910
from abc import ABC, abstractmethod
1011
from inspect import signature
@@ -80,7 +81,7 @@ class SchemaAnnotationError(TypeError):
8081

8182

8283
def _is_annotated_type(typ: type[Any]) -> bool:
83-
return get_origin(typ) is Annotated
84+
return get_origin(typ) is typing.Annotated
8485

8586

8687
def _get_annotation_description(arg_type: type) -> str | None:
@@ -143,11 +144,7 @@ def _infer_arg_descriptions(
143144
error_on_invalid_docstring: bool = False,
144145
) -> tuple[str, dict]:
145146
"""Infer argument descriptions from a function's docstring."""
146-
if hasattr(inspect, "get_annotations"):
147-
# This is for python < 3.10
148-
annotations = inspect.get_annotations(fn)
149-
else:
150-
annotations = getattr(fn, "__annotations__", {})
147+
annotations = typing.get_type_hints(fn, include_extras=True)
151148
if parse_docstring:
152149
description, arg_descriptions = _parse_python_function_docstring(
153150
fn, annotations, error_on_invalid_docstring=error_on_invalid_docstring

libs/core/tests/unit_tests/test_tools.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,3 +2711,24 @@ async def async_no_op(foo: int) -> str:
27112711
"id": "call_0_82c17db8-95df-452f-a4c2-03f809022134",
27122712
"type": "tool_call",
27132713
}
2714+
2715+
2716+
def test_tool_args_schema_with_annotated_type() -> None:
2717+
@tool
2718+
def test_tool(
2719+
query_fragments: Annotated[
2720+
list[str],
2721+
"A list of query fragments",
2722+
],
2723+
) -> list[str]:
2724+
"""Search the Internet and retrieve relevant result items."""
2725+
return []
2726+
2727+
assert test_tool.args == {
2728+
"query_fragments": {
2729+
"description": "A list of query fragments",
2730+
"items": {"type": "string"},
2731+
"title": "Query Fragments",
2732+
"type": "array",
2733+
}
2734+
}

0 commit comments

Comments
 (0)