Skip to content

Commit 89368bf

Browse files
committed
working fix, failing lint
1 parent c6b3f5b commit 89368bf

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

libs/core/langchain_core/tools/base.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,25 +189,23 @@ def _infer_arg_descriptions(
189189
*,
190190
parse_docstring: bool = False,
191191
error_on_invalid_docstring: bool = False,
192-
) -> tuple[str, dict]:
193-
"""Infer argument descriptions from function docstring and annotations.
194-
195-
Args:
196-
fn: The function to infer descriptions from.
197-
parse_docstring: Whether to parse the docstring for descriptions.
198-
error_on_invalid_docstring: Whether to raise error on invalid docstring.
199-
200-
Returns:
201-
A tuple containing the function description and argument descriptions.
202-
"""
192+
) -> tuple[str | None, dict]:
193+
"""Infer argument descriptions from function docstring and annotations."""
203194
annotations = typing.get_type_hints(fn, include_extras=True)
204195
if parse_docstring:
205196
description, arg_descriptions = _parse_python_function_docstring(
206197
fn, annotations, error_on_invalid_docstring=error_on_invalid_docstring
207198
)
208199
else:
209-
description = inspect.getdoc(fn) or ""
200+
description = inspect.getdoc(fn)
210201
arg_descriptions = {}
202+
203+
if inspect.isclass(fn) and description:
204+
for parent in fn.__bases__:
205+
if inspect.getdoc(parent) == description:
206+
description = None
207+
break
208+
211209
if parse_docstring:
212210
_validate_docstring_args_against_annotations(arg_descriptions, annotations)
213211
for arg, arg_type in annotations.items():

libs/core/langchain_core/tools/structured.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ def from_function(
129129
coroutine: Callable[..., Awaitable[Any]] | None = None,
130130
name: str | None = None,
131131
description: str | None = None,
132-
return_direct: bool = False, # noqa: FBT001,FBT002
133-
args_schema: ArgsSchema | None = None,
134-
infer_schema: bool = True, # noqa: FBT001,FBT002
135132
*,
133+
return_direct: bool = False,
134+
args_schema: ArgsSchema | None = None,
135+
infer_schema: bool = True,
136136
response_format: Literal["content", "content_and_artifact"] = "content",
137137
parse_docstring: bool = False,
138138
error_on_invalid_docstring: bool = False,
@@ -189,14 +189,14 @@ def add(a: int, b: int) -> int:
189189
raise ValueError(msg)
190190
name = name or source_function.__name__
191191
if args_schema is None and infer_schema:
192-
# schema name is appended within function
193192
args_schema = create_schema_from_function(
194193
name,
195194
source_function,
196195
parse_docstring=parse_docstring,
197196
error_on_invalid_docstring=error_on_invalid_docstring,
198197
filter_args=_filter_schema_args(source_function),
199198
)
199+
200200
description_ = description
201201
if description is None and not parse_docstring:
202202
description_ = source_function.__doc__ or None
@@ -213,20 +213,20 @@ def add(a: int, b: int) -> int:
213213
elif isinstance(args_schema, dict):
214214
description_ = args_schema.get("description")
215215
else:
216-
msg = (
217-
"Invalid args_schema: expected BaseModel or dict, "
218-
f"got {args_schema}"
219-
)
216+
msg = f"""Invalid args_schema: expected BaseModel or
217+
dict, got {args_schema}"""
220218
raise TypeError(msg)
219+
221220
if description_ is None:
222-
msg = "Function must have a docstring if description not provided."
223-
raise ValueError(msg)
221+
if is_basemodel_subclass(source_function):
222+
description_ = ""
223+
else:
224+
msg = "Function must have a docstring if description not provided."
225+
raise ValueError(msg)
226+
224227
if description is None:
225-
# Only apply if using the function's docstring
226228
description_ = textwrap.dedent(description_).strip()
227229

228-
# Description example:
229-
# search_api(query: str) - Searches the API for the query.
230230
description_ = f"{description_.strip()}"
231231
return cls(
232232
name=name,

libs/core/tests/unit_tests/test_tools.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,3 +2757,18 @@ def test_tool(
27572757
"type": "array",
27582758
}
27592759
}
2760+
2761+
2762+
def test_child_tool_does_not_inherit_docstring() -> None:
2763+
"""Test that a tool subclass does not inherit its parent's docstring."""
2764+
2765+
class MyTool(BaseModel):
2766+
"""Parent Tool."""
2767+
2768+
foo: str
2769+
2770+
@tool
2771+
class ChildTool(MyTool):
2772+
bar: str
2773+
2774+
assert ChildTool.description == "" # type: ignore[attr-defined]

0 commit comments

Comments
 (0)