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.
- langchain_core/__init__.py +1 -1
- langchain_core/_api/__init__.py +3 -4
- langchain_core/_api/beta_decorator.py +23 -26
- langchain_core/_api/deprecation.py +51 -64
- langchain_core/_api/path.py +3 -6
- langchain_core/_import_utils.py +3 -4
- langchain_core/agents.py +55 -48
- langchain_core/caches.py +65 -66
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +321 -336
- langchain_core/callbacks/file.py +44 -44
- langchain_core/callbacks/manager.py +454 -514
- langchain_core/callbacks/stdout.py +29 -30
- langchain_core/callbacks/streaming_stdout.py +32 -32
- langchain_core/callbacks/usage.py +60 -57
- langchain_core/chat_history.py +53 -68
- langchain_core/document_loaders/base.py +27 -25
- langchain_core/document_loaders/blob_loaders.py +1 -1
- langchain_core/document_loaders/langsmith.py +44 -48
- langchain_core/documents/__init__.py +23 -3
- langchain_core/documents/base.py +102 -94
- langchain_core/documents/compressor.py +10 -10
- langchain_core/documents/transformers.py +34 -35
- langchain_core/embeddings/fake.py +50 -54
- langchain_core/example_selectors/length_based.py +2 -2
- langchain_core/example_selectors/semantic_similarity.py +28 -32
- langchain_core/exceptions.py +21 -20
- langchain_core/globals.py +3 -151
- langchain_core/indexing/__init__.py +1 -1
- langchain_core/indexing/api.py +121 -126
- langchain_core/indexing/base.py +73 -75
- langchain_core/indexing/in_memory.py +4 -6
- langchain_core/language_models/__init__.py +14 -29
- langchain_core/language_models/_utils.py +58 -61
- langchain_core/language_models/base.py +82 -172
- langchain_core/language_models/chat_models.py +329 -402
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +42 -36
- langchain_core/language_models/llms.py +189 -269
- langchain_core/load/dump.py +9 -12
- langchain_core/load/load.py +18 -28
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +42 -40
- langchain_core/messages/__init__.py +10 -16
- langchain_core/messages/ai.py +148 -148
- langchain_core/messages/base.py +53 -51
- langchain_core/messages/block_translators/__init__.py +19 -22
- langchain_core/messages/block_translators/anthropic.py +6 -6
- langchain_core/messages/block_translators/bedrock_converse.py +5 -5
- langchain_core/messages/block_translators/google_genai.py +10 -7
- langchain_core/messages/block_translators/google_vertexai.py +4 -32
- langchain_core/messages/block_translators/groq.py +117 -21
- langchain_core/messages/block_translators/langchain_v0.py +5 -5
- langchain_core/messages/block_translators/openai.py +11 -11
- langchain_core/messages/chat.py +2 -6
- langchain_core/messages/content.py +339 -330
- langchain_core/messages/function.py +6 -10
- langchain_core/messages/human.py +24 -31
- langchain_core/messages/modifier.py +2 -2
- langchain_core/messages/system.py +19 -29
- langchain_core/messages/tool.py +74 -90
- langchain_core/messages/utils.py +484 -510
- langchain_core/output_parsers/__init__.py +13 -10
- langchain_core/output_parsers/base.py +61 -61
- langchain_core/output_parsers/format_instructions.py +9 -4
- langchain_core/output_parsers/json.py +12 -10
- langchain_core/output_parsers/list.py +21 -23
- langchain_core/output_parsers/openai_functions.py +49 -47
- langchain_core/output_parsers/openai_tools.py +30 -23
- langchain_core/output_parsers/pydantic.py +13 -14
- langchain_core/output_parsers/string.py +5 -5
- langchain_core/output_parsers/transform.py +15 -17
- langchain_core/output_parsers/xml.py +35 -34
- langchain_core/outputs/__init__.py +1 -1
- langchain_core/outputs/chat_generation.py +18 -18
- langchain_core/outputs/chat_result.py +1 -3
- langchain_core/outputs/generation.py +16 -16
- langchain_core/outputs/llm_result.py +10 -10
- langchain_core/prompt_values.py +13 -19
- langchain_core/prompts/__init__.py +3 -27
- langchain_core/prompts/base.py +81 -86
- langchain_core/prompts/chat.py +308 -351
- langchain_core/prompts/dict.py +6 -6
- langchain_core/prompts/few_shot.py +81 -88
- langchain_core/prompts/few_shot_with_templates.py +11 -13
- langchain_core/prompts/image.py +12 -14
- langchain_core/prompts/loading.py +4 -6
- langchain_core/prompts/message.py +7 -7
- langchain_core/prompts/prompt.py +24 -39
- langchain_core/prompts/string.py +26 -10
- langchain_core/prompts/structured.py +49 -53
- langchain_core/rate_limiters.py +51 -60
- langchain_core/retrievers.py +61 -198
- langchain_core/runnables/base.py +1551 -1656
- langchain_core/runnables/branch.py +68 -70
- langchain_core/runnables/config.py +72 -89
- langchain_core/runnables/configurable.py +145 -161
- langchain_core/runnables/fallbacks.py +102 -96
- langchain_core/runnables/graph.py +91 -97
- langchain_core/runnables/graph_ascii.py +27 -28
- langchain_core/runnables/graph_mermaid.py +42 -51
- langchain_core/runnables/graph_png.py +43 -16
- langchain_core/runnables/history.py +175 -177
- langchain_core/runnables/passthrough.py +151 -167
- langchain_core/runnables/retry.py +46 -51
- langchain_core/runnables/router.py +30 -35
- langchain_core/runnables/schema.py +75 -80
- langchain_core/runnables/utils.py +60 -67
- langchain_core/stores.py +85 -121
- langchain_core/structured_query.py +8 -8
- langchain_core/sys_info.py +29 -29
- langchain_core/tools/__init__.py +1 -14
- langchain_core/tools/base.py +306 -245
- langchain_core/tools/convert.py +160 -155
- langchain_core/tools/render.py +10 -10
- langchain_core/tools/retriever.py +12 -11
- langchain_core/tools/simple.py +19 -24
- langchain_core/tools/structured.py +32 -39
- langchain_core/tracers/__init__.py +1 -9
- langchain_core/tracers/base.py +97 -99
- langchain_core/tracers/context.py +29 -52
- langchain_core/tracers/core.py +49 -53
- langchain_core/tracers/evaluation.py +11 -11
- langchain_core/tracers/event_stream.py +65 -64
- langchain_core/tracers/langchain.py +21 -21
- langchain_core/tracers/log_stream.py +45 -45
- langchain_core/tracers/memory_stream.py +3 -3
- langchain_core/tracers/root_listeners.py +16 -16
- langchain_core/tracers/run_collector.py +2 -4
- langchain_core/tracers/schemas.py +0 -129
- langchain_core/tracers/stdout.py +3 -3
- langchain_core/utils/__init__.py +1 -4
- langchain_core/utils/_merge.py +2 -2
- langchain_core/utils/aiter.py +57 -61
- langchain_core/utils/env.py +9 -9
- langchain_core/utils/function_calling.py +94 -188
- langchain_core/utils/html.py +7 -8
- langchain_core/utils/input.py +9 -6
- langchain_core/utils/interactive_env.py +1 -1
- langchain_core/utils/iter.py +36 -40
- langchain_core/utils/json.py +4 -3
- langchain_core/utils/json_schema.py +9 -9
- langchain_core/utils/mustache.py +8 -10
- langchain_core/utils/pydantic.py +35 -37
- langchain_core/utils/strings.py +6 -9
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +66 -62
- langchain_core/vectorstores/base.py +182 -216
- langchain_core/vectorstores/in_memory.py +101 -176
- langchain_core/vectorstores/utils.py +5 -5
- langchain_core/version.py +1 -1
- langchain_core-1.0.4.dist-info/METADATA +69 -0
- langchain_core-1.0.4.dist-info/RECORD +172 -0
- {langchain_core-1.0.0a6.dist-info → langchain_core-1.0.4.dist-info}/WHEEL +1 -1
- langchain_core/memory.py +0 -120
- langchain_core/messages/block_translators/ollama.py +0 -47
- langchain_core/prompts/pipeline.py +0 -138
- langchain_core/pydantic_v1/__init__.py +0 -30
- langchain_core/pydantic_v1/dataclasses.py +0 -23
- langchain_core/pydantic_v1/main.py +0 -23
- langchain_core/tracers/langchain_v1.py +0 -31
- langchain_core/utils/loading.py +0 -35
- langchain_core-1.0.0a6.dist-info/METADATA +0 -67
- langchain_core-1.0.0a6.dist-info/RECORD +0 -181
- 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,
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Literal, cast
|
|
15
14
|
|
|
16
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
15
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
17
16
|
from typing_extensions import override
|
|
18
17
|
|
|
19
|
-
from langchain_core._api import
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
216
|
+
stream: Iterator of `ChatGenerationChunk`.
|
|
217
217
|
|
|
218
218
|
Returns:
|
|
219
|
-
|
|
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:
|
|
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
|
-
|
|
253
|
-
|
|
254
|
-
|
|
|
255
|
-
|
|
256
|
-
| `ainvoke`
|
|
257
|
-
|
|
258
|
-
| `
|
|
259
|
-
|
|
260
|
-
| `
|
|
261
|
-
|
|
262
|
-
| `
|
|
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
|
|
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
|
-
|
|
|
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
|
-
|
|
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:
|
|
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
|
|
339
|
-
defer to
|
|
301
|
+
If streaming is bypassed, then `stream`/`astream`/`astream_events` will
|
|
302
|
+
defer to `invoke`/`ainvoke`.
|
|
340
303
|
|
|
341
|
-
- If True
|
|
342
|
-
- If
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
- If False (
|
|
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
|
|
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:
|
|
316
|
+
output_version: str | None = Field(
|
|
355
317
|
default_factory=from_env("LC_OUTPUT_VERSION", default=None)
|
|
356
318
|
)
|
|
357
|
-
"""Version of
|
|
319
|
+
"""Version of `AIMessage` output format to store in message content.
|
|
358
320
|
|
|
359
|
-
|
|
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
|
-
-
|
|
366
|
-
|
|
367
|
-
-
|
|
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.,
|
|
370
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
372
|
+
config: RunnableConfig | None = None,
|
|
431
373
|
*,
|
|
432
|
-
stop:
|
|
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:
|
|
399
|
+
config: RunnableConfig | None = None,
|
|
458
400
|
*,
|
|
459
|
-
stop:
|
|
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:
|
|
482
|
-
|
|
483
|
-
|
|
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:
|
|
463
|
+
config: RunnableConfig | None = None,
|
|
517
464
|
*,
|
|
518
|
-
stop:
|
|
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:
|
|
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:
|
|
589
|
+
config: RunnableConfig | None = None,
|
|
633
590
|
*,
|
|
634
|
-
stop:
|
|
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:
|
|
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[
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
825
|
+
stop: list[str] | None = None,
|
|
859
826
|
callbacks: Callbacks = None,
|
|
860
827
|
*,
|
|
861
|
-
tags:
|
|
862
|
-
metadata:
|
|
863
|
-
run_name:
|
|
864
|
-
run_id:
|
|
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
|
-
|
|
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.
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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.
|
|
890
|
-
|
|
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
|
|
894
|
-
|
|
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(
|
|
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:
|
|
948
|
+
stop: list[str] | None = None,
|
|
975
949
|
callbacks: Callbacks = None,
|
|
976
950
|
*,
|
|
977
|
-
tags:
|
|
978
|
-
metadata:
|
|
979
|
-
run_name:
|
|
980
|
-
run_id:
|
|
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
|
-
|
|
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.
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
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.
|
|
1006
|
-
|
|
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
|
|
1010
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
1141
|
-
run_manager:
|
|
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:
|
|
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:
|
|
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:
|
|
1249
|
-
run_manager:
|
|
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:
|
|
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:
|
|
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:
|
|
1358
|
-
run_manager:
|
|
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:
|
|
1377
|
-
run_manager:
|
|
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:
|
|
1404
|
-
run_manager:
|
|
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:
|
|
1424
|
-
run_manager:
|
|
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:
|
|
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
|
-
|
|
1488
|
+
typing.Dict[str, Any] | type | Callable | BaseTool # noqa: UP006
|
|
1609
1489
|
],
|
|
1610
1490
|
*,
|
|
1611
|
-
tool_choice:
|
|
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:
|
|
1508
|
+
schema: typing.Dict | type, # noqa: UP006
|
|
1629
1509
|
*,
|
|
1630
1510
|
include_raw: bool = False,
|
|
1631
1511
|
**kwargs: Any,
|
|
1632
|
-
) -> Runnable[LanguageModelInput,
|
|
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
|
-
-
|
|
1639
|
-
-
|
|
1640
|
-
-
|
|
1641
|
-
-
|
|
1518
|
+
- An OpenAI function/tool schema,
|
|
1519
|
+
- A JSON Schema,
|
|
1520
|
+
- A `TypedDict` class,
|
|
1521
|
+
- Or a Pydantic class.
|
|
1642
1522
|
|
|
1643
|
-
If
|
|
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.
|
|
1647
|
-
|
|
1648
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
1664
|
-
|
|
1537
|
+
If `True` then both the raw model response (a `BaseMessage`) and the
|
|
1538
|
+
parsed model response will be returned.
|
|
1665
1539
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1540
|
+
If an error occurs during output parsing it will be caught and returned
|
|
1541
|
+
as well.
|
|
1668
1542
|
|
|
1669
|
-
|
|
1543
|
+
The final output is always a `dict` with keys `'raw'`, `'parsed'`, and
|
|
1544
|
+
`'parsing_error'`.
|
|
1670
1545
|
|
|
1671
|
-
|
|
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
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
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
|
-
|
|
1678
|
-
.. code-block:: python
|
|
1558
|
+
If `include_raw` is `True`, then `Runnable` outputs a `dict` with keys:
|
|
1679
1559
|
|
|
1680
|
-
|
|
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
|
-
|
|
1684
|
-
|
|
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
|
-
|
|
1691
|
-
|
|
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
|
-
|
|
1698
|
-
|
|
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
|
-
|
|
1703
|
-
|
|
1581
|
+
structured_model.invoke(
|
|
1582
|
+
"What weighs more a pound of bricks or a pound of feathers"
|
|
1583
|
+
)
|
|
1704
1584
|
|
|
1705
|
-
|
|
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
|
-
|
|
1709
|
-
|
|
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
|
-
|
|
1716
|
-
|
|
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
|
-
|
|
1730
|
-
|
|
1604
|
+
model = ChatModel(model="model-name", temperature=0)
|
|
1605
|
+
structured_model = model.with_structured_output(
|
|
1606
|
+
AnswerWithJustification, include_raw=True
|
|
1607
|
+
)
|
|
1731
1608
|
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
-
|
|
1737
|
-
|
|
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
|
-
|
|
1744
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1726
|
+
!!! note
|
|
1803
1727
|
This implementation is primarily here for backwards compatibility. For new
|
|
1804
|
-
implementations, please use
|
|
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:
|
|
1812
|
-
run_manager:
|
|
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:
|
|
1825
|
-
run_manager:
|
|
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:
|
|
1834
|
-
run_manager:
|
|
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:
|
|
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 >
|
|
1785
|
+
if depth > _MAX_CLEANUP_DEPTH: # Don't cooperate for pathological cases
|
|
1859
1786
|
return
|
|
1860
1787
|
|
|
1861
1788
|
if not isinstance(serialized, dict):
|