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
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
from typing import (
|
|
4
4
|
TYPE_CHECKING,
|
|
5
5
|
Any,
|
|
6
|
-
Optional,
|
|
7
6
|
TypeVar,
|
|
8
|
-
Union,
|
|
9
7
|
cast,
|
|
10
8
|
)
|
|
11
9
|
|
|
@@ -35,7 +33,7 @@ U = TypeVar("U")
|
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class ExponentialJitterParams(TypedDict, total=False):
|
|
38
|
-
"""Parameters for
|
|
36
|
+
"""Parameters for `tenacity.wait_exponential_jitter`."""
|
|
39
37
|
|
|
40
38
|
initial: float
|
|
41
39
|
"""Initial wait."""
|
|
@@ -47,7 +45,7 @@ class ExponentialJitterParams(TypedDict, total=False):
|
|
|
47
45
|
"""Random additional wait sampled from random.uniform(0, jitter)."""
|
|
48
46
|
|
|
49
47
|
|
|
50
|
-
class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
48
|
+
class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-redef]
|
|
51
49
|
"""Retry a Runnable if it fails.
|
|
52
50
|
|
|
53
51
|
RunnableRetry can be used to add retry logic to any object
|
|
@@ -62,32 +60,34 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
62
60
|
Example:
|
|
63
61
|
Here's an example that uses a RunnableLambda to raise an exception
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
```python
|
|
64
|
+
import time
|
|
66
65
|
|
|
67
|
-
import time
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
def foo(input) -> None:
|
|
68
|
+
'''Fake function that raises an exception.'''
|
|
69
|
+
raise ValueError(f"Invoking foo failed. At time {time.time()}")
|
|
72
70
|
|
|
73
|
-
runnable = RunnableLambda(foo)
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
retry_if_exception_type=(ValueError,), # Retry only on ValueError
|
|
77
|
-
wait_exponential_jitter=True, # Add jitter to the exponential backoff
|
|
78
|
-
stop_after_attempt=2, # Try twice
|
|
79
|
-
exponential_jitter_params={"initial": 2}, # if desired, customize backoff
|
|
80
|
-
)
|
|
72
|
+
runnable = RunnableLambda(foo)
|
|
81
73
|
|
|
82
|
-
|
|
74
|
+
runnable_with_retries = runnable.with_retry(
|
|
75
|
+
retry_if_exception_type=(ValueError,), # Retry only on ValueError
|
|
76
|
+
wait_exponential_jitter=True, # Add jitter to the exponential backoff
|
|
77
|
+
stop_after_attempt=2, # Try twice
|
|
78
|
+
exponential_jitter_params={"initial": 2}, # if desired, customize backoff
|
|
79
|
+
)
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
# The method invocation above is equivalent to the longer form below:
|
|
82
|
+
|
|
83
|
+
runnable_with_retries = RunnableRetry(
|
|
84
|
+
bound=runnable,
|
|
85
|
+
retry_exception_types=(ValueError,),
|
|
86
|
+
max_attempt_number=2,
|
|
87
|
+
wait_exponential_jitter=True,
|
|
88
|
+
exponential_jitter_params={"initial": 2},
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
91
|
|
|
92
92
|
This logic can be used to retry any Runnable, including a chain of Runnables,
|
|
93
93
|
but in general it's best practice to keep the scope of the retry as small as
|
|
@@ -95,23 +95,21 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
95
95
|
the Runnable that is likely to fail, not the entire chain.
|
|
96
96
|
|
|
97
97
|
Example:
|
|
98
|
+
```python
|
|
99
|
+
from langchain_core.chat_models import ChatOpenAI
|
|
100
|
+
from langchain_core.prompts import PromptTemplate
|
|
98
101
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
from langchain_core.chat_models import ChatOpenAI
|
|
102
|
-
from langchain_core.prompts import PromptTemplate
|
|
102
|
+
template = PromptTemplate.from_template("tell me a joke about {topic}.")
|
|
103
|
+
model = ChatOpenAI(temperature=0.5)
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
# Good
|
|
106
|
+
chain = template | model.with_retry()
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
retryable_chain = chain.with_retry()
|
|
113
|
-
|
|
114
|
-
""" # noqa: E501
|
|
108
|
+
# Bad
|
|
109
|
+
chain = template | model
|
|
110
|
+
retryable_chain = chain.with_retry()
|
|
111
|
+
```
|
|
112
|
+
"""
|
|
115
113
|
|
|
116
114
|
retry_exception_types: tuple[type[BaseException], ...] = (Exception,)
|
|
117
115
|
"""The exception types to retry on. By default all exceptions are retried.
|
|
@@ -126,9 +124,9 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
126
124
|
wait_exponential_jitter: bool = True
|
|
127
125
|
"""Whether to add jitter to the exponential backoff."""
|
|
128
126
|
|
|
129
|
-
exponential_jitter_params:
|
|
130
|
-
"""Parameters for
|
|
131
|
-
|
|
127
|
+
exponential_jitter_params: ExponentialJitterParams | None = None
|
|
128
|
+
"""Parameters for `tenacity.wait_exponential_jitter`. Namely: `initial`,
|
|
129
|
+
`max`, `exp_base`, and `jitter` (all `float` values).
|
|
132
130
|
"""
|
|
133
131
|
|
|
134
132
|
max_attempt_number: int = 3
|
|
@@ -174,7 +172,8 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
174
172
|
retry_state: RetryCallState,
|
|
175
173
|
) -> list[RunnableConfig]:
|
|
176
174
|
return [
|
|
177
|
-
self._patch_config(c, rm, retry_state)
|
|
175
|
+
self._patch_config(c, rm, retry_state)
|
|
176
|
+
for c, rm in zip(config, run_manager, strict=False)
|
|
178
177
|
]
|
|
179
178
|
|
|
180
179
|
def _invoke(
|
|
@@ -197,7 +196,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
197
196
|
|
|
198
197
|
@override
|
|
199
198
|
def invoke(
|
|
200
|
-
self, input: Input, config:
|
|
199
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
201
200
|
) -> Output:
|
|
202
201
|
return self._call_with_config(self._invoke, input, config, **kwargs)
|
|
203
202
|
|
|
@@ -221,7 +220,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
221
220
|
|
|
222
221
|
@override
|
|
223
222
|
async def ainvoke(
|
|
224
|
-
self, input: Input, config:
|
|
223
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
225
224
|
) -> Output:
|
|
226
225
|
return await self._acall_with_config(self._ainvoke, input, config, **kwargs)
|
|
227
226
|
|
|
@@ -231,34 +230,43 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
231
230
|
run_manager: list["CallbackManagerForChainRun"],
|
|
232
231
|
config: list[RunnableConfig],
|
|
233
232
|
**kwargs: Any,
|
|
234
|
-
) -> list[
|
|
233
|
+
) -> list[Output | Exception]:
|
|
235
234
|
results_map: dict[int, Output] = {}
|
|
236
235
|
|
|
237
|
-
def pending(iterable: list[U]) -> list[U]:
|
|
238
|
-
return [item for idx, item in enumerate(iterable) if idx not in results_map]
|
|
239
|
-
|
|
240
236
|
not_set: list[Output] = []
|
|
241
237
|
result = not_set
|
|
242
238
|
try:
|
|
243
239
|
for attempt in self._sync_retrying():
|
|
244
240
|
with attempt:
|
|
245
|
-
#
|
|
241
|
+
# Retry for inputs that have not yet succeeded
|
|
242
|
+
# Determine which original indices remain.
|
|
243
|
+
remaining_indices = [
|
|
244
|
+
i for i in range(len(inputs)) if i not in results_map
|
|
245
|
+
]
|
|
246
|
+
if not remaining_indices:
|
|
247
|
+
break
|
|
248
|
+
pending_inputs = [inputs[i] for i in remaining_indices]
|
|
249
|
+
pending_configs = [config[i] for i in remaining_indices]
|
|
250
|
+
pending_run_managers = [run_manager[i] for i in remaining_indices]
|
|
251
|
+
# Invoke underlying batch only on remaining elements.
|
|
246
252
|
result = super().batch(
|
|
247
|
-
|
|
253
|
+
pending_inputs,
|
|
248
254
|
self._patch_config_list(
|
|
249
|
-
|
|
255
|
+
pending_configs, pending_run_managers, attempt.retry_state
|
|
250
256
|
),
|
|
251
257
|
return_exceptions=True,
|
|
252
258
|
**kwargs,
|
|
253
259
|
)
|
|
254
|
-
# Register the results of the inputs that have succeeded
|
|
260
|
+
# Register the results of the inputs that have succeeded, mapping
|
|
261
|
+
# back to their original indices.
|
|
255
262
|
first_exception = None
|
|
256
|
-
for
|
|
263
|
+
for offset, r in enumerate(result):
|
|
257
264
|
if isinstance(r, Exception):
|
|
258
265
|
if not first_exception:
|
|
259
266
|
first_exception = r
|
|
260
267
|
continue
|
|
261
|
-
|
|
268
|
+
orig_idx = remaining_indices[offset]
|
|
269
|
+
results_map[orig_idx] = r
|
|
262
270
|
# If any exception occurred, raise it, to retry the failed ones
|
|
263
271
|
if first_exception:
|
|
264
272
|
raise first_exception
|
|
@@ -271,7 +279,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
271
279
|
if result is not_set:
|
|
272
280
|
result = cast("list[Output]", [e] * len(inputs))
|
|
273
281
|
|
|
274
|
-
outputs: list[
|
|
282
|
+
outputs: list[Output | Exception] = []
|
|
275
283
|
for idx in range(len(inputs)):
|
|
276
284
|
if idx in results_map:
|
|
277
285
|
outputs.append(results_map[idx])
|
|
@@ -283,7 +291,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
283
291
|
def batch(
|
|
284
292
|
self,
|
|
285
293
|
inputs: list[Input],
|
|
286
|
-
config:
|
|
294
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
287
295
|
*,
|
|
288
296
|
return_exceptions: bool = False,
|
|
289
297
|
**kwargs: Any,
|
|
@@ -298,34 +306,42 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
298
306
|
run_manager: list["AsyncCallbackManagerForChainRun"],
|
|
299
307
|
config: list[RunnableConfig],
|
|
300
308
|
**kwargs: Any,
|
|
301
|
-
) -> list[
|
|
309
|
+
) -> list[Output | Exception]:
|
|
302
310
|
results_map: dict[int, Output] = {}
|
|
303
311
|
|
|
304
|
-
def pending(iterable: list[U]) -> list[U]:
|
|
305
|
-
return [item for idx, item in enumerate(iterable) if idx not in results_map]
|
|
306
|
-
|
|
307
312
|
not_set: list[Output] = []
|
|
308
313
|
result = not_set
|
|
309
314
|
try:
|
|
310
315
|
async for attempt in self._async_retrying():
|
|
311
316
|
with attempt:
|
|
312
|
-
#
|
|
317
|
+
# Retry for inputs that have not yet succeeded
|
|
318
|
+
# Determine which original indices remain.
|
|
319
|
+
remaining_indices = [
|
|
320
|
+
i for i in range(len(inputs)) if i not in results_map
|
|
321
|
+
]
|
|
322
|
+
if not remaining_indices:
|
|
323
|
+
break
|
|
324
|
+
pending_inputs = [inputs[i] for i in remaining_indices]
|
|
325
|
+
pending_configs = [config[i] for i in remaining_indices]
|
|
326
|
+
pending_run_managers = [run_manager[i] for i in remaining_indices]
|
|
313
327
|
result = await super().abatch(
|
|
314
|
-
|
|
328
|
+
pending_inputs,
|
|
315
329
|
self._patch_config_list(
|
|
316
|
-
|
|
330
|
+
pending_configs, pending_run_managers, attempt.retry_state
|
|
317
331
|
),
|
|
318
332
|
return_exceptions=True,
|
|
319
333
|
**kwargs,
|
|
320
334
|
)
|
|
321
|
-
# Register the results of the inputs that have succeeded
|
|
335
|
+
# Register the results of the inputs that have succeeded, mapping
|
|
336
|
+
# back to their original indices.
|
|
322
337
|
first_exception = None
|
|
323
|
-
for
|
|
338
|
+
for offset, r in enumerate(result):
|
|
324
339
|
if isinstance(r, Exception):
|
|
325
340
|
if not first_exception:
|
|
326
341
|
first_exception = r
|
|
327
342
|
continue
|
|
328
|
-
|
|
343
|
+
orig_idx = remaining_indices[offset]
|
|
344
|
+
results_map[orig_idx] = r
|
|
329
345
|
# If any exception occurred, raise it, to retry the failed ones
|
|
330
346
|
if first_exception:
|
|
331
347
|
raise first_exception
|
|
@@ -338,7 +354,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
338
354
|
if result is not_set:
|
|
339
355
|
result = cast("list[Output]", [e] * len(inputs))
|
|
340
356
|
|
|
341
|
-
outputs: list[
|
|
357
|
+
outputs: list[Output | Exception] = []
|
|
342
358
|
for idx in range(len(inputs)):
|
|
343
359
|
if idx in results_map:
|
|
344
360
|
outputs.append(results_map[idx])
|
|
@@ -350,7 +366,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
|
|
|
350
366
|
async def abatch(
|
|
351
367
|
self,
|
|
352
368
|
inputs: list[Input],
|
|
353
|
-
config:
|
|
369
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
354
370
|
*,
|
|
355
371
|
return_exceptions: bool = False,
|
|
356
372
|
**kwargs: Any,
|
|
@@ -2,13 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from collections.abc import Mapping
|
|
5
|
+
from collections.abc import Callable, Mapping
|
|
6
6
|
from typing import (
|
|
7
7
|
TYPE_CHECKING,
|
|
8
8
|
Any,
|
|
9
|
-
Callable,
|
|
10
|
-
Optional,
|
|
11
|
-
Union,
|
|
12
9
|
cast,
|
|
13
10
|
)
|
|
14
11
|
|
|
@@ -38,15 +35,12 @@ if TYPE_CHECKING:
|
|
|
38
35
|
|
|
39
36
|
|
|
40
37
|
class RouterInput(TypedDict):
|
|
41
|
-
"""Router input.
|
|
42
|
-
|
|
43
|
-
Attributes:
|
|
44
|
-
key: The key to route on.
|
|
45
|
-
input: The input to pass to the selected Runnable.
|
|
46
|
-
"""
|
|
38
|
+
"""Router input."""
|
|
47
39
|
|
|
48
40
|
key: str
|
|
41
|
+
"""The key to route on."""
|
|
49
42
|
input: Any
|
|
43
|
+
"""The input to pass to the selected Runnable."""
|
|
50
44
|
|
|
51
45
|
|
|
52
46
|
class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
@@ -55,18 +49,16 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
55
49
|
Returns the output of the selected Runnable.
|
|
56
50
|
|
|
57
51
|
Example:
|
|
52
|
+
```python
|
|
53
|
+
from langchain_core.runnables.router import RouterRunnable
|
|
54
|
+
from langchain_core.runnables import RunnableLambda
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
from langchain_core.runnables.router import RouterRunnable
|
|
62
|
-
from langchain_core.runnables import RunnableLambda
|
|
63
|
-
|
|
64
|
-
add = RunnableLambda(func=lambda x: x + 1)
|
|
65
|
-
square = RunnableLambda(func=lambda x: x**2)
|
|
66
|
-
|
|
67
|
-
router = RouterRunnable(runnables={"add": add, "square": square})
|
|
68
|
-
router.invoke({"key": "square", "input": 3})
|
|
56
|
+
add = RunnableLambda(func=lambda x: x + 1)
|
|
57
|
+
square = RunnableLambda(func=lambda x: x**2)
|
|
69
58
|
|
|
59
|
+
router = RouterRunnable(runnables={"add": add, "square": square})
|
|
60
|
+
router.invoke({"key": "square", "input": 3})
|
|
61
|
+
```
|
|
70
62
|
"""
|
|
71
63
|
|
|
72
64
|
runnables: Mapping[str, Runnable[Any, Output]]
|
|
@@ -80,14 +72,14 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
80
72
|
|
|
81
73
|
def __init__(
|
|
82
74
|
self,
|
|
83
|
-
runnables: Mapping[str,
|
|
75
|
+
runnables: Mapping[str, Runnable[Any, Output] | Callable[[Any], Output]],
|
|
84
76
|
) -> None:
|
|
85
77
|
"""Create a RouterRunnable.
|
|
86
78
|
|
|
87
79
|
Args:
|
|
88
80
|
runnables: A mapping of keys to Runnables.
|
|
89
81
|
"""
|
|
90
|
-
super().__init__(
|
|
82
|
+
super().__init__(
|
|
91
83
|
runnables={key: coerce_to_runnable(r) for key, r in runnables.items()}
|
|
92
84
|
)
|
|
93
85
|
|
|
@@ -98,18 +90,22 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
98
90
|
@classmethod
|
|
99
91
|
@override
|
|
100
92
|
def is_lc_serializable(cls) -> bool:
|
|
101
|
-
"""Return
|
|
93
|
+
"""Return True as this class is serializable."""
|
|
102
94
|
return True
|
|
103
95
|
|
|
104
96
|
@classmethod
|
|
105
97
|
@override
|
|
106
98
|
def get_lc_namespace(cls) -> list[str]:
|
|
107
|
-
"""Get the namespace of the
|
|
99
|
+
"""Get the namespace of the LangChain object.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
`["langchain", "schema", "runnable"]`
|
|
103
|
+
"""
|
|
108
104
|
return ["langchain", "schema", "runnable"]
|
|
109
105
|
|
|
110
106
|
@override
|
|
111
107
|
def invoke(
|
|
112
|
-
self, input: RouterInput, config:
|
|
108
|
+
self, input: RouterInput, config: RunnableConfig | None = None, **kwargs: Any
|
|
113
109
|
) -> Output:
|
|
114
110
|
key = input["key"]
|
|
115
111
|
actual_input = input["input"]
|
|
@@ -124,8 +120,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
124
120
|
async def ainvoke(
|
|
125
121
|
self,
|
|
126
122
|
input: RouterInput,
|
|
127
|
-
config:
|
|
128
|
-
**kwargs:
|
|
123
|
+
config: RunnableConfig | None = None,
|
|
124
|
+
**kwargs: Any | None,
|
|
129
125
|
) -> Output:
|
|
130
126
|
key = input["key"]
|
|
131
127
|
actual_input = input["input"]
|
|
@@ -140,10 +136,10 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
140
136
|
def batch(
|
|
141
137
|
self,
|
|
142
138
|
inputs: list[RouterInput],
|
|
143
|
-
config:
|
|
139
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
144
140
|
*,
|
|
145
141
|
return_exceptions: bool = False,
|
|
146
|
-
**kwargs:
|
|
142
|
+
**kwargs: Any | None,
|
|
147
143
|
) -> list[Output]:
|
|
148
144
|
if not inputs:
|
|
149
145
|
return []
|
|
@@ -156,7 +152,7 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
156
152
|
|
|
157
153
|
def invoke(
|
|
158
154
|
runnable: Runnable, input_: Input, config: RunnableConfig
|
|
159
|
-
) ->
|
|
155
|
+
) -> Output | Exception:
|
|
160
156
|
if return_exceptions:
|
|
161
157
|
try:
|
|
162
158
|
return runnable.invoke(input_, config, **kwargs)
|
|
@@ -177,10 +173,10 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
177
173
|
async def abatch(
|
|
178
174
|
self,
|
|
179
175
|
inputs: list[RouterInput],
|
|
180
|
-
config:
|
|
176
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
181
177
|
*,
|
|
182
178
|
return_exceptions: bool = False,
|
|
183
|
-
**kwargs:
|
|
179
|
+
**kwargs: Any | None,
|
|
184
180
|
) -> list[Output]:
|
|
185
181
|
if not inputs:
|
|
186
182
|
return []
|
|
@@ -193,7 +189,7 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
193
189
|
|
|
194
190
|
async def ainvoke(
|
|
195
191
|
runnable: Runnable, input_: Input, config: RunnableConfig
|
|
196
|
-
) ->
|
|
192
|
+
) -> Output | Exception:
|
|
197
193
|
if return_exceptions:
|
|
198
194
|
try:
|
|
199
195
|
return await runnable.ainvoke(input_, config, **kwargs)
|
|
@@ -213,8 +209,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
213
209
|
def stream(
|
|
214
210
|
self,
|
|
215
211
|
input: RouterInput,
|
|
216
|
-
config:
|
|
217
|
-
**kwargs:
|
|
212
|
+
config: RunnableConfig | None = None,
|
|
213
|
+
**kwargs: Any | None,
|
|
218
214
|
) -> Iterator[Output]:
|
|
219
215
|
key = input["key"]
|
|
220
216
|
actual_input = input["input"]
|
|
@@ -229,8 +225,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
229
225
|
async def astream(
|
|
230
226
|
self,
|
|
231
227
|
input: RouterInput,
|
|
232
|
-
config:
|
|
233
|
-
**kwargs:
|
|
228
|
+
config: RunnableConfig | None = None,
|
|
229
|
+
**kwargs: Any | None,
|
|
234
230
|
) -> AsyncIterator[Output]:
|
|
235
231
|
key = input["key"]
|
|
236
232
|
actual_input = input["input"]
|