langchain-core 0.3.75__py3-none-any.whl → 0.3.77__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of langchain-core might be problematic. Click here for more details.

Files changed (119) hide show
  1. langchain_core/_api/beta_decorator.py +22 -44
  2. langchain_core/_api/deprecation.py +30 -17
  3. langchain_core/_api/path.py +19 -2
  4. langchain_core/_import_utils.py +7 -0
  5. langchain_core/agents.py +10 -6
  6. langchain_core/beta/runnables/context.py +1 -2
  7. langchain_core/callbacks/base.py +28 -15
  8. langchain_core/callbacks/manager.py +83 -71
  9. langchain_core/callbacks/usage.py +6 -4
  10. langchain_core/chat_history.py +29 -21
  11. langchain_core/document_loaders/base.py +34 -9
  12. langchain_core/document_loaders/langsmith.py +4 -1
  13. langchain_core/documents/base.py +35 -10
  14. langchain_core/documents/transformers.py +4 -2
  15. langchain_core/embeddings/fake.py +8 -5
  16. langchain_core/env.py +2 -3
  17. langchain_core/example_selectors/base.py +12 -0
  18. langchain_core/exceptions.py +7 -0
  19. langchain_core/globals.py +17 -28
  20. langchain_core/indexing/api.py +88 -76
  21. langchain_core/indexing/base.py +5 -8
  22. langchain_core/indexing/in_memory.py +23 -3
  23. langchain_core/language_models/__init__.py +3 -2
  24. langchain_core/language_models/base.py +31 -20
  25. langchain_core/language_models/chat_models.py +98 -27
  26. langchain_core/language_models/fake_chat_models.py +10 -9
  27. langchain_core/language_models/llms.py +52 -18
  28. langchain_core/load/dump.py +2 -3
  29. langchain_core/load/load.py +15 -1
  30. langchain_core/load/serializable.py +39 -44
  31. langchain_core/memory.py +7 -3
  32. langchain_core/messages/ai.py +53 -24
  33. langchain_core/messages/base.py +43 -22
  34. langchain_core/messages/chat.py +4 -1
  35. langchain_core/messages/content_blocks.py +23 -2
  36. langchain_core/messages/function.py +9 -5
  37. langchain_core/messages/human.py +13 -10
  38. langchain_core/messages/modifier.py +1 -0
  39. langchain_core/messages/system.py +11 -8
  40. langchain_core/messages/tool.py +60 -29
  41. langchain_core/messages/utils.py +250 -131
  42. langchain_core/output_parsers/base.py +5 -2
  43. langchain_core/output_parsers/json.py +4 -4
  44. langchain_core/output_parsers/list.py +7 -22
  45. langchain_core/output_parsers/openai_functions.py +3 -0
  46. langchain_core/output_parsers/openai_tools.py +6 -1
  47. langchain_core/output_parsers/pydantic.py +4 -0
  48. langchain_core/output_parsers/string.py +5 -1
  49. langchain_core/output_parsers/xml.py +19 -19
  50. langchain_core/outputs/chat_generation.py +25 -10
  51. langchain_core/outputs/generation.py +14 -3
  52. langchain_core/outputs/llm_result.py +8 -1
  53. langchain_core/prompt_values.py +16 -6
  54. langchain_core/prompts/base.py +4 -9
  55. langchain_core/prompts/chat.py +89 -57
  56. langchain_core/prompts/dict.py +16 -8
  57. langchain_core/prompts/few_shot.py +12 -11
  58. langchain_core/prompts/few_shot_with_templates.py +5 -1
  59. langchain_core/prompts/image.py +12 -5
  60. langchain_core/prompts/message.py +5 -6
  61. langchain_core/prompts/pipeline.py +13 -8
  62. langchain_core/prompts/prompt.py +22 -8
  63. langchain_core/prompts/string.py +18 -10
  64. langchain_core/prompts/structured.py +7 -2
  65. langchain_core/rate_limiters.py +2 -2
  66. langchain_core/retrievers.py +7 -6
  67. langchain_core/runnables/base.py +406 -186
  68. langchain_core/runnables/branch.py +14 -19
  69. langchain_core/runnables/config.py +9 -15
  70. langchain_core/runnables/configurable.py +34 -19
  71. langchain_core/runnables/fallbacks.py +20 -13
  72. langchain_core/runnables/graph.py +48 -38
  73. langchain_core/runnables/graph_ascii.py +41 -18
  74. langchain_core/runnables/graph_mermaid.py +54 -25
  75. langchain_core/runnables/graph_png.py +27 -31
  76. langchain_core/runnables/history.py +55 -58
  77. langchain_core/runnables/passthrough.py +44 -21
  78. langchain_core/runnables/retry.py +44 -23
  79. langchain_core/runnables/router.py +9 -8
  80. langchain_core/runnables/schema.py +2 -0
  81. langchain_core/runnables/utils.py +51 -89
  82. langchain_core/stores.py +19 -31
  83. langchain_core/sys_info.py +9 -8
  84. langchain_core/tools/base.py +37 -28
  85. langchain_core/tools/convert.py +26 -15
  86. langchain_core/tools/simple.py +36 -8
  87. langchain_core/tools/structured.py +25 -12
  88. langchain_core/tracers/base.py +2 -2
  89. langchain_core/tracers/context.py +5 -1
  90. langchain_core/tracers/core.py +109 -39
  91. langchain_core/tracers/evaluation.py +22 -26
  92. langchain_core/tracers/event_stream.py +45 -34
  93. langchain_core/tracers/langchain.py +12 -3
  94. langchain_core/tracers/langchain_v1.py +10 -2
  95. langchain_core/tracers/log_stream.py +56 -17
  96. langchain_core/tracers/root_listeners.py +4 -20
  97. langchain_core/tracers/run_collector.py +6 -16
  98. langchain_core/tracers/schemas.py +5 -1
  99. langchain_core/utils/aiter.py +15 -7
  100. langchain_core/utils/env.py +3 -0
  101. langchain_core/utils/function_calling.py +50 -28
  102. langchain_core/utils/interactive_env.py +6 -2
  103. langchain_core/utils/iter.py +12 -4
  104. langchain_core/utils/json.py +12 -3
  105. langchain_core/utils/json_schema.py +156 -40
  106. langchain_core/utils/loading.py +5 -1
  107. langchain_core/utils/mustache.py +24 -15
  108. langchain_core/utils/pydantic.py +38 -9
  109. langchain_core/utils/utils.py +25 -9
  110. langchain_core/vectorstores/base.py +7 -20
  111. langchain_core/vectorstores/in_memory.py +23 -17
  112. langchain_core/vectorstores/utils.py +18 -12
  113. langchain_core/version.py +1 -1
  114. langchain_core-0.3.77.dist-info/METADATA +67 -0
  115. langchain_core-0.3.77.dist-info/RECORD +174 -0
  116. langchain_core-0.3.75.dist-info/METADATA +0 -106
  117. langchain_core-0.3.75.dist-info/RECORD +0 -174
  118. {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/WHEEL +0 -0
  119. {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/entry_points.txt +0 -0
langchain_core/stores.py CHANGED
@@ -16,6 +16,8 @@ from typing import (
16
16
  Union,
17
17
  )
18
18
 
19
+ from typing_extensions import override
20
+
19
21
  from langchain_core.exceptions import LangChainException
20
22
  from langchain_core.runnables import run_in_executor
21
23
 
@@ -52,24 +54,24 @@ class BaseStore(ABC, Generic[K, V]):
52
54
 
53
55
  from langchain.storage import BaseStore
54
56
 
55
- class MyInMemoryStore(BaseStore[str, int]):
56
57
 
57
- def __init__(self):
58
- self.store = {}
58
+ class MyInMemoryStore(BaseStore[str, int]):
59
+ def __init__(self) -> None:
60
+ self.store: dict[str, int] = {}
59
61
 
60
- def mget(self, keys):
62
+ def mget(self, keys: Sequence[str]) -> list[int | None]:
61
63
  return [self.store.get(key) for key in keys]
62
64
 
63
- def mset(self, key_value_pairs):
65
+ def mset(self, key_value_pairs: Sequence[tuple[str, int]]) -> None:
64
66
  for key, value in key_value_pairs:
65
67
  self.store[key] = value
66
68
 
67
- def mdelete(self, keys):
69
+ def mdelete(self, keys: Sequence[str]) -> None:
68
70
  for key in keys:
69
71
  if key in self.store:
70
72
  del self.store[key]
71
73
 
72
- def yield_keys(self, prefix=None):
74
+ def yield_keys(self, prefix: str | None = None) -> Iterator[str]:
73
75
  if prefix is None:
74
76
  yield from self.store.keys()
75
77
  else:
@@ -206,27 +208,13 @@ class InMemoryBaseStore(BaseStore[str, V], Generic[V]):
206
208
  """
207
209
  return self.mget(keys)
208
210
 
211
+ @override
209
212
  def mset(self, key_value_pairs: Sequence[tuple[str, V]]) -> None:
210
- """Set the values for the given keys.
211
-
212
- Args:
213
- key_value_pairs (Sequence[tuple[str, V]]): A sequence of key-value pairs.
214
-
215
- Returns:
216
- None
217
- """
218
213
  for key, value in key_value_pairs:
219
214
  self.store[key] = value
220
215
 
216
+ @override
221
217
  async def amset(self, key_value_pairs: Sequence[tuple[str, V]]) -> None:
222
- """Async set the values for the given keys.
223
-
224
- Args:
225
- key_value_pairs (Sequence[tuple[str, V]]): A sequence of key-value pairs.
226
-
227
- Returns:
228
- None
229
- """
230
218
  return self.mset(key_value_pairs)
231
219
 
232
220
  def mdelete(self, keys: Sequence[str]) -> None:
@@ -295,13 +283,13 @@ class InMemoryStore(InMemoryBaseStore[Any]):
295
283
  from langchain.storage import InMemoryStore
296
284
 
297
285
  store = InMemoryStore()
298
- store.mset([('key1', 'value1'), ('key2', 'value2')])
299
- store.mget(['key1', 'key2'])
286
+ store.mset([("key1", "value1"), ("key2", "value2")])
287
+ store.mget(["key1", "key2"])
300
288
  # ['value1', 'value2']
301
- store.mdelete(['key1'])
289
+ store.mdelete(["key1"])
302
290
  list(store.yield_keys())
303
291
  # ['key2']
304
- list(store.yield_keys(prefix='k'))
292
+ list(store.yield_keys(prefix="k"))
305
293
  # ['key2']
306
294
 
307
295
  """
@@ -321,13 +309,13 @@ class InMemoryByteStore(InMemoryBaseStore[bytes]):
321
309
  from langchain.storage import InMemoryByteStore
322
310
 
323
311
  store = InMemoryByteStore()
324
- store.mset([('key1', b'value1'), ('key2', b'value2')])
325
- store.mget(['key1', 'key2'])
312
+ store.mset([("key1", b"value1"), ("key2", b"value2")])
313
+ store.mget(["key1", "key2"])
326
314
  # [b'value1', b'value2']
327
- store.mdelete(['key1'])
315
+ store.mdelete(["key1"])
328
316
  list(store.yield_keys())
329
317
  # ['key2']
330
- list(store.yield_keys(prefix='k'))
318
+ list(store.yield_keys(prefix="k"))
331
319
  # ['key2']
332
320
 
333
321
  """
@@ -1,12 +1,18 @@
1
- """**sys_info** prints information about the system and langchain packages for debugging purposes.""" # noqa: E501
1
+ """**sys_info** implementation.
2
2
 
3
+ sys_info prints information about the system and langchain packages for
4
+ debugging purposes.
5
+ """
6
+
7
+ import pkgutil
8
+ import platform
9
+ import sys
3
10
  from collections.abc import Sequence
11
+ from importlib import metadata, util
4
12
 
5
13
 
6
14
  def _get_sub_deps(packages: Sequence[str]) -> list[str]:
7
15
  """Get any specified sub-dependencies."""
8
- from importlib import metadata
9
-
10
16
  sub_deps = set()
11
17
  underscored_packages = {pkg.replace("-", "_") for pkg in packages}
12
18
 
@@ -33,11 +39,6 @@ def print_sys_info(*, additional_pkgs: Sequence[str] = ()) -> None:
33
39
  Args:
34
40
  additional_pkgs: Additional packages to include in the output.
35
41
  """
36
- import pkgutil
37
- import platform
38
- import sys
39
- from importlib import metadata, util
40
-
41
42
  # Packages that do not start with "langchain" prefix.
42
43
  other_langchain_packages = [
43
44
  "langserve",
@@ -81,6 +81,8 @@ TOOL_MESSAGE_BLOCK_TYPES = (
81
81
  "json",
82
82
  "search_result",
83
83
  "custom_tool_call_output",
84
+ "document",
85
+ "file",
84
86
  )
85
87
 
86
88
 
@@ -271,15 +273,12 @@ def _function_annotations_are_pydantic_v1(
271
273
 
272
274
 
273
275
  class _SchemaConfig:
274
- """Configuration for Pydantic models generated from function signatures.
275
-
276
- Attributes:
277
- extra: Whether to allow extra fields in the model.
278
- arbitrary_types_allowed: Whether to allow arbitrary types in the model.
279
- """
276
+ """Configuration for Pydantic models generated from function signatures."""
280
277
 
281
278
  extra: str = "forbid"
279
+ """Whether to allow extra fields in the model."""
282
280
  arbitrary_types_allowed: bool = True
281
+ """Whether to allow arbitrary types in the model."""
283
282
 
284
283
 
285
284
  def create_schema_from_function(
@@ -506,7 +505,12 @@ class ChildTool(BaseTool):
506
505
  """
507
506
 
508
507
  def __init__(self, **kwargs: Any) -> None:
509
- """Initialize the tool."""
508
+ """Initialize the tool.
509
+
510
+ Raises:
511
+ TypeError: If ``args_schema`` is not a subclass of pydantic ``BaseModel`` or
512
+ dict.
513
+ """
510
514
  if (
511
515
  "args_schema" in kwargs
512
516
  and kwargs["args_schema"] is not None
@@ -543,6 +547,8 @@ class ChildTool(BaseTool):
543
547
  """
544
548
  if isinstance(self.args_schema, dict):
545
549
  json_schema = self.args_schema
550
+ elif self.args_schema and issubclass(self.args_schema, BaseModelV1):
551
+ json_schema = self.args_schema.schema()
546
552
  else:
547
553
  input_schema = self.get_input_schema()
548
554
  json_schema = input_schema.model_json_schema()
@@ -628,9 +634,10 @@ class ChildTool(BaseTool):
628
634
  The parsed and validated input.
629
635
 
630
636
  Raises:
631
- ValueError: If string input is provided with JSON schema or if
632
- InjectedToolCallId is required but not provided.
633
- NotImplementedError: If args_schema is not a supported type.
637
+ ValueError: If string input is provided with JSON schema ``args_schema``.
638
+ ValueError: If InjectedToolCallId is required but ``tool_call_id`` is not
639
+ provided.
640
+ TypeError: If args_schema is not a Pydantic ``BaseModel`` or dict.
634
641
  """
635
642
  input_args = self.args_schema
636
643
  if isinstance(tool_input, str):
@@ -655,10 +662,7 @@ class ChildTool(BaseTool):
655
662
  return tool_input
656
663
  if issubclass(input_args, BaseModel):
657
664
  for k, v in get_all_basemodel_annotations(input_args).items():
658
- if (
659
- _is_injected_arg_type(v, injected_type=InjectedToolCallId)
660
- and k not in tool_input
661
- ):
665
+ if _is_injected_arg_type(v, injected_type=InjectedToolCallId):
662
666
  if tool_call_id is None:
663
667
  msg = (
664
668
  "When tool includes an InjectedToolCallId "
@@ -673,10 +677,7 @@ class ChildTool(BaseTool):
673
677
  result_dict = result.model_dump()
674
678
  elif issubclass(input_args, BaseModelV1):
675
679
  for k, v in get_all_basemodel_annotations(input_args).items():
676
- if (
677
- _is_injected_arg_type(v, injected_type=InjectedToolCallId)
678
- and k not in tool_input
679
- ):
680
+ if _is_injected_arg_type(v, injected_type=InjectedToolCallId):
680
681
  if tool_call_id is None:
681
682
  msg = (
682
683
  "When tool includes an InjectedToolCallId "
@@ -725,6 +726,9 @@ class ChildTool(BaseTool):
725
726
 
726
727
  Add run_manager: Optional[CallbackManagerForToolRun] = None
727
728
  to child implementations to enable tracing.
729
+
730
+ Returns:
731
+ The result of the tool execution.
728
732
  """
729
733
 
730
734
  async def _arun(self, *args: Any, **kwargs: Any) -> Any:
@@ -732,6 +736,9 @@ class ChildTool(BaseTool):
732
736
 
733
737
  Add run_manager: Optional[AsyncCallbackManagerForToolRun] = None
734
738
  to child implementations to enable tracing.
739
+
740
+ Returns:
741
+ The result of the tool execution.
735
742
  """
736
743
  if kwargs.get("run_manager") and signature(self._run).parameters.get(
737
744
  "run_manager"
@@ -1285,7 +1292,7 @@ class InjectedToolCallId(InjectedToolArg):
1285
1292
 
1286
1293
 
1287
1294
  def _is_injected_arg_type(
1288
- type_: type, injected_type: Optional[type[InjectedToolArg]] = None
1295
+ type_: Union[type, TypeVar], injected_type: Optional[type[InjectedToolArg]] = None
1289
1296
  ) -> bool:
1290
1297
  """Check if a type annotation indicates an injected argument.
1291
1298
 
@@ -1306,20 +1313,22 @@ def _is_injected_arg_type(
1306
1313
 
1307
1314
  def get_all_basemodel_annotations(
1308
1315
  cls: Union[TypeBaseModel, Any], *, default_to_bound: bool = True
1309
- ) -> dict[str, type]:
1316
+ ) -> dict[str, Union[type, TypeVar]]:
1310
1317
  """Get all annotations from a Pydantic BaseModel and its parents.
1311
1318
 
1312
1319
  Args:
1313
1320
  cls: The Pydantic BaseModel class.
1314
1321
  default_to_bound: Whether to default to the bound of a TypeVar if it exists.
1322
+
1323
+ Returns:
1324
+ A dictionary of field names to their type annotations.
1315
1325
  """
1316
1326
  # cls has no subscript: cls = FooBar
1317
1327
  if isinstance(cls, type):
1318
- # Gather pydantic field objects (v2: model_fields / v1: __fields__)
1319
- fields = getattr(cls, "model_fields", {}) or getattr(cls, "__fields__", {})
1328
+ fields = get_fields(cls)
1320
1329
  alias_map = {field.alias: name for name, field in fields.items() if field.alias}
1321
1330
 
1322
- annotations: dict[str, type] = {}
1331
+ annotations: dict[str, Union[type, TypeVar]] = {}
1323
1332
  for name, param in inspect.signature(cls).parameters.items():
1324
1333
  # Exclude hidden init args added by pydantic Config. For example if
1325
1334
  # BaseModel(extra="allow") then "extra_data" will part of init sig.
@@ -1355,8 +1364,8 @@ def get_all_basemodel_annotations(
1355
1364
  continue
1356
1365
 
1357
1366
  # if class = FooBar inherits from Baz[str]:
1358
- # parent = Baz[str],
1359
- # parent_origin = Baz,
1367
+ # parent = class Baz[str],
1368
+ # parent_origin = class Baz,
1360
1369
  # generic_type_vars = (type vars in Baz)
1361
1370
  # generic_map = {type var in Baz: str}
1362
1371
  generic_type_vars: tuple = getattr(parent_origin, "__parameters__", ())
@@ -1373,11 +1382,11 @@ def get_all_basemodel_annotations(
1373
1382
 
1374
1383
 
1375
1384
  def _replace_type_vars(
1376
- type_: type,
1385
+ type_: Union[type, TypeVar],
1377
1386
  generic_map: Optional[dict[TypeVar, type]] = None,
1378
1387
  *,
1379
1388
  default_to_bound: bool = True,
1380
- ) -> type:
1389
+ ) -> Union[type, TypeVar]:
1381
1390
  """Replace TypeVars in a type annotation with concrete types.
1382
1391
 
1383
1392
  Args:
@@ -1393,7 +1402,7 @@ def _replace_type_vars(
1393
1402
  if type_ in generic_map:
1394
1403
  return generic_map[type_]
1395
1404
  if default_to_bound:
1396
- return type_.__bound__ or Any
1405
+ return type_.__bound__ if type_.__bound__ is not None else Any
1397
1406
  return type_
1398
1407
  if (origin := get_origin(type_)) and (args := get_args(type_)):
1399
1408
  new_args = tuple(
@@ -92,12 +92,13 @@ def tool(
92
92
  positional argument.
93
93
  description: Optional description for the tool.
94
94
  Precedence for the tool description value is as follows:
95
- - `description` argument
96
- (used even if docstring and/or `args_schema` are provided)
97
- - tool function docstring
98
- (used even if `args_schema` is provided)
99
- - `args_schema` description
100
- (used only if `description` / docstring are not provided)
95
+
96
+ - ``description`` argument
97
+ (used even if docstring and/or ``args_schema`` are provided)
98
+ - tool function docstring
99
+ (used even if ``args_schema`` is provided)
100
+ - ``args_schema`` description
101
+ (used only if `description` / docstring are not provided)
101
102
  *args: Extra positional arguments. Must be empty.
102
103
  return_direct: Whether to return directly from the tool rather
103
104
  than continuing the agent loop. Defaults to False.
@@ -119,6 +120,17 @@ def tool(
119
120
  whether to raise ValueError on invalid Google Style docstrings.
120
121
  Defaults to True.
121
122
 
123
+ Raises:
124
+ ValueError: If too many positional arguments are provided.
125
+ ValueError: If a runnable is provided without a string name.
126
+ ValueError: If the first argument is not a string or callable with
127
+ a ``__name__`` attribute.
128
+ ValueError: If the function does not have a docstring and description
129
+ is not provided and ``infer_schema`` is False.
130
+ ValueError: If ``parse_docstring`` is True and the function has an invalid
131
+ Google-style docstring and ``error_on_invalid_docstring`` is True.
132
+ ValueError: If a Runnable is provided that does not have an object schema.
133
+
122
134
  Returns:
123
135
  The tool.
124
136
 
@@ -134,11 +146,13 @@ def tool(
134
146
  # Searches the API for the query.
135
147
  return
136
148
 
149
+
137
150
  @tool("search", return_direct=True)
138
151
  def search_api(query: str) -> str:
139
152
  # Searches the API for the query.
140
153
  return
141
154
 
155
+
142
156
  @tool(response_format="content_and_artifact")
143
157
  def search_api(query: str) -> tuple[str, dict]:
144
158
  return "partial json of results", {"full": "object of results"}
@@ -171,18 +185,15 @@ def tool(
171
185
  "bar": {
172
186
  "title": "Bar",
173
187
  "description": "The bar.",
174
- "type": "string"
188
+ "type": "string",
175
189
  },
176
190
  "baz": {
177
191
  "title": "Baz",
178
192
  "description": "The baz.",
179
- "type": "integer"
180
- }
193
+ "type": "integer",
194
+ },
181
195
  },
182
- "required": [
183
- "bar",
184
- "baz"
185
- ]
196
+ "required": ["bar", "baz"],
186
197
  }
187
198
 
188
199
  Note that parsing by default will raise ``ValueError`` if the docstring
@@ -216,7 +227,7 @@ def tool(
216
227
  \"\"\"
217
228
  return bar
218
229
 
219
- """ # noqa: D214, D410, D411
230
+ """ # noqa: D214, D410, D411 # We're intentionally showing bad formatting in examples
220
231
 
221
232
  def _create_tool_factory(
222
233
  tool_name: str,
@@ -304,7 +315,7 @@ def tool(
304
315
 
305
316
  if runnable is not None:
306
317
  # tool is used as a function
307
- # tool_from_runnable = tool("name", runnable)
318
+ # for instance tool_from_runnable = tool("name", runnable)
308
319
  if not name_or_callable:
309
320
  msg = "Runnable without name for tool constructor"
310
321
  raise ValueError(msg)
@@ -64,11 +64,7 @@ class Tool(BaseTool):
64
64
  The input arguments for the tool.
65
65
  """
66
66
  if self.args_schema is not None:
67
- if isinstance(self.args_schema, dict):
68
- json_schema = self.args_schema
69
- else:
70
- json_schema = self.args_schema.model_json_schema()
71
- return json_schema["properties"]
67
+ return super().args
72
68
  # For backwards compatibility, if the function signature is ambiguous,
73
69
  # assume it takes a single string input.
74
70
  return {"tool_input": {"type": "string"}}
@@ -76,7 +72,19 @@ class Tool(BaseTool):
76
72
  def _to_args_and_kwargs(
77
73
  self, tool_input: Union[str, dict], tool_call_id: Optional[str]
78
74
  ) -> tuple[tuple, dict]:
79
- """Convert tool input to pydantic model."""
75
+ """Convert tool input to pydantic model.
76
+
77
+ Args:
78
+ tool_input: The input to the tool.
79
+ tool_call_id: The ID of the tool call.
80
+
81
+ Raises:
82
+ ToolException: If the tool input is invalid.
83
+
84
+ Returns:
85
+ the pydantic model args and kwargs.
86
+
87
+ """
80
88
  args, kwargs = super()._to_args_and_kwargs(tool_input, tool_call_id)
81
89
  # For backwards compatibility. The tool must be run with a single input
82
90
  all_args = list(args) + list(kwargs.values())
@@ -96,7 +104,17 @@ class Tool(BaseTool):
96
104
  run_manager: Optional[CallbackManagerForToolRun] = None,
97
105
  **kwargs: Any,
98
106
  ) -> Any:
99
- """Use the tool."""
107
+ """Use the tool.
108
+
109
+ Args:
110
+ *args: Positional arguments to pass to the tool
111
+ config: Configuration for the run
112
+ run_manager: Optional callback manager to use for the run
113
+ **kwargs: Keyword arguments to pass to the tool
114
+
115
+ Returns:
116
+ The result of the tool execution
117
+ """
100
118
  if self.func:
101
119
  if run_manager and signature(self.func).parameters.get("callbacks"):
102
120
  kwargs["callbacks"] = run_manager.get_child()
@@ -113,7 +131,17 @@ class Tool(BaseTool):
113
131
  run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
114
132
  **kwargs: Any,
115
133
  ) -> Any:
116
- """Use the tool asynchronously."""
134
+ """Use the tool asynchronously.
135
+
136
+ Args:
137
+ *args: Positional arguments to pass to the tool
138
+ config: Configuration for the run
139
+ run_manager: Optional callback manager to use for the run
140
+ **kwargs: Keyword arguments to pass to the tool
141
+
142
+ Returns:
143
+ The result of the tool execution
144
+ """
117
145
  if self.coroutine:
118
146
  if run_manager and signature(self.coroutine).parameters.get("callbacks"):
119
147
  kwargs["callbacks"] = run_manager.get_child()
@@ -67,16 +67,6 @@ class StructuredTool(BaseTool):
67
67
 
68
68
  # --- Tool ---
69
69
 
70
- @property
71
- def args(self) -> dict:
72
- """The tool's input arguments."""
73
- if isinstance(self.args_schema, dict):
74
- json_schema = self.args_schema
75
- else:
76
- input_schema = self.get_input_schema()
77
- json_schema = input_schema.model_json_schema()
78
- return json_schema["properties"]
79
-
80
70
  def _run(
81
71
  self,
82
72
  *args: Any,
@@ -84,7 +74,17 @@ class StructuredTool(BaseTool):
84
74
  run_manager: Optional[CallbackManagerForToolRun] = None,
85
75
  **kwargs: Any,
86
76
  ) -> Any:
87
- """Use the tool."""
77
+ """Use the tool.
78
+
79
+ Args:
80
+ *args: Positional arguments to pass to the tool
81
+ config: Configuration for the run
82
+ run_manager: Optional callback manager to use for the run
83
+ **kwargs: Keyword arguments to pass to the tool
84
+
85
+ Returns:
86
+ The result of the tool execution
87
+ """
88
88
  if self.func:
89
89
  if run_manager and signature(self.func).parameters.get("callbacks"):
90
90
  kwargs["callbacks"] = run_manager.get_child()
@@ -101,7 +101,17 @@ class StructuredTool(BaseTool):
101
101
  run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
102
102
  **kwargs: Any,
103
103
  ) -> Any:
104
- """Use the tool asynchronously."""
104
+ """Use the tool asynchronously.
105
+
106
+ Args:
107
+ *args: Positional arguments to pass to the tool
108
+ config: Configuration for the run
109
+ run_manager: Optional callback manager to use for the run
110
+ **kwargs: Keyword arguments to pass to the tool
111
+
112
+ Returns:
113
+ The result of the tool execution
114
+ """
105
115
  if self.coroutine:
106
116
  if run_manager and signature(self.coroutine).parameters.get("callbacks"):
107
117
  kwargs["callbacks"] = run_manager.get_child()
@@ -164,6 +174,9 @@ class StructuredTool(BaseTool):
164
174
 
165
175
  Raises:
166
176
  ValueError: If the function is not provided.
177
+ ValueError: If the function does not have a docstring and description
178
+ is not provided.
179
+ TypeError: If the ``args_schema`` is not a ``BaseModel`` or dict.
167
180
 
168
181
  Examples:
169
182
 
@@ -520,11 +520,11 @@ class BaseTracer(_TracerCore, BaseCallbackHandler, ABC):
520
520
  return retrieval_run
521
521
 
522
522
  def __deepcopy__(self, memo: dict) -> BaseTracer:
523
- """Deepcopy the tracer."""
523
+ """Return self."""
524
524
  return self
525
525
 
526
526
  def __copy__(self) -> BaseTracer:
527
- """Copy the tracer."""
527
+ """Return self."""
528
528
  return self
529
529
 
530
530
 
@@ -43,7 +43,11 @@ run_collector_var: ContextVar[Optional[RunCollectorCallbackHandler]] = ContextVa
43
43
  def tracing_enabled(
44
44
  session_name: str = "default", # noqa: ARG001
45
45
  ) -> Generator[TracerSessionV1, None, None]:
46
- """Throw an error because this has been replaced by tracing_v2_enabled."""
46
+ """Throw an error because this has been replaced by ``tracing_v2_enabled``.
47
+
48
+ Raises:
49
+ RuntimeError: Always, because this function is deprecated.
50
+ """
47
51
  msg = (
48
52
  "tracing_enabled is no longer supported. Please use tracing_enabled_v2 instead."
49
53
  )