langchain-core 0.3.71__py3-none-any.whl → 0.4.0.dev0__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.
Files changed (84) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/beta_decorator.py +1 -0
  3. langchain_core/_api/deprecation.py +2 -0
  4. langchain_core/beta/runnables/context.py +1 -0
  5. langchain_core/callbacks/base.py +23 -14
  6. langchain_core/callbacks/file.py +1 -0
  7. langchain_core/callbacks/manager.py +145 -19
  8. langchain_core/callbacks/streaming_stdout.py +4 -3
  9. langchain_core/callbacks/usage.py +15 -3
  10. langchain_core/chat_history.py +1 -0
  11. langchain_core/document_loaders/langsmith.py +2 -1
  12. langchain_core/documents/base.py +2 -0
  13. langchain_core/embeddings/fake.py +2 -0
  14. langchain_core/indexing/api.py +10 -0
  15. langchain_core/language_models/_utils.py +37 -0
  16. langchain_core/language_models/base.py +4 -1
  17. langchain_core/language_models/chat_models.py +48 -27
  18. langchain_core/language_models/fake_chat_models.py +71 -1
  19. langchain_core/language_models/llms.py +1 -0
  20. langchain_core/memory.py +1 -0
  21. langchain_core/messages/__init__.py +54 -0
  22. langchain_core/messages/ai.py +31 -18
  23. langchain_core/messages/content_blocks.py +1349 -69
  24. langchain_core/messages/human.py +1 -0
  25. langchain_core/messages/modifier.py +1 -1
  26. langchain_core/messages/tool.py +8 -83
  27. langchain_core/messages/utils.py +221 -6
  28. langchain_core/output_parsers/base.py +51 -14
  29. langchain_core/output_parsers/json.py +5 -2
  30. langchain_core/output_parsers/list.py +7 -2
  31. langchain_core/output_parsers/openai_functions.py +29 -5
  32. langchain_core/output_parsers/openai_tools.py +90 -47
  33. langchain_core/output_parsers/pydantic.py +3 -2
  34. langchain_core/output_parsers/transform.py +53 -12
  35. langchain_core/output_parsers/xml.py +14 -5
  36. langchain_core/outputs/llm_result.py +4 -1
  37. langchain_core/prompt_values.py +111 -7
  38. langchain_core/prompts/base.py +4 -0
  39. langchain_core/prompts/chat.py +3 -0
  40. langchain_core/prompts/few_shot.py +1 -0
  41. langchain_core/prompts/few_shot_with_templates.py +1 -0
  42. langchain_core/prompts/image.py +1 -0
  43. langchain_core/prompts/pipeline.py +1 -0
  44. langchain_core/prompts/prompt.py +1 -0
  45. langchain_core/prompts/structured.py +1 -0
  46. langchain_core/rate_limiters.py +1 -0
  47. langchain_core/retrievers.py +3 -0
  48. langchain_core/runnables/base.py +75 -57
  49. langchain_core/runnables/branch.py +1 -0
  50. langchain_core/runnables/config.py +2 -2
  51. langchain_core/runnables/configurable.py +2 -1
  52. langchain_core/runnables/fallbacks.py +3 -7
  53. langchain_core/runnables/graph.py +5 -3
  54. langchain_core/runnables/graph_ascii.py +1 -0
  55. langchain_core/runnables/graph_mermaid.py +1 -0
  56. langchain_core/runnables/history.py +1 -0
  57. langchain_core/runnables/passthrough.py +3 -0
  58. langchain_core/runnables/retry.py +1 -0
  59. langchain_core/runnables/router.py +1 -0
  60. langchain_core/runnables/schema.py +1 -0
  61. langchain_core/stores.py +3 -0
  62. langchain_core/tools/base.py +43 -11
  63. langchain_core/tools/convert.py +25 -3
  64. langchain_core/tools/retriever.py +8 -1
  65. langchain_core/tools/structured.py +10 -1
  66. langchain_core/tracers/base.py +14 -7
  67. langchain_core/tracers/context.py +1 -1
  68. langchain_core/tracers/core.py +27 -4
  69. langchain_core/tracers/event_stream.py +14 -3
  70. langchain_core/tracers/langchain.py +14 -3
  71. langchain_core/tracers/log_stream.py +4 -1
  72. langchain_core/utils/aiter.py +5 -0
  73. langchain_core/utils/function_calling.py +2 -1
  74. langchain_core/utils/iter.py +1 -0
  75. langchain_core/utils/json_schema.py +1 -1
  76. langchain_core/v1/__init__.py +1 -0
  77. langchain_core/v1/chat_models.py +1047 -0
  78. langchain_core/v1/messages.py +755 -0
  79. langchain_core/vectorstores/base.py +1 -0
  80. langchain_core/version.py +1 -1
  81. {langchain_core-0.3.71.dist-info → langchain_core-0.4.0.dev0.dist-info}/METADATA +1 -1
  82. {langchain_core-0.3.71.dist-info → langchain_core-0.4.0.dev0.dist-info}/RECORD +84 -81
  83. {langchain_core-0.3.71.dist-info → langchain_core-0.4.0.dev0.dist-info}/WHEEL +0 -0
  84. {langchain_core-0.3.71.dist-info → langchain_core-0.4.0.dev0.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,7 @@ The interfaces for core components like chat models, LLMs, vector stores, retrie
4
4
  and more are defined here. The universal invocation protocol (Runnables) along with
5
5
  a syntax for combining components (LangChain Expression Language) are also defined here.
6
6
 
7
- No third-party integrations are defined here. The dependencies are kept purposefully
7
+ **No third-party integrations are defined here.** The dependencies are kept purposefully
8
8
  very lightweight.
9
9
  """
10
10
 
@@ -70,6 +70,7 @@ def beta(
70
70
  @beta
71
71
  def the_function_to_annotate():
72
72
  pass
73
+
73
74
  """
74
75
 
75
76
  def beta(
@@ -136,6 +136,7 @@ def deprecated(
136
136
  @deprecated('1.4.0')
137
137
  def the_function_to_deprecate():
138
138
  pass
139
+
139
140
  """
140
141
  _validate_deprecation_params(
141
142
  removal, alternative, alternative_import, pending=pending
@@ -549,6 +550,7 @@ def rename_parameter(
549
550
 
550
551
  @_api.rename_parameter("3.1", "bad_name", "good_name")
551
552
  def func(good_name): ...
553
+
552
554
  """
553
555
 
554
556
  def decorator(f: Callable[_P, _R]) -> Callable[_P, _R]:
@@ -363,6 +363,7 @@ class Context:
363
363
  print(output["result"]) # Output: "hello"
364
364
  print(output["context"]) # Output: "What's your name?"
365
365
  print(output["input"]) # Output: "What's your name?
366
+
366
367
  """
367
368
 
368
369
  @staticmethod
@@ -7,6 +7,8 @@ from typing import TYPE_CHECKING, Any, Optional, Union
7
7
 
8
8
  from typing_extensions import Self
9
9
 
10
+ from langchain_core.v1.messages import AIMessage, AIMessageChunk, MessageV1
11
+
10
12
  if TYPE_CHECKING:
11
13
  from collections.abc import Sequence
12
14
  from uuid import UUID
@@ -66,7 +68,9 @@ class LLMManagerMixin:
66
68
  self,
67
69
  token: str,
68
70
  *,
69
- chunk: Optional[Union[GenerationChunk, ChatGenerationChunk]] = None,
71
+ chunk: Optional[
72
+ Union[GenerationChunk, ChatGenerationChunk, AIMessageChunk]
73
+ ] = None,
70
74
  run_id: UUID,
71
75
  parent_run_id: Optional[UUID] = None,
72
76
  **kwargs: Any,
@@ -75,8 +79,8 @@ class LLMManagerMixin:
75
79
 
76
80
  Args:
77
81
  token (str): The new token.
78
- chunk (GenerationChunk | ChatGenerationChunk): The new generated chunk,
79
- containing content and other information.
82
+ chunk (GenerationChunk | ChatGenerationChunk | AIMessageChunk): The new
83
+ generated chunk, containing content and other information.
80
84
  run_id (UUID): The run ID. This is the ID of the current run.
81
85
  parent_run_id (UUID): The parent run ID. This is the ID of the parent run.
82
86
  kwargs (Any): Additional keyword arguments.
@@ -84,7 +88,7 @@ class LLMManagerMixin:
84
88
 
85
89
  def on_llm_end(
86
90
  self,
87
- response: LLMResult,
91
+ response: Union[LLMResult, AIMessage],
88
92
  *,
89
93
  run_id: UUID,
90
94
  parent_run_id: Optional[UUID] = None,
@@ -93,7 +97,7 @@ class LLMManagerMixin:
93
97
  """Run when LLM ends running.
94
98
 
95
99
  Args:
96
- response (LLMResult): The response which was generated.
100
+ response (LLMResult | AIMessage): The response which was generated.
97
101
  run_id (UUID): The run ID. This is the ID of the current run.
98
102
  parent_run_id (UUID): The parent run ID. This is the ID of the parent run.
99
103
  kwargs (Any): Additional keyword arguments.
@@ -261,7 +265,7 @@ class CallbackManagerMixin:
261
265
  def on_chat_model_start(
262
266
  self,
263
267
  serialized: dict[str, Any],
264
- messages: list[list[BaseMessage]],
268
+ messages: Union[list[list[BaseMessage]], list[MessageV1]],
265
269
  *,
266
270
  run_id: UUID,
267
271
  parent_run_id: Optional[UUID] = None,
@@ -439,6 +443,9 @@ class BaseCallbackHandler(
439
443
  run_inline: bool = False
440
444
  """Whether to run the callback inline."""
441
445
 
446
+ accepts_new_messages: bool = False
447
+ """Whether the callback accepts new message format."""
448
+
442
449
  @property
443
450
  def ignore_llm(self) -> bool:
444
451
  """Whether to ignore LLM callbacks."""
@@ -509,7 +516,7 @@ class AsyncCallbackHandler(BaseCallbackHandler):
509
516
  async def on_chat_model_start(
510
517
  self,
511
518
  serialized: dict[str, Any],
512
- messages: list[list[BaseMessage]],
519
+ messages: Union[list[list[BaseMessage]], list[MessageV1]],
513
520
  *,
514
521
  run_id: UUID,
515
522
  parent_run_id: Optional[UUID] = None,
@@ -540,7 +547,9 @@ class AsyncCallbackHandler(BaseCallbackHandler):
540
547
  self,
541
548
  token: str,
542
549
  *,
543
- chunk: Optional[Union[GenerationChunk, ChatGenerationChunk]] = None,
550
+ chunk: Optional[
551
+ Union[GenerationChunk, ChatGenerationChunk, AIMessageChunk]
552
+ ] = None,
544
553
  run_id: UUID,
545
554
  parent_run_id: Optional[UUID] = None,
546
555
  tags: Optional[list[str]] = None,
@@ -550,8 +559,8 @@ class AsyncCallbackHandler(BaseCallbackHandler):
550
559
 
551
560
  Args:
552
561
  token (str): The new token.
553
- chunk (GenerationChunk | ChatGenerationChunk): The new generated chunk,
554
- containing content and other information.
562
+ chunk (GenerationChunk | ChatGenerationChunk | AIMessageChunk): The new
563
+ generated chunk, containing content and other information.
555
564
  run_id (UUID): The run ID. This is the ID of the current run.
556
565
  parent_run_id (UUID): The parent run ID. This is the ID of the parent run.
557
566
  tags (Optional[list[str]]): The tags.
@@ -560,7 +569,7 @@ class AsyncCallbackHandler(BaseCallbackHandler):
560
569
 
561
570
  async def on_llm_end(
562
571
  self,
563
- response: LLMResult,
572
+ response: Union[LLMResult, AIMessage],
564
573
  *,
565
574
  run_id: UUID,
566
575
  parent_run_id: Optional[UUID] = None,
@@ -570,7 +579,7 @@ class AsyncCallbackHandler(BaseCallbackHandler):
570
579
  """Run when LLM ends running.
571
580
 
572
581
  Args:
573
- response (LLMResult): The response which was generated.
582
+ response (LLMResult | AIMessage): The response which was generated.
574
583
  run_id (UUID): The run ID. This is the ID of the current run.
575
584
  parent_run_id (UUID): The parent run ID. This is the ID of the parent run.
576
585
  tags (Optional[list[str]]): The tags.
@@ -594,8 +603,8 @@ class AsyncCallbackHandler(BaseCallbackHandler):
594
603
  parent_run_id: The parent run ID. This is the ID of the parent run.
595
604
  tags: The tags.
596
605
  kwargs (Any): Additional keyword arguments.
597
- - response (LLMResult): The response which was generated before
598
- the error occurred.
606
+ - response (LLMResult | AIMessage): The response which was generated
607
+ before the error occurred.
599
608
  """
600
609
 
601
610
  async def on_chain_start(
@@ -53,6 +53,7 @@ class FileCallbackHandler(BaseCallbackHandler):
53
53
  When not used as a context manager, a deprecation warning will be issued
54
54
  on first use. The file will be opened immediately in ``__init__`` and closed
55
55
  in ``__del__`` or when ``close()`` is called explicitly.
56
+
56
57
  """
57
58
 
58
59
  def __init__(
@@ -37,8 +37,16 @@ from langchain_core.callbacks.base import (
37
37
  )
38
38
  from langchain_core.callbacks.stdout import StdOutCallbackHandler
39
39
  from langchain_core.messages import BaseMessage, get_buffer_string
40
+ from langchain_core.messages.utils import convert_from_v1_message
41
+ from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, LLMResult
40
42
  from langchain_core.tracers.schemas import Run
41
43
  from langchain_core.utils.env import env_var_is_set
44
+ from langchain_core.v1.messages import (
45
+ AIMessage,
46
+ AIMessageChunk,
47
+ MessageV1,
48
+ MessageV1Types,
49
+ )
42
50
 
43
51
  if TYPE_CHECKING:
44
52
  from collections.abc import AsyncGenerator, Coroutine, Generator, Sequence
@@ -47,7 +55,7 @@ if TYPE_CHECKING:
47
55
 
48
56
  from langchain_core.agents import AgentAction, AgentFinish
49
57
  from langchain_core.documents import Document
50
- from langchain_core.outputs import ChatGenerationChunk, GenerationChunk, LLMResult
58
+ from langchain_core.outputs import GenerationChunk
51
59
  from langchain_core.runnables.config import RunnableConfig
52
60
 
53
61
  logger = logging.getLogger(__name__)
@@ -105,6 +113,7 @@ def trace_as_chain_group(
105
113
  # Use the callback manager for the chain group
106
114
  res = llm.invoke(llm_input, {"callbacks": manager})
107
115
  manager.on_chain_end({"output": res})
116
+
108
117
  """ # noqa: E501
109
118
  from langchain_core.tracers.context import _get_trace_callbacks
110
119
 
@@ -186,6 +195,7 @@ async def atrace_as_chain_group(
186
195
  # Use the async callback manager for the chain group
187
196
  res = await llm.ainvoke(llm_input, {"callbacks": manager})
188
197
  await manager.on_chain_end({"output": res})
198
+
189
199
  """ # noqa: E501
190
200
  from langchain_core.tracers.context import _get_trace_callbacks
191
201
 
@@ -241,6 +251,46 @@ def shielded(func: Func) -> Func:
241
251
  return cast("Func", wrapped)
242
252
 
243
253
 
254
+ def _convert_llm_events(
255
+ event_name: str, args: tuple[Any, ...], kwargs: dict[str, Any]
256
+ ) -> tuple[tuple[Any, ...], dict[str, Any]]:
257
+ args_list = list(args)
258
+ if (
259
+ event_name == "on_chat_model_start"
260
+ and isinstance(args_list[1], list)
261
+ and args_list[1]
262
+ and isinstance(args_list[1][0], MessageV1Types)
263
+ ):
264
+ batch = [
265
+ convert_from_v1_message(item)
266
+ for item in args_list[1]
267
+ if isinstance(item, MessageV1Types)
268
+ ]
269
+ args_list[1] = [batch]
270
+ elif (
271
+ event_name == "on_llm_new_token"
272
+ and "chunk" in kwargs
273
+ and isinstance(kwargs["chunk"], MessageV1Types)
274
+ ):
275
+ chunk = kwargs["chunk"]
276
+ kwargs["chunk"] = ChatGenerationChunk(text=chunk.text, message=chunk)
277
+ elif event_name == "on_llm_end" and isinstance(args_list[0], MessageV1Types):
278
+ args_list[0] = LLMResult(
279
+ generations=[
280
+ [
281
+ ChatGeneration(
282
+ text=args_list[0].text,
283
+ message=convert_from_v1_message(args_list[0]),
284
+ )
285
+ ]
286
+ ]
287
+ )
288
+ else:
289
+ pass
290
+
291
+ return tuple(args_list), kwargs
292
+
293
+
244
294
  def handle_event(
245
295
  handlers: list[BaseCallbackHandler],
246
296
  event_name: str,
@@ -269,6 +319,8 @@ def handle_event(
269
319
  if ignore_condition_name is None or not getattr(
270
320
  handler, ignore_condition_name
271
321
  ):
322
+ if not handler.accepts_new_messages:
323
+ args, kwargs = _convert_llm_events(event_name, args, kwargs)
272
324
  event = getattr(handler, event_name)(*args, **kwargs)
273
325
  if asyncio.iscoroutine(event):
274
326
  coros.append(event)
@@ -363,6 +415,8 @@ async def _ahandle_event_for_handler(
363
415
  ) -> None:
364
416
  try:
365
417
  if ignore_condition_name is None or not getattr(handler, ignore_condition_name):
418
+ if not handler.accepts_new_messages:
419
+ args, kwargs = _convert_llm_events(event_name, args, kwargs)
366
420
  event = getattr(handler, event_name)
367
421
  if asyncio.iscoroutinefunction(event):
368
422
  await event(*args, **kwargs)
@@ -672,7 +726,9 @@ class CallbackManagerForLLMRun(RunManager, LLMManagerMixin):
672
726
  self,
673
727
  token: str,
674
728
  *,
675
- chunk: Optional[Union[GenerationChunk, ChatGenerationChunk]] = None,
729
+ chunk: Optional[
730
+ Union[GenerationChunk, ChatGenerationChunk, AIMessageChunk]
731
+ ] = None,
676
732
  **kwargs: Any,
677
733
  ) -> None:
678
734
  """Run when LLM generates a new token.
@@ -697,11 +753,11 @@ class CallbackManagerForLLMRun(RunManager, LLMManagerMixin):
697
753
  **kwargs,
698
754
  )
699
755
 
700
- def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
756
+ def on_llm_end(self, response: Union[LLMResult, AIMessage], **kwargs: Any) -> None:
701
757
  """Run when LLM ends running.
702
758
 
703
759
  Args:
704
- response (LLMResult): The LLM result.
760
+ response (LLMResult | AIMessage): The LLM result.
705
761
  **kwargs (Any): Additional keyword arguments.
706
762
  """
707
763
  if not self.handlers:
@@ -727,8 +783,8 @@ class CallbackManagerForLLMRun(RunManager, LLMManagerMixin):
727
783
  Args:
728
784
  error (Exception or KeyboardInterrupt): The error.
729
785
  kwargs (Any): Additional keyword arguments.
730
- - response (LLMResult): The response which was generated before
731
- the error occurred.
786
+ - response (LLMResult | AIMessage): The response which was generated
787
+ before the error occurred.
732
788
  """
733
789
  if not self.handlers:
734
790
  return
@@ -768,7 +824,9 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin):
768
824
  self,
769
825
  token: str,
770
826
  *,
771
- chunk: Optional[Union[GenerationChunk, ChatGenerationChunk]] = None,
827
+ chunk: Optional[
828
+ Union[GenerationChunk, ChatGenerationChunk, AIMessageChunk]
829
+ ] = None,
772
830
  **kwargs: Any,
773
831
  ) -> None:
774
832
  """Run when LLM generates a new token.
@@ -794,11 +852,13 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin):
794
852
  )
795
853
 
796
854
  @shielded
797
- async def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
855
+ async def on_llm_end(
856
+ self, response: Union[LLMResult, AIMessage], **kwargs: Any
857
+ ) -> None:
798
858
  """Run when LLM ends running.
799
859
 
800
860
  Args:
801
- response (LLMResult): The LLM result.
861
+ response (LLMResult | AIMessage): The LLM result.
802
862
  **kwargs (Any): Additional keyword arguments.
803
863
  """
804
864
  if not self.handlers:
@@ -825,11 +885,8 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin):
825
885
  Args:
826
886
  error (Exception or KeyboardInterrupt): The error.
827
887
  kwargs (Any): Additional keyword arguments.
828
- - response (LLMResult): The response which was generated before
829
- the error occurred.
830
-
831
-
832
-
888
+ - response (LLMResult | AIMessage): The response which was generated
889
+ before the error occurred.
833
890
  """
834
891
  if not self.handlers:
835
892
  return
@@ -1352,7 +1409,7 @@ class CallbackManager(BaseCallbackManager):
1352
1409
  def on_chat_model_start(
1353
1410
  self,
1354
1411
  serialized: dict[str, Any],
1355
- messages: list[list[BaseMessage]],
1412
+ messages: Union[list[list[BaseMessage]], list[MessageV1]],
1356
1413
  run_id: Optional[UUID] = None,
1357
1414
  **kwargs: Any,
1358
1415
  ) -> list[CallbackManagerForLLMRun]:
@@ -1360,7 +1417,7 @@ class CallbackManager(BaseCallbackManager):
1360
1417
 
1361
1418
  Args:
1362
1419
  serialized (dict[str, Any]): The serialized LLM.
1363
- messages (list[list[BaseMessage]]): The list of messages.
1420
+ messages (list[list[BaseMessage | MessageV1]]): The list of messages.
1364
1421
  run_id (UUID, optional): The ID of the run. Defaults to None.
1365
1422
  **kwargs (Any): Additional keyword arguments.
1366
1423
 
@@ -1368,6 +1425,32 @@ class CallbackManager(BaseCallbackManager):
1368
1425
  list[CallbackManagerForLLMRun]: A callback manager for each
1369
1426
  list of messages as an LLM run.
1370
1427
  """
1428
+ if messages and isinstance(messages[0], MessageV1Types):
1429
+ run_id_ = run_id if run_id is not None else uuid.uuid4()
1430
+ handle_event(
1431
+ self.handlers,
1432
+ "on_chat_model_start",
1433
+ "ignore_chat_model",
1434
+ serialized,
1435
+ messages,
1436
+ run_id=run_id_,
1437
+ parent_run_id=self.parent_run_id,
1438
+ tags=self.tags,
1439
+ metadata=self.metadata,
1440
+ **kwargs,
1441
+ )
1442
+ return [
1443
+ CallbackManagerForLLMRun(
1444
+ run_id=run_id_,
1445
+ handlers=self.handlers,
1446
+ inheritable_handlers=self.inheritable_handlers,
1447
+ parent_run_id=self.parent_run_id,
1448
+ tags=self.tags,
1449
+ inheritable_tags=self.inheritable_tags,
1450
+ metadata=self.metadata,
1451
+ inheritable_metadata=self.inheritable_metadata,
1452
+ )
1453
+ ]
1371
1454
  managers = []
1372
1455
  for message_list in messages:
1373
1456
  if run_id is not None:
@@ -1862,7 +1945,7 @@ class AsyncCallbackManager(BaseCallbackManager):
1862
1945
  async def on_chat_model_start(
1863
1946
  self,
1864
1947
  serialized: dict[str, Any],
1865
- messages: list[list[BaseMessage]],
1948
+ messages: Union[list[list[BaseMessage]], list[MessageV1]],
1866
1949
  run_id: Optional[UUID] = None,
1867
1950
  **kwargs: Any,
1868
1951
  ) -> list[AsyncCallbackManagerForLLMRun]:
@@ -1870,7 +1953,7 @@ class AsyncCallbackManager(BaseCallbackManager):
1870
1953
 
1871
1954
  Args:
1872
1955
  serialized (dict[str, Any]): The serialized LLM.
1873
- messages (list[list[BaseMessage]]): The list of messages.
1956
+ messages (list[list[BaseMessage | MessageV1]]): The list of messages.
1874
1957
  run_id (UUID, optional): The ID of the run. Defaults to None.
1875
1958
  **kwargs (Any): Additional keyword arguments.
1876
1959
 
@@ -1879,10 +1962,51 @@ class AsyncCallbackManager(BaseCallbackManager):
1879
1962
  async callback managers, one for each LLM Run
1880
1963
  corresponding to each inner message list.
1881
1964
  """
1965
+ if messages and isinstance(messages[0], MessageV1Types):
1966
+ run_id_ = run_id if run_id is not None else uuid.uuid4()
1967
+ inline_tasks = []
1968
+ non_inline_tasks = []
1969
+ for handler in self.handlers:
1970
+ task = ahandle_event(
1971
+ [handler],
1972
+ "on_chat_model_start",
1973
+ "ignore_chat_model",
1974
+ serialized,
1975
+ messages,
1976
+ run_id=run_id_,
1977
+ parent_run_id=self.parent_run_id,
1978
+ tags=self.tags,
1979
+ metadata=self.metadata,
1980
+ **kwargs,
1981
+ )
1982
+ if handler.run_inline:
1983
+ inline_tasks.append(task)
1984
+ else:
1985
+ non_inline_tasks.append(task)
1986
+ managers = [
1987
+ AsyncCallbackManagerForLLMRun(
1988
+ run_id=run_id_,
1989
+ handlers=self.handlers,
1990
+ inheritable_handlers=self.inheritable_handlers,
1991
+ parent_run_id=self.parent_run_id,
1992
+ tags=self.tags,
1993
+ inheritable_tags=self.inheritable_tags,
1994
+ metadata=self.metadata,
1995
+ inheritable_metadata=self.inheritable_metadata,
1996
+ )
1997
+ ]
1998
+ # Run inline tasks sequentially
1999
+ for task in inline_tasks:
2000
+ await task
2001
+
2002
+ # Run non-inline tasks concurrently
2003
+ if non_inline_tasks:
2004
+ await asyncio.gather(*non_inline_tasks)
2005
+
2006
+ return managers
1882
2007
  inline_tasks = []
1883
2008
  non_inline_tasks = []
1884
2009
  managers = []
1885
-
1886
2010
  for message_list in messages:
1887
2011
  if run_id is not None:
1888
2012
  run_id_ = run_id
@@ -2575,6 +2699,7 @@ async def adispatch_custom_event(
2575
2699
  behalf.
2576
2700
 
2577
2701
  .. versionadded:: 0.2.15
2702
+
2578
2703
  """
2579
2704
  from langchain_core.runnables.config import (
2580
2705
  ensure_config,
@@ -2645,6 +2770,7 @@ def dispatch_custom_event(
2645
2770
  foo_.invoke({"a": "1"}, {"callbacks": [CustomCallbackManager()]})
2646
2771
 
2647
2772
  .. versionadded:: 0.2.15
2773
+
2648
2774
  """
2649
2775
  from langchain_core.runnables.config import (
2650
2776
  ensure_config,
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import sys
6
- from typing import TYPE_CHECKING, Any
6
+ from typing import TYPE_CHECKING, Any, Union
7
7
 
8
8
  from typing_extensions import override
9
9
 
@@ -13,6 +13,7 @@ if TYPE_CHECKING:
13
13
  from langchain_core.agents import AgentAction, AgentFinish
14
14
  from langchain_core.messages import BaseMessage
15
15
  from langchain_core.outputs import LLMResult
16
+ from langchain_core.v1.messages import AIMessage, MessageV1
16
17
 
17
18
 
18
19
  class StreamingStdOutCallbackHandler(BaseCallbackHandler):
@@ -32,7 +33,7 @@ class StreamingStdOutCallbackHandler(BaseCallbackHandler):
32
33
  def on_chat_model_start(
33
34
  self,
34
35
  serialized: dict[str, Any],
35
- messages: list[list[BaseMessage]],
36
+ messages: Union[list[list[BaseMessage]], list[MessageV1]],
36
37
  **kwargs: Any,
37
38
  ) -> None:
38
39
  """Run when LLM starts running.
@@ -54,7 +55,7 @@ class StreamingStdOutCallbackHandler(BaseCallbackHandler):
54
55
  sys.stdout.write(token)
55
56
  sys.stdout.flush()
56
57
 
57
- def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
58
+ def on_llm_end(self, response: Union[LLMResult, AIMessage], **kwargs: Any) -> None:
58
59
  """Run when LLM ends running.
59
60
 
60
61
  Args:
@@ -4,14 +4,16 @@ import threading
4
4
  from collections.abc import Generator
5
5
  from contextlib import contextmanager
6
6
  from contextvars import ContextVar
7
- from typing import Any, Optional
7
+ from typing import Any, Optional, Union
8
8
 
9
9
  from typing_extensions import override
10
10
 
11
11
  from langchain_core.callbacks import BaseCallbackHandler
12
12
  from langchain_core.messages import AIMessage
13
13
  from langchain_core.messages.ai import UsageMetadata, add_usage
14
+ from langchain_core.messages.utils import convert_from_v1_message
14
15
  from langchain_core.outputs import ChatGeneration, LLMResult
16
+ from langchain_core.v1.messages import AIMessage as AIMessageV1
15
17
 
16
18
 
17
19
  class UsageMetadataCallbackHandler(BaseCallbackHandler):
@@ -44,6 +46,7 @@ class UsageMetadataCallbackHandler(BaseCallbackHandler):
44
46
  'input_token_details': {'cache_read': 0, 'cache_creation': 0}}}
45
47
 
46
48
  .. versionadded:: 0.3.49
49
+
47
50
  """
48
51
 
49
52
  def __init__(self) -> None:
@@ -57,9 +60,17 @@ class UsageMetadataCallbackHandler(BaseCallbackHandler):
57
60
  return str(self.usage_metadata)
58
61
 
59
62
  @override
60
- def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
63
+ def on_llm_end(
64
+ self, response: Union[LLMResult, AIMessageV1], **kwargs: Any
65
+ ) -> None:
61
66
  """Collect token usage."""
62
67
  # Check for usage_metadata (langchain-core >= 0.2.2)
68
+ if isinstance(response, AIMessageV1):
69
+ response = LLMResult(
70
+ generations=[
71
+ [ChatGeneration(message=convert_from_v1_message(response))]
72
+ ]
73
+ )
63
74
  try:
64
75
  generation = response.generations[0][0]
65
76
  except IndexError:
@@ -98,7 +109,7 @@ def get_usage_metadata_callback(
98
109
 
99
110
  Args:
100
111
  name (str): The name of the context variable. Defaults to
101
- ``"usage_metadata_callback"``.
112
+ ``'usage_metadata_callback'``.
102
113
 
103
114
  Example:
104
115
  .. code-block:: python
@@ -127,6 +138,7 @@ def get_usage_metadata_callback(
127
138
  'input_token_details': {'cache_read': 0, 'cache_creation': 0}}}
128
139
 
129
140
  .. versionadded:: 0.3.49
141
+
130
142
  """
131
143
  from langchain_core.tracers.context import register_configure_hook
132
144
 
@@ -91,6 +91,7 @@ class BaseChatMessageHistory(ABC):
91
91
  def clear(self):
92
92
  with open(os.path.join(storage_path, session_id), "w") as f:
93
93
  f.write("[]")
94
+
94
95
  """
95
96
 
96
97
  messages: list[BaseMessage]
@@ -36,6 +36,7 @@ class LangSmithLoader(BaseLoader):
36
36
  # -> [Document("...", metadata={"inputs": {...}, "outputs": {...}, ...}), ...]
37
37
 
38
38
  .. versionadded:: 0.2.34
39
+
39
40
  """ # noqa: E501
40
41
 
41
42
  def __init__(
@@ -61,7 +62,7 @@ class LangSmithLoader(BaseLoader):
61
62
  Args:
62
63
  dataset_id: The ID of the dataset to filter by. Defaults to None.
63
64
  dataset_name: The name of the dataset to filter by. Defaults to None.
64
- content_key: The inputs key to set as Document page content. ``"."`` characters
65
+ content_key: The inputs key to set as Document page content. ``'.'`` characters
65
66
  are interpreted as nested keys. E.g. ``content_key="first.second"`` will
66
67
  result in
67
68
  ``Document(page_content=format_content(example.inputs["first"]["second"]))``
@@ -102,6 +102,7 @@ class Blob(BaseMedia):
102
102
  # Read the blob as a byte stream
103
103
  with blob.as_bytes_io() as f:
104
104
  print(f.read())
105
+
105
106
  """
106
107
 
107
108
  data: Union[bytes, str, None] = None
@@ -265,6 +266,7 @@ class Document(BaseMedia):
265
266
  page_content="Hello, world!",
266
267
  metadata={"source": "https://example.com"}
267
268
  )
269
+
268
270
  """
269
271
 
270
272
  page_content: str
@@ -46,6 +46,7 @@ class FakeEmbeddings(Embeddings, BaseModel):
46
46
 
47
47
  2
48
48
  [-0.5670477847544458, -0.31403828652395727, -0.5840547508955257]
49
+
49
50
  """
50
51
 
51
52
  size: int
@@ -103,6 +104,7 @@ class DeterministicFakeEmbedding(Embeddings, BaseModel):
103
104
 
104
105
  2
105
106
  [-0.5670477847544458, -0.31403828652395727, -0.5840547508955257]
107
+
106
108
  """
107
109
 
108
110
  size: int
@@ -444,6 +444,9 @@ def index(
444
444
  scoped_full_cleanup_source_ids: set[str] = set()
445
445
 
446
446
  for doc_batch in _batch(batch_size, doc_iterator):
447
+ # Track original batch size before deduplication
448
+ original_batch_size = len(doc_batch)
449
+
447
450
  hashed_docs = list(
448
451
  _deduplicate_in_order(
449
452
  [
@@ -452,6 +455,8 @@ def index(
452
455
  ]
453
456
  )
454
457
  )
458
+ # Count documents removed by within-batch deduplication
459
+ num_skipped += original_batch_size - len(hashed_docs)
455
460
 
456
461
  source_ids: Sequence[Optional[str]] = [
457
462
  source_id_assigner(hashed_doc) for hashed_doc in hashed_docs
@@ -784,6 +789,9 @@ async def aindex(
784
789
  scoped_full_cleanup_source_ids: set[str] = set()
785
790
 
786
791
  async for doc_batch in _abatch(batch_size, async_doc_iterator):
792
+ # Track original batch size before deduplication
793
+ original_batch_size = len(doc_batch)
794
+
787
795
  hashed_docs = list(
788
796
  _deduplicate_in_order(
789
797
  [
@@ -792,6 +800,8 @@ async def aindex(
792
800
  ]
793
801
  )
794
802
  )
803
+ # Count documents removed by within-batch deduplication
804
+ num_skipped += original_batch_size - len(hashed_docs)
795
805
 
796
806
  source_ids: Sequence[Optional[str]] = [
797
807
  source_id_assigner(doc) for doc in hashed_docs