langchain-core 1.0.0a6__py3-none-any.whl → 1.0.4__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 +55 -48
  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 +454 -514
  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 +102 -94
  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 +2 -2
  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 +82 -172
  36. langchain_core/language_models/chat_models.py +329 -402
  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 +189 -269
  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 +339 -330
  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 +484 -510
  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 +30 -23
  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 +16 -16
  78. langchain_core/outputs/llm_result.py +10 -10
  79. langchain_core/prompt_values.py +13 -19
  80. langchain_core/prompts/__init__.py +3 -27
  81. langchain_core/prompts/base.py +81 -86
  82. langchain_core/prompts/chat.py +308 -351
  83. langchain_core/prompts/dict.py +6 -6
  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 +7 -7
  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 +1551 -1656
  95. langchain_core/runnables/branch.py +68 -70
  96. langchain_core/runnables/config.py +72 -89
  97. langchain_core/runnables/configurable.py +145 -161
  98. langchain_core/runnables/fallbacks.py +102 -96
  99. langchain_core/runnables/graph.py +91 -97
  100. langchain_core/runnables/graph_ascii.py +27 -28
  101. langchain_core/runnables/graph_mermaid.py +42 -51
  102. langchain_core/runnables/graph_png.py +43 -16
  103. langchain_core/runnables/history.py +175 -177
  104. langchain_core/runnables/passthrough.py +151 -167
  105. langchain_core/runnables/retry.py +46 -51
  106. langchain_core/runnables/router.py +30 -35
  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 +29 -29
  112. langchain_core/tools/__init__.py +1 -14
  113. langchain_core/tools/base.py +306 -245
  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 +94 -188
  137. langchain_core/utils/html.py +7 -8
  138. langchain_core/utils/input.py +9 -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 +35 -37
  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.4.dist-info/METADATA +69 -0
  153. langchain_core-1.0.4.dist-info/RECORD +172 -0
  154. {langchain_core-1.0.0a6.dist-info → langchain_core-1.0.4.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
@@ -6,22 +6,20 @@ import asyncio
6
6
  import inspect
7
7
  import json
8
8
  import typing
9
- import warnings
10
9
  from abc import ABC, abstractmethod
11
- from collections.abc import AsyncIterator, Iterator, Sequence
10
+ from collections.abc import AsyncIterator, Callable, Iterator, Sequence
12
11
  from functools import cached_property
13
12
  from operator import itemgetter
14
- from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, Union, cast
13
+ from typing import TYPE_CHECKING, Any, Literal, cast
15
14
 
16
- from pydantic import BaseModel, ConfigDict, Field, model_validator
15
+ from pydantic import BaseModel, ConfigDict, Field
17
16
  from typing_extensions import override
18
17
 
19
- from langchain_core._api import deprecated
18
+ from langchain_core._api.beta_decorator import beta
20
19
  from langchain_core.caches import BaseCache
21
20
  from langchain_core.callbacks import (
22
21
  AsyncCallbackManager,
23
22
  AsyncCallbackManagerForLLMRun,
24
- BaseCallbackManager,
25
23
  CallbackManager,
26
24
  CallbackManagerForLLMRun,
27
25
  Callbacks,
@@ -42,11 +40,11 @@ from langchain_core.messages import (
42
40
  AIMessageChunk,
43
41
  AnyMessage,
44
42
  BaseMessage,
45
- HumanMessage,
46
43
  convert_to_messages,
47
44
  is_data_content_block,
48
45
  message_chunk_to_message,
49
46
  )
47
+ from langchain_core.messages import content as types
50
48
  from langchain_core.messages.block_translators.openai import (
51
49
  convert_to_openai_image_block,
52
50
  )
@@ -78,6 +76,8 @@ from langchain_core.utils.utils import LC_ID_PREFIX, from_env
78
76
  if TYPE_CHECKING:
79
77
  import uuid
80
78
 
79
+ from langchain_model_profiles import ModelProfile # type: ignore[import-untyped]
80
+
81
81
  from langchain_core.output_parsers.base import OutputParserLike
82
82
  from langchain_core.runnables import Runnable, RunnableConfig
83
83
  from langchain_core.tools import BaseTool
@@ -111,11 +111,11 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]:
111
111
 
112
112
 
113
113
  def _format_for_tracing(messages: list[BaseMessage]) -> list[BaseMessage]:
114
- """Format messages for tracing in ``on_chat_model_start``.
114
+ """Format messages for tracing in `on_chat_model_start`.
115
115
 
116
116
  - Update image content blocks to OpenAI Chat Completions format (backward
117
117
  compatibility).
118
- - Add ``type`` key to content blocks that have a single key.
118
+ - Add `type` key to content blocks that have a single key.
119
119
 
120
120
  Args:
121
121
  messages: List of messages to format.
@@ -182,13 +182,13 @@ def generate_from_stream(stream: Iterator[ChatGenerationChunk]) -> ChatResult:
182
182
  """Generate from a stream.
183
183
 
184
184
  Args:
185
- stream: Iterator of ``ChatGenerationChunk``.
185
+ stream: Iterator of `ChatGenerationChunk`.
186
186
 
187
187
  Raises:
188
188
  ValueError: If no generations are found in the stream.
189
189
 
190
190
  Returns:
191
- ChatResult: Chat result.
191
+ Chat result.
192
192
 
193
193
  """
194
194
  generation = next(stream, None)
@@ -213,17 +213,17 @@ async def agenerate_from_stream(
213
213
  """Async generate from a stream.
214
214
 
215
215
  Args:
216
- stream: Iterator of ``ChatGenerationChunk``.
216
+ stream: Iterator of `ChatGenerationChunk`.
217
217
 
218
218
  Returns:
219
- ChatResult: Chat result.
219
+ Chat result.
220
220
 
221
221
  """
222
222
  chunks = [chunk async for chunk in stream]
223
223
  return await run_in_executor(None, generate_from_stream, iter(chunks))
224
224
 
225
225
 
226
- def _format_ls_structured_output(ls_structured_output_format: Optional[dict]) -> dict:
226
+ def _format_ls_structured_output(ls_structured_output_format: dict | None) -> dict:
227
227
  if ls_structured_output_format:
228
228
  try:
229
229
  ls_structured_output_format_dict = {
@@ -243,157 +243,99 @@ def _format_ls_structured_output(ls_structured_output_format: Optional[dict]) ->
243
243
 
244
244
 
245
245
  class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
246
- """Base class for chat models.
246
+ r"""Base class for chat models.
247
247
 
248
248
  Key imperative methods:
249
249
  Methods that actually call the underlying model.
250
250
 
251
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
252
- | Method | Input | Output | Description |
253
- +===========================+================================================================+=====================================================================+==================================================================================================+
254
- | `invoke` | str | list[dict | tuple | BaseMessage] | PromptValue | BaseMessage | A single chat model call. |
255
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
256
- | `ainvoke` | ''' | BaseMessage | Defaults to running invoke in an async executor. |
257
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
258
- | `stream` | ''' | Iterator[BaseMessageChunk] | Defaults to yielding output of invoke. |
259
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
260
- | `astream` | ''' | AsyncIterator[BaseMessageChunk] | Defaults to yielding output of ainvoke. |
261
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
262
- | `astream_events` | ''' | AsyncIterator[StreamEvent] | Event types: 'on_chat_model_start', 'on_chat_model_stream', 'on_chat_model_end'. |
263
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
264
- | `batch` | list['''] | list[BaseMessage] | Defaults to running invoke in concurrent threads. |
265
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
266
- | `abatch` | list['''] | list[BaseMessage] | Defaults to running ainvoke in concurrent threads. |
267
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
268
- | `batch_as_completed` | list['''] | Iterator[tuple[int, Union[BaseMessage, Exception]]] | Defaults to running invoke in concurrent threads. |
269
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
270
- | `abatch_as_completed` | list['''] | AsyncIterator[tuple[int, Union[BaseMessage, Exception]]] | Defaults to running ainvoke in concurrent threads. |
271
- +---------------------------+----------------------------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
272
-
273
- This table provides a brief overview of the main imperative methods. Please see the base Runnable reference for full documentation.
251
+ This table provides a brief overview of the main imperative methods. Please see the base `Runnable` reference for full documentation.
252
+
253
+ | Method | Input | Output | Description |
254
+ | ---------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------------------------------- |
255
+ | `invoke` | `str` \| `list[dict | tuple | BaseMessage]` \| `PromptValue` | `BaseMessage` | A single chat model call. |
256
+ | `ainvoke` | `'''` | `BaseMessage` | Defaults to running `invoke` in an async executor. |
257
+ | `stream` | `'''` | `Iterator[BaseMessageChunk]` | Defaults to yielding output of `invoke`. |
258
+ | `astream` | `'''` | `AsyncIterator[BaseMessageChunk]` | Defaults to yielding output of `ainvoke`. |
259
+ | `astream_events` | `'''` | `AsyncIterator[StreamEvent]` | Event types: `on_chat_model_start`, `on_chat_model_stream`, `on_chat_model_end`. |
260
+ | `batch` | `list[''']` | `list[BaseMessage]` | Defaults to running `invoke` in concurrent threads. |
261
+ | `abatch` | `list[''']` | `list[BaseMessage]` | Defaults to running `ainvoke` in concurrent threads. |
262
+ | `batch_as_completed` | `list[''']` | `Iterator[tuple[int, Union[BaseMessage, Exception]]]` | Defaults to running `invoke` in concurrent threads. |
263
+ | `abatch_as_completed` | `list[''']` | `AsyncIterator[tuple[int, Union[BaseMessage, Exception]]]` | Defaults to running `ainvoke` in concurrent threads. |
274
264
 
275
265
  Key declarative methods:
276
- Methods for creating another Runnable using the ChatModel.
277
-
278
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
279
- | Method | Description |
280
- +==================================+===========================================================================================================+
281
- | `bind_tools` | Create ChatModel that can call tools. |
282
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
283
- | `with_structured_output` | Create wrapper that structures model output using schema. |
284
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
285
- | `with_retry` | Create wrapper that retries model calls on failure. |
286
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
287
- | `with_fallbacks` | Create wrapper that falls back to other models on failure. |
288
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
289
- | `configurable_fields` | Specify init args of the model that can be configured at runtime via the RunnableConfig. |
290
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
291
- | `configurable_alternatives` | Specify alternative models which can be swapped in at runtime via the RunnableConfig. |
292
- +----------------------------------+-----------------------------------------------------------------------------------------------------------+
266
+ Methods for creating another `Runnable` using the chat model.
293
267
 
294
268
  This table provides a brief overview of the main declarative methods. Please see the reference for each method for full documentation.
295
269
 
270
+ | Method | Description |
271
+ | ---------------------------- | ------------------------------------------------------------------------------------------ |
272
+ | `bind_tools` | Create chat model that can call tools. |
273
+ | `with_structured_output` | Create wrapper that structures model output using schema. |
274
+ | `with_retry` | Create wrapper that retries model calls on failure. |
275
+ | `with_fallbacks` | Create wrapper that falls back to other models on failure. |
276
+ | `configurable_fields` | Specify init args of the model that can be configured at runtime via the `RunnableConfig`. |
277
+ | `configurable_alternatives` | Specify alternative models which can be swapped in at runtime via the `RunnableConfig`. |
278
+
296
279
  Creating custom chat model:
297
280
  Custom chat model implementations should inherit from this class.
298
281
  Please reference the table below for information about which
299
282
  methods and properties are required or optional for implementations.
300
283
 
301
- +----------------------------------+--------------------------------------------------------------------+-------------------+
302
- | Method/Property | Description | Required/Optional |
303
- +==================================+====================================================================+===================+
284
+ | Method/Property | Description | Required |
285
+ | -------------------------------- | ------------------------------------------------------------------ | ----------------- |
304
286
  | `_generate` | Use to generate a chat result from a prompt | Required |
305
- +----------------------------------+--------------------------------------------------------------------+-------------------+
306
287
  | `_llm_type` (property) | Used to uniquely identify the type of the model. Used for logging. | Required |
307
- +----------------------------------+--------------------------------------------------------------------+-------------------+
308
288
  | `_identifying_params` (property) | Represent model parameterization for tracing purposes. | Optional |
309
- +----------------------------------+--------------------------------------------------------------------+-------------------+
310
289
  | `_stream` | Use to implement streaming | Optional |
311
- +----------------------------------+--------------------------------------------------------------------+-------------------+
312
290
  | `_agenerate` | Use to implement a native async method | Optional |
313
- +----------------------------------+--------------------------------------------------------------------+-------------------+
314
291
  | `_astream` | Use to implement async version of `_stream` | Optional |
315
- +----------------------------------+--------------------------------------------------------------------+-------------------+
316
-
317
- Follow the guide for more information on how to implement a custom Chat Model:
318
- [Guide](https://python.langchain.com/docs/how_to/custom_chat_model/).
319
292
 
320
293
  """ # noqa: E501
321
294
 
322
- callback_manager: Optional[BaseCallbackManager] = deprecated(
323
- name="callback_manager", since="0.1.7", removal="1.0", alternative="callbacks"
324
- )(
325
- Field(
326
- default=None,
327
- exclude=True,
328
- description="Callback manager to add to the run trace.",
329
- )
330
- )
331
-
332
- rate_limiter: Optional[BaseRateLimiter] = Field(default=None, exclude=True)
295
+ rate_limiter: BaseRateLimiter | None = Field(default=None, exclude=True)
333
296
  "An optional rate limiter to use for limiting the number of requests."
334
297
 
335
- disable_streaming: Union[bool, Literal["tool_calling"]] = False
298
+ disable_streaming: bool | Literal["tool_calling"] = False
336
299
  """Whether to disable streaming for this model.
337
300
 
338
- If streaming is bypassed, then ``stream()``/``astream()``/``astream_events()`` will
339
- defer to ``invoke()``/``ainvoke()``.
301
+ If streaming is bypassed, then `stream`/`astream`/`astream_events` will
302
+ defer to `invoke`/`ainvoke`.
340
303
 
341
- - If True, will always bypass streaming case.
342
- - If ``'tool_calling'``, will bypass streaming case only when the model is called
343
- with a ``tools`` keyword argument. In other words, LangChain will automatically
344
- switch to non-streaming behavior (``invoke()``) only when the tools argument is
345
- provided. This offers the best of both worlds.
346
- - If False (default), will always use streaming case if available.
304
+ - If `True`, will always bypass streaming case.
305
+ - If `'tool_calling'`, will bypass streaming case only when the model is called
306
+ with a `tools` keyword argument. In other words, LangChain will automatically
307
+ switch to non-streaming behavior (`invoke`) only when the tools argument is
308
+ provided. This offers the best of both worlds.
309
+ - If `False` (Default), will always use streaming case if available.
347
310
 
348
- The main reason for this flag is that code might be written using ``stream()`` and
311
+ The main reason for this flag is that code might be written using `stream` and
349
312
  a user may want to swap out a given model for another model whose the implementation
350
313
  does not properly support streaming.
351
-
352
314
  """
353
315
 
354
- output_version: Optional[str] = Field(
316
+ output_version: str | None = Field(
355
317
  default_factory=from_env("LC_OUTPUT_VERSION", default=None)
356
318
  )
357
- """Version of ``AIMessage`` output format to store in message content.
319
+ """Version of `AIMessage` output format to store in message content.
358
320
 
359
- ``AIMessage.content_blocks`` will lazily parse the contents of ``content`` into a
321
+ `AIMessage.content_blocks` will lazily parse the contents of `content` into a
360
322
  standard format. This flag can be used to additionally store the standard format
361
323
  in message content, e.g., for serialization purposes.
362
324
 
363
325
  Supported values:
364
326
 
365
- - ``"v0"``: provider-specific format in content (can lazily-parse with
366
- ``.content_blocks``)
367
- - ``"v1"``: standardized format in content (consistent with ``.content_blocks``)
327
+ - `'v0'`: provider-specific format in content (can lazily-parse with
328
+ `content_blocks`)
329
+ - `'v1'`: standardized format in content (consistent with `content_blocks`)
368
330
 
369
- Partner packages (e.g., ``langchain-openai``) can also use this field to roll out
370
- new content formats in a backward-compatible way.
331
+ Partner packages (e.g.,
332
+ [`langchain-openai`](https://pypi.org/project/langchain-openai)) can also use this
333
+ field to roll out new content formats in a backward-compatible way.
371
334
 
372
- .. versionadded:: 1.0
335
+ !!! version-added "Added in `langchain-core` 1.0"
373
336
 
374
337
  """
375
338
 
376
- @model_validator(mode="before")
377
- @classmethod
378
- def raise_deprecation(cls, values: dict) -> Any:
379
- """Emit deprecation warning if ``callback_manager`` is used.
380
-
381
- Args:
382
- values (Dict): Values to validate.
383
-
384
- Returns:
385
- Dict: Validated values.
386
-
387
- """
388
- if values.get("callback_manager") is not None:
389
- warnings.warn(
390
- "callback_manager is deprecated. Please use callbacks instead.",
391
- DeprecationWarning,
392
- stacklevel=5,
393
- )
394
- values["callbacks"] = values.pop("callback_manager", None)
395
- return values
396
-
397
339
  model_config = ConfigDict(
398
340
  arbitrary_types_allowed=True,
399
341
  )
@@ -407,7 +349,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
407
349
  @property
408
350
  @override
409
351
  def OutputType(self) -> Any:
410
- """Get the output type for this runnable."""
352
+ """Get the output type for this `Runnable`."""
411
353
  return AnyMessage
412
354
 
413
355
  def _convert_input(self, model_input: LanguageModelInput) -> PromptValue:
@@ -427,9 +369,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
427
369
  def invoke(
428
370
  self,
429
371
  input: LanguageModelInput,
430
- config: Optional[RunnableConfig] = None,
372
+ config: RunnableConfig | None = None,
431
373
  *,
432
- stop: Optional[list[str]] = None,
374
+ stop: list[str] | None = None,
433
375
  **kwargs: Any,
434
376
  ) -> AIMessage:
435
377
  config = ensure_config(config)
@@ -454,9 +396,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
454
396
  async def ainvoke(
455
397
  self,
456
398
  input: LanguageModelInput,
457
- config: Optional[RunnableConfig] = None,
399
+ config: RunnableConfig | None = None,
458
400
  *,
459
- stop: Optional[list[str]] = None,
401
+ stop: list[str] | None = None,
460
402
  **kwargs: Any,
461
403
  ) -> AIMessage:
462
404
  config = ensure_config(config)
@@ -478,9 +420,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
478
420
  self,
479
421
  *,
480
422
  async_api: bool,
481
- run_manager: Optional[
482
- Union[CallbackManagerForLLMRun, AsyncCallbackManagerForLLMRun]
483
- ] = None,
423
+ run_manager: CallbackManagerForLLMRun
424
+ | AsyncCallbackManagerForLLMRun
425
+ | None = None,
484
426
  **kwargs: Any,
485
427
  ) -> bool:
486
428
  """Determine if a given model call should hit the streaming API."""
@@ -505,6 +447,11 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
505
447
  if "stream" in kwargs:
506
448
  return kwargs["stream"]
507
449
 
450
+ if "streaming" in self.model_fields_set:
451
+ streaming_value = getattr(self, "streaming", None)
452
+ if isinstance(streaming_value, bool):
453
+ return streaming_value
454
+
508
455
  # Check if any streaming callback handlers have been passed in.
509
456
  handlers = run_manager.handlers if run_manager else []
510
457
  return any(isinstance(h, _StreamingCallbackHandler) for h in handlers)
@@ -513,9 +460,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
513
460
  def stream(
514
461
  self,
515
462
  input: LanguageModelInput,
516
- config: Optional[RunnableConfig] = None,
463
+ config: RunnableConfig | None = None,
517
464
  *,
518
- stop: Optional[list[str]] = None,
465
+ stop: list[str] | None = None,
519
466
  **kwargs: Any,
520
467
  ) -> Iterator[AIMessageChunk]:
521
468
  if not self._should_stream(async_api=False, **{**kwargs, "stream": True}):
@@ -568,6 +515,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
568
515
  input_messages = _normalize_messages(messages)
569
516
  run_id = "-".join((LC_ID_PREFIX, str(run_manager.run_id)))
570
517
  yielded = False
518
+ index = -1
519
+ index_type = ""
571
520
  for chunk in self._stream(input_messages, stop=stop, **kwargs):
572
521
  if chunk.message.id is None:
573
522
  chunk.message.id = run_id
@@ -577,6 +526,14 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
577
526
  chunk.message = _update_message_content_to_blocks(
578
527
  chunk.message, "v1"
579
528
  )
529
+ for block in cast(
530
+ "list[types.ContentBlock]", chunk.message.content
531
+ ):
532
+ if block["type"] != index_type:
533
+ index_type = block["type"]
534
+ index = index + 1
535
+ if "index" not in block:
536
+ block["index"] = index
580
537
  run_manager.on_llm_new_token(
581
538
  cast("str", chunk.message.content), chunk=chunk
582
539
  )
@@ -591,7 +548,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
591
548
  and isinstance(chunk.message, AIMessageChunk)
592
549
  and not chunk.message.chunk_position
593
550
  ):
594
- empty_content: Union[str, list] = (
551
+ empty_content: str | list = (
595
552
  "" if isinstance(chunk.message.content, str) else []
596
553
  )
597
554
  msg_chunk = AIMessageChunk(
@@ -629,9 +586,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
629
586
  async def astream(
630
587
  self,
631
588
  input: LanguageModelInput,
632
- config: Optional[RunnableConfig] = None,
589
+ config: RunnableConfig | None = None,
633
590
  *,
634
- stop: Optional[list[str]] = None,
591
+ stop: list[str] | None = None,
635
592
  **kwargs: Any,
636
593
  ) -> AsyncIterator[AIMessageChunk]:
637
594
  if not self._should_stream(async_api=True, **{**kwargs, "stream": True}):
@@ -686,6 +643,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
686
643
  input_messages = _normalize_messages(messages)
687
644
  run_id = "-".join((LC_ID_PREFIX, str(run_manager.run_id)))
688
645
  yielded = False
646
+ index = -1
647
+ index_type = ""
689
648
  async for chunk in self._astream(
690
649
  input_messages,
691
650
  stop=stop,
@@ -699,6 +658,14 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
699
658
  chunk.message = _update_message_content_to_blocks(
700
659
  chunk.message, "v1"
701
660
  )
661
+ for block in cast(
662
+ "list[types.ContentBlock]", chunk.message.content
663
+ ):
664
+ if block["type"] != index_type:
665
+ index_type = block["type"]
666
+ index = index + 1
667
+ if "index" not in block:
668
+ block["index"] = index
702
669
  await run_manager.on_llm_new_token(
703
670
  cast("str", chunk.message.content), chunk=chunk
704
671
  )
@@ -712,7 +679,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
712
679
  and isinstance(chunk.message, AIMessageChunk)
713
680
  and not chunk.message.chunk_position
714
681
  ):
715
- empty_content: Union[str, list] = (
682
+ empty_content: str | list = (
716
683
  "" if isinstance(chunk.message.content, str) else []
717
684
  )
718
685
  msg_chunk = AIMessageChunk(
@@ -747,7 +714,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
747
714
 
748
715
  # --- Custom methods ---
749
716
 
750
- def _combine_llm_outputs(self, llm_outputs: list[Optional[dict]]) -> dict: # noqa: ARG002
717
+ def _combine_llm_outputs(self, llm_outputs: list[dict | None]) -> dict: # noqa: ARG002
751
718
  return {}
752
719
 
753
720
  def _convert_cached_generations(self, cache_val: list) -> list[ChatGeneration]:
@@ -791,7 +758,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
791
758
 
792
759
  def _get_invocation_params(
793
760
  self,
794
- stop: Optional[list[str]] = None,
761
+ stop: list[str] | None = None,
795
762
  **kwargs: Any,
796
763
  ) -> dict:
797
764
  params = self.dict()
@@ -800,7 +767,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
800
767
 
801
768
  def _get_ls_params(
802
769
  self,
803
- stop: Optional[list[str]] = None,
770
+ stop: list[str] | None = None,
804
771
  **kwargs: Any,
805
772
  ) -> LangSmithParams:
806
773
  """Get standard params for tracing."""
@@ -838,7 +805,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
838
805
 
839
806
  return ls_params
840
807
 
841
- def _get_llm_string(self, stop: Optional[list[str]] = None, **kwargs: Any) -> str:
808
+ def _get_llm_string(self, stop: list[str] | None = None, **kwargs: Any) -> str:
842
809
  if self.is_lc_serializable():
843
810
  params = {**kwargs, "stop": stop}
844
811
  param_string = str(sorted(params.items()))
@@ -855,13 +822,13 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
855
822
  def generate(
856
823
  self,
857
824
  messages: list[list[BaseMessage]],
858
- stop: Optional[list[str]] = None,
825
+ stop: list[str] | None = None,
859
826
  callbacks: Callbacks = None,
860
827
  *,
861
- tags: Optional[list[str]] = None,
862
- metadata: Optional[dict[str, Any]] = None,
863
- run_name: Optional[str] = None,
864
- run_id: Optional[uuid.UUID] = None,
828
+ tags: list[str] | None = None,
829
+ metadata: dict[str, Any] | None = None,
830
+ run_name: str | None = None,
831
+ run_id: uuid.UUID | None = None,
865
832
  **kwargs: Any,
866
833
  ) -> LLMResult:
867
834
  """Pass a sequence of prompts to the model and return model generations.
@@ -874,24 +841,29 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
874
841
  1. Take advantage of batched calls,
875
842
  2. Need more output from the model than just the top generated value,
876
843
  3. Are building chains that are agnostic to the underlying language model
877
- type (e.g., pure text completion models vs chat models).
844
+ type (e.g., pure text completion models vs chat models).
878
845
 
879
846
  Args:
880
847
  messages: List of list of messages.
881
- stop: Stop words to use when generating. Model output is cut off at the
882
- first occurrence of any of these substrings.
883
- callbacks: Callbacks to pass through. Used for executing additional
884
- functionality, such as logging or streaming, throughout generation.
848
+ stop: Stop words to use when generating.
849
+
850
+ Model output is cut off at the first occurrence of any of these
851
+ substrings.
852
+ callbacks: `Callbacks` to pass through.
853
+
854
+ Used for executing additional functionality, such as logging or
855
+ streaming, throughout generation.
885
856
  tags: The tags to apply.
886
857
  metadata: The metadata to apply.
887
858
  run_name: The name of the run.
888
859
  run_id: The ID of the run.
889
- **kwargs: Arbitrary additional keyword arguments. These are usually passed
890
- to the model provider API call.
860
+ **kwargs: Arbitrary additional keyword arguments.
861
+
862
+ These are usually passed to the model provider API call.
891
863
 
892
864
  Returns:
893
- An LLMResult, which contains a list of candidate Generations for each input
894
- prompt and additional model provider-specific output.
865
+ An `LLMResult`, which contains a list of candidate `Generations` for each
866
+ input prompt and additional model provider-specific output.
895
867
 
896
868
  """
897
869
  ls_structured_output_format = kwargs.pop(
@@ -962,7 +934,9 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
962
934
  output = LLMResult(generations=generations, llm_output=llm_output)
963
935
  if run_managers:
964
936
  run_infos = []
965
- for manager, flattened_output in zip(run_managers, flattened_outputs):
937
+ for manager, flattened_output in zip(
938
+ run_managers, flattened_outputs, strict=False
939
+ ):
966
940
  manager.on_llm_end(flattened_output)
967
941
  run_infos.append(RunInfo(run_id=manager.run_id))
968
942
  output.run = run_infos
@@ -971,13 +945,13 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
971
945
  async def agenerate(
972
946
  self,
973
947
  messages: list[list[BaseMessage]],
974
- stop: Optional[list[str]] = None,
948
+ stop: list[str] | None = None,
975
949
  callbacks: Callbacks = None,
976
950
  *,
977
- tags: Optional[list[str]] = None,
978
- metadata: Optional[dict[str, Any]] = None,
979
- run_name: Optional[str] = None,
980
- run_id: Optional[uuid.UUID] = None,
951
+ tags: list[str] | None = None,
952
+ metadata: dict[str, Any] | None = None,
953
+ run_name: str | None = None,
954
+ run_id: uuid.UUID | None = None,
981
955
  **kwargs: Any,
982
956
  ) -> LLMResult:
983
957
  """Asynchronously pass a sequence of prompts to a model and return generations.
@@ -990,24 +964,29 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
990
964
  1. Take advantage of batched calls,
991
965
  2. Need more output from the model than just the top generated value,
992
966
  3. Are building chains that are agnostic to the underlying language model
993
- type (e.g., pure text completion models vs chat models).
967
+ type (e.g., pure text completion models vs chat models).
994
968
 
995
969
  Args:
996
970
  messages: List of list of messages.
997
- stop: Stop words to use when generating. Model output is cut off at the
998
- first occurrence of any of these substrings.
999
- callbacks: Callbacks to pass through. Used for executing additional
1000
- functionality, such as logging or streaming, throughout generation.
971
+ stop: Stop words to use when generating.
972
+
973
+ Model output is cut off at the first occurrence of any of these
974
+ substrings.
975
+ callbacks: `Callbacks` to pass through.
976
+
977
+ Used for executing additional functionality, such as logging or
978
+ streaming, throughout generation.
1001
979
  tags: The tags to apply.
1002
980
  metadata: The metadata to apply.
1003
981
  run_name: The name of the run.
1004
982
  run_id: The ID of the run.
1005
- **kwargs: Arbitrary additional keyword arguments. These are usually passed
1006
- to the model provider API call.
983
+ **kwargs: Arbitrary additional keyword arguments.
984
+
985
+ These are usually passed to the model provider API call.
1007
986
 
1008
987
  Returns:
1009
- An LLMResult, which contains a list of candidate Generations for each input
1010
- prompt and additional model provider-specific output.
988
+ An `LLMResult`, which contains a list of candidate `Generations` for each
989
+ input prompt and additional model provider-specific output.
1011
990
 
1012
991
  """
1013
992
  ls_structured_output_format = kwargs.pop(
@@ -1084,7 +1063,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1084
1063
  llm_output=res.llm_output, # type: ignore[union-attr]
1085
1064
  )
1086
1065
  )
1087
- for run_manager, res in zip(run_managers, results)
1066
+ for run_manager, res in zip(run_managers, results, strict=False)
1088
1067
  if not isinstance(res, Exception)
1089
1068
  ]
1090
1069
  )
@@ -1100,7 +1079,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1100
1079
  *[
1101
1080
  run_manager.on_llm_end(flattened_output)
1102
1081
  for run_manager, flattened_output in zip(
1103
- run_managers, flattened_outputs
1082
+ run_managers, flattened_outputs, strict=False
1104
1083
  )
1105
1084
  ]
1106
1085
  )
@@ -1114,7 +1093,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1114
1093
  def generate_prompt(
1115
1094
  self,
1116
1095
  prompts: list[PromptValue],
1117
- stop: Optional[list[str]] = None,
1096
+ stop: list[str] | None = None,
1118
1097
  callbacks: Callbacks = None,
1119
1098
  **kwargs: Any,
1120
1099
  ) -> LLMResult:
@@ -1125,7 +1104,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1125
1104
  async def agenerate_prompt(
1126
1105
  self,
1127
1106
  prompts: list[PromptValue],
1128
- stop: Optional[list[str]] = None,
1107
+ stop: list[str] | None = None,
1129
1108
  callbacks: Callbacks = None,
1130
1109
  **kwargs: Any,
1131
1110
  ) -> LLMResult:
@@ -1137,8 +1116,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1137
1116
  def _generate_with_cache(
1138
1117
  self,
1139
1118
  messages: list[BaseMessage],
1140
- stop: Optional[list[str]] = None,
1141
- run_manager: Optional[CallbackManagerForLLMRun] = None,
1119
+ stop: list[str] | None = None,
1120
+ run_manager: CallbackManagerForLLMRun | None = None,
1142
1121
  **kwargs: Any,
1143
1122
  ) -> ChatResult:
1144
1123
  llm_cache = self.cache if isinstance(self.cache, BaseCache) else get_llm_cache()
@@ -1174,10 +1153,12 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1174
1153
  **kwargs,
1175
1154
  ):
1176
1155
  chunks: list[ChatGenerationChunk] = []
1177
- run_id: Optional[str] = (
1156
+ run_id: str | None = (
1178
1157
  f"{LC_ID_PREFIX}-{run_manager.run_id}" if run_manager else None
1179
1158
  )
1180
1159
  yielded = False
1160
+ index = -1
1161
+ index_type = ""
1181
1162
  for chunk in self._stream(messages, stop=stop, **kwargs):
1182
1163
  chunk.message.response_metadata = _gen_info_and_msg_metadata(chunk)
1183
1164
  if self.output_version == "v1":
@@ -1185,6 +1166,14 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1185
1166
  chunk.message = _update_message_content_to_blocks(
1186
1167
  chunk.message, "v1"
1187
1168
  )
1169
+ for block in cast(
1170
+ "list[types.ContentBlock]", chunk.message.content
1171
+ ):
1172
+ if block["type"] != index_type:
1173
+ index_type = block["type"]
1174
+ index = index + 1
1175
+ if "index" not in block:
1176
+ block["index"] = index
1188
1177
  if run_manager:
1189
1178
  if chunk.message.id is None:
1190
1179
  chunk.message.id = run_id
@@ -1200,7 +1189,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1200
1189
  and isinstance(chunk.message, AIMessageChunk)
1201
1190
  and not chunk.message.chunk_position
1202
1191
  ):
1203
- empty_content: Union[str, list] = (
1192
+ empty_content: str | list = (
1204
1193
  "" if isinstance(chunk.message.content, str) else []
1205
1194
  )
1206
1195
  chunk = ChatGenerationChunk(
@@ -1245,8 +1234,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1245
1234
  async def _agenerate_with_cache(
1246
1235
  self,
1247
1236
  messages: list[BaseMessage],
1248
- stop: Optional[list[str]] = None,
1249
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
1237
+ stop: list[str] | None = None,
1238
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
1250
1239
  **kwargs: Any,
1251
1240
  ) -> ChatResult:
1252
1241
  llm_cache = self.cache if isinstance(self.cache, BaseCache) else get_llm_cache()
@@ -1282,10 +1271,12 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1282
1271
  **kwargs,
1283
1272
  ):
1284
1273
  chunks: list[ChatGenerationChunk] = []
1285
- run_id: Optional[str] = (
1274
+ run_id: str | None = (
1286
1275
  f"{LC_ID_PREFIX}-{run_manager.run_id}" if run_manager else None
1287
1276
  )
1288
1277
  yielded = False
1278
+ index = -1
1279
+ index_type = ""
1289
1280
  async for chunk in self._astream(messages, stop=stop, **kwargs):
1290
1281
  chunk.message.response_metadata = _gen_info_and_msg_metadata(chunk)
1291
1282
  if self.output_version == "v1":
@@ -1293,6 +1284,14 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1293
1284
  chunk.message = _update_message_content_to_blocks(
1294
1285
  chunk.message, "v1"
1295
1286
  )
1287
+ for block in cast(
1288
+ "list[types.ContentBlock]", chunk.message.content
1289
+ ):
1290
+ if block["type"] != index_type:
1291
+ index_type = block["type"]
1292
+ index = index + 1
1293
+ if "index" not in block:
1294
+ block["index"] = index
1296
1295
  if run_manager:
1297
1296
  if chunk.message.id is None:
1298
1297
  chunk.message.id = run_id
@@ -1308,7 +1307,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1308
1307
  and isinstance(chunk.message, AIMessageChunk)
1309
1308
  and not chunk.message.chunk_position
1310
1309
  ):
1311
- empty_content: Union[str, list] = (
1310
+ empty_content: str | list = (
1312
1311
  "" if isinstance(chunk.message.content, str) else []
1313
1312
  )
1314
1313
  chunk = ChatGenerationChunk(
@@ -1354,8 +1353,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1354
1353
  def _generate(
1355
1354
  self,
1356
1355
  messages: list[BaseMessage],
1357
- stop: Optional[list[str]] = None,
1358
- run_manager: Optional[CallbackManagerForLLMRun] = None,
1356
+ stop: list[str] | None = None,
1357
+ run_manager: CallbackManagerForLLMRun | None = None,
1359
1358
  **kwargs: Any,
1360
1359
  ) -> ChatResult:
1361
1360
  """Generate the result.
@@ -1373,8 +1372,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1373
1372
  async def _agenerate(
1374
1373
  self,
1375
1374
  messages: list[BaseMessage],
1376
- stop: Optional[list[str]] = None,
1377
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
1375
+ stop: list[str] | None = None,
1376
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
1378
1377
  **kwargs: Any,
1379
1378
  ) -> ChatResult:
1380
1379
  """Generate the result.
@@ -1400,8 +1399,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1400
1399
  def _stream(
1401
1400
  self,
1402
1401
  messages: list[BaseMessage],
1403
- stop: Optional[list[str]] = None,
1404
- run_manager: Optional[CallbackManagerForLLMRun] = None,
1402
+ stop: list[str] | None = None,
1403
+ run_manager: CallbackManagerForLLMRun | None = None,
1405
1404
  **kwargs: Any,
1406
1405
  ) -> Iterator[ChatGenerationChunk]:
1407
1406
  """Stream the output of the model.
@@ -1420,8 +1419,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1420
1419
  async def _astream(
1421
1420
  self,
1422
1421
  messages: list[BaseMessage],
1423
- stop: Optional[list[str]] = None,
1424
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
1422
+ stop: list[str] | None = None,
1423
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
1425
1424
  **kwargs: Any,
1426
1425
  ) -> AsyncIterator[ChatGenerationChunk]:
1427
1426
  """Stream the output of the model.
@@ -1455,44 +1454,10 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1455
1454
  break
1456
1455
  yield item # type: ignore[misc]
1457
1456
 
1458
- @deprecated("0.1.7", alternative="invoke", removal="1.0")
1459
- def __call__(
1460
- self,
1461
- messages: list[BaseMessage],
1462
- stop: Optional[list[str]] = None,
1463
- callbacks: Callbacks = None,
1464
- **kwargs: Any,
1465
- ) -> BaseMessage:
1466
- """Call the model.
1467
-
1468
- Args:
1469
- messages: List of messages.
1470
- stop: Stop words to use when generating. Model output is cut off at the
1471
- first occurrence of any of these substrings.
1472
- callbacks: Callbacks to pass through. Used for executing additional
1473
- functionality, such as logging or streaming, throughout generation.
1474
- **kwargs: Arbitrary additional keyword arguments. These are usually passed
1475
- to the model provider API call.
1476
-
1477
- Raises:
1478
- ValueError: If the generation is not a chat generation.
1479
-
1480
- Returns:
1481
- The model output message.
1482
-
1483
- """
1484
- generation = self.generate(
1485
- [messages], stop=stop, callbacks=callbacks, **kwargs
1486
- ).generations[0][0]
1487
- if isinstance(generation, ChatGeneration):
1488
- return generation.message
1489
- msg = "Unexpected generation type"
1490
- raise ValueError(msg)
1491
-
1492
1457
  async def _call_async(
1493
1458
  self,
1494
1459
  messages: list[BaseMessage],
1495
- stop: Optional[list[str]] = None,
1460
+ stop: list[str] | None = None,
1496
1461
  callbacks: Callbacks = None,
1497
1462
  **kwargs: Any,
1498
1463
  ) -> BaseMessage:
@@ -1505,91 +1470,6 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1505
1470
  msg = "Unexpected generation type"
1506
1471
  raise ValueError(msg)
1507
1472
 
1508
- @deprecated("0.1.7", alternative="invoke", removal="1.0")
1509
- def call_as_llm(
1510
- self, message: str, stop: Optional[list[str]] = None, **kwargs: Any
1511
- ) -> str:
1512
- """Call the model.
1513
-
1514
- Args:
1515
- message: The input message.
1516
- stop: Stop words to use when generating. Model output is cut off at the
1517
- first occurrence of any of these substrings.
1518
- **kwargs: Arbitrary additional keyword arguments. These are usually passed
1519
- to the model provider API call.
1520
-
1521
- Returns:
1522
- The model output string.
1523
-
1524
- """
1525
- return self.predict(message, stop=stop, **kwargs)
1526
-
1527
- @deprecated("0.1.7", alternative="invoke", removal="1.0")
1528
- @override
1529
- def predict(
1530
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
1531
- ) -> str:
1532
- """Predict the next message.
1533
-
1534
- Args:
1535
- text: The input message.
1536
- stop: Stop words to use when generating. Model output is cut off at the
1537
- first occurrence of any of these substrings.
1538
- **kwargs: Arbitrary additional keyword arguments. These are usually passed
1539
- to the model provider API call.
1540
-
1541
- Raises:
1542
- ValueError: If the output is not a string.
1543
-
1544
- Returns:
1545
- The predicted output string.
1546
-
1547
- """
1548
- stop_ = None if stop is None else list(stop)
1549
- result = self([HumanMessage(content=text)], stop=stop_, **kwargs)
1550
- if isinstance(result.content, str):
1551
- return result.content
1552
- msg = "Cannot use predict when output is not a string."
1553
- raise ValueError(msg)
1554
-
1555
- @deprecated("0.1.7", alternative="invoke", removal="1.0")
1556
- @override
1557
- def predict_messages(
1558
- self,
1559
- messages: list[BaseMessage],
1560
- *,
1561
- stop: Optional[Sequence[str]] = None,
1562
- **kwargs: Any,
1563
- ) -> BaseMessage:
1564
- stop_ = None if stop is None else list(stop)
1565
- return self(messages, stop=stop_, **kwargs)
1566
-
1567
- @deprecated("0.1.7", alternative="ainvoke", removal="1.0")
1568
- @override
1569
- async def apredict(
1570
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
1571
- ) -> str:
1572
- stop_ = None if stop is None else list(stop)
1573
- result = await self._call_async(
1574
- [HumanMessage(content=text)], stop=stop_, **kwargs
1575
- )
1576
- if isinstance(result.content, str):
1577
- return result.content
1578
- msg = "Cannot use predict when output is not a string."
1579
- raise ValueError(msg)
1580
-
1581
- @deprecated("0.1.7", alternative="ainvoke", removal="1.0")
1582
- @override
1583
- async def apredict_messages(
1584
- self,
1585
- messages: list[BaseMessage],
1586
- *,
1587
- stop: Optional[Sequence[str]] = None,
1588
- **kwargs: Any,
1589
- ) -> BaseMessage:
1590
- stop_ = None if stop is None else list(stop)
1591
- return await self._call_async(messages, stop=stop_, **kwargs)
1592
-
1593
1473
  @property
1594
1474
  @abstractmethod
1595
1475
  def _llm_type(self) -> str:
@@ -1605,10 +1485,10 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1605
1485
  def bind_tools(
1606
1486
  self,
1607
1487
  tools: Sequence[
1608
- Union[typing.Dict[str, Any], type, Callable, BaseTool] # noqa: UP006
1488
+ typing.Dict[str, Any] | type | Callable | BaseTool # noqa: UP006
1609
1489
  ],
1610
1490
  *,
1611
- tool_choice: Optional[Union[str]] = None,
1491
+ tool_choice: str | None = None,
1612
1492
  **kwargs: Any,
1613
1493
  ) -> Runnable[LanguageModelInput, AIMessage]:
1614
1494
  """Bind tools to the model.
@@ -1625,136 +1505,146 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1625
1505
 
1626
1506
  def with_structured_output(
1627
1507
  self,
1628
- schema: Union[typing.Dict, type], # noqa: UP006
1508
+ schema: typing.Dict | type, # noqa: UP006
1629
1509
  *,
1630
1510
  include_raw: bool = False,
1631
1511
  **kwargs: Any,
1632
- ) -> Runnable[LanguageModelInput, Union[typing.Dict, BaseModel]]: # noqa: UP006
1512
+ ) -> Runnable[LanguageModelInput, typing.Dict | BaseModel]: # noqa: UP006
1633
1513
  """Model wrapper that returns outputs formatted to match the given schema.
1634
1514
 
1635
1515
  Args:
1636
1516
  schema: The output schema. Can be passed in as:
1637
1517
 
1638
- - an OpenAI function/tool schema,
1639
- - a JSON Schema,
1640
- - a TypedDict class,
1641
- - or a Pydantic class.
1518
+ - An OpenAI function/tool schema,
1519
+ - A JSON Schema,
1520
+ - A `TypedDict` class,
1521
+ - Or a Pydantic class.
1642
1522
 
1643
- If ``schema`` is a Pydantic class then the model output will be a
1523
+ If `schema` is a Pydantic class then the model output will be a
1644
1524
  Pydantic instance of that class, and the model-generated fields will be
1645
1525
  validated by the Pydantic class. Otherwise the model output will be a
1646
- dict and will not be validated. See :meth:`langchain_core.utils.function_calling.convert_to_openai_tool`
1647
- for more on how to properly specify types and descriptions of
1648
- schema fields when specifying a Pydantic or TypedDict class.
1526
+ dict and will not be validated.
1527
+
1528
+ See `langchain_core.utils.function_calling.convert_to_openai_tool` for
1529
+ more on how to properly specify types and descriptions of schema fields
1530
+ when specifying a Pydantic or `TypedDict` class.
1649
1531
 
1650
1532
  include_raw:
1651
- If False then only the parsed structured output is returned. If
1652
- an error occurs during model output parsing it will be raised. If True
1653
- then both the raw model response (a BaseMessage) and the parsed model
1654
- response will be returned. If an error occurs during output parsing it
1655
- will be caught and returned as well. The final output is always a dict
1656
- with keys ``'raw'``, ``'parsed'``, and ``'parsing_error'``.
1533
+ If `False` then only the parsed structured output is returned.
1657
1534
 
1658
- Raises:
1659
- ValueError: If there are any unsupported ``kwargs``.
1660
- NotImplementedError: If the model does not implement
1661
- ``with_structured_output()``.
1535
+ If an error occurs during model output parsing it will be raised.
1662
1536
 
1663
- Returns:
1664
- A Runnable that takes same inputs as a :class:`langchain_core.language_models.chat.BaseChatModel`.
1537
+ If `True` then both the raw model response (a `BaseMessage`) and the
1538
+ parsed model response will be returned.
1665
1539
 
1666
- If ``include_raw`` is False and ``schema`` is a Pydantic class, Runnable outputs
1667
- an instance of ``schema`` (i.e., a Pydantic object).
1540
+ If an error occurs during output parsing it will be caught and returned
1541
+ as well.
1668
1542
 
1669
- Otherwise, if ``include_raw`` is False then Runnable outputs a dict.
1543
+ The final output is always a `dict` with keys `'raw'`, `'parsed'`, and
1544
+ `'parsing_error'`.
1670
1545
 
1671
- If ``include_raw`` is True, then Runnable outputs a dict with keys:
1546
+ Raises:
1547
+ ValueError: If there are any unsupported `kwargs`.
1548
+ NotImplementedError: If the model does not implement
1549
+ `with_structured_output()`.
1672
1550
 
1673
- - ``'raw'``: BaseMessage
1674
- - ``'parsed'``: None if there was a parsing error, otherwise the type depends on the ``schema`` as described above.
1675
- - ``'parsing_error'``: Optional[BaseException]
1551
+ Returns:
1552
+ A `Runnable` that takes same inputs as a
1553
+ `langchain_core.language_models.chat.BaseChatModel`. If `include_raw` is
1554
+ `False` and `schema` is a Pydantic class, `Runnable` outputs an instance
1555
+ of `schema` (i.e., a Pydantic object). Otherwise, if `include_raw` is
1556
+ `False` then `Runnable` outputs a `dict`.
1676
1557
 
1677
- Example: Pydantic schema (include_raw=False):
1678
- .. code-block:: python
1558
+ If `include_raw` is `True`, then `Runnable` outputs a `dict` with keys:
1679
1559
 
1680
- from pydantic import BaseModel
1560
+ - `'raw'`: `BaseMessage`
1561
+ - `'parsed'`: `None` if there was a parsing error, otherwise the type
1562
+ depends on the `schema` as described above.
1563
+ - `'parsing_error'`: `BaseException | None`
1681
1564
 
1565
+ Example: Pydantic schema (`include_raw=False`):
1682
1566
 
1683
- class AnswerWithJustification(BaseModel):
1684
- '''An answer to the user question along with justification for the answer.'''
1567
+ ```python
1568
+ from pydantic import BaseModel
1685
1569
 
1686
- answer: str
1687
- justification: str
1688
1570
 
1571
+ class AnswerWithJustification(BaseModel):
1572
+ '''An answer to the user question along with justification for the answer.'''
1689
1573
 
1690
- llm = ChatModel(model="model-name", temperature=0)
1691
- structured_llm = llm.with_structured_output(AnswerWithJustification)
1574
+ answer: str
1575
+ justification: str
1692
1576
 
1693
- structured_llm.invoke(
1694
- "What weighs more a pound of bricks or a pound of feathers"
1695
- )
1696
1577
 
1697
- # -> AnswerWithJustification(
1698
- # answer='They weigh the same',
1699
- # justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'
1700
- # )
1578
+ model = ChatModel(model="model-name", temperature=0)
1579
+ structured_model = model.with_structured_output(AnswerWithJustification)
1701
1580
 
1702
- Example: Pydantic schema (include_raw=True):
1703
- .. code-block:: python
1581
+ structured_model.invoke(
1582
+ "What weighs more a pound of bricks or a pound of feathers"
1583
+ )
1704
1584
 
1705
- from pydantic import BaseModel
1585
+ # -> AnswerWithJustification(
1586
+ # answer='They weigh the same',
1587
+ # justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'
1588
+ # )
1589
+ ```
1706
1590
 
1591
+ Example: Pydantic schema (`include_raw=True`):
1707
1592
 
1708
- class AnswerWithJustification(BaseModel):
1709
- '''An answer to the user question along with justification for the answer.'''
1593
+ ```python
1594
+ from pydantic import BaseModel
1710
1595
 
1711
- answer: str
1712
- justification: str
1713
1596
 
1597
+ class AnswerWithJustification(BaseModel):
1598
+ '''An answer to the user question along with justification for the answer.'''
1714
1599
 
1715
- llm = ChatModel(model="model-name", temperature=0)
1716
- structured_llm = llm.with_structured_output(
1717
- AnswerWithJustification, include_raw=True
1718
- )
1600
+ answer: str
1601
+ justification: str
1719
1602
 
1720
- structured_llm.invoke(
1721
- "What weighs more a pound of bricks or a pound of feathers"
1722
- )
1723
- # -> {
1724
- # 'raw': AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ao02pnFYXD6GN1yzc0uXPsvF', 'function': {'arguments': '{"answer":"They weigh the same.","justification":"Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ."}', 'name': 'AnswerWithJustification'}, 'type': 'function'}]}),
1725
- # 'parsed': AnswerWithJustification(answer='They weigh the same.', justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'),
1726
- # 'parsing_error': None
1727
- # }
1728
1603
 
1729
- Example: Dict schema (include_raw=False):
1730
- .. code-block:: python
1604
+ model = ChatModel(model="model-name", temperature=0)
1605
+ structured_model = model.with_structured_output(
1606
+ AnswerWithJustification, include_raw=True
1607
+ )
1731
1608
 
1732
- from pydantic import BaseModel
1733
- from langchain_core.utils.function_calling import convert_to_openai_tool
1609
+ structured_model.invoke(
1610
+ "What weighs more a pound of bricks or a pound of feathers"
1611
+ )
1612
+ # -> {
1613
+ # 'raw': AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ao02pnFYXD6GN1yzc0uXPsvF', 'function': {'arguments': '{"answer":"They weigh the same.","justification":"Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ."}', 'name': 'AnswerWithJustification'}, 'type': 'function'}]}),
1614
+ # 'parsed': AnswerWithJustification(answer='They weigh the same.', justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'),
1615
+ # 'parsing_error': None
1616
+ # }
1617
+ ```
1734
1618
 
1619
+ Example: `dict` schema (`include_raw=False`):
1735
1620
 
1736
- class AnswerWithJustification(BaseModel):
1737
- '''An answer to the user question along with justification for the answer.'''
1621
+ ```python
1622
+ from pydantic import BaseModel
1623
+ from langchain_core.utils.function_calling import convert_to_openai_tool
1738
1624
 
1739
- answer: str
1740
- justification: str
1741
1625
 
1626
+ class AnswerWithJustification(BaseModel):
1627
+ '''An answer to the user question along with justification for the answer.'''
1742
1628
 
1743
- dict_schema = convert_to_openai_tool(AnswerWithJustification)
1744
- llm = ChatModel(model="model-name", temperature=0)
1745
- structured_llm = llm.with_structured_output(dict_schema)
1629
+ answer: str
1630
+ justification: str
1746
1631
 
1747
- structured_llm.invoke(
1748
- "What weighs more a pound of bricks or a pound of feathers"
1749
- )
1750
- # -> {
1751
- # 'answer': 'They weigh the same',
1752
- # 'justification': 'Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume and density of the two substances differ.'
1753
- # }
1754
1632
 
1755
- .. versionchanged:: 0.2.26
1633
+ dict_schema = convert_to_openai_tool(AnswerWithJustification)
1634
+ model = ChatModel(model="model-name", temperature=0)
1635
+ structured_model = model.with_structured_output(dict_schema)
1636
+
1637
+ structured_model.invoke(
1638
+ "What weighs more a pound of bricks or a pound of feathers"
1639
+ )
1640
+ # -> {
1641
+ # 'answer': 'They weigh the same',
1642
+ # 'justification': 'Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume and density of the two substances differ.'
1643
+ # }
1644
+ ```
1756
1645
 
1757
- Added support for TypedDict class.
1646
+ !!! warning "Behavior changed in `langchain-core` 0.2.26"
1647
+ Added support for `TypedDict` class.
1758
1648
 
1759
1649
  """ # noqa: E501
1760
1650
  _ = kwargs.pop("method", None)
@@ -1795,21 +1685,55 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1795
1685
  return RunnableMap(raw=llm) | parser_with_fallback
1796
1686
  return llm | output_parser
1797
1687
 
1688
+ @property
1689
+ @beta()
1690
+ def profile(self) -> ModelProfile:
1691
+ """Return profiling information for the model.
1692
+
1693
+ This property relies on the `langchain-model-profiles` package to retrieve chat
1694
+ model capabilities, such as context window sizes and supported features.
1695
+
1696
+ Raises:
1697
+ ImportError: If `langchain-model-profiles` is not installed.
1698
+
1699
+ Returns:
1700
+ A `ModelProfile` object containing profiling information for the model.
1701
+ """
1702
+ try:
1703
+ from langchain_model_profiles import get_model_profile # noqa: PLC0415
1704
+ except ImportError as err:
1705
+ informative_error_message = (
1706
+ "To access model profiling information, please install the "
1707
+ "`langchain-model-profiles` package: "
1708
+ "`pip install langchain-model-profiles`."
1709
+ )
1710
+ raise ImportError(informative_error_message) from err
1711
+
1712
+ provider_id = self._llm_type
1713
+ model_name = (
1714
+ # Model name is not standardized across integrations. New integrations
1715
+ # should prefer `model`.
1716
+ getattr(self, "model", None)
1717
+ or getattr(self, "model_name", None)
1718
+ or getattr(self, "model_id", "")
1719
+ )
1720
+ return get_model_profile(provider_id, model_name) or {}
1721
+
1798
1722
 
1799
1723
  class SimpleChatModel(BaseChatModel):
1800
1724
  """Simplified implementation for a chat model to inherit from.
1801
1725
 
1802
- .. note::
1726
+ !!! note
1803
1727
  This implementation is primarily here for backwards compatibility. For new
1804
- implementations, please use ``BaseChatModel`` directly.
1728
+ implementations, please use `BaseChatModel` directly.
1805
1729
 
1806
1730
  """
1807
1731
 
1808
1732
  def _generate(
1809
1733
  self,
1810
1734
  messages: list[BaseMessage],
1811
- stop: Optional[list[str]] = None,
1812
- run_manager: Optional[CallbackManagerForLLMRun] = None,
1735
+ stop: list[str] | None = None,
1736
+ run_manager: CallbackManagerForLLMRun | None = None,
1813
1737
  **kwargs: Any,
1814
1738
  ) -> ChatResult:
1815
1739
  output_str = self._call(messages, stop=stop, run_manager=run_manager, **kwargs)
@@ -1821,8 +1745,8 @@ class SimpleChatModel(BaseChatModel):
1821
1745
  def _call(
1822
1746
  self,
1823
1747
  messages: list[BaseMessage],
1824
- stop: Optional[list[str]] = None,
1825
- run_manager: Optional[CallbackManagerForLLMRun] = None,
1748
+ stop: list[str] | None = None,
1749
+ run_manager: CallbackManagerForLLMRun | None = None,
1826
1750
  **kwargs: Any,
1827
1751
  ) -> str:
1828
1752
  """Simpler interface."""
@@ -1830,8 +1754,8 @@ class SimpleChatModel(BaseChatModel):
1830
1754
  async def _agenerate(
1831
1755
  self,
1832
1756
  messages: list[BaseMessage],
1833
- stop: Optional[list[str]] = None,
1834
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
1757
+ stop: list[str] | None = None,
1758
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
1835
1759
  **kwargs: Any,
1836
1760
  ) -> ChatResult:
1837
1761
  return await run_in_executor(
@@ -1845,7 +1769,7 @@ class SimpleChatModel(BaseChatModel):
1845
1769
 
1846
1770
 
1847
1771
  def _gen_info_and_msg_metadata(
1848
- generation: Union[ChatGeneration, ChatGenerationChunk],
1772
+ generation: ChatGeneration | ChatGenerationChunk,
1849
1773
  ) -> dict:
1850
1774
  return {
1851
1775
  **(generation.generation_info or {}),
@@ -1853,9 +1777,12 @@ def _gen_info_and_msg_metadata(
1853
1777
  }
1854
1778
 
1855
1779
 
1780
+ _MAX_CLEANUP_DEPTH = 100
1781
+
1782
+
1856
1783
  def _cleanup_llm_representation(serialized: Any, depth: int) -> None:
1857
1784
  """Remove non-serializable objects from a serialized object."""
1858
- if depth > 100: # Don't cooperate for pathological cases
1785
+ if depth > _MAX_CLEANUP_DEPTH: # Don't cooperate for pathological cases
1859
1786
  return
1860
1787
 
1861
1788
  if not isinstance(serialized, dict):