langchain-core 1.0.3__py3-none-any.whl → 1.0.4__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.
- langchain_core/agents.py +36 -27
- langchain_core/callbacks/manager.py +18 -1
- langchain_core/callbacks/usage.py +2 -2
- langchain_core/documents/base.py +6 -6
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/indexing/api.py +6 -6
- langchain_core/language_models/_utils.py +1 -1
- langchain_core/language_models/base.py +37 -18
- langchain_core/language_models/chat_models.py +44 -28
- langchain_core/language_models/llms.py +66 -36
- langchain_core/messages/ai.py +3 -3
- langchain_core/messages/base.py +1 -1
- langchain_core/messages/content.py +2 -2
- langchain_core/messages/utils.py +12 -8
- langchain_core/output_parsers/openai_tools.py +14 -2
- langchain_core/outputs/generation.py +6 -5
- langchain_core/prompt_values.py +2 -2
- langchain_core/prompts/base.py +47 -44
- langchain_core/prompts/chat.py +35 -28
- langchain_core/prompts/dict.py +1 -1
- langchain_core/prompts/message.py +4 -4
- langchain_core/runnables/base.py +97 -52
- langchain_core/runnables/branch.py +22 -20
- langchain_core/runnables/configurable.py +30 -29
- langchain_core/runnables/fallbacks.py +22 -20
- langchain_core/runnables/graph_mermaid.py +4 -1
- langchain_core/runnables/graph_png.py +28 -0
- langchain_core/runnables/history.py +43 -32
- langchain_core/runnables/passthrough.py +35 -25
- langchain_core/runnables/router.py +5 -5
- langchain_core/runnables/schema.py +1 -1
- langchain_core/sys_info.py +4 -2
- langchain_core/tools/base.py +22 -16
- langchain_core/utils/function_calling.py +9 -6
- langchain_core/utils/input.py +3 -0
- langchain_core/utils/pydantic.py +2 -2
- langchain_core/version.py +1 -1
- {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/METADATA +1 -1
- {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/RECORD +40 -40
- {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/WHEEL +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""`Runnable` objects that can be dynamically configured."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -47,14 +47,14 @@ if TYPE_CHECKING:
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
50
|
-
"""Serializable Runnable that can be dynamically configured.
|
|
50
|
+
"""Serializable `Runnable` that can be dynamically configured.
|
|
51
51
|
|
|
52
|
-
A DynamicRunnable should be initiated using the `configurable_fields` or
|
|
53
|
-
`configurable_alternatives` method of a Runnable
|
|
52
|
+
A `DynamicRunnable` should be initiated using the `configurable_fields` or
|
|
53
|
+
`configurable_alternatives` method of a `Runnable`.
|
|
54
54
|
"""
|
|
55
55
|
|
|
56
56
|
default: RunnableSerializable[Input, Output]
|
|
57
|
-
"""The default Runnable to use."""
|
|
57
|
+
"""The default `Runnable` to use."""
|
|
58
58
|
|
|
59
59
|
config: RunnableConfig | None = None
|
|
60
60
|
"""The configuration to use."""
|
|
@@ -66,7 +66,7 @@ class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
|
66
66
|
@classmethod
|
|
67
67
|
@override
|
|
68
68
|
def is_lc_serializable(cls) -> bool:
|
|
69
|
-
"""Return True as this class is serializable."""
|
|
69
|
+
"""Return `True` as this class is serializable."""
|
|
70
70
|
return True
|
|
71
71
|
|
|
72
72
|
@classmethod
|
|
@@ -120,13 +120,13 @@ class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
|
120
120
|
def prepare(
|
|
121
121
|
self, config: RunnableConfig | None = None
|
|
122
122
|
) -> tuple[Runnable[Input, Output], RunnableConfig]:
|
|
123
|
-
"""Prepare the Runnable for invocation.
|
|
123
|
+
"""Prepare the `Runnable` for invocation.
|
|
124
124
|
|
|
125
125
|
Args:
|
|
126
126
|
config: The configuration to use.
|
|
127
127
|
|
|
128
128
|
Returns:
|
|
129
|
-
The prepared Runnable and configuration.
|
|
129
|
+
The prepared `Runnable` and configuration.
|
|
130
130
|
"""
|
|
131
131
|
runnable: Runnable[Input, Output] = self
|
|
132
132
|
while isinstance(runnable, DynamicRunnable):
|
|
@@ -316,12 +316,12 @@ class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
|
316
316
|
|
|
317
317
|
|
|
318
318
|
class RunnableConfigurableFields(DynamicRunnable[Input, Output]):
|
|
319
|
-
"""Runnable that can be dynamically configured.
|
|
319
|
+
"""`Runnable` that can be dynamically configured.
|
|
320
320
|
|
|
321
|
-
A RunnableConfigurableFields should be initiated using the
|
|
322
|
-
`configurable_fields` method of a Runnable
|
|
321
|
+
A `RunnableConfigurableFields` should be initiated using the
|
|
322
|
+
`configurable_fields` method of a `Runnable`.
|
|
323
323
|
|
|
324
|
-
Here is an example of using a RunnableConfigurableFields with LLMs:
|
|
324
|
+
Here is an example of using a `RunnableConfigurableFields` with LLMs:
|
|
325
325
|
|
|
326
326
|
```python
|
|
327
327
|
from langchain_core.prompts import PromptTemplate
|
|
@@ -348,7 +348,7 @@ class RunnableConfigurableFields(DynamicRunnable[Input, Output]):
|
|
|
348
348
|
chain.invoke({"x": 0}, config={"configurable": {"temperature": 0.9}})
|
|
349
349
|
```
|
|
350
350
|
|
|
351
|
-
Here is an example of using a RunnableConfigurableFields with HubRunnables
|
|
351
|
+
Here is an example of using a `RunnableConfigurableFields` with `HubRunnables`:
|
|
352
352
|
|
|
353
353
|
```python
|
|
354
354
|
from langchain_core.prompts import PromptTemplate
|
|
@@ -380,7 +380,7 @@ class RunnableConfigurableFields(DynamicRunnable[Input, Output]):
|
|
|
380
380
|
|
|
381
381
|
@property
|
|
382
382
|
def config_specs(self) -> list[ConfigurableFieldSpec]:
|
|
383
|
-
"""Get the configuration specs for the RunnableConfigurableFields
|
|
383
|
+
"""Get the configuration specs for the `RunnableConfigurableFields`.
|
|
384
384
|
|
|
385
385
|
Returns:
|
|
386
386
|
The configuration specs.
|
|
@@ -473,10 +473,10 @@ _enums_for_spec_lock = threading.Lock()
|
|
|
473
473
|
|
|
474
474
|
|
|
475
475
|
class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
476
|
-
"""Runnable that can be dynamically configured.
|
|
476
|
+
"""`Runnable` that can be dynamically configured.
|
|
477
477
|
|
|
478
478
|
A `RunnableConfigurableAlternatives` should be initiated using the
|
|
479
|
-
`configurable_alternatives` method of a Runnable or can be
|
|
479
|
+
`configurable_alternatives` method of a `Runnable` or can be
|
|
480
480
|
initiated directly as well.
|
|
481
481
|
|
|
482
482
|
Here is an example of using a `RunnableConfigurableAlternatives` that uses
|
|
@@ -531,7 +531,7 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
531
531
|
"""
|
|
532
532
|
|
|
533
533
|
which: ConfigurableField
|
|
534
|
-
"""The ConfigurableField to use to choose between alternatives."""
|
|
534
|
+
"""The `ConfigurableField` to use to choose between alternatives."""
|
|
535
535
|
|
|
536
536
|
alternatives: dict[
|
|
537
537
|
str,
|
|
@@ -544,8 +544,9 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
544
544
|
|
|
545
545
|
prefix_keys: bool
|
|
546
546
|
"""Whether to prefix configurable fields of each alternative with a namespace
|
|
547
|
-
of the form <which.id>==<alternative_key>,
|
|
548
|
-
the alternative named "gpt3" becomes "model==gpt3/temperature".
|
|
547
|
+
of the form <which.id>==<alternative_key>, e.g. a key named "temperature" used by
|
|
548
|
+
the alternative named "gpt3" becomes "model==gpt3/temperature".
|
|
549
|
+
"""
|
|
549
550
|
|
|
550
551
|
@property
|
|
551
552
|
@override
|
|
@@ -638,24 +639,24 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
638
639
|
|
|
639
640
|
|
|
640
641
|
def _strremoveprefix(s: str, prefix: str) -> str:
|
|
641
|
-
"""str.removeprefix() is only available in Python 3.9+."""
|
|
642
|
+
"""`str.removeprefix()` is only available in Python 3.9+."""
|
|
642
643
|
return s.replace(prefix, "", 1) if s.startswith(prefix) else s
|
|
643
644
|
|
|
644
645
|
|
|
645
646
|
def prefix_config_spec(
|
|
646
647
|
spec: ConfigurableFieldSpec, prefix: str
|
|
647
648
|
) -> ConfigurableFieldSpec:
|
|
648
|
-
"""Prefix the id of a ConfigurableFieldSpec
|
|
649
|
+
"""Prefix the id of a `ConfigurableFieldSpec`.
|
|
649
650
|
|
|
650
|
-
This is useful when a RunnableConfigurableAlternatives is used as a
|
|
651
|
-
ConfigurableField of another RunnableConfigurableAlternatives
|
|
651
|
+
This is useful when a `RunnableConfigurableAlternatives` is used as a
|
|
652
|
+
`ConfigurableField` of another `RunnableConfigurableAlternatives`.
|
|
652
653
|
|
|
653
654
|
Args:
|
|
654
|
-
spec: The ConfigurableFieldSpec to prefix.
|
|
655
|
+
spec: The `ConfigurableFieldSpec` to prefix.
|
|
655
656
|
prefix: The prefix to add.
|
|
656
657
|
|
|
657
658
|
Returns:
|
|
658
|
-
The prefixed ConfigurableFieldSpec
|
|
659
|
+
The prefixed `ConfigurableFieldSpec`.
|
|
659
660
|
"""
|
|
660
661
|
return (
|
|
661
662
|
ConfigurableFieldSpec(
|
|
@@ -677,15 +678,15 @@ def make_options_spec(
|
|
|
677
678
|
) -> ConfigurableFieldSpec:
|
|
678
679
|
"""Make options spec.
|
|
679
680
|
|
|
680
|
-
Make a ConfigurableFieldSpec for a ConfigurableFieldSingleOption or
|
|
681
|
-
ConfigurableFieldMultiOption
|
|
681
|
+
Make a `ConfigurableFieldSpec` for a `ConfigurableFieldSingleOption` or
|
|
682
|
+
`ConfigurableFieldMultiOption`.
|
|
682
683
|
|
|
683
684
|
Args:
|
|
684
|
-
spec: The ConfigurableFieldSingleOption or ConfigurableFieldMultiOption
|
|
685
|
+
spec: The `ConfigurableFieldSingleOption` or `ConfigurableFieldMultiOption`.
|
|
685
686
|
description: The description to use if the spec does not have one.
|
|
686
687
|
|
|
687
688
|
Returns:
|
|
688
|
-
The ConfigurableFieldSpec
|
|
689
|
+
The `ConfigurableFieldSpec`.
|
|
689
690
|
"""
|
|
690
691
|
with _enums_for_spec_lock:
|
|
691
692
|
if enum := _enums_for_spec.get(spec):
|
|
@@ -35,20 +35,20 @@ if TYPE_CHECKING:
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
38
|
-
"""Runnable that can fallback to other
|
|
38
|
+
"""`Runnable` that can fallback to other `Runnable`s if it fails.
|
|
39
39
|
|
|
40
40
|
External APIs (e.g., APIs for a language model) may at times experience
|
|
41
41
|
degraded performance or even downtime.
|
|
42
42
|
|
|
43
|
-
In these cases, it can be useful to have a fallback Runnable that can be
|
|
44
|
-
used in place of the original Runnable (e.g., fallback to another LLM provider).
|
|
43
|
+
In these cases, it can be useful to have a fallback `Runnable` that can be
|
|
44
|
+
used in place of the original `Runnable` (e.g., fallback to another LLM provider).
|
|
45
45
|
|
|
46
|
-
Fallbacks can be defined at the level of a single Runnable
|
|
47
|
-
of a chain of
|
|
46
|
+
Fallbacks can be defined at the level of a single `Runnable`, or at the level
|
|
47
|
+
of a chain of `Runnable`s. Fallbacks are tried in order until one succeeds or
|
|
48
48
|
all fail.
|
|
49
49
|
|
|
50
50
|
While you can instantiate a `RunnableWithFallbacks` directly, it is usually
|
|
51
|
-
more convenient to use the `with_fallbacks` method on a Runnable
|
|
51
|
+
more convenient to use the `with_fallbacks` method on a `Runnable`.
|
|
52
52
|
|
|
53
53
|
Example:
|
|
54
54
|
```python
|
|
@@ -87,7 +87,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
87
87
|
"""
|
|
88
88
|
|
|
89
89
|
runnable: Runnable[Input, Output]
|
|
90
|
-
"""The Runnable to run first."""
|
|
90
|
+
"""The `Runnable` to run first."""
|
|
91
91
|
fallbacks: Sequence[Runnable[Input, Output]]
|
|
92
92
|
"""A sequence of fallbacks to try."""
|
|
93
93
|
exceptions_to_handle: tuple[type[BaseException], ...] = (Exception,)
|
|
@@ -97,9 +97,12 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
97
97
|
"""
|
|
98
98
|
exception_key: str | None = None
|
|
99
99
|
"""If `string` is specified then handled exceptions will be passed to fallbacks as
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
part of the input under the specified key.
|
|
101
|
+
|
|
102
|
+
If `None`, exceptions will not be passed to fallbacks.
|
|
103
|
+
|
|
104
|
+
If used, the base `Runnable` and its fallbacks must accept a dictionary as input.
|
|
105
|
+
"""
|
|
103
106
|
|
|
104
107
|
model_config = ConfigDict(
|
|
105
108
|
arbitrary_types_allowed=True,
|
|
@@ -137,7 +140,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
137
140
|
@classmethod
|
|
138
141
|
@override
|
|
139
142
|
def is_lc_serializable(cls) -> bool:
|
|
140
|
-
"""Return True as this class is serializable."""
|
|
143
|
+
"""Return `True` as this class is serializable."""
|
|
141
144
|
return True
|
|
142
145
|
|
|
143
146
|
@classmethod
|
|
@@ -152,10 +155,10 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
152
155
|
|
|
153
156
|
@property
|
|
154
157
|
def runnables(self) -> Iterator[Runnable[Input, Output]]:
|
|
155
|
-
"""Iterator over the Runnable and its fallbacks.
|
|
158
|
+
"""Iterator over the `Runnable` and its fallbacks.
|
|
156
159
|
|
|
157
160
|
Yields:
|
|
158
|
-
The Runnable then its fallbacks.
|
|
161
|
+
The `Runnable` then its fallbacks.
|
|
159
162
|
"""
|
|
160
163
|
yield self.runnable
|
|
161
164
|
yield from self.fallbacks
|
|
@@ -589,14 +592,14 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
589
592
|
await run_manager.on_chain_end(output)
|
|
590
593
|
|
|
591
594
|
def __getattr__(self, name: str) -> Any:
|
|
592
|
-
"""Get an attribute from the wrapped Runnable and its fallbacks.
|
|
595
|
+
"""Get an attribute from the wrapped `Runnable` and its fallbacks.
|
|
593
596
|
|
|
594
597
|
Returns:
|
|
595
|
-
If the attribute is anything other than a method that outputs a Runnable
|
|
596
|
-
returns getattr(self.runnable, name)
|
|
597
|
-
does return a new Runnable (e.g. model.bind_tools([...]) outputs a new
|
|
598
|
-
RunnableBinding) then self.runnable and each of the runnables in
|
|
599
|
-
self.fallbacks is replaced with getattr(x, name)
|
|
598
|
+
If the attribute is anything other than a method that outputs a `Runnable`,
|
|
599
|
+
returns `getattr(self.runnable, name)`. If the attribute is a method that
|
|
600
|
+
does return a new `Runnable` (e.g. `model.bind_tools([...])` outputs a new
|
|
601
|
+
`RunnableBinding`) then `self.runnable` and each of the runnables in
|
|
602
|
+
`self.fallbacks` is replaced with `getattr(x, name)`.
|
|
600
603
|
|
|
601
604
|
Example:
|
|
602
605
|
```python
|
|
@@ -618,7 +621,6 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
618
621
|
runnable=RunnableBinding(bound=ChatOpenAI(...), kwargs={"tools": [...]}),
|
|
619
622
|
fallbacks=[RunnableBinding(bound=ChatAnthropic(...), kwargs={"tools": [...]})],
|
|
620
623
|
)
|
|
621
|
-
|
|
622
624
|
```
|
|
623
625
|
""" # noqa: E501
|
|
624
626
|
attr = getattr(self.runnable, name)
|
|
@@ -454,7 +454,10 @@ def _render_mermaid_using_api(
|
|
|
454
454
|
return img_bytes
|
|
455
455
|
|
|
456
456
|
# If we get a server error (5xx), retry
|
|
457
|
-
if
|
|
457
|
+
if (
|
|
458
|
+
requests.codes.internal_server_error <= response.status_code
|
|
459
|
+
and attempt < max_retries
|
|
460
|
+
):
|
|
458
461
|
# Exponential backoff with jitter
|
|
459
462
|
sleep_time = retry_delay * (2**attempt) * (0.5 + 0.5 * random.random()) # noqa: S311 not used for crypto
|
|
460
463
|
time.sleep(sleep_time)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Helper class to draw a state graph into a PNG file."""
|
|
2
2
|
|
|
3
|
+
from itertools import groupby
|
|
3
4
|
from typing import Any
|
|
4
5
|
|
|
5
6
|
from langchain_core.runnables.graph import Graph, LabelsDict
|
|
@@ -141,6 +142,7 @@ class PngDrawer:
|
|
|
141
142
|
# Add nodes, conditional edges, and edges to the graph
|
|
142
143
|
self.add_nodes(viz, graph)
|
|
143
144
|
self.add_edges(viz, graph)
|
|
145
|
+
self.add_subgraph(viz, [node.split(":") for node in graph.nodes])
|
|
144
146
|
|
|
145
147
|
# Update entrypoint and END styles
|
|
146
148
|
self.update_styles(viz, graph)
|
|
@@ -161,6 +163,32 @@ class PngDrawer:
|
|
|
161
163
|
for node in graph.nodes:
|
|
162
164
|
self.add_node(viz, node)
|
|
163
165
|
|
|
166
|
+
def add_subgraph(
|
|
167
|
+
self,
|
|
168
|
+
viz: Any,
|
|
169
|
+
nodes: list[list[str]],
|
|
170
|
+
parent_prefix: list[str] | None = None,
|
|
171
|
+
) -> None:
|
|
172
|
+
"""Add subgraphs to the graph.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
viz: The graphviz object.
|
|
176
|
+
nodes: The nodes to add.
|
|
177
|
+
parent_prefix: The prefix of the parent subgraph.
|
|
178
|
+
"""
|
|
179
|
+
for prefix, grouped in groupby(
|
|
180
|
+
[node[:] for node in sorted(nodes)],
|
|
181
|
+
key=lambda x: x.pop(0),
|
|
182
|
+
):
|
|
183
|
+
current_prefix = (parent_prefix or []) + [prefix]
|
|
184
|
+
grouped_nodes = list(grouped)
|
|
185
|
+
if len(grouped_nodes) > 1:
|
|
186
|
+
subgraph = viz.add_subgraph(
|
|
187
|
+
[":".join(current_prefix + node) for node in grouped_nodes],
|
|
188
|
+
name="cluster_" + ":".join(current_prefix),
|
|
189
|
+
)
|
|
190
|
+
self.add_subgraph(subgraph, grouped_nodes, current_prefix)
|
|
191
|
+
|
|
164
192
|
def add_edges(self, viz: Any, graph: Graph) -> None:
|
|
165
193
|
"""Add edges to the graph.
|
|
166
194
|
|
|
@@ -36,23 +36,23 @@ GetSessionHistoryCallable = Callable[..., BaseChatMessageHistory]
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
39
|
-
"""Runnable that manages chat message history for another Runnable
|
|
39
|
+
"""`Runnable` that manages chat message history for another `Runnable`.
|
|
40
40
|
|
|
41
41
|
A chat message history is a sequence of messages that represent a conversation.
|
|
42
42
|
|
|
43
|
-
RunnableWithMessageHistory wraps another Runnable and manages the chat message
|
|
43
|
+
`RunnableWithMessageHistory` wraps another `Runnable` and manages the chat message
|
|
44
44
|
history for it; it is responsible for reading and updating the chat message
|
|
45
45
|
history.
|
|
46
46
|
|
|
47
|
-
The formats supported for the inputs and outputs of the wrapped Runnable
|
|
47
|
+
The formats supported for the inputs and outputs of the wrapped `Runnable`
|
|
48
48
|
are described below.
|
|
49
49
|
|
|
50
|
-
RunnableWithMessageHistory must always be called with a config that contains
|
|
50
|
+
`RunnableWithMessageHistory` must always be called with a config that contains
|
|
51
51
|
the appropriate parameters for the chat message history factory.
|
|
52
52
|
|
|
53
|
-
By default, the Runnable is expected to take a single configuration parameter
|
|
53
|
+
By default, the `Runnable` is expected to take a single configuration parameter
|
|
54
54
|
called `session_id` which is a string. This parameter is used to create a new
|
|
55
|
-
or look up an existing chat message history that matches the given session_id
|
|
55
|
+
or look up an existing chat message history that matches the given `session_id`.
|
|
56
56
|
|
|
57
57
|
In this case, the invocation would look like this:
|
|
58
58
|
|
|
@@ -117,12 +117,12 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
117
117
|
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
-
Example where the wrapped Runnable takes a dictionary input:
|
|
120
|
+
Example where the wrapped `Runnable` takes a dictionary input:
|
|
121
121
|
|
|
122
122
|
```python
|
|
123
123
|
from typing import Optional
|
|
124
124
|
|
|
125
|
-
from
|
|
125
|
+
from langchain_anthropic import ChatAnthropic
|
|
126
126
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
|
127
127
|
from langchain_core.runnables.history import RunnableWithMessageHistory
|
|
128
128
|
|
|
@@ -166,7 +166,7 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
166
166
|
print(store) # noqa: T201
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
-
Example where the session factory takes two keys
|
|
169
|
+
Example where the session factory takes two keys (`user_id` and `conversation_id`):
|
|
170
170
|
|
|
171
171
|
```python
|
|
172
172
|
store = {}
|
|
@@ -223,21 +223,28 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
223
223
|
"""
|
|
224
224
|
|
|
225
225
|
get_session_history: GetSessionHistoryCallable
|
|
226
|
-
"""Function that returns a new BaseChatMessageHistory
|
|
226
|
+
"""Function that returns a new `BaseChatMessageHistory`.
|
|
227
|
+
|
|
227
228
|
This function should either take a single positional argument `session_id` of type
|
|
228
|
-
string and return a corresponding chat message history instance
|
|
229
|
+
string and return a corresponding chat message history instance
|
|
230
|
+
"""
|
|
229
231
|
input_messages_key: str | None = None
|
|
230
|
-
"""Must be specified if the base
|
|
231
|
-
The key in the input dict that contains the messages.
|
|
232
|
+
"""Must be specified if the base `Runnable` accepts a `dict` as input.
|
|
233
|
+
The key in the input `dict` that contains the messages.
|
|
234
|
+
"""
|
|
232
235
|
output_messages_key: str | None = None
|
|
233
|
-
"""Must be specified if the base Runnable returns a dict as output.
|
|
234
|
-
The key in the output dict that contains the messages.
|
|
236
|
+
"""Must be specified if the base `Runnable` returns a `dict` as output.
|
|
237
|
+
The key in the output `dict` that contains the messages.
|
|
238
|
+
"""
|
|
235
239
|
history_messages_key: str | None = None
|
|
236
|
-
"""Must be specified if the base
|
|
237
|
-
separate key for historical messages.
|
|
240
|
+
"""Must be specified if the base `Runnable` accepts a `dict` as input and expects a
|
|
241
|
+
separate key for historical messages.
|
|
242
|
+
"""
|
|
238
243
|
history_factory_config: Sequence[ConfigurableFieldSpec]
|
|
239
244
|
"""Configure fields that should be passed to the chat history factory.
|
|
240
|
-
|
|
245
|
+
|
|
246
|
+
See `ConfigurableFieldSpec` for more details.
|
|
247
|
+
"""
|
|
241
248
|
|
|
242
249
|
def __init__(
|
|
243
250
|
self,
|
|
@@ -254,15 +261,16 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
254
261
|
history_factory_config: Sequence[ConfigurableFieldSpec] | None = None,
|
|
255
262
|
**kwargs: Any,
|
|
256
263
|
) -> None:
|
|
257
|
-
"""Initialize RunnableWithMessageHistory
|
|
264
|
+
"""Initialize `RunnableWithMessageHistory`.
|
|
258
265
|
|
|
259
266
|
Args:
|
|
260
|
-
runnable: The base Runnable to be wrapped.
|
|
267
|
+
runnable: The base `Runnable` to be wrapped.
|
|
268
|
+
|
|
261
269
|
Must take as input one of:
|
|
262
270
|
|
|
263
271
|
1. A list of `BaseMessage`
|
|
264
|
-
2. A dict with one key for all messages
|
|
265
|
-
3. A dict with one key for the current input string/message(s) and
|
|
272
|
+
2. A `dict` with one key for all messages
|
|
273
|
+
3. A `dict` with one key for the current input string/message(s) and
|
|
266
274
|
a separate key for historical messages. If the input key points
|
|
267
275
|
to a string, it will be treated as a `HumanMessage` in history.
|
|
268
276
|
|
|
@@ -270,13 +278,15 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
270
278
|
|
|
271
279
|
1. A string which can be treated as an `AIMessage`
|
|
272
280
|
2. A `BaseMessage` or sequence of `BaseMessage`
|
|
273
|
-
3. A dict with a key for a `BaseMessage` or sequence of
|
|
281
|
+
3. A `dict` with a key for a `BaseMessage` or sequence of
|
|
274
282
|
`BaseMessage`
|
|
275
283
|
|
|
276
|
-
get_session_history: Function that returns a new BaseChatMessageHistory
|
|
284
|
+
get_session_history: Function that returns a new `BaseChatMessageHistory`.
|
|
285
|
+
|
|
277
286
|
This function should either take a single positional argument
|
|
278
287
|
`session_id` of type string and return a corresponding
|
|
279
288
|
chat message history instance.
|
|
289
|
+
|
|
280
290
|
```python
|
|
281
291
|
def get_session_history(
|
|
282
292
|
session_id: str, *, user_id: str | None = None
|
|
@@ -295,16 +305,17 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
295
305
|
) -> BaseChatMessageHistory: ...
|
|
296
306
|
```
|
|
297
307
|
|
|
298
|
-
input_messages_key: Must be specified if the base runnable accepts a dict
|
|
308
|
+
input_messages_key: Must be specified if the base runnable accepts a `dict`
|
|
299
309
|
as input.
|
|
300
|
-
output_messages_key: Must be specified if the base runnable returns a dict
|
|
310
|
+
output_messages_key: Must be specified if the base runnable returns a `dict`
|
|
301
311
|
as output.
|
|
302
|
-
history_messages_key: Must be specified if the base runnable accepts a
|
|
303
|
-
as input and expects a separate key for historical messages.
|
|
312
|
+
history_messages_key: Must be specified if the base runnable accepts a
|
|
313
|
+
`dict` as input and expects a separate key for historical messages.
|
|
304
314
|
history_factory_config: Configure fields that should be passed to the
|
|
305
315
|
chat history factory. See `ConfigurableFieldSpec` for more details.
|
|
306
|
-
|
|
307
|
-
into the
|
|
316
|
+
|
|
317
|
+
Specifying these allows you to pass multiple config keys into the
|
|
318
|
+
`get_session_history` factory.
|
|
308
319
|
**kwargs: Arbitrary additional kwargs to pass to parent class
|
|
309
320
|
`RunnableBindingBase` init.
|
|
310
321
|
|
|
@@ -364,7 +375,7 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
364
375
|
@property
|
|
365
376
|
@override
|
|
366
377
|
def config_specs(self) -> list[ConfigurableFieldSpec]:
|
|
367
|
-
"""Get the configuration specs for the RunnableWithMessageHistory
|
|
378
|
+
"""Get the configuration specs for the `RunnableWithMessageHistory`."""
|
|
368
379
|
return get_unique_config_specs(
|
|
369
380
|
super().config_specs + list(self.history_factory_config)
|
|
370
381
|
)
|
|
@@ -606,6 +617,6 @@ class RunnableWithMessageHistory(RunnableBindingBase): # type: ignore[no-redef]
|
|
|
606
617
|
|
|
607
618
|
|
|
608
619
|
def _get_parameter_names(callable_: GetSessionHistoryCallable) -> list[str]:
|
|
609
|
-
"""Get the parameter names of the
|
|
620
|
+
"""Get the parameter names of the `Callable`."""
|
|
610
621
|
sig = inspect.signature(callable_)
|
|
611
622
|
return list(sig.parameters.keys())
|
|
@@ -51,10 +51,10 @@ def identity(x: Other) -> Other:
|
|
|
51
51
|
"""Identity function.
|
|
52
52
|
|
|
53
53
|
Args:
|
|
54
|
-
x:
|
|
54
|
+
x: Input.
|
|
55
55
|
|
|
56
56
|
Returns:
|
|
57
|
-
|
|
57
|
+
Output.
|
|
58
58
|
"""
|
|
59
59
|
return x
|
|
60
60
|
|
|
@@ -63,10 +63,10 @@ async def aidentity(x: Other) -> Other:
|
|
|
63
63
|
"""Async identity function.
|
|
64
64
|
|
|
65
65
|
Args:
|
|
66
|
-
x:
|
|
66
|
+
x: Input.
|
|
67
67
|
|
|
68
68
|
Returns:
|
|
69
|
-
|
|
69
|
+
Output.
|
|
70
70
|
"""
|
|
71
71
|
return x
|
|
72
72
|
|
|
@@ -74,11 +74,11 @@ async def aidentity(x: Other) -> Other:
|
|
|
74
74
|
class RunnablePassthrough(RunnableSerializable[Other, Other]):
|
|
75
75
|
"""Runnable to passthrough inputs unchanged or with additional keys.
|
|
76
76
|
|
|
77
|
-
This Runnable behaves almost like the identity function, except that it
|
|
77
|
+
This `Runnable` behaves almost like the identity function, except that it
|
|
78
78
|
can be configured to add additional keys to the output, if the input is a
|
|
79
79
|
dict.
|
|
80
80
|
|
|
81
|
-
The examples below demonstrate this Runnable works using a few simple
|
|
81
|
+
The examples below demonstrate this `Runnable` works using a few simple
|
|
82
82
|
chains. The chains rely on simple lambdas to make the examples easy to execute
|
|
83
83
|
and experiment with.
|
|
84
84
|
|
|
@@ -164,7 +164,7 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
|
|
|
164
164
|
input_type: type[Other] | None = None,
|
|
165
165
|
**kwargs: Any,
|
|
166
166
|
) -> None:
|
|
167
|
-
"""Create
|
|
167
|
+
"""Create a `RunnablePassthrough`.
|
|
168
168
|
|
|
169
169
|
Args:
|
|
170
170
|
func: Function to be called with the input.
|
|
@@ -180,7 +180,7 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
|
|
|
180
180
|
@classmethod
|
|
181
181
|
@override
|
|
182
182
|
def is_lc_serializable(cls) -> bool:
|
|
183
|
-
"""Return True as this class is serializable."""
|
|
183
|
+
"""Return `True` as this class is serializable."""
|
|
184
184
|
return True
|
|
185
185
|
|
|
186
186
|
@classmethod
|
|
@@ -213,11 +213,11 @@ class RunnablePassthrough(RunnableSerializable[Other, Other]):
|
|
|
213
213
|
"""Merge the Dict input with the output produced by the mapping argument.
|
|
214
214
|
|
|
215
215
|
Args:
|
|
216
|
-
**kwargs: Runnable
|
|
217
|
-
or
|
|
216
|
+
**kwargs: `Runnable`, `Callable` or a `Mapping` from keys to `Runnable`
|
|
217
|
+
objects or `Callable`s.
|
|
218
218
|
|
|
219
219
|
Returns:
|
|
220
|
-
A Runnable that merges the
|
|
220
|
+
A `Runnable` that merges the `dict` input with the output produced by the
|
|
221
221
|
mapping argument.
|
|
222
222
|
"""
|
|
223
223
|
return RunnableAssign(RunnableParallel[dict[str, Any]](kwargs))
|
|
@@ -350,7 +350,7 @@ _graph_passthrough: RunnablePassthrough = RunnablePassthrough()
|
|
|
350
350
|
|
|
351
351
|
|
|
352
352
|
class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
353
|
-
"""Runnable that assigns key-value pairs to dict[str, Any] inputs.
|
|
353
|
+
"""Runnable that assigns key-value pairs to `dict[str, Any]` inputs.
|
|
354
354
|
|
|
355
355
|
The `RunnableAssign` class takes input dictionaries and, through a
|
|
356
356
|
`RunnableParallel` instance, applies transformations, then combines
|
|
@@ -392,7 +392,7 @@ class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
|
392
392
|
mapper: RunnableParallel
|
|
393
393
|
|
|
394
394
|
def __init__(self, mapper: RunnableParallel[dict[str, Any]], **kwargs: Any) -> None:
|
|
395
|
-
"""Create a RunnableAssign
|
|
395
|
+
"""Create a `RunnableAssign`.
|
|
396
396
|
|
|
397
397
|
Args:
|
|
398
398
|
mapper: A `RunnableParallel` instance that will be used to transform the
|
|
@@ -403,7 +403,7 @@ class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
|
403
403
|
@classmethod
|
|
404
404
|
@override
|
|
405
405
|
def is_lc_serializable(cls) -> bool:
|
|
406
|
-
"""Return True as this class is serializable."""
|
|
406
|
+
"""Return `True` as this class is serializable."""
|
|
407
407
|
return True
|
|
408
408
|
|
|
409
409
|
@classmethod
|
|
@@ -668,13 +668,19 @@ class RunnableAssign(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
|
668
668
|
yield chunk
|
|
669
669
|
|
|
670
670
|
|
|
671
|
-
class RunnablePick(RunnableSerializable[dict[str, Any],
|
|
672
|
-
"""Runnable that picks keys from dict[str, Any] inputs.
|
|
671
|
+
class RunnablePick(RunnableSerializable[dict[str, Any], Any]):
|
|
672
|
+
"""`Runnable` that picks keys from `dict[str, Any]` inputs.
|
|
673
673
|
|
|
674
|
-
RunnablePick class represents a Runnable that selectively picks keys from a
|
|
674
|
+
`RunnablePick` class represents a `Runnable` that selectively picks keys from a
|
|
675
675
|
dictionary input. It allows you to specify one or more keys to extract
|
|
676
|
-
from the input dictionary.
|
|
677
|
-
|
|
676
|
+
from the input dictionary.
|
|
677
|
+
|
|
678
|
+
!!! note "Return Type Behavior"
|
|
679
|
+
The return type depends on the `keys` parameter:
|
|
680
|
+
|
|
681
|
+
- When `keys` is a `str`: Returns the single value associated with that key
|
|
682
|
+
- When `keys` is a `list`: Returns a dictionary containing only the selected
|
|
683
|
+
keys
|
|
678
684
|
|
|
679
685
|
Example:
|
|
680
686
|
```python
|
|
@@ -687,18 +693,22 @@ class RunnablePick(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
|
687
693
|
"country": "USA",
|
|
688
694
|
}
|
|
689
695
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
696
|
+
# Single key - returns the value directly
|
|
697
|
+
runnable_single = RunnablePick(keys="name")
|
|
698
|
+
result_single = runnable_single.invoke(input_data)
|
|
699
|
+
print(result_single) # Output: "John"
|
|
693
700
|
|
|
694
|
-
|
|
701
|
+
# Multiple keys - returns a dictionary
|
|
702
|
+
runnable_multiple = RunnablePick(keys=["name", "age"])
|
|
703
|
+
result_multiple = runnable_multiple.invoke(input_data)
|
|
704
|
+
print(result_multiple) # Output: {'name': 'John', 'age': 30}
|
|
695
705
|
```
|
|
696
706
|
"""
|
|
697
707
|
|
|
698
708
|
keys: str | list[str]
|
|
699
709
|
|
|
700
710
|
def __init__(self, keys: str | list[str], **kwargs: Any) -> None:
|
|
701
|
-
"""Create a RunnablePick
|
|
711
|
+
"""Create a `RunnablePick`.
|
|
702
712
|
|
|
703
713
|
Args:
|
|
704
714
|
keys: A single key or a list of keys to pick from the input dictionary.
|
|
@@ -708,7 +718,7 @@ class RunnablePick(RunnableSerializable[dict[str, Any], dict[str, Any]]):
|
|
|
708
718
|
@classmethod
|
|
709
719
|
@override
|
|
710
720
|
def is_lc_serializable(cls) -> bool:
|
|
711
|
-
"""Return True as this class is serializable."""
|
|
721
|
+
"""Return `True` as this class is serializable."""
|
|
712
722
|
return True
|
|
713
723
|
|
|
714
724
|
@classmethod
|