langchain-core 1.0.0a6__py3-none-any.whl → 1.0.3__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 (165) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/__init__.py +3 -4
  3. langchain_core/_api/beta_decorator.py +23 -26
  4. langchain_core/_api/deprecation.py +51 -64
  5. langchain_core/_api/path.py +3 -6
  6. langchain_core/_import_utils.py +3 -4
  7. langchain_core/agents.py +20 -22
  8. langchain_core/caches.py +65 -66
  9. langchain_core/callbacks/__init__.py +1 -8
  10. langchain_core/callbacks/base.py +321 -336
  11. langchain_core/callbacks/file.py +44 -44
  12. langchain_core/callbacks/manager.py +436 -513
  13. langchain_core/callbacks/stdout.py +29 -30
  14. langchain_core/callbacks/streaming_stdout.py +32 -32
  15. langchain_core/callbacks/usage.py +60 -57
  16. langchain_core/chat_history.py +53 -68
  17. langchain_core/document_loaders/base.py +27 -25
  18. langchain_core/document_loaders/blob_loaders.py +1 -1
  19. langchain_core/document_loaders/langsmith.py +44 -48
  20. langchain_core/documents/__init__.py +23 -3
  21. langchain_core/documents/base.py +98 -90
  22. langchain_core/documents/compressor.py +10 -10
  23. langchain_core/documents/transformers.py +34 -35
  24. langchain_core/embeddings/fake.py +50 -54
  25. langchain_core/example_selectors/length_based.py +1 -1
  26. langchain_core/example_selectors/semantic_similarity.py +28 -32
  27. langchain_core/exceptions.py +21 -20
  28. langchain_core/globals.py +3 -151
  29. langchain_core/indexing/__init__.py +1 -1
  30. langchain_core/indexing/api.py +121 -126
  31. langchain_core/indexing/base.py +73 -75
  32. langchain_core/indexing/in_memory.py +4 -6
  33. langchain_core/language_models/__init__.py +14 -29
  34. langchain_core/language_models/_utils.py +58 -61
  35. langchain_core/language_models/base.py +53 -162
  36. langchain_core/language_models/chat_models.py +298 -387
  37. langchain_core/language_models/fake.py +11 -11
  38. langchain_core/language_models/fake_chat_models.py +42 -36
  39. langchain_core/language_models/llms.py +125 -235
  40. langchain_core/load/dump.py +9 -12
  41. langchain_core/load/load.py +18 -28
  42. langchain_core/load/mapping.py +2 -4
  43. langchain_core/load/serializable.py +42 -40
  44. langchain_core/messages/__init__.py +10 -16
  45. langchain_core/messages/ai.py +148 -148
  46. langchain_core/messages/base.py +53 -51
  47. langchain_core/messages/block_translators/__init__.py +19 -22
  48. langchain_core/messages/block_translators/anthropic.py +6 -6
  49. langchain_core/messages/block_translators/bedrock_converse.py +5 -5
  50. langchain_core/messages/block_translators/google_genai.py +10 -7
  51. langchain_core/messages/block_translators/google_vertexai.py +4 -32
  52. langchain_core/messages/block_translators/groq.py +117 -21
  53. langchain_core/messages/block_translators/langchain_v0.py +5 -5
  54. langchain_core/messages/block_translators/openai.py +11 -11
  55. langchain_core/messages/chat.py +2 -6
  56. langchain_core/messages/content.py +337 -328
  57. langchain_core/messages/function.py +6 -10
  58. langchain_core/messages/human.py +24 -31
  59. langchain_core/messages/modifier.py +2 -2
  60. langchain_core/messages/system.py +19 -29
  61. langchain_core/messages/tool.py +74 -90
  62. langchain_core/messages/utils.py +474 -504
  63. langchain_core/output_parsers/__init__.py +13 -10
  64. langchain_core/output_parsers/base.py +61 -61
  65. langchain_core/output_parsers/format_instructions.py +9 -4
  66. langchain_core/output_parsers/json.py +12 -10
  67. langchain_core/output_parsers/list.py +21 -23
  68. langchain_core/output_parsers/openai_functions.py +49 -47
  69. langchain_core/output_parsers/openai_tools.py +16 -21
  70. langchain_core/output_parsers/pydantic.py +13 -14
  71. langchain_core/output_parsers/string.py +5 -5
  72. langchain_core/output_parsers/transform.py +15 -17
  73. langchain_core/output_parsers/xml.py +35 -34
  74. langchain_core/outputs/__init__.py +1 -1
  75. langchain_core/outputs/chat_generation.py +18 -18
  76. langchain_core/outputs/chat_result.py +1 -3
  77. langchain_core/outputs/generation.py +10 -11
  78. langchain_core/outputs/llm_result.py +10 -10
  79. langchain_core/prompt_values.py +11 -17
  80. langchain_core/prompts/__init__.py +3 -27
  81. langchain_core/prompts/base.py +48 -56
  82. langchain_core/prompts/chat.py +275 -325
  83. langchain_core/prompts/dict.py +5 -5
  84. langchain_core/prompts/few_shot.py +81 -88
  85. langchain_core/prompts/few_shot_with_templates.py +11 -13
  86. langchain_core/prompts/image.py +12 -14
  87. langchain_core/prompts/loading.py +4 -6
  88. langchain_core/prompts/message.py +3 -3
  89. langchain_core/prompts/prompt.py +24 -39
  90. langchain_core/prompts/string.py +26 -10
  91. langchain_core/prompts/structured.py +49 -53
  92. langchain_core/rate_limiters.py +51 -60
  93. langchain_core/retrievers.py +61 -198
  94. langchain_core/runnables/base.py +1476 -1626
  95. langchain_core/runnables/branch.py +53 -57
  96. langchain_core/runnables/config.py +72 -89
  97. langchain_core/runnables/configurable.py +120 -137
  98. langchain_core/runnables/fallbacks.py +83 -79
  99. langchain_core/runnables/graph.py +91 -97
  100. langchain_core/runnables/graph_ascii.py +27 -28
  101. langchain_core/runnables/graph_mermaid.py +38 -50
  102. langchain_core/runnables/graph_png.py +15 -16
  103. langchain_core/runnables/history.py +135 -148
  104. langchain_core/runnables/passthrough.py +124 -150
  105. langchain_core/runnables/retry.py +46 -51
  106. langchain_core/runnables/router.py +25 -30
  107. langchain_core/runnables/schema.py +75 -80
  108. langchain_core/runnables/utils.py +60 -67
  109. langchain_core/stores.py +85 -121
  110. langchain_core/structured_query.py +8 -8
  111. langchain_core/sys_info.py +27 -29
  112. langchain_core/tools/__init__.py +1 -14
  113. langchain_core/tools/base.py +284 -229
  114. langchain_core/tools/convert.py +160 -155
  115. langchain_core/tools/render.py +10 -10
  116. langchain_core/tools/retriever.py +12 -11
  117. langchain_core/tools/simple.py +19 -24
  118. langchain_core/tools/structured.py +32 -39
  119. langchain_core/tracers/__init__.py +1 -9
  120. langchain_core/tracers/base.py +97 -99
  121. langchain_core/tracers/context.py +29 -52
  122. langchain_core/tracers/core.py +49 -53
  123. langchain_core/tracers/evaluation.py +11 -11
  124. langchain_core/tracers/event_stream.py +65 -64
  125. langchain_core/tracers/langchain.py +21 -21
  126. langchain_core/tracers/log_stream.py +45 -45
  127. langchain_core/tracers/memory_stream.py +3 -3
  128. langchain_core/tracers/root_listeners.py +16 -16
  129. langchain_core/tracers/run_collector.py +2 -4
  130. langchain_core/tracers/schemas.py +0 -129
  131. langchain_core/tracers/stdout.py +3 -3
  132. langchain_core/utils/__init__.py +1 -4
  133. langchain_core/utils/_merge.py +2 -2
  134. langchain_core/utils/aiter.py +57 -61
  135. langchain_core/utils/env.py +9 -9
  136. langchain_core/utils/function_calling.py +89 -186
  137. langchain_core/utils/html.py +7 -8
  138. langchain_core/utils/input.py +6 -6
  139. langchain_core/utils/interactive_env.py +1 -1
  140. langchain_core/utils/iter.py +36 -40
  141. langchain_core/utils/json.py +4 -3
  142. langchain_core/utils/json_schema.py +9 -9
  143. langchain_core/utils/mustache.py +8 -10
  144. langchain_core/utils/pydantic.py +33 -35
  145. langchain_core/utils/strings.py +6 -9
  146. langchain_core/utils/usage.py +1 -1
  147. langchain_core/utils/utils.py +66 -62
  148. langchain_core/vectorstores/base.py +182 -216
  149. langchain_core/vectorstores/in_memory.py +101 -176
  150. langchain_core/vectorstores/utils.py +5 -5
  151. langchain_core/version.py +1 -1
  152. langchain_core-1.0.3.dist-info/METADATA +69 -0
  153. langchain_core-1.0.3.dist-info/RECORD +172 -0
  154. {langchain_core-1.0.0a6.dist-info → langchain_core-1.0.3.dist-info}/WHEEL +1 -1
  155. langchain_core/memory.py +0 -120
  156. langchain_core/messages/block_translators/ollama.py +0 -47
  157. langchain_core/prompts/pipeline.py +0 -138
  158. langchain_core/pydantic_v1/__init__.py +0 -30
  159. langchain_core/pydantic_v1/dataclasses.py +0 -23
  160. langchain_core/pydantic_v1/main.py +0 -23
  161. langchain_core/tracers/langchain_v1.py +0 -31
  162. langchain_core/utils/loading.py +0 -35
  163. langchain_core-1.0.0a6.dist-info/METADATA +0 -67
  164. langchain_core-1.0.0a6.dist-info/RECORD +0 -181
  165. langchain_core-1.0.0a6.dist-info/entry_points.txt +0 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
