langchain-core 0.4.0.dev0__py3-none-any.whl → 1.0.0__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 (172) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/__init__.py +3 -4
  3. langchain_core/_api/beta_decorator.py +45 -70
  4. langchain_core/_api/deprecation.py +80 -80
  5. langchain_core/_api/path.py +22 -8
  6. langchain_core/_import_utils.py +10 -4
  7. langchain_core/agents.py +25 -21
  8. langchain_core/caches.py +53 -63
  9. langchain_core/callbacks/__init__.py +1 -8
  10. langchain_core/callbacks/base.py +341 -348
  11. langchain_core/callbacks/file.py +55 -44
  12. langchain_core/callbacks/manager.py +546 -683
  13. langchain_core/callbacks/stdout.py +29 -30
  14. langchain_core/callbacks/streaming_stdout.py +35 -36
  15. langchain_core/callbacks/usage.py +65 -70
  16. langchain_core/chat_history.py +48 -55
  17. langchain_core/document_loaders/base.py +46 -21
  18. langchain_core/document_loaders/langsmith.py +39 -36
  19. langchain_core/documents/__init__.py +0 -1
  20. langchain_core/documents/base.py +96 -74
  21. langchain_core/documents/compressor.py +12 -9
  22. langchain_core/documents/transformers.py +29 -28
  23. langchain_core/embeddings/fake.py +56 -57
  24. langchain_core/env.py +2 -3
  25. langchain_core/example_selectors/base.py +12 -0
  26. langchain_core/example_selectors/length_based.py +1 -1
  27. langchain_core/example_selectors/semantic_similarity.py +21 -25
  28. langchain_core/exceptions.py +15 -9
  29. langchain_core/globals.py +4 -163
  30. langchain_core/indexing/api.py +132 -125
  31. langchain_core/indexing/base.py +64 -67
  32. langchain_core/indexing/in_memory.py +26 -6
  33. langchain_core/language_models/__init__.py +15 -27
  34. langchain_core/language_models/_utils.py +267 -117
  35. langchain_core/language_models/base.py +92 -177
  36. langchain_core/language_models/chat_models.py +547 -407
  37. langchain_core/language_models/fake.py +11 -11
  38. langchain_core/language_models/fake_chat_models.py +72 -118
  39. langchain_core/language_models/llms.py +168 -242
  40. langchain_core/load/dump.py +8 -11
  41. langchain_core/load/load.py +32 -28
  42. langchain_core/load/mapping.py +2 -4
  43. langchain_core/load/serializable.py +50 -56
  44. langchain_core/messages/__init__.py +36 -51
  45. langchain_core/messages/ai.py +377 -150
  46. langchain_core/messages/base.py +239 -47
  47. langchain_core/messages/block_translators/__init__.py +111 -0
  48. langchain_core/messages/block_translators/anthropic.py +470 -0
  49. langchain_core/messages/block_translators/bedrock.py +94 -0
  50. langchain_core/messages/block_translators/bedrock_converse.py +297 -0
  51. langchain_core/messages/block_translators/google_genai.py +530 -0
  52. langchain_core/messages/block_translators/google_vertexai.py +21 -0
  53. langchain_core/messages/block_translators/groq.py +143 -0
  54. langchain_core/messages/block_translators/langchain_v0.py +301 -0
  55. langchain_core/messages/block_translators/openai.py +1010 -0
  56. langchain_core/messages/chat.py +2 -3
  57. langchain_core/messages/content.py +1423 -0
  58. langchain_core/messages/function.py +7 -7
  59. langchain_core/messages/human.py +44 -38
  60. langchain_core/messages/modifier.py +3 -2
  61. langchain_core/messages/system.py +40 -27
  62. langchain_core/messages/tool.py +160 -58
  63. langchain_core/messages/utils.py +527 -638
  64. langchain_core/output_parsers/__init__.py +1 -14
  65. langchain_core/output_parsers/base.py +68 -104
  66. langchain_core/output_parsers/json.py +13 -17
  67. langchain_core/output_parsers/list.py +11 -33
  68. langchain_core/output_parsers/openai_functions.py +56 -74
  69. langchain_core/output_parsers/openai_tools.py +68 -109
  70. langchain_core/output_parsers/pydantic.py +15 -13
  71. langchain_core/output_parsers/string.py +6 -2
  72. langchain_core/output_parsers/transform.py +17 -60
  73. langchain_core/output_parsers/xml.py +34 -44
  74. langchain_core/outputs/__init__.py +1 -1
  75. langchain_core/outputs/chat_generation.py +26 -11
  76. langchain_core/outputs/chat_result.py +1 -3
  77. langchain_core/outputs/generation.py +17 -6
  78. langchain_core/outputs/llm_result.py +15 -8
  79. langchain_core/prompt_values.py +29 -123
  80. langchain_core/prompts/__init__.py +3 -27
  81. langchain_core/prompts/base.py +48 -63
  82. langchain_core/prompts/chat.py +259 -288
  83. langchain_core/prompts/dict.py +19 -11
  84. langchain_core/prompts/few_shot.py +84 -90
  85. langchain_core/prompts/few_shot_with_templates.py +14 -12
  86. langchain_core/prompts/image.py +19 -14
  87. langchain_core/prompts/loading.py +6 -8
  88. langchain_core/prompts/message.py +7 -8
  89. langchain_core/prompts/prompt.py +42 -43
  90. langchain_core/prompts/string.py +37 -16
  91. langchain_core/prompts/structured.py +43 -46
  92. langchain_core/rate_limiters.py +51 -60
  93. langchain_core/retrievers.py +52 -192
  94. langchain_core/runnables/base.py +1727 -1683
  95. langchain_core/runnables/branch.py +52 -73
  96. langchain_core/runnables/config.py +89 -103
  97. langchain_core/runnables/configurable.py +128 -130
  98. langchain_core/runnables/fallbacks.py +93 -82
  99. langchain_core/runnables/graph.py +127 -127
  100. langchain_core/runnables/graph_ascii.py +63 -41
  101. langchain_core/runnables/graph_mermaid.py +87 -70
  102. langchain_core/runnables/graph_png.py +31 -36
  103. langchain_core/runnables/history.py +145 -161
  104. langchain_core/runnables/passthrough.py +141 -144
  105. langchain_core/runnables/retry.py +84 -68
  106. langchain_core/runnables/router.py +33 -37
  107. langchain_core/runnables/schema.py +79 -72
  108. langchain_core/runnables/utils.py +95 -139
  109. langchain_core/stores.py +85 -131
  110. langchain_core/structured_query.py +11 -15
  111. langchain_core/sys_info.py +31 -32
  112. langchain_core/tools/__init__.py +1 -14
  113. langchain_core/tools/base.py +221 -247
  114. langchain_core/tools/convert.py +144 -161
  115. langchain_core/tools/render.py +10 -10
  116. langchain_core/tools/retriever.py +12 -19
  117. langchain_core/tools/simple.py +52 -29
  118. langchain_core/tools/structured.py +56 -60
  119. langchain_core/tracers/__init__.py +1 -9
  120. langchain_core/tracers/_streaming.py +6 -7
  121. langchain_core/tracers/base.py +103 -112
  122. langchain_core/tracers/context.py +29 -48
  123. langchain_core/tracers/core.py +142 -105
  124. langchain_core/tracers/evaluation.py +30 -34
  125. langchain_core/tracers/event_stream.py +162 -117
  126. langchain_core/tracers/langchain.py +34 -36
  127. langchain_core/tracers/log_stream.py +87 -49
  128. langchain_core/tracers/memory_stream.py +3 -3
  129. langchain_core/tracers/root_listeners.py +18 -34
  130. langchain_core/tracers/run_collector.py +8 -20
  131. langchain_core/tracers/schemas.py +0 -125
  132. langchain_core/tracers/stdout.py +3 -3
  133. langchain_core/utils/__init__.py +1 -4
  134. langchain_core/utils/_merge.py +47 -9
  135. langchain_core/utils/aiter.py +70 -66
  136. langchain_core/utils/env.py +12 -9
  137. langchain_core/utils/function_calling.py +139 -206
  138. langchain_core/utils/html.py +7 -8
  139. langchain_core/utils/input.py +6 -6
  140. langchain_core/utils/interactive_env.py +6 -2
  141. langchain_core/utils/iter.py +48 -45
  142. langchain_core/utils/json.py +14 -4
  143. langchain_core/utils/json_schema.py +159 -43
  144. langchain_core/utils/mustache.py +32 -25
  145. langchain_core/utils/pydantic.py +67 -40
  146. langchain_core/utils/strings.py +5 -5
  147. langchain_core/utils/usage.py +1 -1
  148. langchain_core/utils/utils.py +104 -62
  149. langchain_core/vectorstores/base.py +131 -179
  150. langchain_core/vectorstores/in_memory.py +113 -182
  151. langchain_core/vectorstores/utils.py +23 -17
  152. langchain_core/version.py +1 -1
  153. langchain_core-1.0.0.dist-info/METADATA +68 -0
  154. langchain_core-1.0.0.dist-info/RECORD +172 -0
  155. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0.dist-info}/WHEEL +1 -1
  156. langchain_core/beta/__init__.py +0 -1
  157. langchain_core/beta/runnables/__init__.py +0 -1
  158. langchain_core/beta/runnables/context.py +0 -448
  159. langchain_core/memory.py +0 -116
  160. langchain_core/messages/content_blocks.py +0 -1435
  161. langchain_core/prompts/pipeline.py +0 -133
  162. langchain_core/pydantic_v1/__init__.py +0 -30
  163. langchain_core/pydantic_v1/dataclasses.py +0 -23
  164. langchain_core/pydantic_v1/main.py +0 -23
  165. langchain_core/tracers/langchain_v1.py +0 -23
  166. langchain_core/utils/loading.py +0 -31
  167. langchain_core/v1/__init__.py +0 -1
  168. langchain_core/v1/chat_models.py +0 -1047
  169. langchain_core/v1/messages.py +0 -755
  170. langchain_core-0.4.0.dev0.dist-info/METADATA +0 -108
  171. langchain_core-0.4.0.dev0.dist-info/RECORD +0 -177
  172. langchain_core-0.4.0.dev0.dist-info/entry_points.txt +0 -4
