langchain-core 0.3.79__py3-none-any.whl → 1.0.0__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 +3 -4
- langchain_core/_api/beta_decorator.py +23 -26
- langchain_core/_api/deprecation.py +52 -65
- langchain_core/_api/path.py +3 -6
- langchain_core/_import_utils.py +3 -4
- langchain_core/agents.py +19 -19
- langchain_core/caches.py +53 -63
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +323 -334
- langchain_core/callbacks/file.py +44 -44
- langchain_core/callbacks/manager.py +441 -507
- 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 +48 -63
- langchain_core/document_loaders/base.py +23 -23
- langchain_core/document_loaders/langsmith.py +37 -37
- langchain_core/documents/__init__.py +0 -1
- langchain_core/documents/base.py +62 -65
- langchain_core/documents/compressor.py +4 -4
- langchain_core/documents/transformers.py +28 -29
- langchain_core/embeddings/fake.py +50 -54
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/example_selectors/semantic_similarity.py +21 -25
- langchain_core/exceptions.py +10 -11
- langchain_core/globals.py +3 -151
- langchain_core/indexing/api.py +61 -66
- langchain_core/indexing/base.py +58 -58
- langchain_core/indexing/in_memory.py +3 -3
- langchain_core/language_models/__init__.py +14 -27
- langchain_core/language_models/_utils.py +270 -84
- langchain_core/language_models/base.py +55 -162
- langchain_core/language_models/chat_models.py +442 -402
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +61 -39
- langchain_core/language_models/llms.py +123 -231
- langchain_core/load/dump.py +4 -5
- langchain_core/load/load.py +18 -28
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +39 -40
- langchain_core/messages/__init__.py +61 -22
- langchain_core/messages/ai.py +368 -163
- langchain_core/messages/base.py +214 -43
- langchain_core/messages/block_translators/__init__.py +111 -0
- langchain_core/messages/block_translators/anthropic.py +470 -0
- langchain_core/messages/block_translators/bedrock.py +94 -0
- langchain_core/messages/block_translators/bedrock_converse.py +297 -0
- langchain_core/messages/block_translators/google_genai.py +530 -0
- langchain_core/messages/block_translators/google_vertexai.py +21 -0
- langchain_core/messages/block_translators/groq.py +143 -0
- langchain_core/messages/block_translators/langchain_v0.py +301 -0
- langchain_core/messages/block_translators/openai.py +1010 -0
- langchain_core/messages/chat.py +2 -6
- langchain_core/messages/content.py +1423 -0
- langchain_core/messages/function.py +6 -10
- langchain_core/messages/human.py +41 -38
- langchain_core/messages/modifier.py +2 -2
- langchain_core/messages/system.py +38 -28
- langchain_core/messages/tool.py +96 -103
- langchain_core/messages/utils.py +478 -504
- langchain_core/output_parsers/__init__.py +1 -14
- langchain_core/output_parsers/base.py +58 -61
- langchain_core/output_parsers/json.py +7 -8
- langchain_core/output_parsers/list.py +5 -7
- langchain_core/output_parsers/openai_functions.py +49 -47
- langchain_core/output_parsers/openai_tools.py +14 -19
- langchain_core/output_parsers/pydantic.py +12 -13
- langchain_core/output_parsers/string.py +2 -2
- langchain_core/output_parsers/transform.py +15 -17
- langchain_core/output_parsers/xml.py +8 -10
- 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 +8 -8
- langchain_core/outputs/llm_result.py +10 -10
- langchain_core/prompt_values.py +12 -12
- langchain_core/prompts/__init__.py +3 -27
- langchain_core/prompts/base.py +45 -55
- langchain_core/prompts/chat.py +254 -313
- langchain_core/prompts/dict.py +5 -5
- 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 +6 -8
- langchain_core/prompts/message.py +3 -3
- langchain_core/prompts/prompt.py +24 -39
- langchain_core/prompts/string.py +4 -4
- langchain_core/prompts/structured.py +42 -50
- langchain_core/rate_limiters.py +51 -60
- langchain_core/retrievers.py +49 -190
- langchain_core/runnables/base.py +1484 -1709
- langchain_core/runnables/branch.py +45 -61
- langchain_core/runnables/config.py +80 -88
- langchain_core/runnables/configurable.py +117 -134
- langchain_core/runnables/fallbacks.py +83 -79
- langchain_core/runnables/graph.py +85 -95
- langchain_core/runnables/graph_ascii.py +27 -28
- langchain_core/runnables/graph_mermaid.py +38 -50
- langchain_core/runnables/graph_png.py +15 -16
- langchain_core/runnables/history.py +135 -148
- langchain_core/runnables/passthrough.py +124 -150
- langchain_core/runnables/retry.py +46 -51
- langchain_core/runnables/router.py +25 -30
- langchain_core/runnables/schema.py +79 -74
- langchain_core/runnables/utils.py +62 -68
- langchain_core/stores.py +81 -115
- langchain_core/structured_query.py +8 -8
- langchain_core/sys_info.py +27 -29
- langchain_core/tools/__init__.py +1 -14
- langchain_core/tools/base.py +179 -187
- langchain_core/tools/convert.py +131 -139
- langchain_core/tools/render.py +10 -10
- langchain_core/tools/retriever.py +11 -11
- langchain_core/tools/simple.py +19 -24
- langchain_core/tools/structured.py +30 -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 +50 -60
- langchain_core/tracers/evaluation.py +11 -11
- langchain_core/tracers/event_stream.py +115 -70
- langchain_core/tracers/langchain.py +21 -21
- langchain_core/tracers/log_stream.py +43 -43
- 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 +46 -8
- langchain_core/utils/aiter.py +57 -61
- langchain_core/utils/env.py +9 -9
- langchain_core/utils/function_calling.py +89 -191
- langchain_core/utils/html.py +7 -8
- langchain_core/utils/input.py +6 -6
- langchain_core/utils/interactive_env.py +1 -1
- langchain_core/utils/iter.py +37 -42
- langchain_core/utils/json.py +4 -3
- langchain_core/utils/json_schema.py +8 -8
- langchain_core/utils/mustache.py +9 -11
- langchain_core/utils/pydantic.py +33 -35
- langchain_core/utils/strings.py +5 -5
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +80 -54
- langchain_core/vectorstores/base.py +129 -164
- langchain_core/vectorstores/in_memory.py +99 -174
- langchain_core/vectorstores/utils.py +5 -5
- langchain_core/version.py +1 -1
- {langchain_core-0.3.79.dist-info → langchain_core-1.0.0.dist-info}/METADATA +28 -27
- langchain_core-1.0.0.dist-info/RECORD +172 -0
- {langchain_core-0.3.79.dist-info → langchain_core-1.0.0.dist-info}/WHEEL +1 -1
- langchain_core/beta/__init__.py +0 -1
- langchain_core/beta/runnables/__init__.py +0 -1
- langchain_core/beta/runnables/context.py +0 -447
- langchain_core/memory.py +0 -120
- langchain_core/messages/content_blocks.py +0 -176
- 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-0.3.79.dist-info/RECORD +0 -174
- langchain_core-0.3.79.dist-info/entry_points.txt +0 -4
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
"""**OutputParser** classes parse the output of an LLM call.
|
|
2
|
-
|
|
3
|
-
**Class hierarchy:**
|
|
4
|
-
|
|
5
|
-
.. code-block::
|
|
6
|
-
|
|
7
|
-
BaseLLMOutputParser --> BaseOutputParser --> <name>OutputParser # ListOutputParser, PydanticOutputParser
|
|
8
|
-
|
|
9
|
-
**Main helpers:**
|
|
10
|
-
|
|
11
|
-
.. code-block::
|
|
12
|
-
|
|
13
|
-
Serializable, Generation, PromptValue
|
|
14
|
-
""" # noqa: E501
|
|
1
|
+
"""**OutputParser** classes parse the output of an LLM call."""
|
|
15
2
|
|
|
16
3
|
from typing import TYPE_CHECKING
|
|
17
4
|
|
|
@@ -8,9 +8,7 @@ from typing import (
|
|
|
8
8
|
TYPE_CHECKING,
|
|
9
9
|
Any,
|
|
10
10
|
Generic,
|
|
11
|
-
Optional,
|
|
12
11
|
TypeVar,
|
|
13
|
-
Union,
|
|
14
12
|
)
|
|
15
13
|
|
|
16
14
|
from typing_extensions import override
|
|
@@ -33,13 +31,13 @@ class BaseLLMOutputParser(ABC, Generic[T]):
|
|
|
33
31
|
|
|
34
32
|
@abstractmethod
|
|
35
33
|
def parse_result(self, result: list[Generation], *, partial: bool = False) -> T:
|
|
36
|
-
"""Parse a list of candidate model
|
|
34
|
+
"""Parse a list of candidate model `Generation` objects into a specific format.
|
|
37
35
|
|
|
38
36
|
Args:
|
|
39
|
-
result: A list of
|
|
40
|
-
to be different candidate outputs for a single model input.
|
|
37
|
+
result: A list of `Generation` to be parsed. The `Generation` objects are
|
|
38
|
+
assumed to be different candidate outputs for a single model input.
|
|
41
39
|
partial: Whether to parse the output as a partial result. This is useful
|
|
42
|
-
for parsers that can parse partial results.
|
|
40
|
+
for parsers that can parse partial results.
|
|
43
41
|
|
|
44
42
|
Returns:
|
|
45
43
|
Structured output.
|
|
@@ -48,17 +46,17 @@ class BaseLLMOutputParser(ABC, Generic[T]):
|
|
|
48
46
|
async def aparse_result(
|
|
49
47
|
self, result: list[Generation], *, partial: bool = False
|
|
50
48
|
) -> T:
|
|
51
|
-
"""Async parse a list of candidate model
|
|
49
|
+
"""Async parse a list of candidate model `Generation` objects into a specific format.
|
|
52
50
|
|
|
53
51
|
Args:
|
|
54
|
-
result: A list of
|
|
52
|
+
result: A list of `Generation` to be parsed. The Generations are assumed
|
|
55
53
|
to be different candidate outputs for a single model input.
|
|
56
54
|
partial: Whether to parse the output as a partial result. This is useful
|
|
57
|
-
for parsers that can parse partial results.
|
|
55
|
+
for parsers that can parse partial results.
|
|
58
56
|
|
|
59
57
|
Returns:
|
|
60
58
|
Structured output.
|
|
61
|
-
"""
|
|
59
|
+
""" # noqa: E501
|
|
62
60
|
return await run_in_executor(None, self.parse_result, result, partial=partial)
|
|
63
61
|
|
|
64
62
|
|
|
@@ -71,7 +69,7 @@ class BaseGenerationOutputParser(
|
|
|
71
69
|
@override
|
|
72
70
|
def InputType(self) -> Any:
|
|
73
71
|
"""Return the input type for the parser."""
|
|
74
|
-
return
|
|
72
|
+
return str | AnyMessage
|
|
75
73
|
|
|
76
74
|
@property
|
|
77
75
|
@override
|
|
@@ -84,8 +82,8 @@ class BaseGenerationOutputParser(
|
|
|
84
82
|
@override
|
|
85
83
|
def invoke(
|
|
86
84
|
self,
|
|
87
|
-
input:
|
|
88
|
-
config:
|
|
85
|
+
input: str | BaseMessage,
|
|
86
|
+
config: RunnableConfig | None = None,
|
|
89
87
|
**kwargs: Any,
|
|
90
88
|
) -> T:
|
|
91
89
|
if isinstance(input, BaseMessage):
|
|
@@ -107,9 +105,9 @@ class BaseGenerationOutputParser(
|
|
|
107
105
|
@override
|
|
108
106
|
async def ainvoke(
|
|
109
107
|
self,
|
|
110
|
-
input:
|
|
111
|
-
config:
|
|
112
|
-
**kwargs:
|
|
108
|
+
input: str | BaseMessage,
|
|
109
|
+
config: RunnableConfig | None = None,
|
|
110
|
+
**kwargs: Any | None,
|
|
113
111
|
) -> T:
|
|
114
112
|
if isinstance(input, BaseMessage):
|
|
115
113
|
return await self._acall_with_config(
|
|
@@ -136,36 +134,35 @@ class BaseOutputParser(
|
|
|
136
134
|
Output parsers help structure language model responses.
|
|
137
135
|
|
|
138
136
|
Example:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
137
|
+
```python
|
|
138
|
+
class BooleanOutputParser(BaseOutputParser[bool]):
|
|
139
|
+
true_val: str = "YES"
|
|
140
|
+
false_val: str = "NO"
|
|
141
|
+
|
|
142
|
+
def parse(self, text: str) -> bool:
|
|
143
|
+
cleaned_text = text.strip().upper()
|
|
144
|
+
if cleaned_text not in (
|
|
145
|
+
self.true_val.upper(),
|
|
146
|
+
self.false_val.upper(),
|
|
147
|
+
):
|
|
148
|
+
raise OutputParserException(
|
|
149
|
+
f"BooleanOutputParser expected output value to either be "
|
|
150
|
+
f"{self.true_val} or {self.false_val} (case-insensitive). "
|
|
151
|
+
f"Received {cleaned_text}."
|
|
152
|
+
)
|
|
153
|
+
return cleaned_text == self.true_val.upper()
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def _type(self) -> str:
|
|
157
|
+
return "boolean_output_parser"
|
|
158
|
+
```
|
|
162
159
|
"""
|
|
163
160
|
|
|
164
161
|
@property
|
|
165
162
|
@override
|
|
166
163
|
def InputType(self) -> Any:
|
|
167
164
|
"""Return the input type for the parser."""
|
|
168
|
-
return
|
|
165
|
+
return str | AnyMessage
|
|
169
166
|
|
|
170
167
|
@property
|
|
171
168
|
@override
|
|
@@ -175,7 +172,7 @@ class BaseOutputParser(
|
|
|
175
172
|
This property is inferred from the first type argument of the class.
|
|
176
173
|
|
|
177
174
|
Raises:
|
|
178
|
-
TypeError: If the class doesn't have an inferable OutputType
|
|
175
|
+
TypeError: If the class doesn't have an inferable `OutputType`.
|
|
179
176
|
"""
|
|
180
177
|
for base in self.__class__.mro():
|
|
181
178
|
if hasattr(base, "__pydantic_generic_metadata__"):
|
|
@@ -192,8 +189,8 @@ class BaseOutputParser(
|
|
|
192
189
|
@override
|
|
193
190
|
def invoke(
|
|
194
191
|
self,
|
|
195
|
-
input:
|
|
196
|
-
config:
|
|
192
|
+
input: str | BaseMessage,
|
|
193
|
+
config: RunnableConfig | None = None,
|
|
197
194
|
**kwargs: Any,
|
|
198
195
|
) -> T:
|
|
199
196
|
if isinstance(input, BaseMessage):
|
|
@@ -215,9 +212,9 @@ class BaseOutputParser(
|
|
|
215
212
|
@override
|
|
216
213
|
async def ainvoke(
|
|
217
214
|
self,
|
|
218
|
-
input:
|
|
219
|
-
config:
|
|
220
|
-
**kwargs:
|
|
215
|
+
input: str | BaseMessage,
|
|
216
|
+
config: RunnableConfig | None = None,
|
|
217
|
+
**kwargs: Any | None,
|
|
221
218
|
) -> T:
|
|
222
219
|
if isinstance(input, BaseMessage):
|
|
223
220
|
return await self._acall_with_config(
|
|
@@ -237,16 +234,16 @@ class BaseOutputParser(
|
|
|
237
234
|
|
|
238
235
|
@override
|
|
239
236
|
def parse_result(self, result: list[Generation], *, partial: bool = False) -> T:
|
|
240
|
-
"""Parse a list of candidate model
|
|
237
|
+
"""Parse a list of candidate model `Generation` objects into a specific format.
|
|
241
238
|
|
|
242
|
-
The return value is parsed from only the first Generation in the result, which
|
|
243
|
-
is assumed to be the highest-likelihood Generation
|
|
239
|
+
The return value is parsed from only the first `Generation` in the result, which
|
|
240
|
+
is assumed to be the highest-likelihood `Generation`.
|
|
244
241
|
|
|
245
242
|
Args:
|
|
246
|
-
result: A list of
|
|
247
|
-
to be different candidate outputs for a single model input.
|
|
243
|
+
result: A list of `Generation` to be parsed. The `Generation` objects are
|
|
244
|
+
assumed to be different candidate outputs for a single model input.
|
|
248
245
|
partial: Whether to parse the output as a partial result. This is useful
|
|
249
|
-
for parsers that can parse partial results.
|
|
246
|
+
for parsers that can parse partial results.
|
|
250
247
|
|
|
251
248
|
Returns:
|
|
252
249
|
Structured output.
|
|
@@ -267,20 +264,20 @@ class BaseOutputParser(
|
|
|
267
264
|
async def aparse_result(
|
|
268
265
|
self, result: list[Generation], *, partial: bool = False
|
|
269
266
|
) -> T:
|
|
270
|
-
"""Async parse a list of candidate model
|
|
267
|
+
"""Async parse a list of candidate model `Generation` objects into a specific format.
|
|
271
268
|
|
|
272
|
-
The return value is parsed from only the first Generation in the result, which
|
|
273
|
-
is assumed to be the highest-likelihood Generation
|
|
269
|
+
The return value is parsed from only the first `Generation` in the result, which
|
|
270
|
+
is assumed to be the highest-likelihood `Generation`.
|
|
274
271
|
|
|
275
272
|
Args:
|
|
276
|
-
result: A list of
|
|
277
|
-
to be different candidate outputs for a single model input.
|
|
273
|
+
result: A list of `Generation` to be parsed. The `Generation` objects are
|
|
274
|
+
assumed to be different candidate outputs for a single model input.
|
|
278
275
|
partial: Whether to parse the output as a partial result. This is useful
|
|
279
|
-
for parsers that can parse partial results.
|
|
276
|
+
for parsers that can parse partial results.
|
|
280
277
|
|
|
281
278
|
Returns:
|
|
282
279
|
Structured output.
|
|
283
|
-
"""
|
|
280
|
+
""" # noqa: E501
|
|
284
281
|
return await run_in_executor(None, self.parse_result, result, partial=partial)
|
|
285
282
|
|
|
286
283
|
async def aparse(self, text: str) -> T:
|
|
@@ -302,13 +299,13 @@ class BaseOutputParser(
|
|
|
302
299
|
) -> Any:
|
|
303
300
|
"""Parse the output of an LLM call with the input prompt for context.
|
|
304
301
|
|
|
305
|
-
The prompt is largely provided in the event the OutputParser wants
|
|
302
|
+
The prompt is largely provided in the event the `OutputParser` wants
|
|
306
303
|
to retry or fix the output in some way, and needs information from
|
|
307
304
|
the prompt to do so.
|
|
308
305
|
|
|
309
306
|
Args:
|
|
310
307
|
completion: String output of a language model.
|
|
311
|
-
prompt: Input PromptValue
|
|
308
|
+
prompt: Input `PromptValue`.
|
|
312
309
|
|
|
313
310
|
Returns:
|
|
314
311
|
Structured output.
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
from json import JSONDecodeError
|
|
7
|
-
from typing import Annotated, Any,
|
|
7
|
+
from typing import Annotated, Any, TypeVar
|
|
8
8
|
|
|
9
9
|
import jsonpatch # type: ignore[import-untyped]
|
|
10
10
|
import pydantic
|
|
@@ -23,7 +23,7 @@ from langchain_core.utils.json import (
|
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
# Union type needs to be last assignment to PydanticBaseModel to make mypy happy.
|
|
26
|
-
PydanticBaseModel =
|
|
26
|
+
PydanticBaseModel = BaseModel | pydantic.BaseModel
|
|
27
27
|
|
|
28
28
|
TBaseModel = TypeVar("TBaseModel", bound=PydanticBaseModel)
|
|
29
29
|
|
|
@@ -38,12 +38,12 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
38
38
|
describing the difference between the previous and the current object.
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
pydantic_object: Annotated[
|
|
41
|
+
pydantic_object: Annotated[type[TBaseModel] | None, SkipValidation()] = None # type: ignore[valid-type]
|
|
42
42
|
"""The Pydantic object to use for validation.
|
|
43
|
-
If None
|
|
43
|
+
If `None`, no validation is performed."""
|
|
44
44
|
|
|
45
45
|
@override
|
|
46
|
-
def _diff(self, prev:
|
|
46
|
+
def _diff(self, prev: Any | None, next: Any) -> Any:
|
|
47
47
|
return jsonpatch.make_patch(prev, next).patch
|
|
48
48
|
|
|
49
49
|
@staticmethod
|
|
@@ -59,10 +59,9 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
59
59
|
Args:
|
|
60
60
|
result: The result of the LLM call.
|
|
61
61
|
partial: Whether to parse partial JSON objects.
|
|
62
|
-
If True
|
|
62
|
+
If `True`, the output will be a JSON object containing
|
|
63
63
|
all the keys that have been returned so far.
|
|
64
|
-
If False
|
|
65
|
-
Default is False.
|
|
64
|
+
If `False`, the output will be the full JSON object.
|
|
66
65
|
|
|
67
66
|
Returns:
|
|
68
67
|
The parsed JSON object.
|
|
@@ -7,7 +7,7 @@ import re
|
|
|
7
7
|
from abc import abstractmethod
|
|
8
8
|
from collections import deque
|
|
9
9
|
from io import StringIO
|
|
10
|
-
from typing import TYPE_CHECKING, TypeVar
|
|
10
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
11
11
|
|
|
12
12
|
from typing_extensions import override
|
|
13
13
|
|
|
@@ -70,9 +70,7 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
70
70
|
raise NotImplementedError
|
|
71
71
|
|
|
72
72
|
@override
|
|
73
|
-
def _transform(
|
|
74
|
-
self, input: Iterator[Union[str, BaseMessage]]
|
|
75
|
-
) -> Iterator[list[str]]:
|
|
73
|
+
def _transform(self, input: Iterator[str | BaseMessage]) -> Iterator[list[str]]:
|
|
76
74
|
buffer = ""
|
|
77
75
|
for chunk in input:
|
|
78
76
|
if isinstance(chunk, BaseMessage):
|
|
@@ -105,7 +103,7 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
105
103
|
|
|
106
104
|
@override
|
|
107
105
|
async def _atransform(
|
|
108
|
-
self, input: AsyncIterator[
|
|
106
|
+
self, input: AsyncIterator[str | BaseMessage]
|
|
109
107
|
) -> AsyncIterator[list[str]]:
|
|
110
108
|
buffer = ""
|
|
111
109
|
async for chunk in input:
|
|
@@ -148,10 +146,10 @@ class CommaSeparatedListOutputParser(ListOutputParser):
|
|
|
148
146
|
|
|
149
147
|
@classmethod
|
|
150
148
|
def get_lc_namespace(cls) -> list[str]:
|
|
151
|
-
"""Get the namespace of the
|
|
149
|
+
"""Get the namespace of the LangChain object.
|
|
152
150
|
|
|
153
151
|
Returns:
|
|
154
|
-
|
|
152
|
+
`["langchain", "output_parsers", "list"]`
|
|
155
153
|
"""
|
|
156
154
|
return ["langchain", "output_parsers", "list"]
|
|
157
155
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import copy
|
|
4
4
|
import json
|
|
5
5
|
from types import GenericAlias
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
import jsonpatch # type: ignore[import-untyped]
|
|
9
9
|
from pydantic import BaseModel, model_validator
|
|
@@ -31,13 +31,13 @@ class OutputFunctionsParser(BaseGenerationOutputParser[Any]):
|
|
|
31
31
|
|
|
32
32
|
Args:
|
|
33
33
|
result: The result of the LLM call.
|
|
34
|
-
partial: Whether to parse partial JSON objects.
|
|
34
|
+
partial: Whether to parse partial JSON objects.
|
|
35
35
|
|
|
36
36
|
Returns:
|
|
37
37
|
The parsed JSON object.
|
|
38
38
|
|
|
39
39
|
Raises:
|
|
40
|
-
OutputParserException
|
|
40
|
+
`OutputParserException`: If the output is not valid JSON.
|
|
41
41
|
"""
|
|
42
42
|
generation = result[0]
|
|
43
43
|
if not isinstance(generation, ChatGeneration):
|
|
@@ -56,7 +56,7 @@ class OutputFunctionsParser(BaseGenerationOutputParser[Any]):
|
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class JsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
59
|
-
"""Parse an output as the
|
|
59
|
+
"""Parse an output as the JSON object."""
|
|
60
60
|
|
|
61
61
|
strict: bool = False
|
|
62
62
|
"""Whether to allow non-JSON-compliant strings.
|
|
@@ -74,7 +74,7 @@ class JsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
74
74
|
return "json_functions"
|
|
75
75
|
|
|
76
76
|
@override
|
|
77
|
-
def _diff(self, prev:
|
|
77
|
+
def _diff(self, prev: Any | None, next: Any) -> Any:
|
|
78
78
|
return jsonpatch.make_patch(prev, next).patch
|
|
79
79
|
|
|
80
80
|
def parse_result(self, result: list[Generation], *, partial: bool = False) -> Any:
|
|
@@ -82,13 +82,13 @@ class JsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
82
82
|
|
|
83
83
|
Args:
|
|
84
84
|
result: The result of the LLM call.
|
|
85
|
-
partial: Whether to parse partial JSON objects.
|
|
85
|
+
partial: Whether to parse partial JSON objects.
|
|
86
86
|
|
|
87
87
|
Returns:
|
|
88
88
|
The parsed JSON object.
|
|
89
89
|
|
|
90
90
|
Raises:
|
|
91
|
-
|
|
91
|
+
OutputParserExcept`ion: If the output is not valid JSON.
|
|
92
92
|
"""
|
|
93
93
|
if len(result) != 1:
|
|
94
94
|
msg = f"Expected exactly one result, but got {len(result)}"
|
|
@@ -155,7 +155,7 @@ class JsonOutputFunctionsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
class JsonKeyOutputFunctionsParser(JsonOutputFunctionsParser):
|
|
158
|
-
"""Parse an output as the element of the
|
|
158
|
+
"""Parse an output as the element of the JSON object."""
|
|
159
159
|
|
|
160
160
|
key_name: str
|
|
161
161
|
"""The name of the key to return."""
|
|
@@ -165,7 +165,7 @@ class JsonKeyOutputFunctionsParser(JsonOutputFunctionsParser):
|
|
|
165
165
|
|
|
166
166
|
Args:
|
|
167
167
|
result: The result of the LLM call.
|
|
168
|
-
partial: Whether to parse partial JSON objects.
|
|
168
|
+
partial: Whether to parse partial JSON objects.
|
|
169
169
|
|
|
170
170
|
Returns:
|
|
171
171
|
The parsed JSON object.
|
|
@@ -177,48 +177,50 @@ class JsonKeyOutputFunctionsParser(JsonOutputFunctionsParser):
|
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
class PydanticOutputFunctionsParser(OutputFunctionsParser):
|
|
180
|
-
"""Parse an output as a
|
|
180
|
+
"""Parse an output as a Pydantic object.
|
|
181
181
|
|
|
182
|
-
This parser is used to parse the output of a
|
|
183
|
-
|
|
182
|
+
This parser is used to parse the output of a chat model that uses OpenAI function
|
|
183
|
+
format to invoke functions.
|
|
184
184
|
|
|
185
|
-
The parser extracts the function call invocation and matches
|
|
186
|
-
|
|
185
|
+
The parser extracts the function call invocation and matches them to the Pydantic
|
|
186
|
+
schema provided.
|
|
187
187
|
|
|
188
|
-
An exception will be raised if the function call does not match
|
|
189
|
-
the provided schema.
|
|
188
|
+
An exception will be raised if the function call does not match the provided schema.
|
|
190
189
|
|
|
191
190
|
Example:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
chat_generation = ChatGeneration(message=message)
|
|
191
|
+
```python
|
|
192
|
+
message = AIMessage(
|
|
193
|
+
content="This is a test message",
|
|
194
|
+
additional_kwargs={
|
|
195
|
+
"function_call": {
|
|
196
|
+
"name": "cookie",
|
|
197
|
+
"arguments": json.dumps({"name": "value", "age": 10}),
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
)
|
|
201
|
+
chat_generation = ChatGeneration(message=message)
|
|
204
202
|
|
|
205
|
-
class Cookie(BaseModel):
|
|
206
|
-
name: str
|
|
207
|
-
age: int
|
|
208
203
|
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
class Cookie(BaseModel):
|
|
205
|
+
name: str
|
|
206
|
+
age: int
|
|
211
207
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
208
|
+
|
|
209
|
+
class Dog(BaseModel):
|
|
210
|
+
species: str
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# Full output
|
|
214
|
+
parser = PydanticOutputFunctionsParser(
|
|
215
|
+
pydantic_schema={"cookie": Cookie, "dog": Dog}
|
|
216
|
+
)
|
|
217
|
+
result = parser.parse_result([chat_generation])
|
|
218
|
+
```
|
|
217
219
|
|
|
218
220
|
"""
|
|
219
221
|
|
|
220
|
-
pydantic_schema:
|
|
221
|
-
"""The
|
|
222
|
+
pydantic_schema: type[BaseModel] | dict[str, type[BaseModel]]
|
|
223
|
+
"""The Pydantic schema to parse the output with.
|
|
222
224
|
|
|
223
225
|
If multiple schemas are provided, then the function name will be used to
|
|
224
226
|
determine which schema to use.
|
|
@@ -227,7 +229,7 @@ class PydanticOutputFunctionsParser(OutputFunctionsParser):
|
|
|
227
229
|
@model_validator(mode="before")
|
|
228
230
|
@classmethod
|
|
229
231
|
def validate_schema(cls, values: dict) -> Any:
|
|
230
|
-
"""Validate the
|
|
232
|
+
"""Validate the Pydantic schema.
|
|
231
233
|
|
|
232
234
|
Args:
|
|
233
235
|
values: The values to validate.
|
|
@@ -236,7 +238,7 @@ class PydanticOutputFunctionsParser(OutputFunctionsParser):
|
|
|
236
238
|
The validated values.
|
|
237
239
|
|
|
238
240
|
Raises:
|
|
239
|
-
ValueError: If the schema is not a
|
|
241
|
+
ValueError: If the schema is not a Pydantic schema.
|
|
240
242
|
"""
|
|
241
243
|
schema = values["pydantic_schema"]
|
|
242
244
|
if "args_only" not in values:
|
|
@@ -259,10 +261,10 @@ class PydanticOutputFunctionsParser(OutputFunctionsParser):
|
|
|
259
261
|
|
|
260
262
|
Args:
|
|
261
263
|
result: The result of the LLM call.
|
|
262
|
-
partial: Whether to parse partial JSON objects.
|
|
264
|
+
partial: Whether to parse partial JSON objects.
|
|
263
265
|
|
|
264
266
|
Raises:
|
|
265
|
-
ValueError: If the
|
|
267
|
+
ValueError: If the Pydantic schema is not valid.
|
|
266
268
|
|
|
267
269
|
Returns:
|
|
268
270
|
The parsed JSON object.
|
|
@@ -285,13 +287,13 @@ class PydanticOutputFunctionsParser(OutputFunctionsParser):
|
|
|
285
287
|
elif issubclass(pydantic_schema, BaseModelV1):
|
|
286
288
|
pydantic_args = pydantic_schema.parse_raw(args)
|
|
287
289
|
else:
|
|
288
|
-
msg = f"Unsupported
|
|
290
|
+
msg = f"Unsupported Pydantic schema: {pydantic_schema}"
|
|
289
291
|
raise ValueError(msg)
|
|
290
292
|
return pydantic_args
|
|
291
293
|
|
|
292
294
|
|
|
293
295
|
class PydanticAttrOutputFunctionsParser(PydanticOutputFunctionsParser):
|
|
294
|
-
"""Parse an output as an attribute of a
|
|
296
|
+
"""Parse an output as an attribute of a Pydantic object."""
|
|
295
297
|
|
|
296
298
|
attr_name: str
|
|
297
299
|
"""The name of the attribute to return."""
|
|
@@ -302,7 +304,7 @@ class PydanticAttrOutputFunctionsParser(PydanticOutputFunctionsParser):
|
|
|
302
304
|
|
|
303
305
|
Args:
|
|
304
306
|
result: The result of the LLM call.
|
|
305
|
-
partial: Whether to parse partial JSON objects.
|
|
307
|
+
partial: Whether to parse partial JSON objects.
|
|
306
308
|
|
|
307
309
|
Returns:
|
|
308
310
|
The parsed JSON object.
|
|
@@ -4,7 +4,7 @@ import copy
|
|
|
4
4
|
import json
|
|
5
5
|
import logging
|
|
6
6
|
from json import JSONDecodeError
|
|
7
|
-
from typing import Annotated, Any
|
|
7
|
+
from typing import Annotated, Any
|
|
8
8
|
|
|
9
9
|
from pydantic import SkipValidation, ValidationError
|
|
10
10
|
|
|
@@ -26,15 +26,14 @@ def parse_tool_call(
|
|
|
26
26
|
partial: bool = False,
|
|
27
27
|
strict: bool = False,
|
|
28
28
|
return_id: bool = True,
|
|
29
|
-
) ->
|
|
29
|
+
) -> dict[str, Any] | None:
|
|
30
30
|
"""Parse a single tool call.
|
|
31
31
|
|
|
32
32
|
Args:
|
|
33
33
|
raw_tool_call: The raw tool call to parse.
|
|
34
|
-
partial: Whether to parse partial JSON.
|
|
34
|
+
partial: Whether to parse partial JSON.
|
|
35
35
|
strict: Whether to allow non-JSON-compliant strings.
|
|
36
|
-
|
|
37
|
-
return_id: Whether to return the tool call id. Default is True.
|
|
36
|
+
return_id: Whether to return the tool call id.
|
|
38
37
|
|
|
39
38
|
Returns:
|
|
40
39
|
The parsed tool call.
|
|
@@ -75,7 +74,7 @@ def parse_tool_call(
|
|
|
75
74
|
|
|
76
75
|
def make_invalid_tool_call(
|
|
77
76
|
raw_tool_call: dict[str, Any],
|
|
78
|
-
error_msg:
|
|
77
|
+
error_msg: str | None,
|
|
79
78
|
) -> InvalidToolCall:
|
|
80
79
|
"""Create an InvalidToolCall from a raw tool call.
|
|
81
80
|
|
|
@@ -105,10 +104,9 @@ def parse_tool_calls(
|
|
|
105
104
|
|
|
106
105
|
Args:
|
|
107
106
|
raw_tool_calls: The raw tool calls to parse.
|
|
108
|
-
partial: Whether to parse partial JSON.
|
|
107
|
+
partial: Whether to parse partial JSON.
|
|
109
108
|
strict: Whether to allow non-JSON-compliant strings.
|
|
110
|
-
|
|
111
|
-
return_id: Whether to return the tool call id. Default is True.
|
|
109
|
+
return_id: Whether to return the tool call id.
|
|
112
110
|
|
|
113
111
|
Returns:
|
|
114
112
|
The parsed tool calls.
|
|
@@ -148,7 +146,7 @@ class JsonOutputToolsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
148
146
|
first_tool_only: bool = False
|
|
149
147
|
"""Whether to return only the first tool call.
|
|
150
148
|
|
|
151
|
-
If False
|
|
149
|
+
If `False`, the result will be a list of tool calls, or an empty list
|
|
152
150
|
if no tool calls are found.
|
|
153
151
|
|
|
154
152
|
If true, and multiple tool calls are found, only the first one will be returned,
|
|
@@ -162,10 +160,9 @@ class JsonOutputToolsParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
162
160
|
Args:
|
|
163
161
|
result: The result of the LLM call.
|
|
164
162
|
partial: Whether to parse partial JSON.
|
|
165
|
-
If True
|
|
163
|
+
If `True`, the output will be a JSON object containing
|
|
166
164
|
all the keys that have been returned so far.
|
|
167
|
-
If False
|
|
168
|
-
Default is False.
|
|
165
|
+
If `False`, the output will be the full JSON object.
|
|
169
166
|
|
|
170
167
|
Returns:
|
|
171
168
|
The parsed tool calls.
|
|
@@ -226,10 +223,9 @@ class JsonOutputKeyToolsParser(JsonOutputToolsParser):
|
|
|
226
223
|
Args:
|
|
227
224
|
result: The result of the LLM call.
|
|
228
225
|
partial: Whether to parse partial JSON.
|
|
229
|
-
If True
|
|
226
|
+
If `True`, the output will be a JSON object containing
|
|
230
227
|
all the keys that have been returned so far.
|
|
231
|
-
If False
|
|
232
|
-
Default is False.
|
|
228
|
+
If `False`, the output will be the full JSON object.
|
|
233
229
|
|
|
234
230
|
Raises:
|
|
235
231
|
OutputParserException: If the generation is not a chat generation.
|
|
@@ -310,10 +306,9 @@ class PydanticToolsParser(JsonOutputToolsParser):
|
|
|
310
306
|
Args:
|
|
311
307
|
result: The result of the LLM call.
|
|
312
308
|
partial: Whether to parse partial JSON.
|
|
313
|
-
If True
|
|
309
|
+
If `True`, the output will be a JSON object containing
|
|
314
310
|
all the keys that have been returned so far.
|
|
315
|
-
If False
|
|
316
|
-
Default is False.
|
|
311
|
+
If `False`, the output will be the full JSON object.
|
|
317
312
|
|
|
318
313
|
Returns:
|
|
319
314
|
The parsed Pydantic objects.
|