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
@@ -8,22 +8,22 @@ import logging
8
8
  from typing import (
9
9
  TYPE_CHECKING,
10
10
  Any,
11
- Optional,
11
+ TypedDict,
12
12
  TypeVar,
13
- Union,
14
13
  cast,
15
14
  )
16
15
  from uuid import UUID, uuid4
17
16
 
18
- from typing_extensions import NotRequired, TypedDict, override
17
+ from typing_extensions import NotRequired, override
19
18
 
20
- from langchain_core.callbacks.base import AsyncCallbackHandler
19
+ from langchain_core.callbacks.base import AsyncCallbackHandler, BaseCallbackManager
21
20
  from langchain_core.messages import AIMessageChunk, BaseMessage, BaseMessageChunk
22
21
  from langchain_core.outputs import (
23
22
  ChatGenerationChunk,
24
23
  GenerationChunk,
25
24
  LLMResult,
26
25
  )
26
+ from langchain_core.runnables import ensure_config
27
27
  from langchain_core.runnables.schema import (
28
28
  CustomStreamEvent,
29
29
  EventData,
@@ -36,9 +36,13 @@ from langchain_core.runnables.utils import (
36
36
  _RootEventFilter,
37
37
  )
38
38
  from langchain_core.tracers._streaming import _StreamingCallbackHandler
39
+ from langchain_core.tracers.log_stream import (
40
+ LogStreamCallbackHandler,
41
+ RunLog,
42
+ _astream_log_implementation,
43
+ )
39
44
  from langchain_core.tracers.memory_stream import _MemoryStream
40
45
  from langchain_core.utils.aiter import aclosing, py_anext
41
- from langchain_core.v1.messages import MessageV1
42
46
 
43
47
  if TYPE_CHECKING:
44
48
  from collections.abc import AsyncIterator, Iterator, Sequence
@@ -46,8 +50,6 @@ if TYPE_CHECKING:
46
50
  from langchain_core.documents import Document
47
51
  from langchain_core.runnables import Runnable, RunnableConfig
48
52
  from langchain_core.tracers.log_stream import LogEntry
49
- from langchain_core.v1.messages import AIMessage as AIMessageV1
50
- from langchain_core.v1.messages import AIMessageChunk as AIMessageChunkV1
51
53
 
52
54
  logger = logging.getLogger(__name__)
53
55
 
@@ -56,25 +58,23 @@ class RunInfo(TypedDict):
56
58
  """Information about a run.
57
59
 
58
60
  This is used to keep track of the metadata associated with a run.
59
-
60
- Parameters:
61
- name: The name of the run.
62
- tags: The tags associated with the run.
63
- metadata: The metadata associated with the run.
64
- run_type: The type of the run.
65
- inputs: The inputs to the run.
66
- parent_run_id: The ID of the parent run.
67
61
  """
68
62
 
69
63
  name: str
64
+ """The name of the run."""
70
65
  tags: list[str]
66
+ """The tags associated with the run."""
71
67
  metadata: dict[str, Any]
68
+ """The metadata associated with the run."""
72
69
  run_type: str
70
+ """The type of the run."""
73
71
  inputs: NotRequired[Any]
74
- parent_run_id: Optional[UUID]
72
+ """The inputs to the run."""
73
+ parent_run_id: UUID | None
74
+ """The ID of the parent run."""
75
75
 
76
76
 
77
- def _assign_name(name: Optional[str], serialized: Optional[dict[str, Any]]) -> str:
77
+ def _assign_name(name: str | None, serialized: dict[str, Any] | None) -> str:
78
78
  """Assign a name to a run."""
79
79
  if name is not None:
80
80
  return name
@@ -95,12 +95,12 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
95
95
  def __init__(
96
96
  self,
97
97
  *args: Any,
98
- include_names: Optional[Sequence[str]] = None,
99
- include_types: Optional[Sequence[str]] = None,
100
- include_tags: Optional[Sequence[str]] = None,
101
- exclude_names: Optional[Sequence[str]] = None,
102
- exclude_types: Optional[Sequence[str]] = None,
103
- exclude_tags: Optional[Sequence[str]] = None,
98
+ include_names: Sequence[str] | None = None,
99
+ include_types: Sequence[str] | None = None,
100
+ include_tags: Sequence[str] | None = None,
101
+ exclude_names: Sequence[str] | None = None,
102
+ exclude_types: Sequence[str] | None = None,
103
+ exclude_tags: Sequence[str] | None = None,
104
104
  **kwargs: Any,
105
105
  ) -> None:
106
106
  """Initialize the tracer."""
@@ -114,7 +114,7 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
114
114
  # of a child run, which results in clean up of run_map.
115
115
  # So we keep track of the mapping between children and parent run IDs
116
116
  # in a separate container. This container is GCed when the tracer is GCed.
117
- self.parent_map: dict[UUID, Optional[UUID]] = {}
117
+ self.parent_map: dict[UUID, UUID | None] = {}
118
118
 
119
119
  self.is_tapped: dict[UUID, Any] = {}
120
120
 
@@ -128,7 +128,10 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
128
128
  exclude_tags=exclude_tags,
129
129
  )
