langchain-core 0.4.0.dev0__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 +45 -70
- langchain_core/_api/deprecation.py +80 -80
- langchain_core/_api/path.py +22 -8
- langchain_core/_import_utils.py +10 -4
- langchain_core/agents.py +25 -21
- langchain_core/caches.py +53 -63
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +341 -348
- langchain_core/callbacks/file.py +55 -44
- langchain_core/callbacks/manager.py +546 -683
- langchain_core/callbacks/stdout.py +29 -30
- langchain_core/callbacks/streaming_stdout.py +35 -36
- langchain_core/callbacks/usage.py +65 -70
- langchain_core/chat_history.py +48 -55
- langchain_core/document_loaders/base.py +46 -21
- langchain_core/document_loaders/langsmith.py +39 -36
- langchain_core/documents/__init__.py +0 -1
- langchain_core/documents/base.py +96 -74
- langchain_core/documents/compressor.py +12 -9
- langchain_core/documents/transformers.py +29 -28
- langchain_core/embeddings/fake.py +56 -57
- langchain_core/env.py +2 -3
- langchain_core/example_selectors/base.py +12 -0
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/example_selectors/semantic_similarity.py +21 -25
- langchain_core/exceptions.py +15 -9
- langchain_core/globals.py +4 -163
- langchain_core/indexing/api.py +132 -125
- langchain_core/indexing/base.py +64 -67
- langchain_core/indexing/in_memory.py +26 -6
- langchain_core/language_models/__init__.py +15 -27
- langchain_core/language_models/_utils.py +267 -117
- langchain_core/language_models/base.py +92 -177
- langchain_core/language_models/chat_models.py +547 -407
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +72 -118
- langchain_core/language_models/llms.py +168 -242
- langchain_core/load/dump.py +8 -11
- langchain_core/load/load.py +32 -28
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +50 -56
- langchain_core/messages/__init__.py +36 -51
- langchain_core/messages/ai.py +377 -150
- langchain_core/messages/base.py +239 -47
- 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 -3
- langchain_core/messages/content.py +1423 -0
- langchain_core/messages/function.py +7 -7
- langchain_core/messages/human.py +44 -38
- langchain_core/messages/modifier.py +3 -2
- langchain_core/messages/system.py +40 -27
- langchain_core/messages/tool.py +160 -58
- langchain_core/messages/utils.py +527 -638
- langchain_core/output_parsers/__init__.py +1 -14
- langchain_core/output_parsers/base.py +68 -104
- langchain_core/output_parsers/json.py +13 -17
- langchain_core/output_parsers/list.py +11 -33
- langchain_core/output_parsers/openai_functions.py +56 -74
- langchain_core/output_parsers/openai_tools.py +68 -109
- langchain_core/output_parsers/pydantic.py +15 -13
- langchain_core/output_parsers/string.py +6 -2
- langchain_core/output_parsers/transform.py +17 -60
- langchain_core/output_parsers/xml.py +34 -44
- langchain_core/outputs/__init__.py +1 -1
- langchain_core/outputs/chat_generation.py +26 -11
- langchain_core/outputs/chat_result.py +1 -3
- langchain_core/outputs/generation.py +17 -6
- langchain_core/outputs/llm_result.py +15 -8
- langchain_core/prompt_values.py +29 -123
- langchain_core/prompts/__init__.py +3 -27
- langchain_core/prompts/base.py +48 -63
- langchain_core/prompts/chat.py +259 -288
- langchain_core/prompts/dict.py +19 -11
- langchain_core/prompts/few_shot.py +84 -90
- langchain_core/prompts/few_shot_with_templates.py +14 -12
- langchain_core/prompts/image.py +19 -14
- langchain_core/prompts/loading.py +6 -8
- langchain_core/prompts/message.py +7 -8
- langchain_core/prompts/prompt.py +42 -43
- langchain_core/prompts/string.py +37 -16
- langchain_core/prompts/structured.py +43 -46
- langchain_core/rate_limiters.py +51 -60
- langchain_core/retrievers.py +52 -192
- langchain_core/runnables/base.py +1727 -1683
- langchain_core/runnables/branch.py +52 -73
- langchain_core/runnables/config.py +89 -103
- langchain_core/runnables/configurable.py +128 -130
- langchain_core/runnables/fallbacks.py +93 -82
- langchain_core/runnables/graph.py +127 -127
- langchain_core/runnables/graph_ascii.py +63 -41
- langchain_core/runnables/graph_mermaid.py +87 -70
- langchain_core/runnables/graph_png.py +31 -36
- langchain_core/runnables/history.py +145 -161
- langchain_core/runnables/passthrough.py +141 -144
- langchain_core/runnables/retry.py +84 -68
- langchain_core/runnables/router.py +33 -37
- langchain_core/runnables/schema.py +79 -72
- langchain_core/runnables/utils.py +95 -139
- langchain_core/stores.py +85 -131
- langchain_core/structured_query.py +11 -15
- langchain_core/sys_info.py +31 -32
- langchain_core/tools/__init__.py +1 -14
- langchain_core/tools/base.py +221 -247
- langchain_core/tools/convert.py +144 -161
- langchain_core/tools/render.py +10 -10
- langchain_core/tools/retriever.py +12 -19
- langchain_core/tools/simple.py +52 -29
- langchain_core/tools/structured.py +56 -60
- langchain_core/tracers/__init__.py +1 -9
- langchain_core/tracers/_streaming.py +6 -7
- langchain_core/tracers/base.py +103 -112
- langchain_core/tracers/context.py +29 -48
- langchain_core/tracers/core.py +142 -105
- langchain_core/tracers/evaluation.py +30 -34
- langchain_core/tracers/event_stream.py +162 -117
- langchain_core/tracers/langchain.py +34 -36
- langchain_core/tracers/log_stream.py +87 -49
- langchain_core/tracers/memory_stream.py +3 -3
- langchain_core/tracers/root_listeners.py +18 -34
- langchain_core/tracers/run_collector.py +8 -20
- langchain_core/tracers/schemas.py +0 -125
- langchain_core/tracers/stdout.py +3 -3
- langchain_core/utils/__init__.py +1 -4
- langchain_core/utils/_merge.py +47 -9
- langchain_core/utils/aiter.py +70 -66
- langchain_core/utils/env.py +12 -9
- langchain_core/utils/function_calling.py +139 -206
- langchain_core/utils/html.py +7 -8
- langchain_core/utils/input.py +6 -6
- langchain_core/utils/interactive_env.py +6 -2
- langchain_core/utils/iter.py +48 -45
- langchain_core/utils/json.py +14 -4
- langchain_core/utils/json_schema.py +159 -43
- langchain_core/utils/mustache.py +32 -25
- langchain_core/utils/pydantic.py +67 -40
- langchain_core/utils/strings.py +5 -5
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +104 -62
- langchain_core/vectorstores/base.py +131 -179
- langchain_core/vectorstores/in_memory.py +113 -182
- langchain_core/vectorstores/utils.py +23 -17
- langchain_core/version.py +1 -1
- langchain_core-1.0.0.dist-info/METADATA +68 -0
- langchain_core-1.0.0.dist-info/RECORD +172 -0
- {langchain_core-0.4.0.dev0.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 -448
- langchain_core/memory.py +0 -116
- langchain_core/messages/content_blocks.py +0 -1435
- langchain_core/prompts/pipeline.py +0 -133
- 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 -23
- langchain_core/utils/loading.py +0 -31
- langchain_core/v1/__init__.py +0 -1
- langchain_core/v1/chat_models.py +0 -1047
- langchain_core/v1/messages.py +0 -755
- langchain_core-0.4.0.dev0.dist-info/METADATA +0 -108
- langchain_core-0.4.0.dev0.dist-info/RECORD +0 -177
- langchain_core-0.4.0.dev0.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,10 +8,7 @@ from typing import (
|
|
|
8
8
|
TYPE_CHECKING,
|
|
9
9
|
Any,
|
|
10
10
|
Generic,
|
|
11
|
-
Optional,
|
|
12
11
|
TypeVar,
|
|
13
|
-
Union,
|
|
14
|
-
cast,
|
|
15
12
|
)
|
|
16
13
|
|
|
17
14
|
from typing_extensions import override
|
|
@@ -21,48 +18,45 @@ from langchain_core.messages import AnyMessage, BaseMessage
|
|
|
21
18
|
from langchain_core.outputs import ChatGeneration, Generation
|
|
22
19
|
from langchain_core.runnables import Runnable, RunnableConfig, RunnableSerializable
|
|
23
20
|
from langchain_core.runnables.config import run_in_executor
|
|
24
|
-
from langchain_core.v1.messages import AIMessage, MessageV1, MessageV1Types
|
|
25
21
|
|
|
26
22
|
if TYPE_CHECKING:
|
|
27
23
|
from langchain_core.prompt_values import PromptValue
|
|
28
24
|
|
|
29
25
|
T = TypeVar("T")
|
|
30
|
-
OutputParserLike = Runnable[
|
|
26
|
+
OutputParserLike = Runnable[LanguageModelOutput, T]
|
|
31
27
|
|
|
32
28
|
|
|
33
29
|
class BaseLLMOutputParser(ABC, Generic[T]):
|
|
34
30
|
"""Abstract base class for parsing the outputs of a model."""
|
|
35
31
|
|
|
36
32
|
@abstractmethod
|
|
37
|
-
def parse_result(
|
|
38
|
-
|
|
39
|
-
) -> T:
|
|
40
|
-
"""Parse a list of candidate model Generations into a specific format.
|
|
33
|
+
def parse_result(self, result: list[Generation], *, partial: bool = False) -> T:
|
|
34
|
+
"""Parse a list of candidate model `Generation` objects into a specific format.
|
|
41
35
|
|
|
42
36
|
Args:
|
|
43
|
-
result: A list of
|
|
44
|
-
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.
|
|
45
39
|
partial: Whether to parse the output as a partial result. This is useful
|
|
46
|
-
for parsers that can parse partial results.
|
|
40
|
+
for parsers that can parse partial results.
|
|
47
41
|
|
|
48
42
|
Returns:
|
|
49
43
|
Structured output.
|
|
50
44
|
"""
|
|
51
45
|
|
|
52
46
|
async def aparse_result(
|
|
53
|
-
self, result:
|
|
47
|
+
self, result: list[Generation], *, partial: bool = False
|
|
54
48
|
) -> T:
|
|
55
|
-
"""Async parse a list of candidate model
|
|
49
|
+
"""Async parse a list of candidate model `Generation` objects into a specific format.
|
|
56
50
|
|
|
57
51
|
Args:
|
|
58
|
-
result: A list of
|
|
52
|
+
result: A list of `Generation` to be parsed. The Generations are assumed
|
|
59
53
|
to be different candidate outputs for a single model input.
|
|
60
54
|
partial: Whether to parse the output as a partial result. This is useful
|
|
61
|
-
for parsers that can parse partial results.
|
|
55
|
+
for parsers that can parse partial results.
|
|
62
56
|
|
|
63
57
|
Returns:
|
|
64
58
|
Structured output.
|
|
65
|
-
"""
|
|
59
|
+
""" # noqa: E501
|
|
66
60
|
return await run_in_executor(None, self.parse_result, result, partial=partial)
|
|
67
61
|
|
|
68
62
|
|
|
@@ -75,7 +69,7 @@ class BaseGenerationOutputParser(
|
|
|
75
69
|
@override
|
|
76
70
|
def InputType(self) -> Any:
|
|
77
71
|
"""Return the input type for the parser."""
|
|
78
|
-
return
|
|
72
|
+
return str | AnyMessage
|
|
79
73
|
|
|
80
74
|
@property
|
|
81
75
|
@override
|
|
@@ -88,8 +82,8 @@ class BaseGenerationOutputParser(
|
|
|
88
82
|
@override
|
|
89
83
|
def invoke(
|
|
90
84
|
self,
|
|
91
|
-
input:
|
|
92
|
-
config:
|
|
85
|
+
input: str | BaseMessage,
|
|
86
|
+
config: RunnableConfig | None = None,
|
|
93
87
|
**kwargs: Any,
|
|
94
88
|
) -> T:
|
|
95
89
|
if isinstance(input, BaseMessage):
|
|
@@ -101,16 +95,9 @@ class BaseGenerationOutputParser(
|
|
|
101
95
|
config,
|
|
102
96
|
run_type="parser",
|
|
103
97
|
)
|
|
104
|
-
if isinstance(input, MessageV1Types):
|
|
105
|
-
return self._call_with_config(
|
|
106
|
-
lambda inner_input: self.parse_result(inner_input),
|
|
107
|
-
input,
|
|
108
|
-
config,
|
|
109
|
-
run_type="parser",
|
|
110
|
-
)
|
|
111
98
|
return self._call_with_config(
|
|
112
99
|
lambda inner_input: self.parse_result([Generation(text=inner_input)]),
|
|
113
|
-
|
|
100
|
+
input,
|
|
114
101
|
config,
|
|
115
102
|
run_type="parser",
|
|
116
103
|
)
|
|
@@ -118,9 +105,9 @@ class BaseGenerationOutputParser(
|
|
|
118
105
|
@override
|
|
119
106
|
async def ainvoke(
|
|
120
107
|
self,
|
|
121
|
-
input:
|
|
122
|
-
config:
|
|
123
|
-
**kwargs:
|
|
108
|
+
input: str | BaseMessage,
|
|
109
|
+
config: RunnableConfig | None = None,
|
|
110
|
+
**kwargs: Any | None,
|
|
124
111
|
) -> T:
|
|
125
112
|
if isinstance(input, BaseMessage):
|
|
126
113
|
return await self._acall_with_config(
|
|
@@ -131,13 +118,6 @@ class BaseGenerationOutputParser(
|
|
|
131
118
|
config,
|
|
132
119
|
run_type="parser",
|
|
133
120
|
)
|
|
134
|
-
if isinstance(input, MessageV1Types):
|
|
135
|
-
return await self._acall_with_config(
|
|
136
|
-
lambda inner_input: self.aparse_result(inner_input),
|
|
137
|
-
input,
|
|
138
|
-
config,
|
|
139
|
-
run_type="parser",
|
|
140
|
-
)
|
|
141
121
|
return await self._acall_with_config(
|
|
142
122
|
lambda inner_input: self.aparse_result([Generation(text=inner_input)]),
|
|
143
123
|
input,
|
|
@@ -147,40 +127,42 @@ class BaseGenerationOutputParser(
|
|
|
147
127
|
|
|
148
128
|
|
|
149
129
|
class BaseOutputParser(
|
|
150
|
-
BaseLLMOutputParser, RunnableSerializable[
|
|
130
|
+
BaseLLMOutputParser, RunnableSerializable[LanguageModelOutput, T]
|
|
151
131
|
):
|
|
152
132
|
"""Base class to parse the output of an LLM call.
|
|
153
133
|
|
|
154
134
|
Output parsers help structure language model responses.
|
|
155
135
|
|
|
156
136
|
Example:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
+
```
|
|
159
|
+
"""
|
|
178
160
|
|
|
179
161
|
@property
|
|
180
162
|
@override
|
|
181
163
|
def InputType(self) -> Any:
|
|
182
164
|
"""Return the input type for the parser."""
|
|
183
|
-
return
|
|
165
|
+
return str | AnyMessage
|
|
184
166
|
|
|
185
167
|
@property
|
|
186
168
|
@override
|
|
@@ -190,7 +172,7 @@ class BaseOutputParser(
|
|
|
190
172
|
This property is inferred from the first type argument of the class.
|
|
191
173
|
|
|
192
174
|
Raises:
|
|
193
|
-
TypeError: If the class doesn't have an inferable OutputType
|
|
175
|
+
TypeError: If the class doesn't have an inferable `OutputType`.
|
|
194
176
|
"""
|
|
195
177
|
for base in self.__class__.mro():
|
|
196
178
|
if hasattr(base, "__pydantic_generic_metadata__"):
|
|
@@ -207,8 +189,8 @@ class BaseOutputParser(
|
|
|
207
189
|
@override
|
|
208
190
|
def invoke(
|
|
209
191
|
self,
|
|
210
|
-
input:
|
|
211
|
-
config:
|
|
192
|
+
input: str | BaseMessage,
|
|
193
|
+
config: RunnableConfig | None = None,
|
|
212
194
|
**kwargs: Any,
|
|
213
195
|
) -> T:
|
|
214
196
|
if isinstance(input, BaseMessage):
|
|
@@ -220,16 +202,9 @@ class BaseOutputParser(
|
|
|
220
202
|
config,
|
|
221
203
|
run_type="parser",
|
|
222
204
|
)
|
|
223
|
-
if isinstance(input, MessageV1Types):
|
|
224
|
-
return self._call_with_config(
|
|
225
|
-
lambda inner_input: self.parse_result(inner_input),
|
|
226
|
-
input,
|
|
227
|
-
config,
|
|
228
|
-
run_type="parser",
|
|
229
|
-
)
|
|
230
205
|
return self._call_with_config(
|
|
231
206
|
lambda inner_input: self.parse_result([Generation(text=inner_input)]),
|
|
232
|
-
|
|
207
|
+
input,
|
|
233
208
|
config,
|
|
234
209
|
run_type="parser",
|
|
235
210
|
)
|
|
@@ -237,9 +212,9 @@ class BaseOutputParser(
|
|
|
237
212
|
@override
|
|
238
213
|
async def ainvoke(
|
|
239
214
|
self,
|
|
240
|
-
input:
|
|
241
|
-
config:
|
|
242
|
-
**kwargs:
|
|
215
|
+
input: str | BaseMessage,
|
|
216
|
+
config: RunnableConfig | None = None,
|
|
217
|
+
**kwargs: Any | None,
|
|
243
218
|
) -> T:
|
|
244
219
|
if isinstance(input, BaseMessage):
|
|
245
220
|
return await self._acall_with_config(
|
|
@@ -250,40 +225,29 @@ class BaseOutputParser(
|
|
|
250
225
|
config,
|
|
251
226
|
run_type="parser",
|
|
252
227
|
)
|
|
253
|
-
if isinstance(input, MessageV1Types):
|
|
254
|
-
return await self._acall_with_config(
|
|
255
|
-
lambda inner_input: self.aparse_result(inner_input),
|
|
256
|
-
input,
|
|
257
|
-
config,
|
|
258
|
-
run_type="parser",
|
|
259
|
-
)
|
|
260
228
|
return await self._acall_with_config(
|
|
261
229
|
lambda inner_input: self.aparse_result([Generation(text=inner_input)]),
|
|
262
|
-
|
|
230
|
+
input,
|
|
263
231
|
config,
|
|
264
232
|
run_type="parser",
|
|
265
233
|
)
|
|
266
234
|
|
|
267
235
|
@override
|
|
268
|
-
def parse_result(
|
|
269
|
-
|
|
270
|
-
) -> T:
|
|
271
|
-
"""Parse a list of candidate model Generations into a specific format.
|
|
236
|
+
def parse_result(self, result: list[Generation], *, partial: bool = False) -> T:
|
|
237
|
+
"""Parse a list of candidate model `Generation` objects into a specific format.
|
|
272
238
|
|
|
273
|
-
The return value is parsed from only the first Generation in the result, which
|
|
274
|
-
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`.
|
|
275
241
|
|
|
276
242
|
Args:
|
|
277
|
-
result: A list of
|
|
278
|
-
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.
|
|
279
245
|
partial: Whether to parse the output as a partial result. This is useful
|
|
280
|
-
for parsers that can parse partial results.
|
|
246
|
+
for parsers that can parse partial results.
|
|
281
247
|
|
|
282
248
|
Returns:
|
|
283
249
|
Structured output.
|
|
284
250
|
"""
|
|
285
|
-
if isinstance(result, AIMessage):
|
|
286
|
-
return self.parse(result.text)
|
|
287
251
|
return self.parse(result[0].text)
|
|
288
252
|
|
|
289
253
|
@abstractmethod
|
|
@@ -298,22 +262,22 @@ class BaseOutputParser(
|
|
|
298
262
|
"""
|
|
299
263
|
|
|
300
264
|
async def aparse_result(
|
|
301
|
-
self, result:
|
|
265
|
+
self, result: list[Generation], *, partial: bool = False
|
|
302
266
|
) -> T:
|
|
303
|
-
"""Async parse a list of candidate model
|
|
267
|
+
"""Async parse a list of candidate model `Generation` objects into a specific format.
|
|
304
268
|
|
|
305
|
-
The return value is parsed from only the first Generation in the result, which
|
|
306
|
-
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`.
|
|
307
271
|
|
|
308
272
|
Args:
|
|
309
|
-
result: A list of
|
|
310
|
-
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.
|
|
311
275
|
partial: Whether to parse the output as a partial result. This is useful
|
|
312
|
-
for parsers that can parse partial results.
|
|
276
|
+
for parsers that can parse partial results.
|
|
313
277
|
|
|
314
278
|
Returns:
|
|
315
279
|
Structured output.
|
|
316
|
-
"""
|
|
280
|
+
""" # noqa: E501
|
|
317
281
|
return await run_in_executor(None, self.parse_result, result, partial=partial)
|
|
318
282
|
|
|
319
283
|
async def aparse(self, text: str) -> T:
|
|
@@ -335,13 +299,13 @@ class BaseOutputParser(
|
|
|
335
299
|
) -> Any:
|
|
336
300
|
"""Parse the output of an LLM call with the input prompt for context.
|
|
337
301
|
|
|
338
|
-
The prompt is largely provided in the event the OutputParser wants
|
|
302
|
+
The prompt is largely provided in the event the `OutputParser` wants
|
|
339
303
|
to retry or fix the output in some way, and needs information from
|
|
340
304
|
the prompt to do so.
|
|
341
305
|
|
|
342
306
|
Args:
|
|
343
307
|
completion: String output of a language model.
|
|
344
|
-
prompt: Input PromptValue
|
|
308
|
+
prompt: Input `PromptValue`.
|
|
345
309
|
|
|
346
310
|
Returns:
|
|
347
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
|
|
@@ -21,10 +21,9 @@ from langchain_core.utils.json import (
|
|
|
21
21
|
parse_json_markdown,
|
|
22
22
|
parse_partial_json,
|
|
23
23
|
)
|
|
24
|
-
from langchain_core.v1.messages import AIMessage
|
|
25
24
|
|
|
26
25
|
# Union type needs to be last assignment to PydanticBaseModel to make mypy happy.
|
|
27
|
-
PydanticBaseModel =
|
|
26
|
+
PydanticBaseModel = BaseModel | pydantic.BaseModel
|
|
28
27
|
|
|
29
28
|
TBaseModel = TypeVar("TBaseModel", bound=PydanticBaseModel)
|
|
30
29
|
|
|
@@ -39,33 +38,30 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
39
38
|
describing the difference between the previous and the current object.
|
|
40
39
|
"""
|
|
41
40
|
|
|
42
|
-
pydantic_object: Annotated[
|
|
41
|
+
pydantic_object: Annotated[type[TBaseModel] | None, SkipValidation()] = None # type: ignore[valid-type]
|
|
43
42
|
"""The Pydantic object to use for validation.
|
|
44
|
-
If None
|
|
43
|
+
If `None`, no validation is performed."""
|
|
45
44
|
|
|
46
45
|
@override
|
|
47
|
-
def _diff(self, prev:
|
|
46
|
+
def _diff(self, prev: Any | None, next: Any) -> Any:
|
|
48
47
|
return jsonpatch.make_patch(prev, next).patch
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
@staticmethod
|
|
50
|
+
def _get_schema(pydantic_object: type[TBaseModel]) -> dict[str, Any]:
|
|
51
51
|
if issubclass(pydantic_object, pydantic.BaseModel):
|
|
52
52
|
return pydantic_object.model_json_schema()
|
|
53
|
-
|
|
54
|
-
return pydantic_object.schema()
|
|
55
|
-
return None
|
|
53
|
+
return pydantic_object.schema()
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
) -> Any:
|
|
55
|
+
@override
|
|
56
|
+
def parse_result(self, result: list[Generation], *, partial: bool = False) -> Any:
|
|
60
57
|
"""Parse the result of an LLM call to a JSON object.
|
|
61
58
|
|
|
62
59
|
Args:
|
|
63
60
|
result: The result of the LLM call.
|
|
64
61
|
partial: Whether to parse partial JSON objects.
|
|
65
|
-
If True
|
|
62
|
+
If `True`, the output will be a JSON object containing
|
|
66
63
|
all the keys that have been returned so far.
|
|
67
|
-
If False
|
|
68
|
-
Default is False.
|
|
64
|
+
If `False`, the output will be the full JSON object.
|
|
69
65
|
|
|
70
66
|
Returns:
|
|
71
67
|
The parsed JSON object.
|
|
@@ -73,7 +69,7 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
|
|
|
73
69
|
Raises:
|
|
74
70
|
OutputParserException: If the output is not valid JSON.
|
|
75
71
|
"""
|
|
76
|
-
text = result
|
|
72
|
+
text = result[0].text
|
|
77
73
|
text = text.strip()
|
|
78
74
|
if partial:
|
|
79
75
|
try:
|
|
@@ -7,13 +7,12 @@ 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
|
|
|
14
14
|
from langchain_core.messages import BaseMessage
|
|
15
15
|
from langchain_core.output_parsers.transform import BaseTransformOutputParser
|
|
16
|
-
from langchain_core.v1.messages import AIMessage
|
|
17
16
|
|
|
18
17
|
if TYPE_CHECKING:
|
|
19
18
|
from collections.abc import AsyncIterator, Iterator
|
|
@@ -71,9 +70,7 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
71
70
|
raise NotImplementedError
|
|
72
71
|
|
|
73
72
|
@override
|
|
74
|
-
def _transform(
|
|
75
|
-
self, input: Iterator[Union[str, BaseMessage, AIMessage]]
|
|
76
|
-
) -> Iterator[list[str]]:
|
|
73
|
+
def _transform(self, input: Iterator[str | BaseMessage]) -> Iterator[list[str]]:
|
|
77
74
|
buffer = ""
|
|
78
75
|
for chunk in input:
|
|
79
76
|
if isinstance(chunk, BaseMessage):
|
|
@@ -82,8 +79,6 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
82
79
|
if not isinstance(chunk_content, str):
|
|
83
80
|
continue
|
|
84
81
|
buffer += chunk_content
|
|
85
|
-
elif isinstance(chunk, AIMessage):
|
|
86
|
-
buffer += chunk.text
|
|
87
82
|
else:
|
|
88
83
|
# add current chunk to buffer
|
|
89
84
|
buffer += chunk
|
|
@@ -108,7 +103,7 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
108
103
|
|
|
109
104
|
@override
|
|
110
105
|
async def _atransform(
|
|
111
|
-
self, input: AsyncIterator[
|
|
106
|
+
self, input: AsyncIterator[str | BaseMessage]
|
|
112
107
|
) -> AsyncIterator[list[str]]:
|
|
113
108
|
buffer = ""
|
|
114
109
|
async for chunk in input:
|
|
@@ -118,8 +113,6 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
|
|
|
118
113
|
if not isinstance(chunk_content, str):
|
|
119
114
|
continue
|
|
120
115
|
buffer += chunk_content
|
|
121
|
-
elif isinstance(chunk, AIMessage):
|
|
122
|
-
buffer += chunk.text
|
|
123
116
|
else:
|
|
124
117
|
# add current chunk to buffer
|
|
125
118
|
buffer += chunk
|
|
@@ -148,22 +141,19 @@ class CommaSeparatedListOutputParser(ListOutputParser):
|
|
|
148
141
|
|
|
149
142
|
@classmethod
|
|
150
143
|
def is_lc_serializable(cls) -> bool:
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
Returns True.
|
|
154
|
-
"""
|
|
144
|
+
"""Return True as this class is serializable."""
|
|
155
145
|
return True
|
|
156
146
|
|
|
157
147
|
@classmethod
|
|
158
148
|
def get_lc_namespace(cls) -> list[str]:
|
|
159
|
-
"""Get the namespace of the
|
|
149
|
+
"""Get the namespace of the LangChain object.
|
|
160
150
|
|
|
161
151
|
Returns:
|
|
162
|
-
|
|
163
|
-
Default is ["langchain", "output_parsers", "list"].
|
|
152
|
+
`["langchain", "output_parsers", "list"]`
|
|
164
153
|
"""
|
|
165
154
|
return ["langchain", "output_parsers", "list"]
|
|
166
155
|
|
|
156
|
+
@override
|
|
167
157
|
def get_format_instructions(self) -> str:
|
|
168
158
|
"""Return the format instructions for the comma-separated list output."""
|
|
169
159
|
return (
|
|
@@ -171,6 +161,7 @@ class CommaSeparatedListOutputParser(ListOutputParser):
|
|
|
171
161
|
"eg: `foo, bar, baz` or `foo,bar,baz`"
|
|
172
162
|
)
|
|
173
163
|
|
|
164
|
+
@override
|
|
174
165
|
def parse(self, text: str) -> list[str]:
|
|
175
166
|
"""Parse the output of an LLM call.
|
|
176
167
|
|
|
@@ -218,15 +209,8 @@ class NumberedListOutputParser(ListOutputParser):
|
|
|
218
209
|
"""
|
|
219
210
|
return re.findall(self.pattern, text)
|
|
220
211
|
|
|
212
|
+
@override
|
|
221
213
|
def parse_iter(self, text: str) -> Iterator[re.Match]:
|
|
222
|
-
"""Parse the output of an LLM call.
|
|
223
|
-
|
|
224
|
-
Args:
|
|
225
|
-
text: The output of an LLM call.
|
|
226
|
-
|
|
227
|
-
Yields:
|
|
228
|
-
A match object for each part of the output.
|
|
229
|
-
"""
|
|
230
214
|
return re.finditer(self.pattern, text)
|
|
231
215
|
|
|
232
216
|
@property
|
|
@@ -240,6 +224,7 @@ class MarkdownListOutputParser(ListOutputParser):
|
|
|
240
224
|
pattern: str = r"^\s*[-*]\s([^\n]+)$"
|
|
241
225
|
"""The pattern to match a Markdown list item."""
|
|
242
226
|
|
|
227
|
+
@override
|
|
243
228
|
def get_format_instructions(self) -> str:
|
|
244
229
|
"""Return the format instructions for the Markdown list output."""
|
|
245
230
|
return "Your response should be a markdown list, eg: `- foo\n- bar\n- baz`"
|
|
@@ -255,15 +240,8 @@ class MarkdownListOutputParser(ListOutputParser):
|
|
|
255
240
|
"""
|
|
256
241
|
return re.findall(self.pattern, text, re.MULTILINE)
|
|
257
242
|
|
|
243
|
+
@override
|
|
258
244
|
def parse_iter(self, text: str) -> Iterator[re.Match]:
|
|
259
|
-
"""Parse the output of an LLM call.
|
|
260
|
-
|
|
261
|
-
Args:
|
|
262
|
-
text: The output of an LLM call.
|
|
263
|
-
|
|
264
|
-
Yields:
|
|
265
|
-
A match object for each part of the output.
|
|
266
|
-
"""
|
|
267
245
|
return re.finditer(self.pattern, text, re.MULTILINE)
|
|
268
246
|
|
|
269
247
|
@property
|