5
+ from typing import TYPE_CHECKING, Any, cast, overload
6
6
 
7
7
  from pydantic import ConfigDict, Field
8
8
  from typing_extensions import Self
@@ -22,7 +22,7 @@ if TYPE_CHECKING:
22
22
 
23
23
  def _extract_reasoning_from_additional_kwargs(
24
24
  message: BaseMessage,
25
- ) -> Optional[types.ReasoningContentBlock]:
25
+ ) -> types.ReasoningContentBlock | None:
26
26
  """Extract `reasoning_content` from `additional_kwargs`.
27
27
 
28
28
  Handles reasoning content stored in various formats:
@@ -34,13 +34,11 @@ def _extract_reasoning_from_additional_kwargs(
34
34
  Returns:
35
35
  A `ReasoningContentBlock` if reasoning content is found, None otherwise.
36
36
  """
37
- from langchain_core.messages.content import create_reasoning_block # noqa: PLC0415
38
-
39
37
  additional_kwargs = getattr(message, "additional_kwargs", {})
40
38
 
41
39
  reasoning_content = additional_kwargs.get("reasoning_content")
42
40
  if reasoning_content is not None and isinstance(reasoning_content, str):
43
- return create_reasoning_block(reasoning=reasoning_content)
41
+ return {"type": "reasoning", "reasoning": reasoning_content}
44
42
 