130
130
 
131
- loop = asyncio.get_event_loop()
131
+ try:
132
+ loop = asyncio.get_event_loop()
133
+ except RuntimeError:
134
+ loop = asyncio.new_event_loop()
132
135
  memory_stream = _MemoryStream[StreamEvent](loop)
133
136
  self.send_stream = memory_stream.get_send_stream()
134
137
  self.receive_stream = memory_stream.get_receive_stream()
@@ -158,7 +161,11 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
158
161
  self.send_stream.send_nowait(event)
159
162
 
160
163
  def __aiter__(self) -> AsyncIterator[Any]:
161
- """Iterate over the receive stream."""
164
+ """Iterate over the receive stream.
165
+
166
+ Returns:
167
+ An async iterator over the receive stream.
168
+ """
162
169
  return self.receive_stream.__aiter__()
163
170
 
164
171
  async def tap_output_aiter(
@@ -175,7 +182,7 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
175
182
  output: The output of the Runnable.
176
183
 
177
184
  Yields:
178
- T: The output of the Runnable.
185
+ The output of the Runnable.
179
186
  """
180
187
  sentinel = object()
181
188
  # atomic check and set
@@ -218,14 +225,14 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
218
225
  yield chunk
219
226
 
220
227
  def tap_output_iter(self, run_id: UUID, output: Iterator[T]) -> Iterator[T]:
221
- """Tap the output aiter.
228
+ """Tap the output iter.
222
229
 
223
230
  Args:
224
231
  run_id: The ID of the run.
225
232
  output: The output of the Runnable.
226
233
 
227
234
  Yields:
228
- T: The output of the Runnable.
235
+ The output of the Runnable.
229
236
  """
230
237
  sentinel = object()
231
238
  # atomic check and set
@@ -271,9 +278,9 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
271
278
  self,
272
279
  run_id: UUID,
273
280
  *,
274
- tags: Optional[list[str]],
275
- metadata: Optional[dict[str, Any]],
276
- parent_run_id: Optional[UUID],
281
+ tags: list[str] | None,
282
+ metadata: dict[str, Any] | None,
283
+ parent_run_id: UUID | None,
277
284
  name_: str,
278
285
  run_type: str,
279
286
  **kwargs: Any,
@@ -300,18 +307,16 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
300
307
  async def on_chat_model_start(
301
308
  self,
302
309
  serialized: dict[str, Any],
303
- messages: Union[list[list[BaseMessage]], list[MessageV1]],
310
+ messages: list[list[BaseMessage]],
304
311
  *,
305
312
  run_id: UUID,
306
- tags: Optional[list[str]] = None,
307
- parent_run_id: Optional[UUID] = None,
308
- metadata: Optional[dict[str, Any]] = None,
309
- name: Optional[str] = None,
313
+ tags: list[str] | None = None,
314
+ parent_run_id: UUID | None = None,
315
+ metadata: dict[str, Any] | None = None,
316
+ name: str | None = None,
310
317
  **kwargs: Any,
311
318
  ) -> None:
312
- """Start a trace for an LLM run."""
313
- # below cast is because type is converted in handle_event
314
- messages = cast("list[list[BaseMessage]]", messages)
319
+ """Start a trace for a chat model run."""
315
320
  name_ = _assign_name(name, serialized)
316
321
  run_type = "chat_model"
317
322
 
@@ -347,13 +352,13 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
347
352
  prompts: list[str],
348
353
  *,
349
354
  run_id: UUID,
350
- tags: Optional[list[str]] = None,
351
- parent_run_id: Optional[UUID] = None,
352
- metadata: Optional[dict[str, Any]] = None,
353
- name: Optional[str] = None,
355
+ tags: list[str] | None = None,
356
+ parent_run_id: UUID | None = None,
357
+ metadata: dict[str, Any] | None = None,
358
+ name: str | None = None,
354
359
  **kwargs: Any,
355
360
  ) -> None:
