langchain-core 0.3.75__py3-none-any.whl → 0.3.77__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/beta_decorator.py +22 -44
- langchain_core/_api/deprecation.py +30 -17
- langchain_core/_api/path.py +19 -2
- langchain_core/_import_utils.py +7 -0
- langchain_core/agents.py +10 -6
- langchain_core/beta/runnables/context.py +1 -2
- langchain_core/callbacks/base.py +28 -15
- langchain_core/callbacks/manager.py +83 -71
- langchain_core/callbacks/usage.py +6 -4
- langchain_core/chat_history.py +29 -21
- langchain_core/document_loaders/base.py +34 -9
- langchain_core/document_loaders/langsmith.py +4 -1
- langchain_core/documents/base.py +35 -10
- langchain_core/documents/transformers.py +4 -2
- langchain_core/embeddings/fake.py +8 -5
- langchain_core/env.py +2 -3
- langchain_core/example_selectors/base.py +12 -0
- langchain_core/exceptions.py +7 -0
- langchain_core/globals.py +17 -28
- langchain_core/indexing/api.py +88 -76
- langchain_core/indexing/base.py +5 -8
- langchain_core/indexing/in_memory.py +23 -3
- langchain_core/language_models/__init__.py +3 -2
- langchain_core/language_models/base.py +31 -20
- langchain_core/language_models/chat_models.py +98 -27
- langchain_core/language_models/fake_chat_models.py +10 -9
- langchain_core/language_models/llms.py +52 -18
- langchain_core/load/dump.py +2 -3
- langchain_core/load/load.py +15 -1
- langchain_core/load/serializable.py +39 -44
- langchain_core/memory.py +7 -3
- langchain_core/messages/ai.py +53 -24
- langchain_core/messages/base.py +43 -22
- langchain_core/messages/chat.py +4 -1
- langchain_core/messages/content_blocks.py +23 -2
- langchain_core/messages/function.py +9 -5
- langchain_core/messages/human.py +13 -10
- langchain_core/messages/modifier.py +1 -0
- langchain_core/messages/system.py +11 -8
- langchain_core/messages/tool.py +60 -29
- langchain_core/messages/utils.py +250 -131
- langchain_core/output_parsers/base.py +5 -2
- langchain_core/output_parsers/json.py +4 -4
- langchain_core/output_parsers/list.py +7 -22
- langchain_core/output_parsers/openai_functions.py +3 -0
- langchain_core/output_parsers/openai_tools.py +6 -1
- langchain_core/output_parsers/pydantic.py +4 -0
- langchain_core/output_parsers/string.py +5 -1
- langchain_core/output_parsers/xml.py +19 -19
- langchain_core/outputs/chat_generation.py +25 -10
- langchain_core/outputs/generation.py +14 -3
- langchain_core/outputs/llm_result.py +8 -1
- langchain_core/prompt_values.py +16 -6
- langchain_core/prompts/base.py +4 -9
- langchain_core/prompts/chat.py +89 -57
- langchain_core/prompts/dict.py +16 -8
- langchain_core/prompts/few_shot.py +12 -11
- langchain_core/prompts/few_shot_with_templates.py +5 -1
- langchain_core/prompts/image.py +12 -5
- langchain_core/prompts/message.py +5 -6
- langchain_core/prompts/pipeline.py +13 -8
- langchain_core/prompts/prompt.py +22 -8
- langchain_core/prompts/string.py +18 -10
- langchain_core/prompts/structured.py +7 -2
- langchain_core/rate_limiters.py +2 -2
- langchain_core/retrievers.py +7 -6
- langchain_core/runnables/base.py +406 -186
- langchain_core/runnables/branch.py +14 -19
- langchain_core/runnables/config.py +9 -15
- langchain_core/runnables/configurable.py +34 -19
- langchain_core/runnables/fallbacks.py +20 -13
- langchain_core/runnables/graph.py +48 -38
- langchain_core/runnables/graph_ascii.py +41 -18
- langchain_core/runnables/graph_mermaid.py +54 -25
- langchain_core/runnables/graph_png.py +27 -31
- langchain_core/runnables/history.py +55 -58
- langchain_core/runnables/passthrough.py +44 -21
- langchain_core/runnables/retry.py +44 -23
- langchain_core/runnables/router.py +9 -8
- langchain_core/runnables/schema.py +2 -0
- langchain_core/runnables/utils.py +51 -89
- langchain_core/stores.py +19 -31
- langchain_core/sys_info.py +9 -8
- langchain_core/tools/base.py +37 -28
- langchain_core/tools/convert.py +26 -15
- langchain_core/tools/simple.py +36 -8
- langchain_core/tools/structured.py +25 -12
- langchain_core/tracers/base.py +2 -2
- langchain_core/tracers/context.py +5 -1
- langchain_core/tracers/core.py +109 -39
- langchain_core/tracers/evaluation.py +22 -26
- langchain_core/tracers/event_stream.py +45 -34
- langchain_core/tracers/langchain.py +12 -3
- langchain_core/tracers/langchain_v1.py +10 -2
- langchain_core/tracers/log_stream.py +56 -17
- langchain_core/tracers/root_listeners.py +4 -20
- langchain_core/tracers/run_collector.py +6 -16
- langchain_core/tracers/schemas.py +5 -1
- langchain_core/utils/aiter.py +15 -7
- langchain_core/utils/env.py +3 -0
- langchain_core/utils/function_calling.py +50 -28
- langchain_core/utils/interactive_env.py +6 -2
- langchain_core/utils/iter.py +12 -4
- langchain_core/utils/json.py +12 -3
- langchain_core/utils/json_schema.py +156 -40
- langchain_core/utils/loading.py +5 -1
- langchain_core/utils/mustache.py +24 -15
- langchain_core/utils/pydantic.py +38 -9
- langchain_core/utils/utils.py +25 -9
- langchain_core/vectorstores/base.py +7 -20
- langchain_core/vectorstores/in_memory.py +23 -17
- langchain_core/vectorstores/utils.py +18 -12
- langchain_core/version.py +1 -1
- langchain_core-0.3.77.dist-info/METADATA +67 -0
- langchain_core-0.3.77.dist-info/RECORD +174 -0
- langchain_core-0.3.75.dist-info/METADATA +0 -106
- langchain_core-0.3.75.dist-info/RECORD +0 -174
- {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/WHEEL +0 -0
- {langchain_core-0.3.75.dist-info → langchain_core-0.3.77.dist-info}/entry_points.txt +0 -0
|
@@ -12,6 +12,10 @@ from typing import (
|
|
|
12
12
|
from pydantic import BaseModel, ConfigDict
|
|
13
13
|
from typing_extensions import override
|
|
14
14
|
|
|
15
|
+
from langchain_core.beta.runnables.context import (
|
|
16
|
+
CONTEXT_CONFIG_PREFIX,
|
|
17
|
+
CONTEXT_CONFIG_SUFFIX_SET,
|
|
18
|
+
)
|
|
15
19
|
from langchain_core.runnables.base import (
|
|
16
20
|
Runnable,
|
|
17
21
|
RunnableLike,
|
|
@@ -44,10 +48,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
44
48
|
|
|
45
49
|
If no condition evaluates to True, the default branch is run on the input.
|
|
46
50
|
|
|
47
|
-
Parameters:
|
|
48
|
-
branches: A list of (condition, Runnable) pairs.
|
|
49
|
-
default: A Runnable to run if no condition is met.
|
|
50
|
-
|
|
51
51
|
Examples:
|
|
52
52
|
|
|
53
53
|
.. code-block:: python
|
|
@@ -61,13 +61,15 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
61
61
|
lambda x: "goodbye",
|
|
62
62
|
)
|
|
63
63
|
|
|
64
|
-
branch.invoke("hello")
|
|
65
|
-
branch.invoke(None)
|
|
64
|
+
branch.invoke("hello") # "HELLO"
|
|
65
|
+
branch.invoke(None) # "goodbye"
|
|
66
66
|
|
|
67
67
|
"""
|
|
68
68
|
|
|
69
69
|
branches: Sequence[tuple[Runnable[Input, bool], Runnable[Input, Output]]]
|
|
70
|
+
"""A list of (condition, Runnable) pairs."""
|
|
70
71
|
default: Runnable[Input, Output]
|
|
72
|
+
"""A Runnable to run if no condition is met."""
|
|
71
73
|
|
|
72
74
|
def __init__(
|
|
73
75
|
self,
|
|
@@ -144,12 +146,17 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
144
146
|
|
|
145
147
|
@classmethod
|
|
146
148
|
def is_lc_serializable(cls) -> bool:
|
|
147
|
-
"""
|
|
149
|
+
"""Return True as this class is serializable."""
|
|
148
150
|
return True
|
|
149
151
|
|
|
150
152
|
@classmethod
|
|
151
153
|
@override
|
|
152
154
|
def get_lc_namespace(cls) -> list[str]:
|
|
155
|
+
"""Get the namespace of the langchain object.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
``["langchain", "schema", "runnable"]``
|
|
159
|
+
"""
|
|
153
160
|
return ["langchain", "schema", "runnable"]
|
|
154
161
|
|
|
155
162
|
@override
|
|
@@ -174,11 +181,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
174
181
|
@property
|
|
175
182
|
@override
|
|
176
183
|
def config_specs(self) -> list[ConfigurableFieldSpec]:
|
|
177
|
-
from langchain_core.beta.runnables.context import (
|
|
178
|
-
CONTEXT_CONFIG_PREFIX,
|
|
179
|
-
CONTEXT_CONFIG_SUFFIX_SET,
|
|
180
|
-
)
|
|
181
|
-
|
|
182
184
|
specs = get_unique_config_specs(
|
|
183
185
|
spec
|
|
184
186
|
for step in (
|
|
@@ -260,7 +262,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
260
262
|
async def ainvoke(
|
|
261
263
|
self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any
|
|
262
264
|
) -> Output:
|
|
263
|
-
"""Async version of invoke."""
|
|
264
265
|
config = ensure_config(config)
|
|
265
266
|
callback_manager = get_async_callback_manager_for_config(config)
|
|
266
267
|
run_manager = await callback_manager.on_chain_start(
|
|
@@ -321,9 +322,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
321
322
|
|
|
322
323
|
Yields:
|
|
323
324
|
The output of the branch that was run.
|
|
324
|
-
|
|
325
|
-
Raises:
|
|
326
|
-
BaseException: If an error occurs during the execution of the Runnable.
|
|
327
325
|
"""
|
|
328
326
|
config = ensure_config(config)
|
|
329
327
|
callback_manager = get_callback_manager_for_config(config)
|
|
@@ -408,9 +406,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
408
406
|
|
|
409
407
|
Yields:
|
|
410
408
|
The output of the branch that was run.
|
|
411
|
-
|
|
412
|
-
Raises:
|
|
413
|
-
BaseException: If an error occurs during the execution of the Runnable.
|
|
414
409
|
"""
|
|
415
410
|
config = ensure_config(config)
|
|
416
411
|
callback_manager = get_async_callback_manager_for_config(config)
|
|
@@ -12,21 +12,22 @@ from contextvars import Context, ContextVar, Token, copy_context
|
|
|
12
12
|
from functools import partial
|
|
13
13
|
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, cast
|
|
14
14
|
|
|
15
|
+
from langsmith.run_helpers import _set_tracing_context, get_tracing_context
|
|
15
16
|
from typing_extensions import ParamSpec, TypedDict
|
|
16
17
|
|
|
18
|
+
from langchain_core.callbacks.manager import AsyncCallbackManager, CallbackManager
|
|
17
19
|
from langchain_core.runnables.utils import (
|
|
18
20
|
Input,
|
|
19
21
|
Output,
|
|
20
22
|
accepts_config,
|
|
21
23
|
accepts_run_manager,
|
|
22
24
|
)
|
|
25
|
+
from langchain_core.tracers.langchain import LangChainTracer
|
|
23
26
|
|
|
24
27
|
if TYPE_CHECKING:
|
|
25
28
|
from langchain_core.callbacks.base import BaseCallbackManager, Callbacks
|
|
26
29
|
from langchain_core.callbacks.manager import (
|
|
27
|
-
AsyncCallbackManager,
|
|
28
30
|
AsyncCallbackManagerForChainRun,
|
|
29
|
-
CallbackManager,
|
|
30
31
|
CallbackManagerForChainRun,
|
|
31
32
|
)
|
|
32
33
|
else:
|
|
@@ -125,9 +126,10 @@ def _set_config_context(
|
|
|
125
126
|
|
|
126
127
|
Args:
|
|
127
128
|
config (RunnableConfig): The config to set.
|
|
128
|
-
"""
|
|
129
|
-
from langchain_core.tracers.langchain import LangChainTracer
|
|
130
129
|
|
|
130
|
+
Returns:
|
|
131
|
+
The token to reset the config and the previous tracing context.
|
|
132
|
+
"""
|
|
131
133
|
config_token = var_child_runnable_config.set(config)
|
|
132
134
|
current_context = None
|
|
133
135
|
if (
|
|
@@ -147,8 +149,6 @@ def _set_config_context(
|
|
|
147
149
|
)
|
|
148
150
|
and (run := tracer.run_map.get(str(parent_run_id)))
|
|
149
151
|
):
|
|
150
|
-
from langsmith.run_helpers import _set_tracing_context, get_tracing_context
|
|
151
|
-
|
|
152
152
|
current_context = get_tracing_context()
|
|
153
153
|
_set_tracing_context({"parent": run})
|
|
154
154
|
return config_token, current_context
|
|
@@ -160,9 +160,10 @@ def set_config_context(config: RunnableConfig) -> Generator[Context, None, None]
|
|
|
160
160
|
|
|
161
161
|
Args:
|
|
162
162
|
config (RunnableConfig): The config to set.
|
|
163
|
-
"""
|
|
164
|
-
from langsmith.run_helpers import _set_tracing_context
|
|
165
163
|
|
|
164
|
+
Yields:
|
|
165
|
+
The config context.
|
|
166
|
+
"""
|
|
166
167
|
ctx = copy_context()
|
|
167
168
|
config_token, _ = ctx.run(_set_config_context, config)
|
|
168
169
|
try:
|
|
@@ -475,8 +476,6 @@ def get_callback_manager_for_config(config: RunnableConfig) -> CallbackManager:
|
|
|
475
476
|
Returns:
|
|
476
477
|
CallbackManager: The callback manager.
|
|
477
478
|
"""
|
|
478
|
-
from langchain_core.callbacks.manager import CallbackManager
|
|
479
|
-
|
|
480
479
|
return CallbackManager.configure(
|
|
481
480
|
inheritable_callbacks=config.get("callbacks"),
|
|
482
481
|
inheritable_tags=config.get("tags"),
|
|
@@ -495,8 +494,6 @@ def get_async_callback_manager_for_config(
|
|
|
495
494
|
Returns:
|
|
496
495
|
AsyncCallbackManager: The async callback manager.
|
|
497
496
|
"""
|
|
498
|
-
from langchain_core.callbacks.manager import AsyncCallbackManager
|
|
499
|
-
|
|
500
497
|
return AsyncCallbackManager.configure(
|
|
501
498
|
inheritable_callbacks=config.get("callbacks"),
|
|
502
499
|
inheritable_tags=config.get("tags"),
|
|
@@ -598,9 +595,6 @@ async def run_in_executor(
|
|
|
598
595
|
|
|
599
596
|
Returns:
|
|
600
597
|
Output: The output of the function.
|
|
601
|
-
|
|
602
|
-
Raises:
|
|
603
|
-
RuntimeError: If the function raises a StopIteration.
|
|
604
598
|
"""
|
|
605
599
|
|
|
606
600
|
def wrapper() -> T:
|
|
@@ -51,17 +51,15 @@ if TYPE_CHECKING:
|
|
|
51
51
|
class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
52
52
|
"""Serializable Runnable that can be dynamically configured.
|
|
53
53
|
|
|
54
|
-
A DynamicRunnable should be initiated using the
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
Parameters:
|
|
58
|
-
default: The default Runnable to use.
|
|
59
|
-
config: The configuration to use.
|
|
54
|
+
A DynamicRunnable should be initiated using the ``configurable_fields`` or
|
|
55
|
+
``configurable_alternatives`` method of a Runnable.
|
|
60
56
|
"""
|
|
61
57
|
|
|
62
58
|
default: RunnableSerializable[Input, Output]
|
|
59
|
+
"""The default Runnable to use."""
|
|
63
60
|
|
|
64
61
|
config: Optional[RunnableConfig] = None
|
|
62
|
+
"""The configuration to use."""
|
|
65
63
|
|
|
66
64
|
model_config = ConfigDict(
|
|
67
65
|
arbitrary_types_allowed=True,
|
|
@@ -70,11 +68,17 @@ class DynamicRunnable(RunnableSerializable[Input, Output]):
|
|
|
70
68
|
@classmethod
|
|
71
69
|
@override
|
|
72
70
|
def is_lc_serializable(cls) -> bool:
|
|
71
|
+
"""Return True as this class is serializable."""
|
|
73
72
|
return True
|
|
74
73
|
|
|
75
74
|
@classmethod
|
|
76
75
|
@override
|
|
77
76
|
def get_lc_namespace(cls) -> list[str]:
|
|
77
|
+
"""Get the namespace of the langchain object.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
``["langchain", "schema", "runnable"]``
|
|
81
|
+
"""
|
|
78
82
|
return ["langchain", "schema", "runnable"]
|
|
79
83
|
|
|
80
84
|
@property
|
|
@@ -322,9 +326,6 @@ class RunnableConfigurableFields(DynamicRunnable[Input, Output]):
|
|
|
322
326
|
A RunnableConfigurableFields should be initiated using the
|
|
323
327
|
`configurable_fields` method of a Runnable.
|
|
324
328
|
|
|
325
|
-
Parameters:
|
|
326
|
-
fields: The configurable fields to use.
|
|
327
|
-
|
|
328
329
|
Here is an example of using a RunnableConfigurableFields with LLMs:
|
|
329
330
|
|
|
330
331
|
.. code-block:: python
|
|
@@ -382,6 +383,7 @@ class RunnableConfigurableFields(DynamicRunnable[Input, Output]):
|
|
|
382
383
|
"""
|
|
383
384
|
|
|
384
385
|
fields: dict[str, AnyConfigurableField]
|
|
386
|
+
"""The configurable fields to use."""
|
|
385
387
|
|
|
386
388
|
@property
|
|
387
389
|
def config_specs(self) -> list[ConfigurableFieldSpec]:
|
|
@@ -501,7 +503,7 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
501
503
|
).configurable_alternatives(
|
|
502
504
|
ConfigurableField(id="prompt"),
|
|
503
505
|
default_key="joke",
|
|
504
|
-
poem=PromptTemplate.from_template("Write a short poem about {topic}")
|
|
506
|
+
poem=PromptTemplate.from_template("Write a short poem about {topic}"),
|
|
505
507
|
)
|
|
506
508
|
|
|
507
509
|
# When invoking the created RunnableSequence, you can pass in the
|
|
@@ -511,7 +513,9 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
511
513
|
|
|
512
514
|
# The `with_config` method brings in the desired Prompt Runnable in your
|
|
513
515
|
# Runnable Sequence.
|
|
514
|
-
chain.with_config(configurable={"prompt": "poem"}).invoke(
|
|
516
|
+
chain.with_config(configurable={"prompt": "poem"}).invoke(
|
|
517
|
+
{"topic": "bears"}
|
|
518
|
+
)
|
|
515
519
|
|
|
516
520
|
|
|
517
521
|
Equivalently, you can initialize RunnableConfigurableAlternatives directly
|
|
@@ -520,20 +524,28 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|
|
520
524
|
.. code-block:: python
|
|
521
525
|
|
|
522
526
|
from langchain_core.runnables import ConfigurableField
|
|
523
|
-
from langchain_core.runnables.configurable import
|
|
527
|
+
from langchain_core.runnables.configurable import (
|
|
528
|
+
RunnableConfigurableAlternatives,
|
|
529
|
+
)
|
|
524
530
|
from langchain_openai import ChatOpenAI
|
|
525
531
|
|
|
526
532
|
prompt = RunnableConfigurableAlternatives(
|
|
527
|
-
which=ConfigurableField(id=
|
|
533
|
+
which=ConfigurableField(id="prompt"),
|
|
528
534
|
default=PromptTemplate.from_template("Tell me a joke about {topic}"),
|
|
529
|
-
default_key=
|
|
535
|
+
default_key="joke",
|
|
530
536
|
prefix_keys=False,
|
|
531
|
-
alternatives={
|
|
537
|
+
alternatives={
|
|
538
|
+
"poem": PromptTemplate.from_template(
|
|
539
|
+
"Write a short poem about {topic}"
|
|
540
|
+
)
|
|
541
|
+
},
|
|
532
542
|
)
|
|
533
543
|
chain = prompt | ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
|
|
534
|
-
chain.with_config(configurable={"prompt": "poem"}).invoke(
|
|
544
|
+
chain.with_config(configurable={"prompt": "poem"}).invoke(
|
|
545
|
+
{"topic": "bears"}
|
|
546
|
+
)
|
|
535
547
|
|
|
536
|
-
"""
|
|
548
|
+
"""
|
|
537
549
|
|
|
538
550
|
which: ConfigurableField
|
|
539
551
|
"""The ConfigurableField to use to choose between alternatives."""
|
|
@@ -680,7 +692,10 @@ def make_options_spec(
|
|
|
680
692
|
spec: Union[ConfigurableFieldSingleOption, ConfigurableFieldMultiOption],
|
|
681
693
|
description: Optional[str],
|
|
682
694
|
) -> ConfigurableFieldSpec:
|
|
683
|
-
"""Make
|
|
695
|
+
"""Make options spec.
|
|
696
|
+
|
|
697
|
+
Make a ConfigurableFieldSpec for a ConfigurableFieldSingleOption or
|
|
698
|
+
ConfigurableFieldMultiOption.
|
|
684
699
|
|
|
685
700
|
Args:
|
|
686
701
|
spec: The ConfigurableFieldSingleOption or ConfigurableFieldMultiOption.
|
|
@@ -688,7 +703,7 @@ def make_options_spec(
|
|
|
688
703
|
|
|
689
704
|
Returns:
|
|
690
705
|
The ConfigurableFieldSpec.
|
|
691
|
-
"""
|
|
706
|
+
"""
|
|
692
707
|
with _enums_for_spec_lock:
|
|
693
708
|
if enum := _enums_for_spec.get(spec):
|
|
694
709
|
pass
|
|
@@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
|
|
10
10
|
from pydantic import BaseModel, ConfigDict
|
|
11
11
|
from typing_extensions import override
|
|
12
12
|
|
|
13
|
+
from langchain_core.callbacks.manager import AsyncCallbackManager, CallbackManager
|
|
13
14
|
from langchain_core.runnables.base import Runnable, RunnableSerializable
|
|
14
15
|
from langchain_core.runnables.config import (
|
|
15
16
|
RunnableConfig,
|
|
@@ -56,12 +57,12 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
56
57
|
from langchain_core.chat_models.openai import ChatOpenAI
|
|
57
58
|
from langchain_core.chat_models.anthropic import ChatAnthropic
|
|
58
59
|
|
|
59
|
-
model = ChatAnthropic(
|
|
60
|
-
model="
|
|
61
|
-
)
|
|
60
|
+
model = ChatAnthropic(model="claude-3-haiku-20240307").with_fallbacks(
|
|
61
|
+
[ChatOpenAI(model="gpt-3.5-turbo-0125")]
|
|
62
|
+
)
|
|
62
63
|
# Will usually use ChatAnthropic, but fallback to ChatOpenAI
|
|
63
64
|
# if ChatAnthropic fails.
|
|
64
|
-
model.invoke(
|
|
65
|
+
model.invoke("hello")
|
|
65
66
|
|
|
66
67
|
# And you can also use fallbacks at the level of a chain.
|
|
67
68
|
# Here if both LLM providers fail, we'll fallback to a good hardcoded
|
|
@@ -71,12 +72,16 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
71
72
|
from langchain_core.output_parser import StrOutputParser
|
|
72
73
|
from langchain_core.runnables import RunnableLambda
|
|
73
74
|
|
|
75
|
+
|
|
74
76
|
def when_all_is_lost(inputs):
|
|
75
|
-
return (
|
|
76
|
-
|
|
77
|
+
return (
|
|
78
|
+
"Looks like our LLM providers are down. "
|
|
79
|
+
"Here's a nice 🦜️ emoji for you instead."
|
|
80
|
+
)
|
|
81
|
+
|
|
77
82
|
|
|
78
83
|
chain_with_fallback = (
|
|
79
|
-
PromptTemplate.from_template(
|
|
84
|
+
PromptTemplate.from_template("Tell me a joke about {topic}")
|
|
80
85
|
| model
|
|
81
86
|
| StrOutputParser()
|
|
82
87
|
).with_fallbacks([RunnableLambda(when_all_is_lost)])
|
|
@@ -136,6 +141,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
136
141
|
@classmethod
|
|
137
142
|
@override
|
|
138
143
|
def is_lc_serializable(cls) -> bool:
|
|
144
|
+
"""Return True as this class is serializable."""
|
|
139
145
|
return True
|
|
140
146
|
|
|
141
147
|
@classmethod
|
|
@@ -143,13 +149,18 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
143
149
|
def get_lc_namespace(cls) -> list[str]:
|
|
144
150
|
"""Get the namespace of the langchain object.
|
|
145
151
|
|
|
146
|
-
|
|
152
|
+
Returns:
|
|
153
|
+
``["langchain", "schema", "runnable"]``
|
|
147
154
|
"""
|
|
148
155
|
return ["langchain", "schema", "runnable"]
|
|
149
156
|
|
|
150
157
|
@property
|
|
151
158
|
def runnables(self) -> Iterator[Runnable[Input, Output]]:
|
|
152
|
-
"""Iterator over the Runnable and its fallbacks.
|
|
159
|
+
"""Iterator over the Runnable and its fallbacks.
|
|
160
|
+
|
|
161
|
+
Yields:
|
|
162
|
+
The Runnable then its fallbacks.
|
|
163
|
+
"""
|
|
153
164
|
yield self.runnable
|
|
154
165
|
yield from self.fallbacks
|
|
155
166
|
|
|
@@ -262,8 +273,6 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
262
273
|
return_exceptions: bool = False,
|
|
263
274
|
**kwargs: Optional[Any],
|
|
264
275
|
) -> list[Output]:
|
|
265
|
-
from langchain_core.callbacks.manager import CallbackManager
|
|
266
|
-
|
|
267
276
|
if self.exception_key is not None and not all(
|
|
268
277
|
isinstance(input_, dict) for input_ in inputs
|
|
269
278
|
):
|
|
@@ -356,8 +365,6 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
|
|
356
365
|
return_exceptions: bool = False,
|
|
357
366
|
**kwargs: Optional[Any],
|
|
358
367
|
) -> list[Output]:
|
|
359
|
-
from langchain_core.callbacks.manager import AsyncCallbackManager
|
|
360
|
-
|
|
361
368
|
if self.exception_key is not None and not all(
|
|
362
369
|
isinstance(input_, dict) for input_ in inputs
|
|
363
370
|
):
|
|
@@ -19,6 +19,8 @@ from typing import (
|
|
|
19
19
|
)
|
|
20
20
|
from uuid import UUID, uuid4
|
|
21
21
|
|
|
22
|
+
from langchain_core.load.serializable import to_json_not_implemented
|
|
23
|
+
from langchain_core.runnables.base import Runnable, RunnableSerializable
|
|
22
24
|
from langchain_core.utils.pydantic import _IgnoreUnserializable, is_basemodel_subclass
|
|
23
25
|
|
|
24
26
|
if TYPE_CHECKING:
|
|
@@ -62,19 +64,16 @@ def is_uuid(value: str) -> bool:
|
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
class Edge(NamedTuple):
|
|
65
|
-
"""Edge in a graph.
|
|
66
|
-
|
|
67
|
-
Parameters:
|
|
68
|
-
source: The source node id.
|
|
69
|
-
target: The target node id.
|
|
70
|
-
data: Optional data associated with the edge. Defaults to None.
|
|
71
|
-
conditional: Whether the edge is conditional. Defaults to False.
|
|
72
|
-
"""
|
|
67
|
+
"""Edge in a graph."""
|
|
73
68
|
|
|
74
69
|
source: str
|
|
70
|
+
"""The source node id."""
|
|
75
71
|
target: str
|
|
72
|
+
"""The target node id."""
|
|
76
73
|
data: Optional[Stringifiable] = None
|
|
74
|
+
"""Optional data associated with the edge. Defaults to None."""
|
|
77
75
|
conditional: bool = False
|
|
76
|
+
"""Whether the edge is conditional. Defaults to False."""
|
|
78
77
|
|
|
79
78
|
def copy(
|
|
80
79
|
self, *, source: Optional[str] = None, target: Optional[str] = None
|
|
@@ -97,19 +96,16 @@ class Edge(NamedTuple):
|
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
class Node(NamedTuple):
|
|
100
|
-
"""Node in a graph.
|
|
101
|
-
|
|
102
|
-
Parameters:
|
|
103
|
-
id: The unique identifier of the node.
|
|
104
|
-
name: The name of the node.
|
|
105
|
-
data: The data of the node.
|
|
106
|
-
metadata: Optional metadata for the node. Defaults to None.
|
|
107
|
-
"""
|
|
99
|
+
"""Node in a graph."""
|
|
108
100
|
|
|
109
101
|
id: str
|
|
102
|
+
"""The unique identifier of the node."""
|
|
110
103
|
name: str
|
|
104
|
+
"""The name of the node."""
|
|
111
105
|
data: Union[type[BaseModel], RunnableType, None]
|
|
106
|
+
"""The data of the node."""
|
|
112
107
|
metadata: Optional[dict[str, Any]]
|
|
108
|
+
"""Optional metadata for the node. Defaults to None."""
|
|
113
109
|
|
|
114
110
|
def copy(
|
|
115
111
|
self,
|
|
@@ -135,16 +131,12 @@ class Node(NamedTuple):
|
|
|
135
131
|
|
|
136
132
|
|
|
137
133
|
class Branch(NamedTuple):
|
|
138
|
-
"""Branch in a graph.
|
|
139
|
-
|
|
140
|
-
Parameters:
|
|
141
|
-
condition: A callable that returns a string representation of the condition.
|
|
142
|
-
ends: Optional dictionary of end node ids for the branches. Defaults
|
|
143
|
-
to None.
|
|
144
|
-
"""
|
|
134
|
+
"""Branch in a graph."""
|
|
145
135
|
|
|
146
136
|
condition: Callable[..., str]
|
|
137
|
+
"""A callable that returns a string representation of the condition."""
|
|
147
138
|
ends: Optional[dict[str, str]]
|
|
139
|
+
"""Optional dictionary of end node ids for the branches. Defaults to None."""
|
|
148
140
|
|
|
149
141
|
|
|
150
142
|
class CurveStyle(Enum):
|
|
@@ -168,7 +160,7 @@ class CurveStyle(Enum):
|
|
|
168
160
|
class NodeStyles:
|
|
169
161
|
"""Schema for Hexadecimal color codes for different node types.
|
|
170
162
|
|
|
171
|
-
|
|
163
|
+
Args:
|
|
172
164
|
default: The default color code. Defaults to "fill:#f2f0ff,line-height:1.2".
|
|
173
165
|
first: The color code for the first node. Defaults to "fill-opacity:0".
|
|
174
166
|
last: The color code for the last node. Defaults to "fill:#bfb6fc".
|
|
@@ -182,8 +174,10 @@ class NodeStyles:
|
|
|
182
174
|
class MermaidDrawMethod(Enum):
|
|
183
175
|
"""Enum for different draw methods supported by Mermaid."""
|
|
184
176
|
|
|
185
|
-
PYPPETEER = "pyppeteer"
|
|
186
|
-
|
|
177
|
+
PYPPETEER = "pyppeteer"
|
|
178
|
+
"""Uses Pyppeteer to render the graph"""
|
|
179
|
+
API = "api"
|
|
180
|
+
"""Uses Mermaid.INK API to render the graph"""
|
|
187
181
|
|
|
188
182
|
|
|
189
183
|
def node_data_str(
|
|
@@ -199,8 +193,6 @@ def node_data_str(
|
|
|
199
193
|
Returns:
|
|
200
194
|
A string representation of the data.
|
|
201
195
|
"""
|
|
202
|
-
from langchain_core.runnables.base import Runnable
|
|
203
|
-
|
|
204
196
|
if not is_uuid(id) or data is None:
|
|
205
197
|
return id
|
|
206
198
|
data_str = data.get_name() if isinstance(data, Runnable) else data.__name__
|
|
@@ -220,9 +212,6 @@ def node_data_json(
|
|
|
220
212
|
Returns:
|
|
221
213
|
A dictionary with the type of the data and the data itself.
|
|
222
214
|
"""
|
|
223
|
-
from langchain_core.load.serializable import to_json_not_implemented
|
|
224
|
-
from langchain_core.runnables.base import Runnable, RunnableSerializable
|
|
225
|
-
|
|
226
215
|
if node.data is None:
|
|
227
216
|
json: dict[str, Any] = {}
|
|
228
217
|
elif isinstance(node.data, RunnableSerializable):
|
|
@@ -269,7 +258,7 @@ def node_data_json(
|
|
|
269
258
|
class Graph:
|
|
270
259
|
"""Graph of nodes and edges.
|
|
271
260
|
|
|
272
|
-
|
|
261
|
+
Args:
|
|
273
262
|
nodes: Dictionary of nodes in the graph. Defaults to an empty dictionary.
|
|
274
263
|
edges: List of edges in the graph. Defaults to an empty list.
|
|
275
264
|
"""
|
|
@@ -475,6 +464,10 @@ class Graph:
|
|
|
475
464
|
|
|
476
465
|
If there is no such node, or there are multiple, return None.
|
|
477
466
|
When drawing the graph, this node would be the origin.
|
|
467
|
+
|
|
468
|
+
Returns:
|
|
469
|
+
The first node, or None if there is no such node or multiple
|
|
470
|
+
candidates.
|
|
478
471
|
"""
|
|
479
472
|
return _first_node(self)
|
|
480
473
|
|
|
@@ -483,6 +476,10 @@ class Graph:
|
|
|
483
476
|
|
|
484
477
|
If there is no such node, or there are multiple, return None.
|
|
485
478
|
When drawing the graph, this node would be the destination.
|
|
479
|
+
|
|
480
|
+
Returns:
|
|
481
|
+
The last node, or None if there is no such node or multiple
|
|
482
|
+
candidates.
|
|
486
483
|
"""
|
|
487
484
|
return _last_node(self)
|
|
488
485
|
|
|
@@ -513,8 +510,13 @@ class Graph:
|
|
|
513
510
|
self.remove_node(last_node)
|
|
514
511
|
|
|
515
512
|
def draw_ascii(self) -> str:
|
|
516
|
-
"""Draw the graph as an ASCII art string.
|
|
517
|
-
|
|
513
|
+
"""Draw the graph as an ASCII art string.
|
|
514
|
+
|
|
515
|
+
Returns:
|
|
516
|
+
The ASCII art string.
|
|
517
|
+
"""
|
|
518
|
+
# Import locally to prevent circular import
|
|
519
|
+
from langchain_core.runnables.graph_ascii import draw_ascii # noqa: PLC0415
|
|
518
520
|
|
|
519
521
|
return draw_ascii(
|
|
520
522
|
{node.id: node.name for node in self.nodes.values()},
|
|
@@ -558,7 +560,8 @@ class Graph:
|
|
|
558
560
|
Returns:
|
|
559
561
|
The PNG image as bytes if output_file_path is None, None otherwise.
|
|
560
562
|
"""
|
|
561
|
-
|
|
563
|
+
# Import locally to prevent circular import
|
|
564
|
+
from langchain_core.runnables.graph_png import PngDrawer # noqa: PLC0415
|
|
562
565
|
|
|
563
566
|
default_node_labels = {node.id: node.name for node in self.nodes.values()}
|
|
564
567
|
|
|
@@ -611,9 +614,9 @@ class Graph:
|
|
|
611
614
|
|
|
612
615
|
Returns:
|
|
613
616
|
The Mermaid syntax string.
|
|
614
|
-
|
|
615
617
|
"""
|
|
616
|
-
|
|
618
|
+
# Import locally to prevent circular import
|
|
619
|
+
from langchain_core.runnables.graph_mermaid import draw_mermaid # noqa: PLC0415
|
|
617
620
|
|
|
618
621
|
graph = self.reid()
|
|
619
622
|
first_node = graph.first_node()
|
|
@@ -644,6 +647,7 @@ class Graph:
|
|
|
644
647
|
max_retries: int = 1,
|
|
645
648
|
retry_delay: float = 1.0,
|
|
646
649
|
frontmatter_config: Optional[dict[str, Any]] = None,
|
|
650
|
+
base_url: Optional[str] = None,
|
|
647
651
|
) -> bytes:
|
|
648
652
|
"""Draw the graph as a PNG image using Mermaid.
|
|
649
653
|
|
|
@@ -679,12 +683,17 @@ class Graph:
|
|
|
679
683
|
"themeVariables": { "primaryColor": "#e2e2e2"},
|
|
680
684
|
}
|
|
681
685
|
}
|
|
686
|
+
base_url: The base URL of the Mermaid server for rendering via API.
|
|
687
|
+
Defaults to None.
|
|
682
688
|
|
|
683
689
|
Returns:
|
|
684
690
|
The PNG image as bytes.
|
|
685
691
|
|
|
686
692
|
"""
|
|
687
|
-
|
|
693
|
+
# Import locally to prevent circular import
|
|
694
|
+
from langchain_core.runnables.graph_mermaid import ( # noqa: PLC0415
|
|
695
|
+
draw_mermaid_png,
|
|
696
|
+
)
|
|
688
697
|
|
|
689
698
|
mermaid_syntax = self.draw_mermaid(
|
|
690
699
|
curve_style=curve_style,
|
|
@@ -700,6 +709,7 @@ class Graph:
|
|
|
700
709
|
padding=padding,
|
|
701
710
|
max_retries=max_retries,
|
|
702
711
|
retry_delay=retry_delay,
|
|
712
|
+
base_url=base_url,
|
|
703
713
|
)
|
|
704
714
|
|
|
705
715
|
|