45
43
  return None
46
44
 
@@ -50,13 +48,13 @@ class TextAccessor(str):
50
48
 
51
49
  Exists to maintain backward compatibility while transitioning from method-based to
52
50
  property-based text access in message objects. In LangChain <v1.0, message text was
53
- accessed via ``.text()`` method calls. In v1.0=<, the preferred pattern is property
54
- access via ``.text``.
51
+ accessed via `.text()` method calls. In v1.0=<, the preferred pattern is property
52
+ access via `.text`.
55
53
 
56
- Rather than breaking existing code immediately, ``TextAccessor`` allows both
54
+ Rather than breaking existing code immediately, `TextAccessor` allows both
57
55
  patterns:
58
- - Modern property access: ``message.text`` (returns string directly)
59
- - Legacy method access: ``message.text()`` (callable, emits deprecation warning)
56
+ - Modern property access: `message.text` (returns string directly)
57
+ - Legacy method access: `message.text()` (callable, emits deprecation warning)
60
58
 
61
59
  """
62
60
 
@@ -69,12 +67,12 @@ class TextAccessor(str):
69
67
  def __call__(self) -> str:
70
68
  """Enable method-style text access for backward compatibility.
71
69
 
72
- This method exists solely to support legacy code that calls ``.text()``
73
- as a method. New code should use property access (``.text``) instead.
70
+ This method exists solely to support legacy code that calls `.text()`
71
+ as a method. New code should use property access (`.text`) instead.
74
72
 
75
- .. deprecated:: 1.0.0
76
- Calling ``.text()`` as a method is deprecated. Use ``.text`` as a property
77
- instead. This method will be removed in 2.0.0.
73
+ !!! deprecated
74
+ As of `langchain-core` 1.0.0, calling `.text()` as a method is deprecated.
75
+ Use `.text` as a property instead. This method will be removed in 2.0.0.
78
76
 
79
77
  Returns:
80
78
  The string content, identical to property access.
@@ -94,11 +92,15 @@ class TextAccessor(str):
94
92
  class BaseMessage(Serializable):