356
- """Start a trace for an LLM run."""
361
+ """Start a trace for a (non-chat model) LLM run."""
357
362
  name_ = _assign_name(name, serialized)
358
363
  run_type = "llm"
359
364
 
@@ -391,8 +396,8 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
391
396
  data: Any,
392
397
  *,
393
398
  run_id: UUID,
394
- tags: Optional[list[str]] = None,
395
- metadata: Optional[dict[str, Any]] = None,
399
+ tags: list[str] | None = None,
400
+ metadata: dict[str, Any] | None = None,
396
401
  **kwargs: Any,
397
402
  ) -> None:
398
403
  """Generate a custom astream event."""
@@ -412,19 +417,17 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
412
417
  self,
413
418
  token: str,
414
419
  *,
415
- chunk: Optional[
416
- Union[GenerationChunk, ChatGenerationChunk, AIMessageChunkV1]
417
- ] = None,
420
+ chunk: GenerationChunk | ChatGenerationChunk | None = None,
418
421
  run_id: UUID,
419
- parent_run_id: Optional[UUID] = None,
422
+ parent_run_id: UUID | None = None,
420
423
  **kwargs: Any,
421
424
  ) -> None:
422
- """Run on new LLM token. Only available when streaming is enabled."""
425
+ """Run on new output token. Only available when streaming is enabled.
426
+
427
+ For both chat models and non-chat models (legacy LLMs).
428
+ """
423
429
  run_info = self.run_map.get(run_id)
424
- chunk = cast(
425
- "Optional[Union[GenerationChunk, ChatGenerationChunk]]", chunk
426
- ) # converted in handle_event
427
- chunk_: Union[GenerationChunk, BaseMessageChunk]
430
+ chunk_: GenerationChunk | BaseMessageChunk
428
431
 
429
432
  if run_info is None:
430
433
  msg = f"Run ID {run_id} not found in run map."
@@ -466,15 +469,20 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
466
469
 
467
470
  @override
468
471
  async def on_llm_end(
469
- self, response: Union[LLMResult, AIMessageV1], *, run_id: UUID, **kwargs: Any
472
+ self, response: LLMResult, *, run_id: UUID, **kwargs: Any
470
473
  ) -> None:
471
- """End a trace for an LLM run."""
472
- response = cast("LLMResult", response) # converted in handle_event
474
+ """End a trace for a model run.
475
+
476
+ For both chat models and non-chat models (legacy LLMs).
477
+
478
+ Raises:
479
+ ValueError: If the run type is not `'llm'` or `'chat_model'`.
480
+ """
473
481
  run_info = self.run_map.pop(run_id)
474
- inputs_ = run_info["inputs"]
482
+ inputs_ = run_info.get("inputs")
475
483
 
476
- generations: Union[list[list[GenerationChunk]], list[list[ChatGenerationChunk]]]
477
- output: Union[dict, BaseMessage] = {}
484
+ generations: list[list[GenerationChunk]] | list[list[ChatGenerationChunk]]
485
+ output: dict | BaseMessage = {}
478
486
 
479
487
  if run_info["run_type"] == "chat_model":
480
488
  generations = cast("list[list[ChatGenerationChunk]]", response.generations)
@@ -526,11 +534,11 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
526
534
  inputs: dict[str, Any],
527
535
  *,
528
536
  run_id: UUID,
529
- tags: Optional[list[str]] = None,
530
- parent_run_id: Optional[UUID] = None,
531
- metadata: Optional[dict[str, Any]] = None,
532
- run_type: Optional[str] = None,
533
- name: Optional[str] = None,
537
+ tags: list[str] | None = None,
538
+ parent_run_id: UUID | None = None,
539
+ metadata: dict[str, Any] | None = None,
540
+ run_type: str | None = None,
541
+ name: str | None = None,
534
542
  **kwargs: Any,
535
543
  ) -> None:
536
544
  """Start a trace for a chain run."""
@@ -574,7 +582,7 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
574
582
  outputs: dict[str, Any],
575
583
  *,
576
584
  run_id: UUID,
577
- inputs: Optional[dict[str, Any]] = None,
585
+ inputs: dict[str, Any] | None = None,
578
586
  **kwargs: Any,
579
587
  ) -> None:
580
588
  """End a trace for a chain run."""
@@ -603,6 +611,28 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
603
611
  run_type,
604
612
  )
605
613
 
