langchain-core 1.0.0a6__py3-none-any.whl → 1.0.0a8__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 +5 -5
- 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 +23 -25
- langchain_core/messages/block_translators/__init__.py +2 -5
- langchain_core/messages/block_translators/anthropic.py +3 -3
- langchain_core/messages/block_translators/bedrock_converse.py +2 -2
- 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 +928 -1042
- 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 +62 -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.0a6.dist-info → langchain_core-1.0.0a8.dist-info}/METADATA +10 -21
- langchain_core-1.0.0a8.dist-info/RECORD +176 -0
- {langchain_core-1.0.0a6.dist-info → langchain_core-1.0.0a8.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.0a6.dist-info/RECORD +0 -181
- langchain_core-1.0.0a6.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
|
-
|
|
704
|
+
```python
|
|
705
|
+
import json
|
|
718
706
|
|
|
719
|
-
|
|
707
|
+
from langchain_core.runnables import RunnableLambda, RunnableMap
|
|
720
708
|
|
|
721
|
-
|
|
709
|
+
as_str = RunnableLambda(str)
|
|
710
|
+
as_json = RunnableLambda(json.loads)
|
|
711
|
+
chain = RunnableMap(str=as_str, json=as_json)
|
|
722
712
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
chain = RunnableMap(str=as_str, json=as_json)
|
|
713
|
+
chain.invoke("[1, 2, 3]")
|
|
714
|
+
# -> {"str": "[1, 2, 3]", "json": [1, 2, 3]}
|
|
726
715
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
json_only_chain.invoke("[1, 2, 3]")
|
|
732
|
-
# -> [1, 2, 3]
|
|
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
|
|
|
@@ -898,14 +878,13 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
898
878
|
|
|
899
879
|
Returns:
|
|
900
880
|
A list of outputs from the ``Runnable``.
|
|
901
|
-
|
|
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
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
return ", ".join([doc.page_content for doc in docs])
|
|
1354
|
+
```python
|
|
1355
|
+
def format_docs(docs: list[Document]) -> str:
|
|
1356
|
+
'''Format the docs.'''
|
|
1357
|
+
return ", ".join([doc.page_content for doc in docs])
|
|
1384
1358
|
|
|
1385
1359
|
|
|
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
|
|
1384
|
+
```python
|
|
1385
|
+
from langchain_core.runnables import RunnableLambda
|
|
1414
1386
|
|
|
1415
1387
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1388
|
+
async def reverse(s: str) -> str:
|
|
1389
|
+
return s[::-1]
|
|
1418
1390
|
|
|
1419
1391
|
|
|
1420
|
-
|
|
1392
|
+
chain = RunnableLambda(func=reverse)
|
|
1421
1393
|
|
|
1422
|
-
|
|
1423
|
-
event async for event in chain.astream_events("hello", version="v2")
|
|
1424
|
-
]
|
|
1425
|
-
|
|
1426
|
-
# will produce the following events (run_id, and parent_ids
|
|
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
|
|
|
@@ -2542,82 +2476,82 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2542
2476
|
|
|
2543
2477
|
Typed dict input:
|
|
2544
2478
|
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
from langchain_core.runnables import RunnableLambda
|
|
2479
|
+
```python
|
|
2480
|
+
from typing_extensions import TypedDict
|
|
2481
|
+
from langchain_core.runnables import RunnableLambda
|
|
2549
2482
|
|
|
2550
2483
|
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2484
|
+
class Args(TypedDict):
|
|
2485
|
+
a: int
|
|
2486
|
+
b: list[int]
|
|
2554
2487
|
|
|
2555
2488
|
|
|
2556
|
-
|
|
2557
|
-
|
|
2489
|
+
def f(x: Args) -> str:
|
|
2490
|
+
return str(x["a"] * max(x["b"]))
|
|
2558
2491
|
|
|
2559
2492
|
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2493
|
+
runnable = RunnableLambda(f)
|
|
2494
|
+
as_tool = runnable.as_tool()
|
|
2495
|
+
as_tool.invoke({"a": 3, "b": [1, 2]})
|
|
2496
|
+
```
|
|
2563
2497
|
|
|
2564
2498
|
``dict`` input, specifying schema via ``args_schema``:
|
|
2565
2499
|
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
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
|
|
2571
2504
|
|
|
2572
|
-
|
|
2573
|
-
|
|
2505
|
+
def f(x: dict[str, Any]) -> str:
|
|
2506
|
+
return str(x["a"] * max(x["b"]))
|
|
2574
2507
|
|
|
2575
|
-
|
|
2576
|
-
|
|
2508
|
+
class FSchema(BaseModel):
|
|
2509
|
+
\"\"\"Apply a function to an integer and list of integers.\"\"\"
|
|
2577
2510
|
|
|
2578
|
-
|
|
2579
|
-
|
|
2511
|
+
a: int = Field(..., description="Integer")
|
|
2512
|
+
b: list[int] = Field(..., description="List of ints")
|
|
2580
2513
|
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2514
|
+
runnable = RunnableLambda(f)
|
|
2515
|
+
as_tool = runnable.as_tool(FSchema)
|
|
2516
|
+
as_tool.invoke({"a": 3, "b": [1, 2]})
|
|
2517
|
+
```
|
|
2584
2518
|
|
|
2585
2519
|
``dict`` input, specifying schema via ``arg_types``:
|
|
2586
2520
|
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
from langchain_core.runnables import RunnableLambda
|
|
2521
|
+
```python
|
|
2522
|
+
from typing import Any
|
|
2523
|
+
from langchain_core.runnables import RunnableLambda
|
|
2591
2524
|
|
|
2592
2525
|
|
|
2593
|
-
|
|
2594
|
-
|
|
2526
|
+
def f(x: dict[str, Any]) -> str:
|
|
2527
|
+
return str(x["a"] * max(x["b"]))
|
|
2595
2528
|
|
|
2596
2529
|
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
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
|
+
```
|
|
2600
2534
|
|
|
2601
2535
|
String input:
|
|
2602
2536
|
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
from langchain_core.runnables import RunnableLambda
|
|
2537
|
+
```python
|
|
2538
|
+
from langchain_core.runnables import RunnableLambda
|
|
2606
2539
|
|
|
2607
2540
|
|
|
2608
|
-
|
|
2609
|
-
|
|
2541
|
+
def f(x: str) -> str:
|
|
2542
|
+
return x + "a"
|
|
2610
2543
|
|
|
2611
2544
|
|
|
2612
|
-
|
|
2613
|
-
|
|
2545
|
+
def g(x: str) -> str:
|
|
2546
|
+
return x + "z"
|
|
2614
2547
|
|
|
2615
2548
|
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2549
|
+
runnable = RunnableLambda(f) | g
|
|
2550
|
+
as_tool = runnable.as_tool()
|
|
2551
|
+
as_tool.invoke("b")
|
|
2552
|
+
```
|
|
2619
2553
|
|
|
2620
|
-
|
|
2554
|
+
!!! version-added "Added in version 0.2.14"
|
|
2621
2555
|
|
|
2622
2556
|
"""
|
|
2623
2557
|
# Avoid circular import
|
|
@@ -2635,7 +2569,7 @@ class Runnable(ABC, Generic[Input, Output]):
|
|
|
2635
2569
|
class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
2636
2570
|
"""Runnable that can be serialized to JSON."""
|
|
2637
2571
|
|
|
2638
|
-
name:
|
|
2572
|
+
name: str | None = None
|
|
2639
2573
|
|
|
2640
2574
|
model_config = ConfigDict(
|
|
2641
2575
|
# Suppress warnings from pydantic protected namespaces
|
|
@@ -2644,7 +2578,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2644
2578
|
)
|
|
2645
2579
|
|
|
2646
2580
|
@override
|
|
2647
|
-
def to_json(self) ->
|
|
2581
|
+
def to_json(self) -> SerializedConstructor | SerializedNotImplemented:
|
|
2648
2582
|
"""Serialize the ``Runnable`` to JSON.
|
|
2649
2583
|
|
|
2650
2584
|
Returns:
|
|
@@ -2670,32 +2604,29 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2670
2604
|
Returns:
|
|
2671
2605
|
A new ``Runnable`` with the fields configured.
|
|
2672
2606
|
|
|
2673
|
-
|
|
2607
|
+
```python
|
|
2608
|
+
from langchain_core.runnables import ConfigurableField
|
|
2609
|
+
from langchain_openai import ChatOpenAI
|
|
2674
2610
|
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
id="output_token_number",
|
|
2681
|
-
name="Max tokens in the output",
|
|
2682
|
-
description="The maximum number of tokens in the output",
|
|
2683
|
-
)
|
|
2684
|
-
)
|
|
2685
|
-
|
|
2686
|
-
# max_tokens = 20
|
|
2687
|
-
print(
|
|
2688
|
-
"max_tokens_20: ", model.invoke("tell me something about chess").content
|
|
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",
|
|
2689
2616
|
)
|
|
2617
|
+
)
|
|
2690
2618
|
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
"max_tokens_200: ",
|
|
2694
|
-
model.with_config(configurable={"output_token_number": 200})
|
|
2695
|
-
.invoke("tell me something about chess")
|
|
2696
|
-
.content,
|
|
2697
|
-
)
|
|
2619
|
+
# max_tokens = 20
|
|
2620
|
+
print("max_tokens_20: ", model.invoke("tell me something about chess").content)
|
|
2698
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
|
+
```
|
|
2699
2630
|
"""
|
|
2700
2631
|
# Import locally to prevent circular import
|
|
2701
2632
|
from langchain_core.runnables.configurable import ( # noqa: PLC0415
|
|
@@ -2719,7 +2650,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2719
2650
|
*,
|
|
2720
2651
|
default_key: str = "default",
|
|
2721
2652
|
prefix_keys: bool = False,
|
|
2722
|
-
**kwargs:
|
|
2653
|
+
**kwargs: Runnable[Input, Output] | Callable[[], Runnable[Input, Output]],
|
|
2723
2654
|
) -> RunnableSerializable[Input, Output]:
|
|
2724
2655
|
"""Configure alternatives for ``Runnables`` that can be set at runtime.
|
|
2725
2656
|
|
|
@@ -2736,30 +2667,29 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2736
2667
|
Returns:
|
|
2737
2668
|
A new ``Runnable`` with the alternatives configured.
|
|
2738
2669
|
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
)
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
)
|
|
2752
|
-
|
|
2753
|
-
# uses the default model ChatAnthropic
|
|
2754
|
-
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
|
+
)
|
|
2755
2682
|
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
model.with_config(configurable={"llm": "openai"})
|
|
2759
|
-
.invoke("which organization created you?")
|
|
2760
|
-
.content
|
|
2761
|
-
)
|
|
2683
|
+
# uses the default model ChatAnthropic
|
|
2684
|
+
print(model.invoke("which organization created you?").content)
|
|
2762
2685
|
|
|
2686
|
+
# uses ChatOpenAI
|
|
2687
|
+
print(
|
|
2688
|
+
model.with_config(configurable={"llm": "openai"})
|
|
2689
|
+
.invoke("which organization created you?")
|
|
2690
|
+
.content
|
|
2691
|
+
)
|
|
2692
|
+
```
|
|
2763
2693
|
"""
|
|
2764
2694
|
# Import locally to prevent circular import
|
|
2765
2695
|
from langchain_core.runnables.configurable import ( # noqa: PLC0415
|
|
@@ -2776,7 +2706,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|
|
2776
2706
|
|
|
2777
2707
|
|
|
2778
2708
|
def _seq_input_schema(
|
|
2779
|
-
steps: list[Runnable[Any, Any]], config:
|
|
2709
|
+
steps: list[Runnable[Any, Any]], config: RunnableConfig | None
|
|
2780
2710
|
) -> type[BaseModel]:
|
|
2781
2711
|
# Import locally to prevent circular import
|
|
2782
2712
|
from langchain_core.runnables.passthrough import ( # noqa: PLC0415
|
|
@@ -2806,7 +2736,7 @@ def _seq_input_schema(
|
|
|
2806
2736
|
|
|
2807
2737
|
|
|
2808
2738
|
def _seq_output_schema(
|
|
2809
|
-
steps: list[Runnable[Any, Any]], config:
|
|
2739
|
+
steps: list[Runnable[Any, Any]], config: RunnableConfig | None
|
|
2810
2740
|
) -> type[BaseModel]:
|
|
2811
2741
|
# Import locally to prevent circular import
|
|
2812
2742
|
from langchain_core.runnables.passthrough import ( # noqa: PLC0415
|
|
@@ -2884,7 +2814,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2884
2814
|
streaming will only begin after this component is run. If there are
|
|
2885
2815
|
multiple blocking components, streaming begins after the last one.
|
|
2886
2816
|
|
|
2887
|
-
|
|
2817
|
+
!!! note
|
|
2888
2818
|
``RunnableLambdas`` do not support ``transform`` by default! So if you need to
|
|
2889
2819
|
use a ``RunnableLambdas`` be careful about where you place them in a
|
|
2890
2820
|
``RunnableSequence`` (if you need to use the ``stream``/``astream`` methods).
|
|
@@ -2895,50 +2825,49 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2895
2825
|
Here is a simple example that uses simple functions to illustrate the use of
|
|
2896
2826
|
``RunnableSequence``:
|
|
2897
2827
|
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
from langchain_core.runnables import RunnableLambda
|
|
2828
|
+
```python
|
|
2829
|
+
from langchain_core.runnables import RunnableLambda
|
|
2901
2830
|
|
|
2902
2831
|
|
|
2903
|
-
|
|
2904
|
-
|
|
2832
|
+
def add_one(x: int) -> int:
|
|
2833
|
+
return x + 1
|
|
2905
2834
|
|
|
2906
2835
|
|
|
2907
|
-
|
|
2908
|
-
|
|
2836
|
+
def mul_two(x: int) -> int:
|
|
2837
|
+
return x * 2
|
|
2909
2838
|
|
|
2910
2839
|
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
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)
|
|
2918
2847
|
|
|
2919
|
-
|
|
2920
|
-
|
|
2848
|
+
sequence.batch([1, 2, 3])
|
|
2849
|
+
await sequence.abatch([1, 2, 3])
|
|
2850
|
+
```
|
|
2921
2851
|
|
|
2922
2852
|
Here's an example that uses streams JSON output generated by an LLM:
|
|
2923
2853
|
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
from langchain_openai import ChatOpenAI
|
|
2854
|
+
```python
|
|
2855
|
+
from langchain_core.output_parsers.json import SimpleJsonOutputParser
|
|
2856
|
+
from langchain_openai import ChatOpenAI
|
|
2928
2857
|
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
model = ChatOpenAI()
|
|
2936
|
-
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
|
+
)
|
|
2937
2863
|
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
print(chunk, sep="", flush=True) # noqa: T201
|
|
2864
|
+
model = ChatOpenAI()
|
|
2865
|
+
chain = prompt | model | SimpleJsonOutputParser()
|
|
2941
2866
|
|
|
2867
|
+
async for chunk in chain.astream({"topic": "colors"}):
|
|
2868
|
+
print("-") # noqa: T201
|
|
2869
|
+
print(chunk, sep="", flush=True) # noqa: T201
|
|
2870
|
+
```
|
|
2942
2871
|
"""
|
|
2943
2872
|
|
|
2944
2873
|
# The steps are broken into first, middle and last, solely for type checking
|
|
@@ -2954,10 +2883,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
2954
2883
|
def __init__(
|
|
2955
2884
|
self,
|
|
2956
2885
|
*steps: RunnableLike,
|
|
2957
|
-
name:
|
|
2958
|
-
first:
|
|
2959
|
-
middle:
|
|
2960
|
-
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,
|
|
2961
2890
|
) -> None:
|
|
2962
2891
|
"""Create a new ``RunnableSequence``.
|
|
2963
2892
|
|
|
@@ -3031,9 +2960,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3031
2960
|
return self.last.OutputType
|
|
3032
2961
|
|
|
3033
2962
|
@override
|
|
3034
|
-
def get_input_schema(
|
|
3035
|
-
self, config: Optional[RunnableConfig] = None
|
|
3036
|
-
) -> type[BaseModel]:
|
|
2963
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
3037
2964
|
"""Get the input schema of the ``Runnable``.
|
|
3038
2965
|
|
|
3039
2966
|
Args:
|
|
@@ -3047,7 +2974,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3047
2974
|
|
|
3048
2975
|
@override
|
|
3049
2976
|
def get_output_schema(
|
|
3050
|
-
self, config:
|
|
2977
|
+
self, config: RunnableConfig | None = None
|
|
3051
2978
|
) -> type[BaseModel]:
|
|
3052
2979
|
"""Get the output schema of the ``Runnable``.
|
|
3053
2980
|
|
|
@@ -3075,7 +3002,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3075
3002
|
)
|
|
3076
3003
|
|
|
3077
3004
|
@override
|
|
3078
|
-
def get_graph(self, config:
|
|
3005
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
3079
3006
|
"""Get the graph representation of the ``Runnable``.
|
|
3080
3007
|
|
|
3081
3008
|
Args:
|
|
@@ -3118,13 +3045,11 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3118
3045
|
@override
|
|
3119
3046
|
def __or__(
|
|
3120
3047
|
self,
|
|
3121
|
-
other:
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
Mapping[str, Union[Runnable[Any, Other], Callable[[Any], Other], Any]],
|
|
3127
|
-
],
|
|
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],
|
|
3128
3053
|
) -> RunnableSerializable[Input, Other]:
|
|
3129
3054
|
if isinstance(other, RunnableSequence):
|
|
3130
3055
|
return RunnableSequence(
|
|
@@ -3147,13 +3072,11 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3147
3072
|
@override
|
|
3148
3073
|
def __ror__(
|
|
3149
3074
|
self,
|
|
3150
|
-
other:
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
Mapping[str, Union[Runnable[Other, Any], Callable[[Other], Any], Any]],
|
|
3156
|
-
],
|
|
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],
|
|
3157
3080
|
) -> RunnableSerializable[Other, Output]:
|
|
3158
3081
|
if isinstance(other, RunnableSequence):
|
|
3159
3082
|
return RunnableSequence(
|
|
@@ -3175,7 +3098,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3175
3098
|
|
|
3176
3099
|
@override
|
|
3177
3100
|
def invoke(
|
|
3178
|
-
self, input: Input, config:
|
|
3101
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
3179
3102
|
) -> Output:
|
|
3180
3103
|
# setup callbacks and context
|
|
3181
3104
|
config = ensure_config(config)
|
|
@@ -3213,8 +3136,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3213
3136
|
async def ainvoke(
|
|
3214
3137
|
self,
|
|
3215
3138
|
input: Input,
|
|
3216
|
-
config:
|
|
3217
|
-
**kwargs:
|
|
3139
|
+
config: RunnableConfig | None = None,
|
|
3140
|
+
**kwargs: Any | None,
|
|
3218
3141
|
) -> Output:
|
|
3219
3142
|
# setup callbacks and context
|
|
3220
3143
|
config = ensure_config(config)
|
|
@@ -3253,10 +3176,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3253
3176
|
def batch(
|
|
3254
3177
|
self,
|
|
3255
3178
|
inputs: list[Input],
|
|
3256
|
-
config:
|
|
3179
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
3257
3180
|
*,
|
|
3258
3181
|
return_exceptions: bool = False,
|
|
3259
|
-
**kwargs:
|
|
3182
|
+
**kwargs: Any | None,
|
|
3260
3183
|
) -> list[Output]:
|
|
3261
3184
|
if not inputs:
|
|
3262
3185
|
return []
|
|
@@ -3283,7 +3206,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3283
3206
|
name=config.get("run_name") or self.get_name(),
|
|
3284
3207
|
run_id=config.pop("run_id", None),
|
|
3285
3208
|
)
|
|
3286
|
-
for cm, input_, config in zip(
|
|
3209
|
+
for cm, input_, config in zip(
|
|
3210
|
+
callback_managers, inputs, configs, strict=False
|
|
3211
|
+
)
|
|
3287
3212
|
]
|
|
3288
3213
|
|
|
3289
3214
|
# invoke
|
|
@@ -3303,7 +3228,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3303
3228
|
inputs = step.batch(
|
|
3304
3229
|
[
|
|
3305
3230
|
inp
|
|
3306
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3231
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3307
3232
|
if i not in failed_inputs_map
|
|
3308
3233
|
],
|
|
3309
3234
|
[
|
|
@@ -3312,7 +3237,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3312
3237
|
config,
|
|
3313
3238
|
callbacks=rm.get_child(f"seq:step:{stepidx + 1}"),
|
|
3314
3239
|
)
|
|
3315
|
-
for i, (rm, config) in enumerate(
|
|
3240
|
+
for i, (rm, config) in enumerate(
|
|
3241
|
+
zip(run_managers, configs, strict=False)
|
|
3242
|
+
)
|
|
3316
3243
|
if i not in failed_inputs_map
|
|
3317
3244
|
],
|
|
3318
3245
|
return_exceptions=return_exceptions,
|
|
@@ -3322,7 +3249,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3322
3249
|
failed_inputs_map.update(
|
|
3323
3250
|
{
|
|
3324
3251
|
i: inp
|
|
3325
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3252
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3326
3253
|
if isinstance(inp, Exception)
|
|
3327
3254
|
}
|
|
3328
3255
|
)
|
|
@@ -3348,7 +3275,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3348
3275
|
patch_config(
|
|
3349
3276
|
config, callbacks=rm.get_child(f"seq:step:{i + 1}")
|
|
3350
3277
|
)
|
|
3351
|
-
for rm, config in zip(run_managers, configs)
|
|
3278
|
+
for rm, config in zip(run_managers, configs, strict=False)
|
|
3352
3279
|
],
|
|
3353
3280
|
return_exceptions=return_exceptions,
|
|
3354
3281
|
**(kwargs if i == 0 else {}),
|
|
@@ -3362,8 +3289,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3362
3289
|
return cast("list[Output]", [e for _ in inputs])
|
|
3363
3290
|
raise
|
|
3364
3291
|
else:
|
|
3365
|
-
first_exception:
|
|
3366
|
-
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):
|
|
3367
3294
|
if isinstance(out, Exception):
|
|
3368
3295
|
first_exception = first_exception or out
|
|
3369
3296
|
run_manager.on_chain_error(out)
|
|
@@ -3377,10 +3304,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3377
3304
|
async def abatch(
|
|
3378
3305
|
self,
|
|
3379
3306
|
inputs: list[Input],
|
|
3380
|
-
config:
|
|
3307
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
3381
3308
|
*,
|
|
3382
3309
|
return_exceptions: bool = False,
|
|
3383
|
-
**kwargs:
|
|
3310
|
+
**kwargs: Any | None,
|
|
3384
3311
|
) -> list[Output]:
|
|
3385
3312
|
if not inputs:
|
|
3386
3313
|
return []
|
|
@@ -3408,7 +3335,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3408
3335
|
name=config.get("run_name") or self.get_name(),
|
|
3409
3336
|
run_id=config.pop("run_id", None),
|
|
3410
3337
|
)
|
|
3411
|
-
for cm, input_, config in zip(
|
|
3338
|
+
for cm, input_, config in zip(
|
|
3339
|
+
callback_managers, inputs, configs, strict=False
|
|
3340
|
+
)
|
|
3412
3341
|
)
|
|
3413
3342
|
)
|
|
3414
3343
|
|
|
@@ -3430,7 +3359,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3430
3359
|
inputs = await step.abatch(
|
|
3431
3360
|
[
|
|
3432
3361
|
inp
|
|
3433
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3362
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3434
3363
|
if i not in failed_inputs_map
|
|
3435
3364
|
],
|
|
3436
3365
|
[
|
|
@@ -3439,7 +3368,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3439
3368
|
config,
|
|
3440
3369
|
callbacks=rm.get_child(f"seq:step:{stepidx + 1}"),
|
|
3441
3370
|
)
|
|
3442
|
-
for i, (rm, config) in enumerate(
|
|
3371
|
+
for i, (rm, config) in enumerate(
|
|
3372
|
+
zip(run_managers, configs, strict=False)
|
|
3373
|
+
)
|
|
3443
3374
|
if i not in failed_inputs_map
|
|
3444
3375
|
],
|
|
3445
3376
|
return_exceptions=return_exceptions,
|
|
@@ -3449,7 +3380,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3449
3380
|
failed_inputs_map.update(
|
|
3450
3381
|
{
|
|
3451
3382
|
i: inp
|
|
3452
|
-
for i, inp in zip(remaining_idxs, inputs)
|
|
3383
|
+
for i, inp in zip(remaining_idxs, inputs, strict=False)
|
|
3453
3384
|
if isinstance(inp, Exception)
|
|
3454
3385
|
}
|
|
3455
3386
|
)
|
|
@@ -3475,7 +3406,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3475
3406
|
patch_config(
|
|
3476
3407
|
config, callbacks=rm.get_child(f"seq:step:{i + 1}")
|
|
3477
3408
|
)
|
|
3478
|
-
for rm, config in zip(run_managers, configs)
|
|
3409
|
+
for rm, config in zip(run_managers, configs, strict=False)
|
|
3479
3410
|
],
|
|
3480
3411
|
return_exceptions=return_exceptions,
|
|
3481
3412
|
**(kwargs if i == 0 else {}),
|
|
@@ -3487,9 +3418,9 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3487
3418
|
return cast("list[Output]", [e for _ in inputs])
|
|
3488
3419
|
raise
|
|
3489
3420
|
else:
|
|
3490
|
-
first_exception:
|
|
3421
|
+
first_exception: Exception | None = None
|
|
3491
3422
|
coros: list[Awaitable[None]] = []
|
|
3492
|
-
for run_manager, out in zip(run_managers, inputs):
|
|
3423
|
+
for run_manager, out in zip(run_managers, inputs, strict=False):
|
|
3493
3424
|
if isinstance(out, Exception):
|
|
3494
3425
|
first_exception = first_exception or out
|
|
3495
3426
|
coros.append(run_manager.on_chain_error(out))
|
|
@@ -3552,8 +3483,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3552
3483
|
def transform(
|
|
3553
3484
|
self,
|
|
3554
3485
|
input: Iterator[Input],
|
|
3555
|
-
config:
|
|
3556
|
-
**kwargs:
|
|
3486
|
+
config: RunnableConfig | None = None,
|
|
3487
|
+
**kwargs: Any | None,
|
|
3557
3488
|
) -> Iterator[Output]:
|
|
3558
3489
|
yield from self._transform_stream_with_config(
|
|
3559
3490
|
input,
|
|
@@ -3566,8 +3497,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3566
3497
|
def stream(
|
|
3567
3498
|
self,
|
|
3568
3499
|
input: Input,
|
|
3569
|
-
config:
|
|
3570
|
-
**kwargs:
|
|
3500
|
+
config: RunnableConfig | None = None,
|
|
3501
|
+
**kwargs: Any | None,
|
|
3571
3502
|
) -> Iterator[Output]:
|
|
3572
3503
|
yield from self.transform(iter([input]), config, **kwargs)
|
|
3573
3504
|
|
|
@@ -3575,8 +3506,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3575
3506
|
async def atransform(
|
|
3576
3507
|
self,
|
|
3577
3508
|
input: AsyncIterator[Input],
|
|
3578
|
-
config:
|
|
3579
|
-
**kwargs:
|
|
3509
|
+
config: RunnableConfig | None = None,
|
|
3510
|
+
**kwargs: Any | None,
|
|
3580
3511
|
) -> AsyncIterator[Output]:
|
|
3581
3512
|
async for chunk in self._atransform_stream_with_config(
|
|
3582
3513
|
input,
|
|
@@ -3590,8 +3521,8 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
|
|
|
3590
3521
|
async def astream(
|
|
3591
3522
|
self,
|
|
3592
3523
|
input: Input,
|
|
3593
|
-
config:
|
|
3594
|
-
**kwargs:
|
|
3524
|
+
config: RunnableConfig | None = None,
|
|
3525
|
+
**kwargs: Any | None,
|
|
3595
3526
|
) -> AsyncIterator[Output]:
|
|
3596
3527
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
3597
3528
|
yield input
|
|
@@ -3615,95 +3546,89 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3615
3546
|
Here is a simple example that uses functions to illustrate the use of
|
|
3616
3547
|
``RunnableParallel``:
|
|
3617
3548
|
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
from langchain_core.runnables import RunnableLambda
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
def add_one(x: int) -> int:
|
|
3624
|
-
return x + 1
|
|
3549
|
+
```python
|
|
3550
|
+
from langchain_core.runnables import RunnableLambda
|
|
3625
3551
|
|
|
3626
3552
|
|
|
3627
|
-
|
|
3628
|
-
|
|
3553
|
+
def add_one(x: int) -> int:
|
|
3554
|
+
return x + 1
|
|
3629
3555
|
|
|
3630
3556
|
|
|
3631
|
-
|
|
3632
|
-
|
|
3557
|
+
def mul_two(x: int) -> int:
|
|
3558
|
+
return x * 2
|
|
3633
3559
|
|
|
3634
3560
|
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
runnable_3 = RunnableLambda(mul_three)
|
|
3561
|
+
def mul_three(x: int) -> int:
|
|
3562
|
+
return x * 3
|
|
3638
3563
|
|
|
3639
|
-
sequence = runnable_1 | { # this dict is coerced to a RunnableParallel
|
|
3640
|
-
"mul_two": runnable_2,
|
|
3641
|
-
"mul_three": runnable_3,
|
|
3642
|
-
}
|
|
3643
|
-
# Or equivalently:
|
|
3644
|
-
# sequence = runnable_1 | RunnableParallel(
|
|
3645
|
-
# {"mul_two": runnable_2, "mul_three": runnable_3}
|
|
3646
|
-
# )
|
|
3647
|
-
# Also equivalently:
|
|
3648
|
-
# sequence = runnable_1 | RunnableParallel(
|
|
3649
|
-
# mul_two=runnable_2,
|
|
3650
|
-
# mul_three=runnable_3,
|
|
3651
|
-
# )
|
|
3652
3564
|
|
|
3653
|
-
|
|
3654
|
-
|
|
3565
|
+
runnable_1 = RunnableLambda(add_one)
|
|
3566
|
+
runnable_2 = RunnableLambda(mul_two)
|
|
3567
|
+
runnable_3 = RunnableLambda(mul_three)
|
|
3655
3568
|
|
|
3656
|
-
|
|
3657
|
-
|
|
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
|
+
```
|
|
3658
3589
|
|
|
3659
3590
|
``RunnableParallel`` makes it easy to run ``Runnable``s in parallel. In the below
|
|
3660
3591
|
example, we simultaneously stream output from two different ``Runnables``:
|
|
3661
3592
|
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
from langchain_openai import ChatOpenAI
|
|
3667
|
-
|
|
3668
|
-
model = ChatOpenAI()
|
|
3669
|
-
joke_chain = (
|
|
3670
|
-
ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
|
|
3671
|
-
)
|
|
3672
|
-
poem_chain = (
|
|
3673
|
-
ChatPromptTemplate.from_template("write a 2-line poem about {topic}")
|
|
3674
|
-
| model
|
|
3675
|
-
)
|
|
3593
|
+
```python
|
|
3594
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
3595
|
+
from langchain_core.runnables import RunnableParallel
|
|
3596
|
+
from langchain_openai import ChatOpenAI
|
|
3676
3597
|
|
|
3677
|
-
|
|
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
|
+
)
|
|
3678
3606
|
|
|
3679
|
-
|
|
3680
|
-
output = {key: "" for key, _ in runnable.output_schema()}
|
|
3681
|
-
for chunk in runnable.stream({"topic": "bear"}):
|
|
3682
|
-
for key in chunk:
|
|
3683
|
-
output[key] = output[key] + chunk[key].content
|
|
3684
|
-
print(output) # noqa: T201
|
|
3607
|
+
runnable = RunnableParallel(joke=joke_chain, poem=poem_chain)
|
|
3685
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
|
+
```
|
|
3686
3616
|
"""
|
|
3687
3617
|
|
|
3688
3618
|
steps__: Mapping[str, Runnable[Input, Any]]
|
|
3689
3619
|
|
|
3690
3620
|
def __init__(
|
|
3691
3621
|
self,
|
|
3692
|
-
steps__:
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
]
|
|
3702
|
-
**kwargs: Union[
|
|
3703
|
-
Runnable[Input, Any],
|
|
3704
|
-
Callable[[Input], Any],
|
|
3705
|
-
Mapping[str, Union[Runnable[Input, Any], Callable[[Input], Any]]],
|
|
3706
|
-
],
|
|
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]],
|
|
3707
3632
|
) -> None:
|
|
3708
3633
|
"""Create a ``RunnableParallel``.
|
|
3709
3634
|
|
|
@@ -3739,9 +3664,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3739
3664
|
)
|
|
3740
3665
|
|
|
3741
3666
|
@override
|
|
3742
|
-
def get_name(
|
|
3743
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
3744
|
-
) -> str:
|
|
3667
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
3745
3668
|
"""Get the name of the ``Runnable``.
|
|
3746
3669
|
|
|
3747
3670
|
Args:
|
|
@@ -3766,9 +3689,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3766
3689
|
return Any
|
|
3767
3690
|
|
|
3768
3691
|
@override
|
|
3769
|
-
def get_input_schema(
|
|
3770
|
-
self, config: Optional[RunnableConfig] = None
|
|
3771
|
-
) -> type[BaseModel]:
|
|
3692
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
3772
3693
|
"""Get the input schema of the ``Runnable``.
|
|
3773
3694
|
|
|
3774
3695
|
Args:
|
|
@@ -3798,7 +3719,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3798
3719
|
|
|
3799
3720
|
@override
|
|
3800
3721
|
def get_output_schema(
|
|
3801
|
-
self, config:
|
|
3722
|
+
self, config: RunnableConfig | None = None
|
|
3802
3723
|
) -> type[BaseModel]:
|
|
3803
3724
|
"""Get the output schema of the ``Runnable``.
|
|
3804
3725
|
|
|
@@ -3826,7 +3747,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3826
3747
|
)
|
|
3827
3748
|
|
|
3828
3749
|
@override
|
|
3829
|
-
def get_graph(self, config:
|
|
3750
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
3830
3751
|
"""Get the graph representation of the ``Runnable``.
|
|
3831
3752
|
|
|
3832
3753
|
Args:
|
|
@@ -3874,7 +3795,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3874
3795
|
|
|
3875
3796
|
@override
|
|
3876
3797
|
def invoke(
|
|
3877
|
-
self, input: Input, config:
|
|
3798
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
3878
3799
|
) -> dict[str, Any]:
|
|
3879
3800
|
# setup callbacks
|
|
3880
3801
|
config = ensure_config(config)
|
|
@@ -3920,7 +3841,10 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3920
3841
|
executor.submit(_invoke_step, step, input, config, key)
|
|
3921
3842
|
for key, step in steps.items()
|
|
3922
3843
|
]
|
|
3923
|
-
output = {
|
|
3844
|
+
output = {
|
|
3845
|
+
key: future.result()
|
|
3846
|
+
for key, future in zip(steps, futures, strict=False)
|
|
3847
|
+
}
|
|
3924
3848
|
# finish the root run
|
|
3925
3849
|
except BaseException as e:
|
|
3926
3850
|
run_manager.on_chain_error(e)
|
|
@@ -3933,8 +3857,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3933
3857
|
async def ainvoke(
|
|
3934
3858
|
self,
|
|
3935
3859
|
input: Input,
|
|
3936
|
-
config:
|
|
3937
|
-
**kwargs:
|
|
3860
|
+
config: RunnableConfig | None = None,
|
|
3861
|
+
**kwargs: Any | None,
|
|
3938
3862
|
) -> dict[str, Any]:
|
|
3939
3863
|
# setup callbacks
|
|
3940
3864
|
config = ensure_config(config)
|
|
@@ -3975,7 +3899,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
3975
3899
|
for key, step in steps.items()
|
|
3976
3900
|
)
|
|
3977
3901
|
)
|
|
3978
|
-
output = dict(zip(steps, results))
|
|
3902
|
+
output = dict(zip(steps, results, strict=False))
|
|
3979
3903
|
# finish the root run
|
|
3980
3904
|
except BaseException as e:
|
|
3981
3905
|
await run_manager.on_chain_error(e)
|
|
@@ -4035,7 +3959,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4035
3959
|
def transform(
|
|
4036
3960
|
self,
|
|
4037
3961
|
input: Iterator[Input],
|
|
4038
|
-
config:
|
|
3962
|
+
config: RunnableConfig | None = None,
|
|
4039
3963
|
**kwargs: Any,
|
|
4040
3964
|
) -> Iterator[dict[str, Any]]:
|
|
4041
3965
|
yield from self._transform_stream_with_config(
|
|
@@ -4046,8 +3970,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4046
3970
|
def stream(
|
|
4047
3971
|
self,
|
|
4048
3972
|
input: Input,
|
|
4049
|
-
config:
|
|
4050
|
-
**kwargs:
|
|
3973
|
+
config: RunnableConfig | None = None,
|
|
3974
|
+
**kwargs: Any | None,
|
|
4051
3975
|
) -> Iterator[dict[str, Any]]:
|
|
4052
3976
|
yield from self.transform(iter([input]), config)
|
|
4053
3977
|
|
|
@@ -4077,7 +4001,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4077
4001
|
]
|
|
4078
4002
|
|
|
4079
4003
|
# Wrap in a coroutine to satisfy linter
|
|
4080
|
-
async def get_next_chunk(generator: AsyncIterator) ->
|
|
4004
|
+
async def get_next_chunk(generator: AsyncIterator) -> Output | None:
|
|
4081
4005
|
return await py_anext(generator)
|
|
4082
4006
|
|
|
4083
4007
|
# Start the first iteration of each generator
|
|
@@ -4106,7 +4030,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4106
4030
|
async def atransform(
|
|
4107
4031
|
self,
|
|
4108
4032
|
input: AsyncIterator[Input],
|
|
4109
|
-
config:
|
|
4033
|
+
config: RunnableConfig | None = None,
|
|
4110
4034
|
**kwargs: Any,
|
|
4111
4035
|
) -> AsyncIterator[dict[str, Any]]:
|
|
4112
4036
|
async for chunk in self._atransform_stream_with_config(
|
|
@@ -4118,8 +4042,8 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
|
|
|
4118
4042
|
async def astream(
|
|
4119
4043
|
self,
|
|
4120
4044
|
input: Input,
|
|
4121
|
-
config:
|
|
4122
|
-
**kwargs:
|
|
4045
|
+
config: RunnableConfig | None = None,
|
|
4046
|
+
**kwargs: Any | None,
|
|
4123
4047
|
) -> AsyncIterator[dict[str, Any]]:
|
|
4124
4048
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
4125
4049
|
yield input
|
|
@@ -4144,7 +4068,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4144
4068
|
``RunnableGenerator`` allows it to emit output chunks as soon as they are streamed
|
|
4145
4069
|
in from the previous step.
|
|
4146
4070
|
|
|
4147
|
-
|
|
4071
|
+
!!! note
|
|
4148
4072
|
If a generator function has a ``signature A -> Iterator[B]``, such that it
|
|
4149
4073
|
requires its input from the previous step to be completed before emitting chunks
|
|
4150
4074
|
(e.g., most LLMs need the entire prompt available to start generating), it can
|
|
@@ -4152,92 +4076,86 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4152
4076
|
|
|
4153
4077
|
Here is an example to show the basic mechanics of a ``RunnableGenerator``:
|
|
4154
4078
|
|
|
4155
|
-
|
|
4079
|
+
```python
|
|
4080
|
+
from typing import Any, AsyncIterator, Iterator
|
|
4156
4081
|
|
|
4157
|
-
|
|
4082
|
+
from langchain_core.runnables import RunnableGenerator
|
|
4158
4083
|
|
|
4159
|
-
from langchain_core.runnables import RunnableGenerator
|
|
4160
4084
|
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
yield token
|
|
4085
|
+
def gen(input: Iterator[Any]) -> Iterator[str]:
|
|
4086
|
+
for token in ["Have", " a", " nice", " day"]:
|
|
4087
|
+
yield token
|
|
4165
4088
|
|
|
4166
4089
|
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
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"]
|
|
4171
4094
|
|
|
4172
4095
|
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4096
|
+
# Async version:
|
|
4097
|
+
async def agen(input: AsyncIterator[Any]) -> AsyncIterator[str]:
|
|
4098
|
+
for token in ["Have", " a", " nice", " day"]:
|
|
4099
|
+
yield token
|
|
4177
4100
|
|
|
4178
4101
|
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
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
|
+
```
|
|
4182
4106
|
|
|
4183
4107
|
``RunnableGenerator`` makes it easy to implement custom behavior within a streaming
|
|
4184
4108
|
context. Below we show an example:
|
|
4185
4109
|
|
|
4186
|
-
|
|
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
|
|
4187
4115
|
|
|
4188
|
-
from langchain_core.prompts import ChatPromptTemplate
|
|
4189
|
-
from langchain_core.runnables import RunnableGenerator, RunnableLambda
|
|
4190
|
-
from langchain_openai import ChatOpenAI
|
|
4191
|
-
from langchain_core.output_parsers import StrOutputParser
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
model = ChatOpenAI()
|
|
4195
|
-
chant_chain = (
|
|
4196
|
-
ChatPromptTemplate.from_template("Give me a 3 word chant about {topic}")
|
|
4197
|
-
| model
|
|
4198
|
-
| StrOutputParser()
|
|
4199
|
-
)
|
|
4200
4116
|
|
|
4117
|
+
model = ChatOpenAI()
|
|
4118
|
+
chant_chain = (
|
|
4119
|
+
ChatPromptTemplate.from_template("Give me a 3 word chant about {topic}")
|
|
4120
|
+
| model
|
|
4121
|
+
| StrOutputParser()
|
|
4122
|
+
)
|
|
4201
4123
|
|
|
4202
|
-
def character_generator(input: Iterator[str]) -> Iterator[str]:
|
|
4203
|
-
for token in input:
|
|
4204
|
-
if "," in token or "." in token:
|
|
4205
|
-
yield "👏" + token
|
|
4206
|
-
else:
|
|
4207
|
-
yield token
|
|
4208
4124
|
|
|
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
|
|
4209
4131
|
|
|
4210
|
-
runnable = chant_chain | character_generator
|
|
4211
|
-
assert type(runnable.last) is RunnableGenerator
|
|
4212
|
-
"".join(
|
|
4213
|
-
runnable.stream({"topic": "waste"})
|
|
4214
|
-
) # Reduce👏, Reuse👏, Recycle👏.
|
|
4215
4132
|
|
|
4133
|
+
runnable = chant_chain | character_generator
|
|
4134
|
+
assert type(runnable.last) is RunnableGenerator
|
|
4135
|
+
"".join(runnable.stream({"topic": "waste"})) # Reduce👏, Reuse👏, Recycle👏.
|
|
4216
4136
|
|
|
4217
|
-
# Note that RunnableLambda can be used to delay streaming of one step in a
|
|
4218
|
-
# sequence until the previous step is finished:
|
|
4219
|
-
def reverse_generator(input: str) -> Iterator[str]:
|
|
4220
|
-
# Yield characters of input in reverse order.
|
|
4221
|
-
for character in input[::-1]:
|
|
4222
|
-
yield character
|
|
4223
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
|
|
4224
4144
|
|
|
4225
|
-
runnable = chant_chain | RunnableLambda(reverse_generator)
|
|
4226
|
-
"".join(runnable.stream({"topic": "waste"})) # ".elcycer ,esuer ,ecudeR"
|
|
4227
4145
|
|
|
4146
|
+
runnable = chant_chain | RunnableLambda(reverse_generator)
|
|
4147
|
+
"".join(runnable.stream({"topic": "waste"})) # ".elcycer ,esuer ,ecudeR"
|
|
4148
|
+
```
|
|
4228
4149
|
"""
|
|
4229
4150
|
|
|
4230
4151
|
def __init__(
|
|
4231
4152
|
self,
|
|
4232
|
-
transform:
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
atransform: Optional[
|
|
4237
|
-
Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
4238
|
-
] = None,
|
|
4153
|
+
transform: Callable[[Iterator[Input]], Iterator[Output]]
|
|
4154
|
+
| Callable[[AsyncIterator[Input]], AsyncIterator[Output]],
|
|
4155
|
+
atransform: Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
4156
|
+
| None = None,
|
|
4239
4157
|
*,
|
|
4240
|
-
name:
|
|
4158
|
+
name: str | None = None,
|
|
4241
4159
|
) -> None:
|
|
4242
4160
|
"""Initialize a ``RunnableGenerator``.
|
|
4243
4161
|
|
|
@@ -4286,9 +4204,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4286
4204
|
return Any
|
|
4287
4205
|
|
|
4288
4206
|
@override
|
|
4289
|
-
def get_input_schema(
|
|
4290
|
-
self, config: Optional[RunnableConfig] = None
|
|
4291
|
-
) -> type[BaseModel]:
|
|
4207
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
4292
4208
|
# Override the default implementation.
|
|
4293
4209
|
# For a runnable generator, we need to bring to provide the
|
|
4294
4210
|
# module of the underlying function when creating the model.
|
|
@@ -4329,7 +4245,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4329
4245
|
|
|
4330
4246
|
@override
|
|
4331
4247
|
def get_output_schema(
|
|
4332
|
-
self, config:
|
|
4248
|
+
self, config: RunnableConfig | None = None
|
|
4333
4249
|
) -> type[BaseModel]:
|
|
4334
4250
|
# Override the default implementation.
|
|
4335
4251
|
# For a runnable generator, we need to bring to provide the
|
|
@@ -4374,7 +4290,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4374
4290
|
def transform(
|
|
4375
4291
|
self,
|
|
4376
4292
|
input: Iterator[Input],
|
|
4377
|
-
config:
|
|
4293
|
+
config: RunnableConfig | None = None,
|
|
4378
4294
|
**kwargs: Any,
|
|
4379
4295
|
) -> Iterator[Output]:
|
|
4380
4296
|
if not hasattr(self, "_transform"):
|
|
@@ -4391,16 +4307,16 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4391
4307
|
def stream(
|
|
4392
4308
|
self,
|
|
4393
4309
|
input: Input,
|
|
4394
|
-
config:
|
|
4310
|
+
config: RunnableConfig | None = None,
|
|
4395
4311
|
**kwargs: Any,
|
|
4396
4312
|
) -> Iterator[Output]:
|
|
4397
4313
|
return self.transform(iter([input]), config, **kwargs)
|
|
4398
4314
|
|
|
4399
4315
|
@override
|
|
4400
4316
|
def invoke(
|
|
4401
|
-
self, input: Input, config:
|
|
4317
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
4402
4318
|
) -> Output:
|
|
4403
|
-
final:
|
|
4319
|
+
final: Output | None = None
|
|
4404
4320
|
for output in self.stream(input, config, **kwargs):
|
|
4405
4321
|
final = output if final is None else final + output # type: ignore[operator]
|
|
4406
4322
|
return cast("Output", final)
|
|
@@ -4409,7 +4325,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4409
4325
|
def atransform(
|
|
4410
4326
|
self,
|
|
4411
4327
|
input: AsyncIterator[Input],
|
|
4412
|
-
config:
|
|
4328
|
+
config: RunnableConfig | None = None,
|
|
4413
4329
|
**kwargs: Any,
|
|
4414
4330
|
) -> AsyncIterator[Output]:
|
|
4415
4331
|
if not hasattr(self, "_atransform"):
|
|
@@ -4424,7 +4340,7 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4424
4340
|
def astream(
|
|
4425
4341
|
self,
|
|
4426
4342
|
input: Input,
|
|
4427
|
-
config:
|
|
4343
|
+
config: RunnableConfig | None = None,
|
|
4428
4344
|
**kwargs: Any,
|
|
4429
4345
|
) -> AsyncIterator[Output]:
|
|
4430
4346
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
@@ -4434,9 +4350,9 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4434
4350
|
|
|
4435
4351
|
@override
|
|
4436
4352
|
async def ainvoke(
|
|
4437
|
-
self, input: Input, config:
|
|
4353
|
+
self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
|
|
4438
4354
|
) -> Output:
|
|
4439
|
-
final:
|
|
4355
|
+
final: Output | None = None
|
|
4440
4356
|
async for output in self.astream(input, config, **kwargs):
|
|
4441
4357
|
final = output if final is None else final + output # type: ignore[operator]
|
|
4442
4358
|
return cast("Output", final)
|
|
@@ -4460,73 +4376,60 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4460
4376
|
instance is invoked (or streamed) during execution.
|
|
4461
4377
|
|
|
4462
4378
|
Examples:
|
|
4379
|
+
```python
|
|
4380
|
+
# This is a RunnableLambda
|
|
4381
|
+
from langchain_core.runnables import RunnableLambda
|
|
4463
4382
|
|
|
4464
|
-
.. code-block:: python
|
|
4465
|
-
|
|
4466
|
-
# This is a RunnableLambda
|
|
4467
|
-
from langchain_core.runnables import RunnableLambda
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
def add_one(x: int) -> int:
|
|
4471
|
-
return x + 1
|
|
4472
4383
|
|
|
4384
|
+
def add_one(x: int) -> int:
|
|
4385
|
+
return x + 1
|
|
4473
4386
|
|
|
4474
|
-
runnable = RunnableLambda(add_one)
|
|
4475
4387
|
|
|
4476
|
-
|
|
4477
|
-
runnable.batch([1, 2, 3]) # returns [2, 3, 4]
|
|
4388
|
+
runnable = RunnableLambda(add_one)
|
|
4478
4389
|
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
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]
|
|
4482
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]
|
|
4483
4396
|
|
|
4484
|
-
# Alternatively, can provide both synd and sync implementations
|
|
4485
|
-
async def add_one_async(x: int) -> int:
|
|
4486
|
-
return x + 1
|
|
4487
4397
|
|
|
4398
|
+
# Alternatively, can provide both synd and sync implementations
|
|
4399
|
+
async def add_one_async(x: int) -> int:
|
|
4400
|
+
return x + 1
|
|
4488
4401
|
|
|
4489
|
-
runnable = RunnableLambda(add_one, afunc=add_one_async)
|
|
4490
|
-
runnable.invoke(1) # Uses add_one
|
|
4491
|
-
await runnable.ainvoke(1) # Uses add_one_async
|
|
4492
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
|
+
```
|
|
4493
4407
|
"""
|
|
4494
4408
|
|
|
4495
4409
|
def __init__(
|
|
4496
4410
|
self,
|
|
4497
|
-
func:
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
Callable[[Input, RunnableConfig], Awaitable[Output]],
|
|
4510
|
-
Callable[[Input, AsyncCallbackManagerForChainRun], Awaitable[Output]],
|
|
4511
|
-
Callable[
|
|
4512
|
-
[Input, AsyncCallbackManagerForChainRun, RunnableConfig],
|
|
4513
|
-
Awaitable[Output],
|
|
4514
|
-
],
|
|
4515
|
-
],
|
|
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]
|
|
4516
4423
|
],
|
|
4517
|
-
afunc:
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
],
|
|
4527
|
-
]
|
|
4528
|
-
] = None,
|
|
4529
|
-
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,
|
|
4530
4433
|
) -> None:
|
|
4531
4434
|
"""Create a ``RunnableLambda`` from a callable, and async callable or both.
|
|
4532
4435
|
|
|
@@ -4576,7 +4479,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4576
4479
|
except AttributeError:
|
|
4577
4480
|
pass
|
|
4578
4481
|
|
|
4579
|
-
self._repr:
|
|
4482
|
+
self._repr: str | None = None
|
|
4580
4483
|
|
|
4581
4484
|
@property
|
|
4582
4485
|
@override
|
|
@@ -4593,9 +4496,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4593
4496
|
return Any
|
|
4594
4497
|
|
|
4595
4498
|
@override
|
|
4596
|
-
def get_input_schema(
|
|
4597
|
-
self, config: Optional[RunnableConfig] = None
|
|
4598
|
-
) -> type[BaseModel]:
|
|
4499
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
4599
4500
|
"""The pydantic schema for the input to this ``Runnable``.
|
|
4600
4501
|
|
|
4601
4502
|
Args:
|
|
@@ -4664,7 +4565,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4664
4565
|
|
|
4665
4566
|
@override
|
|
4666
4567
|
def get_output_schema(
|
|
4667
|
-
self, config:
|
|
4568
|
+
self, config: RunnableConfig | None = None
|
|
4668
4569
|
) -> type[BaseModel]:
|
|
4669
4570
|
# Override the default implementation.
|
|
4670
4571
|
# For a runnable lambda, we need to bring to provide the
|
|
@@ -4785,7 +4686,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4785
4686
|
**kwargs: Any,
|
|
4786
4687
|
) -> Output:
|
|
4787
4688
|
if inspect.isgeneratorfunction(self.func):
|
|
4788
|
-
output:
|
|
4689
|
+
output: Output | None = None
|
|
4789
4690
|
for chunk in call_func_with_variable_args(
|
|
4790
4691
|
cast("Callable[[Input], Iterator[Output]]", self.func),
|
|
4791
4692
|
input_,
|
|
@@ -4840,7 +4741,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4840
4741
|
config: RunnableConfig,
|
|
4841
4742
|
**kwargs: Any,
|
|
4842
4743
|
) -> Output:
|
|
4843
|
-
output:
|
|
4744
|
+
output: Output | None = None
|
|
4844
4745
|
for chunk in call_func_with_variable_args(
|
|
4845
4746
|
cast("Callable[[Input], Iterator[Output]]", self.func),
|
|
4846
4747
|
value,
|
|
@@ -4876,7 +4777,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4876
4777
|
afunc = f
|
|
4877
4778
|
|
|
4878
4779
|
if is_async_generator(afunc):
|
|
4879
|
-
output:
|
|
4780
|
+
output: Output | None = None
|
|
4880
4781
|
async with aclosing(
|
|
4881
4782
|
cast(
|
|
4882
4783
|
"AsyncGenerator[Any, Any]",
|
|
@@ -4926,8 +4827,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4926
4827
|
def invoke(
|
|
4927
4828
|
self,
|
|
4928
4829
|
input: Input,
|
|
4929
|
-
config:
|
|
4930
|
-
**kwargs:
|
|
4830
|
+
config: RunnableConfig | None = None,
|
|
4831
|
+
**kwargs: Any | None,
|
|
4931
4832
|
) -> Output:
|
|
4932
4833
|
"""Invoke this ``Runnable`` synchronously.
|
|
4933
4834
|
|
|
@@ -4957,8 +4858,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4957
4858
|
async def ainvoke(
|
|
4958
4859
|
self,
|
|
4959
4860
|
input: Input,
|
|
4960
|
-
config:
|
|
4961
|
-
**kwargs:
|
|
4861
|
+
config: RunnableConfig | None = None,
|
|
4862
|
+
**kwargs: Any | None,
|
|
4962
4863
|
) -> Output:
|
|
4963
4864
|
"""Invoke this ``Runnable`` asynchronously.
|
|
4964
4865
|
|
|
@@ -5002,7 +4903,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5002
4903
|
final = ichunk
|
|
5003
4904
|
|
|
5004
4905
|
if inspect.isgeneratorfunction(self.func):
|
|
5005
|
-
output:
|
|
4906
|
+
output: Output | None = None
|
|
5006
4907
|
for chunk in call_func_with_variable_args(
|
|
5007
4908
|
self.func, final, config, run_manager, **kwargs
|
|
5008
4909
|
):
|
|
@@ -5044,8 +4945,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5044
4945
|
def transform(
|
|
5045
4946
|
self,
|
|
5046
4947
|
input: Iterator[Input],
|
|
5047
|
-
config:
|
|
5048
|
-
**kwargs:
|
|
4948
|
+
config: RunnableConfig | None = None,
|
|
4949
|
+
**kwargs: Any | None,
|
|
5049
4950
|
) -> Iterator[Output]:
|
|
5050
4951
|
if hasattr(self, "func"):
|
|
5051
4952
|
yield from self._transform_stream_with_config(
|
|
@@ -5065,8 +4966,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5065
4966
|
def stream(
|
|
5066
4967
|
self,
|
|
5067
4968
|
input: Input,
|
|
5068
|
-
config:
|
|
5069
|
-
**kwargs:
|
|
4969
|
+
config: RunnableConfig | None = None,
|
|
4970
|
+
**kwargs: Any | None,
|
|
5070
4971
|
) -> Iterator[Output]:
|
|
5071
4972
|
return self.transform(iter([input]), config, **kwargs)
|
|
5072
4973
|
|
|
@@ -5120,7 +5021,7 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5120
5021
|
afunc = f
|
|
5121
5022
|
|
|
5122
5023
|
if is_async_generator(afunc):
|
|
5123
|
-
output:
|
|
5024
|
+
output: Output | None = None
|
|
5124
5025
|
async for chunk in cast(
|
|
5125
5026
|
"AsyncIterator[Output]",
|
|
5126
5027
|
acall_func_with_variable_args(
|
|
@@ -5173,8 +5074,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5173
5074
|
async def atransform(
|
|
5174
5075
|
self,
|
|
5175
5076
|
input: AsyncIterator[Input],
|
|
5176
|
-
config:
|
|
5177
|
-
**kwargs:
|
|
5077
|
+
config: RunnableConfig | None = None,
|
|
5078
|
+
**kwargs: Any | None,
|
|
5178
5079
|
) -> AsyncIterator[Output]:
|
|
5179
5080
|
async for output in self._atransform_stream_with_config(
|
|
5180
5081
|
input,
|
|
@@ -5188,8 +5089,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
5188
5089
|
async def astream(
|
|
5189
5090
|
self,
|
|
5190
5091
|
input: Input,
|
|
5191
|
-
config:
|
|
5192
|
-
**kwargs:
|
|
5092
|
+
config: RunnableConfig | None = None,
|
|
5093
|
+
**kwargs: Any | None,
|
|
5193
5094
|
) -> AsyncIterator[Output]:
|
|
5194
5095
|
async def input_aiter() -> AsyncIterator[Input]:
|
|
5195
5096
|
yield input
|
|
@@ -5222,9 +5123,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5222
5123
|
return list[self.bound.InputType] # type: ignore[name-defined]
|
|
5223
5124
|
|
|
5224
5125
|
@override
|
|
5225
|
-
def get_input_schema(
|
|
5226
|
-
self, config: Optional[RunnableConfig] = None
|
|
5227
|
-
) -> type[BaseModel]:
|
|
5126
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
5228
5127
|
return create_model_v2(
|
|
5229
5128
|
self.get_name("Input"),
|
|
5230
5129
|
root=(
|
|
@@ -5248,7 +5147,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5248
5147
|
|
|
5249
5148
|
@override
|
|
5250
5149
|
def get_output_schema(
|
|
5251
|
-
self, config:
|
|
5150
|
+
self, config: RunnableConfig | None = None
|
|
5252
5151
|
) -> type[BaseModel]:
|
|
5253
5152
|
schema = self.bound.get_output_schema(config)
|
|
5254
5153
|
return create_model_v2(
|
|
@@ -5270,7 +5169,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5270
5169
|
return self.bound.config_specs
|
|
5271
5170
|
|
|
5272
5171
|
@override
|
|
5273
|
-
def get_graph(self, config:
|
|
5172
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
5274
5173
|
return self.bound.get_graph(config)
|
|
5275
5174
|
|
|
5276
5175
|
@classmethod
|
|
@@ -5303,7 +5202,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5303
5202
|
|
|
5304
5203
|
@override
|
|
5305
5204
|
def invoke(
|
|
5306
|
-
self, input: list[Input], config:
|
|
5205
|
+
self, input: list[Input], config: RunnableConfig | None = None, **kwargs: Any
|
|
5307
5206
|
) -> list[Output]:
|
|
5308
5207
|
return self._call_with_config(self._invoke, input, config, **kwargs)
|
|
5309
5208
|
|
|
@@ -5321,7 +5220,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5321
5220
|
|
|
5322
5221
|
@override
|
|
5323
5222
|
async def ainvoke(
|
|
5324
|
-
self, input: list[Input], config:
|
|
5223
|
+
self, input: list[Input], config: RunnableConfig | None = None, **kwargs: Any
|
|
5325
5224
|
) -> list[Output]:
|
|
5326
5225
|
return await self._acall_with_config(self._ainvoke, input, config, **kwargs)
|
|
5327
5226
|
|
|
@@ -5329,8 +5228,8 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
|
|
|
5329
5228
|
async def astream_events(
|
|
5330
5229
|
self,
|
|
5331
5230
|
input: Input,
|
|
5332
|
-
config:
|
|
5333
|
-
**kwargs:
|
|
5231
|
+
config: RunnableConfig | None = None,
|
|
5232
|
+
**kwargs: Any | None,
|
|
5334
5233
|
) -> AsyncIterator[StreamEvent]:
|
|
5335
5234
|
def _error_stream_event(message: str) -> StreamEvent:
|
|
5336
5235
|
raise NotImplementedError(message)
|
|
@@ -5352,29 +5251,27 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5352
5251
|
In the below example, we associate and run three inputs
|
|
5353
5252
|
with a ``Runnable``:
|
|
5354
5253
|
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
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
|
+
```
|
|
5372
5271
|
"""
|
|
5373
5272
|
|
|
5374
5273
|
@override
|
|
5375
|
-
def get_name(
|
|
5376
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
5377
|
-
) -> str:
|
|
5274
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
5378
5275
|
name = name or self.name or f"RunnableEach<{self.bound.get_name()}>"
|
|
5379
5276
|
return super().get_name(suffix, name=name)
|
|
5380
5277
|
|
|
@@ -5384,7 +5281,7 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5384
5281
|
|
|
5385
5282
|
@override
|
|
5386
5283
|
def with_config(
|
|
5387
|
-
self, config:
|
|
5284
|
+
self, config: RunnableConfig | None = None, **kwargs: Any
|
|
5388
5285
|
) -> RunnableEach[Input, Output]:
|
|
5389
5286
|
return RunnableEach(bound=self.bound.with_config(config, **kwargs))
|
|
5390
5287
|
|
|
@@ -5392,15 +5289,15 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5392
5289
|
def with_listeners(
|
|
5393
5290
|
self,
|
|
5394
5291
|
*,
|
|
5395
|
-
on_start:
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
on_end:
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
on_error:
|
|
5402
|
-
|
|
5403
|
-
|
|
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,
|
|
5404
5301
|
) -> RunnableEach[Input, Output]:
|
|
5405
5302
|
"""Bind lifecycle listeners to a ``Runnable``, returning a new ``Runnable``.
|
|
5406
5303
|
|
|
@@ -5429,9 +5326,9 @@ class RunnableEach(RunnableEachBase[Input, Output]):
|
|
|
5429
5326
|
def with_alisteners(
|
|
5430
5327
|
self,
|
|
5431
5328
|
*,
|
|
5432
|
-
on_start:
|
|
5433
|
-
on_end:
|
|
5434
|
-
on_error:
|
|
5329
|
+
on_start: AsyncListener | None = None,
|
|
5330
|
+
on_end: AsyncListener | None = None,
|
|
5331
|
+
on_error: AsyncListener | None = None,
|
|
5435
5332
|
) -> RunnableEach[Input, Output]:
|
|
5436
5333
|
"""Bind async lifecycle listeners to a ``Runnable``.
|
|
5437
5334
|
|
|
@@ -5491,13 +5388,13 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5491
5388
|
"""The config factories to bind to the underlying ``Runnable``."""
|
|
5492
5389
|
|
|
5493
5390
|
# Union[Type[Input], BaseModel] + things like list[str]
|
|
5494
|
-
custom_input_type:
|
|
5391
|
+
custom_input_type: Any | None = None
|
|
5495
5392
|
"""Override the input type of the underlying ``Runnable`` with a custom type.
|
|
5496
5393
|
|
|
5497
5394
|
The type can be a pydantic model, or a type annotation (e.g., ``list[str]``).
|
|
5498
5395
|
"""
|
|
5499
5396
|
# Union[Type[Output], BaseModel] + things like list[str]
|
|
5500
|
-
custom_output_type:
|
|
5397
|
+
custom_output_type: Any | None = None
|
|
5501
5398
|
"""Override the output type of the underlying ``Runnable`` with a custom type.
|
|
5502
5399
|
|
|
5503
5400
|
The type can be a pydantic model, or a type annotation (e.g., ``list[str]``).
|
|
@@ -5511,13 +5408,12 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5511
5408
|
self,
|
|
5512
5409
|
*,
|
|
5513
5410
|
bound: Runnable[Input, Output],
|
|
5514
|
-
kwargs:
|
|
5515
|
-
config:
|
|
5516
|
-
config_factories:
|
|
5517
|
-
|
|
5518
|
-
] = None,
|
|
5519
|
-
|
|
5520
|
-
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,
|
|
5521
5417
|
**other_kwargs: Any,
|
|
5522
5418
|
) -> None:
|
|
5523
5419
|
"""Create a ``RunnableBinding`` from a ``Runnable`` and kwargs.
|
|
@@ -5555,9 +5451,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5555
5451
|
self.config = config or {}
|
|
5556
5452
|
|
|
5557
5453
|
@override
|
|
5558
|
-
def get_name(
|
|
5559
|
-
self, suffix: Optional[str] = None, *, name: Optional[str] = None
|
|
5560
|
-
) -> str:
|
|
5454
|
+
def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
|
|
5561
5455
|
return self.bound.get_name(suffix, name=name)
|
|
5562
5456
|
|
|
5563
5457
|
@property
|
|
@@ -5579,16 +5473,14 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5579
5473
|
)
|
|
5580
5474
|
|
|
5581
5475
|
@override
|
|
5582
|
-
def get_input_schema(
|
|
5583
|
-
self, config: Optional[RunnableConfig] = None
|
|
5584
|
-
) -> type[BaseModel]:
|
|
5476
|
+
def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]:
|
|
5585
5477
|
if self.custom_input_type is not None:
|
|
5586
5478
|
return super().get_input_schema(config)
|
|
5587
5479
|
return self.bound.get_input_schema(merge_configs(self.config, config))
|
|
5588
5480
|
|
|
5589
5481
|
@override
|
|
5590
5482
|
def get_output_schema(
|
|
5591
|
-
self, config:
|
|
5483
|
+
self, config: RunnableConfig | None = None
|
|
5592
5484
|
) -> type[BaseModel]:
|
|
5593
5485
|
if self.custom_output_type is not None:
|
|
5594
5486
|
return super().get_output_schema(config)
|
|
@@ -5600,7 +5492,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5600
5492
|
return self.bound.config_specs
|
|
5601
5493
|
|
|
5602
5494
|
@override
|
|
5603
|
-
def get_graph(self, config:
|
|
5495
|
+
def get_graph(self, config: RunnableConfig | None = None) -> Graph:
|
|
5604
5496
|
return self.bound.get_graph(self._merge_configs(config))
|
|
5605
5497
|
|
|
5606
5498
|
@classmethod
|
|
@@ -5619,7 +5511,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5619
5511
|
"""
|
|
5620
5512
|
return ["langchain", "schema", "runnable"]
|
|
5621
5513
|
|
|
5622
|
-
def _merge_configs(self, *configs:
|
|
5514
|
+
def _merge_configs(self, *configs: RunnableConfig | None) -> RunnableConfig:
|
|
5623
5515
|
config = merge_configs(self.config, *configs)
|
|
5624
5516
|
return merge_configs(config, *(f(config) for f in self.config_factories))
|
|
5625
5517
|
|
|
@@ -5627,8 +5519,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5627
5519
|
def invoke(
|
|
5628
5520
|
self,
|
|
5629
5521
|
input: Input,
|
|
5630
|
-
config:
|
|
5631
|
-
**kwargs:
|
|
5522
|
+
config: RunnableConfig | None = None,
|
|
5523
|
+
**kwargs: Any | None,
|
|
5632
5524
|
) -> Output:
|
|
5633
5525
|
return self.bound.invoke(
|
|
5634
5526
|
input,
|
|
@@ -5640,8 +5532,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5640
5532
|
async def ainvoke(
|
|
5641
5533
|
self,
|
|
5642
5534
|
input: Input,
|
|
5643
|
-
config:
|
|
5644
|
-
**kwargs:
|
|
5535
|
+
config: RunnableConfig | None = None,
|
|
5536
|
+
**kwargs: Any | None,
|
|
5645
5537
|
) -> Output:
|
|
5646
5538
|
return await self.bound.ainvoke(
|
|
5647
5539
|
input,
|
|
@@ -5653,10 +5545,10 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5653
5545
|
def batch(
|
|
5654
5546
|
self,
|
|
5655
5547
|
inputs: list[Input],
|
|
5656
|
-
config:
|
|
5548
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
5657
5549
|
*,
|
|
5658
5550
|
return_exceptions: bool = False,
|
|
5659
|
-
**kwargs:
|
|
5551
|
+
**kwargs: Any | None,
|
|
5660
5552
|
) -> list[Output]:
|
|
5661
5553
|
if isinstance(config, list):
|
|
5662
5554
|
configs = cast(
|
|
@@ -5676,10 +5568,10 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5676
5568
|
async def abatch(
|
|
5677
5569
|
self,
|
|
5678
5570
|
inputs: list[Input],
|
|
5679
|
-
config:
|
|
5571
|
+
config: RunnableConfig | list[RunnableConfig] | None = None,
|
|
5680
5572
|
*,
|
|
5681
5573
|
return_exceptions: bool = False,
|
|
5682
|
-
**kwargs:
|
|
5574
|
+
**kwargs: Any | None,
|
|
5683
5575
|
) -> list[Output]:
|
|
5684
5576
|
if isinstance(config, list):
|
|
5685
5577
|
configs = cast(
|
|
@@ -5699,7 +5591,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5699
5591
|
def batch_as_completed(
|
|
5700
5592
|
self,
|
|
5701
5593
|
inputs: Sequence[Input],
|
|
5702
|
-
config:
|
|
5594
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5703
5595
|
*,
|
|
5704
5596
|
return_exceptions: Literal[False] = False,
|
|
5705
5597
|
**kwargs: Any,
|
|
@@ -5709,21 +5601,21 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5709
5601
|
def batch_as_completed(
|
|
5710
5602
|
self,
|
|
5711
5603
|
inputs: Sequence[Input],
|
|
5712
|
-
config:
|
|
5604
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5713
5605
|
*,
|
|
5714
5606
|
return_exceptions: Literal[True],
|
|
5715
5607
|
**kwargs: Any,
|
|
5716
|
-
) -> Iterator[tuple[int,
|
|
5608
|
+
) -> Iterator[tuple[int, Output | Exception]]: ...
|
|
5717
5609
|
|
|
5718
5610
|
@override
|
|
5719
5611
|
def batch_as_completed(
|
|
5720
5612
|
self,
|
|
5721
5613
|
inputs: Sequence[Input],
|
|
5722
|
-
config:
|
|
5614
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5723
5615
|
*,
|
|
5724
5616
|
return_exceptions: bool = False,
|
|
5725
|
-
**kwargs:
|
|
5726
|
-
) -> Iterator[tuple[int,
|
|
5617
|
+
**kwargs: Any | None,
|
|
5618
|
+
) -> Iterator[tuple[int, Output | Exception]]:
|
|
5727
5619
|
if isinstance(config, Sequence):
|
|
5728
5620
|
configs = cast(
|
|
5729
5621
|
"list[RunnableConfig]",
|
|
@@ -5751,31 +5643,31 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5751
5643
|
def abatch_as_completed(
|
|
5752
5644
|
self,
|
|
5753
5645
|
inputs: Sequence[Input],
|
|
5754
|
-
config:
|
|
5646
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5755
5647
|
*,
|
|
5756
5648
|
return_exceptions: Literal[False] = False,
|
|
5757
|
-
**kwargs:
|
|
5649
|
+
**kwargs: Any | None,
|
|
5758
5650
|
) -> AsyncIterator[tuple[int, Output]]: ...
|
|
5759
5651
|
|
|
5760
5652
|
@overload
|
|
5761
5653
|
def abatch_as_completed(
|
|
5762
5654
|
self,
|
|
5763
5655
|
inputs: Sequence[Input],
|
|
5764
|
-
config:
|
|
5656
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5765
5657
|
*,
|
|
5766
5658
|
return_exceptions: Literal[True],
|
|
5767
|
-
**kwargs:
|
|
5768
|
-
) -> AsyncIterator[tuple[int,
|
|
5659
|
+
**kwargs: Any | None,
|
|
5660
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]: ...
|
|
5769
5661
|
|
|
5770
5662
|
@override
|
|
5771
5663
|
async def abatch_as_completed(
|
|
5772
5664
|
self,
|
|
5773
5665
|
inputs: Sequence[Input],
|
|
5774
|
-
config:
|
|
5666
|
+
config: RunnableConfig | Sequence[RunnableConfig] | None = None,
|
|
5775
5667
|
*,
|
|
5776
5668
|
return_exceptions: bool = False,
|
|
5777
|
-
**kwargs:
|
|
5778
|
-
) -> AsyncIterator[tuple[int,
|
|
5669
|
+
**kwargs: Any | None,
|
|
5670
|
+
) -> AsyncIterator[tuple[int, Output | Exception]]:
|
|
5779
5671
|
if isinstance(config, Sequence):
|
|
5780
5672
|
configs = cast(
|
|
5781
5673
|
"list[RunnableConfig]",
|
|
@@ -5804,8 +5696,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5804
5696
|
def stream(
|
|
5805
5697
|
self,
|
|
5806
5698
|
input: Input,
|
|
5807
|
-
config:
|
|
5808
|
-
**kwargs:
|
|
5699
|
+
config: RunnableConfig | None = None,
|
|
5700
|
+
**kwargs: Any | None,
|
|
5809
5701
|
) -> Iterator[Output]:
|
|
5810
5702
|
yield from self.bound.stream(
|
|
5811
5703
|
input,
|
|
@@ -5817,8 +5709,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5817
5709
|
async def astream(
|
|
5818
5710
|
self,
|
|
5819
5711
|
input: Input,
|
|
5820
|
-
config:
|
|
5821
|
-
**kwargs:
|
|
5712
|
+
config: RunnableConfig | None = None,
|
|
5713
|
+
**kwargs: Any | None,
|
|
5822
5714
|
) -> AsyncIterator[Output]:
|
|
5823
5715
|
async for item in self.bound.astream(
|
|
5824
5716
|
input,
|
|
@@ -5831,8 +5723,8 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5831
5723
|
async def astream_events(
|
|
5832
5724
|
self,
|
|
5833
5725
|
input: Input,
|
|
5834
|
-
config:
|
|
5835
|
-
**kwargs:
|
|
5726
|
+
config: RunnableConfig | None = None,
|
|
5727
|
+
**kwargs: Any | None,
|
|
5836
5728
|
) -> AsyncIterator[StreamEvent]:
|
|
5837
5729
|
async for item in self.bound.astream_events(
|
|
5838
5730
|
input, self._merge_configs(config), **{**self.kwargs, **kwargs}
|
|
@@ -5843,7 +5735,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5843
5735
|
def transform(
|
|
5844
5736
|
self,
|
|
5845
5737
|
input: Iterator[Input],
|
|
5846
|
-
config:
|
|
5738
|
+
config: RunnableConfig | None = None,
|
|
5847
5739
|
**kwargs: Any,
|
|
5848
5740
|
) -> Iterator[Output]:
|
|
5849
5741
|
yield from self.bound.transform(
|
|
@@ -5856,7 +5748,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
|
|
|
5856
5748
|
async def atransform(
|
|
5857
5749
|
self,
|
|
5858
5750
|
input: AsyncIterator[Input],
|
|
5859
|
-
config:
|
|
5751
|
+
config: RunnableConfig | None = None,
|
|
5860
5752
|
**kwargs: Any,
|
|
5861
5753
|
) -> AsyncIterator[Output]:
|
|
5862
5754
|
async for item in self.bound.atransform(
|
|
@@ -5893,32 +5785,30 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5893
5785
|
Example:
|
|
5894
5786
|
`bind`: Bind kwargs to pass to the underlying ``Runnable`` when running it.
|
|
5895
5787
|
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
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
|
+
```
|
|
5909
5800
|
Can also be done by instantiating a ``RunnableBinding`` directly (not
|
|
5910
5801
|
recommended):
|
|
5911
5802
|
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
from langchain_core.runnables import RunnableBinding
|
|
5915
|
-
|
|
5916
|
-
runnable_binding = RunnableBinding(
|
|
5917
|
-
bound=model,
|
|
5918
|
-
kwargs={"stop": ["-"]}, # <-- Note the additional kwargs
|
|
5919
|
-
)
|
|
5920
|
-
runnable_binding.invoke('Say "Parrot-MAGIC"') # Should return `Parrot`
|
|
5803
|
+
```python
|
|
5804
|
+
from langchain_core.runnables import RunnableBinding
|
|
5921
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
|
+
```
|
|
5922
5812
|
"""
|
|
5923
5813
|
|
|
5924
5814
|
@override
|
|
@@ -5945,7 +5835,7 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5945
5835
|
@override
|
|
5946
5836
|
def with_config(
|
|
5947
5837
|
self,
|
|
5948
|
-
config:
|
|
5838
|
+
config: RunnableConfig | None = None,
|
|
5949
5839
|
# Sadly Unpack is not well supported by mypy so this will have to be untyped
|
|
5950
5840
|
**kwargs: Any,
|
|
5951
5841
|
) -> Runnable[Input, Output]:
|
|
@@ -5962,15 +5852,15 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
5962
5852
|
def with_listeners(
|
|
5963
5853
|
self,
|
|
5964
5854
|
*,
|
|
5965
|
-
on_start:
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
on_end:
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
on_error:
|
|
5972
|
-
|
|
5973
|
-
|
|
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,
|
|
5974
5864
|
) -> Runnable[Input, Output]:
|
|
5975
5865
|
"""Bind lifecycle listeners to a ``Runnable``, returning a new ``Runnable``.
|
|
5976
5866
|
|
|
@@ -6014,8 +5904,8 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
|
|
|
6014
5904
|
@override
|
|
6015
5905
|
def with_types(
|
|
6016
5906
|
self,
|
|
6017
|
-
input_type:
|
|
6018
|
-
output_type:
|
|
5907
|
+
input_type: type[Input] | BaseModel | None = None,
|
|
5908
|
+
output_type: type[Output] | BaseModel | None = None,
|
|
6019
5909
|
) -> Runnable[Input, Output]:
|
|
6020
5910
|
return self.__class__(
|
|
6021
5911
|
bound=self.bound,
|
|
@@ -6099,18 +5989,18 @@ class _RunnableCallableAsyncIterator(Protocol[Input, Output]):
|
|
|
6099
5989
|
) -> AsyncIterator[Output]: ...
|
|
6100
5990
|
|
|
6101
5991
|
|
|
6102
|
-
RunnableLike =
|
|
6103
|
-
Runnable[Input, Output]
|
|
6104
|
-
Callable[[Input], Output]
|
|
6105
|
-
Callable[[Input], Awaitable[Output]]
|
|
6106
|
-
Callable[[Iterator[Input]], Iterator[Output]]
|
|
6107
|
-
Callable[[AsyncIterator[Input]], AsyncIterator[Output]]
|
|
6108
|
-
_RunnableCallableSync[Input, Output]
|
|
6109
|
-
_RunnableCallableAsync[Input, Output]
|
|
6110
|
-
_RunnableCallableIterator[Input, Output]
|
|
6111
|
-
_RunnableCallableAsyncIterator[Input, Output]
|
|
6112
|
-
Mapping[str, Any]
|
|
6113
|
-
|
|
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
|
+
)
|
|
6114
6004
|
|
|
6115
6005
|
|
|
6116
6006
|
def coerce_to_runnable(thing: RunnableLike) -> Runnable[Input, Output]:
|
|
@@ -6165,12 +6055,10 @@ def chain(
|
|
|
6165
6055
|
|
|
6166
6056
|
|
|
6167
6057
|
def chain(
|
|
6168
|
-
func:
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
Callable[[Input], AsyncIterator[Output]],
|
|
6173
|
-
],
|
|
6058
|
+
func: Callable[[Input], Output]
|
|
6059
|
+
| Callable[[Input], Iterator[Output]]
|
|
6060
|
+
| Callable[[Input], Coroutine[Any, Any, Output]]
|
|
6061
|
+
| Callable[[Input], AsyncIterator[Output]],
|
|
6174
6062
|
) -> Runnable[Input, Output]:
|
|
6175
6063
|
"""Decorate a function to make it a ``Runnable``.
|
|
6176
6064
|
|
|
@@ -6184,9 +6072,7 @@ def chain(
|
|
|
6184
6072
|
A ``Runnable``.
|
|
6185
6073
|
|
|
6186
6074
|
Example:
|
|
6187
|
-
|
|
6188
|
-
.. code-block:: python
|
|
6189
|
-
|
|
6075
|
+
```python
|
|
6190
6076
|
from langchain_core.runnables import chain
|
|
6191
6077
|
from langchain_core.prompts import PromptTemplate
|
|
6192
6078
|
from langchain_openai import OpenAI
|
|
@@ -6200,6 +6086,6 @@ def chain(
|
|
|
6200
6086
|
|
|
6201
6087
|
for chunk in llm.stream(formatted):
|
|
6202
6088
|
yield chunk
|
|
6203
|
-
|
|
6089
|
+
```
|
|
6204
6090
|
"""
|
|
6205
6091
|
return RunnableLambda(func)
|