95
93
  """Base abstract message class.
96
94
 
97
- Messages are the inputs and outputs of ``ChatModel``s.
95
+ Messages are the inputs and outputs of a chat model.
96
+
97
+ Examples include [`HumanMessage`][langchain.messages.HumanMessage],
98
+ [`AIMessage`][langchain.messages.AIMessage], and
99
+ [`SystemMessage`][langchain.messages.SystemMessage].
98
100
  """
99
101
 
100
- content: Union[str, list[Union[str, dict]]]
101
- """The string contents of the message."""
102
+ content: str | list[str | dict]
103
+ """The contents of the message."""
102
104
 
103
105
  additional_kwargs: dict = Field(default_factory=dict)
104
106
  """Reserved for additional payload data associated with the message.
@@ -119,7 +121,7 @@ class BaseMessage(Serializable):
119
121
 
120
122
  """
121
123
 
122
- name: Optional[str] = None
124
+ name: str | None = None
123
125
  """An optional name for the message.
124
126
 
125
127
  This can be used to provide a human-readable name for the message.
@@ -129,7 +131,7 @@ class BaseMessage(Serializable):
129
131
 
130
132
  """
131
133
 
132
- id: Optional[str] = Field(default=None, coerce_numbers_to_str=True)
134
+ id: str | None = Field(default=None, coerce_numbers_to_str=True)
133
135
  """An optional unique identifier for the message.
134
136
 
135
137
  This should ideally be provided by the provider/model which created the message.
@@ -143,32 +145,32 @@ class BaseMessage(Serializable):
143
145
  @overload
144
146
  def __init__(
145
147
  self,
146
- content: Union[str, list[Union[str, dict]]],
148
+ content: str | list[str | dict],
147
149
  **kwargs: Any,
148
150
  ) -> None: ...
149
151
 
150
152
  @overload
151
153
  def __init__(
152
154
  self,
153
- content: Optional[Union[str, list[Union[str, dict]]]] = None,
154
- content_blocks: Optional[list[types.ContentBlock]] = None,
155
+ content: str | list[str | dict] | None = None,
156
+ content_blocks: list[types.ContentBlock] | None = None,
155
157
  **kwargs: Any,
156
158
  ) -> None: ...
157
159
 
158
160
  def __init__(
159
161
  self,
160
- content: Optional[Union[str, list[Union[str, dict]]]] = None,
161
- content_blocks: Optional[list[types.ContentBlock]] = None,
162
+ content: str | list[str | dict] | None = None,
163
+ content_blocks: list[types.ContentBlock] | None = None,
162
164
  **kwargs: Any,
163
165
  ) -> None:
164
- """Initialize ``BaseMessage``.
166
+ """Initialize a `BaseMessage`.
165
167
 
166
- Specify ``content`` as positional arg or ``content_blocks`` for typing.
168
+ Specify `content` as positional arg or `content_blocks` for typing.
167
169
 
168
170
  Args:
169
- content: The string contents of the message.
171
+ content: The contents of the message.
170
172
  content_blocks: Typed standard content.
171
- kwargs: Additional arguments to pass to the parent class.
173
+ **kwargs: Additional arguments to pass to the parent class.
172
174
  """
173
175
  if content_blocks is not None:
174
176
  super().__init__(content=content_blocks, **kwargs)
@@ -177,7 +179,7 @@ class BaseMessage(Serializable):
177
179
 
178
180
  @classmethod
179
181
  def is_lc_serializable(cls) -> bool:
180
- """``BaseMessage`` is serializable.
182
+ """`BaseMessage` is serializable.
181
183
 
182
184
  Returns:
183
185
  True
@@ -186,10 +188,10 @@ class BaseMessage(Serializable):
186
188
 
187
189
  @classmethod
188
190
  def get_lc_namespace(cls) -> list[str]:
189
- """Get the namespace of the langchain object.
191
+ """Get the namespace of the LangChain object.
190
192
 
191
193
  Returns:
192
- ``["langchain", "schema", "messages"]``
194
+ `["langchain", "schema", "messages"]`
193
195
  """
194
196
  return ["langchain", "schema", "messages"]
195
197
 
@@ -197,7 +199,7 @@ class BaseMessage(Serializable):
197
199
  def content_blocks(self) -> list[types.ContentBlock]:
198
200
  r"""Load content blocks from the message content.
199
201
 
200
- .. versionadded:: 1.0.0
202
+ !!! version-added "Added in version 1.0.0"
201
203
 