614
+ def _get_tool_run_info_with_inputs(self, run_id: UUID) -> tuple[RunInfo, Any]:
615
+ """Get run info for a tool and extract inputs, with validation.
616
+
617
+ Args:
618
+ run_id: The run ID of the tool.
619
+
620
+ Returns:
621
+ A tuple of (run_info, inputs).
622
+
623
+ Raises:
624
+ AssertionError: If the run ID is a tool call and does not have inputs.
625
+ """
626
+ run_info = self.run_map.pop(run_id)
627
+ if "inputs" not in run_info:
628
+ msg = (
629
+ f"Run ID {run_id} is a tool call and is expected to have "
630
+ f"inputs associated with it."
631
+ )
632
+ raise AssertionError(msg)
633
+ inputs = run_info["inputs"]
634
+ return run_info, inputs
635
+
606
636
  @override
607
637
  async def on_tool_start(
608
638
  self,
@@ -610,11 +640,11 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
610
640
  input_str: str,
611
641
  *,
612
642
  run_id: UUID,
613
- tags: Optional[list[str]] = None,
614
- parent_run_id: Optional[UUID] = None,
615
- metadata: Optional[dict[str, Any]] = None,
616
- name: Optional[str] = None,
617
- inputs: Optional[dict[str, Any]] = None,
643
+ tags: list[str] | None = None,
644
+ parent_run_id: UUID | None = None,
645
+ metadata: dict[str, Any] | None = None,
646
+ name: str | None = None,
647
+ inputs: dict[str, Any] | None = None,
618
648
  **kwargs: Any,
619
649
  ) -> None:
620
650
  """Start a trace for a tool run."""
@@ -645,17 +675,43 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
645
675
  "tool",
646
676
  )
647
677
 
678
+ @override
679
+ async def on_tool_error(
680
+ self,
681
+ error: BaseException,
682
+ *,
683
+ run_id: UUID,
684
+ parent_run_id: UUID | None = None,
685
+ tags: list[str] | None = None,
686
+ **kwargs: Any,
687
+ ) -> None:
688
+ """Run when tool errors."""
689
+ run_info, inputs = self._get_tool_run_info_with_inputs(run_id)
690
+
691
+ self._send(
692
+ {
693
+ "event": "on_tool_error",
694
+ "data": {
695
+ "error": error,
696
+ "input": inputs,
697
+ },
698
+ "run_id": str(run_id),
699
+ "name": run_info["name"],
700
+ "tags": run_info["tags"],
701
+ "metadata": run_info["metadata"],
702
+ "parent_ids": self._get_parent_ids(run_id),
703
+ },
704
+ "tool",
705
+ )
706
+
648
707
  @override
649
708
  async def on_tool_end(self, output: Any, *, run_id: UUID, **kwargs: Any) -> None:
650
- """End a trace for a tool run."""
651
- run_info = self.run_map.pop(run_id)
652
- if "inputs" not in run_info:
653
- msg = (
654
- f"Run ID {run_id} is a tool call and is expected to have "
655
- f"inputs associated with it."
656
- )
657
- raise AssertionError(msg)
658
- inputs = run_info["inputs"]
709
+ """End a trace for a tool run.
710
+
711
+ Raises:
712
+ AssertionError: If the run ID is a tool call and does not have inputs
713
+ """
714
+ run_info, inputs = self._get_tool_run_info_with_inputs(run_id)
659
715
 
