langchain-core 0.3.79__py3-none-any.whl → 1.0.0__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/__init__.py +1 -1
- langchain_core/_api/__init__.py +3 -4
- langchain_core/_api/beta_decorator.py +23 -26
- langchain_core/_api/deprecation.py +52 -65
- langchain_core/_api/path.py +3 -6
- langchain_core/_import_utils.py +3 -4
- langchain_core/agents.py +19 -19
- langchain_core/caches.py +53 -63
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +323 -334
- langchain_core/callbacks/file.py +44 -44
- langchain_core/callbacks/manager.py +441 -507
- langchain_core/callbacks/stdout.py +29 -30
- langchain_core/callbacks/streaming_stdout.py +32 -32
- langchain_core/callbacks/usage.py +60 -57
- langchain_core/chat_history.py +48 -63
- langchain_core/document_loaders/base.py +23 -23
- langchain_core/document_loaders/langsmith.py +37 -37
- langchain_core/documents/__init__.py +0 -1
- langchain_core/documents/base.py +62 -65
- langchain_core/documents/compressor.py +4 -4
- langchain_core/documents/transformers.py +28 -29
- langchain_core/embeddings/fake.py +50 -54
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/example_selectors/semantic_similarity.py +21 -25
- langchain_core/exceptions.py +10 -11
- langchain_core/globals.py +3 -151
- langchain_core/indexing/api.py +61 -66
- langchain_core/indexing/base.py +58 -58
- langchain_core/indexing/in_memory.py +3 -3
- langchain_core/language_models/__init__.py +14 -27
- langchain_core/language_models/_utils.py +270 -84
- langchain_core/language_models/base.py +55 -162
- langchain_core/language_models/chat_models.py +442 -402
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +61 -39
- langchain_core/language_models/llms.py +123 -231
- langchain_core/load/dump.py +4 -5
- langchain_core/load/load.py +18 -28
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +39 -40
- langchain_core/messages/__init__.py +61 -22
- langchain_core/messages/ai.py +368 -163
- langchain_core/messages/base.py +214 -43
- langchain_core/messages/block_translators/__init__.py +111 -0
- langchain_core/messages/block_translators/anthropic.py +470 -0
- langchain_core/messages/block_translators/bedrock.py +94 -0
- langchain_core/messages/block_translators/bedrock_converse.py +297 -0
- langchain_core/messages/block_translators/google_genai.py +530 -0
- langchain_core/messages/block_translators/google_vertexai.py +21 -0
- langchain_core/messages/block_translators/groq.py +143 -0
- langchain_core/messages/block_translators/langchain_v0.py +301 -0
- langchain_core/messages/block_translators/openai.py +1010 -0
- langchain_core/messages/chat.py +2 -6
- langchain_core/messages/content.py +1423 -0
- langchain_core/messages/function.py +6 -10
- langchain_core/messages/human.py +41 -38
- langchain_core/messages/modifier.py +2 -2
- langchain_core/messages/system.py +38 -28
- langchain_core/messages/tool.py +96 -103
- langchain_core/messages/utils.py +478 -504
- langchain_core/output_parsers/__init__.py +1 -14
- langchain_core/output_parsers/base.py +58 -61
- langchain_core/output_parsers/json.py +7 -8
- langchain_core/output_parsers/list.py +5 -7
- langchain_core/output_parsers/openai_functions.py +49 -47
- langchain_core/output_parsers/openai_tools.py +14 -19
- langchain_core/output_parsers/pydantic.py +12 -13
- langchain_core/output_parsers/string.py +2 -2
- langchain_core/output_parsers/transform.py +15 -17
- langchain_core/output_parsers/xml.py +8 -10
- langchain_core/outputs/__init__.py +1 -1
- langchain_core/outputs/chat_generation.py +18 -18
- langchain_core/outputs/chat_result.py +1 -3
- langchain_core/outputs/generation.py +8 -8
- langchain_core/outputs/llm_result.py +10 -10
- langchain_core/prompt_values.py +12 -12
- langchain_core/prompts/__init__.py +3 -27
- langchain_core/prompts/base.py +45 -55
- langchain_core/prompts/chat.py +254 -313
- langchain_core/prompts/dict.py +5 -5
- langchain_core/prompts/few_shot.py +81 -88
- langchain_core/prompts/few_shot_with_templates.py +11 -13
- langchain_core/prompts/image.py +12 -14
- langchain_core/prompts/loading.py +6 -8
- langchain_core/prompts/message.py +3 -3
- langchain_core/prompts/prompt.py +24 -39
- langchain_core/prompts/string.py +4 -4
- langchain_core/prompts/structured.py +42 -50
- langchain_core/rate_limiters.py +51 -60
- langchain_core/retrievers.py +49 -190
- langchain_core/runnables/base.py +1484 -1709
- langchain_core/runnables/branch.py +45 -61
- langchain_core/runnables/config.py +80 -88
- langchain_core/runnables/configurable.py +117 -134
- langchain_core/runnables/fallbacks.py +83 -79
- langchain_core/runnables/graph.py +85 -95
- langchain_core/runnables/graph_ascii.py +27 -28
- langchain_core/runnables/graph_mermaid.py +38 -50
- langchain_core/runnables/graph_png.py +15 -16
- langchain_core/runnables/history.py +135 -148
- langchain_core/runnables/passthrough.py +124 -150
- langchain_core/runnables/retry.py +46 -51
- langchain_core/runnables/router.py +25 -30
- langchain_core/runnables/schema.py +79 -74
- langchain_core/runnables/utils.py +62 -68
- langchain_core/stores.py +81 -115
- langchain_core/structured_query.py +8 -8
- langchain_core/sys_info.py +27 -29
- langchain_core/tools/__init__.py +1 -14
- langchain_core/tools/base.py +179 -187
- langchain_core/tools/convert.py +131 -139
- langchain_core/tools/render.py +10 -10
- langchain_core/tools/retriever.py +11 -11
- langchain_core/tools/simple.py +19 -24
- langchain_core/tools/structured.py +30 -39
- langchain_core/tracers/__init__.py +1 -9
- langchain_core/tracers/base.py +97 -99
- langchain_core/tracers/context.py +29 -52
- langchain_core/tracers/core.py +50 -60
- langchain_core/tracers/evaluation.py +11 -11
- langchain_core/tracers/event_stream.py +115 -70
- langchain_core/tracers/langchain.py +21 -21
- langchain_core/tracers/log_stream.py +43 -43
- langchain_core/tracers/memory_stream.py +3 -3
- langchain_core/tracers/root_listeners.py +16 -16
- langchain_core/tracers/run_collector.py +2 -4
- langchain_core/tracers/schemas.py +0 -129
- langchain_core/tracers/stdout.py +3 -3
- langchain_core/utils/__init__.py +1 -4
- langchain_core/utils/_merge.py +46 -8
- langchain_core/utils/aiter.py +57 -61
- langchain_core/utils/env.py +9 -9
- langchain_core/utils/function_calling.py +89 -191
- langchain_core/utils/html.py +7 -8
- langchain_core/utils/input.py +6 -6
- langchain_core/utils/interactive_env.py +1 -1
- langchain_core/utils/iter.py +37 -42
- langchain_core/utils/json.py +4 -3
- langchain_core/utils/json_schema.py +8 -8
- langchain_core/utils/mustache.py +9 -11
- langchain_core/utils/pydantic.py +33 -35
- langchain_core/utils/strings.py +5 -5
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +80 -54
- langchain_core/vectorstores/base.py +129 -164
- langchain_core/vectorstores/in_memory.py +99 -174
- langchain_core/vectorstores/utils.py +5 -5
- langchain_core/version.py +1 -1
- {langchain_core-0.3.79.dist-info → langchain_core-1.0.0.dist-info}/METADATA +28 -27
- langchain_core-1.0.0.dist-info/RECORD +172 -0
- {langchain_core-0.3.79.dist-info → langchain_core-1.0.0.dist-info}/WHEEL +1 -1
- langchain_core/beta/__init__.py +0 -1
- langchain_core/beta/runnables/__init__.py +0 -1
- langchain_core/beta/runnables/context.py +0 -447
- langchain_core/memory.py +0 -120
- langchain_core/messages/content_blocks.py +0 -176
- langchain_core/prompts/pipeline.py +0 -138
- langchain_core/pydantic_v1/__init__.py +0 -30
- langchain_core/pydantic_v1/dataclasses.py +0 -23
- langchain_core/pydantic_v1/main.py +0 -23
- langchain_core/tracers/langchain_v1.py +0 -31
- langchain_core/utils/loading.py +0 -35
- langchain_core-0.3.79.dist-info/RECORD +0 -174
- langchain_core-0.3.79.dist-info/entry_points.txt +0 -4
|
@@ -5,8 +5,9 @@ from __future__ import annotations
|
|
|
5
5
|
import ast
|
|
6
6
|
import asyncio
|
|
7
7
|
import inspect
|
|
8
|
+
import sys
|
|
8
9
|
import textwrap
|
|
9
|
-
from collections.abc import Mapping, Sequence
|
|
10
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
10
11
|
from contextvars import Context
|
|
11
12
|
from functools import lru_cache
|
|
12
13
|
from inspect import signature
|
|
@@ -14,15 +15,13 @@ from itertools import groupby
|
|
|
14
15
|
from typing import (
|
|
15
16
|
TYPE_CHECKING,
|
|
16
17
|
Any,
|
|
17
|
-
Callable,
|
|
18
18
|
NamedTuple,
|
|
19
|
-
Optional,
|
|
20
19
|
Protocol,
|
|
20
|
+
TypeGuard,
|
|
21
21
|
TypeVar,
|
|
22
|
-
Union,
|
|
23
22
|
)
|
|
24
23
|
|
|
25
|
-
from typing_extensions import
|
|
24
|
+
from typing_extensions import override
|
|
26
25
|
|
|
27
26
|
# Re-export create-model for backwards compatibility
|
|
28
27
|
from langchain_core.utils.pydantic import create_model # noqa: F401
|
|
@@ -57,7 +56,7 @@ async def gated_coro(semaphore: asyncio.Semaphore, coro: Coroutine) -> Any:
|
|
|
57
56
|
return await coro
|
|
58
57
|
|
|
59
58
|
|
|
60
|
-
async def gather_with_concurrency(n:
|
|
59
|
+
async def gather_with_concurrency(n: int | None, *coros: Coroutine) -> list:
|
|
61
60
|
"""Gather coroutines with a limit on the number of concurrent coroutines.
|
|
62
61
|
|
|
63
62
|
Args:
|
|
@@ -82,7 +81,7 @@ def accepts_run_manager(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
82
81
|
callable: The callable to check.
|
|
83
82
|
|
|
84
83
|
Returns:
|
|
85
|
-
|
|
84
|
+
`True` if the callable accepts a run_manager argument, `False` otherwise.
|
|
86
85
|
"""
|
|
87
86
|
try:
|
|
88
87
|
return signature(callable).parameters.get("run_manager") is not None
|
|
@@ -97,7 +96,7 @@ def accepts_config(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
97
96
|
callable: The callable to check.
|
|
98
97
|
|
|
99
98
|
Returns:
|
|
100
|
-
|
|
99
|
+
`True` if the callable accepts a config argument, `False` otherwise.
|
|
101
100
|
"""
|
|
102
101
|
try:
|
|
103
102
|
return signature(callable).parameters.get("config") is not None
|
|
@@ -112,7 +111,7 @@ def accepts_context(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
112
111
|
callable: The callable to check.
|
|
113
112
|
|
|
114
113
|
Returns:
|
|
115
|
-
|
|
114
|
+
`True` if the callable accepts a context argument, `False` otherwise.
|
|
116
115
|
"""
|
|
117
116
|
try:
|
|
118
117
|
return signature(callable).parameters.get("context") is not None
|
|
@@ -120,15 +119,13 @@ def accepts_context(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
120
119
|
return False
|
|
121
120
|
|
|
122
121
|
|
|
123
|
-
@lru_cache(maxsize=1)
|
|
124
122
|
def asyncio_accepts_context() -> bool:
|
|
125
|
-
"""
|
|
123
|
+
"""Check if asyncio.create_task accepts a `context` arg.
|
|
126
124
|
|
|
127
125
|
Returns:
|
|
128
|
-
|
|
129
|
-
otherwise.
|
|
126
|
+
True if `asyncio.create_task` accepts a context argument, `False` otherwise.
|
|
130
127
|
"""
|
|
131
|
-
return
|
|
128
|
+
return sys.version_info >= (3, 11)
|
|
132
129
|
|
|
133
130
|
|
|
134
131
|
def coro_with_context(
|
|
@@ -139,7 +136,7 @@ def coro_with_context(
|
|
|
139
136
|
Args:
|
|
140
137
|
coro: The coroutine to await.
|
|
141
138
|
context: The context to use.
|
|
142
|
-
create_task: Whether to create a task.
|
|
139
|
+
create_task: Whether to create a task.
|
|
143
140
|
|
|
144
141
|
Returns:
|
|
145
142
|
The coroutine with the context.
|
|
@@ -343,7 +340,7 @@ class GetLambdaSource(ast.NodeVisitor):
|
|
|
343
340
|
|
|
344
341
|
def __init__(self) -> None:
|
|
345
342
|
"""Initialize the visitor."""
|
|
346
|
-
self.source:
|
|
343
|
+
self.source: str | None = None
|
|
347
344
|
self.count = 0
|
|
348
345
|
|
|
349
346
|
@override
|
|
@@ -358,15 +355,14 @@ class GetLambdaSource(ast.NodeVisitor):
|
|
|
358
355
|
self.source = ast.unparse(node)
|
|
359
356
|
|
|
360
357
|
|
|
361
|
-
def get_function_first_arg_dict_keys(func: Callable) ->
|
|
358
|
+
def get_function_first_arg_dict_keys(func: Callable) -> list[str] | None:
|
|
362
359
|
"""Get the keys of the first argument of a function if it is a dict.
|
|
363
360
|
|
|
364
361
|
Args:
|
|
365
362
|
func: The function to check.
|
|
366
363
|
|
|
367
364
|
Returns:
|
|
368
|
-
|
|
369
|
-
None otherwise.
|
|
365
|
+
The keys of the first argument if it is a dict, None otherwise.
|
|
370
366
|
"""
|
|
371
367
|
try:
|
|
372
368
|
code = inspect.getsource(func)
|
|
@@ -378,14 +374,14 @@ def get_function_first_arg_dict_keys(func: Callable) -> Optional[list[str]]:
|
|
|
378
374
|
return None
|
|
379
375
|
|
|
380
376
|
|
|
381
|
-
def get_lambda_source(func: Callable) ->
|
|
377
|
+
def get_lambda_source(func: Callable) -> str | None:
|
|
382
378
|
"""Get the source code of a lambda function.
|
|
383
379
|
|
|
384
380
|
Args:
|
|
385
381
|
func: a Callable that can be a lambda function.
|
|
386
382
|
|
|
387
383
|
Returns:
|
|
388
|
-
|
|
384
|
+
the source code of the lambda function.
|
|
389
385
|
"""
|
|
390
386
|
try:
|
|
391
387
|
name = func.__name__ if func.__name__ != "<lambda>" else None
|
|
@@ -409,7 +405,7 @@ def get_function_nonlocals(func: Callable) -> list[Any]:
|
|
|
409
405
|
func: The function to check.
|
|
410
406
|
|
|
411
407
|
Returns:
|
|
412
|
-
|
|
408
|
+
The nonlocal variables accessed by the function.
|
|
413
409
|
"""
|
|
414
410
|
try:
|
|
415
411
|
code = inspect.getsource(func)
|
|
@@ -452,7 +448,7 @@ def indent_lines_after_first(text: str, prefix: str) -> str:
|
|
|
452
448
|
prefix: Used to determine the number of spaces to indent.
|
|
453
449
|
|
|
454
450
|
Returns:
|
|
455
|
-
|
|
451
|
+
The indented text.
|
|
456
452
|
"""
|
|
457
453
|
n_spaces = len(prefix)
|
|
458
454
|
spaces = " " * n_spaces
|
|
@@ -520,31 +516,31 @@ class SupportsAdd(Protocol[_T_contra, _T_co]):
|
|
|
520
516
|
Addable = TypeVar("Addable", bound=SupportsAdd[Any, Any])
|
|
521
517
|
|
|
522
518
|
|
|
523
|
-
def add(addables: Iterable[Addable]) ->
|
|
519
|
+
def add(addables: Iterable[Addable]) -> Addable | None:
|
|
524
520
|
"""Add a sequence of addable objects together.
|
|
525
521
|
|
|
526
522
|
Args:
|
|
527
523
|
addables: The addable objects to add.
|
|
528
524
|
|
|
529
525
|
Returns:
|
|
530
|
-
|
|
526
|
+
The result of adding the addable objects.
|
|
531
527
|
"""
|
|
532
|
-
final:
|
|
528
|
+
final: Addable | None = None
|
|
533
529
|
for chunk in addables:
|
|
534
530
|
final = chunk if final is None else final + chunk
|
|
535
531
|
return final
|
|
536
532
|
|
|
537
533
|
|
|
538
|
-
async def aadd(addables: AsyncIterable[Addable]) ->
|
|
534
|
+
async def aadd(addables: AsyncIterable[Addable]) -> Addable | None:
|
|
539
535
|
"""Asynchronously add a sequence of addable objects together.
|
|
540
536
|
|
|
541
537
|
Args:
|
|
542
538
|
addables: The addable objects to add.
|
|
543
539
|
|
|
544
540
|
Returns:
|
|
545
|
-
|
|
541
|
+
The result of adding the addable objects.
|
|
546
542
|
"""
|
|
547
|
-
final:
|
|
543
|
+
final: Addable | None = None
|
|
548
544
|
async for chunk in addables:
|
|
549
545
|
final = chunk if final is None else final + chunk
|
|
550
546
|
return final
|
|
@@ -555,14 +551,14 @@ class ConfigurableField(NamedTuple):
|
|
|
555
551
|
|
|
556
552
|
id: str
|
|
557
553
|
"""The unique identifier of the field."""
|
|
558
|
-
name:
|
|
559
|
-
"""The name of the field.
|
|
560
|
-
description:
|
|
561
|
-
"""The description of the field.
|
|
562
|
-
annotation:
|
|
563
|
-
"""The annotation of the field.
|
|
554
|
+
name: str | None = None
|
|
555
|
+
"""The name of the field. """
|
|
556
|
+
description: str | None = None
|
|
557
|
+
"""The description of the field. """
|
|
558
|
+
annotation: Any | None = None
|
|
559
|
+
"""The annotation of the field. """
|
|
564
560
|
is_shared: bool = False
|
|
565
|
-
"""Whether the field is shared.
|
|
561
|
+
"""Whether the field is shared."""
|
|
566
562
|
|
|
567
563
|
@override
|
|
568
564
|
def __hash__(self) -> int:
|
|
@@ -578,12 +574,12 @@ class ConfigurableFieldSingleOption(NamedTuple):
|
|
|
578
574
|
"""The options for the field."""
|
|
579
575
|
default: str
|
|
580
576
|
"""The default value for the field."""
|
|
581
|
-
name:
|
|
582
|
-
"""The name of the field.
|
|
583
|
-
description:
|
|
584
|
-
"""The description of the field.
|
|
577
|
+
name: str | None = None
|
|
578
|
+
"""The name of the field. """
|
|
579
|
+
description: str | None = None
|
|
580
|
+
"""The description of the field. """
|
|
585
581
|
is_shared: bool = False
|
|
586
|
-
"""Whether the field is shared.
|
|
582
|
+
"""Whether the field is shared."""
|
|
587
583
|
|
|
588
584
|
@override
|
|
589
585
|
def __hash__(self) -> int:
|
|
@@ -599,21 +595,21 @@ class ConfigurableFieldMultiOption(NamedTuple):
|
|
|
599
595
|
"""The options for the field."""
|
|
600
596
|
default: Sequence[str]
|
|
601
597
|
"""The default values for the field."""
|
|
602
|
-
name:
|
|
603
|
-
"""The name of the field.
|
|
604
|
-
description:
|
|
605
|
-
"""The description of the field.
|
|
598
|
+
name: str | None = None
|
|
599
|
+
"""The name of the field. """
|
|
600
|
+
description: str | None = None
|
|
601
|
+
"""The description of the field. """
|
|
606
602
|
is_shared: bool = False
|
|
607
|
-
"""Whether the field is shared.
|
|
603
|
+
"""Whether the field is shared."""
|
|
608
604
|
|
|
609
605
|
@override
|
|
610
606
|
def __hash__(self) -> int:
|
|
611
607
|
return hash((self.id, tuple(self.options.keys()), tuple(self.default)))
|
|
612
608
|
|
|
613
609
|
|
|
614
|
-
AnyConfigurableField =
|
|
615
|
-
ConfigurableField
|
|
616
|
-
|
|
610
|
+
AnyConfigurableField = (
|
|
611
|
+
ConfigurableField | ConfigurableFieldSingleOption | ConfigurableFieldMultiOption
|
|
612
|
+
)
|
|
617
613
|
|
|
618
614
|
|
|
619
615
|
class ConfigurableFieldSpec(NamedTuple):
|
|
@@ -623,16 +619,16 @@ class ConfigurableFieldSpec(NamedTuple):
|
|
|
623
619
|
"""The unique identifier of the field."""
|
|
624
620
|
annotation: Any
|
|
625
621
|
"""The annotation of the field."""
|
|
626
|
-
name:
|
|
627
|
-
"""The name of the field.
|
|
628
|
-
description:
|
|
629
|
-
"""The description of the field.
|
|
622
|
+
name: str | None = None
|
|
623
|
+
"""The name of the field. """
|
|
624
|
+
description: str | None = None
|
|
625
|
+
"""The description of the field. """
|
|
630
626
|
default: Any = None
|
|
631
|
-
"""The default value for the field.
|
|
627
|
+
"""The default value for the field. """
|
|
632
628
|
is_shared: bool = False
|
|
633
|
-
"""Whether the field is shared.
|
|
634
|
-
dependencies:
|
|
635
|
-
"""The dependencies of the field.
|
|
629
|
+
"""Whether the field is shared."""
|
|
630
|
+
dependencies: list[str] | None = None
|
|
631
|
+
"""The dependencies of the field. """
|
|
636
632
|
|
|
637
633
|
|
|
638
634
|
def get_unique_config_specs(
|
|
@@ -644,7 +640,7 @@ def get_unique_config_specs(
|
|
|
644
640
|
specs: The config specs.
|
|
645
641
|
|
|
646
642
|
Returns:
|
|
647
|
-
|
|
643
|
+
The unique config specs.
|
|
648
644
|
|
|
649
645
|
Raises:
|
|
650
646
|
ValueError: If the runnable sequence contains conflicting config specs.
|
|
@@ -671,12 +667,12 @@ class _RootEventFilter:
|
|
|
671
667
|
def __init__(
|
|
672
668
|
self,
|
|
673
669
|
*,
|
|
674
|
-
include_names:
|
|
675
|
-
include_types:
|
|
676
|
-
include_tags:
|
|
677
|
-
exclude_names:
|
|
678
|
-
exclude_types:
|
|
679
|
-
exclude_tags:
|
|
670
|
+
include_names: Sequence[str] | None = None,
|
|
671
|
+
include_types: Sequence[str] | None = None,
|
|
672
|
+
include_tags: Sequence[str] | None = None,
|
|
673
|
+
exclude_names: Sequence[str] | None = None,
|
|
674
|
+
exclude_types: Sequence[str] | None = None,
|
|
675
|
+
exclude_tags: Sequence[str] | None = None,
|
|
680
676
|
) -> None:
|
|
681
677
|
"""Utility to filter the root event in the astream_events implementation.
|
|
682
678
|
|
|
@@ -731,8 +727,7 @@ def is_async_generator(
|
|
|
731
727
|
func: The function to check.
|
|
732
728
|
|
|
733
729
|
Returns:
|
|
734
|
-
|
|
735
|
-
an async generator, False otherwise.
|
|
730
|
+
`True` if the function is an async generator, `False` otherwise.
|
|
736
731
|
"""
|
|
737
732
|
return inspect.isasyncgenfunction(func) or (
|
|
738
733
|
hasattr(func, "__call__") # noqa: B004
|
|
@@ -749,8 +744,7 @@ def is_async_callable(
|
|
|
749
744
|
func: The function to check.
|
|
750
745
|
|
|
751
746
|
Returns:
|
|
752
|
-
|
|
753
|
-
False otherwise.
|
|
747
|
+
`True` if the function is async, `False` otherwise.
|
|
754
748
|
"""
|
|
755
749
|
return asyncio.iscoroutinefunction(func) or (
|
|
756
750
|
hasattr(func, "__call__") # noqa: B004
|
langchain_core/stores.py
CHANGED
|
@@ -11,9 +11,7 @@ from collections.abc import AsyncIterator, Iterator, Sequence
|
|
|
11
11
|
from typing import (
|
|
12
12
|
Any,
|
|
13
13
|
Generic,
|
|
14
|
-
Optional,
|
|
15
14
|
TypeVar,
|
|
16
|
-
Union,
|
|
17
15
|
)
|
|
18
16
|
|
|
19
17
|
from typing_extensions import override
|
|
@@ -49,55 +47,53 @@ class BaseStore(ABC, Generic[K, V]):
|
|
|
49
47
|
which will usually be more efficient by saving on round trips to the store.
|
|
50
48
|
|
|
51
49
|
Examples:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
yield key
|
|
81
|
-
|
|
50
|
+
```python
|
|
51
|
+
from langchain.storage import BaseStore
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class MyInMemoryStore(BaseStore[str, int]):
|
|
55
|
+
def __init__(self) -> None:
|
|
56
|
+
self.store: dict[str, int] = {}
|
|
57
|
+
|
|
58
|
+
def mget(self, keys: Sequence[str]) -> list[int | None]:
|
|
59
|
+
return [self.store.get(key) for key in keys]
|
|
60
|
+
|
|
61
|
+
def mset(self, key_value_pairs: Sequence[tuple[str, int]]) -> None:
|
|
62
|
+
for key, value in key_value_pairs:
|
|
63
|
+
self.store[key] = value
|
|
64
|
+
|
|
65
|
+
def mdelete(self, keys: Sequence[str]) -> None:
|
|
66
|
+
for key in keys:
|
|
67
|
+
if key in self.store:
|
|
68
|
+
del self.store[key]
|
|
69
|
+
|
|
70
|
+
def yield_keys(self, prefix: str | None = None) -> Iterator[str]:
|
|
71
|
+
if prefix is None:
|
|
72
|
+
yield from self.store.keys()
|
|
73
|
+
else:
|
|
74
|
+
for key in self.store.keys():
|
|
75
|
+
if key.startswith(prefix):
|
|
76
|
+
yield key
|
|
77
|
+
```
|
|
82
78
|
"""
|
|
83
79
|
|
|
84
80
|
@abstractmethod
|
|
85
|
-
def mget(self, keys: Sequence[K]) -> list[
|
|
81
|
+
def mget(self, keys: Sequence[K]) -> list[V | None]:
|
|
86
82
|
"""Get the values associated with the given keys.
|
|
87
83
|
|
|
88
84
|
Args:
|
|
89
|
-
keys
|
|
85
|
+
keys: A sequence of keys.
|
|
90
86
|
|
|
91
87
|
Returns:
|
|
92
88
|
A sequence of optional values associated with the keys.
|
|
93
89
|
If a key is not found, the corresponding value will be None.
|
|
94
90
|
"""
|
|
95
91
|
|
|
96
|
-
async def amget(self, keys: Sequence[K]) -> list[
|
|
92
|
+
async def amget(self, keys: Sequence[K]) -> list[V | None]:
|
|
97
93
|
"""Async get the values associated with the given keys.
|
|
98
94
|
|
|
99
95
|
Args:
|
|
100
|
-
keys
|
|
96
|
+
keys: A sequence of keys.
|
|
101
97
|
|
|
102
98
|
Returns:
|
|
103
99
|
A sequence of optional values associated with the keys.
|
|
@@ -110,14 +106,14 @@ class BaseStore(ABC, Generic[K, V]):
|
|
|
110
106
|
"""Set the values for the given keys.
|
|
111
107
|
|
|
112
108
|
Args:
|
|
113
|
-
key_value_pairs
|
|
109
|
+
key_value_pairs: A sequence of key-value pairs.
|
|
114
110
|
"""
|
|
115
111
|
|
|
116
112
|
async def amset(self, key_value_pairs: Sequence[tuple[K, V]]) -> None:
|
|
117
113
|
"""Async set the values for the given keys.
|
|
118
114
|
|
|
119
115
|
Args:
|
|
120
|
-
key_value_pairs
|
|
116
|
+
key_value_pairs: A sequence of key-value pairs.
|
|
121
117
|
"""
|
|
122
118
|
return await run_in_executor(None, self.mset, key_value_pairs)
|
|
123
119
|
|
|
@@ -126,42 +122,40 @@ class BaseStore(ABC, Generic[K, V]):
|
|
|
126
122
|
"""Delete the given keys and their associated values.
|
|
127
123
|
|
|
128
124
|
Args:
|
|
129
|
-
keys
|
|
125
|
+
keys: A sequence of keys to delete.
|
|
130
126
|
"""
|
|
131
127
|
|
|
132
128
|
async def amdelete(self, keys: Sequence[K]) -> None:
|
|
133
129
|
"""Async delete the given keys and their associated values.
|
|
134
130
|
|
|
135
131
|
Args:
|
|
136
|
-
keys
|
|
132
|
+
keys: A sequence of keys to delete.
|
|
137
133
|
"""
|
|
138
134
|
return await run_in_executor(None, self.mdelete, keys)
|
|
139
135
|
|
|
140
136
|
@abstractmethod
|
|
141
|
-
def yield_keys(
|
|
142
|
-
self, *, prefix: Optional[str] = None
|
|
143
|
-
) -> Union[Iterator[K], Iterator[str]]:
|
|
137
|
+
def yield_keys(self, *, prefix: str | None = None) -> Iterator[K] | Iterator[str]:
|
|
144
138
|
"""Get an iterator over keys that match the given prefix.
|
|
145
139
|
|
|
146
140
|
Args:
|
|
147
|
-
prefix
|
|
141
|
+
prefix: The prefix to match.
|
|
148
142
|
|
|
149
143
|
Yields:
|
|
150
|
-
|
|
144
|
+
An iterator over keys that match the given prefix.
|
|
151
145
|
This method is allowed to return an iterator over either K or str
|
|
152
146
|
depending on what makes more sense for the given store.
|
|
153
147
|
"""
|
|
154
148
|
|
|
155
149
|
async def ayield_keys(
|
|
156
|
-
self, *, prefix:
|
|
157
|
-
) ->
|
|
150
|
+
self, *, prefix: str | None = None
|
|
151
|
+
) -> AsyncIterator[K] | AsyncIterator[str]:
|
|
158
152
|
"""Async get an iterator over keys that match the given prefix.
|
|
159
153
|
|
|
160
154
|
Args:
|
|
161
|
-
prefix
|
|
155
|
+
prefix: The prefix to match.
|
|
162
156
|
|
|
163
157
|
Yields:
|
|
164
|
-
|
|
158
|
+
The keys that match the given prefix.
|
|
165
159
|
This method is allowed to return an iterator over either K or str
|
|
166
160
|
depending on what makes more sense for the given store.
|
|
167
161
|
"""
|
|
@@ -184,28 +178,12 @@ class InMemoryBaseStore(BaseStore[str, V], Generic[V]):
|
|
|
184
178
|
"""Initialize an empty store."""
|
|
185
179
|
self.store: dict[str, V] = {}
|
|
186
180
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Args:
|
|
191
|
-
keys (Sequence[str]): A sequence of keys.
|
|
192
|
-
|
|
193
|
-
Returns:
|
|
194
|
-
A sequence of optional values associated with the keys.
|
|
195
|
-
If a key is not found, the corresponding value will be None.
|
|
196
|
-
"""
|
|
181
|
+
@override
|
|
182
|
+
def mget(self, keys: Sequence[str]) -> list[V | None]:
|
|
197
183
|
return [self.store.get(key) for key in keys]
|
|
198
184
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
Args:
|
|
203
|
-
keys (Sequence[str]): A sequence of keys.
|
|
204
|
-
|
|
205
|
-
Returns:
|
|
206
|
-
A sequence of optional values associated with the keys.
|
|
207
|
-
If a key is not found, the corresponding value will be None.
|
|
208
|
-
"""
|
|
185
|
+
@override
|
|
186
|
+
async def amget(self, keys: Sequence[str]) -> list[V | None]:
|
|
209
187
|
return self.mget(keys)
|
|
210
188
|
|
|
211
189
|
@override
|
|
@@ -217,32 +195,24 @@ class InMemoryBaseStore(BaseStore[str, V], Generic[V]):
|
|
|
217
195
|
async def amset(self, key_value_pairs: Sequence[tuple[str, V]]) -> None:
|
|
218
196
|
return self.mset(key_value_pairs)
|
|
219
197
|
|
|
198
|
+
@override
|
|
220
199
|
def mdelete(self, keys: Sequence[str]) -> None:
|
|
221
|
-
"""Delete the given keys and their associated values.
|
|
222
|
-
|
|
223
|
-
Args:
|
|
224
|
-
keys (Sequence[str]): A sequence of keys to delete.
|
|
225
|
-
"""
|
|
226
200
|
for key in keys:
|
|
227
201
|
if key in self.store:
|
|
228
202
|
del self.store[key]
|
|
229
203
|
|
|
204
|
+
@override
|
|
230
205
|
async def amdelete(self, keys: Sequence[str]) -> None:
|
|
231
|
-
"""Async delete the given keys and their associated values.
|
|
232
|
-
|
|
233
|
-
Args:
|
|
234
|
-
keys (Sequence[str]): A sequence of keys to delete.
|
|
235
|
-
"""
|
|
236
206
|
self.mdelete(keys)
|
|
237
207
|
|
|
238
|
-
def yield_keys(self, prefix:
|
|
208
|
+
def yield_keys(self, prefix: str | None = None) -> Iterator[str]:
|
|
239
209
|
"""Get an iterator over keys that match the given prefix.
|
|
240
210
|
|
|
241
211
|
Args:
|
|
242
|
-
prefix
|
|
212
|
+
prefix: The prefix to match.
|
|
243
213
|
|
|
244
214
|
Yields:
|
|
245
|
-
|
|
215
|
+
The keys that match the given prefix.
|
|
246
216
|
"""
|
|
247
217
|
if prefix is None:
|
|
248
218
|
yield from self.store.keys()
|
|
@@ -251,14 +221,14 @@ class InMemoryBaseStore(BaseStore[str, V], Generic[V]):
|
|
|
251
221
|
if key.startswith(prefix):
|
|
252
222
|
yield key
|
|
253
223
|
|
|
254
|
-
async def ayield_keys(self, prefix:
|
|
224
|
+
async def ayield_keys(self, prefix: str | None = None) -> AsyncIterator[str]:
|
|
255
225
|
"""Async get an async iterator over keys that match the given prefix.
|
|
256
226
|
|
|
257
227
|
Args:
|
|
258
|
-
prefix
|
|
228
|
+
prefix: The prefix to match.
|
|
259
229
|
|
|
260
230
|
Yields:
|
|
261
|
-
|
|
231
|
+
The keys that match the given prefix.
|
|
262
232
|
"""
|
|
263
233
|
if prefix is None:
|
|
264
234
|
for key in self.store:
|
|
@@ -277,21 +247,19 @@ class InMemoryStore(InMemoryBaseStore[Any]):
|
|
|
277
247
|
the key-value pairs.
|
|
278
248
|
|
|
279
249
|
Examples:
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
# ['key2']
|
|
294
|
-
|
|
250
|
+
```python
|
|
251
|
+
from langchain.storage import InMemoryStore
|
|
252
|
+
|
|
253
|
+
store = InMemoryStore()
|
|
254
|
+
store.mset([("key1", "value1"), ("key2", "value2")])
|
|
255
|
+
store.mget(["key1", "key2"])
|
|
256
|
+
# ['value1', 'value2']
|
|
257
|
+
store.mdelete(["key1"])
|
|
258
|
+
list(store.yield_keys())
|
|
259
|
+
# ['key2']
|
|
260
|
+
list(store.yield_keys(prefix="k"))
|
|
261
|
+
# ['key2']
|
|
262
|
+
```
|
|
295
263
|
"""
|
|
296
264
|
|
|
297
265
|
|
|
@@ -303,21 +271,19 @@ class InMemoryByteStore(InMemoryBaseStore[bytes]):
|
|
|
303
271
|
the key-value pairs.
|
|
304
272
|
|
|
305
273
|
Examples:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
# ['key2']
|
|
320
|
-
|
|
274
|
+
```python
|
|
275
|
+
from langchain.storage import InMemoryByteStore
|
|
276
|
+
|
|
277
|
+
store = InMemoryByteStore()
|
|
278
|
+
store.mset([("key1", b"value1"), ("key2", b"value2")])
|
|
279
|
+
store.mget(["key1", "key2"])
|
|
280
|
+
# [b'value1', b'value2']
|
|
281
|
+
store.mdelete(["key1"])
|
|
282
|
+
list(store.yield_keys())
|
|
283
|
+
# ['key2']
|
|
284
|
+
list(store.yield_keys(prefix="k"))
|
|
285
|
+
# ['key2']
|
|
286
|
+
```
|
|
321
287
|
"""
|
|
322
288
|
|
|
323
289
|
|