202
204
  """
203
205
  # Needed here to avoid circular import, as these classes import BaseMessages
@@ -261,11 +263,11 @@ class BaseMessage(Serializable):
261
263
  def text(self) -> TextAccessor:
262
264
  """Get the text content of the message as a string.
263
265
 
264
- Can be used as both property (``message.text``) and method (``message.text()``).
266
+ Can be used as both property (`message.text`) and method (`message.text()`).
265
267
 
266
- .. deprecated:: 1.0.0
267
- Calling ``.text()`` as a method is deprecated. Use ``.text`` as a property
268
- instead. This method will be removed in 2.0.0.
268
+ !!! deprecated
269
+ As of `langchain-core` 1.0.0, calling `.text()` as a method is deprecated.
270
+ Use `.text` as a property instead. This method will be removed in 2.0.0.
269
271
 
270
272
  Returns:
271
273
  The text content of the message.
@@ -308,8 +310,8 @@ class BaseMessage(Serializable):
308
310
  """Get a pretty representation of the message.
309
311
 
310
312
  Args:
311
- html: Whether to format the message as HTML. If True, the message will be
312
- formatted with HTML tags. Default is False.
313
+ html: Whether to format the message as HTML. If `True`, the message will be
314
+ formatted with HTML tags.
313
315
 
314
316
  Returns:
315
317
  A pretty representation of the message.
@@ -327,20 +329,20 @@ class BaseMessage(Serializable):
327
329
 
328
330
 
329
331
  def merge_content(
330
- first_content: Union[str, list[Union[str, dict]]],
331
- *contents: Union[str, list[Union[str, dict]]],
332
- ) -> Union[str, list[Union[str, dict]]]:
332
+ first_content: str | list[str | dict],
333
+ *contents: str | list[str | dict],
334
+ ) -> str | list[str | dict]:
333
335
  """Merge multiple message contents.
334
336
 
335
337
  Args:
336
- first_content: The first ``content``. Can be a string or a list.
337
- contents: The other ``content``s. Can be a string or a list.
338
+ first_content: The first `content`. Can be a string or a list.
339
+ contents: The other `content`s. Can be a string or a list.
338
340
 
339
341
  Returns:
340
342
  The merged content.
341
343
 
342
344
  """
343
- merged: Union[str, list[Union[str, dict]]]
345
+ merged: str | list[str | dict]
344
346
  merged = "" if first_content is None else first_content
345
347
 
346
348
  for content in contents:
@@ -390,9 +392,9 @@ class BaseMessageChunk(BaseMessage):
390
392
 
391
393
  For example,
392
394
 
393
- ``AIMessageChunk(content="Hello") + AIMessageChunk(content=" World")``
395
+ `AIMessageChunk(content="Hello") + AIMessageChunk(content=" World")`
394
396
 
395
- will give ``AIMessageChunk(content="Hello World")``
397
+ will give `AIMessageChunk(content="Hello World")`
396
398
 
397
399
  """
398
400
  if isinstance(other, BaseMessageChunk):
@@ -441,8 +443,8 @@ def message_to_dict(message: BaseMessage) -> dict:
441
443
  message: Message to convert.
442
444
 
443
445
  Returns:
444
- Message as a dict. The dict will have a ``type`` key with the message type
445
- and a ``data`` key with the message data as a dict.
446
+ Message as a dict. The dict will have a `type` key with the message type
447
+ and a `data` key with the message data as a dict.
446
448
 
447
449
  """
448
450
  return {"type": message.type, "data": message.model_dump()}
@@ -452,7 +454,7 @@ def messages_to_dict(messages: Sequence[BaseMessage]) -> list[dict]:
452
454
  """Convert a sequence of Messages to a list of dictionaries.
453
455
 
454
456
  Args:
455
- messages: Sequence of messages (as ``BaseMessage``s) to convert.
457
+ messages: Sequence of messages (as `BaseMessage`s) to convert.
456
458
 
457
459
  Returns:
458
460
  List of messages as dicts.
@@ -466,7 +468,7 @@ def get_msg_title_repr(title: str, *, bold: bool = False) -> str:
466
468
 
467
469
  Args:
468
470
  title: The title.
469
- bold: Whether to bold the title. Default is False.
471
+ bold: Whether to bold the title.
470
472
 
471
473
  Returns:
472
474
  The title representation.