@@ -5,16 +5,14 @@ from __future__ import annotations
5
5
  import inspect
6
6
  import textwrap
7
7
  import warnings
8
+ from collections.abc import Callable
8
9
  from contextlib import nullcontext
9
10
  from functools import lru_cache, wraps
10
11
  from types import GenericAlias
11
12
  from typing import (
12
13
  TYPE_CHECKING,
13
14
  Any,
14
- Callable,
15
- Optional,
16
15
  TypeVar,
17
- Union,
18
16
  cast,
19
17
  overload,
20
18
  )
@@ -57,6 +55,9 @@ def get_pydantic_major_version() -> int:
57
55
  """DEPRECATED - Get the major version of Pydantic.
58
56
 
59
57
  Use PYDANTIC_VERSION.major instead.
58
+
59
+ Returns:
60
+ The major version of Pydantic.
60
61
  """
61
62
  return PYDANTIC_VERSION.major
62
63
 
@@ -74,12 +75,20 @@ TBaseModel = TypeVar("TBaseModel", bound=PydanticBaseModel)
74
75
 
75
76
 
76
77
  def is_pydantic_v1_subclass(cls: type) -> bool:
77
- """Check if the installed Pydantic version is 1.x-like."""
78
+ """Check if the given class is Pydantic v1-like.
79
+
80
+ Returns:
81
+ `True` if the given class is a subclass of Pydantic `BaseModel` 1.x.
82
+ """
78
83
  return issubclass(cls, BaseModelV1)
79
84
 
80
85
 
81
86
  def is_pydantic_v2_subclass(cls: type) -> bool:
82
- """Check if the installed Pydantic version is 1.x-like."""
87
+ """Check if the given class is Pydantic v2-like.
88
+
89
+ Returns:
90
+ `True` if the given class is a subclass of Pydantic BaseModel 2.x.
91
+ """
83
92
  return issubclass(cls, BaseModel)
84
93
 
85
94
 
@@ -90,6 +99,9 @@ def is_basemodel_subclass(cls: type) -> bool:
90
99
 
91
100
  * pydantic.BaseModel in Pydantic 2.x
92
101
  * pydantic.v1.BaseModel in Pydantic 2.x
102
+
103
+ Returns:
104
+ `True` if the given class is a subclass of Pydantic `BaseModel`.
93
105
  """
94
106
  # Before we can use issubclass on the cls we need to check if it is a class
95
107
  if not inspect.isclass(cls) or isinstance(cls, GenericAlias):
@@ -105,6 +117,9 @@ def is_basemodel_instance(obj: Any) -> bool:
105
117
 
106
118
  * pydantic.BaseModel in Pydantic 2.x
107
119
  * pydantic.v1.BaseModel in Pydantic 2.x
120
+
121
+ Returns:
122
+ `True` if the given class is an instance of Pydantic `BaseModel`.
108
123
  """
109
124
  return isinstance(obj, (BaseModel, BaseModelV1))
110
125
 
@@ -114,10 +129,10 @@ def pre_init(func: Callable) -> Any:
114
129
  """Decorator to run a function before model initialization.
115
130
 
116
131
  Args:
117
- func (Callable): The function to run before model initialization.
132
+ func: The function to run before model initialization.
118
133
 
119
134
  Returns:
120
- Any: The decorated function.
135
+ The decorated function.
121
136
  """
122
137
  with warnings.catch_warnings():
123
138
  warnings.filterwarnings(action="ignore", category=PydanticDeprecationWarning)
@@ -125,17 +140,17 @@ def pre_init(func: Callable) -> Any:
125
140
  # Ideally we would use @model_validator(mode="before") but this would change the
126
141
  # order of the validators. See https://github.com/pydantic/pydantic/discussions/7434.
127
142
  # So we keep root_validator for backward compatibility.