660
716
  self._send(
661
717
  {
@@ -680,10 +736,10 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
680
736
  query: str,
681
737
  *,
682
738
  run_id: UUID,
683
- parent_run_id: Optional[UUID] = None,
684
- tags: Optional[list[str]] = None,
685
- metadata: Optional[dict[str, Any]] = None,
686
- name: Optional[str] = None,
739
+ parent_run_id: UUID | None = None,
740
+ tags: list[str] | None = None,
741
+ metadata: dict[str, Any] | None = None,
742
+ name: str | None = None,
687
743
  **kwargs: Any,
688
744
  ) -> None:
689
745
  """Run when Retriever starts running."""
@@ -729,7 +785,7 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
729
785
  "event": "on_retriever_end",
730
786
  "data": {
731
787
  "output": documents,
732
- "input": run_info["inputs"],
788
+ "input": run_info.get("inputs"),
733
789
  },
734
790
  "run_id": str(run_id),
735
791
  "name": run_info["name"],
@@ -741,35 +797,27 @@ class _AstreamEventsCallbackHandler(AsyncCallbackHandler, _StreamingCallbackHand
741
797
  )
742
798
 
743
799
  def __deepcopy__(self, memo: dict) -> _AstreamEventsCallbackHandler:
744
- """Deepcopy the tracer."""
800
+ """Return self."""
745
801
  return self
746
802
 
747
803
  def __copy__(self) -> _AstreamEventsCallbackHandler:
748
- """Copy the tracer."""
804
+ """Return self."""
749
805
  return self
750
806
 
751
807
 
752
808
  async def _astream_events_implementation_v1(
753
809
  runnable: Runnable[Input, Output],
754
810
  value: Any,
755
- config: Optional[RunnableConfig] = None,
811
+ config: RunnableConfig | None = None,
756
812
  *,
757
- include_names: Optional[Sequence[str]] = None,
758
- include_types: Optional[Sequence[str]] = None,
759
- include_tags: Optional[Sequence[str]] = None,
760
- exclude_names: Optional[Sequence[str]] = None,
761
- exclude_types: Optional[Sequence[str]] = None,
762
- exclude_tags: Optional[Sequence[str]] = None,
813
+ include_names: Sequence[str] | None = None,
814
+ include_types: Sequence[str] | None = None,
815
+ include_tags: Sequence[str] | None = None,
816
+ exclude_names: Sequence[str] | None = None,
817
+ exclude_types: Sequence[str] | None = None,
818
+ exclude_tags: Sequence[str] | None = None,
763
819
  **kwargs: Any,
764
820
  ) -> AsyncIterator[StandardStreamEvent]:
765
- from langchain_core.runnables import ensure_config
766
- from langchain_core.runnables.utils import _RootEventFilter
767
- from langchain_core.tracers.log_stream import (
768
- LogStreamCallbackHandler,
769
- RunLog,
770
- _astream_log_implementation,
771
- )
772
-
773
821
  stream = LogStreamCallbackHandler(
774
822
  auto_close=False,
775
823
  include_names=include_names,
@@ -849,12 +897,12 @@ async def _astream_events_implementation_v1(
849
897
  # Usually they will NOT be available for components that operate
850
898
  # on streams, since those components stream the input and
851
899
  # don't know its final value until the end of the stream.
852
- inputs = log_entry["inputs"]
900
+ inputs = log_entry.get("inputs")
853
901
  if inputs is not None:
854
902
  data["input"] = inputs
855
903
 
856
904
  if event_type == "end":
857
- inputs = log_entry["inputs"]
905
+ inputs = log_entry.get("inputs")
858
906
  if inputs is not None:
859
907
  data["input"] = inputs
860
908
 
@@ -936,20 +984,17 @@ async def _astream_events_implementation_v1(
936
984
  async def _astream_events_implementation_v2(
937
985
  runnable: Runnable[Input, Output],
938
986
  value: Any,
939
- config: Optional[RunnableConfig] = None,
987
+ config: RunnableConfig | None = None,
940
988
  *,
941
- include_names: Optional[Sequence[str]] = None,
942
- include_types: Optional[Sequence[str]] = None,
943
- include_tags: Optional[Sequence[str]] = None,
944
- exclude_names: Optional[Sequence[str]] = None,
945
- exclude_types: Optional[Sequence[str]] = None,
946
- exclude_tags: Optional[Sequence[str]] = None,
989
+ include_names: Sequence[str] | None = None,
990
+ include_types: Sequence[str] | None = None,
991
+ include_tags: Sequence[str] | None = None,
992
+ exclude_names: Sequence[str] | None = None,
993
+ exclude_types: Sequence[str] | None = None,
994
+ exclude_tags: Sequence[str] | None = None,
947
995
  **kwargs: Any,
948
996
  ) -> AsyncIterator[StandardStreamEvent]:
949
997
  """Implementation of the astream events API for V2 runnables."""
950
- from langchain_core.callbacks.base import BaseCallbackManager
951
- from langchain_core.runnables import ensure_config
952
-
953
998
  event_streamer = _AstreamEventsCallbackHandler(
954
999
  include_names=include_names,
955
1000
  include_types=include_types,
@@ -1010,7 +1055,7 @@ async def _astream_events_implementation_v2(
1010
1055
  continue
1011
1056
 
1012
1057
  # If it's the end event corresponding to the root runnable
1013
- # we dont include the input in the event since it's guaranteed
1058
+ # we don't include the input in the event since it's guaranteed
1014
1059
  # to be included in the first event.
1015
1060
  if (
1016
1061
  event["run_id"] == first_event_run_id