@@ -1,18 +1,19 @@
1
1
  """Derivations of standard content blocks from provider content.
2
2
 
3
- ``AIMessage`` will first attempt to use a provider-specific translator if
4
- ``model_provider`` is set in ``response_metadata`` on the message. Consequently, each
3
+ `AIMessage` will first attempt to use a provider-specific translator if
4
+ `model_provider` is set in `response_metadata` on the message. Consequently, each
5
5
  provider translator must handle all possible content response types from the provider,
6
6
  including text.
7
7
 
8
8
  If no provider is set, or if the provider does not have a registered translator,
9
- ``AIMessage`` will fall back to best-effort parsing of the content into blocks using
10
- the implementation in ``BaseMessage``.
9
+ `AIMessage` will fall back to best-effort parsing of the content into blocks using
10
+ the implementation in `BaseMessage`.
11
11
  """
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- from typing import TYPE_CHECKING, Callable
15
+ from collections.abc import Callable
16
+ from typing import TYPE_CHECKING
16
17
 
17
18
  if TYPE_CHECKING:
18
19
  from langchain_core.messages import AIMessage, AIMessageChunk
@@ -22,15 +23,15 @@ if TYPE_CHECKING:
22
23
  PROVIDER_TRANSLATORS: dict[str, dict[str, Callable[..., list[types.ContentBlock]]]] = {}
23
24
  """Map model provider names to translator functions.
24
25
 
25
- The dictionary maps provider names (e.g. ``'openai'``, ``'anthropic'``) to another
26
+ The dictionary maps provider names (e.g. `'openai'`, `'anthropic'`) to another
26
27
  dictionary with two keys:
27
- - ``'translate_content'``: Function to translate ``AIMessage`` content.
28
- - ``'translate_content_chunk'``: Function to translate ``AIMessageChunk`` content.
28
+ - `'translate_content'`: Function to translate `AIMessage` content.
29
+ - `'translate_content_chunk'`: Function to translate `AIMessageChunk` content.
29
30
 
30
- When calling `.content_blocks` on an ``AIMessage`` or ``AIMessageChunk``, if
31
- ``model_provider`` is set in ``response_metadata``, the corresponding translator
31
+ When calling `content_blocks` on an `AIMessage` or `AIMessageChunk`, if
32
+ `model_provider` is set in `response_metadata`, the corresponding translator
32
33
  functions will be used to parse the content into blocks. Otherwise, best-effort parsing
33
- in ``BaseMessage`` will be used.
34
+ in `BaseMessage` will be used.
34
35
  """
35
36
 
36
37
 