128
- @root_validator(pre=True)
143
+ @root_validator(pre=True) # type: ignore[deprecated]
129
144
  @wraps(func)
130
145
  def wrapper(cls: type[BaseModel], values: dict[str, Any]) -> dict[str, Any]:
131
146
  """Decorator to run a function before model initialization.
132
147
 
133
148
  Args:
134
- cls (Type[BaseModel]): The model class.
135
- values (dict[str, Any]): The values to initialize the model with.
149
+ cls: The model class.
150
+ values: The values to initialize the model with.
136
151
 
137
152
  Returns:
138
- dict[str, Any]: The values to initialize the model with.
153
+ The values to initialize the model with.
139
154
  """
140
155
  # Insert default values
141
156
  fields = cls.model_fields
@@ -188,10 +203,10 @@ def _create_subset_model_v1(
188
203
  model: type[BaseModelV1],
189
204
  field_names: list,
190
205
  *,
191
- descriptions: Optional[dict] = None,
192
- fn_description: Optional[str] = None,
206
+ descriptions: dict | None = None,
207
+ fn_description: str | None = None,
193
208
  ) -> type[BaseModel]:
194
- """Create a pydantic model with only a subset of model's fields."""
209
+ """Create a Pydantic model with only a subset of model's fields."""
195
210
  fields = {}
196
211
 
197
212
  for field_name in field_names:
@@ -201,7 +216,7 @@ def _create_subset_model_v1(
201
216
  # this isn't perfect but should work for most functions
202
217
  field.outer_type_
203
218
  if field.required and not field.allow_none
204
- else Optional[field.outer_type_]
219
+ else field.outer_type_ | None
205
220
  )
206
221
  if descriptions and field_name in descriptions:
207
222
  field.field_info.description = descriptions[field_name]
@@ -217,10 +232,10 @@ def _create_subset_model_v2(
217
232
  model: type[BaseModel],
218
233
  field_names: list[str],
219
234
  *,
220
- descriptions: Optional[dict] = None,
221
- fn_description: Optional[str] = None,
235
+ descriptions: dict | None = None,
236
+ fn_description: str | None = None,
222
237
  ) -> type[BaseModel]:
223
- """Create a pydantic model with a subset of the model fields."""
238
+ """Create a Pydantic model with a subset of the model fields."""
224
239
  descriptions_ = descriptions or {}
225
240
  fields = {}
226
241
  for field_name in field_names:
@@ -259,10 +274,14 @@ def _create_subset_model(
259
274
  model: TypeBaseModel,
260
275
  field_names: list[str],
261
276
  *,
262
- descriptions: Optional[dict] = None,
263
- fn_description: Optional[str] = None,
277
+ descriptions: dict | None = None,
278
+ fn_description: str | None = None,
264
279
  ) -> type[BaseModel]:
265
- """Create subset model using the same pydantic version as the input model."""
280
+ """Create subset model using the same pydantic version as the input model.
281
+
282
+ Returns:
283
+ The created subset model.
284
+ """
266
285
  if issubclass(model, BaseModelV1):
267
286
  return _create_subset_model_v1(
268
287
  name,
@@ -297,15 +316,23 @@ def get_fields(model: BaseModelV1) -> dict[str, ModelField]: ...
297
316
 
298
317
 
299
318
  def get_fields(
300
- model: Union[type[Union[BaseModel, BaseModelV1]], BaseModel, BaseModelV1],
301
- ) -> Union[dict[str, FieldInfoV2], dict[str, ModelField]]:
302
- """Get the field names of a Pydantic model."""
303
- if hasattr(model, "model_fields"):
304
- return model.model_fields
319
+ model: type[BaseModel | BaseModelV1] | BaseModel | BaseModelV1,
320
+ ) -> dict[str, FieldInfoV2] | dict[str, ModelField]:
321
+ """Return the field names of a Pydantic model.
305
322
 
306
- if hasattr(model, "__fields__"):
323
+ Args:
324
+ model: The Pydantic model or instance.
325
+
326
+ Raises:
327
+ TypeError: If the model is not a Pydantic model.
328
+ """
329
+ if not isinstance(model, type):
330
+ model = type(model)
331
+ if issubclass(model, BaseModel):
332
+ return model.model_fields
333
+ if issubclass(model, BaseModelV1):
307
334
  return model.__fields__
308
- msg = f"Expected a Pydantic model. Got {type(model)}"
335
+ msg = f"Expected a Pydantic model. Got {model}"
309
336
  raise TypeError(msg)
310
337
 
311
338
 
@@ -319,7 +346,7 @@ NO_DEFAULT = object()
319
346
  def _create_root_model(
320
347
  name: str,
321
348
  type_: Any,
322
- module_name: Optional[str] = None,
349
+ module_name: str | None = None,
323
350
  default_: object = NO_DEFAULT,
324
351
  ) -> type[BaseModel]:
325
352
  """Create a base class."""
@@ -384,7 +411,7 @@ def _create_root_model_cached(
384
411
  model_name: str,
385
412
  type_: Any,
386
413
  *,
387
- module_name: Optional[str] = None,
414
+ module_name: str | None = None,
388
415
  default_: object = NO_DEFAULT,
389
416
  ) -> type[BaseModel]:
390
417
  return _create_root_model(
@@ -407,13 +434,13 @@ def _create_model_cached(
407
434
 
408
435
  def create_model(
409
436
  model_name: str,
410
- module_name: Optional[str] = None,
437
+ module_name: str | None = None,
411
438
  /,
412
439
  **field_definitions: Any,
413
440
  ) -> type[BaseModel]:
414
- """Create a pydantic model with the given field definitions.
441
+ """Create a Pydantic model with the given field definitions.
415
442
 
416
- Please use create_model_v2 instead of this function.
443
+ Please use `create_model_v2` instead of this function.
417
444
 
418
445
  Args:
419
446
  model_name: The name of the model.
@@ -422,7 +449,7 @@ def create_model(
422
449
  **field_definitions: The field definitions for the model.
423
450
 
424
451
  Returns:
425
- Type[BaseModel]: The created model.
452
+ The created model.
426
453
  """
427
454
  kwargs = {}
428
455
  if "__root__" in field_definitions:
@@ -480,11 +507,11 @@ def _remap_field_definitions(field_definitions: dict[str, Any]) -> dict[str, Any
480
507
  def create_model_v2(
481
508
  model_name: str,
482
509
  *,
483
- module_name: Optional[str] = None,
484
- field_definitions: Optional[dict[str, Any]] = None,
485
- root: Optional[Any] = None,
510
+ module_name: str | None = None,
511
+ field_definitions: dict[str, Any] | None = None,
512
+ root: Any | None = None,
486
513
  ) -> type[BaseModel]:
487
- """Create a pydantic model with the given field definitions.
514
+ """Create a Pydantic model with the given field definitions.
488
515
 
489
516
  Attention:
490
517
  Please do not use outside of langchain packages. This API
@@ -495,10 +522,10 @@ def create_model_v2(
495
522
  module_name: The name of the module where the model is defined.
496
523
  This is used by Pydantic to resolve any forward references.
497
524
  field_definitions: The field definitions for the model.
498
- root: Type for a root model (RootModel)
525
+ root: Type for a root model (`RootModel`)
499
526
 
500
527
  Returns:
501
- Type[BaseModel]: The created model.
528
+ The created model.
502
529
  """
503
530
  field_definitions = field_definitions or {}
504
531
 
@@ -10,7 +10,7 @@ def stringify_value(val: Any) -> str:
10
10
  val: The value to stringify.
11
11
 
12
12
  Returns:
13
- str: The stringified value.
13
+ The stringified value.
14
14
  """
15
15
  if isinstance(val, str):
16
16
  return val
@@ -28,7 +28,7 @@ def stringify_dict(data: dict) -> str:
28
28
  data: The dictionary to stringify.
29
29
 
30
30
  Returns:
31
- str: The stringified dictionary.
31
+ The stringified dictionary.
32
32
  """
33
33
  text = ""
34
34
  for key, value in data.items():
@@ -43,7 +43,7 @@ def comma_list(items: list[Any]) -> str:
43
43
  items: The list to convert.
44
44
 
45
45
  Returns:
46
- str: The comma-separated string.
46
+ The comma-separated string.
47
47
  """
48
48
  return ", ".join(str(item) for item in items)
49
49
 
@@ -57,10 +57,10 @@ def sanitize_for_postgres(text: str, replacement: str = "") -> str:
57
57
 
58
58
  Args:
59
59
  text: The text to sanitize.
60
- replacement: String to replace NUL bytes with. Defaults to empty string.
60
+ replacement: String to replace NUL bytes with.
61
61
 
62
62
  Returns:
63
- str: The sanitized text with NUL bytes removed or replaced.
63
+ The sanitized text with NUL bytes removed or replaced.
64
64
 
65
65
  Example:
66
66
  >>> sanitize_for_postgres("Hello\\x00world")
@@ -1,6 +1,6 @@
1
1
  """Usage utilities."""
2
2
 
3
- from typing import Callable
3
+ from collections.abc import Callable
4
4
 
5
5
 
6
6
  def _dict_int_op(
@@ -6,9 +6,10 @@ import functools
6
6
  import importlib
7
7
  import os
8
8
  import warnings
9
- from collections.abc import Iterator, Sequence
9
+ from collections.abc import Callable, Iterator, Sequence
10
10
  from importlib.metadata import version
11
- from typing import Any, Callable, Optional, Union, overload
11
+ from typing import Any, overload
12
+ from uuid import uuid4
12
13
 
13
14
  from packaging.version import parse
14
15
  from pydantic import SecretStr
@@ -21,17 +22,14 @@ from langchain_core.utils.pydantic import (
21
22
 
22
23
 
23
24
  def xor_args(*arg_groups: tuple[str, ...]) -> Callable:
24
- """Validate specified keyword args are mutually exclusive.".
25
+ """Validate specified keyword args are mutually exclusive.
25
26
 
26
27
  Args:
27
- *arg_groups (tuple[str, ...]): Groups of mutually exclusive keyword args.
28
+ *arg_groups: Groups of mutually exclusive keyword args.
28
29
 
29
30
  Returns:
30
- Callable: Decorator that validates the specified keyword args
31
- are mutually exclusive
32
-
33
- Raises:
34
- ValueError: If more than one arg in a group is defined.
31
+ Decorator that validates the specified keyword args
32
+ are mutually exclusive.
35
33
  """
36
34
 
37
35
  def decorator(func: Callable) -> Callable:
@@ -62,7 +60,7 @@ def raise_for_status_with_text(response: Response) -> None:
62
60
  """Raise an error with the response text.
63
61
 
64
62
  Args:
65
- response (Response): The response to check for errors.
63
+ response: The response to check for errors.
66
64
 
67
65
  Raises:
68
66
  ValueError: If the response has an error status code.
@@ -81,11 +79,13 @@ def mock_now(dt_value: datetime.datetime) -> Iterator[type]:
81
79
  dt_value: The datetime value to use for datetime.now().
82
80
 
83
81
  Yields:
84
- datetime.datetime: The mocked datetime class.
82
+ The mocked datetime class.
85
83
 
86
84
  Example:
87
- with mock_now(datetime.datetime(2011, 2, 3, 10, 11)):
88
- assert datetime.datetime.now() == datetime.datetime(2011, 2, 3, 10, 11)
85
+ ```python
86
+ with mock_now(datetime.datetime(2011, 2, 3, 10, 11)):
87
+ assert datetime.datetime.now() == datetime.datetime(2011, 2, 3, 10, 11)
88
+ ```
89
89
  """
90
90
 
91
91
  class MockDateTime(datetime.datetime):
@@ -93,7 +93,7 @@ def mock_now(dt_value: datetime.datetime) -> Iterator[type]:
93
93
 
94
94
  @classmethod
95
95
  @override
96
- def now(cls, tz: Union[datetime.tzinfo, None] = None) -> "MockDateTime":
96
+ def now(cls, tz: datetime.tzinfo | None = None) -> "MockDateTime":
97
97
  # Create a copy of dt_value.
98
98
  return MockDateTime(
99
99
  dt_value.year,
@@ -115,21 +115,19 @@ def mock_now(dt_value: datetime.datetime) -> Iterator[type]:
115
115
 
116
116
 
117
117
  def guard_import(
118
- module_name: str, *, pip_name: Optional[str] = None, package: Optional[str] = None
118
+ module_name: str, *, pip_name: str | None = None, package: str | None = None
119
119
  ) -> Any:
120
120
  """Dynamically import a module.
121
121
 
122
122
  Raise an exception if the module is not installed.
123
123
 
124
124
  Args:
125
- module_name (str): The name of the module to import.
126
- pip_name (str, optional): The name of the module to install with pip.
127
- Defaults to None.
128
- package (str, optional): The package to import the module from.
129
- Defaults to None.
125
+ module_name: The name of the module to import.
126
+ pip_name: The name of the module to install with pip.
127
+ package: The package to import the module from.
130
128
 
131
129
  Returns:
132
- Any: The imported module.
130
+ The imported module.
133
131
 
134
132
  Raises:
135
133
  ImportError: If the module is not installed.
@@ -137,7 +135,7 @@ def guard_import(
137
135
  try:
138
136
  module = importlib.import_module(module_name, package)
139
137
  except (ImportError, ModuleNotFoundError) as e:
140
- pip_name = pip_name or module_name.split(".")[0].replace("_", "-")
138
+ pip_name = pip_name or module_name.split(".", maxsplit=1)[0].replace("_", "-")
141
139
  msg = (
142
140
  f"Could not import {module_name} python package. "
143
141
  f"Please install it with `pip install {pip_name}`."
@@ -148,23 +146,20 @@ def guard_import(
148
146
 
149
147
  def check_package_version(
150
148
  package: str,
151
- lt_version: Optional[str] = None,
152
- lte_version: Optional[str] = None,
153
- gt_version: Optional[str] = None,
154
- gte_version: Optional[str] = None,
149
+ lt_version: str | None = None,
150
+ lte_version: str | None = None,
151
+ gt_version: str | None = None,
152
+ gte_version: str | None = None,
155
153
  ) -> None:
156
154
  """Check the version of a package.
157
155
 
158
156
  Args:
159
- package (str): The name of the package.
160
- lt_version (str, optional): The version must be less than this.
161
- Defaults to None.
162
- lte_version (str, optional): The version must be less than or equal to this.
163
- Defaults to None.
164
- gt_version (str, optional): The version must be greater than this.
165
- Defaults to None.
166
- gte_version (str, optional): The version must be greater than or equal to this.
167
- Defaults to None.
157
+ package: The name of the package.
158
+ lt_version: The version must be less than this.
159
+ lte_version: The version must be less than or equal to this.
160
+ gt_version: The version must be greater than this.
161
+ gte_version: The version must be greater than or equal to this.
162
+
168
163
 
169
164
  Raises:
170
165
  ValueError: If the package version does not meet the requirements.
@@ -203,7 +198,7 @@ def get_pydantic_field_names(pydantic_cls: Any) -> set[str]:
203
198
  pydantic_cls: Pydantic class.
204
199
 
205
200
  Returns:
206
- set[str]: Field names.
201
+ Field names.
207
202
  """
208
203
  all_required_field_names = set()
209
204
  if is_pydantic_v1_subclass(pydantic_cls):
@@ -223,14 +218,14 @@ def _build_model_kwargs(
223
218
  values: dict[str, Any],
224
219
  all_required_field_names: set[str],
225
220
  ) -> dict[str, Any]:
226
- """Build "model_kwargs" param from Pydanitc constructor values.
221
+ """Build "model_kwargs" param from Pydantic constructor values.
227
222
 
228
223
  Args:
229
224
  values: All init args passed in by user.
230
225
  all_required_field_names: All required field names for the pydantic class.
231
226
 
232
227
  Returns:
233
- dict[str, Any]: Extra kwargs.
228
+ Extra kwargs.
234
229
 
235
230
  Raises:
236
231
  ValueError: If a field is specified in both values and extra_kwargs.
@@ -278,7 +273,7 @@ def build_extra_kwargs(
278
273
  all_required_field_names: All required field names for the pydantic class.
279
274
 
280
275
  Returns:
281
- dict[str, Any]: Extra kwargs.
276
+ Extra kwargs.
282
277
 
283
278
  Raises:
284
279
  ValueError: If a field is specified in both values and extra_kwargs.
@@ -308,14 +303,14 @@ def build_extra_kwargs(
308
303
  return extra_kwargs
309
304
 
310
305
 
311
- def convert_to_secret_str(value: Union[SecretStr, str]) -> SecretStr:
306
+ def convert_to_secret_str(value: SecretStr | str) -> SecretStr:
312
307
  """Convert a string to a SecretStr if needed.
313
308
 
314
309
  Args:
315
- value (Union[SecretStr, str]): The value to convert.
310
+ value: The value to convert.
316
311
 
317
312
  Returns:
318
- SecretStr: The SecretStr value.
313
+ The SecretStr value.
319
314
  """
320
315
  if isinstance(value, SecretStr):
321
316
  return value
@@ -347,29 +342,29 @@ def from_env(key: str, /, *, error_message: str) -> Callable[[], str]: ...
347
342
 
348
343
  @overload
349
344
  def from_env(
350
- key: Union[str, Sequence[str]], /, *, default: str, error_message: Optional[str]
345
+ key: str | Sequence[str], /, *, default: str, error_message: str | None
351
346
  ) -> Callable[[], str]: ...
352
347
 
353
348
 
354
349
  @overload
355
350
  def from_env(
356
- key: str, /, *, default: None, error_message: Optional[str]
357
- ) -> Callable[[], Optional[str]]: ...
351
+ key: str, /, *, default: None, error_message: str | None
352
+ ) -> Callable[[], str | None]: ...
358
353
 
359
354
 
360
355
  @overload
361
356
  def from_env(
362
- key: Union[str, Sequence[str]], /, *, default: None
363
- ) -> Callable[[], Optional[str]]: ...
357
+ key: str | Sequence[str], /, *, default: None
358
+ ) -> Callable[[], str | None]: ...
364
359
 
365
360
 
366
361
  def from_env(
367
- key: Union[str, Sequence[str]],
362
+ key: str | Sequence[str],
368
363
  /,
369
364
  *,
370
- default: Union[str, _NoDefaultType, None] = _NoDefault,
371
- error_message: Optional[str] = None,
372
- ) -> Union[Callable[[], str], Callable[[], Optional[str]]]:
365
+ default: str | _NoDefaultType | None = _NoDefault,
366
+ error_message: str | None = None,
367
+ ) -> Callable[[], str] | Callable[[], str | None]:
373
368
  """Create a factory method that gets a value from an environment variable.
374
369
 
375
370
  Args:
@@ -381,10 +376,21 @@ def from_env(
381
376
  error_message: the error message which will be raised if the key is not found
382
377
  and no default value is provided.
383
378
  This will be raised as a ValueError.
379
+
380
+ Returns:
381
+ factory method that will look up the value from the environment.
384
382
  """
385
383
 
386
- def get_from_env_fn() -> Optional[str]:
387
- """Get a value from an environment variable."""
384
+ def get_from_env_fn() -> str | None:
385
+ """Get a value from an environment variable.
386
+
387
+ Raises:
388
+ ValueError: If the environment variable is not set and no default is
389
+ provided.
390
+
391
+ Returns:
392
+ The value from the environment.
393
+ """
388
394
  if isinstance(key, (list, tuple)):
389
395
  for k in key:
390
396
  if k in os.environ:
@@ -407,7 +413,7 @@ def from_env(
407
413
 
408
414
 
409
415
  @overload
410
- def secret_from_env(key: Union[str, Sequence[str]], /) -> Callable[[], SecretStr]: ...
416
+ def secret_from_env(key: str | Sequence[str], /) -> Callable[[], SecretStr]: ...
411
417
 
412
418
 
413
419
  @overload
@@ -416,8 +422,8 @@ def secret_from_env(key: str, /, *, default: str) -> Callable[[], SecretStr]: ..
416
422
 
417
423
  @overload
418
424
  def secret_from_env(
419
- key: Union[str, Sequence[str]], /, *, default: None
420
- ) -> Callable[[], Optional[SecretStr]]: ...
425
+ key: str | Sequence[str], /, *, default: None
426
+ ) -> Callable[[], SecretStr | None]: ...
421
427
 
422
428
 
423
429
  @overload
@@ -425,12 +431,12 @@ def secret_from_env(key: str, /, *, error_message: str) -> Callable[[], SecretSt
425
431
 
426
432
 
427
433
  def secret_from_env(
428
- key: Union[str, Sequence[str]],
434
+ key: str | Sequence[str],
429
435
  /,
430
436
  *,
431
- default: Union[str, _NoDefaultType, None] = _NoDefault,
432
- error_message: Optional[str] = None,
433
- ) -> Union[Callable[[], Optional[SecretStr]], Callable[[], SecretStr]]:
437
+ default: str | _NoDefaultType | None = _NoDefault,
438
+ error_message: str | None = None,
439
+ ) -> Callable[[], SecretStr | None] | Callable[[], SecretStr]:
434
440
  """Secret from env.
435
441
 
436
442
  Args:
@@ -444,8 +450,16 @@ def secret_from_env(
444
450
  factory method that will look up the secret from the environment.
445
451
  """
446
452
 
447
- def get_secret_from_env() -> Optional[SecretStr]:
448
- """Get a value from an environment variable."""
453
+ def get_secret_from_env() -> SecretStr | None:
454
+ """Get a value from an environment variable.
455
+
456
+ Raises:
457
+ ValueError: If the environment variable is not set and no default is
458
+ provided.
459
+
460
+ Returns:
461
+ The secret from the environment.
462
+ """
449
463
  if isinstance(key, (list, tuple)):
450
464
  for k in key:
451
465
  if k in os.environ:
@@ -466,3 +480,31 @@ def secret_from_env(
466
480
  raise ValueError(msg)
467
481
 
468
482
  return get_secret_from_env
483
+
484
+
485
+ LC_AUTO_PREFIX = "lc_"
486
+ """LangChain auto-generated ID prefix for messages and content blocks."""
487
+
488
+ LC_ID_PREFIX = "lc_run-"
489
+ """Internal tracing/callback system identifier.
490
+
491
+ Used for:
492
+ - Tracing. Every LangChain operation (LLM call, chain execution, tool use, etc.)
493
+ gets a unique run_id (UUID)
494
+ - Enables tracking parent-child relationships between operations
495
+ """
496
+
497
+
498
+ def ensure_id(id_val: str | None) -> str:
499
+ """Ensure the ID is a valid string, generating a new UUID if not provided.
500
+
501
+ Auto-generated UUIDs are prefixed by `'lc_'` to indicate they are
502
+ LangChain-generated IDs.
503
+
504
+ Args:
505
+ id_val: Optional string ID value to validate.
506
+
507
+ Returns:
508
+ A string ID, either the validated provided value or a newly generated UUID4.
509
+ """
510
+ return id_val or f"{LC_AUTO_PREFIX}{uuid4()}"