langchain-core 1.0.0a5__py3-none-any.whl → 1.0.0a7__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/_api/__init__.py +3 -3
- langchain_core/_api/beta_decorator.py +6 -6
- langchain_core/_api/deprecation.py +21 -29
- langchain_core/_api/path.py +3 -6
- langchain_core/_import_utils.py +2 -3
- langchain_core/agents.py +10 -11
- langchain_core/caches.py +7 -7
- langchain_core/callbacks/base.py +91 -91
- langchain_core/callbacks/file.py +11 -11
- langchain_core/callbacks/manager.py +86 -89
- langchain_core/callbacks/stdout.py +8 -8
- langchain_core/callbacks/usage.py +4 -4
- langchain_core/chat_history.py +1 -37
- langchain_core/document_loaders/base.py +2 -2
- langchain_core/document_loaders/langsmith.py +15 -15
- langchain_core/documents/base.py +16 -16
- langchain_core/documents/compressor.py +4 -4
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/example_selectors/semantic_similarity.py +17 -19
- langchain_core/exceptions.py +3 -3
- langchain_core/globals.py +3 -151
- langchain_core/indexing/api.py +44 -43
- langchain_core/indexing/base.py +30 -30
- langchain_core/indexing/in_memory.py +3 -3
- langchain_core/language_models/_utils.py +5 -7
- langchain_core/language_models/base.py +18 -132
- langchain_core/language_models/chat_models.py +118 -227
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +35 -29
- langchain_core/language_models/llms.py +91 -201
- langchain_core/load/dump.py +1 -1
- langchain_core/load/load.py +11 -12
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +2 -4
- langchain_core/messages/ai.py +17 -20
- langchain_core/messages/base.py +28 -26
- langchain_core/messages/block_translators/__init__.py +17 -7
- langchain_core/messages/block_translators/anthropic.py +3 -3
- langchain_core/messages/block_translators/bedrock_converse.py +2 -2
- langchain_core/messages/block_translators/google_genai.py +502 -20
- langchain_core/messages/block_translators/langchain_v0.py +2 -2
- langchain_core/messages/block_translators/openai.py +6 -6
- langchain_core/messages/content.py +120 -124
- langchain_core/messages/human.py +7 -7
- langchain_core/messages/system.py +7 -7
- langchain_core/messages/tool.py +24 -24
- langchain_core/messages/utils.py +67 -79
- langchain_core/output_parsers/base.py +12 -14
- langchain_core/output_parsers/json.py +4 -4
- langchain_core/output_parsers/list.py +3 -5
- langchain_core/output_parsers/openai_functions.py +3 -3
- langchain_core/output_parsers/openai_tools.py +3 -3
- langchain_core/output_parsers/pydantic.py +2 -2
- langchain_core/output_parsers/transform.py +13 -15
- langchain_core/output_parsers/xml.py +7 -9
- langchain_core/outputs/chat_generation.py +4 -4
- langchain_core/outputs/chat_result.py +1 -3
- langchain_core/outputs/generation.py +2 -2
- langchain_core/outputs/llm_result.py +5 -5
- langchain_core/prompts/__init__.py +1 -5
- langchain_core/prompts/base.py +10 -15
- langchain_core/prompts/chat.py +31 -82
- langchain_core/prompts/dict.py +2 -2
- langchain_core/prompts/few_shot.py +5 -5
- langchain_core/prompts/few_shot_with_templates.py +4 -4
- langchain_core/prompts/loading.py +3 -5
- langchain_core/prompts/prompt.py +4 -16
- langchain_core/prompts/string.py +2 -1
- langchain_core/prompts/structured.py +16 -23
- langchain_core/rate_limiters.py +3 -4
- langchain_core/retrievers.py +14 -14
- langchain_core/runnables/base.py +938 -1054
- langchain_core/runnables/branch.py +36 -40
- langchain_core/runnables/config.py +27 -35
- langchain_core/runnables/configurable.py +108 -124
- langchain_core/runnables/fallbacks.py +76 -72
- langchain_core/runnables/graph.py +39 -45
- langchain_core/runnables/graph_ascii.py +9 -11
- langchain_core/runnables/graph_mermaid.py +18 -19
- langchain_core/runnables/graph_png.py +8 -9
- langchain_core/runnables/history.py +114 -127
- langchain_core/runnables/passthrough.py +113 -139
- langchain_core/runnables/retry.py +43 -48
- langchain_core/runnables/router.py +23 -28
- langchain_core/runnables/schema.py +42 -44
- langchain_core/runnables/utils.py +28 -31
- langchain_core/stores.py +9 -13
- langchain_core/structured_query.py +8 -8
- langchain_core/tools/base.py +63 -115
- langchain_core/tools/convert.py +31 -35
- langchain_core/tools/render.py +1 -1
- langchain_core/tools/retriever.py +4 -4
- langchain_core/tools/simple.py +13 -17
- langchain_core/tools/structured.py +12 -15
- langchain_core/tracers/base.py +62 -64
- langchain_core/tracers/context.py +17 -35
- langchain_core/tracers/core.py +49 -53
- langchain_core/tracers/evaluation.py +11 -11
- langchain_core/tracers/event_stream.py +58 -60
- langchain_core/tracers/langchain.py +13 -13
- langchain_core/tracers/log_stream.py +22 -24
- langchain_core/tracers/root_listeners.py +14 -14
- langchain_core/tracers/run_collector.py +2 -4
- langchain_core/tracers/schemas.py +8 -8
- langchain_core/tracers/stdout.py +2 -1
- langchain_core/utils/__init__.py +0 -3
- langchain_core/utils/_merge.py +2 -2
- langchain_core/utils/aiter.py +24 -28
- langchain_core/utils/env.py +4 -4
- langchain_core/utils/function_calling.py +31 -41
- langchain_core/utils/html.py +3 -4
- langchain_core/utils/input.py +3 -3
- langchain_core/utils/iter.py +15 -19
- langchain_core/utils/json.py +3 -2
- langchain_core/utils/json_schema.py +6 -6
- langchain_core/utils/mustache.py +3 -5
- langchain_core/utils/pydantic.py +16 -18
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +29 -29
- langchain_core/vectorstores/base.py +18 -21
- langchain_core/vectorstores/in_memory.py +14 -87
- langchain_core/vectorstores/utils.py +2 -2
- langchain_core/version.py +1 -1
- {langchain_core-1.0.0a5.dist-info → langchain_core-1.0.0a7.dist-info}/METADATA +10 -31
- langchain_core-1.0.0a7.dist-info/RECORD +176 -0
- {langchain_core-1.0.0a5.dist-info → langchain_core-1.0.0a7.dist-info}/WHEEL +1 -1
- langchain_core/messages/block_translators/ollama.py +0 -47
- langchain_core/prompts/pipeline.py +0 -138
- langchain_core/tracers/langchain_v1.py +0 -31
- langchain_core/utils/loading.py +0 -35
- langchain_core-1.0.0a5.dist-info/RECORD +0 -181
- langchain_core-1.0.0a5.dist-info/entry_points.txt +0 -4
langchain_core/runnables/base.py
CHANGED
|
@@ -13,6 +13,7 @@ from collections.abc import (
|
|
|
13
13
|
AsyncGenerator,
|
|
14
14
|
AsyncIterator,
|
|
15
15
|
Awaitable,
|
|
16
|
+
Callable,
|
|
16
17
|
Coroutine,
|
|
17
18
|
Iterator,
|
|
18
19
|
Mapping,
|
|
@@ -26,13 +27,10 @@ from types import GenericAlias
|
|
|
26
27
|
from typing import (
|
|
27
28
|
TYPE_CHECKING,
|
|
28
29
|
Any,
|
|
29
|
-
Callable,
|
|
30
30
|
Generic,
|
|
31
31
|
Literal,
|
|
32
|
-
Optional,
|
|
33
32
|
Protocol,
|
|
34
33
|
TypeVar,
|
|
35
|
-
Union,
|
|
36
34
|
cast,
|
|
37
35
|
get_args,
|
|
38
36
|
get_type_hints,
|
|
@@ -170,22 +168,22 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
170
168
|
|
|
171
169
|
For example,
|
|
172
170
|
|
|
173
|
-
|
|
171
|
+
```python
|
|
172
|
+
from langchain_core.runnables import RunnableLambda
|
|
174
173
|
|
|
175
|
-
|
|
174
|
+
# A RunnableSequence constructed using the `|` operator
|
|
175
|
+
sequence = RunnableLambda(lambda x: x + 1) | RunnableLambda(lambda x: x * 2)
|
|
176
|
+
sequence.invoke(1) # 4
|
|
177
|
+
sequence.batch([1, 2, 3]) # [4, 6, 8]
|
|
176
178
|
|
|
177
|
-
# A RunnableSequence constructed using the `|` operator
|
|
178
|
-
sequence = RunnableLambda(lambda x: x + 1) | RunnableLambda(lambda x: x * 2)
|
|
179
|
-
sequence.invoke(1) # 4
|
|
180
|
-
sequence.batch([1, 2, 3]) # [4, 6, 8]
|
|
181
179
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
180
|
+
# A sequence that contains a RunnableParallel constructed using a dict literal
|
|
181
|
+
sequence = RunnableLambda(lambda x: x + 1) | {
|
|
182
|
+
"mul_2": RunnableLambda(lambda x: x * 2),
|
|
183
|
+
"mul_5": RunnableLambda(lambda x: x * 5),
|
|
184
|
+
}
|
|
185
|
+
sequence.invoke(1) # {'mul_2': 4, 'mul_5': 10}
|
|
186
|
+
```
|
|
189
187
|
|
|
190
188
|
Standard Methods
|
|
191
189
|
================
|
|
@@ -200,34 +198,34 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
200
198
|
|
|
201
199
|
For example,
|
|
202
200
|
|
|
203
|
-
|
|
201
|
+
```python
|
|
202
|
+
from langchain_core.runnables import RunnableLambda
|
|
204
203
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
import random
|
|
204
|
+
import random
|
|
208
205
|
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
def add_one(x: int) -> int:
|
|
207
|
+
return x + 1
|
|
211
208
|
|
|
212
209
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
210
|
+
def buggy_double(y: int) -> int:
|
|
211
|
+
\"\"\"Buggy code that will fail 70% of the time\"\"\"
|
|
212
|
+
if random.random() > 0.3:
|
|
213
|
+
print('This code failed, and will probably be retried!') # noqa: T201
|
|
214
|
+
raise ValueError('Triggered buggy code')
|
|
215
|
+
return y * 2
|
|
219
216
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
)
|
|
217
|
+
sequence = (
|
|
218
|
+
RunnableLambda(add_one) |
|
|
219
|
+
RunnableLambda(buggy_double).with_retry( # Retry on failure
|
|
220
|
+
stop_after_attempt=10,
|
|
221
|
+
wait_exponential_jitter=False
|
|
226
222
|
)
|
|
223
|
+
)
|
|
227
224
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
225
|
+
print(sequence.input_schema.model_json_schema()) # Show inferred input schema
|
|
226
|
+
print(sequence.output_schema.model_json_schema()) # Show inferred output schema
|
|
227
|
+
print(sequence.invoke(2)) # invoke the sequence (note the retry above!!)
|
|
228
|
+
```
|
|
231
229
|
|
|
232
230
|
Debugging and tracing
|
|
233
231
|
=====================
|
|
@@ -237,30 +235,28 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
237
235
|
|
|
238
236
|
You can set the global debug flag to True to enable debug output for all chains:
|
|
239
237
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
from langchain_core.globals import set_debug
|
|
238
|
+
```python
|
|
239
|
+
from langchain_core.globals import set_debug
|
|
243
240
|
|
|
244
|
-
|
|
241
|
+
set_debug(True)
|
|
242
|
+
```
|
|
245
243
|
|
|
246
244
|
Alternatively, you can pass existing or custom callbacks to any given chain:
|
|
247
245
|
|
|
248
|
-
|
|
246
|
+
```python
|
|
247
|
+
from langchain_core.tracers import ConsoleCallbackHandler
|
|
249
248
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
chain.invoke(..., config={"callbacks": [ConsoleCallbackHandler()]})
|
|
249
|
+
chain.invoke(..., config={"callbacks": [ConsoleCallbackHandler()]})
|
|
250
|
+
```
|
|
253
251
|
|
|
254
252
|
For a UI (and much more) checkout `LangSmith <https://docs.smith.langchain.com/>`__.
|
|
255
253
|
|
|
256
254
|
"""
|
|
257
255
|
|
|
258
|
-
name:
|
|
256
|
+
name: str | None
|
|
259
257
|
"""The name of the ``Runnable``. Used for debugging and tracing."""
|
|
260
258
|
|
|
261
|
-
def get_name(
|
|
262
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
263
|
-
) -> str:
|
|
259
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
264
260
|
"""Get the name of the ``Runnable``.
|
|
265
261
|
|
|
266
262
|
Args:
|
|
@@ -365,7 +361,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
365
361
|
|
|
366
362
|
def get_input_schema(
|
|
367
363
|
self,
|
|
368
|
-
config:
|
|
364
|
+
config: RunnableConfig | None = None, # noqa: ARG002
|
|
369
365
|
) -> type[BaseModel]:
|
|
370
366
|
"""Get a pydantic model that can be used to validate input to the Runnable.
|
|
371
367
|
|
|
@@ -404,7 +400,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
404
400
|
)
|
|
405
401
|
|
|
406
402
|
def get_input_jsonschema(
|
|
407
|
-
self, config:
|
|
403
|
+
self, config: RunnableConfig | None = None
|
|
408
404
|
) -> dict[str, Any]:
|
|
409
405
|
"""Get a JSON schema that represents the input to the ``Runnable``.
|
|
410
406
|
|
|
@@ -415,21 +411,20 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
415
411
|
A JSON schema that represents the input to the ``Runnable``.
|
|
416
412
|
|
|
417
413
|
Example:
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
from langchain_core.runnables import RunnableLambda
|
|
414
|
+
```python
|
|
415
|
+
from langchain_core.runnables import RunnableLambda
|
|
422
416
|
|
|
423
417
|
|
|
424
|
-
|
|
425
|
-
|
|
418
|
+
def add_one(x: int) -> int:
|
|
419
|
+
return x + 1
|
|
426
420
|
|
|
427
421
|
|
|
428
|
-
|
|
422
|
+
runnable = RunnableLambda(add_one)
|
|
429
423
|
|
|
430
|
-
|
|
424
|
+
print(runnable.get_input_jsonschema())
|
|
425
|
+
```
|
|
431
426
|
|
|
432
|
-
|
|
427
|
+
!!! version-added "Added in version 0.3.0"
|
|
433
428
|
|
|
434
429
|
"""
|
|
435
430
|
return self.get_input_schema(config).model_json_schema()
|
|
@@ -444,7 +439,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
444
439
|
|
|
445
440
|
def get_output_schema(
|
|
446
441
|
self,
|
|
447
|
-
config:
|
|
442
|
+
config: RunnableConfig | None = None, # noqa: ARG002
|
|
448
443
|
) -> type[BaseModel]:
|
|
449
444
|
"""Get a pydantic model that can be used to validate output to the ``Runnable``.
|
|
450
445
|
|
|
@@ -483,7 +478,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
483
478
|
)
|
|
484
479
|
|
|
485
480
|
def get_output_jsonschema(
|
|
486
|
-
self, config:
|
|
481
|
+
self, config: RunnableConfig | None = None
|
|
487
482
|
) -> dict[str, Any]:
|
|
488
483
|
"""Get a JSON schema that represents the output of the ``Runnable``.
|
|
489
484
|
|
|
@@ -494,21 +489,20 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
494
489
|
A JSON schema that represents the output of the ``Runnable``.
|
|
495
490
|
|
|
496
491
|
Example:
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
from langchain_core.runnables import RunnableLambda
|
|
492
|
+
```python
|
|
493
|
+
from langchain_core.runnables import RunnableLambda
|
|
501
494
|
|
|
502
495
|
|
|
503
|
-
|
|
504
|
-
|
|
496
|
+
def add_one(x: int) -> int:
|
|
497
|
+
return x + 1
|
|
505
498
|
|
|
506
499
|
|
|
507
|
-
|
|
500
|
+
runnable = RunnableLambda(add_one)
|
|
508
501
|
|
|
509
|
-
|
|
502
|
+
print(runnable.get_output_jsonschema())
|
|
503
|
+
```
|
|
510
504
|
|
|
511
|
-
|
|
505
|
+
!!! version-added "Added in version 0.3.0"
|
|
512
506
|
|
|
513
507
|
"""
|
|
514
508
|
return self.get_output_schema(config).model_json_schema()
|
|
@@ -518,9 +512,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
518
512
|
"""List configurable fields for this ``Runnable``."""
|
|
519
513
|
return []
|
|
520
514
|
|
|
521
|
-
def config_schema(
|
|
522
|
-
self, *, include: Optional[Sequence[str]] = None
|
|
523
|
-
) -> type[BaseModel]:
|
|
515
|
+
def config_schema(self, *, include: Sequence[str] | None = None) -> type[BaseModel]:
|
|
524
516
|
"""The type of config this ``Runnable`` accepts specified as a pydantic model.
|
|
525
517
|
|
|
526
518
|
To mark a field as configurable, see the ``configurable_fields``
|
|
@@ -564,7 +556,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
564
556
|
return create_model_v2(self.get_name("Config"), field_definitions=all_fields)
|
|
565
557
|
|
|
566
558
|
def get_config_jsonschema(
|
|
567
|
-
self, *, include:
|
|
559
|
+
self, *, include: Sequence[str] | None = None
|
|
568
560
|
) -> dict[str, Any]:
|
|
569
561
|
"""Get a JSON schema that represents the config of the ``Runnable``.
|
|
570
562
|
|
|
@@ -574,12 +566,12 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
574
566
|
Returns:
|
|
575
567
|
A JSON schema that represents the config of the ``Runnable``.
|
|
576
568
|
|
|
577
|
-
|
|
569
|
+
!!! version-added "Added in version 0.3.0"
|
|
578
570
|
|
|
579
571
|
"""
|
|
580
572
|
return self.config_schema(include=include).model_json_schema()
|
|
581
573
|
|
|
582
|
-
def get_graph(self, config:
|
|
574
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
583
575
|
"""Return a graph representation of this ``Runnable``."""
|
|
584
576
|
# Import locally to prevent circular import
|
|
585
577
|
from langchain_core.runnables.graph import Graph # noqa: PLC0415
|
|
@@ -601,7 +593,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
601
593
|
return graph
|
|
602
594
|
|
|
603
595
|
def get_prompts(
|
|
604
|
-
self, config:
|
|
596
|
+
self, config: RunnableConfig | None = None
|
|
605
597
|
) -> list[BasePromptTemplate]:
|
|
606
598
|
"""Return a list of prompts used by this ``Runnable``."""
|
|
607
599
|
# Import locally to prevent circular import
|
|
@@ -615,13 +607,11 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
615
607
|
|
|
616
608
|
def __or__(
|
|
617
609
|
self,
|
|
618
|
-
other:
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
Mapping[str, Union[Runnable[Any, Other], Callable[[Any], Other], Any]],
|
|
624
|
-
],
|
|
610
|
+
other: Runnable[Any, Other]
|
|
611
|
+
| Callable[[Iterator[Any]], Iterator[Other]]
|
|
612
|
+
| Callable[[AsyncIterator[Any]], AsyncIterator[Other]]
|
|
613
|
+
| Callable[[Any], Other]
|
|
614
|
+
| Mapping[str, Runnable[Any, Other] | Callable[[Any], Other] | Any],
|
|
625
615
|
) -> RunnableSerializable[Input, Other]:
|
|
626
616
|
"""Runnable "or" operator.
|
|
627
617
|
|
|
@@ -638,13 +628,11 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
638
628
|
|
|
639
629
|
def __ror__(
|
|
640
630
|
self,
|
|
641
|
-
other:
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
Mapping[str, Union[Runnable[Other, Any], Callable[[Other], Any], Any]],
|
|
647
|
-
],
|
|
631
|
+
other: Runnable[Other, Any]
|
|
632
|
+
| Callable[[Iterator[Other]], Iterator[Any]]
|
|
633
|
+
| Callable[[AsyncIterator[Other]], AsyncIterator[Any]]
|
|
634
|
+
| Callable[[Other], Any]
|
|
635
|
+
| Mapping[str, Runnable[Other, Any] | Callable[[Other], Any] | Any],
|
|
648
636
|
) -> RunnableSerializable[Other, Output]:
|
|
649
637
|
"""Runnable "reverse-or" operator.
|
|
650
638
|
|
|
@@ -661,8 +649,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
661
649
|
|
|
662
650
|
def pipe(
|
|
663
651
|
self,
|
|
664
|
-
*others:
|
|
665
|
-
name:
|
|
652
|
+
*others: Runnable[Any, Other] | Callable[[Any], Other],
|
|
653
|
+
name: str | None = None,
|
|
666
654
|
) -> RunnableSerializable[Input, Other]:
|
|
667
655
|
"""Pipe runnables.
|
|
668
656
|
|
|
@@ -672,33 +660,32 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
672
660
|
Equivalent to ``RunnableSequence(self, *others)`` or ``self | others[0] | ...``
|
|
673
661
|
|
|
674
662
|
Example:
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
from langchain_core.runnables import RunnableLambda
|
|
663
|
+
```python
|
|
664
|
+
from langchain_core.runnables import RunnableLambda
|
|
679
665
|
|
|
680
666
|
|
|
681
|
-
|
|
682
|
-
|
|
667
|
+
def add_one(x: int) -> int:
|
|
668
|
+
return x + 1
|
|
683
669
|
|
|
684
670
|
|
|
685
|
-
|
|
686
|
-
|
|
671
|
+
def mul_two(x: int) -> int:
|
|
672
|
+
return x * 2
|
|
687
673
|
|
|
688
674
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
675
|
+
runnable_1 = RunnableLambda(add_one)
|
|
676
|
+
runnable_2 = RunnableLambda(mul_two)
|
|
677
|
+
sequence = runnable_1.pipe(runnable_2)
|
|
678
|
+
# Or equivalently:
|
|
679
|
+
# sequence = runnable_1 | runnable_2
|
|
680
|
+
# sequence = RunnableSequence(first=runnable_1, last=runnable_2)
|
|
681
|
+
sequence.invoke(1)
|
|
682
|
+
await sequence.ainvoke(1)
|
|
683
|
+
# -> 4
|
|
698
684
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
685
|
+
sequence.batch([1, 2, 3])
|
|
686
|
+
await sequence.abatch([1, 2, 3])
|
|
687
|
+
# -> [4, 6, 8]
|
|
688
|
+
```
|
|
702
689
|
|
|
703
690
|
Args:
|
|
704
691
|
*others: Other ``Runnable`` or ``Runnable``-like objects to compose
|
|
@@ -709,56 +696,56 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
709
696
|
"""
|
|
710
697
|
return RunnableSequence(self, *others, name=name)
|
|
711
698
|
|
|
712
|
-
def pick(self, keys:
|
|
699
|
+
def pick(self, keys: str | list[str]) -> RunnableSerializable[Any, Any]:
|
|
713
700
|
"""Pick keys from the output dict of this ``Runnable``.
|
|
714
701
|
|
|
715
702
|
Pick single key:
|
|
716
703
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
import json
|
|
704
|
+
```python
|
|
705
|
+
import json
|
|
720
706
|
|
|
721
|
-
|
|
707
|
+
from langchain_core.runnables import RunnableLambda, RunnableMap
|
|
722
708
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
709
|
+
as_str = RunnableLambda(str)
|
|
710
|
+
as_json = RunnableLambda(json.loads)
|
|
711
|
+
chain = RunnableMap(str=as_str, json=as_json)
|
|
726
712
|
|
|
727
|
-
|
|
728
|
-
|
|
713
|
+
chain.invoke("[1, 2, 3]")
|
|
714
|
+
# -> {"str": "[1, 2, 3]", "json": [1, 2, 3]}
|
|
729
715
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
716
|
+
json_only_chain = chain.pick("json")
|
|
717
|
+
json_only_chain.invoke("[1, 2, 3]")
|
|
718
|
+
# -> [1, 2, 3]
|
|
719
|
+
```
|
|
733
720
|
|
|
734
721
|
Pick list of keys:
|
|
735
722
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
from typing import Any
|
|
723
|
+
```python
|
|
724
|
+
from typing import Any
|
|
739
725
|
|
|
740
|
-
|
|
726
|
+
import json
|
|
741
727
|
|
|
742
|
-
|
|
728
|
+
from langchain_core.runnables import RunnableLambda, RunnableMap
|
|
743
729
|
|
|
744
|
-
|
|
745
|
-
|
|
730
|
+
as_str = RunnableLambda(str)
|
|
731
|
+
as_json = RunnableLambda(json.loads)
|
|
746
732
|
|
|
747
733
|
|
|
748
|
-
|
|
749
|
-
|
|
734
|
+
def as_bytes(x: Any) -> bytes:
|
|
735
|
+
return bytes(x, "utf-8")
|
|
750
736
|
|
|
751
737
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
738
|
+
chain = RunnableMap(
|
|
739
|
+
str=as_str, json=as_json, bytes=RunnableLambda(as_bytes)
|
|
740
|
+
)
|
|
755
741
|
|
|
756
|
-
|
|
757
|
-
|
|
742
|
+
chain.invoke("[1, 2, 3]")
|
|
743
|
+
# -> {"str": "[1, 2, 3]", "json": [1, 2, 3], "bytes": b"[1, 2, 3]"}
|
|
758
744
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
745
|
+
json_and_bytes_chain = chain.pick(["json", "bytes"])
|
|
746
|
+
json_and_bytes_chain.invoke("[1, 2, 3]")
|
|
747
|
+
# -> {"json": [1, 2, 3], "bytes": b"[1, 2, 3]"}
|
|
748
|
+
```
|
|
762
749
|
|
|
763
750
|
Args:
|
|
764
751
|
keys: A key or list of keys to pick from the output dict.
|
|
@@ -774,42 +761,37 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
774
761
|
|
|
775
762
|
def assign(
|
|
776
763
|
self,
|
|
777
|
-
**kwargs:
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
Mapping[
|
|
781
|
-
str,
|
|
782
|
-
Union[Runnable[dict[str, Any], Any], Callable[[dict[str, Any]], Any]],
|
|
783
|
-
],
|
|
784
|
-
],
|
|
764
|
+
**kwargs: Runnable[dict[str, Any], Any]
|
|
765
|
+
| Callable[[dict[str, Any]], Any]
|
|
766
|
+
| Mapping[str, Runnable[dict[str, Any], Any] | Callable[[dict[str, Any]], Any]],
|
|
785
767
|
) -> RunnableSerializable[Any, Any]:
|
|
786
768
|
"""Assigns new fields to the dict output of this ``Runnable``.
|
|
787
769
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
from operator import itemgetter
|
|
770
|
+
```python
|
|
771
|
+
from langchain_community.llms.fake import FakeStreamingListLLM
|
|
772
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
773
|
+
from langchain_core.prompts import SystemMessagePromptTemplate
|
|
774
|
+
from langchain_core.runnables import Runnable
|
|
775
|
+
from operator import itemgetter
|
|
795
776
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
777
|
+
prompt = (
|
|
778
|
+
SystemMessagePromptTemplate.from_template("You are a nice assistant.")
|
|
779
|
+
+ "{question}"
|
|
780
|
+
)
|
|
781
|
+
llm = FakeStreamingListLLM(responses=["foo-lish"])
|
|
801
782
|
|
|
802
|
-
|
|
783
|
+
chain: Runnable = prompt | llm | {"str": StrOutputParser()}
|
|
803
784
|
|
|
804
|
-
|
|
785
|
+
chain_with_assign = chain.assign(hello=itemgetter("str") | llm)
|
|
805
786
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
787
|
+
print(chain_with_assign.input_schema.model_json_schema())
|
|
788
|
+
# {'title': 'PromptInput', 'type': 'object', 'properties':
|
|
789
|
+
{'question': {'title': 'Question', 'type': 'string'}}}
|
|
790
|
+
print(chain_with_assign.output_schema.model_json_schema())
|
|
791
|
+
# {'title': 'RunnableSequenceOutput', 'type': 'object', 'properties':
|
|
792
|
+
{'str': {'title': 'Str',
|
|
793
|
+
'type': 'string'}, 'hello': {'title': 'Hello', 'type': 'string'}}}
|
|
794
|
+
```
|
|
813
795
|
|
|
814
796
|
Args:
|
|
815
797
|
**kwargs: A mapping of keys to ``Runnable`` or ``Runnable``-like objects
|
|
@@ -830,7 +812,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
830
812
|
def invoke(
|
|
831
813
|
self,
|
|
832
814
|
input: Input,
|
|
833
|
-
config:
|
|
815
|
+
config: RunnableConfig | None = None,
|
|
834
816
|
**kwargs: Any,
|
|
835
817
|
) -> Output:
|
|
836
818
|
"""Transform a single input into an output.
|
|
@@ -845,13 +827,12 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
845
827
|
|
|
846
828
|
Returns:
|
|
847
829
|
The output of the ``Runnable``.
|
|
848
|
-
|
|
849
830
|
"""
|
|
850
831
|
|
|
851
832
|
async def ainvoke(
|
|
852
833
|
self,
|
|
853
834
|
input: Input,
|
|
854
|
-
config:
|
|
835
|
+
config: RunnableConfig | None = None,
|
|
855
836
|
**kwargs: Any,
|
|
856
837
|
) -> Output:
|
|
857
838
|
"""Transform a single input into an output.
|
|
@@ -866,17 +847,16 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
866
847
|
|
|
867
848
|
Returns:
|
|
868
849
|
The output of the ``Runnable``.
|
|
869
|
-
|
|
870
850
|
"""
|
|
871
851
|
return await run_in_executor(config, self.invoke, input, config, **kwargs)
|
|
872
852
|
|
|
873
853
|
def batch(
|
|
874
854
|
self,
|
|
875
855
|
inputs: list[Input],
|
|
876
|
-
config:
|
|
856
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
877
857
|
*,
|
|
878
858
|
return_exceptions: bool = False,
|
|
879
|
-
**kwargs:
|
|
859
|
+
**kwargs: Any | None,
|
|
880
860
|
) -> list[Output]:
|
|
881
861
|
"""Default implementation runs invoke in parallel using a thread pool executor.
|
|
882
862
|
|
|
@@ -886,26 +866,25 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
886
866
|
e.g., if the underlying ``Runnable`` uses an API which supports a batch mode.
|
|
887
867
|
|
|
888
868
|
Args:
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
869
|
+
inputs: A list of inputs to the ``Runnable``.
|
|
870
|
+
config: A config to use when invoking the ``Runnable``. The config supports
|
|
871
|
+
standard keys like ``'tags'``, ``'metadata'`` for
|
|
872
|
+
tracing purposes, ``'max_concurrency'`` for controlling how much work
|
|
873
|
+
to do in parallel, and other keys. Please refer to the
|
|
874
|
+
``RunnableConfig`` for more details. Defaults to None.
|
|
875
|
+
return_exceptions: Whether to return exceptions instead of raising them.
|
|
876
|
+
Defaults to False.
|
|
877
|
+
**kwargs: Additional keyword arguments to pass to the ``Runnable``.
|
|
898
878
|
|
|
899
879
|
Returns:
|
|
900
|
-
|
|
901
|
-
|
|
880
|
+
A list of outputs from the ``Runnable``.
|
|
902
881
|
"""
|
|
903
882
|
if not inputs:
|
|
904
883
|
return []
|
|
905
884
|
|
|
906
885
|
configs = get_config_list(config, len(inputs))
|
|
907
886
|
|
|
908
|
-
def invoke(input_: Input, config: RunnableConfig) ->
|
|
887
|
+
def invoke(input_: Input, config: RunnableConfig) -> Output | Exception:
|
|
909
888
|
if return_exceptions:
|
|
910
889
|
try:
|
|
911
890
|
return self.invoke(input_, config, **kwargs)
|
|
@@ -925,7 +904,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
925
904
|
def batch_as_completed(
|
|
926
905
|
self,
|
|
927
906
|
inputs: Sequence[Input],
|
|
928
|
-
config:
|
|
907
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
929
908
|
*,
|
|
930
909
|
return_exceptions: Literal[False] = False,
|
|
931
910
|
**kwargs: Any,
|
|
@@ -935,20 +914,20 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
935
914
|
def batch_as_completed(
|
|
936
915
|
self,
|
|
937
916
|
inputs: Sequence[Input],
|
|
938
|
-
config:
|
|
917
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
939
918
|
*,
|
|
940
919
|
return_exceptions: Literal[True],
|
|
941
920
|
**kwargs: Any,
|
|
942
|
-
) -> Iterator[tuple[int,
|
|
921
|
+
) -> Iterator[tuple[int, Output | Exception]]: ...
|
|
943
922
|
|
|
944
923
|
def batch_as_completed(
|
|
945
924
|
self,
|
|
946
925
|
inputs: Sequence[Input],
|
|
947
|
-
config:
|
|
926
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
948
927
|
*,
|
|
949
928
|
return_exceptions: bool = False,
|
|
950
|
-
**kwargs:
|
|
951
|
-
) -> Iterator[tuple[int,
|
|
929
|
+
**kwargs: Any | None,
|
|
930
|
+
) -> Iterator[tuple[int, Output | Exception]]:
|
|
952
931
|
"""Run ``invoke`` in parallel on a list of inputs.
|
|
953
932
|
|
|
954
933
|
Yields results as they complete.
|
|
@@ -975,12 +954,10 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
975
954
|
|
|
976
955
|
def invoke(
|
|
977
956
|
i: int, input_: Input, config: RunnableConfig
|
|
978
|
-
) -> tuple[int,
|
|
957
|
+
) -> tuple[int, Output | Exception]:
|
|
979
958
|
if return_exceptions:
|
|
980
959
|
try:
|
|
981
|
-
out:
|
|
982
|
-
input_, config, **kwargs
|
|
983
|
-
)
|
|
960
|
+
out: Output | Exception = self.invoke(input_, config, **kwargs)
|
|
984
961
|
except Exception as e:
|
|
985
962
|
out = e
|
|
986
963
|
else:
|
|
@@ -995,7 +972,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
995
972
|
with get_executor_for_config(configs[0]) as executor:
|
|
996
973
|
futures = {
|
|
997
974
|
executor.submit(invoke, i, input_, config)
|
|
998
|
-
for i, (input_, config) in enumerate(zip(inputs, configs))
|
|
975
|
+
for i, (input_, config) in enumerate(zip(inputs, configs, strict=False))
|
|
999
976
|
}
|
|
1000
977
|
|
|
1001
978
|
try:
|
|
@@ -1010,10 +987,10 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1010
987
|
async def abatch(
|
|
1011
988
|
self,
|
|
1012
989
|
inputs: list[Input],
|
|
1013
|
-
config:
|
|
990
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
1014
991
|
*,
|
|
1015
992
|
return_exceptions: bool = False,
|
|
1016
|
-
**kwargs:
|
|
993
|
+
**kwargs: Any | None,
|
|
1017
994
|
) -> list[Output]:
|
|
1018
995
|
"""Default implementation runs ``ainvoke`` in parallel using ``asyncio.gather``.
|
|
1019
996
|
|
|
@@ -1042,9 +1019,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1042
1019
|
|
|
1043
1020
|
configs = get_config_list(config, len(inputs))
|
|
1044
1021
|
|
|
1045
|
-
async def ainvoke(
|
|
1046
|
-
value: Input, config: RunnableConfig
|
|
1047
|
-
) -> Union[Output, Exception]:
|
|
1022
|
+
async def ainvoke(value: Input, config: RunnableConfig) -> Output | Exception:
|
|
1048
1023
|
if return_exceptions:
|
|
1049
1024
|
try:
|
|
1050
1025
|
return await self.ainvoke(value, config, **kwargs)
|
|
@@ -1060,30 +1035,30 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1060
1035
|
def abatch_as_completed(
|
|
1061
1036
|
self,
|
|
1062
1037
|
inputs: Sequence[Input],
|
|
1063
|
-
config:
|
|
1038
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
1064
1039
|
*,
|
|
1065
1040
|
return_exceptions: Literal[False] = False,
|
|
1066
|
-
**kwargs:
|
|
1041
|
+
**kwargs: Any | None,
|
|
1067
1042
|
) -> AsyncIterator[tuple[int, Output]]: ...
|
|
1068
1043
|
|
|
1069
1044
|
@overload
|
|
1070
1045
|
def abatch_as_completed(
|
|
1071
1046
|
self,
|
|
1072
1047
|
inputs: Sequence[Input],
|
|
1073
|
-
config:
|
|
1048
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
1074
1049
|
*,
|
|
1075
1050
|
return_exceptions: Literal[True],
|
|
1076
|
-
**kwargs:
|
|
1077
|
-
) -> AsyncIterator[tuple[int,
|
|
1051
|
+
**kwargs: Any | None,
|
|
1052
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]: ...
|
|
1078
1053
|
|
|
1079
1054
|
async def abatch_as_completed(
|
|
1080
1055
|
self,
|
|
1081
1056
|
inputs: Sequence[Input],
|
|
1082
|
-
config:
|
|
1057
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
1083
1058
|
*,
|
|
1084
1059
|
return_exceptions: bool = False,
|
|
1085
|
-
**kwargs:
|
|
1086
|
-
) -> AsyncIterator[tuple[int,
|
|
1060
|
+
**kwargs: Any | None,
|
|
1061
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]:
|
|
1087
1062
|
"""Run ``ainvoke`` in parallel on a list of inputs.
|
|
1088
1063
|
|
|
1089
1064
|
Yields results as they complete.
|
|
@@ -1113,10 +1088,10 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1113
1088
|
|
|
1114
1089
|
async def ainvoke_task(
|
|
1115
1090
|
i: int, input_: Input, config: RunnableConfig
|
|
1116
|
-
) -> tuple[int,
|
|
1091
|
+
) -> tuple[int, Output | Exception]:
|
|
1117
1092
|
if return_exceptions:
|
|
1118
1093
|
try:
|
|
1119
|
-
out:
|
|
1094
|
+
out: Output | Exception = await self.ainvoke(
|
|
1120
1095
|
input_, config, **kwargs
|
|
1121
1096
|
)
|
|
1122
1097
|
except Exception as e:
|
|
@@ -1129,7 +1104,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1129
1104
|
gated_coro(semaphore, ainvoke_task(i, input_, config))
|
|
1130
1105
|
if semaphore
|
|
1131
1106
|
else ainvoke_task(i, input_, config)
|
|
1132
|
-
for i, (input_, config) in enumerate(zip(inputs, configs))
|
|
1107
|
+
for i, (input_, config) in enumerate(zip(inputs, configs, strict=False))
|
|
1133
1108
|
]
|
|
1134
1109
|
|
|
1135
1110
|
for coro in asyncio.as_completed(coros):
|
|
@@ -1138,8 +1113,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1138
1113
|
def stream(
|
|
1139
1114
|
self,
|
|
1140
1115
|
input: Input,
|
|
1141
|
-
config:
|
|
1142
|
-
**kwargs:
|
|
1116
|
+
config: RunnableConfig | None = None,
|
|
1117
|
+
**kwargs: Any | None,
|
|
1143
1118
|
) -> Iterator[Output]:
|
|
1144
1119
|
"""Default implementation of ``stream``, which calls ``invoke``.
|
|
1145
1120
|
|
|
@@ -1159,8 +1134,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1159
1134
|
async def astream(
|
|
1160
1135
|
self,
|
|
1161
1136
|
input: Input,
|
|
1162
|
-
config:
|
|
1163
|
-
**kwargs:
|
|
1137
|
+
config: RunnableConfig | None = None,
|
|
1138
|
+
**kwargs: Any | None,
|
|
1164
1139
|
) -> AsyncIterator[Output]:
|
|
1165
1140
|
"""Default implementation of ``astream``, which calls ``ainvoke``.
|
|
1166
1141
|
|
|
@@ -1181,16 +1156,16 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1181
1156
|
def astream_log(
|
|
1182
1157
|
self,
|
|
1183
1158
|
input: Any,
|
|
1184
|
-
config:
|
|
1159
|
+
config: RunnableConfig | None = None,
|
|
1185
1160
|
*,
|
|
1186
1161
|
diff: Literal[True] = True,
|
|
1187
1162
|
with_streamed_output_list: bool = True,
|
|
1188
|
-
include_names:
|
|
1189
|
-
include_types:
|
|
1190
|
-
include_tags:
|
|
1191
|
-
exclude_names:
|
|
1192
|
-
exclude_types:
|
|
1193
|
-
exclude_tags:
|
|
1163
|
+
include_names: Sequence[str] | None = None,
|
|
1164
|
+
include_types: Sequence[str] | None = None,
|
|
1165
|
+
include_tags: Sequence[str] | None = None,
|
|
1166
|
+
exclude_names: Sequence[str] | None = None,
|
|
1167
|
+
exclude_types: Sequence[str] | None = None,
|
|
1168
|
+
exclude_tags: Sequence[str] | None = None,
|
|
1194
1169
|
**kwargs: Any,
|
|
1195
1170
|
) -> AsyncIterator[RunLogPatch]: ...
|
|
1196
1171
|
|
|
@@ -1198,34 +1173,34 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1198
1173
|
def astream_log(
|
|
1199
1174
|
self,
|
|
1200
1175
|
input: Any,
|
|
1201
|
-
config:
|
|
1176
|
+
config: RunnableConfig | None = None,
|
|
1202
1177
|
*,
|
|
1203
1178
|
diff: Literal[False],
|
|
1204
1179
|
with_streamed_output_list: bool = True,
|
|
1205
|
-
include_names:
|
|
1206
|
-
include_types:
|
|
1207
|
-
include_tags:
|
|
1208
|
-
exclude_names:
|
|
1209
|
-
exclude_types:
|
|
1210
|
-
exclude_tags:
|
|
1180
|
+
include_names: Sequence[str] | None = None,
|
|
1181
|
+
include_types: Sequence[str] | None = None,
|
|
1182
|
+
include_tags: Sequence[str] | None = None,
|
|
1183
|
+
exclude_names: Sequence[str] | None = None,
|
|
1184
|
+
exclude_types: Sequence[str] | None = None,
|
|
1185
|
+
exclude_tags: Sequence[str] | None = None,
|
|
1211
1186
|
**kwargs: Any,
|
|
1212
1187
|
) -> AsyncIterator[RunLog]: ...
|
|
1213
1188
|
|
|
1214
1189
|
async def astream_log(
|
|
1215
1190
|
self,
|
|
1216
1191
|
input: Any,
|
|
1217
|
-
config:
|
|
1192
|
+
config: RunnableConfig | None = None,
|
|
1218
1193
|
*,
|
|
1219
1194
|
diff: bool = True,
|
|
1220
1195
|
with_streamed_output_list: bool = True,
|
|
1221
|
-
include_names:
|
|
1222
|
-
include_types:
|
|
1223
|
-
include_tags:
|
|
1224
|
-
exclude_names:
|
|
1225
|
-
exclude_types:
|
|
1226
|
-
exclude_tags:
|
|
1196
|
+
include_names: Sequence[str] | None = None,
|
|
1197
|
+
include_types: Sequence[str] | None = None,
|
|
1198
|
+
include_tags: Sequence[str] | None = None,
|
|
1199
|
+
exclude_names: Sequence[str] | None = None,
|
|
1200
|
+
exclude_types: Sequence[str] | None = None,
|
|
1201
|
+
exclude_tags: Sequence[str] | None = None,
|
|
1227
1202
|
**kwargs: Any,
|
|
1228
|
-
) ->
|
|
1203
|
+
) -> AsyncIterator[RunLogPatch] | AsyncIterator[RunLog]:
|
|
1229
1204
|
"""Stream all output from a ``Runnable``, as reported to the callback system.
|
|
1230
1205
|
|
|
1231
1206
|
This includes all inner runs of LLMs, Retrievers, Tools, etc.
|
|
@@ -1281,15 +1256,15 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1281
1256
|
async def astream_events(
|
|
1282
1257
|
self,
|
|
1283
1258
|
input: Any,
|
|
1284
|
-
config:
|
|
1259
|
+
config: RunnableConfig | None = None,
|
|
1285
1260
|
*,
|
|
1286
1261
|
version: Literal["v1", "v2"] = "v2",
|
|
1287
|
-
include_names:
|
|
1288
|
-
include_types:
|
|
1289
|
-
include_tags:
|
|
1290
|
-
exclude_names:
|
|
1291
|
-
exclude_types:
|
|
1292
|
-
exclude_tags:
|
|
1262
|
+
include_names: Sequence[str] | None = None,
|
|
1263
|
+
include_types: Sequence[str] | None = None,
|
|
1264
|
+
include_tags: Sequence[str] | None = None,
|
|
1265
|
+
exclude_names: Sequence[str] | None = None,
|
|
1266
|
+
exclude_types: Sequence[str] | None = None,
|
|
1267
|
+
exclude_tags: Sequence[str] | None = None,
|
|
1293
1268
|
**kwargs: Any,
|
|
1294
1269
|
) -> AsyncIterator[StreamEvent]:
|
|
1295
1270
|
"""Generate a stream of events.
|
|
@@ -1321,7 +1296,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1321
1296
|
chains. Metadata fields have been omitted from the table for brevity.
|
|
1322
1297
|
Chain definitions have been included after the table.
|
|
1323
1298
|
|
|
1324
|
-
|
|
1299
|
+
!!! note
|
|
1325
1300
|
This reference table is for the v2 version of the schema.
|
|
1326
1301
|
|
|
1327
1302
|
+--------------------------+------------------+-------------------------------------+---------------------------------------------------+-----------------------------------------------------+
|
|
@@ -1376,112 +1351,107 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1376
1351
|
|
|
1377
1352
|
``format_docs``:
|
|
1378
1353
|
|
|
1379
|
-
|
|
1354
|
+
```python
|
|
1355
|
+
def format_docs(docs: list[Document]) -> str:
|
|
1356
|
+
'''Format the docs.'''
|
|
1357
|
+
return ", ".join([doc.page_content for doc in docs])
|
|
1380
1358
|
|
|
1381
|
-
def format_docs(docs: list[Document]) -> str:
|
|
1382
|
-
'''Format the docs.'''
|
|
1383
|
-
return ", ".join([doc.page_content for doc in docs])
|
|
1384
1359
|
|
|
1385
|
-
|
|
1386
|
-
|
|
1360
|
+
format_docs = RunnableLambda(format_docs)
|
|
1361
|
+
```
|
|
1387
1362
|
|
|
1388
1363
|
``some_tool``:
|
|
1389
1364
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1365
|
+
```python
|
|
1366
|
+
@tool
|
|
1367
|
+
def some_tool(x: int, y: str) -> dict:
|
|
1368
|
+
'''Some_tool.'''
|
|
1369
|
+
return {"x": x, "y": y}
|
|
1370
|
+
```
|
|
1396
1371
|
|
|
1397
1372
|
``prompt``:
|
|
1398
1373
|
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1374
|
+
```python
|
|
1375
|
+
template = ChatPromptTemplate.from_messages(
|
|
1376
|
+
[
|
|
1377
|
+
("system", "You are Cat Agent 007"),
|
|
1378
|
+
("human", "{question}"),
|
|
1379
|
+
]
|
|
1380
|
+
).with_config({"run_name": "my_template", "tags": ["my_template"]})
|
|
1381
|
+
```
|
|
1409
1382
|
Example:
|
|
1410
1383
|
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
from langchain_core.runnables import RunnableLambda
|
|
1414
|
-
|
|
1384
|
+
```python
|
|
1385
|
+
from langchain_core.runnables import RunnableLambda
|
|
1415
1386
|
|
|
1416
|
-
async def reverse(s: str) -> str:
|
|
1417
|
-
return s[::-1]
|
|
1418
1387
|
|
|
1388
|
+
async def reverse(s: str) -> str:
|
|
1389
|
+
return s[::-1]
|
|
1419
1390
|
|
|
1420
|
-
chain = RunnableLambda(func=reverse)
|
|
1421
1391
|
|
|
1422
|
-
|
|
1423
|
-
event async for event in chain.astream_events("hello", version="v2")
|
|
1424
|
-
]
|
|
1392
|
+
chain = RunnableLambda(func=reverse)
|
|
1425
1393
|
|
|
1426
|
-
|
|
1427
|
-
# has been omitted for brevity):
|
|
1428
|
-
[
|
|
1429
|
-
{
|
|
1430
|
-
"data": {"input": "hello"},
|
|
1431
|
-
"event": "on_chain_start",
|
|
1432
|
-
"metadata": {},
|
|
1433
|
-
"name": "reverse",
|
|
1434
|
-
"tags": [],
|
|
1435
|
-
},
|
|
1436
|
-
{
|
|
1437
|
-
"data": {"chunk": "olleh"},
|
|
1438
|
-
"event": "on_chain_stream",
|
|
1439
|
-
"metadata": {},
|
|
1440
|
-
"name": "reverse",
|
|
1441
|
-
"tags": [],
|
|
1442
|
-
},
|
|
1443
|
-
{
|
|
1444
|
-
"data": {"output": "olleh"},
|
|
1445
|
-
"event": "on_chain_end",
|
|
1446
|
-
"metadata": {},
|
|
1447
|
-
"name": "reverse",
|
|
1448
|
-
"tags": [],
|
|
1449
|
-
},
|
|
1450
|
-
]
|
|
1394
|
+
events = [event async for event in chain.astream_events("hello", version="v2")]
|
|
1451
1395
|
|
|
1396
|
+
# will produce the following events (run_id, and parent_ids
|
|
1397
|
+
# has been omitted for brevity):
|
|
1398
|
+
[
|
|
1399
|
+
{
|
|
1400
|
+
"data": {"input": "hello"},
|
|
1401
|
+
"event": "on_chain_start",
|
|
1402
|
+
"metadata": {},
|
|
1403
|
+
"name": "reverse",
|
|
1404
|
+
"tags": [],
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
"data": {"chunk": "olleh"},
|
|
1408
|
+
"event": "on_chain_stream",
|
|
1409
|
+
"metadata": {},
|
|
1410
|
+
"name": "reverse",
|
|
1411
|
+
"tags": [],
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
"data": {"output": "olleh"},
|
|
1415
|
+
"event": "on_chain_end",
|
|
1416
|
+
"metadata": {},
|
|
1417
|
+
"name": "reverse",
|
|
1418
|
+
"tags": [],
|
|
1419
|
+
},
|
|
1420
|
+
]
|
|
1421
|
+
```
|
|
1452
1422
|
|
|
1453
1423
|
Example: Dispatch Custom Event
|
|
1454
1424
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
import asyncio
|
|
1425
|
+
```python
|
|
1426
|
+
from langchain_core.callbacks.manager import (
|
|
1427
|
+
adispatch_custom_event,
|
|
1428
|
+
)
|
|
1429
|
+
from langchain_core.runnables import RunnableLambda, RunnableConfig
|
|
1430
|
+
import asyncio
|
|
1462
1431
|
|
|
1463
1432
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1433
|
+
async def slow_thing(some_input: str, config: RunnableConfig) -> str:
|
|
1434
|
+
\"\"\"Do something that takes a long time.\"\"\"
|
|
1435
|
+
await asyncio.sleep(1) # Placeholder for some slow operation
|
|
1436
|
+
await adispatch_custom_event(
|
|
1437
|
+
"progress_event",
|
|
1438
|
+
{"message": "Finished step 1 of 3"},
|
|
1439
|
+
config=config # Must be included for python < 3.10
|
|
1440
|
+
)
|
|
1441
|
+
await asyncio.sleep(1) # Placeholder for some slow operation
|
|
1442
|
+
await adispatch_custom_event(
|
|
1443
|
+
"progress_event",
|
|
1444
|
+
{"message": "Finished step 2 of 3"},
|
|
1445
|
+
config=config # Must be included for python < 3.10
|
|
1446
|
+
)
|
|
1447
|
+
await asyncio.sleep(1) # Placeholder for some slow operation
|
|
1448
|
+
return "Done"
|
|
1480
1449
|
|
|
1481
|
-
|
|
1450
|
+
slow_thing = RunnableLambda(slow_thing)
|
|
1482
1451
|
|
|
1483
|
-
|
|
1484
|
-
|
|
1452
|
+
async for event in slow_thing.astream_events("some_input", version="v2"):
|
|
1453
|
+
print(event)
|
|
1454
|
+
```
|
|
1485
1455
|
|
|
1486
1456
|
Args:
|
|
1487
1457
|
input: The input to the ``Runnable``.
|
|
@@ -1548,8 +1518,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1548
1518
|
def transform(
|
|
1549
1519
|
self,
|
|
1550
1520
|
input: Iterator[Input],
|
|
1551
|
-
config:
|
|
1552
|
-
**kwargs:
|
|
1521
|
+
config: RunnableConfig | None = None,
|
|
1522
|
+
**kwargs: Any | None,
|
|
1553
1523
|
) -> Iterator[Output]:
|
|
1554
1524
|
"""Transform inputs to outputs.
|
|
1555
1525
|
|
|
@@ -1593,8 +1563,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1593
1563
|
async def atransform(
|
|
1594
1564
|
self,
|
|
1595
1565
|
input: AsyncIterator[Input],
|
|
1596
|
-
config:
|
|
1597
|
-
**kwargs:
|
|
1566
|
+
config: RunnableConfig | None = None,
|
|
1567
|
+
**kwargs: Any | None,
|
|
1598
1568
|
) -> AsyncIterator[Output]:
|
|
1599
1569
|
"""Transform inputs to outputs.
|
|
1600
1570
|
|
|
@@ -1649,13 +1619,11 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1649
1619
|
A new ``Runnable`` with the arguments bound.
|
|
1650
1620
|
|
|
1651
1621
|
Example:
|
|
1652
|
-
|
|
1653
|
-
.. code-block:: python
|
|
1654
|
-
|
|
1622
|
+
```python
|
|
1655
1623
|
from langchain_ollama import ChatOllama
|
|
1656
1624
|
from langchain_core.output_parsers import StrOutputParser
|
|
1657
1625
|
|
|
1658
|
-
llm = ChatOllama(model="
|
|
1626
|
+
llm = ChatOllama(model="llama3.1")
|
|
1659
1627
|
|
|
1660
1628
|
# Without bind.
|
|
1661
1629
|
chain = llm | StrOutputParser()
|
|
@@ -1668,13 +1636,13 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1668
1636
|
|
|
1669
1637
|
chain.invoke("Repeat quoted words exactly: 'One two three four five.'")
|
|
1670
1638
|
# Output is 'One two'
|
|
1671
|
-
|
|
1639
|
+
```
|
|
1672
1640
|
"""
|
|
1673
1641
|
return RunnableBinding(bound=self, kwargs=kwargs, config={})
|
|
1674
1642
|
|
|
1675
1643
|
def with_config(
|
|
1676
1644
|
self,
|
|
1677
|
-
config:
|
|
1645
|
+
config: RunnableConfig | None = None,
|
|
1678
1646
|
# Sadly Unpack is not well-supported by mypy so this will have to be untyped
|
|
1679
1647
|
**kwargs: Any,
|
|
1680
1648
|
) -> Runnable[Input, Output]:
|
|
@@ -1700,15 +1668,15 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1700
1668
|
def with_listeners(
|
|
1701
1669
|
self,
|
|
1702
1670
|
*,
|
|
1703
|
-
on_start:
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
on_end:
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
on_error:
|
|
1710
|
-
|
|
1711
|
-
|
|
1671
|
+
on_start: Callable[[Run], None]
|
|
1672
|
+
| Callable[[Run, RunnableConfig], None]
|
|
1673
|
+
| None = None,
|
|
1674
|
+
on_end: Callable[[Run], None]
|
|
1675
|
+
| Callable[[Run, RunnableConfig], None]
|
|
1676
|
+
| None = None,
|
|
1677
|
+
on_error: Callable[[Run], None]
|
|
1678
|
+
| Callable[[Run, RunnableConfig], None]
|
|
1679
|
+
| None = None,
|
|
1712
1680
|
) -> Runnable[Input, Output]:
|
|
1713
1681
|
"""Bind lifecycle listeners to a ``Runnable``, returning a new ``Runnable``.
|
|
1714
1682
|
|
|
@@ -1728,9 +1696,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1728
1696
|
A new ``Runnable`` with the listeners bound.
|
|
1729
1697
|
|
|
1730
1698
|
Example:
|
|
1731
|
-
|
|
1732
|
-
.. code-block:: python
|
|
1733
|
-
|
|
1699
|
+
```python
|
|
1734
1700
|
from langchain_core.runnables import RunnableLambda
|
|
1735
1701
|
from langchain_core.tracers.schemas import Run
|
|
1736
1702
|
|
|
@@ -1753,7 +1719,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1753
1719
|
on_start=fn_start, on_end=fn_end
|
|
1754
1720
|
)
|
|
1755
1721
|
chain.invoke(2)
|
|
1756
|
-
|
|
1722
|
+
```
|
|
1757
1723
|
"""
|
|
1758
1724
|
return RunnableBinding(
|
|
1759
1725
|
bound=self,
|
|
@@ -1774,9 +1740,9 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1774
1740
|
def with_alisteners(
|
|
1775
1741
|
self,
|
|
1776
1742
|
*,
|
|
1777
|
-
on_start:
|
|
1778
|
-
on_end:
|
|
1779
|
-
on_error:
|
|
1743
|
+
on_start: AsyncListener | None = None,
|
|
1744
|
+
on_end: AsyncListener | None = None,
|
|
1745
|
+
on_error: AsyncListener | None = None,
|
|
1780
1746
|
) -> Runnable[Input, Output]:
|
|
1781
1747
|
"""Bind async lifecycle listeners to a ``Runnable``.
|
|
1782
1748
|
|
|
@@ -1798,9 +1764,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1798
1764
|
A new ``Runnable`` with the listeners bound.
|
|
1799
1765
|
|
|
1800
1766
|
Example:
|
|
1801
|
-
|
|
1802
|
-
.. code-block:: python
|
|
1803
|
-
|
|
1767
|
+
```python
|
|
1804
1768
|
from langchain_core.runnables import RunnableLambda, Runnable
|
|
1805
1769
|
from datetime import datetime, timezone
|
|
1806
1770
|
import time
|
|
@@ -1809,17 +1773,17 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1809
1773
|
def format_t(timestamp: float) -> str:
|
|
1810
1774
|
return datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat()
|
|
1811
1775
|
|
|
1812
|
-
async def test_runnable(time_to_sleep
|
|
1776
|
+
async def test_runnable(time_to_sleep: int):
|
|
1813
1777
|
print(f"Runnable[{time_to_sleep}s]: starts at {format_t(time.time())}")
|
|
1814
1778
|
await asyncio.sleep(time_to_sleep)
|
|
1815
1779
|
print(f"Runnable[{time_to_sleep}s]: ends at {format_t(time.time())}")
|
|
1816
1780
|
|
|
1817
|
-
async def fn_start(run_obj
|
|
1781
|
+
async def fn_start(run_obj: Runnable):
|
|
1818
1782
|
print(f"on start callback starts at {format_t(time.time())}")
|
|
1819
1783
|
await asyncio.sleep(3)
|
|
1820
1784
|
print(f"on start callback ends at {format_t(time.time())}")
|
|
1821
1785
|
|
|
1822
|
-
async def fn_end(run_obj
|
|
1786
|
+
async def fn_end(run_obj: Runnable):
|
|
1823
1787
|
print(f"on end callback starts at {format_t(time.time())}")
|
|
1824
1788
|
await asyncio.sleep(2)
|
|
1825
1789
|
print(f"on end callback ends at {format_t(time.time())}")
|
|
@@ -1846,6 +1810,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1846
1810
|
on end callback ends at 2025-03-01T07:05:29.883893+00:00
|
|
1847
1811
|
on end callback ends at 2025-03-01T07:05:30.884831+00:00
|
|
1848
1812
|
|
|
1813
|
+
```
|
|
1849
1814
|
"""
|
|
1850
1815
|
return RunnableBinding(
|
|
1851
1816
|
bound=self,
|
|
@@ -1866,8 +1831,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1866
1831
|
def with_types(
|
|
1867
1832
|
self,
|
|
1868
1833
|
*,
|
|
1869
|
-
input_type:
|
|
1870
|
-
output_type:
|
|
1834
|
+
input_type: type[Input] | None = None,
|
|
1835
|
+
output_type: type[Output] | None = None,
|
|
1871
1836
|
) -> Runnable[Input, Output]:
|
|
1872
1837
|
"""Bind input and output types to a ``Runnable``, returning a new ``Runnable``.
|
|
1873
1838
|
|
|
@@ -1890,7 +1855,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1890
1855
|
*,
|
|
1891
1856
|
retry_if_exception_type: tuple[type[BaseException], ...] = (Exception,),
|
|
1892
1857
|
wait_exponential_jitter: bool = True,
|
|
1893
|
-
exponential_jitter_params:
|
|
1858
|
+
exponential_jitter_params: ExponentialJitterParams | None = None,
|
|
1894
1859
|
stop_after_attempt: int = 3,
|
|
1895
1860
|
) -> Runnable[Input, Output]:
|
|
1896
1861
|
"""Create a new Runnable that retries the original Runnable on exceptions.
|
|
@@ -1910,9 +1875,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1910
1875
|
A new Runnable that retries the original Runnable on exceptions.
|
|
1911
1876
|
|
|
1912
1877
|
Example:
|
|
1913
|
-
|
|
1914
|
-
.. code-block:: python
|
|
1915
|
-
|
|
1878
|
+
```python
|
|
1916
1879
|
from langchain_core.runnables import RunnableLambda
|
|
1917
1880
|
|
|
1918
1881
|
count = 0
|
|
@@ -1937,7 +1900,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1937
1900
|
pass
|
|
1938
1901
|
|
|
1939
1902
|
assert count == 2
|
|
1940
|
-
|
|
1903
|
+
```
|
|
1941
1904
|
"""
|
|
1942
1905
|
# Import locally to prevent circular import
|
|
1943
1906
|
from langchain_core.runnables.retry import RunnableRetry # noqa: PLC0415
|
|
@@ -1961,19 +1924,17 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1961
1924
|
A new ``Runnable`` that maps a list of inputs to a list of outputs.
|
|
1962
1925
|
|
|
1963
1926
|
Example:
|
|
1927
|
+
```python
|
|
1928
|
+
from langchain_core.runnables import RunnableLambda
|
|
1964
1929
|
|
|
1965
|
-
.. code-block:: python
|
|
1966
|
-
|
|
1967
|
-
from langchain_core.runnables import RunnableLambda
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
def _lambda(x: int) -> int:
|
|
1971
|
-
return x + 1
|
|
1972
1930
|
|
|
1931
|
+
def _lambda(x: int) -> int:
|
|
1932
|
+
return x + 1
|
|
1973
1933
|
|
|
1974
|
-
runnable = RunnableLambda(_lambda)
|
|
1975
|
-
print(runnable.map().invoke([1, 2, 3])) # [2, 3, 4]
|
|
1976
1934
|
|
|
1935
|
+
runnable = RunnableLambda(_lambda)
|
|
1936
|
+
print(runnable.map().invoke([1, 2, 3])) # [2, 3, 4]
|
|
1937
|
+
```
|
|
1977
1938
|
"""
|
|
1978
1939
|
return RunnableEach(bound=self)
|
|
1979
1940
|
|
|
@@ -1982,7 +1943,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
1982
1943
|
fallbacks: Sequence[Runnable[Input, Output]],
|
|
1983
1944
|
*,
|
|
1984
1945
|
exceptions_to_handle: tuple[type[BaseException], ...] = (Exception,),
|
|
1985
|
-
exception_key:
|
|
1946
|
+
exception_key: str | None = None,
|
|
1986
1947
|
) -> RunnableWithFallbacksT[Input, Output]:
|
|
1987
1948
|
"""Add fallbacks to a ``Runnable``, returning a new ``Runnable``.
|
|
1988
1949
|
|
|
@@ -2005,27 +1966,26 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2005
1966
|
fallback in order, upon failures.
|
|
2006
1967
|
|
|
2007
1968
|
Example:
|
|
1969
|
+
```python
|
|
1970
|
+
from typing import Iterator
|
|
2008
1971
|
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
from typing import Iterator
|
|
2012
|
-
|
|
2013
|
-
from langchain_core.runnables import RunnableGenerator
|
|
1972
|
+
from langchain_core.runnables import RunnableGenerator
|
|
2014
1973
|
|
|
2015
1974
|
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
1975
|
+
def _generate_immediate_error(input: Iterator) -> Iterator[str]:
|
|
1976
|
+
raise ValueError()
|
|
1977
|
+
yield ""
|
|
2019
1978
|
|
|
2020
1979
|
|
|
2021
|
-
|
|
2022
|
-
|
|
1980
|
+
def _generate(input: Iterator) -> Iterator[str]:
|
|
1981
|
+
yield from "foo bar"
|
|
2023
1982
|
|
|
2024
1983
|
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
1984
|
+
runnable = RunnableGenerator(_generate_immediate_error).with_fallbacks(
|
|
1985
|
+
[RunnableGenerator(_generate)]
|
|
1986
|
+
)
|
|
1987
|
+
print("".join(runnable.stream({}))) # foo bar
|
|
1988
|
+
```
|
|
2029
1989
|
|
|
2030
1990
|
Args:
|
|
2031
1991
|
fallbacks: A sequence of runnables to try if the original ``Runnable``
|
|
@@ -2058,16 +2018,14 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2058
2018
|
|
|
2059
2019
|
def _call_with_config(
|
|
2060
2020
|
self,
|
|
2061
|
-
func:
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
Callable[[Input, CallbackManagerForChainRun, RunnableConfig], Output],
|
|
2065
|
-
],
|
|
2021
|
+
func: Callable[[Input], Output]
|
|
2022
|
+
| Callable[[Input, CallbackManagerForChainRun], Output]
|
|
2023
|
+
| Callable[[Input, CallbackManagerForChainRun, RunnableConfig], Output],
|
|
2066
2024
|
input_: Input,
|
|
2067
|
-
config:
|
|
2068
|
-
run_type:
|
|
2069
|
-
serialized:
|
|
2070
|
-
**kwargs:
|
|
2025
|
+
config: RunnableConfig | None,
|
|
2026
|
+
run_type: str | None = None,
|
|
2027
|
+
serialized: dict[str, Any] | None = None,
|
|
2028
|
+
**kwargs: Any | None,
|
|
2071
2029
|
) -> Output:
|
|
2072
2030
|
"""Call with config.
|
|
2073
2031
|
|
|
@@ -2109,19 +2067,16 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2109
2067
|
|
|
2110
2068
|
async def _acall_with_config(
|
|
2111
2069
|
self,
|
|
2112
|
-
func:
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
[Input, AsyncCallbackManagerForChainRun, RunnableConfig],
|
|
2117
|
-
Awaitable[Output],
|
|
2118
|
-
],
|
|
2070
|
+
func: Callable[[Input], Awaitable[Output]]
|
|
2071
|
+
| Callable[[Input, AsyncCallbackManagerForChainRun], Awaitable[Output]]
|
|
2072
|
+
| Callable[
|
|
2073
|
+
[Input, AsyncCallbackManagerForChainRun, RunnableConfig], Awaitable[Output]
|
|
2119
2074
|
],
|
|
2120
2075
|
input_: Input,
|
|
2121
|
-
config:
|
|
2122
|
-
run_type:
|
|
2123
|
-
serialized:
|
|
2124
|
-
**kwargs:
|
|
2076
|
+
config: RunnableConfig | None,
|
|
2077
|
+
run_type: str | None = None,
|
|
2078
|
+
serialized: dict[str, Any] | None = None,
|
|
2079
|
+
**kwargs: Any | None,
|
|
2125
2080
|
) -> Output:
|
|
2126
2081
|
"""Async call with config.
|
|
2127
2082
|
|
|
@@ -2155,23 +2110,20 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2155
2110
|
|
|
2156
2111
|
def _batch_with_config(
|
|
2157
2112
|
self,
|
|
2158
|
-
func:
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
],
|
|
2164
|
-
|
|
2165
|
-
[list[Input], list[CallbackManagerForChainRun], list[RunnableConfig]],
|
|
2166
|
-
list[Union[Exception, Output]],
|
|
2167
|
-
],
|
|
2113
|
+
func: Callable[[list[Input]], list[Exception | Output]]
|
|
2114
|
+
| Callable[
|
|
2115
|
+
[list[Input], list[CallbackManagerForChainRun]], list[Exception | Output]
|
|
2116
|
+
]
|
|
2117
|
+
| Callable[
|
|
2118
|
+
[list[Input], list[CallbackManagerForChainRun], list[RunnableConfig]],
|
|
2119
|
+
list[Exception | Output],
|
|
2168
2120
|
],
|
|
2169
2121
|
inputs: list[Input],
|
|
2170
|
-
config:
|
|
2122
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
2171
2123
|
*,
|
|
2172
2124
|
return_exceptions: bool = False,
|
|
2173
|
-
run_type:
|
|
2174
|
-
**kwargs:
|
|
2125
|
+
run_type: str | None = None,
|
|
2126
|
+
**kwargs: Any | None,
|
|
2175
2127
|
) -> list[Output]:
|
|
2176
2128
|
"""Transform a list of inputs to a list of outputs, with callbacks.
|
|
2177
2129
|
|
|
@@ -2193,14 +2145,14 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2193
2145
|
run_id=config.pop("run_id", None),
|
|
2194
2146
|
)
|
|
2195
2147
|
for callback_manager, input_, config in zip(
|
|
2196
|
-
callback_managers, inputs, configs
|
|
2148
|
+
callback_managers, inputs, configs, strict=False
|
|
2197
2149
|
)
|
|
2198
2150
|
]
|
|
2199
2151
|
try:
|
|
2200
2152
|
if accepts_config(func):
|
|
2201
2153
|
kwargs["config"] = [
|
|
2202
2154
|
patch_config(c, callbacks=rm.get_child())
|
|
2203
|
-
for c, rm in zip(configs, run_managers)
|
|
2155
|
+
for c, rm in zip(configs, run_managers, strict=False)
|
|
2204
2156
|
]
|
|
2205
2157
|
if accepts_run_manager(func):
|
|
2206
2158
|
kwargs["run_manager"] = run_managers
|
|
@@ -2212,8 +2164,8 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2212
2164
|
return cast("list[Output]", [e for _ in inputs])
|
|
2213
2165
|
raise
|
|
2214
2166
|
else:
|
|
2215
|
-
first_exception:
|
|
2216
|
-
for run_manager, out in zip(run_managers, output):
|
|
2167
|
+
first_exception: Exception | None = None
|
|
2168
|
+
for run_manager, out in zip(run_managers, output, strict=False):
|
|
2217
2169
|
if isinstance(out, Exception):
|
|
2218
2170
|
first_exception = first_exception or out
|
|
2219
2171
|
run_manager.on_chain_error(out)
|
|
@@ -2225,27 +2177,21 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2225
2177
|
|
|
2226
2178
|
async def _abatch_with_config(
|
|
2227
2179
|
self,
|
|
2228
|
-
func:
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
list[Input],
|
|
2237
|
-
list[AsyncCallbackManagerForChainRun],
|
|
2238
|
-
list[RunnableConfig],
|
|
2239
|
-
],
|
|
2240
|
-
Awaitable[list[Union[Exception, Output]]],
|
|
2241
|
-
],
|
|
2180
|
+
func: Callable[[list[Input]], Awaitable[list[Exception | Output]]]
|
|
2181
|
+
| Callable[
|
|
2182
|
+
[list[Input], list[AsyncCallbackManagerForChainRun]],
|
|
2183
|
+
Awaitable[list[Exception | Output]],
|
|
2184
|
+
]
|
|
2185
|
+
| Callable[
|
|
2186
|
+
[list[Input], list[AsyncCallbackManagerForChainRun], list[RunnableConfig]],
|
|
2187
|
+
Awaitable[list[Exception | Output]],
|
|
2242
2188
|
],
|
|
2243
2189
|
inputs: list[Input],
|
|
2244
|
-
config:
|
|
2190
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
2245
2191
|
*,
|
|
2246
2192
|
return_exceptions: bool = False,
|
|
2247
|
-
run_type:
|
|
2248
|
-
**kwargs:
|
|
2193
|
+
run_type: str | None = None,
|
|
2194
|
+
**kwargs: Any | None,
|
|
2249
2195
|
) -> list[Output]:
|
|
2250
2196
|
"""Transform a list of inputs to a list of outputs, with callbacks.
|
|
2251
2197
|
|
|
@@ -2270,7 +2216,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2270
2216
|
run_id=config.pop("run_id", None),
|
|
2271
2217
|
)
|
|
2272
2218
|
for callback_manager, input_, config in zip(
|
|
2273
|
-
callback_managers, inputs, configs
|
|
2219
|
+
callback_managers, inputs, configs, strict=False
|
|
2274
2220
|
)
|
|
2275
2221
|
)
|
|
2276
2222
|
)
|
|
@@ -2278,7 +2224,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2278
2224
|
if accepts_config(func):
|
|
2279
2225
|
kwargs["config"] = [
|
|
2280
2226
|
patch_config(c, callbacks=rm.get_child())
|
|
2281
|
-
for c, rm in zip(configs, run_managers)
|
|
2227
|
+
for c, rm in zip(configs, run_managers, strict=False)
|
|
2282
2228
|
]
|
|
2283
2229
|
if accepts_run_manager(func):
|
|
2284
2230
|
kwargs["run_manager"] = run_managers
|
|
@@ -2291,9 +2237,9 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2291
2237
|
return cast("list[Output]", [e for _ in inputs])
|
|
2292
2238
|
raise
|
|
2293
2239
|
else:
|
|
2294
|
-
first_exception:
|
|
2240
|
+
first_exception: Exception | None = None
|
|
2295
2241
|
coros: list[Awaitable[None]] = []
|
|
2296
|
-
for run_manager, out in zip(run_managers, output):
|
|
2242
|
+
for run_manager, out in zip(run_managers, output, strict=False):
|
|
2297
2243
|
if isinstance(out, Exception):
|
|
2298
2244
|
first_exception = first_exception or out
|
|
2299
2245
|
coros.append(run_manager.on_chain_error(out))
|
|
@@ -2307,21 +2253,15 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2307
2253
|
def _transform_stream_with_config(
|
|
2308
2254
|
self,
|
|
2309
2255
|
inputs: Iterator[Input],
|
|
2310
|
-
transformer:
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
Iterator[Input],
|
|
2316
|
-
CallbackManagerForChainRun,
|
|
2317
|
-
RunnableConfig,
|
|
2318
|
-
],
|
|
2319
|
-
Iterator[Output],
|
|
2320
|
-
],
|
|
2256
|
+
transformer: Callable[[Iterator[Input]], Iterator[Output]]
|
|
2257
|
+
| Callable[[Iterator[Input], CallbackManagerForChainRun], Iterator[Output]]
|
|
2258
|
+
| Callable[
|
|
2259
|
+
[Iterator[Input], CallbackManagerForChainRun, RunnableConfig],
|
|
2260
|
+
Iterator[Output],
|
|
2321
2261
|
],
|
|
2322
|
-
config:
|
|
2323
|
-
run_type:
|
|
2324
|
-
**kwargs:
|
|
2262
|
+
config: RunnableConfig | None,
|
|
2263
|
+
run_type: str | None = None,
|
|
2264
|
+
**kwargs: Any | None,
|
|
2325
2265
|
) -> Iterator[Output]:
|
|
2326
2266
|
"""Transform a stream with config.
|
|
2327
2267
|
|
|
@@ -2334,9 +2274,9 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2334
2274
|
# tee the input so we can iterate over it twice
|
|
2335
2275
|
input_for_tracing, input_for_transform = tee(inputs, 2)
|
|
2336
2276
|
# Start the input iterator to ensure the input Runnable starts before this one
|
|
2337
|
-
final_input:
|
|
2277
|
+
final_input: Input | None = next(input_for_tracing, None)
|
|
2338
2278
|
final_input_supported = True
|
|
2339
|
-
final_output:
|
|
2279
|
+
final_output: Output | None = None
|
|
2340
2280
|
final_output_supported = True
|
|
2341
2281
|
|
|
2342
2282
|
config = ensure_config(config)
|
|
@@ -2407,24 +2347,18 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2407
2347
|
async def _atransform_stream_with_config(
|
|
2408
2348
|
self,
|
|
2409
2349
|
inputs: AsyncIterator[Input],
|
|
2410
|
-
transformer:
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
AsyncIterator[Input],
|
|
2419
|
-
AsyncCallbackManagerForChainRun,
|
|
2420
|
-
RunnableConfig,
|
|
2421
|
-
],
|
|
2422
|
-
AsyncIterator[Output],
|
|
2423
|
-
],
|
|
2350
|
+
transformer: Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
2351
|
+
| Callable[
|
|
2352
|
+
[AsyncIterator[Input], AsyncCallbackManagerForChainRun],
|
|
2353
|
+
AsyncIterator[Output],
|
|
2354
|
+
]
|
|
2355
|
+
| Callable[
|
|
2356
|
+
[AsyncIterator[Input], AsyncCallbackManagerForChainRun, RunnableConfig],
|
|
2357
|
+
AsyncIterator[Output],
|
|
2424
2358
|
],
|
|
2425
|
-
config:
|
|
2426
|
-
run_type:
|
|
2427
|
-
**kwargs:
|
|
2359
|
+
config: RunnableConfig | None,
|
|
2360
|
+
run_type: str | None = None,
|
|
2361
|
+
**kwargs: Any | None,
|
|
2428
2362
|
) -> AsyncIterator[Output]:
|
|
2429
2363
|
"""Transform a stream with config.
|
|
2430
2364
|
|
|
@@ -2437,9 +2371,9 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2437
2371
|
# tee the input so we can iterate over it twice
|
|
2438
2372
|
input_for_tracing, input_for_transform = atee(inputs, 2)
|
|
2439
2373
|
# Start the input iterator to ensure the input Runnable starts before this one
|
|
2440
|
-
final_input:
|
|
2374
|
+
final_input: Input | None = await py_anext(input_for_tracing, None)
|
|
2441
2375
|
final_input_supported = True
|
|
2442
|
-
final_output:
|
|
2376
|
+
final_output: Output | None = None
|
|
2443
2377
|
final_output_supported = True
|
|
2444
2378
|
|
|
2445
2379
|
config = ensure_config(config)
|
|
@@ -2516,11 +2450,11 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2516
2450
|
@beta_decorator.beta(message="This API is in beta and may change in the future.")
|
|
2517
2451
|
def as_tool(
|
|
2518
2452
|
self,
|
|
2519
|
-
args_schema:
|
|
2453
|
+
args_schema: type[BaseModel] | None = None,
|
|
2520
2454
|
*,
|
|
2521
|
-
name:
|
|
2522
|
-
description:
|
|
2523
|
-
arg_types:
|
|
2455
|
+
name: str | None = None,
|
|
2456
|
+
description: str | None = None,
|
|
2457
|
+
arg_types: dict[str, type] | None = None,
|
|
2524
2458
|
) -> BaseTool:
|
|
2525
2459
|
"""Create a ``BaseTool`` from a ``Runnable``.
|
|
2526
2460
|
|
|
@@ -2536,90 +2470,88 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2536
2470
|
name: The name of the tool. Defaults to None.
|
|
2537
2471
|
description: The description of the tool. Defaults to None.
|
|
2538
2472
|
arg_types: A dictionary of argument names to types. Defaults to None.
|
|
2539
|
-
message_version: Version of ``ToolMessage`` to return given
|
|
2540
|
-
:class:`~langchain_core.messages.content.ToolCall` input.
|
|
2541
2473
|
|
|
2542
2474
|
Returns:
|
|
2543
2475
|
A ``BaseTool`` instance.
|
|
2544
2476
|
|
|
2545
2477
|
Typed dict input:
|
|
2546
2478
|
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
from langchain_core.runnables import RunnableLambda
|
|
2479
|
+
```python
|
|
2480
|
+
from typing_extensions import TypedDict
|
|
2481
|
+
from langchain_core.runnables import RunnableLambda
|
|
2551
2482
|
|
|
2552
2483
|
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2484
|
+
class Args(TypedDict):
|
|
2485
|
+
a: int
|
|
2486
|
+
b: list[int]
|
|
2556
2487
|
|
|
2557
2488
|
|
|
2558
|
-
|
|
2559
|
-
|
|
2489
|
+
def f(x: Args) -> str:
|
|
2490
|
+
return str(x["a"] * max(x["b"]))
|
|
2560
2491
|
|
|
2561
2492
|
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2493
|
+
runnable = RunnableLambda(f)
|
|
2494
|
+
as_tool = runnable.as_tool()
|
|
2495
|
+
as_tool.invoke({"a": 3, "b": [1, 2]})
|
|
2496
|
+
```
|
|
2565
2497
|
|
|
2566
2498
|
``dict`` input, specifying schema via ``args_schema``:
|
|
2567
2499
|
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
from langchain_core.runnables import RunnableLambda
|
|
2500
|
+
```python
|
|
2501
|
+
from typing import Any
|
|
2502
|
+
from pydantic import BaseModel, Field
|
|
2503
|
+
from langchain_core.runnables import RunnableLambda
|
|
2573
2504
|
|
|
2574
|
-
|
|
2575
|
-
|
|
2505
|
+
def f(x: dict[str, Any]) -> str:
|
|
2506
|
+
return str(x["a"] * max(x["b"]))
|
|
2576
2507
|
|
|
2577
|
-
|
|
2578
|
-
|
|
2508
|
+
class FSchema(BaseModel):
|
|
2509
|
+
\"\"\"Apply a function to an integer and list of integers.\"\"\"
|
|
2579
2510
|
|
|
2580
|
-
|
|
2581
|
-
|
|
2511
|
+
a: int = Field(..., description="Integer")
|
|
2512
|
+
b: list[int] = Field(..., description="List of ints")
|
|
2582
2513
|
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2514
|
+
runnable = RunnableLambda(f)
|
|
2515
|
+
as_tool = runnable.as_tool(FSchema)
|
|
2516
|
+
as_tool.invoke({"a": 3, "b": [1, 2]})
|
|
2517
|
+
```
|
|
2586
2518
|
|
|
2587
2519
|
``dict`` input, specifying schema via ``arg_types``:
|
|
2588
2520
|
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
from langchain_core.runnables import RunnableLambda
|
|
2521
|
+
```python
|
|
2522
|
+
from typing import Any
|
|
2523
|
+
from langchain_core.runnables import RunnableLambda
|
|
2593
2524
|
|
|
2594
2525
|
|
|
2595
|
-
|
|
2596
|
-
|
|
2526
|
+
def f(x: dict[str, Any]) -> str:
|
|
2527
|
+
return str(x["a"] * max(x["b"]))
|
|
2597
2528
|
|
|
2598
2529
|
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2530
|
+
runnable = RunnableLambda(f)
|
|
2531
|
+
as_tool = runnable.as_tool(arg_types={"a": int, "b": list[int]})
|
|
2532
|
+
as_tool.invoke({"a": 3, "b": [1, 2]})
|
|
2533
|
+
```
|
|
2602
2534
|
|
|
2603
2535
|
String input:
|
|
2604
2536
|
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
from langchain_core.runnables import RunnableLambda
|
|
2537
|
+
```python
|
|
2538
|
+
from langchain_core.runnables import RunnableLambda
|
|
2608
2539
|
|
|
2609
2540
|
|
|
2610
|
-
|
|
2611
|
-
|
|
2541
|
+
def f(x: str) -> str:
|
|
2542
|
+
return x + "a"
|
|
2612
2543
|
|
|
2613
2544
|
|
|
2614
|
-
|
|
2615
|
-
|
|
2545
|
+
def g(x: str) -> str:
|
|
2546
|
+
return x + "z"
|
|
2616
2547
|
|
|
2617
2548
|
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2549
|
+
runnable = RunnableLambda(f) | g
|
|
2550
|
+
as_tool = runnable.as_tool()
|
|
2551
|
+
as_tool.invoke("b")
|
|
2552
|
+
```
|
|
2621
2553
|
|
|
2622
|
-
|
|
2554
|
+
!!! version-added "Added in version 0.2.14"
|
|
2623
2555
|
|
|
2624
2556
|
"""
|
|
2625
2557
|
# Avoid circular import
|
|
@@ -2637,7 +2569,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2637
2569
|
class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
2638
2570
|
"""Runnable that can be serialized to JSON."""
|
|
2639
2571
|
|
|
2640
|
-
name:
|
|
2572
|
+
name: str | None = None
|
|
2641
2573
|
|
|
2642
2574
|
model_config = ConfigDict(
|
|
2643
2575
|
# Suppress warnings from pydantic protected namespaces
|
|
@@ -2646,7 +2578,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2646
2578
|
)
|
|
2647
2579
|
|
|
2648
2580
|
@override
|
|
2649
|
-
def to_json(self) ->
|
|
2581
|
+
def to_json(self) -> SerializedConstructor | SerializedNotImplemented:
|
|
2650
2582
|
"""Serialize the ``Runnable`` to JSON.
|
|
2651
2583
|
|
|
2652
2584
|
Returns:
|
|
@@ -2672,32 +2604,29 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2672
2604
|
Returns:
|
|
2673
2605
|
A new ``Runnable`` with the fields configured.
|
|
2674
2606
|
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
from langchain_openai import ChatOpenAI
|
|
2679
|
-
|
|
2680
|
-
model = ChatOpenAI(max_tokens=20).configurable_fields(
|
|
2681
|
-
max_tokens=ConfigurableField(
|
|
2682
|
-
id="output_token_number",
|
|
2683
|
-
name="Max tokens in the output",
|
|
2684
|
-
description="The maximum number of tokens in the output",
|
|
2685
|
-
)
|
|
2686
|
-
)
|
|
2607
|
+
```python
|
|
2608
|
+
from langchain_core.runnables import ConfigurableField
|
|
2609
|
+
from langchain_openai import ChatOpenAI
|
|
2687
2610
|
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
"
|
|
2611
|
+
model = ChatOpenAI(max_tokens=20).configurable_fields(
|
|
2612
|
+
max_tokens=ConfigurableField(
|
|
2613
|
+
id="output_token_number",
|
|
2614
|
+
name="Max tokens in the output",
|
|
2615
|
+
description="The maximum number of tokens in the output",
|
|
2691
2616
|
)
|
|
2617
|
+
)
|
|
2692
2618
|
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
"max_tokens_200: ",
|
|
2696
|
-
model.with_config(configurable={"output_token_number": 200})
|
|
2697
|
-
.invoke("tell me something about chess")
|
|
2698
|
-
.content,
|
|
2699
|
-
)
|
|
2619
|
+
# max_tokens = 20
|
|
2620
|
+
print("max_tokens_20: ", model.invoke("tell me something about chess").content)
|
|
2700
2621
|
|
|
2622
|
+
# max_tokens = 200
|
|
2623
|
+
print(
|
|
2624
|
+
"max_tokens_200: ",
|
|
2625
|
+
model.with_config(configurable={"output_token_number": 200})
|
|
2626
|
+
.invoke("tell me something about chess")
|
|
2627
|
+
.content,
|
|
2628
|
+
)
|
|
2629
|
+
```
|
|
2701
2630
|
"""
|
|
2702
2631
|
# Import locally to prevent circular import
|
|
2703
2632
|
from langchain_core.runnables.configurable import ( # noqa: PLC0415
|
|
@@ -2721,7 +2650,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2721
2650
|
*,
|
|
2722
2651
|
default_key: str = "default",
|
|
2723
2652
|
prefix_keys: bool = False,
|
|
2724
|
-
**kwargs:
|
|
2653
|
+
**kwargs: Runnable[Input, Output] | Callable[[], Runnable[Input, Output]],
|
|
2725
2654
|
) -> RunnableSerializable[Input, Output]:
|
|
2726
2655
|
"""Configure alternatives for ``Runnables`` that can be set at runtime.
|
|
2727
2656
|
|
|
@@ -2738,30 +2667,29 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2738
2667
|
Returns:
|
|
2739
2668
|
A new ``Runnable`` with the alternatives configured.
|
|
2740
2669
|
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
)
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
)
|
|
2754
|
-
|
|
2755
|
-
# uses the default model ChatAnthropic
|
|
2756
|
-
print(model.invoke("which organization created you?").content)
|
|
2670
|
+
```python
|
|
2671
|
+
from langchain_anthropic import ChatAnthropic
|
|
2672
|
+
from langchain_core.runnables.utils import ConfigurableField
|
|
2673
|
+
from langchain_openai import ChatOpenAI
|
|
2674
|
+
|
|
2675
|
+
model = ChatAnthropic(
|
|
2676
|
+
model_name="claude-3-7-sonnet-20250219"
|
|
2677
|
+
).configurable_alternatives(
|
|
2678
|
+
ConfigurableField(id="llm"),
|
|
2679
|
+
default_key="anthropic",
|
|
2680
|
+
openai=ChatOpenAI(),
|
|
2681
|
+
)
|
|
2757
2682
|
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
model.with_config(configurable={"llm": "openai"})
|
|
2761
|
-
.invoke("which organization created you?")
|
|
2762
|
-
.content
|
|
2763
|
-
)
|
|
2683
|
+
# uses the default model ChatAnthropic
|
|
2684
|
+
print(model.invoke("which organization created you?").content)
|
|
2764
2685
|
|
|
2686
|
+
# uses ChatOpenAI
|
|
2687
|
+
print(
|
|
2688
|
+
model.with_config(configurable={"llm": "openai"})
|
|
2689
|
+
.invoke("which organization created you?")
|
|
2690
|
+
.content
|
|
2691
|
+
)
|
|
2692
|
+
```
|
|
2765
2693
|
"""
|
|
2766
2694
|
# Import locally to prevent circular import
|
|
2767
2695
|
from langchain_core.runnables.configurable import ( # noqa: PLC0415
|
|
@@ -2778,7 +2706,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2778
2706
|
|
|
2779
2707
|
|
|
2780
2708
|
def _seq_input_schema(
|
|
2781
|
-
steps: list[Runnable[Any, Any]], config:
|
|
2709
|
+
steps: list[Runnable[Any, Any]], config: RunnableConfig | None
|
|
2782
2710
|
) -> type[BaseModel]:
|
|
2783
2711
|
# Import locally to prevent circular import
|
|
2784
2712
|
from langchain_core.runnables.passthrough import ( # noqa: PLC0415
|
|
@@ -2808,7 +2736,7 @@ def _seq_input_schema(
|
|
|
2808
2736
|
|
|
2809
2737
|
|
|
2810
2738
|
def _seq_output_schema(
|
|
2811
|
-
steps: list[Runnable[Any, Any]], config:
|
|
2739
|
+
steps: list[Runnable[Any, Any]], config: RunnableConfig | None
|
|
2812
2740
|
) -> type[BaseModel]:
|
|
2813
2741
|
# Import locally to prevent circular import
|
|
2814
2742
|
from langchain_core.runnables.passthrough import ( # noqa: PLC0415
|
|
@@ -2886,7 +2814,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2886
2814
|
streaming will only begin after this component is run. If there are
|
|
2887
2815
|
multiple blocking components, streaming begins after the last one.
|
|
2888
2816
|
|
|
2889
|
-
|
|
2817
|
+
!!! note
|
|
2890
2818
|
``RunnableLambdas`` do not support ``transform`` by default! So if you need to
|
|
2891
2819
|
use a ``RunnableLambdas`` be careful about where you place them in a
|
|
2892
2820
|
``RunnableSequence`` (if you need to use the ``stream``/``astream`` methods).
|
|
@@ -2897,50 +2825,49 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2897
2825
|
Here is a simple example that uses simple functions to illustrate the use of
|
|
2898
2826
|
``RunnableSequence``:
|
|
2899
2827
|
|
|
2900
|
-
|
|
2828
|
+
```python
|
|
2829
|
+
from langchain_core.runnables import RunnableLambda
|
|
2901
2830
|
|
|
2902
|
-
from langchain_core.runnables import RunnableLambda
|
|
2903
2831
|
|
|
2832
|
+
def add_one(x: int) -> int:
|
|
2833
|
+
return x + 1
|
|
2904
2834
|
|
|
2905
|
-
def add_one(x: int) -> int:
|
|
2906
|
-
return x + 1
|
|
2907
2835
|
|
|
2836
|
+
def mul_two(x: int) -> int:
|
|
2837
|
+
return x * 2
|
|
2908
2838
|
|
|
2909
|
-
def mul_two(x: int) -> int:
|
|
2910
|
-
return x * 2
|
|
2911
2839
|
|
|
2840
|
+
runnable_1 = RunnableLambda(add_one)
|
|
2841
|
+
runnable_2 = RunnableLambda(mul_two)
|
|
2842
|
+
sequence = runnable_1 | runnable_2
|
|
2843
|
+
# Or equivalently:
|
|
2844
|
+
# sequence = RunnableSequence(first=runnable_1, last=runnable_2)
|
|
2845
|
+
sequence.invoke(1)
|
|
2846
|
+
await sequence.ainvoke(1)
|
|
2912
2847
|
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
# Or equivalently:
|
|
2917
|
-
# sequence = RunnableSequence(first=runnable_1, last=runnable_2)
|
|
2918
|
-
sequence.invoke(1)
|
|
2919
|
-
await sequence.ainvoke(1)
|
|
2920
|
-
|
|
2921
|
-
sequence.batch([1, 2, 3])
|
|
2922
|
-
await sequence.abatch([1, 2, 3])
|
|
2848
|
+
sequence.batch([1, 2, 3])
|
|
2849
|
+
await sequence.abatch([1, 2, 3])
|
|
2850
|
+
```
|
|
2923
2851
|
|
|
2924
2852
|
Here's an example that uses streams JSON output generated by an LLM:
|
|
2925
2853
|
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
from langchain_openai import ChatOpenAI
|
|
2854
|
+
```python
|
|
2855
|
+
from langchain_core.output_parsers.json import SimpleJsonOutputParser
|
|
2856
|
+
from langchain_openai import ChatOpenAI
|
|
2930
2857
|
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
model = ChatOpenAI()
|
|
2938
|
-
chain = prompt | model | SimpleJsonOutputParser()
|
|
2858
|
+
prompt = PromptTemplate.from_template(
|
|
2859
|
+
"In JSON format, give me a list of {topic} and their "
|
|
2860
|
+
"corresponding names in French, Spanish and in a "
|
|
2861
|
+
"Cat Language."
|
|
2862
|
+
)
|
|
2939
2863
|
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
print(chunk, sep="", flush=True) # noqa: T201
|
|
2864
|
+
model = ChatOpenAI()
|
|
2865
|
+
chain = prompt | model | SimpleJsonOutputParser()
|
|
2943
2866
|
|
|
2867
|
+
async for chunk in chain.astream({"topic": "colors"}):
|
|
2868
|
+
print("-") # noqa: T201
|
|
2869
|
+
print(chunk, sep="", flush=True) # noqa: T201
|
|
2870
|
+
```
|
|
2944
2871
|
"""
|
|
2945
2872
|
|
|
2946
2873
|
# The steps are broken into first, middle and last, solely for type checking
|
|
@@ -2956,10 +2883,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2956
2883
|
def __init__(
|
|
2957
2884
|
self,
|
|
2958
2885
|
*steps: RunnableLike,
|
|
2959
|
-
name:
|
|
2960
|
-
first:
|
|
2961
|
-
middle:
|
|
2962
|
-
last:
|
|
2886
|
+
name: str | None = None,
|
|
2887
|
+
first: Runnable[Any, Any] | None = None,
|
|
2888
|
+
middle: list[Runnable[Any, Any]] | None = None,
|
|
2889
|
+
last: Runnable[Any, Any] | None = None,
|
|
2963
2890
|
) -> None:
|
|
2964
2891
|
"""Create a new ``RunnableSequence``.
|
|
2965
2892
|
|
|
@@ -3033,9 +2960,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3033
2960
|
return self.last.OutputType
|
|
3034
2961
|
|
|
3035
2962
|
@override
|
|
3036
|
-
def get_input_schema(
|
|
3037
|
-
self, config: Optional[RunnableConfig] = None
|
|
3038
|
-
) -> type[BaseModel]:
|
|
2963
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
3039
2964
|
"""Get the input schema of the ``Runnable``.
|
|
3040
2965
|
|
|
3041
2966
|
Args:
|
|
@@ -3049,7 +2974,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3049
2974
|
|
|
3050
2975
|
@override
|
|
3051
2976
|
def get_output_schema(
|
|
3052
|
-
self, config:
|
|
2977
|
+
self, config: RunnableConfig | None = None
|
|
3053
2978
|
) -> type[BaseModel]:
|
|
3054
2979
|
"""Get the output schema of the ``Runnable``.
|
|
3055
2980
|
|
|
@@ -3077,7 +3002,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3077
3002
|
)
|
|
3078
3003
|
|
|
3079
3004
|
@override
|
|
3080
|
-
def get_graph(self, config:
|
|
3005
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
3081
3006
|
"""Get the graph representation of the ``Runnable``.
|
|
3082
3007
|
|
|
3083
3008
|
Args:
|
|
@@ -3120,13 +3045,11 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3120
3045
|
@override
|
|
3121
3046
|
def __or__(
|
|
3122
3047
|
self,
|
|
3123
|
-
other:
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
Mapping[str, Union[Runnable[Any, Other], Callable[[Any], Other], Any]],
|
|
3129
|
-
],
|
|
3048
|
+
other: Runnable[Any, Other]
|
|
3049
|
+
| Callable[[Iterator[Any]], Iterator[Other]]
|
|
3050
|
+
| Callable[[AsyncIterator[Any]], AsyncIterator[Other]]
|
|
3051
|
+
| Callable[[Any], Other]
|
|
3052
|
+
| Mapping[str, Runnable[Any, Other] | Callable[[Any], Other] | Any],
|
|
3130
3053
|
) -> RunnableSerializable[Input, Other]:
|
|
3131
3054
|
if isinstance(other, RunnableSequence):
|
|
3132
3055
|
return RunnableSequence(
|
|
@@ -3149,13 +3072,11 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3149
3072
|
@override
|
|
3150
3073
|
def __ror__(
|
|
3151
3074
|
self,
|
|
3152
|
-
other:
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
Mapping[str, Union[Runnable[Other, Any], Callable[[Other], Any], Any]],
|
|
3158
|
-
],
|
|
3075
|
+
other: Runnable[Other, Any]
|
|
3076
|
+
| Callable[[Iterator[Other]], Iterator[Any]]
|
|
3077
|
+
| Callable[[AsyncIterator[Other]], AsyncIterator[Any]]
|
|
3078
|
+
| Callable[[Other], Any]
|
|
3079
|
+
| Mapping[str, Runnable[Other, Any] | Callable[[Other], Any] | Any],
|
|
3159
3080
|
) -> RunnableSerializable[Other, Output]:
|
|
3160
3081
|
if isinstance(other, RunnableSequence):
|
|
3161
3082
|
return RunnableSequence(
|
|
@@ -3177,7 +3098,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3177
3098
|
|
|
3178
3099
|
@override
|
|
3179
3100
|
def invoke(
|
|
3180
|
-
self, input: Input, config:
|
|
3101
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
3181
3102
|
) -> Output:
|
|
3182
3103
|
# setup callbacks and context
|
|
3183
3104
|
config = ensure_config(config)
|
|
@@ -3215,8 +3136,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3215
3136
|
async def ainvoke(
|
|
3216
3137
|
self,
|
|
3217
3138
|
input: Input,
|
|
3218
|
-
config:
|
|
3219
|
-
**kwargs:
|
|
3139
|
+
config: RunnableConfig | None = None,
|
|
3140
|
+
**kwargs: Any | None,
|
|
3220
3141
|
) -> Output:
|
|
3221
3142
|
# setup callbacks and context
|
|
3222
3143
|
config = ensure_config(config)
|
|
@@ -3255,10 +3176,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3255
3176
|
def batch(
|
|
3256
3177
|
self,
|
|
3257
3178
|
inputs: list[Input],
|
|
3258
|
-
config:
|
|
3179
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
3259
3180
|
*,
|
|
3260
3181
|
return_exceptions: bool = False,
|
|
3261
|
-
**kwargs:
|
|
3182
|
+
**kwargs: Any | None,
|
|
3262
3183
|
) -> list[Output]:
|
|
3263
3184
|
if not inputs:
|
|
3264
3185
|
return []
|
|
@@ -3285,7 +3206,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3285
3206
|
name=config.get("run_name") or self.get_name(),
|
|
3286
3207
|
run_id=config.pop("run_id", None),
|
|
3287
3208
|
)
|
|
3288
|
-
for cm, input_, config in zip(
|
|
3209
|
+
for cm, input_, config in zip(
|
|
3210
|
+
callback_managers, inputs, configs, strict=False
|
|
3211
|
+
)
|
|
3289
3212
|
]
|
|
3290
3213
|
|
|
3291
3214
|
# invoke
|
|
@@ -3305,7 +3228,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3305
3228
|
inputs = step.batch(
|
|
3306
3229
|
[
|
|
3307
3230
|
inp
|
|
3308
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3231
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3309
3232
|
if i not in failed_inputs_map
|
|
3310
3233
|
],
|
|
3311
3234
|
[
|
|
@@ -3314,7 +3237,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3314
3237
|
config,
|
|
3315
3238
|
callbacks=rm.get_child(f"seq:step:{stepidx + 1}"),
|
|
3316
3239
|
)
|
|
3317
|
-
for i, (rm, config) in enumerate(
|
|
3240
|
+
for i, (rm, config) in enumerate(
|
|
3241
|
+
zip(run_managers, configs, strict=False)
|
|
3242
|
+
)
|
|
3318
3243
|
if i not in failed_inputs_map
|
|
3319
3244
|
],
|
|
3320
3245
|
return_exceptions=return_exceptions,
|
|
@@ -3324,7 +3249,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3324
3249
|
failed_inputs_map.update(
|
|
3325
3250
|
{
|
|
3326
3251
|
i: inp
|
|
3327
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3252
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3328
3253
|
if isinstance(inp, Exception)
|
|
3329
3254
|
}
|
|
3330
3255
|
)
|
|
@@ -3350,7 +3275,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3350
3275
|
patch_config(
|
|
3351
3276
|
config, callbacks=rm.get_child(f"seq:step:{i + 1}")
|
|
3352
3277
|
)
|
|
3353
|
-
for rm, config in zip(run_managers, configs)
|
|
3278
|
+
for rm, config in zip(run_managers, configs, strict=False)
|
|
3354
3279
|
],
|
|
3355
3280
|
return_exceptions=return_exceptions,
|
|
3356
3281
|
**(kwargs if i == 0 else {}),
|
|
@@ -3364,8 +3289,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3364
3289
|
return cast("list[Output]", [e for _ in inputs])
|
|
3365
3290
|
raise
|
|
3366
3291
|
else:
|
|
3367
|
-
first_exception:
|
|
3368
|
-
for run_manager, out in zip(run_managers, inputs):
|
|
3292
|
+
first_exception: Exception | None = None
|
|
3293
|
+
for run_manager, out in zip(run_managers, inputs, strict=False):
|
|
3369
3294
|
if isinstance(out, Exception):
|
|
3370
3295
|
first_exception = first_exception or out
|
|
3371
3296
|
run_manager.on_chain_error(out)
|
|
@@ -3379,10 +3304,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3379
3304
|
async def abatch(
|
|
3380
3305
|
self,
|
|
3381
3306
|
inputs: list[Input],
|
|
3382
|
-
config:
|
|
3307
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
3383
3308
|
*,
|
|
3384
3309
|
return_exceptions: bool = False,
|
|
3385
|
-
**kwargs:
|
|
3310
|
+
**kwargs: Any | None,
|
|
3386
3311
|
) -> list[Output]:
|
|
3387
3312
|
if not inputs:
|
|
3388
3313
|
return []
|
|
@@ -3410,7 +3335,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3410
3335
|
name=config.get("run_name") or self.get_name(),
|
|
3411
3336
|
run_id=config.pop("run_id", None),
|
|
3412
3337
|
)
|
|
3413
|
-
for cm, input_, config in zip(
|
|
3338
|
+
for cm, input_, config in zip(
|
|
3339
|
+
callback_managers, inputs, configs, strict=False
|
|
3340
|
+
)
|
|
3414
3341
|
)
|
|
3415
3342
|
)
|
|
3416
3343
|
|
|
@@ -3432,7 +3359,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3432
3359
|
inputs = await step.abatch(
|
|
3433
3360
|
[
|
|
3434
3361
|
inp
|
|
3435
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3362
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3436
3363
|
if i not in failed_inputs_map
|
|
3437
3364
|
],
|
|
3438
3365
|
[
|
|
@@ -3441,7 +3368,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3441
3368
|
config,
|
|
3442
3369
|
callbacks=rm.get_child(f"seq:step:{stepidx + 1}"),
|
|
3443
3370
|
)
|
|
3444
|
-
for i, (rm, config) in enumerate(
|
|
3371
|
+
for i, (rm, config) in enumerate(
|
|
3372
|
+
zip(run_managers, configs, strict=False)
|
|
3373
|
+
)
|
|
3445
3374
|
if i not in failed_inputs_map
|
|
3446
3375
|
],
|
|
3447
3376
|
return_exceptions=return_exceptions,
|
|
@@ -3451,7 +3380,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3451
3380
|
failed_inputs_map.update(
|
|
3452
3381
|
{
|
|
3453
3382
|
i: inp
|
|
3454
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3383
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3455
3384
|
if isinstance(inp, Exception)
|
|
3456
3385
|
}
|
|
3457
3386
|
)
|
|
@@ -3477,7 +3406,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3477
3406
|
patch_config(
|
|
3478
3407
|
config, callbacks=rm.get_child(f"seq:step:{i + 1}")
|
|
3479
3408
|
)
|
|
3480
|
-
for rm, config in zip(run_managers, configs)
|
|
3409
|
+
for rm, config in zip(run_managers, configs, strict=False)
|
|
3481
3410
|
],
|
|
3482
3411
|
return_exceptions=return_exceptions,
|
|
3483
3412
|
**(kwargs if i == 0 else {}),
|
|
@@ -3489,9 +3418,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3489
3418
|
return cast("list[Output]", [e for _ in inputs])
|
|
3490
3419
|
raise
|
|
3491
3420
|
else:
|
|
3492
|
-
first_exception:
|
|
3421
|
+
first_exception: Exception | None = None
|
|
3493
3422
|
coros: list[Awaitable[None]] = []
|
|
3494
|
-
for run_manager, out in zip(run_managers, inputs):
|
|
3423
|
+
for run_manager, out in zip(run_managers, inputs, strict=False):
|
|
3495
3424
|
if isinstance(out, Exception):
|
|
3496
3425
|
first_exception = first_exception or out
|
|
3497
3426
|
coros.append(run_manager.on_chain_error(out))
|
|
@@ -3554,8 +3483,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3554
3483
|
def transform(
|
|
3555
3484
|
self,
|
|
3556
3485
|
input: Iterator[Input],
|
|
3557
|
-
config:
|
|
3558
|
-
**kwargs:
|
|
3486
|
+
config: RunnableConfig | None = None,
|
|
3487
|
+
**kwargs: Any | None,
|
|
3559
3488
|
) -> Iterator[Output]:
|
|
3560
3489
|
yield from self._transform_stream_with_config(
|
|
3561
3490
|
input,
|
|
@@ -3568,8 +3497,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3568
3497
|
def stream(
|
|
3569
3498
|
self,
|
|
3570
3499
|
input: Input,
|
|
3571
|
-
config:
|
|
3572
|
-
**kwargs:
|
|
3500
|
+
config: RunnableConfig | None = None,
|
|
3501
|
+
**kwargs: Any | None,
|
|
3573
3502
|
) -> Iterator[Output]:
|
|
3574
3503
|
yield from self.transform(iter([input]), config, **kwargs)
|
|
3575
3504
|
|
|
@@ -3577,8 +3506,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3577
3506
|
async def atransform(
|
|
3578
3507
|
self,
|
|
3579
3508
|
input: AsyncIterator[Input],
|
|
3580
|
-
config:
|
|
3581
|
-
**kwargs:
|
|
3509
|
+
config: RunnableConfig | None = None,
|
|
3510
|
+
**kwargs: Any | None,
|
|
3582
3511
|
) -> AsyncIterator[Output]:
|
|
3583
3512
|
async for chunk in self._atransform_stream_with_config(
|
|
3584
3513
|
input,
|
|
@@ -3592,8 +3521,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3592
3521
|
async def astream(
|
|
3593
3522
|
self,
|
|
3594
3523
|
input: Input,
|
|
3595
|
-
config:
|
|
3596
|
-
**kwargs:
|
|
3524
|
+
config: RunnableConfig | None = None,
|
|
3525
|
+
**kwargs: Any | None,
|
|
3597
3526
|
) -> AsyncIterator[Output]:
|
|
3598
3527
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
3599
3528
|
yield input
|
|
@@ -3617,95 +3546,89 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3617
3546
|
Here is a simple example that uses functions to illustrate the use of
|
|
3618
3547
|
``RunnableParallel``:
|
|
3619
3548
|
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
from langchain_core.runnables import RunnableLambda
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
def add_one(x: int) -> int:
|
|
3626
|
-
return x + 1
|
|
3549
|
+
```python
|
|
3550
|
+
from langchain_core.runnables import RunnableLambda
|
|
3627
3551
|
|
|
3628
3552
|
|
|
3629
|
-
|
|
3630
|
-
|
|
3553
|
+
def add_one(x: int) -> int:
|
|
3554
|
+
return x + 1
|
|
3631
3555
|
|
|
3632
3556
|
|
|
3633
|
-
|
|
3634
|
-
|
|
3557
|
+
def mul_two(x: int) -> int:
|
|
3558
|
+
return x * 2
|
|
3635
3559
|
|
|
3636
3560
|
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
runnable_3 = RunnableLambda(mul_three)
|
|
3561
|
+
def mul_three(x: int) -> int:
|
|
3562
|
+
return x * 3
|
|
3640
3563
|
|
|
3641
|
-
sequence = runnable_1 | { # this dict is coerced to a RunnableParallel
|
|
3642
|
-
"mul_two": runnable_2,
|
|
3643
|
-
"mul_three": runnable_3,
|
|
3644
|
-
}
|
|
3645
|
-
# Or equivalently:
|
|
3646
|
-
# sequence = runnable_1 | RunnableParallel(
|
|
3647
|
-
# {"mul_two": runnable_2, "mul_three": runnable_3}
|
|
3648
|
-
# )
|
|
3649
|
-
# Also equivalently:
|
|
3650
|
-
# sequence = runnable_1 | RunnableParallel(
|
|
3651
|
-
# mul_two=runnable_2,
|
|
3652
|
-
# mul_three=runnable_3,
|
|
3653
|
-
# )
|
|
3654
3564
|
|
|
3655
|
-
|
|
3656
|
-
|
|
3565
|
+
runnable_1 = RunnableLambda(add_one)
|
|
3566
|
+
runnable_2 = RunnableLambda(mul_two)
|
|
3567
|
+
runnable_3 = RunnableLambda(mul_three)
|
|
3657
3568
|
|
|
3658
|
-
|
|
3659
|
-
|
|
3569
|
+
sequence = runnable_1 | { # this dict is coerced to a RunnableParallel
|
|
3570
|
+
"mul_two": runnable_2,
|
|
3571
|
+
"mul_three": runnable_3,
|
|
3572
|
+
}
|
|
3573
|
+
# Or equivalently:
|
|
3574
|
+
# sequence = runnable_1 | RunnableParallel(
|
|
3575
|
+
# {"mul_two": runnable_2, "mul_three": runnable_3}
|
|
3576
|
+
# )
|
|
3577
|
+
# Also equivalently:
|
|
3578
|
+
# sequence = runnable_1 | RunnableParallel(
|
|
3579
|
+
# mul_two=runnable_2,
|
|
3580
|
+
# mul_three=runnable_3,
|
|
3581
|
+
# )
|
|
3582
|
+
|
|
3583
|
+
sequence.invoke(1)
|
|
3584
|
+
await sequence.ainvoke(1)
|
|
3585
|
+
|
|
3586
|
+
sequence.batch([1, 2, 3])
|
|
3587
|
+
await sequence.abatch([1, 2, 3])
|
|
3588
|
+
```
|
|
3660
3589
|
|
|
3661
3590
|
``RunnableParallel`` makes it easy to run ``Runnable``s in parallel. In the below
|
|
3662
3591
|
example, we simultaneously stream output from two different ``Runnables``:
|
|
3663
3592
|
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
from langchain_openai import ChatOpenAI
|
|
3593
|
+
```python
|
|
3594
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
3595
|
+
from langchain_core.runnables import RunnableParallel
|
|
3596
|
+
from langchain_openai import ChatOpenAI
|
|
3669
3597
|
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
runnable = RunnableParallel(joke=joke_chain, poem=poem_chain)
|
|
3598
|
+
model = ChatOpenAI()
|
|
3599
|
+
joke_chain = (
|
|
3600
|
+
ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
|
|
3601
|
+
)
|
|
3602
|
+
poem_chain = (
|
|
3603
|
+
ChatPromptTemplate.from_template("write a 2-line poem about {topic}")
|
|
3604
|
+
| model
|
|
3605
|
+
)
|
|
3680
3606
|
|
|
3681
|
-
|
|
3682
|
-
output = {key: "" for key, _ in runnable.output_schema()}
|
|
3683
|
-
for chunk in runnable.stream({"topic": "bear"}):
|
|
3684
|
-
for key in chunk:
|
|
3685
|
-
output[key] = output[key] + chunk[key].content
|
|
3686
|
-
print(output) # noqa: T201
|
|
3607
|
+
runnable = RunnableParallel(joke=joke_chain, poem=poem_chain)
|
|
3687
3608
|
|
|
3609
|
+
# Display stream
|
|
3610
|
+
output = {key: "" for key, _ in runnable.output_schema()}
|
|
3611
|
+
for chunk in runnable.stream({"topic": "bear"}):
|
|
3612
|
+
for key in chunk:
|
|
3613
|
+
output[key] = output[key] + chunk[key].content
|
|
3614
|
+
print(output) # noqa: T201
|
|
3615
|
+
```
|
|
3688
3616
|
"""
|
|
3689
3617
|
|
|
3690
3618
|
steps__: Mapping[str, Runnable[Input, Any]]
|
|
3691
3619
|
|
|
3692
3620
|
def __init__(
|
|
3693
3621
|
self,
|
|
3694
|
-
steps__:
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
]
|
|
3704
|
-
**kwargs: Union[
|
|
3705
|
-
Runnable[Input, Any],
|
|
3706
|
-
Callable[[Input], Any],
|
|
3707
|
-
Mapping[str, Union[Runnable[Input, Any], Callable[[Input], Any]]],
|
|
3708
|
-
],
|
|
3622
|
+
steps__: Mapping[
|
|
3623
|
+
str,
|
|
3624
|
+
Runnable[Input, Any]
|
|
3625
|
+
| Callable[[Input], Any]
|
|
3626
|
+
| Mapping[str, Runnable[Input, Any] | Callable[[Input], Any]],
|
|
3627
|
+
]
|
|
3628
|
+
| None = None,
|
|
3629
|
+
**kwargs: Runnable[Input, Any]
|
|
3630
|
+
| Callable[[Input], Any]
|
|
3631
|
+
| Mapping[str, Runnable[Input, Any] | Callable[[Input], Any]],
|
|
3709
3632
|
) -> None:
|
|
3710
3633
|
"""Create a ``RunnableParallel``.
|
|
3711
3634
|
|
|
@@ -3741,9 +3664,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3741
3664
|
)
|
|
3742
3665
|
|
|
3743
3666
|
@override
|
|
3744
|
-
def get_name(
|
|
3745
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
3746
|
-
) -> str:
|
|
3667
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
3747
3668
|
"""Get the name of the ``Runnable``.
|
|
3748
3669
|
|
|
3749
3670
|
Args:
|
|
@@ -3768,9 +3689,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3768
3689
|
return Any
|
|
3769
3690
|
|
|
3770
3691
|
@override
|
|
3771
|
-
def get_input_schema(
|
|
3772
|
-
self, config: Optional[RunnableConfig] = None
|
|
3773
|
-
) -> type[BaseModel]:
|
|
3692
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
3774
3693
|
"""Get the input schema of the ``Runnable``.
|
|
3775
3694
|
|
|
3776
3695
|
Args:
|
|
@@ -3800,7 +3719,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3800
3719
|
|
|
3801
3720
|
@override
|
|
3802
3721
|
def get_output_schema(
|
|
3803
|
-
self, config:
|
|
3722
|
+
self, config: RunnableConfig | None = None
|
|
3804
3723
|
) -> type[BaseModel]:
|
|
3805
3724
|
"""Get the output schema of the ``Runnable``.
|
|
3806
3725
|
|
|
@@ -3828,7 +3747,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3828
3747
|
)
|
|
3829
3748
|
|
|
3830
3749
|
@override
|
|
3831
|
-
def get_graph(self, config:
|
|
3750
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
3832
3751
|
"""Get the graph representation of the ``Runnable``.
|
|
3833
3752
|
|
|
3834
3753
|
Args:
|
|
@@ -3876,7 +3795,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3876
3795
|
|
|
3877
3796
|
@override
|
|
3878
3797
|
def invoke(
|
|
3879
|
-
self, input: Input, config:
|
|
3798
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
3880
3799
|
) -> dict[str, Any]:
|
|
3881
3800
|
# setup callbacks
|
|
3882
3801
|
config = ensure_config(config)
|
|
@@ -3922,7 +3841,10 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3922
3841
|
executor.submit(_invoke_step, step, input, config, key)
|
|
3923
3842
|
for key, step in steps.items()
|
|
3924
3843
|
]
|
|
3925
|
-
output = {
|
|
3844
|
+
output = {
|
|
3845
|
+
key: future.result()
|
|
3846
|
+
for key, future in zip(steps, futures, strict=False)
|
|
3847
|
+
}
|
|
3926
3848
|
# finish the root run
|
|
3927
3849
|
except BaseException as e:
|
|
3928
3850
|
run_manager.on_chain_error(e)
|
|
@@ -3935,8 +3857,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3935
3857
|
async def ainvoke(
|
|
3936
3858
|
self,
|
|
3937
3859
|
input: Input,
|
|
3938
|
-
config:
|
|
3939
|
-
**kwargs:
|
|
3860
|
+
config: RunnableConfig | None = None,
|
|
3861
|
+
**kwargs: Any | None,
|
|
3940
3862
|
) -> dict[str, Any]:
|
|
3941
3863
|
# setup callbacks
|
|
3942
3864
|
config = ensure_config(config)
|
|
@@ -3977,7 +3899,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3977
3899
|
for key, step in steps.items()
|
|
3978
3900
|
)
|
|
3979
3901
|
)
|
|
3980
|
-
output = dict(zip(steps, results))
|
|
3902
|
+
output = dict(zip(steps, results, strict=False))
|
|
3981
3903
|
# finish the root run
|
|
3982
3904
|
except BaseException as e:
|
|
3983
3905
|
await run_manager.on_chain_error(e)
|
|
@@ -4037,7 +3959,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4037
3959
|
def transform(
|
|
4038
3960
|
self,
|
|
4039
3961
|
input: Iterator[Input],
|
|
4040
|
-
config:
|
|
3962
|
+
config: RunnableConfig | None = None,
|
|
4041
3963
|
**kwargs: Any,
|
|
4042
3964
|
) -> Iterator[dict[str, Any]]:
|
|
4043
3965
|
yield from self._transform_stream_with_config(
|
|
@@ -4048,8 +3970,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4048
3970
|
def stream(
|
|
4049
3971
|
self,
|
|
4050
3972
|
input: Input,
|
|
4051
|
-
config:
|
|
4052
|
-
**kwargs:
|
|
3973
|
+
config: RunnableConfig | None = None,
|
|
3974
|
+
**kwargs: Any | None,
|
|
4053
3975
|
) -> Iterator[dict[str, Any]]:
|
|
4054
3976
|
yield from self.transform(iter([input]), config)
|
|
4055
3977
|
|
|
@@ -4079,7 +4001,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4079
4001
|
]
|
|
4080
4002
|
|
|
4081
4003
|
# Wrap in a coroutine to satisfy linter
|
|
4082
|
-
async def get_next_chunk(generator: AsyncIterator) ->
|
|
4004
|
+
async def get_next_chunk(generator: AsyncIterator) -> Output | None:
|
|
4083
4005
|
return await py_anext(generator)
|
|
4084
4006
|
|
|
4085
4007
|
# Start the first iteration of each generator
|
|
@@ -4108,7 +4030,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4108
4030
|
async def atransform(
|
|
4109
4031
|
self,
|
|
4110
4032
|
input: AsyncIterator[Input],
|
|
4111
|
-
config:
|
|
4033
|
+
config: RunnableConfig | None = None,
|
|
4112
4034
|
**kwargs: Any,
|
|
4113
4035
|
) -> AsyncIterator[dict[str, Any]]:
|
|
4114
4036
|
async for chunk in self._atransform_stream_with_config(
|
|
@@ -4120,8 +4042,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4120
4042
|
async def astream(
|
|
4121
4043
|
self,
|
|
4122
4044
|
input: Input,
|
|
4123
|
-
config:
|
|
4124
|
-
**kwargs:
|
|
4045
|
+
config: RunnableConfig | None = None,
|
|
4046
|
+
**kwargs: Any | None,
|
|
4125
4047
|
) -> AsyncIterator[dict[str, Any]]:
|
|
4126
4048
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
4127
4049
|
yield input
|
|
@@ -4146,7 +4068,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4146
4068
|
``RunnableGenerator`` allows it to emit output chunks as soon as they are streamed
|
|
4147
4069
|
in from the previous step.
|
|
4148
4070
|
|
|
4149
|
-
|
|
4071
|
+
!!! note
|
|
4150
4072
|
If a generator function has a ``signature A -> Iterator[B]``, such that it
|
|
4151
4073
|
requires its input from the previous step to be completed before emitting chunks
|
|
4152
4074
|
(e.g., most LLMs need the entire prompt available to start generating), it can
|
|
@@ -4154,92 +4076,86 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4154
4076
|
|
|
4155
4077
|
Here is an example to show the basic mechanics of a ``RunnableGenerator``:
|
|
4156
4078
|
|
|
4157
|
-
|
|
4079
|
+
```python
|
|
4080
|
+
from typing import Any, AsyncIterator, Iterator
|
|
4158
4081
|
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
from langchain_core.runnables import RunnableGenerator
|
|
4082
|
+
from langchain_core.runnables import RunnableGenerator
|
|
4162
4083
|
|
|
4163
4084
|
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4085
|
+
def gen(input: Iterator[Any]) -> Iterator[str]:
|
|
4086
|
+
for token in ["Have", " a", " nice", " day"]:
|
|
4087
|
+
yield token
|
|
4167
4088
|
|
|
4168
4089
|
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4090
|
+
runnable = RunnableGenerator(gen)
|
|
4091
|
+
runnable.invoke(None) # "Have a nice day"
|
|
4092
|
+
list(runnable.stream(None)) # ["Have", " a", " nice", " day"]
|
|
4093
|
+
runnable.batch([None, None]) # ["Have a nice day", "Have a nice day"]
|
|
4173
4094
|
|
|
4174
4095
|
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4096
|
+
# Async version:
|
|
4097
|
+
async def agen(input: AsyncIterator[Any]) -> AsyncIterator[str]:
|
|
4098
|
+
for token in ["Have", " a", " nice", " day"]:
|
|
4099
|
+
yield token
|
|
4179
4100
|
|
|
4180
4101
|
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4102
|
+
runnable = RunnableGenerator(agen)
|
|
4103
|
+
await runnable.ainvoke(None) # "Have a nice day"
|
|
4104
|
+
[p async for p in runnable.astream(None)] # ["Have", " a", " nice", " day"]
|
|
4105
|
+
```
|
|
4184
4106
|
|
|
4185
4107
|
``RunnableGenerator`` makes it easy to implement custom behavior within a streaming
|
|
4186
4108
|
context. Below we show an example:
|
|
4187
4109
|
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
from langchain_core.output_parsers import StrOutputParser
|
|
4110
|
+
```python
|
|
4111
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
4112
|
+
from langchain_core.runnables import RunnableGenerator, RunnableLambda
|
|
4113
|
+
from langchain_openai import ChatOpenAI
|
|
4114
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
4194
4115
|
|
|
4195
4116
|
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4117
|
+
model = ChatOpenAI()
|
|
4118
|
+
chant_chain = (
|
|
4119
|
+
ChatPromptTemplate.from_template("Give me a 3 word chant about {topic}")
|
|
4120
|
+
| model
|
|
4121
|
+
| StrOutputParser()
|
|
4122
|
+
)
|
|
4202
4123
|
|
|
4203
4124
|
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4125
|
+
def character_generator(input: Iterator[str]) -> Iterator[str]:
|
|
4126
|
+
for token in input:
|
|
4127
|
+
if "," in token or "." in token:
|
|
4128
|
+
yield "👏" + token
|
|
4129
|
+
else:
|
|
4130
|
+
yield token
|
|
4211
4131
|
|
|
4212
|
-
runnable = chant_chain | character_generator
|
|
4213
|
-
assert type(runnable.last) is RunnableGenerator
|
|
4214
|
-
"".join(
|
|
4215
|
-
runnable.stream({"topic": "waste"})
|
|
4216
|
-
) # Reduce👏, Reuse👏, Recycle👏.
|
|
4217
4132
|
|
|
4133
|
+
runnable = chant_chain | character_generator
|
|
4134
|
+
assert type(runnable.last) is RunnableGenerator
|
|
4135
|
+
"".join(runnable.stream({"topic": "waste"})) # Reduce👏, Reuse👏, Recycle👏.
|
|
4218
4136
|
|
|
4219
|
-
# Note that RunnableLambda can be used to delay streaming of one step in a
|
|
4220
|
-
# sequence until the previous step is finished:
|
|
4221
|
-
def reverse_generator(input: str) -> Iterator[str]:
|
|
4222
|
-
# Yield characters of input in reverse order.
|
|
4223
|
-
for character in input[::-1]:
|
|
4224
|
-
yield character
|
|
4225
4137
|
|
|
4138
|
+
# Note that RunnableLambda can be used to delay streaming of one step in a
|
|
4139
|
+
# sequence until the previous step is finished:
|
|
4140
|
+
def reverse_generator(input: str) -> Iterator[str]:
|
|
4141
|
+
# Yield characters of input in reverse order.
|
|
4142
|
+
for character in input[::-1]:
|
|
4143
|
+
yield character
|
|
4226
4144
|
|
|
4227
|
-
runnable = chant_chain | RunnableLambda(reverse_generator)
|
|
4228
|
-
"".join(runnable.stream({"topic": "waste"})) # ".elcycer ,esuer ,ecudeR"
|
|
4229
4145
|
|
|
4146
|
+
runnable = chant_chain | RunnableLambda(reverse_generator)
|
|
4147
|
+
"".join(runnable.stream({"topic": "waste"})) # ".elcycer ,esuer ,ecudeR"
|
|
4148
|
+
```
|
|
4230
4149
|
"""
|
|
4231
4150
|
|
|
4232
4151
|
def __init__(
|
|
4233
4152
|
self,
|
|
4234
|
-
transform:
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
atransform: Optional[
|
|
4239
|
-
Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
4240
|
-
] = None,
|
|
4153
|
+
transform: Callable[[Iterator[Input]], Iterator[Output]]
|
|
4154
|
+
| Callable[[AsyncIterator[Input]], AsyncIterator[Output]],
|
|
4155
|
+
atransform: Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
4156
|
+
| None = None,
|
|
4241
4157
|
*,
|
|
4242
|
-
name:
|
|
4158
|
+
name: str | None = None,
|
|
4243
4159
|
) -> None:
|
|
4244
4160
|
"""Initialize a ``RunnableGenerator``.
|
|
4245
4161
|
|
|
@@ -4288,9 +4204,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4288
4204
|
return Any
|
|
4289
4205
|
|
|
4290
4206
|
@override
|
|
4291
|
-
def get_input_schema(
|
|
4292
|
-
self, config: Optional[RunnableConfig] = None
|
|
4293
|
-
) -> type[BaseModel]:
|
|
4207
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
4294
4208
|
# Override the default implementation.
|
|
4295
4209
|
# For a runnable generator, we need to bring to provide the
|
|
4296
4210
|
# module of the underlying function when creating the model.
|
|
@@ -4331,7 +4245,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4331
4245
|
|
|
4332
4246
|
@override
|
|
4333
4247
|
def get_output_schema(
|
|
4334
|
-
self, config:
|
|
4248
|
+
self, config: RunnableConfig | None = None
|
|
4335
4249
|
) -> type[BaseModel]:
|
|
4336
4250
|
# Override the default implementation.
|
|
4337
4251
|
# For a runnable generator, we need to bring to provide the
|
|
@@ -4376,7 +4290,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4376
4290
|
def transform(
|
|
4377
4291
|
self,
|
|
4378
4292
|
input: Iterator[Input],
|
|
4379
|
-
config:
|
|
4293
|
+
config: RunnableConfig | None = None,
|
|
4380
4294
|
**kwargs: Any,
|
|
4381
4295
|
) -> Iterator[Output]:
|
|
4382
4296
|
if not hasattr(self, "_transform"):
|
|
@@ -4393,16 +4307,16 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4393
4307
|
def stream(
|
|
4394
4308
|
self,
|
|
4395
4309
|
input: Input,
|
|
4396
|
-
config:
|
|
4310
|
+
config: RunnableConfig | None = None,
|
|
4397
4311
|
**kwargs: Any,
|
|
4398
4312
|
) -> Iterator[Output]:
|
|
4399
4313
|
return self.transform(iter([input]), config, **kwargs)
|
|
4400
4314
|
|
|
4401
4315
|
@override
|
|
4402
4316
|
def invoke(
|
|
4403
|
-
self, input: Input, config:
|
|
4317
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
4404
4318
|
) -> Output:
|
|
4405
|
-
final:
|
|
4319
|
+
final: Output | None = None
|
|
4406
4320
|
for output in self.stream(input, config, **kwargs):
|
|
4407
4321
|
final = output if final is None else final + output # type: ignore[operator]
|
|
4408
4322
|
return cast("Output", final)
|
|
@@ -4411,7 +4325,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4411
4325
|
def atransform(
|
|
4412
4326
|
self,
|
|
4413
4327
|
input: AsyncIterator[Input],
|
|
4414
|
-
config:
|
|
4328
|
+
config: RunnableConfig | None = None,
|
|
4415
4329
|
**kwargs: Any,
|
|
4416
4330
|
) -> AsyncIterator[Output]:
|
|
4417
4331
|
if not hasattr(self, "_atransform"):
|
|
@@ -4426,7 +4340,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4426
4340
|
def astream(
|
|
4427
4341
|
self,
|
|
4428
4342
|
input: Input,
|
|
4429
|
-
config:
|
|
4343
|
+
config: RunnableConfig | None = None,
|
|
4430
4344
|
**kwargs: Any,
|
|
4431
4345
|
) -> AsyncIterator[Output]:
|
|
4432
4346
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
@@ -4436,9 +4350,9 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4436
4350
|
|
|
4437
4351
|
@override
|
|
4438
4352
|
async def ainvoke(
|
|
4439
|
-
self, input: Input, config:
|
|
4353
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
4440
4354
|
) -> Output:
|
|
4441
|
-
final:
|
|
4355
|
+
final: Output | None = None
|
|
4442
4356
|
async for output in self.astream(input, config, **kwargs):
|
|
4443
4357
|
final = output if final is None else final + output # type: ignore[operator]
|
|
4444
4358
|
return cast("Output", final)
|
|
@@ -4462,73 +4376,60 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4462
4376
|
instance is invoked (or streamed) during execution.
|
|
4463
4377
|
|
|
4464
4378
|
Examples:
|
|
4379
|
+
```python
|
|
4380
|
+
# This is a RunnableLambda
|
|
4381
|
+
from langchain_core.runnables import RunnableLambda
|
|
4465
4382
|
|
|
4466
|
-
.. code-block:: python
|
|
4467
|
-
|
|
4468
|
-
# This is a RunnableLambda
|
|
4469
|
-
from langchain_core.runnables import RunnableLambda
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
def add_one(x: int) -> int:
|
|
4473
|
-
return x + 1
|
|
4474
4383
|
|
|
4384
|
+
def add_one(x: int) -> int:
|
|
4385
|
+
return x + 1
|
|
4475
4386
|
|
|
4476
|
-
runnable = RunnableLambda(add_one)
|
|
4477
4387
|
|
|
4478
|
-
|
|
4479
|
-
runnable.batch([1, 2, 3]) # returns [2, 3, 4]
|
|
4388
|
+
runnable = RunnableLambda(add_one)
|
|
4480
4389
|
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
await runnable.abatch([1, 2, 3]) # returns [2, 3, 4]
|
|
4390
|
+
runnable.invoke(1) # returns 2
|
|
4391
|
+
runnable.batch([1, 2, 3]) # returns [2, 3, 4]
|
|
4484
4392
|
|
|
4393
|
+
# Async is supported by default by delegating to the sync implementation
|
|
4394
|
+
await runnable.ainvoke(1) # returns 2
|
|
4395
|
+
await runnable.abatch([1, 2, 3]) # returns [2, 3, 4]
|
|
4485
4396
|
|
|
4486
|
-
# Alternatively, can provide both synd and sync implementations
|
|
4487
|
-
async def add_one_async(x: int) -> int:
|
|
4488
|
-
return x + 1
|
|
4489
4397
|
|
|
4398
|
+
# Alternatively, can provide both synd and sync implementations
|
|
4399
|
+
async def add_one_async(x: int) -> int:
|
|
4400
|
+
return x + 1
|
|
4490
4401
|
|
|
4491
|
-
runnable = RunnableLambda(add_one, afunc=add_one_async)
|
|
4492
|
-
runnable.invoke(1) # Uses add_one
|
|
4493
|
-
await runnable.ainvoke(1) # Uses add_one_async
|
|
4494
4402
|
|
|
4403
|
+
runnable = RunnableLambda(add_one, afunc=add_one_async)
|
|
4404
|
+
runnable.invoke(1) # Uses add_one
|
|
4405
|
+
await runnable.ainvoke(1) # Uses add_one_async
|
|
4406
|
+
```
|
|
4495
4407
|
"""
|
|
4496
4408
|
|
|
4497
4409
|
def __init__(
|
|
4498
4410
|
self,
|
|
4499
|
-
func:
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
Callable[[Input, RunnableConfig], Awaitable[Output]],
|
|
4512
|
-
Callable[[Input, AsyncCallbackManagerForChainRun], Awaitable[Output]],
|
|
4513
|
-
Callable[
|
|
4514
|
-
[Input, AsyncCallbackManagerForChainRun, RunnableConfig],
|
|
4515
|
-
Awaitable[Output],
|
|
4516
|
-
],
|
|
4517
|
-
],
|
|
4411
|
+
func: Callable[[Input], Iterator[Output]]
|
|
4412
|
+
| Callable[[Input], Runnable[Input, Output]]
|
|
4413
|
+
| Callable[[Input], Output]
|
|
4414
|
+
| Callable[[Input, RunnableConfig], Output]
|
|
4415
|
+
| Callable[[Input, CallbackManagerForChainRun], Output]
|
|
4416
|
+
| Callable[[Input, CallbackManagerForChainRun, RunnableConfig], Output]
|
|
4417
|
+
| Callable[[Input], Awaitable[Output]]
|
|
4418
|
+
| Callable[[Input], AsyncIterator[Output]]
|
|
4419
|
+
| Callable[[Input, RunnableConfig], Awaitable[Output]]
|
|
4420
|
+
| Callable[[Input, AsyncCallbackManagerForChainRun], Awaitable[Output]]
|
|
4421
|
+
| Callable[
|
|
4422
|
+
[Input, AsyncCallbackManagerForChainRun, RunnableConfig], Awaitable[Output]
|
|
4518
4423
|
],
|
|
4519
|
-
afunc:
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
],
|
|
4529
|
-
]
|
|
4530
|
-
] = None,
|
|
4531
|
-
name: Optional[str] = None,
|
|
4424
|
+
afunc: Callable[[Input], Awaitable[Output]]
|
|
4425
|
+
| Callable[[Input], AsyncIterator[Output]]
|
|
4426
|
+
| Callable[[Input, RunnableConfig], Awaitable[Output]]
|
|
4427
|
+
| Callable[[Input, AsyncCallbackManagerForChainRun], Awaitable[Output]]
|
|
4428
|
+
| Callable[
|
|
4429
|
+
[Input, AsyncCallbackManagerForChainRun, RunnableConfig], Awaitable[Output]
|
|
4430
|
+
]
|
|
4431
|
+
| None = None,
|
|
4432
|
+
name: str | None = None,
|
|
4532
4433
|
) -> None:
|
|
4533
4434
|
"""Create a ``RunnableLambda`` from a callable, and async callable or both.
|
|
4534
4435
|
|
|
@@ -4578,7 +4479,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4578
4479
|
except AttributeError:
|
|
4579
4480
|
pass
|
|
4580
4481
|
|
|
4581
|
-
self._repr:
|
|
4482
|
+
self._repr: str | None = None
|
|
4582
4483
|
|
|
4583
4484
|
@property
|
|
4584
4485
|
@override
|
|
@@ -4595,9 +4496,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4595
4496
|
return Any
|
|
4596
4497
|
|
|
4597
4498
|
@override
|
|
4598
|
-
def get_input_schema(
|
|
4599
|
-
self, config: Optional[RunnableConfig] = None
|
|
4600
|
-
) -> type[BaseModel]:
|
|
4499
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
4601
4500
|
"""The pydantic schema for the input to this ``Runnable``.
|
|
4602
4501
|
|
|
4603
4502
|
Args:
|
|
@@ -4666,7 +4565,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4666
4565
|
|
|
4667
4566
|
@override
|
|
4668
4567
|
def get_output_schema(
|
|
4669
|
-
self, config:
|
|
4568
|
+
self, config: RunnableConfig | None = None
|
|
4670
4569
|
) -> type[BaseModel]:
|
|
4671
4570
|
# Override the default implementation.
|
|
4672
4571
|
# For a runnable lambda, we need to bring to provide the
|
|
@@ -4787,7 +4686,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4787
4686
|
**kwargs: Any,
|
|
4788
4687
|
) -> Output:
|
|
4789
4688
|
if inspect.isgeneratorfunction(self.func):
|
|
4790
|
-
output:
|
|
4689
|
+
output: Output | None = None
|
|
4791
4690
|
for chunk in call_func_with_variable_args(
|
|
4792
4691
|
cast("Callable[[Input], Iterator[Output]]", self.func),
|
|
4793
4692
|
input_,
|
|
@@ -4842,7 +4741,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4842
4741
|
config: RunnableConfig,
|
|
4843
4742
|
**kwargs: Any,
|
|
4844
4743
|
) -> Output:
|
|
4845
|
-
output:
|
|
4744
|
+
output: Output | None = None
|
|
4846
4745
|
for chunk in call_func_with_variable_args(
|
|
4847
4746
|
cast("Callable[[Input], Iterator[Output]]", self.func),
|
|
4848
4747
|
value,
|
|
@@ -4878,7 +4777,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4878
4777
|
afunc = f
|
|
4879
4778
|
|
|
4880
4779
|
if is_async_generator(afunc):
|
|
4881
|
-
output:
|
|
4780
|
+
output: Output | None = None
|
|
4882
4781
|
async with aclosing(
|
|
4883
4782
|
cast(
|
|
4884
4783
|
"AsyncGenerator[Any, Any]",
|
|
@@ -4928,8 +4827,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4928
4827
|
def invoke(
|
|
4929
4828
|
self,
|
|
4930
4829
|
input: Input,
|
|
4931
|
-
config:
|
|
4932
|
-
**kwargs:
|
|
4830
|
+
config: RunnableConfig | None = None,
|
|
4831
|
+
**kwargs: Any | None,
|
|
4933
4832
|
) -> Output:
|
|
4934
4833
|
"""Invoke this ``Runnable`` synchronously.
|
|
4935
4834
|
|
|
@@ -4959,8 +4858,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4959
4858
|
async def ainvoke(
|
|
4960
4859
|
self,
|
|
4961
4860
|
input: Input,
|
|
4962
|
-
config:
|
|
4963
|
-
**kwargs:
|
|
4861
|
+
config: RunnableConfig | None = None,
|
|
4862
|
+
**kwargs: Any | None,
|
|
4964
4863
|
) -> Output:
|
|
4965
4864
|
"""Invoke this ``Runnable`` asynchronously.
|
|
4966
4865
|
|
|
@@ -5004,7 +4903,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5004
4903
|
final = ichunk
|
|
5005
4904
|
|
|
5006
4905
|
if inspect.isgeneratorfunction(self.func):
|
|
5007
|
-
output:
|
|
4906
|
+
output: Output | None = None
|
|
5008
4907
|
for chunk in call_func_with_variable_args(
|
|
5009
4908
|
self.func, final, config, run_manager, **kwargs
|
|
5010
4909
|
):
|
|
@@ -5046,8 +4945,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5046
4945
|
def transform(
|
|
5047
4946
|
self,
|
|
5048
4947
|
input: Iterator[Input],
|
|
5049
|
-
config:
|
|
5050
|
-
**kwargs:
|
|
4948
|
+
config: RunnableConfig | None = None,
|
|
4949
|
+
**kwargs: Any | None,
|
|
5051
4950
|
) -> Iterator[Output]:
|
|
5052
4951
|
if hasattr(self, "func"):
|
|
5053
4952
|
yield from self._transform_stream_with_config(
|
|
@@ -5067,8 +4966,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5067
4966
|
def stream(
|
|
5068
4967
|
self,
|
|
5069
4968
|
input: Input,
|
|
5070
|
-
config:
|
|
5071
|
-
**kwargs:
|
|
4969
|
+
config: RunnableConfig | None = None,
|
|
4970
|
+
**kwargs: Any | None,
|
|
5072
4971
|
) -> Iterator[Output]:
|
|
5073
4972
|
return self.transform(iter([input]), config, **kwargs)
|
|
5074
4973
|
|
|
@@ -5122,7 +5021,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5122
5021
|
afunc = f
|
|
5123
5022
|
|
|
5124
5023
|
if is_async_generator(afunc):
|
|
5125
|
-
output:
|
|
5024
|
+
output: Output | None = None
|
|
5126
5025
|
async for chunk in cast(
|
|
5127
5026
|
"AsyncIterator[Output]",
|
|
5128
5027
|
acall_func_with_variable_args(
|
|
@@ -5175,8 +5074,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5175
5074
|
async def atransform(
|
|
5176
5075
|
self,
|
|
5177
5076
|
input: AsyncIterator[Input],
|
|
5178
|
-
config:
|
|
5179
|
-
**kwargs:
|
|
5077
|
+
config: RunnableConfig | None = None,
|
|
5078
|
+
**kwargs: Any | None,
|
|
5180
5079
|
) -> AsyncIterator[Output]:
|
|
5181
5080
|
async for output in self._atransform_stream_with_config(
|
|
5182
5081
|
input,
|
|
@@ -5190,8 +5089,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5190
5089
|
async def astream(
|
|
5191
5090
|
self,
|
|
5192
5091
|
input: Input,
|
|
5193
|
-
config:
|
|
5194
|
-
**kwargs:
|
|
5092
|
+
config: RunnableConfig | None = None,
|
|
5093
|
+
**kwargs: Any | None,
|
|
5195
5094
|
) -> AsyncIterator[Output]:
|
|
5196
5095
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
5197
5096
|
yield input
|
|
@@ -5224,9 +5123,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5224
5123
|
return list[self.bound.InputType] # type: ignore[name-defined]
|
|
5225
5124
|
|
|
5226
5125
|
@override
|
|
5227
|
-
def get_input_schema(
|
|
5228
|
-
self, config: Optional[RunnableConfig] = None
|
|
5229
|
-
) -> type[BaseModel]:
|
|
5126
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
5230
5127
|
return create_model_v2(
|
|
5231
5128
|
self.get_name("Input"),
|
|
5232
5129
|
root=(
|
|
@@ -5250,7 +5147,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5250
5147
|
|
|
5251
5148
|
@override
|
|
5252
5149
|
def get_output_schema(
|
|
5253
|
-
self, config:
|
|
5150
|
+
self, config: RunnableConfig | None = None
|
|
5254
5151
|
) -> type[BaseModel]:
|
|
5255
5152
|
schema = self.bound.get_output_schema(config)
|
|
5256
5153
|
return create_model_v2(
|
|
@@ -5272,7 +5169,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5272
5169
|
return self.bound.config_specs
|
|
5273
5170
|
|
|
5274
5171
|
@override
|
|
5275
|
-
def get_graph(self, config:
|
|
5172
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
5276
5173
|
return self.bound.get_graph(config)
|
|
5277
5174
|
|
|
5278
5175
|
@classmethod
|
|
@@ -5305,7 +5202,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5305
5202
|
|
|
5306
5203
|
@override
|
|
5307
5204
|
def invoke(
|
|
5308
|
-
self, input: list[Input], config:
|
|
5205
|
+
self, input: list[Input], config: RunnableConfig | None = None, **kwargs: Any
|
|
5309
5206
|
) -> list[Output]:
|
|
5310
5207
|
return self._call_with_config(self._invoke, input, config, **kwargs)
|
|
5311
5208
|
|
|
@@ -5323,7 +5220,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5323
5220
|
|
|
5324
5221
|
@override
|
|
5325
5222
|
async def ainvoke(
|
|
5326
|
-
self, input: list[Input], config:
|
|
5223
|
+
self, input: list[Input], config: RunnableConfig | None = None, **kwargs: Any
|
|
5327
5224
|
) -> list[Output]:
|
|
5328
5225
|
return await self._acall_with_config(self._ainvoke, input, config, **kwargs)
|
|
5329
5226
|
|
|
@@ -5331,8 +5228,8 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5331
5228
|
async def astream_events(
|
|
5332
5229
|
self,
|
|
5333
5230
|
input: Input,
|
|
5334
|
-
config:
|
|
5335
|
-
**kwargs:
|
|
5231
|
+
config: RunnableConfig | None = None,
|
|
5232
|
+
**kwargs: Any | None,
|
|
5336
5233
|
) -> AsyncIterator[StreamEvent]:
|
|
5337
5234
|
def _error_stream_event(message: str) -> StreamEvent:
|
|
5338
5235
|
raise NotImplementedError(message)
|
|
@@ -5354,29 +5251,27 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5354
5251
|
In the below example, we associate and run three inputs
|
|
5355
5252
|
with a ``Runnable``:
|
|
5356
5253
|
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5254
|
+
```python
|
|
5255
|
+
from langchain_core.runnables.base import RunnableEach
|
|
5256
|
+
from langchain_openai import ChatOpenAI
|
|
5257
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
5258
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
5259
|
+
prompt = ChatPromptTemplate.from_template("Tell me a short joke about
|
|
5260
|
+
{topic}")
|
|
5261
|
+
model = ChatOpenAI()
|
|
5262
|
+
output_parser = StrOutputParser()
|
|
5263
|
+
runnable = prompt | model | output_parser
|
|
5264
|
+
runnable_each = RunnableEach(bound=runnable)
|
|
5265
|
+
output = runnable_each.invoke([{'topic':'Computer Science'},
|
|
5266
|
+
{'topic':'Art'},
|
|
5267
|
+
{'topic':'Biology'}])
|
|
5268
|
+
print(output) # noqa: T201
|
|
5269
|
+
|
|
5270
|
+
```
|
|
5374
5271
|
"""
|
|
5375
5272
|
|
|
5376
5273
|
@override
|
|
5377
|
-
def get_name(
|
|
5378
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
5379
|
-
) -> str:
|
|
5274
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
5380
5275
|
name = name or self.name or f"RunnableEach<{self.bound.get_name()}>"
|
|
5381
5276
|
return super().get_name(suffix, name=name)
|
|
5382
5277
|
|
|
@@ -5386,7 +5281,7 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5386
5281
|
|
|
5387
5282
|
@override
|
|
5388
5283
|
def with_config(
|
|
5389
|
-
self, config:
|
|
5284
|
+
self, config: RunnableConfig | None = None, **kwargs: Any
|
|
5390
5285
|
) -> RunnableEach[Input, Output]:
|
|
5391
5286
|
return RunnableEach(bound=self.bound.with_config(config, **kwargs))
|
|
5392
5287
|
|
|
@@ -5394,15 +5289,15 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5394
5289
|
def with_listeners(
|
|
5395
5290
|
self,
|
|
5396
5291
|
*,
|
|
5397
|
-
on_start:
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
on_end:
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
on_error:
|
|
5404
|
-
|
|
5405
|
-
|
|
5292
|
+
on_start: Callable[[Run], None]
|
|
5293
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5294
|
+
| None = None,
|
|
5295
|
+
on_end: Callable[[Run], None]
|
|
5296
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5297
|
+
| None = None,
|
|
5298
|
+
on_error: Callable[[Run], None]
|
|
5299
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5300
|
+
| None = None,
|
|
5406
5301
|
) -> RunnableEach[Input, Output]:
|
|
5407
5302
|
"""Bind lifecycle listeners to a ``Runnable``, returning a new ``Runnable``.
|
|
5408
5303
|
|
|
@@ -5431,9 +5326,9 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5431
5326
|
def with_alisteners(
|
|
5432
5327
|
self,
|
|
5433
5328
|
*,
|
|
5434
|
-
on_start:
|
|
5435
|
-
on_end:
|
|
5436
|
-
on_error:
|
|
5329
|
+
on_start: AsyncListener | None = None,
|
|
5330
|
+
on_end: AsyncListener | None = None,
|
|
5331
|
+
on_error: AsyncListener | None = None,
|
|
5437
5332
|
) -> RunnableEach[Input, Output]:
|
|
5438
5333
|
"""Bind async lifecycle listeners to a ``Runnable``.
|
|
5439
5334
|
|
|
@@ -5493,13 +5388,13 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5493
5388
|
"""The config factories to bind to the underlying ``Runnable``."""
|
|
5494
5389
|
|
|
5495
5390
|
# Union[Type[Input], BaseModel] + things like list[str]
|
|
5496
|
-
custom_input_type:
|
|
5391
|
+
custom_input_type: Any | None = None
|
|
5497
5392
|
"""Override the input type of the underlying ``Runnable`` with a custom type.
|
|
5498
5393
|
|
|
5499
5394
|
The type can be a pydantic model, or a type annotation (e.g., ``list[str]``).
|
|
5500
5395
|
"""
|
|
5501
5396
|
# Union[Type[Output], BaseModel] + things like list[str]
|
|
5502
|
-
custom_output_type:
|
|
5397
|
+
custom_output_type: Any | None = None
|
|
5503
5398
|
"""Override the output type of the underlying ``Runnable`` with a custom type.
|
|
5504
5399
|
|
|
5505
5400
|
The type can be a pydantic model, or a type annotation (e.g., ``list[str]``).
|
|
@@ -5513,13 +5408,12 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5513
5408
|
self,
|
|
5514
5409
|
*,
|
|
5515
5410
|
bound: Runnable[Input, Output],
|
|
5516
|
-
kwargs:
|
|
5517
|
-
config:
|
|
5518
|
-
config_factories:
|
|
5519
|
-
|
|
5520
|
-
] = None,
|
|
5521
|
-
|
|
5522
|
-
custom_output_type: Optional[Union[type[Output], BaseModel]] = None,
|
|
5411
|
+
kwargs: Mapping[str, Any] | None = None,
|
|
5412
|
+
config: RunnableConfig | None = None,
|
|
5413
|
+
config_factories: list[Callable[[RunnableConfig], RunnableConfig]]
|
|
5414
|
+
| None = None,
|
|
5415
|
+
custom_input_type: type[Input] | BaseModel | None = None,
|
|
5416
|
+
custom_output_type: type[Output] | BaseModel | None = None,
|
|
5523
5417
|
**other_kwargs: Any,
|
|
5524
5418
|
) -> None:
|
|
5525
5419
|
"""Create a ``RunnableBinding`` from a ``Runnable`` and kwargs.
|
|
@@ -5557,9 +5451,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5557
5451
|
self.config = config or {}
|
|
5558
5452
|
|
|
5559
5453
|
@override
|
|
5560
|
-
def get_name(
|
|
5561
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
5562
|
-
) -> str:
|
|
5454
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
5563
5455
|
return self.bound.get_name(suffix, name=name)
|
|
5564
5456
|
|
|
5565
5457
|
@property
|
|
@@ -5581,16 +5473,14 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5581
5473
|
)
|
|
5582
5474
|
|
|
5583
5475
|
@override
|
|
5584
|
-
def get_input_schema(
|
|
5585
|
-
self, config: Optional[RunnableConfig] = None
|
|
5586
|
-
) -> type[BaseModel]:
|
|
5476
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
5587
5477
|
if self.custom_input_type is not None:
|
|
5588
5478
|
return super().get_input_schema(config)
|
|
5589
5479
|
return self.bound.get_input_schema(merge_configs(self.config, config))
|
|
5590
5480
|
|
|
5591
5481
|
@override
|
|
5592
5482
|
def get_output_schema(
|
|
5593
|
-
self, config:
|
|
5483
|
+
self, config: RunnableConfig | None = None
|
|
5594
5484
|
) -> type[BaseModel]:
|
|
5595
5485
|
if self.custom_output_type is not None:
|
|
5596
5486
|
return super().get_output_schema(config)
|
|
@@ -5602,7 +5492,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5602
5492
|
return self.bound.config_specs
|
|
5603
5493
|
|
|
5604
5494
|
@override
|
|
5605
|
-
def get_graph(self, config:
|
|
5495
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
5606
5496
|
return self.bound.get_graph(self._merge_configs(config))
|
|
5607
5497
|
|
|
5608
5498
|
@classmethod
|
|
@@ -5621,7 +5511,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5621
5511
|
"""
|
|
5622
5512
|
return ["langchain", "schema", "runnable"]
|
|
5623
5513
|
|
|
5624
|
-
def _merge_configs(self, *configs:
|
|
5514
|
+
def _merge_configs(self, *configs: RunnableConfig | None) -> RunnableConfig:
|
|
5625
5515
|
config = merge_configs(self.config, *configs)
|
|
5626
5516
|
return merge_configs(config, *(f(config) for f in self.config_factories))
|
|
5627
5517
|
|
|
@@ -5629,8 +5519,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5629
5519
|
def invoke(
|
|
5630
5520
|
self,
|
|
5631
5521
|
input: Input,
|
|
5632
|
-
config:
|
|
5633
|
-
**kwargs:
|
|
5522
|
+
config: RunnableConfig | None = None,
|
|
5523
|
+
**kwargs: Any | None,
|
|
5634
5524
|
) -> Output:
|
|
5635
5525
|
return self.bound.invoke(
|
|
5636
5526
|
input,
|
|
@@ -5642,8 +5532,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5642
5532
|
async def ainvoke(
|
|
5643
5533
|
self,
|
|
5644
5534
|
input: Input,
|
|
5645
|
-
config:
|
|
5646
|
-
**kwargs:
|
|
5535
|
+
config: RunnableConfig | None = None,
|
|
5536
|
+
**kwargs: Any | None,
|
|
5647
5537
|
) -> Output:
|
|
5648
5538
|
return await self.bound.ainvoke(
|
|
5649
5539
|
input,
|
|
@@ -5655,10 +5545,10 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5655
5545
|
def batch(
|
|
5656
5546
|
self,
|
|
5657
5547
|
inputs: list[Input],
|
|
5658
|
-
config:
|
|
5548
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
5659
5549
|
*,
|
|
5660
5550
|
return_exceptions: bool = False,
|
|
5661
|
-
**kwargs:
|
|
5551
|
+
**kwargs: Any | None,
|
|
5662
5552
|
) -> list[Output]:
|
|
5663
5553
|
if isinstance(config, list):
|
|
5664
5554
|
configs = cast(
|
|
@@ -5678,10 +5568,10 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5678
5568
|
async def abatch(
|
|
5679
5569
|
self,
|
|
5680
5570
|
inputs: list[Input],
|
|
5681
|
-
config:
|
|
5571
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
5682
5572
|
*,
|
|
5683
5573
|
return_exceptions: bool = False,
|
|
5684
|
-
**kwargs:
|
|
5574
|
+
**kwargs: Any | None,
|
|
5685
5575
|
) -> list[Output]:
|
|
5686
5576
|
if isinstance(config, list):
|
|
5687
5577
|
configs = cast(
|
|
@@ -5701,7 +5591,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5701
5591
|
def batch_as_completed(
|
|
5702
5592
|
self,
|
|
5703
5593
|
inputs: Sequence[Input],
|
|
5704
|
-
config:
|
|
5594
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5705
5595
|
*,
|
|
5706
5596
|
return_exceptions: Literal[False] = False,
|
|
5707
5597
|
**kwargs: Any,
|
|
@@ -5711,21 +5601,21 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5711
5601
|
def batch_as_completed(
|
|
5712
5602
|
self,
|
|
5713
5603
|
inputs: Sequence[Input],
|
|
5714
|
-
config:
|
|
5604
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5715
5605
|
*,
|
|
5716
5606
|
return_exceptions: Literal[True],
|
|
5717
5607
|
**kwargs: Any,
|
|
5718
|
-
) -> Iterator[tuple[int,
|
|
5608
|
+
) -> Iterator[tuple[int, Output | Exception]]: ...
|
|
5719
5609
|
|
|
5720
5610
|
@override
|
|
5721
5611
|
def batch_as_completed(
|
|
5722
5612
|
self,
|
|
5723
5613
|
inputs: Sequence[Input],
|
|
5724
|
-
config:
|
|
5614
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5725
5615
|
*,
|
|
5726
5616
|
return_exceptions: bool = False,
|
|
5727
|
-
**kwargs:
|
|
5728
|
-
) -> Iterator[tuple[int,
|
|
5617
|
+
**kwargs: Any | None,
|
|
5618
|
+
) -> Iterator[tuple[int, Output | Exception]]:
|
|
5729
5619
|
if isinstance(config, Sequence):
|
|
5730
5620
|
configs = cast(
|
|
5731
5621
|
"list[RunnableConfig]",
|
|
@@ -5753,31 +5643,31 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5753
5643
|
def abatch_as_completed(
|
|
5754
5644
|
self,
|
|
5755
5645
|
inputs: Sequence[Input],
|
|
5756
|
-
config:
|
|
5646
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5757
5647
|
*,
|
|
5758
5648
|
return_exceptions: Literal[False] = False,
|
|
5759
|
-
**kwargs:
|
|
5649
|
+
**kwargs: Any | None,
|
|
5760
5650
|
) -> AsyncIterator[tuple[int, Output]]: ...
|
|
5761
5651
|
|
|
5762
5652
|
@overload
|
|
5763
5653
|
def abatch_as_completed(
|
|
5764
5654
|
self,
|
|
5765
5655
|
inputs: Sequence[Input],
|
|
5766
|
-
config:
|
|
5656
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5767
5657
|
*,
|
|
5768
5658
|
return_exceptions: Literal[True],
|
|
5769
|
-
**kwargs:
|
|
5770
|
-
) -> AsyncIterator[tuple[int,
|
|
5659
|
+
**kwargs: Any | None,
|
|
5660
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]: ...
|
|
5771
5661
|
|
|
5772
5662
|
@override
|
|
5773
5663
|
async def abatch_as_completed(
|
|
5774
5664
|
self,
|
|
5775
5665
|
inputs: Sequence[Input],
|
|
5776
|
-
config:
|
|
5666
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5777
5667
|
*,
|
|
5778
5668
|
return_exceptions: bool = False,
|
|
5779
|
-
**kwargs:
|
|
5780
|
-
) -> AsyncIterator[tuple[int,
|
|
5669
|
+
**kwargs: Any | None,
|
|
5670
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]:
|
|
5781
5671
|
if isinstance(config, Sequence):
|
|
5782
5672
|
configs = cast(
|
|
5783
5673
|
"list[RunnableConfig]",
|
|
@@ -5806,8 +5696,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5806
5696
|
def stream(
|
|
5807
5697
|
self,
|
|
5808
5698
|
input: Input,
|
|
5809
|
-
config:
|
|
5810
|
-
**kwargs:
|
|
5699
|
+
config: RunnableConfig | None = None,
|
|
5700
|
+
**kwargs: Any | None,
|
|
5811
5701
|
) -> Iterator[Output]:
|
|
5812
5702
|
yield from self.bound.stream(
|
|
5813
5703
|
input,
|
|
@@ -5819,8 +5709,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5819
5709
|
async def astream(
|
|
5820
5710
|
self,
|
|
5821
5711
|
input: Input,
|
|
5822
|
-
config:
|
|
5823
|
-
**kwargs:
|
|
5712
|
+
config: RunnableConfig | None = None,
|
|
5713
|
+
**kwargs: Any | None,
|
|
5824
5714
|
) -> AsyncIterator[Output]:
|
|
5825
5715
|
async for item in self.bound.astream(
|
|
5826
5716
|
input,
|
|
@@ -5833,8 +5723,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5833
5723
|
async def astream_events(
|
|
5834
5724
|
self,
|
|
5835
5725
|
input: Input,
|
|
5836
|
-
config:
|
|
5837
|
-
**kwargs:
|
|
5726
|
+
config: RunnableConfig | None = None,
|
|
5727
|
+
**kwargs: Any | None,
|
|
5838
5728
|
) -> AsyncIterator[StreamEvent]:
|
|
5839
5729
|
async for item in self.bound.astream_events(
|
|
5840
5730
|
input, self._merge_configs(config), **{**self.kwargs, **kwargs}
|
|
@@ -5845,7 +5735,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5845
5735
|
def transform(
|
|
5846
5736
|
self,
|
|
5847
5737
|
input: Iterator[Input],
|
|
5848
|
-
config:
|
|
5738
|
+
config: RunnableConfig | None = None,
|
|
5849
5739
|
**kwargs: Any,
|
|
5850
5740
|
) -> Iterator[Output]:
|
|
5851
5741
|
yield from self.bound.transform(
|
|
@@ -5858,7 +5748,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5858
5748
|
async def atransform(
|
|
5859
5749
|
self,
|
|
5860
5750
|
input: AsyncIterator[Input],
|
|
5861
|
-
config:
|
|
5751
|
+
config: RunnableConfig | None = None,
|
|
5862
5752
|
**kwargs: Any,
|
|
5863
5753
|
) -> AsyncIterator[Output]:
|
|
5864
5754
|
async for item in self.bound.atransform(
|
|
@@ -5895,32 +5785,30 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5895
5785
|
Example:
|
|
5896
5786
|
`bind`: Bind kwargs to pass to the underlying ``Runnable`` when running it.
|
|
5897
5787
|
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5788
|
+
```python
|
|
5789
|
+
# Create a Runnable binding that invokes the ChatModel with the
|
|
5790
|
+
# additional kwarg `stop=['-']` when running it.
|
|
5791
|
+
from langchain_community.chat_models import ChatOpenAI
|
|
5792
|
+
|
|
5793
|
+
model = ChatOpenAI()
|
|
5794
|
+
model.invoke('Say "Parrot-MAGIC"', stop=["-"]) # Should return `Parrot`
|
|
5795
|
+
# Using it the easy way via `bind` method which returns a new
|
|
5796
|
+
# RunnableBinding
|
|
5797
|
+
runnable_binding = model.bind(stop=["-"])
|
|
5798
|
+
runnable_binding.invoke('Say "Parrot-MAGIC"') # Should return `Parrot`
|
|
5799
|
+
```
|
|
5911
5800
|
Can also be done by instantiating a ``RunnableBinding`` directly (not
|
|
5912
5801
|
recommended):
|
|
5913
5802
|
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
from langchain_core.runnables import RunnableBinding
|
|
5917
|
-
|
|
5918
|
-
runnable_binding = RunnableBinding(
|
|
5919
|
-
bound=model,
|
|
5920
|
-
kwargs={"stop": ["-"]}, # <-- Note the additional kwargs
|
|
5921
|
-
)
|
|
5922
|
-
runnable_binding.invoke('Say "Parrot-MAGIC"') # Should return `Parrot`
|
|
5803
|
+
```python
|
|
5804
|
+
from langchain_core.runnables import RunnableBinding
|
|
5923
5805
|
|
|
5806
|
+
runnable_binding = RunnableBinding(
|
|
5807
|
+
bound=model,
|
|
5808
|
+
kwargs={"stop": ["-"]}, # <-- Note the additional kwargs
|
|
5809
|
+
)
|
|
5810
|
+
runnable_binding.invoke('Say "Parrot-MAGIC"') # Should return `Parrot`
|
|
5811
|
+
```
|
|
5924
5812
|
"""
|
|
5925
5813
|
|
|
5926
5814
|
@override
|
|
@@ -5947,7 +5835,7 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5947
5835
|
@override
|
|
5948
5836
|
def with_config(
|
|
5949
5837
|
self,
|
|
5950
|
-
config:
|
|
5838
|
+
config: RunnableConfig | None = None,
|
|
5951
5839
|
# Sadly Unpack is not well supported by mypy so this will have to be untyped
|
|
5952
5840
|
**kwargs: Any,
|
|
5953
5841
|
) -> Runnable[Input, Output]:
|
|
@@ -5964,15 +5852,15 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5964
5852
|
def with_listeners(
|
|
5965
5853
|
self,
|
|
5966
5854
|
*,
|
|
5967
|
-
on_start:
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
on_end:
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
on_error:
|
|
5974
|
-
|
|
5975
|
-
|
|
5855
|
+
on_start: Callable[[Run], None]
|
|
5856
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5857
|
+
| None = None,
|
|
5858
|
+
on_end: Callable[[Run], None]
|
|
5859
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5860
|
+
| None = None,
|
|
5861
|
+
on_error: Callable[[Run], None]
|
|
5862
|
+
| Callable[[Run, RunnableConfig], None]
|
|
5863
|
+
| None = None,
|
|
5976
5864
|
) -> Runnable[Input, Output]:
|
|
5977
5865
|
"""Bind lifecycle listeners to a ``Runnable``, returning a new ``Runnable``.
|
|
5978
5866
|
|
|
@@ -6016,8 +5904,8 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
6016
5904
|
@override
|
|
6017
5905
|
def with_types(
|
|
6018
5906
|
self,
|
|
6019
|
-
input_type:
|
|
6020
|
-
output_type:
|
|
5907
|
+
input_type: type[Input] | BaseModel | None = None,
|
|
5908
|
+
output_type: type[Output] | BaseModel | None = None,
|
|
6021
5909
|
) -> Runnable[Input, Output]:
|
|
6022
5910
|
return self.__class__(
|
|
6023
5911
|
bound=self.bound,
|
|
@@ -6101,18 +5989,18 @@ class _RunnableCallableAsyncIterator(Protocol[Input, Output]):
|
|
|
6101
5989
|
) -> AsyncIterator[Output]: ...
|
|
6102
5990
|
|
|
6103
5991
|
|
|
6104
|
-
RunnableLike =
|
|
6105
|
-
Runnable[Input, Output]
|
|
6106
|
-
Callable[[Input], Output]
|
|
6107
|
-
Callable[[Input], Awaitable[Output]]
|
|
6108
|
-
Callable[[Iterator[Input]], Iterator[Output]]
|
|
6109
|
-
Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
6110
|
-
_RunnableCallableSync[Input, Output]
|
|
6111
|
-
_RunnableCallableAsync[Input, Output]
|
|
6112
|
-
_RunnableCallableIterator[Input, Output]
|
|
6113
|
-
_RunnableCallableAsyncIterator[Input, Output]
|
|
6114
|
-
Mapping[str, Any]
|
|
6115
|
-
|
|
5992
|
+
RunnableLike = (
|
|
5993
|
+
Runnable[Input, Output]
|
|
5994
|
+
| Callable[[Input], Output]
|
|
5995
|
+
| Callable[[Input], Awaitable[Output]]
|
|
5996
|
+
| Callable[[Iterator[Input]], Iterator[Output]]
|
|
5997
|
+
| Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
5998
|
+
| _RunnableCallableSync[Input, Output]
|
|
5999
|
+
| _RunnableCallableAsync[Input, Output]
|
|
6000
|
+
| _RunnableCallableIterator[Input, Output]
|
|
6001
|
+
| _RunnableCallableAsyncIterator[Input, Output]
|
|
6002
|
+
| Mapping[str, Any]
|
|
6003
|
+
)
|
|
6116
6004
|
|
|
6117
6005
|
|
|
6118
6006
|
def coerce_to_runnable(thing: RunnableLike) -> Runnable[Input, Output]:
|
|
@@ -6167,12 +6055,10 @@ def chain(
|
|
|
6167
6055
|
|
|
6168
6056
|
|
|
6169
6057
|
def chain(
|
|
6170
|
-
func:
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
Callable[[Input], AsyncIterator[Output]],
|
|
6175
|
-
],
|
|
6058
|
+
func: Callable[[Input], Output]
|
|
6059
|
+
| Callable[[Input], Iterator[Output]]
|
|
6060
|
+
| Callable[[Input], Coroutine[Any, Any, Output]]
|
|
6061
|
+
| Callable[[Input], AsyncIterator[Output]],
|
|
6176
6062
|
) -> Runnable[Input, Output]:
|
|
6177
6063
|
"""Decorate a function to make it a ``Runnable``.
|
|
6178
6064
|
|
|
@@ -6186,9 +6072,7 @@ def chain(
|
|
|
6186
6072
|
A ``Runnable``.
|
|
6187
6073
|
|
|
6188
6074
|
Example:
|
|
6189
|
-
|
|
6190
|
-
.. code-block:: python
|
|
6191
|
-
|
|
6075
|
+
```python
|
|
6192
6076
|
from langchain_core.runnables import chain
|
|
6193
6077
|
from langchain_core.prompts import PromptTemplate
|
|
6194
6078
|
from langchain_openai import OpenAI
|
|
@@ -6202,6 +6086,6 @@ def chain(
|
|
|
6202
6086
|
|
|
6203
6087
|
for chunk in llm.stream(formatted):
|
|
6204
6088
|
yield chunk
|
|
6205
|
-
|
|
6089
|
+
```
|
|
6206
6090
|
"""
|
|
6207
6091
|
return RunnableLambda(func)
|