@@ -42,9 +43,9 @@ def register_translator(
42
43
  """Register content translators for a provider in `PROVIDER_TRANSLATORS`.
43
44
 
44
45
  Args:
45
- provider: The model provider name (e.g. ``'openai'``, ``'anthropic'``).
46
- translate_content: Function to translate ``AIMessage`` content.
47
- translate_content_chunk: Function to translate ``AIMessageChunk`` content.
46
+ provider: The model provider name (e.g. `'openai'`, `'anthropic'`).
47
+ translate_content: Function to translate `AIMessage` content.
48
+ translate_content_chunk: Function to translate `AIMessageChunk` content.
48
49
  """
49
50
  PROVIDER_TRANSLATORS[provider] = {
50
51
  "translate_content": translate_content,
@@ -61,9 +62,9 @@ def get_translator(
61
62
  provider: The model provider name.
62
63
 
63
64
  Returns:
64
- Dictionary with ``'translate_content'`` and ``'translate_content_chunk'``
65
+ Dictionary with `'translate_content'` and `'translate_content_chunk'`
65
66
  functions, or None if no translator is registered for the provider. In such
66
- case, best-effort parsing in ``BaseMessage`` will be used.
67
+ case, best-effort parsing in `BaseMessage` will be used.
67
68
  """
68
69
  return PROVIDER_TRANSLATORS.get(provider)
69
70
 
@@ -71,10 +72,10 @@ def get_translator(
71
72
  def _register_translators() -> None:
72
73
  """Register all translators in langchain-core.
73
74
 
74
- A unit test ensures all modules in ``block_translators`` are represented here.
75
+ A unit test ensures all modules in `block_translators` are represented here.
75
76
 
76
77
  For translators implemented outside langchain-core, they can be registered by
77
- calling ``register_translator`` from within the integration package.
78
+ calling `register_translator` from within the integration package.
78
79
  """
79
80
  from langchain_core.messages.block_translators.anthropic import ( # noqa: PLC0415
80
81
  _register_anthropic_translator,
@@ -94,9 +95,6 @@ def _register_translators() -> None:
94
95
  from langchain_core.messages.block_translators.groq import ( # noqa: PLC0415
95
96
  _register_groq_translator,
96
97
  )
97
- from langchain_core.messages.block_translators.ollama import ( # noqa: PLC0415
98
- _register_ollama_translator,
99
- )
100
98
  from langchain_core.messages.block_translators.openai import ( # noqa: PLC0415
101
99
  _register_openai_translator,
102
100
  )
@@ -107,7 +105,6 @@ def _register_translators() -> None:
107
105
  _register_google_genai_translator()
108
106
  _register_google_vertexai_translator()
109
107
  _register_groq_translator()
110
- _register_ollama_translator()
111
108
  _register_openai_translator()
112
109
 
113
110
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  import json
4
4
  from collections.abc import Iterable
5
- from typing import Any, Optional, Union, cast
5
+ from typing import Any, cast
6
6
 
7
7
  from langchain_core.messages import AIMessage, AIMessageChunk
8
8
  from langchain_core.messages import content as types
@@ -31,12 +31,12 @@ def _convert_to_v1_from_anthropic_input(
31
31
  ) -> list[types.ContentBlock]:
32
32
  """Convert Anthropic format blocks to v1 format.
33
33
 
34
- During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
35
- block as a ``'non_standard'`` block with the original block stored in the ``value``
34
+ During the `content_blocks` parsing process, we wrap blocks not recognized as a v1
35
+ block as a `'non_standard'` block with the original block stored in the `value`
36
36
  field. This function attempts to unpack those blocks and convert any blocks that
37
37
  might be Anthropic format to v1 ContentBlocks.
38
38
 
39
- If conversion fails, the block is left as a ``'non_standard'`` block.
39
+ If conversion fails, the block is left as a `'non_standard'` block.
40
40
 
41
41
  Args:
42
42
  content: List of content blocks to process.
@@ -200,7 +200,7 @@ def _convert_citation_to_v1(citation: dict[str, Any]) -> types.Annotation:
200
200
  def _convert_to_v1_from_anthropic(message: AIMessage) -> list[types.ContentBlock]:
201
201
  """Convert Anthropic message content to v1 format."""
202
202
  if isinstance(message.content, str):
203
- content: list[Union[str, dict]] = [{"type": "text", "text": message.content}]
203
+ content: list[str | dict] = [{"type": "text", "text": message.content}]
204
204
  else:
205
205
  content = message.content
206
206
 
@@ -252,7 +252,7 @@ def _convert_to_v1_from_anthropic(message: AIMessage) -> list[types.ContentBlock
252
252
  tool_call_chunk["type"] = "tool_call_chunk"
253
253
  yield tool_call_chunk
254
254
  else:
255
- tool_call_block: Optional[types.ToolCall] = None
255
+ tool_call_block: types.ToolCall | None = None
256
256
  # Non-streaming or gathered chunk
257
257
  if len(message.tool_calls) == 1:
258
258
  tool_call_block = {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import base64
4
4
  from collections.abc import Iterable
5
- from typing import Any, Optional, cast
5
+ from typing import Any, cast
6
6
 
7
7
  from langchain_core.messages import AIMessage, AIMessageChunk
8
8
  from langchain_core.messages import content as types
@@ -35,12 +35,12 @@ def _convert_to_v1_from_converse_input(
35
35
  ) -> list[types.ContentBlock]:
36
36
  """Convert Bedrock Converse format blocks to v1 format.
37
37
 
38
- During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
39
- block as a ``'non_standard'`` block with the original block stored in the ``value``
38
+ During the `content_blocks` parsing process, we wrap blocks not recognized as a v1
39
+ block as a `'non_standard'` block with the original block stored in the `value`
40
40
  field. This function attempts to unpack those blocks and convert any blocks that
41
41
  might be Converse format to v1 ContentBlocks.
42
42
 
43
- If conversion fails, the block is left as a ``'non_standard'`` block.
43
+ If conversion fails, the block is left as a `'non_standard'` block.
44
44
 
45
45
  Args:
46
46
  content: List of content blocks to process.
@@ -216,7 +216,7 @@ def _convert_to_v1_from_converse(message: AIMessage) -> list[types.ContentBlock]
216
216
  tool_call_chunk["type"] = "tool_call_chunk"
217
217
  yield tool_call_chunk
218
218
  else:
219
- tool_call_block: Optional[types.ToolCall] = None
219
+ tool_call_block: types.ToolCall | None = None
220
220
  # Non-streaming or gathered chunk
221
221
  if len(message.tool_calls) == 1:
222
222
  tool_call_block = {
@@ -105,12 +105,12 @@ def _convert_to_v1_from_genai_input(
105
105
  Called when message isn't an `AIMessage` or `model_provider` isn't set on
106
106
  `response_metadata`.
107
107
 
108
- During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
109
- block as a ``'non_standard'`` block with the original block stored in the ``value``
108
+ During the `content_blocks` parsing process, we wrap blocks not recognized as a v1
109
+ block as a `'non_standard'` block with the original block stored in the `value`
110
110
  field. This function attempts to unpack those blocks and convert any blocks that
111
111
  might be GenAI format to v1 ContentBlocks.
112
112
 
113
- If conversion fails, the block is left as a ``'non_standard'`` block.
113
+ If conversion fails, the block is left as a `'non_standard'` block.
114
114
 
115
115
  Args:
116
116
  content: List of content blocks to process.
@@ -282,7 +282,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
282
282
  standard content blocks for returning.
283
283
 
284
284
  Args:
285
- message: The AIMessage or AIMessageChunk to convert.
285
+ message: The `AIMessage` or `AIMessageChunk` to convert.
286
286
 
287
287
  Returns:
288
288
  List of standard content blocks derived from the message content.
@@ -368,7 +368,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
368
368
  else:
369
369
  # Assume it's raw base64 without data URI
370
370
  try:
371
- # Validate base64 and decode for mime type detection
371
+ # Validate base64 and decode for MIME type detection
372
372
  decoded_bytes = base64.b64decode(url, validate=True)
373
373
 
374
374
  image_url_b64_block = {
@@ -379,7 +379,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
379
379
  try:
380
380
  import filetype # type: ignore[import-not-found] # noqa: PLC0415
381
381
 
382
- # Guess mime type based on file bytes
382
+ # Guess MIME type based on file bytes
383
383
  mime_type = None
384
384
  kind = filetype.guess(decoded_bytes)
385
385
  if kind:
@@ -453,10 +453,13 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
453
453
  "status": status, # type: ignore[typeddict-item]
454
454
  "output": item.get("code_execution_result", ""),
455
455
  }
456
+ server_tool_result_block["extras"] = {"block_type": item_type}
456
457
  # Preserve original outcome in extras
457
458
  if outcome is not None:
458
- server_tool_result_block["extras"] = {"outcome": outcome}
459
+ server_tool_result_block["extras"]["outcome"] = outcome
459
460
  converted_blocks.append(server_tool_result_block)
461
+ elif item_type == "text":
462
+ converted_blocks.append(cast("types.TextContentBlock", item))
460
463
  else:
461
464
  # Unknown type, preserve as non-standard
462
465
  converted_blocks.append({"type": "non_standard", "value": item})
@@ -1,37 +1,9 @@
1
1
  """Derivations of standard content blocks from Google (VertexAI) content."""
2
2
 
3
- import warnings
4
-
5
- from langchain_core.messages import AIMessage, AIMessageChunk
6
- from langchain_core.messages import content as types
7
-
8
- WARNED = False
9
-
10
-
11
- def translate_content(message: AIMessage) -> list[types.ContentBlock]: # noqa: ARG001
12
- """Derive standard content blocks from a message with Google (VertexAI) content."""
13
- global WARNED # noqa: PLW0603
14
- if not WARNED:
15
- warning_message = (
16
- "Content block standardization is not yet fully supported for Google "
17
- "VertexAI."
18
- )
19
- warnings.warn(warning_message, stacklevel=2)
20
- WARNED = True
21
- raise NotImplementedError
22
-
23
-
24
- def translate_content_chunk(message: AIMessageChunk) -> list[types.ContentBlock]: # noqa: ARG001
25
- """Derive standard content blocks from a chunk with Google (VertexAI) content."""
26
- global WARNED # noqa: PLW0603
27
- if not WARNED:
28
- warning_message = (
29
- "Content block standardization is not yet fully supported for Google "
30
- "VertexAI."
31
- )
32
- warnings.warn(warning_message, stacklevel=2)
33
- WARNED = True
34
- raise NotImplementedError
3
+ from langchain_core.messages.block_translators.google_genai import (
4
+ translate_content,
5
+ translate_content_chunk,
6
+ )
35
7
 
36
8
 
37
9
  def _register_google_vertexai_translator() -> None: