langchain-core 1.0.0a7__py3-none-any.whl → 1.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of langchain-core might be problematic. Click here for more details.
- langchain_core/__init__.py +1 -1
- langchain_core/_api/__init__.py +0 -1
- langchain_core/_api/beta_decorator.py +17 -20
- langchain_core/_api/deprecation.py +30 -35
- langchain_core/_import_utils.py +1 -1
- langchain_core/agents.py +7 -6
- langchain_core/caches.py +4 -10
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +232 -243
- langchain_core/callbacks/file.py +33 -33
- langchain_core/callbacks/manager.py +353 -416
- langchain_core/callbacks/stdout.py +21 -22
- langchain_core/callbacks/streaming_stdout.py +32 -32
- langchain_core/callbacks/usage.py +54 -51
- langchain_core/chat_history.py +76 -55
- langchain_core/document_loaders/langsmith.py +21 -21
- langchain_core/documents/__init__.py +0 -1
- langchain_core/documents/base.py +37 -40
- langchain_core/documents/transformers.py +28 -29
- langchain_core/embeddings/fake.py +46 -52
- langchain_core/exceptions.py +5 -5
- langchain_core/indexing/api.py +11 -11
- langchain_core/indexing/base.py +24 -24
- langchain_core/language_models/__init__.py +0 -2
- langchain_core/language_models/_utils.py +51 -53
- langchain_core/language_models/base.py +23 -24
- langchain_core/language_models/chat_models.py +121 -144
- langchain_core/language_models/fake_chat_models.py +5 -5
- langchain_core/language_models/llms.py +10 -12
- langchain_core/load/dump.py +1 -1
- langchain_core/load/load.py +16 -16
- langchain_core/load/serializable.py +35 -34
- langchain_core/messages/__init__.py +1 -16
- langchain_core/messages/ai.py +105 -104
- langchain_core/messages/base.py +26 -26
- langchain_core/messages/block_translators/__init__.py +17 -17
- langchain_core/messages/block_translators/anthropic.py +2 -2
- langchain_core/messages/block_translators/bedrock_converse.py +2 -2
- langchain_core/messages/block_translators/google_genai.py +2 -2
- langchain_core/messages/block_translators/groq.py +117 -21
- langchain_core/messages/block_translators/langchain_v0.py +2 -2
- langchain_core/messages/block_translators/openai.py +4 -4
- langchain_core/messages/chat.py +1 -1
- langchain_core/messages/content.py +189 -193
- langchain_core/messages/function.py +5 -5
- langchain_core/messages/human.py +15 -17
- langchain_core/messages/modifier.py +1 -1
- langchain_core/messages/system.py +12 -14
- langchain_core/messages/tool.py +45 -49
- langchain_core/messages/utils.py +384 -396
- langchain_core/output_parsers/__init__.py +1 -14
- langchain_core/output_parsers/base.py +22 -23
- langchain_core/output_parsers/json.py +3 -3
- langchain_core/output_parsers/list.py +1 -1
- langchain_core/output_parsers/openai_functions.py +46 -44
- langchain_core/output_parsers/openai_tools.py +7 -7
- langchain_core/output_parsers/pydantic.py +10 -11
- langchain_core/output_parsers/string.py +1 -1
- langchain_core/output_parsers/transform.py +2 -2
- langchain_core/output_parsers/xml.py +1 -1
- langchain_core/outputs/__init__.py +1 -1
- langchain_core/outputs/chat_generation.py +14 -14
- langchain_core/outputs/generation.py +5 -5
- langchain_core/outputs/llm_result.py +5 -5
- langchain_core/prompt_values.py +5 -5
- langchain_core/prompts/__init__.py +3 -23
- langchain_core/prompts/base.py +32 -37
- langchain_core/prompts/chat.py +216 -222
- langchain_core/prompts/dict.py +2 -2
- langchain_core/prompts/few_shot.py +76 -83
- langchain_core/prompts/few_shot_with_templates.py +6 -8
- langchain_core/prompts/image.py +11 -13
- langchain_core/prompts/loading.py +1 -1
- langchain_core/prompts/message.py +2 -2
- langchain_core/prompts/prompt.py +14 -16
- langchain_core/prompts/string.py +19 -7
- langchain_core/prompts/structured.py +24 -25
- langchain_core/rate_limiters.py +36 -38
- langchain_core/retrievers.py +41 -182
- langchain_core/runnables/base.py +565 -590
- langchain_core/runnables/branch.py +7 -7
- langchain_core/runnables/config.py +37 -44
- langchain_core/runnables/configurable.py +8 -9
- langchain_core/runnables/fallbacks.py +8 -8
- langchain_core/runnables/graph.py +28 -27
- langchain_core/runnables/graph_ascii.py +19 -18
- langchain_core/runnables/graph_mermaid.py +20 -31
- langchain_core/runnables/graph_png.py +7 -7
- langchain_core/runnables/history.py +20 -20
- langchain_core/runnables/passthrough.py +8 -8
- langchain_core/runnables/retry.py +3 -3
- langchain_core/runnables/router.py +1 -1
- langchain_core/runnables/schema.py +33 -33
- langchain_core/runnables/utils.py +30 -34
- langchain_core/stores.py +72 -102
- langchain_core/sys_info.py +27 -29
- langchain_core/tools/__init__.py +1 -14
- langchain_core/tools/base.py +63 -63
- langchain_core/tools/convert.py +92 -92
- langchain_core/tools/render.py +9 -9
- langchain_core/tools/retriever.py +1 -1
- langchain_core/tools/simple.py +6 -7
- langchain_core/tools/structured.py +17 -18
- langchain_core/tracers/__init__.py +1 -9
- langchain_core/tracers/base.py +35 -35
- langchain_core/tracers/context.py +12 -17
- langchain_core/tracers/event_stream.py +3 -3
- langchain_core/tracers/langchain.py +8 -8
- langchain_core/tracers/log_stream.py +17 -18
- langchain_core/tracers/memory_stream.py +2 -2
- langchain_core/tracers/schemas.py +0 -129
- langchain_core/utils/aiter.py +31 -31
- langchain_core/utils/env.py +5 -5
- langchain_core/utils/function_calling.py +48 -120
- langchain_core/utils/html.py +4 -4
- langchain_core/utils/input.py +2 -2
- langchain_core/utils/interactive_env.py +1 -1
- langchain_core/utils/iter.py +19 -19
- langchain_core/utils/json.py +1 -1
- langchain_core/utils/json_schema.py +2 -2
- langchain_core/utils/mustache.py +5 -5
- langchain_core/utils/pydantic.py +17 -17
- langchain_core/utils/strings.py +4 -4
- langchain_core/utils/utils.py +25 -28
- langchain_core/vectorstores/base.py +43 -64
- langchain_core/vectorstores/in_memory.py +83 -85
- langchain_core/version.py +1 -1
- {langchain_core-1.0.0a7.dist-info → langchain_core-1.0.0rc1.dist-info}/METADATA +23 -11
- langchain_core-1.0.0rc1.dist-info/RECORD +172 -0
- langchain_core/memory.py +0 -120
- 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-1.0.0a7.dist-info/RECORD +0 -176
- {langchain_core-1.0.0a7.dist-info → langchain_core-1.0.0rc1.dist-info}/WHEEL +0 -0
|
@@ -25,16 +25,16 @@ class BaseSerialized(TypedDict):
|
|
|
25
25
|
id: list[str]
|
|
26
26
|
"""The unique identifier of the object."""
|
|
27
27
|
name: NotRequired[str]
|
|
28
|
-
"""The name of the object.
|
|
28
|
+
"""The name of the object."""
|
|
29
29
|
graph: NotRequired[dict[str, Any]]
|
|
30
|
-
"""The graph of the object.
|
|
30
|
+
"""The graph of the object."""
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class SerializedConstructor(BaseSerialized):
|
|
34
34
|
"""Serialized constructor."""
|
|
35
35
|
|
|
36
36
|
type: Literal["constructor"]
|
|
37
|
-
"""The type of the object. Must be
|
|
37
|
+
"""The type of the object. Must be `'constructor'`."""
|
|
38
38
|
kwargs: dict[str, Any]
|
|
39
39
|
"""The constructor arguments."""
|
|
40
40
|
|
|
@@ -43,16 +43,16 @@ class SerializedSecret(BaseSerialized):
|
|
|
43
43
|
"""Serialized secret."""
|
|
44
44
|
|
|
45
45
|
type: Literal["secret"]
|
|
46
|
-
"""The type of the object. Must be
|
|
46
|
+
"""The type of the object. Must be `'secret'`."""
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
class SerializedNotImplemented(BaseSerialized):
|
|
50
50
|
"""Serialized not implemented."""
|
|
51
51
|
|
|
52
52
|
type: Literal["not_implemented"]
|
|
53
|
-
"""The type of the object. Must be
|
|
53
|
+
"""The type of the object. Must be `'not_implemented'`."""
|
|
54
54
|
repr: str | None
|
|
55
|
-
"""The representation of the object.
|
|
55
|
+
"""The representation of the object."""
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def try_neq_default(value: Any, key: str, model: BaseModel) -> bool:
|
|
@@ -61,7 +61,7 @@ def try_neq_default(value: Any, key: str, model: BaseModel) -> bool:
|
|
|
61
61
|
Args:
|
|
62
62
|
value: The value.
|
|
63
63
|
key: The key.
|
|
64
|
-
model: The
|
|
64
|
+
model: The Pydantic model.
|
|
65
65
|
|
|
66
66
|
Returns:
|
|
67
67
|
Whether the value is different from the default.
|
|
@@ -92,19 +92,19 @@ class Serializable(BaseModel, ABC):
|
|
|
92
92
|
|
|
93
93
|
It relies on the following methods and properties:
|
|
94
94
|
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
|
|
95
|
+
- `is_lc_serializable`: Is this class serializable?
|
|
96
|
+
By design, even if a class inherits from `Serializable`, it is not serializable
|
|
97
|
+
by default. This is to prevent accidental serialization of objects that should
|
|
98
|
+
not be serialized.
|
|
99
|
+
- `get_lc_namespace`: Get the namespace of the langchain object.
|
|
100
|
+
During deserialization, this namespace is used to identify
|
|
101
|
+
the correct class to instantiate.
|
|
102
|
+
Please see the `Reviver` class in `langchain_core.load.load` for more details.
|
|
103
|
+
During deserialization an additional mapping is handle classes that have moved
|
|
104
|
+
or been renamed across package versions.
|
|
105
|
+
- `lc_secrets`: A map of constructor argument names to secret ids.
|
|
106
|
+
- `lc_attributes`: List of additional attribute names that should be included
|
|
107
|
+
as part of the serialized representation.
|
|
108
108
|
"""
|
|
109
109
|
|
|
110
110
|
# Remove default BaseModel init docstring.
|
|
@@ -116,12 +116,12 @@ class Serializable(BaseModel, ABC):
|
|
|
116
116
|
def is_lc_serializable(cls) -> bool:
|
|
117
117
|
"""Is this class serializable?
|
|
118
118
|
|
|
119
|
-
By design, even if a class inherits from Serializable
|
|
120
|
-
default. This is to prevent accidental serialization of objects that should
|
|
121
|
-
be serialized.
|
|
119
|
+
By design, even if a class inherits from `Serializable`, it is not serializable
|
|
120
|
+
by default. This is to prevent accidental serialization of objects that should
|
|
121
|
+
not be serialized.
|
|
122
122
|
|
|
123
123
|
Returns:
|
|
124
|
-
Whether the class is serializable. Default is False
|
|
124
|
+
Whether the class is serializable. Default is `False`.
|
|
125
125
|
"""
|
|
126
126
|
return False
|
|
127
127
|
|
|
@@ -133,7 +133,7 @@ class Serializable(BaseModel, ABC):
|
|
|
133
133
|
namespace is ["langchain", "llms", "openai"]
|
|
134
134
|
|
|
135
135
|
Returns:
|
|
136
|
-
The namespace
|
|
136
|
+
The namespace.
|
|
137
137
|
"""
|
|
138
138
|
return cls.__module__.split(".")
|
|
139
139
|
|
|
@@ -141,8 +141,7 @@ class Serializable(BaseModel, ABC):
|
|
|
141
141
|
def lc_secrets(self) -> dict[str, str]:
|
|
142
142
|
"""A map of constructor argument names to secret ids.
|
|
143
143
|
|
|
144
|
-
For example,
|
|
145
|
-
{"openai_api_key": "OPENAI_API_KEY"}
|
|
144
|
+
For example, `{"openai_api_key": "OPENAI_API_KEY"}`
|
|
146
145
|
"""
|
|
147
146
|
return {}
|
|
148
147
|
|
|
@@ -151,6 +150,7 @@ class Serializable(BaseModel, ABC):
|
|
|
151
150
|
"""List of attribute names that should be included in the serialized kwargs.
|
|
152
151
|
|
|
153
152
|
These attributes must be accepted by the constructor.
|
|
153
|
+
|
|
154
154
|
Default is an empty dictionary.
|
|
155
155
|
"""
|
|
156
156
|
return {}
|
|
@@ -161,8 +161,9 @@ class Serializable(BaseModel, ABC):
|
|
|
161
161
|
|
|
162
162
|
The unique identifier is a list of strings that describes the path
|
|
163
163
|
to the object.
|
|
164
|
+
|
|
164
165
|
For example, for the class `langchain.llms.openai.OpenAI`, the id is
|
|
165
|
-
["langchain", "llms", "openai", "OpenAI"]
|
|
166
|
+
`["langchain", "llms", "openai", "OpenAI"]`.
|
|
166
167
|
"""
|
|
167
168
|
# Pydantic generics change the class name. So we need to do the following
|
|
168
169
|
if (
|
|
@@ -193,7 +194,7 @@ class Serializable(BaseModel, ABC):
|
|
|
193
194
|
ValueError: If the class has deprecated attributes.
|
|
194
195
|
|
|
195
196
|
Returns:
|
|
196
|
-
A json serializable object or a SerializedNotImplemented object.
|
|
197
|
+
A json serializable object or a `SerializedNotImplemented` object.
|
|
197
198
|
"""
|
|
198
199
|
if not self.is_lc_serializable():
|
|
199
200
|
return self.to_json_not_implemented()
|
|
@@ -268,7 +269,7 @@ class Serializable(BaseModel, ABC):
|
|
|
268
269
|
"""Serialize a "not implemented" object.
|
|
269
270
|
|
|
270
271
|
Returns:
|
|
271
|
-
SerializedNotImplemented
|
|
272
|
+
`SerializedNotImplemented`.
|
|
272
273
|
"""
|
|
273
274
|
return to_json_not_implemented(self)
|
|
274
275
|
|
|
@@ -283,8 +284,8 @@ def _is_field_useful(inst: Serializable, key: str, value: Any) -> bool:
|
|
|
283
284
|
|
|
284
285
|
Returns:
|
|
285
286
|
Whether the field is useful. If the field is required, it is useful.
|
|
286
|
-
If the field is not required, it is useful if the value is not None
|
|
287
|
-
If the field is not required and the value is None
|
|
287
|
+
If the field is not required, it is useful if the value is not `None`.
|
|
288
|
+
If the field is not required and the value is `None`, it is useful if the
|
|
288
289
|
default value is different from the value.
|
|
289
290
|
"""
|
|
290
291
|
field = type(inst).model_fields.get(key)
|
|
@@ -343,10 +344,10 @@ def to_json_not_implemented(obj: object) -> SerializedNotImplemented:
|
|
|
343
344
|
"""Serialize a "not implemented" object.
|
|
344
345
|
|
|
345
346
|
Args:
|
|
346
|
-
obj:
|
|
347
|
+
obj: Object to serialize.
|
|
347
348
|
|
|
348
349
|
Returns:
|
|
349
|
-
SerializedNotImplemented
|
|
350
|
+
`SerializedNotImplemented`
|
|
350
351
|
"""
|
|
351
352
|
id_: list[str] = []
|
|
352
353
|
try:
|
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
"""**Messages** are objects used in prompts and chat conversations.
|
|
2
|
-
|
|
3
|
-
**Class hierarchy:**
|
|
4
|
-
|
|
5
|
-
.. code-block::
|
|
6
|
-
|
|
7
|
-
BaseMessage --> SystemMessage, AIMessage, HumanMessage, ChatMessage, FunctionMessage, ToolMessage
|
|
8
|
-
--> BaseMessageChunk --> SystemMessageChunk, AIMessageChunk, HumanMessageChunk, ChatMessageChunk, FunctionMessageChunk, ToolMessageChunk
|
|
9
|
-
|
|
10
|
-
**Main helpers:**
|
|
11
|
-
|
|
12
|
-
.. code-block::
|
|
13
|
-
|
|
14
|
-
ChatPromptTemplate
|
|
15
|
-
|
|
16
|
-
""" # noqa: E501
|
|
1
|
+
"""**Messages** are objects used in prompts and chat conversations."""
|
|
17
2
|
|
|
18
3
|
from typing import TYPE_CHECKING
|
|
19
4
|
|
langchain_core/messages/ai.py
CHANGED
|
@@ -40,13 +40,13 @@ class InputTokenDetails(TypedDict, total=False):
|
|
|
40
40
|
Does *not* need to sum to full input token count. Does *not* need to have all keys.
|
|
41
41
|
|
|
42
42
|
Example:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
```python
|
|
44
|
+
{
|
|
45
|
+
"audio": 10,
|
|
46
|
+
"cache_creation": 200,
|
|
47
|
+
"cache_read": 100,
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
50
|
|
|
51
51
|
!!! version-added "Added in version 0.3.9"
|
|
52
52
|
|
|
@@ -76,12 +76,12 @@ class OutputTokenDetails(TypedDict, total=False):
|
|
|
76
76
|
Does *not* need to sum to full output token count. Does *not* need to have all keys.
|
|
77
77
|
|
|
78
78
|
Example:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
```python
|
|
80
|
+
{
|
|
81
|
+
"audio": 10,
|
|
82
|
+
"reasoning": 200,
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
85
|
|
|
86
86
|
!!! version-added "Added in version 0.3.9"
|
|
87
87
|
|
|
@@ -104,25 +104,25 @@ class UsageMetadata(TypedDict):
|
|
|
104
104
|
This is a standard representation of token usage that is consistent across models.
|
|
105
105
|
|
|
106
106
|
Example:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
107
|
+
```python
|
|
108
|
+
{
|
|
109
|
+
"input_tokens": 350,
|
|
110
|
+
"output_tokens": 240,
|
|
111
|
+
"total_tokens": 590,
|
|
112
|
+
"input_token_details": {
|
|
113
|
+
"audio": 10,
|
|
114
|
+
"cache_creation": 200,
|
|
115
|
+
"cache_read": 100,
|
|
116
|
+
},
|
|
117
|
+
"output_token_details": {
|
|
118
|
+
"audio": 10,
|
|
119
|
+
"reasoning": 200,
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
123
|
|
|
124
124
|
!!! warning "Behavior changed in 0.3.9"
|
|
125
|
-
Added
|
|
125
|
+
Added `input_token_details` and `output_token_details`.
|
|
126
126
|
|
|
127
127
|
"""
|
|
128
128
|
|
|
@@ -191,14 +191,14 @@ class AIMessage(BaseMessage):
|
|
|
191
191
|
content_blocks: list[types.ContentBlock] | None = None,
|
|
192
192
|
**kwargs: Any,
|
|
193
193
|
) -> None:
|
|
194
|
-
"""Initialize
|
|
194
|
+
"""Initialize `AIMessage`.
|
|
195
195
|
|
|
196
|
-
Specify
|
|
196
|
+
Specify `content` as positional arg or `content_blocks` for typing.
|
|
197
197
|
|
|
198
198
|
Args:
|
|
199
199
|
content: The content of the message.
|
|
200
200
|
content_blocks: Typed standard content.
|
|
201
|
-
kwargs: Additional arguments to pass to the parent class.
|
|
201
|
+
**kwargs: Additional arguments to pass to the parent class.
|
|
202
202
|
"""
|
|
203
203
|
if content_blocks is not None:
|
|
204
204
|
# If there are tool calls in content_blocks, but not in tool_calls, add them
|
|
@@ -229,7 +229,7 @@ class AIMessage(BaseMessage):
|
|
|
229
229
|
|
|
230
230
|
If the message has a known model provider, use the provider-specific translator
|
|
231
231
|
first before falling back to best-effort parsing. For details, see the property
|
|
232
|
-
on
|
|
232
|
+
on `BaseMessage`.
|
|
233
233
|
"""
|
|
234
234
|
if self.response_metadata.get("output_version") == "v1":
|
|
235
235
|
return cast("list[types.ContentBlock]", self.content)
|
|
@@ -335,7 +335,7 @@ class AIMessage(BaseMessage):
|
|
|
335
335
|
|
|
336
336
|
Args:
|
|
337
337
|
html: Whether to return an HTML-formatted string.
|
|
338
|
-
|
|
338
|
+
Defaults to `False`.
|
|
339
339
|
|
|
340
340
|
Returns:
|
|
341
341
|
A pretty representation of the message.
|
|
@@ -380,7 +380,7 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
|
|
|
380
380
|
type: Literal["AIMessageChunk"] = "AIMessageChunk" # type: ignore[assignment]
|
|
381
381
|
"""The type of the message (used for deserialization).
|
|
382
382
|
|
|
383
|
-
Defaults to
|
|
383
|
+
Defaults to `AIMessageChunk`.
|
|
384
384
|
|
|
385
385
|
"""
|
|
386
386
|
|
|
@@ -390,8 +390,8 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
|
|
|
390
390
|
chunk_position: Literal["last"] | None = None
|
|
391
391
|
"""Optional span represented by an aggregated AIMessageChunk.
|
|
392
392
|
|
|
393
|
-
If a chunk with
|
|
394
|
-
|
|
393
|
+
If a chunk with `chunk_position="last"` is aggregated into a stream,
|
|
394
|
+
`tool_call_chunks` in message content will be parsed into `tool_calls`.
|
|
395
395
|
"""
|
|
396
396
|
|
|
397
397
|
@property
|
|
@@ -545,6 +545,9 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
|
|
|
545
545
|
and call_id in id_to_tc
|
|
546
546
|
):
|
|
547
547
|
self.content[idx] = cast("dict[str, Any]", id_to_tc[call_id])
|
|
548
|
+
if "extras" in block:
|
|
549
|
+
# mypy does not account for instance check for dict above
|
|
550
|
+
self.content[idx]["extras"] = block["extras"] # type: ignore[index]
|
|
548
551
|
|
|
549
552
|
return self
|
|
550
553
|
|
|
@@ -596,14 +599,14 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
|
|
|
596
599
|
def add_ai_message_chunks(
|
|
597
600
|
left: AIMessageChunk, *others: AIMessageChunk
|
|
598
601
|
) -> AIMessageChunk:
|
|
599
|
-
"""Add multiple
|
|
602
|
+
"""Add multiple `AIMessageChunk`s together.
|
|
600
603
|
|
|
601
604
|
Args:
|
|
602
|
-
left: The first
|
|
603
|
-
*others: Other
|
|
605
|
+
left: The first `AIMessageChunk`.
|
|
606
|
+
*others: Other `AIMessageChunk`s to add.
|
|
604
607
|
|
|
605
608
|
Returns:
|
|
606
|
-
The resulting
|
|
609
|
+
The resulting `AIMessageChunk`.
|
|
607
610
|
|
|
608
611
|
"""
|
|
609
612
|
content = merge_content(left.content, *(o.content for o in others))
|
|
@@ -681,43 +684,42 @@ def add_usage(left: UsageMetadata | None, right: UsageMetadata | None) -> UsageM
|
|
|
681
684
|
"""Recursively add two UsageMetadata objects.
|
|
682
685
|
|
|
683
686
|
Example:
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
)
|
|
687
|
+
```python
|
|
688
|
+
from langchain_core.messages.ai import add_usage
|
|
689
|
+
|
|
690
|
+
left = UsageMetadata(
|
|
691
|
+
input_tokens=5,
|
|
692
|
+
output_tokens=0,
|
|
693
|
+
total_tokens=5,
|
|
694
|
+
input_token_details=InputTokenDetails(cache_read=3),
|
|
695
|
+
)
|
|
696
|
+
right = UsageMetadata(
|
|
697
|
+
input_tokens=0,
|
|
698
|
+
output_tokens=10,
|
|
699
|
+
total_tokens=10,
|
|
700
|
+
output_token_details=OutputTokenDetails(reasoning=4),
|
|
701
|
+
)
|
|
700
702
|
|
|
701
|
-
|
|
703
|
+
add_usage(left, right)
|
|
704
|
+
```
|
|
702
705
|
|
|
703
706
|
results in
|
|
704
707
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
708
|
+
```python
|
|
709
|
+
UsageMetadata(
|
|
710
|
+
input_tokens=5,
|
|
711
|
+
output_tokens=10,
|
|
712
|
+
total_tokens=15,
|
|
713
|
+
input_token_details=InputTokenDetails(cache_read=3),
|
|
714
|
+
output_token_details=OutputTokenDetails(reasoning=4),
|
|
715
|
+
)
|
|
716
|
+
```
|
|
715
717
|
Args:
|
|
716
|
-
left: The first
|
|
717
|
-
right: The second
|
|
718
|
+
left: The first `UsageMetadata` object.
|
|
719
|
+
right: The second `UsageMetadata` object.
|
|
718
720
|
|
|
719
721
|
Returns:
|
|
720
|
-
The sum of the two
|
|
722
|
+
The sum of the two `UsageMetadata` objects.
|
|
721
723
|
|
|
722
724
|
"""
|
|
723
725
|
if not (left or right):
|
|
@@ -740,48 +742,47 @@ def add_usage(left: UsageMetadata | None, right: UsageMetadata | None) -> UsageM
|
|
|
740
742
|
def subtract_usage(
|
|
741
743
|
left: UsageMetadata | None, right: UsageMetadata | None
|
|
742
744
|
) -> UsageMetadata:
|
|
743
|
-
"""Recursively subtract two
|
|
745
|
+
"""Recursively subtract two `UsageMetadata` objects.
|
|
744
746
|
|
|
745
|
-
Token counts cannot be negative so the actual operation is
|
|
747
|
+
Token counts cannot be negative so the actual operation is `max(left - right, 0)`.
|
|
746
748
|
|
|
747
749
|
Example:
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
)
|
|
750
|
+
```python
|
|
751
|
+
from langchain_core.messages.ai import subtract_usage
|
|
752
|
+
|
|
753
|
+
left = UsageMetadata(
|
|
754
|
+
input_tokens=5,
|
|
755
|
+
output_tokens=10,
|
|
756
|
+
total_tokens=15,
|
|
757
|
+
input_token_details=InputTokenDetails(cache_read=4),
|
|
758
|
+
)
|
|
759
|
+
right = UsageMetadata(
|
|
760
|
+
input_tokens=3,
|
|
761
|
+
output_tokens=8,
|
|
762
|
+
total_tokens=11,
|
|
763
|
+
output_token_details=OutputTokenDetails(reasoning=4),
|
|
764
|
+
)
|
|
764
765
|
|
|
765
|
-
|
|
766
|
+
subtract_usage(left, right)
|
|
767
|
+
```
|
|
766
768
|
|
|
767
769
|
results in
|
|
768
770
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
771
|
+
```python
|
|
772
|
+
UsageMetadata(
|
|
773
|
+
input_tokens=2,
|
|
774
|
+
output_tokens=2,
|
|
775
|
+
total_tokens=4,
|
|
776
|
+
input_token_details=InputTokenDetails(cache_read=4),
|
|
777
|
+
output_token_details=OutputTokenDetails(reasoning=0),
|
|
778
|
+
)
|
|
779
|
+
```
|
|
779
780
|
Args:
|
|
780
|
-
left: The first
|
|
781
|
-
right: The second
|
|
781
|
+
left: The first `UsageMetadata` object.
|
|
782
|
+
right: The second `UsageMetadata` object.
|
|
782
783
|
|
|
783
784
|
Returns:
|
|
784
|
-
The resulting
|
|
785
|
+
The resulting `UsageMetadata` after subtraction.
|
|
785
786
|
|
|
786
787
|
"""
|
|
787
788
|
if not (left or right):
|
langchain_core/messages/base.py
CHANGED
|
@@ -48,13 +48,13 @@ class TextAccessor(str):
|
|
|
48
48
|
|
|
49
49
|
Exists to maintain backward compatibility while transitioning from method-based to
|
|
50
50
|
property-based text access in message objects. In LangChain <v1.0, message text was
|
|
51
|
-
accessed via
|
|
52
|
-
access via
|
|
51
|
+
accessed via `.text()` method calls. In v1.0=<, the preferred pattern is property
|
|
52
|
+
access via `.text`.
|
|
53
53
|
|
|
54
|
-
Rather than breaking existing code immediately,
|
|
54
|
+
Rather than breaking existing code immediately, `TextAccessor` allows both
|
|
55
55
|
patterns:
|
|
56
|
-
- Modern property access:
|
|
57
|
-
- Legacy method access:
|
|
56
|
+
- Modern property access: `message.text` (returns string directly)
|
|
57
|
+
- Legacy method access: `message.text()` (callable, emits deprecation warning)
|
|
58
58
|
|
|
59
59
|
"""
|
|
60
60
|
|
|
@@ -67,12 +67,12 @@ class TextAccessor(str):
|
|
|
67
67
|
def __call__(self) -> str:
|
|
68
68
|
"""Enable method-style text access for backward compatibility.
|
|
69
69
|
|
|
70
|
-
This method exists solely to support legacy code that calls
|
|
71
|
-
as a method. New code should use property access (
|
|
70
|
+
This method exists solely to support legacy code that calls `.text()`
|
|
71
|
+
as a method. New code should use property access (`.text`) instead.
|
|
72
72
|
|
|
73
73
|
!!! deprecated
|
|
74
|
-
As of `langchain-core` 1.0.0, calling
|
|
75
|
-
Use
|
|
74
|
+
As of `langchain-core` 1.0.0, calling `.text()` as a method is deprecated.
|
|
75
|
+
Use `.text` as a property instead. This method will be removed in 2.0.0.
|
|
76
76
|
|
|
77
77
|
Returns:
|
|
78
78
|
The string content, identical to property access.
|
|
@@ -92,7 +92,7 @@ class TextAccessor(str):
|
|
|
92
92
|
class BaseMessage(Serializable):
|
|
93
93
|
"""Base abstract message class.
|
|
94
94
|
|
|
95
|
-
Messages are the inputs and outputs of a
|
|
95
|
+
Messages are the inputs and outputs of a `ChatModel`.
|
|
96
96
|
"""
|
|
97
97
|
|
|
98
98
|
content: str | list[str | dict]
|
|
@@ -159,14 +159,14 @@ class BaseMessage(Serializable):
|
|
|
159
159
|
content_blocks: list[types.ContentBlock] | None = None,
|
|
160
160
|
**kwargs: Any,
|
|
161
161
|
) -> None:
|
|
162
|
-
"""Initialize
|
|
162
|
+
"""Initialize `BaseMessage`.
|
|
163
163
|
|
|
164
|
-
Specify
|
|
164
|
+
Specify `content` as positional arg or `content_blocks` for typing.
|
|
165
165
|
|
|
166
166
|
Args:
|
|
167
167
|
content: The string contents of the message.
|
|
168
168
|
content_blocks: Typed standard content.
|
|
169
|
-
kwargs: Additional arguments to pass to the parent class.
|
|
169
|
+
**kwargs: Additional arguments to pass to the parent class.
|
|
170
170
|
"""
|
|
171
171
|
if content_blocks is not None:
|
|
172
172
|
super().__init__(content=content_blocks, **kwargs)
|
|
@@ -175,7 +175,7 @@ class BaseMessage(Serializable):
|
|
|
175
175
|
|
|
176
176
|
@classmethod
|
|
177
177
|
def is_lc_serializable(cls) -> bool:
|
|
178
|
-
"""
|
|
178
|
+
"""`BaseMessage` is serializable.
|
|
179
179
|
|
|
180
180
|
Returns:
|
|
181
181
|
True
|
|
@@ -187,7 +187,7 @@ class BaseMessage(Serializable):
|
|
|
187
187
|
"""Get the namespace of the langchain object.
|
|
188
188
|
|
|
189
189
|
Returns:
|
|
190
|
-
|
|
190
|
+
`["langchain", "schema", "messages"]`
|
|
191
191
|
"""
|
|
192
192
|
return ["langchain", "schema", "messages"]
|
|
193
193
|
|
|
@@ -259,11 +259,11 @@ class BaseMessage(Serializable):
|
|
|
259
259
|
def text(self) -> TextAccessor:
|
|
260
260
|
"""Get the text content of the message as a string.
|
|
261
261
|
|
|
262
|
-
Can be used as both property (
|
|
262
|
+
Can be used as both property (`message.text`) and method (`message.text()`).
|
|
263
263
|
|
|
264
264
|
!!! deprecated
|
|
265
|
-
As of langchain-core 1.0.0, calling
|
|
266
|
-
Use
|
|
265
|
+
As of langchain-core 1.0.0, calling `.text()` as a method is deprecated.
|
|
266
|
+
Use `.text` as a property instead. This method will be removed in 2.0.0.
|
|
267
267
|
|
|
268
268
|
Returns:
|
|
269
269
|
The text content of the message.
|
|
@@ -306,7 +306,7 @@ class BaseMessage(Serializable):
|
|
|
306
306
|
"""Get a pretty representation of the message.
|
|
307
307
|
|
|
308
308
|
Args:
|
|
309
|
-
html: Whether to format the message as HTML. If True
|
|
309
|
+
html: Whether to format the message as HTML. If `True`, the message will be
|
|
310
310
|
formatted with HTML tags. Default is False.
|
|
311
311
|
|
|
312
312
|
Returns:
|
|
@@ -331,8 +331,8 @@ def merge_content(
|
|
|
331
331
|
"""Merge multiple message contents.
|
|
332
332
|
|
|
333
333
|
Args:
|
|
334
|
-
first_content: The first
|
|
335
|
-
contents: The other
|
|
334
|
+
first_content: The first `content`. Can be a string or a list.
|
|
335
|
+
contents: The other `content`s. Can be a string or a list.
|
|
336
336
|
|
|
337
337
|
Returns:
|
|
338
338
|
The merged content.
|
|
@@ -388,9 +388,9 @@ class BaseMessageChunk(BaseMessage):
|
|
|
388
388
|
|
|
389
389
|
For example,
|
|
390
390
|
|
|
391
|
-
|
|
391
|
+
`AIMessageChunk(content="Hello") + AIMessageChunk(content=" World")`
|
|
392
392
|
|
|
393
|
-
will give
|
|
393
|
+
will give `AIMessageChunk(content="Hello World")`
|
|
394
394
|
|
|
395
395
|
"""
|
|
396
396
|
if isinstance(other, BaseMessageChunk):
|
|
@@ -439,8 +439,8 @@ def message_to_dict(message: BaseMessage) -> dict:
|
|
|
439
439
|
message: Message to convert.
|
|
440
440
|
|
|
441
441
|
Returns:
|
|
442
|
-
Message as a dict. The dict will have a
|
|
443
|
-
and a
|
|
442
|
+
Message as a dict. The dict will have a `type` key with the message type
|
|
443
|
+
and a `data` key with the message data as a dict.
|
|
444
444
|
|
|
445
445
|
"""
|
|
446
446
|
return {"type": message.type, "data": message.model_dump()}
|
|
@@ -450,7 +450,7 @@ def messages_to_dict(messages: Sequence[BaseMessage]) -> list[dict]:
|
|
|
450
450
|
"""Convert a sequence of Messages to a list of dictionaries.
|
|
451
451
|
|
|
452
452
|
Args:
|
|
453
|
-
messages: Sequence of messages (as
|
|
453
|
+
messages: Sequence of messages (as `BaseMessage`s) to convert.
|
|
454
454
|
|
|
455
455
|
Returns:
|
|
456
456
|
List of messages as dicts.
|