langchain-core 1.0.0a1__py3-none-any.whl → 1.0.0a3__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 +17 -40
- langchain_core/_api/deprecation.py +20 -7
- langchain_core/_api/path.py +19 -2
- langchain_core/_import_utils.py +7 -0
- langchain_core/agents.py +10 -6
- langchain_core/callbacks/base.py +28 -15
- langchain_core/callbacks/manager.py +81 -69
- langchain_core/callbacks/usage.py +4 -2
- langchain_core/chat_history.py +29 -21
- langchain_core/document_loaders/base.py +34 -9
- langchain_core/document_loaders/langsmith.py +3 -0
- 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 +57 -45
- langchain_core/indexing/base.py +5 -8
- langchain_core/indexing/in_memory.py +23 -3
- langchain_core/language_models/__init__.py +6 -2
- langchain_core/language_models/_utils.py +28 -4
- langchain_core/language_models/base.py +33 -21
- langchain_core/language_models/chat_models.py +103 -29
- langchain_core/language_models/fake_chat_models.py +5 -7
- langchain_core/language_models/llms.py +54 -20
- langchain_core/load/dump.py +2 -3
- langchain_core/load/load.py +15 -1
- langchain_core/load/serializable.py +38 -43
- langchain_core/memory.py +7 -3
- langchain_core/messages/__init__.py +7 -17
- langchain_core/messages/ai.py +41 -34
- langchain_core/messages/base.py +16 -7
- langchain_core/messages/block_translators/__init__.py +10 -8
- langchain_core/messages/block_translators/anthropic.py +3 -1
- langchain_core/messages/block_translators/bedrock.py +3 -1
- langchain_core/messages/block_translators/bedrock_converse.py +3 -1
- langchain_core/messages/block_translators/google_genai.py +3 -1
- langchain_core/messages/block_translators/google_vertexai.py +3 -1
- langchain_core/messages/block_translators/groq.py +3 -1
- langchain_core/messages/block_translators/langchain_v0.py +3 -136
- langchain_core/messages/block_translators/ollama.py +3 -1
- langchain_core/messages/block_translators/openai.py +252 -10
- langchain_core/messages/content.py +26 -124
- langchain_core/messages/human.py +2 -13
- langchain_core/messages/system.py +2 -6
- langchain_core/messages/tool.py +34 -14
- langchain_core/messages/utils.py +189 -74
- 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 +18 -7
- langchain_core/outputs/generation.py +14 -3
- langchain_core/outputs/llm_result.py +8 -1
- langchain_core/prompt_values.py +10 -4
- langchain_core/prompts/base.py +6 -11
- langchain_core/prompts/chat.py +88 -60
- langchain_core/prompts/dict.py +16 -8
- langchain_core/prompts/few_shot.py +9 -11
- langchain_core/prompts/few_shot_with_templates.py +5 -1
- langchain_core/prompts/image.py +12 -5
- langchain_core/prompts/loading.py +2 -2
- 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 +387 -246
- langchain_core/runnables/branch.py +11 -28
- langchain_core/runnables/config.py +20 -17
- 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 +40 -17
- 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 +9 -0
- langchain_core/runnables/utils.py +53 -90
- langchain_core/stores.py +19 -31
- langchain_core/sys_info.py +9 -8
- langchain_core/tools/base.py +36 -27
- langchain_core/tools/convert.py +25 -14
- 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 +110 -46
- langchain_core/tracers/evaluation.py +22 -26
- langchain_core/tracers/event_stream.py +97 -42
- 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 +14 -6
- langchain_core/utils/env.py +3 -0
- langchain_core/utils/function_calling.py +46 -20
- langchain_core/utils/interactive_env.py +6 -2
- langchain_core/utils/iter.py +12 -5
- 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 +25 -16
- 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 +20 -14
- langchain_core/vectorstores/utils.py +18 -12
- langchain_core/version.py +1 -1
- langchain_core-1.0.0a3.dist-info/METADATA +77 -0
- langchain_core-1.0.0a3.dist-info/RECORD +181 -0
- langchain_core/beta/__init__.py +0 -1
- langchain_core/beta/runnables/__init__.py +0 -1
- langchain_core/beta/runnables/context.py +0 -448
- langchain_core-1.0.0a1.dist-info/METADATA +0 -106
- langchain_core-1.0.0a1.dist-info/RECORD +0 -184
- {langchain_core-1.0.0a1.dist-info → langchain_core-1.0.0a3.dist-info}/WHEEL +0 -0
- {langchain_core-1.0.0a1.dist-info → langchain_core-1.0.0a3.dist-info}/entry_points.txt +0 -0
|
@@ -44,10 +44,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
44
44
|
|
|
45
45
|
If no condition evaluates to True, the default branch is run on the input.
|
|
46
46
|
|
|
47
|
-
Parameters:
|
|
48
|
-
branches: A list of (condition, Runnable) pairs.
|
|
49
|
-
default: A Runnable to run if no condition is met.
|
|
50
|
-
|
|
51
47
|
Examples:
|
|
52
48
|
|
|
53
49
|
.. code-block:: python
|
|
@@ -61,13 +57,15 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
61
57
|
lambda x: "goodbye",
|
|
62
58
|
)
|
|
63
59
|
|
|
64
|
-
branch.invoke("hello")
|
|
65
|
-
branch.invoke(None)
|
|
60
|
+
branch.invoke("hello") # "HELLO"
|
|
61
|
+
branch.invoke(None) # "goodbye"
|
|
66
62
|
|
|
67
63
|
"""
|
|
68
64
|
|
|
69
65
|
branches: Sequence[tuple[Runnable[Input, bool], Runnable[Input, Output]]]
|
|
66
|
+
"""A list of (condition, Runnable) pairs."""
|
|
70
67
|
default: Runnable[Input, Output]
|
|
68
|
+
"""A Runnable to run if no condition is met."""
|
|
71
69
|
|
|
72
70
|
def __init__(
|
|
73
71
|
self,
|
|
@@ -144,12 +142,17 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
144
142
|
|
|
145
143
|
@classmethod
|
|
146
144
|
def is_lc_serializable(cls) -> bool:
|
|
147
|
-
"""
|
|
145
|
+
"""Return True as this class is serializable."""
|
|
148
146
|
return True
|
|
149
147
|
|
|
150
148
|
@classmethod
|
|
151
149
|
@override
|
|
152
150
|
def get_lc_namespace(cls) -> list[str]:
|
|
151
|
+
"""Get the namespace of the langchain object.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
``["langchain", "schema", "runnable"]``
|
|
155
|
+
"""
|
|
153
156
|
return ["langchain", "schema", "runnable"]
|
|
154
157
|
|
|
155
158
|
@override
|
|
@@ -174,12 +177,7 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
174
177
|
@property
|
|
175
178
|
@override
|
|
176
179
|
def config_specs(self) -> list[ConfigurableFieldSpec]:
|
|
177
|
-
|
|
178
|
-
CONTEXT_CONFIG_PREFIX,
|
|
179
|
-
CONTEXT_CONFIG_SUFFIX_SET,
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
specs = get_unique_config_specs(
|
|
180
|
+
return get_unique_config_specs(
|
|
183
181
|
spec
|
|
184
182
|
for step in (
|
|
185
183
|
[self.default]
|
|
@@ -188,14 +186,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
188
186
|
)
|
|
189
187
|
for spec in step.config_specs
|
|
190
188
|
)
|
|
191
|
-
if any(
|
|
192
|
-
s.id.startswith(CONTEXT_CONFIG_PREFIX)
|
|
193
|
-
and s.id.endswith(CONTEXT_CONFIG_SUFFIX_SET)
|
|
194
|
-
for s in specs
|
|
195
|
-
):
|
|
196
|
-
msg = "RunnableBranch cannot contain context setters."
|
|
197
|
-
raise ValueError(msg)
|
|
198
|
-
return specs
|
|
199
189
|
|
|
200
190
|
@override
|
|
201
191
|
def invoke(
|
|
@@ -260,7 +250,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
260
250
|
async def ainvoke(
|
|
261
251
|
self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any
|
|
262
252
|
) -> Output:
|
|
263
|
-
"""Async version of invoke."""
|
|
264
253
|
config = ensure_config(config)
|
|
265
254
|
callback_manager = get_async_callback_manager_for_config(config)
|
|
266
255
|
run_manager = await callback_manager.on_chain_start(
|
|
@@ -321,9 +310,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
321
310
|
|
|
322
311
|
Yields:
|
|
323
312
|
The output of the branch that was run.
|
|
324
|
-
|
|
325
|
-
Raises:
|
|
326
|
-
BaseException: If an error occurs during the execution of the Runnable.
|
|
327
313
|
"""
|
|
328
314
|
config = ensure_config(config)
|
|
329
315
|
callback_manager = get_callback_manager_for_config(config)
|
|
@@ -408,9 +394,6 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
408
394
|
|
|
409
395
|
Yields:
|
|
410
396
|
The output of the branch that was run.
|
|
411
|
-
|
|
412
|
-
Raises:
|
|
413
|
-
BaseException: If an error occurs during the execution of the Runnable.
|
|
414
397
|
"""
|
|
415
398
|
config = ensure_config(config)
|
|
416
399
|
callback_manager = get_async_callback_manager_for_config(config)
|
|
@@ -10,23 +10,33 @@ from concurrent.futures import Executor, Future, ThreadPoolExecutor
|
|
|
10
10
|
from contextlib import contextmanager
|
|
11
11
|
from contextvars import Context, ContextVar, Token, copy_context
|
|
12
12
|
from functools import partial
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import (
|
|
14
|
+
TYPE_CHECKING,
|
|
15
|
+
Any,
|
|
16
|
+
Callable,
|
|
17
|
+
Optional,
|
|
18
|
+
ParamSpec,
|
|
19
|
+
TypeVar,
|
|
20
|
+
Union,
|
|
21
|
+
cast,
|
|
22
|
+
)
|
|
14
23
|
|
|
15
|
-
from
|
|
24
|
+
from langsmith.run_helpers import _set_tracing_context, get_tracing_context
|
|
25
|
+
from typing_extensions import TypedDict
|
|
16
26
|
|
|
27
|
+
from langchain_core.callbacks.manager import AsyncCallbackManager, CallbackManager
|
|
17
28
|
from langchain_core.runnables.utils import (
|
|
18
29
|
Input,
|
|
19
30
|
Output,
|
|
20
31
|
accepts_config,
|
|
21
32
|
accepts_run_manager,
|
|
22
33
|
)
|
|
34
|
+
from langchain_core.tracers.langchain import LangChainTracer
|
|
23
35
|
|
|
24
36
|
if TYPE_CHECKING:
|
|
25
37
|
from langchain_core.callbacks.base import BaseCallbackManager, Callbacks
|
|
26
38
|
from langchain_core.callbacks.manager import (
|
|
27
|
-
AsyncCallbackManager,
|
|
28
39
|
AsyncCallbackManagerForChainRun,
|
|
29
|
-
CallbackManager,
|
|
30
40
|
CallbackManagerForChainRun,
|
|
31
41
|
)
|
|
32
42
|
else:
|
|
@@ -125,9 +135,10 @@ def _set_config_context(
|
|
|
125
135
|
|
|
126
136
|
Args:
|
|
127
137
|
config (RunnableConfig): The config to set.
|
|
128
|
-
"""
|
|
129
|
-
from langchain_core.tracers.langchain import LangChainTracer
|
|
130
138
|
|
|
139
|
+
Returns:
|
|
140
|
+
The token to reset the config and the previous tracing context.
|
|
141
|
+
"""
|
|
131
142
|
config_token = var_child_runnable_config.set(config)
|
|
132
143
|
current_context = None
|
|
133
144
|
if (
|
|
@@ -147,8 +158,6 @@ def _set_config_context(
|
|
|
147
158
|
)
|
|
148
159
|
and (run := tracer.run_map.get(str(parent_run_id)))
|
|
149
160
|
):
|
|
150
|
-
from langsmith.run_helpers import _set_tracing_context, get_tracing_context
|
|
151
|
-
|
|
152
161
|
current_context = get_tracing_context()
|
|
153
162
|
_set_tracing_context({"parent": run})
|
|
154
163
|
return config_token, current_context
|
|
@@ -160,9 +169,10 @@ def set_config_context(config: RunnableConfig) -> Generator[Context, None, None]
|
|
|
160
169
|
|
|
161
170
|
Args:
|
|
162
171
|
config (RunnableConfig): The config to set.
|
|
163
|
-
"""
|
|
164
|
-
from langsmith.run_helpers import _set_tracing_context
|
|
165
172
|
|
|
173
|
+
Yields:
|
|
174
|
+
The config context.
|
|
175
|
+
"""
|
|
166
176
|
ctx = copy_context()
|
|
167
177
|
config_token, _ = ctx.run(_set_config_context, config)
|
|
168
178
|
try:
|
|
@@ -475,8 +485,6 @@ def get_callback_manager_for_config(config: RunnableConfig) -> CallbackManager:
|
|
|
475
485
|
Returns:
|
|
476
486
|
CallbackManager: The callback manager.
|
|
477
487
|
"""
|
|
478
|
-
from langchain_core.callbacks.manager import CallbackManager
|
|
479
|
-
|
|
480
488
|
return CallbackManager.configure(
|
|
481
489
|
inheritable_callbacks=config.get("callbacks"),
|
|
482
490
|
inheritable_tags=config.get("tags"),
|
|
@@ -495,8 +503,6 @@ def get_async_callback_manager_for_config(
|
|
|
495
503
|
Returns:
|
|
496
504
|
AsyncCallbackManager: The async callback manager.
|
|
497
505
|
"""
|
|
498
|
-
from langchain_core.callbacks.manager import AsyncCallbackManager
|
|
499
|
-
|
|
500
506
|
return AsyncCallbackManager.configure(
|
|
501
507
|
inheritable_callbacks=config.get("callbacks"),
|
|
502
508
|
inheritable_tags=config.get("tags"),
|
|
@@ -598,9 +604,6 @@ async def run_in_executor(
|
|
|
598
604
|
|
|
599
605
|
Returns:
|
|
600
606
|
Output: The output of the function.
|
|
601
|
-
|
|
602
|
-
Raises:
|
|
603
|
-
RuntimeError: If the function raises a StopIteration.
|
|
604
607
|
"""
|
|
605
608
|
|
|
606
609
|
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
|
|