langchain-core 1.0.0a6__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langchain_core/__init__.py +1 -1
- langchain_core/_api/__init__.py +3 -4
- langchain_core/_api/beta_decorator.py +23 -26
- langchain_core/_api/deprecation.py +51 -64
- langchain_core/_api/path.py +3 -6
- langchain_core/_import_utils.py +3 -4
- langchain_core/agents.py +20 -22
- langchain_core/caches.py +65 -66
- langchain_core/callbacks/__init__.py +1 -8
- langchain_core/callbacks/base.py +321 -336
- langchain_core/callbacks/file.py +44 -44
- langchain_core/callbacks/manager.py +436 -513
- 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 +53 -68
- langchain_core/document_loaders/base.py +27 -25
- langchain_core/document_loaders/blob_loaders.py +1 -1
- langchain_core/document_loaders/langsmith.py +44 -48
- langchain_core/documents/__init__.py +23 -3
- langchain_core/documents/base.py +98 -90
- langchain_core/documents/compressor.py +10 -10
- langchain_core/documents/transformers.py +34 -35
- langchain_core/embeddings/fake.py +50 -54
- langchain_core/example_selectors/length_based.py +1 -1
- langchain_core/example_selectors/semantic_similarity.py +28 -32
- langchain_core/exceptions.py +21 -20
- langchain_core/globals.py +3 -151
- langchain_core/indexing/__init__.py +1 -1
- langchain_core/indexing/api.py +121 -126
- langchain_core/indexing/base.py +73 -75
- langchain_core/indexing/in_memory.py +4 -6
- langchain_core/language_models/__init__.py +14 -29
- langchain_core/language_models/_utils.py +58 -61
- langchain_core/language_models/base.py +53 -162
- langchain_core/language_models/chat_models.py +298 -387
- langchain_core/language_models/fake.py +11 -11
- langchain_core/language_models/fake_chat_models.py +42 -36
- langchain_core/language_models/llms.py +125 -235
- langchain_core/load/dump.py +9 -12
- langchain_core/load/load.py +18 -28
- langchain_core/load/mapping.py +2 -4
- langchain_core/load/serializable.py +42 -40
- langchain_core/messages/__init__.py +10 -16
- langchain_core/messages/ai.py +148 -148
- langchain_core/messages/base.py +53 -51
- langchain_core/messages/block_translators/__init__.py +19 -22
- langchain_core/messages/block_translators/anthropic.py +6 -6
- langchain_core/messages/block_translators/bedrock_converse.py +5 -5
- langchain_core/messages/block_translators/google_genai.py +10 -7
- langchain_core/messages/block_translators/google_vertexai.py +4 -32
- langchain_core/messages/block_translators/groq.py +117 -21
- langchain_core/messages/block_translators/langchain_v0.py +5 -5
- langchain_core/messages/block_translators/openai.py +11 -11
- langchain_core/messages/chat.py +2 -6
- langchain_core/messages/content.py +337 -328
- langchain_core/messages/function.py +6 -10
- langchain_core/messages/human.py +24 -31
- langchain_core/messages/modifier.py +2 -2
- langchain_core/messages/system.py +19 -29
- langchain_core/messages/tool.py +74 -90
- langchain_core/messages/utils.py +474 -504
- langchain_core/output_parsers/__init__.py +13 -10
- langchain_core/output_parsers/base.py +61 -61
- langchain_core/output_parsers/format_instructions.py +9 -4
- langchain_core/output_parsers/json.py +12 -10
- langchain_core/output_parsers/list.py +21 -23
- langchain_core/output_parsers/openai_functions.py +49 -47
- langchain_core/output_parsers/openai_tools.py +16 -21
- langchain_core/output_parsers/pydantic.py +13 -14
- langchain_core/output_parsers/string.py +5 -5
- langchain_core/output_parsers/transform.py +15 -17
- langchain_core/output_parsers/xml.py +35 -34
- 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 +10 -11
- langchain_core/outputs/llm_result.py +10 -10
- langchain_core/prompt_values.py +11 -17
- langchain_core/prompts/__init__.py +3 -27
- langchain_core/prompts/base.py +48 -56
- langchain_core/prompts/chat.py +275 -325
- 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 +4 -6
- langchain_core/prompts/message.py +3 -3
- langchain_core/prompts/prompt.py +24 -39
- langchain_core/prompts/string.py +26 -10
- langchain_core/prompts/structured.py +49 -53
- langchain_core/rate_limiters.py +51 -60
- langchain_core/retrievers.py +61 -198
- langchain_core/runnables/base.py +1476 -1626
- langchain_core/runnables/branch.py +53 -57
- langchain_core/runnables/config.py +72 -89
- langchain_core/runnables/configurable.py +120 -137
- langchain_core/runnables/fallbacks.py +83 -79
- langchain_core/runnables/graph.py +91 -97
- 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 +75 -80
- langchain_core/runnables/utils.py +60 -67
- langchain_core/stores.py +85 -121
- 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 +284 -229
- langchain_core/tools/convert.py +160 -155
- langchain_core/tools/render.py +10 -10
- langchain_core/tools/retriever.py +12 -11
- langchain_core/tools/simple.py +19 -24
- langchain_core/tools/structured.py +32 -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 +49 -53
- langchain_core/tracers/evaluation.py +11 -11
- langchain_core/tracers/event_stream.py +65 -64
- langchain_core/tracers/langchain.py +21 -21
- langchain_core/tracers/log_stream.py +45 -45
- 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 +2 -2
- langchain_core/utils/aiter.py +57 -61
- langchain_core/utils/env.py +9 -9
- langchain_core/utils/function_calling.py +89 -186
- 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 +36 -40
- langchain_core/utils/json.py +4 -3
- langchain_core/utils/json_schema.py +9 -9
- langchain_core/utils/mustache.py +8 -10
- langchain_core/utils/pydantic.py +33 -35
- langchain_core/utils/strings.py +6 -9
- langchain_core/utils/usage.py +1 -1
- langchain_core/utils/utils.py +66 -62
- langchain_core/vectorstores/base.py +182 -216
- langchain_core/vectorstores/in_memory.py +101 -176
- langchain_core/vectorstores/utils.py +5 -5
- langchain_core/version.py +1 -1
- langchain_core-1.0.3.dist-info/METADATA +69 -0
- langchain_core-1.0.3.dist-info/RECORD +172 -0
- {langchain_core-1.0.0a6.dist-info → langchain_core-1.0.3.dist-info}/WHEEL +1 -1
- langchain_core/memory.py +0 -120
- langchain_core/messages/block_translators/ollama.py +0 -47
- 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-1.0.0a6.dist-info/METADATA +0 -67
- langchain_core-1.0.0a6.dist-info/RECORD +0 -181
- langchain_core-1.0.0a6.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,13 +15,10 @@ 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,
|
|
21
20
|
TypeGuard,
|
|
22
21
|
TypeVar,
|
|
23
|
-
Union,
|
|
24
22
|
)
|
|
25
23
|
|
|
26
24
|
from typing_extensions import override
|
|
@@ -58,7 +56,7 @@ async def gated_coro(semaphore: asyncio.Semaphore, coro: Coroutine) -> Any:
|
|
|
58
56
|
return await coro
|
|
59
57
|
|
|
60
58
|
|
|
61
|
-
async def gather_with_concurrency(n:
|
|
59
|
+
async def gather_with_concurrency(n: int | None, *coros: Coroutine) -> list:
|
|
62
60
|
"""Gather coroutines with a limit on the number of concurrent coroutines.
|
|
63
61
|
|
|
64
62
|
Args:
|
|
@@ -83,7 +81,7 @@ def accepts_run_manager(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
83
81
|
callable: The callable to check.
|
|
84
82
|
|
|
85
83
|
Returns:
|
|
86
|
-
|
|
84
|
+
`True` if the callable accepts a run_manager argument, `False` otherwise.
|
|
87
85
|
"""
|
|
88
86
|
try:
|
|
89
87
|
return signature(callable).parameters.get("run_manager") is not None
|
|
@@ -98,7 +96,7 @@ def accepts_config(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
98
96
|
callable: The callable to check.
|
|
99
97
|
|
|
100
98
|
Returns:
|
|
101
|
-
|
|
99
|
+
`True` if the callable accepts a config argument, `False` otherwise.
|
|
102
100
|
"""
|
|
103
101
|
try:
|
|
104
102
|
return signature(callable).parameters.get("config") is not None
|
|
@@ -113,7 +111,7 @@ def accepts_context(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
113
111
|
callable: The callable to check.
|
|
114
112
|
|
|
115
113
|
Returns:
|
|
116
|
-
|
|
114
|
+
`True` if the callable accepts a context argument, `False` otherwise.
|
|
117
115
|
"""
|
|
118
116
|
try:
|
|
119
117
|
return signature(callable).parameters.get("context") is not None
|
|
@@ -121,15 +119,13 @@ def accepts_context(callable: Callable[..., Any]) -> bool: # noqa: A002
|
|
|
121
119
|
return False
|
|
122
120
|
|
|
123
121
|
|
|
124
|
-
@lru_cache(maxsize=1)
|
|
125
122
|
def asyncio_accepts_context() -> bool:
|
|
126
|
-
"""
|
|
123
|
+
"""Check if asyncio.create_task accepts a `context` arg.
|
|
127
124
|
|
|
128
125
|
Returns:
|
|
129
|
-
|
|
130
|
-
otherwise.
|
|
126
|
+
True if `asyncio.create_task` accepts a context argument, `False` otherwise.
|
|
131
127
|
"""
|
|
132
|
-
return
|
|
128
|
+
return sys.version_info >= (3, 11)
|
|
133
129
|
|
|
134
130
|
|
|
135
131
|
def coro_with_context(
|
|
@@ -140,7 +136,7 @@ def coro_with_context(
|
|
|
140
136
|
Args:
|
|
141
137
|
coro: The coroutine to await.
|
|
142
138
|
context: The context to use.
|
|
143
|
-
create_task: Whether to create a task.
|
|
139
|
+
create_task: Whether to create a task.
|
|
144
140
|
|
|
145
141
|
Returns:
|
|
146
142
|
The coroutine with the context.
|
|
@@ -344,7 +340,7 @@ class GetLambdaSource(ast.NodeVisitor):
|
|
|
344
340
|
|
|
345
341
|
def __init__(self) -> None:
|
|
346
342
|
"""Initialize the visitor."""
|
|
347
|
-
self.source:
|
|
343
|
+
self.source: str | None = None
|
|
348
344
|
self.count = 0
|
|
349
345
|
|
|
350
346
|
@override
|
|
@@ -359,15 +355,14 @@ class GetLambdaSource(ast.NodeVisitor):
|
|
|
359
355
|
self.source = ast.unparse(node)
|
|
360
356
|
|
|
361
357
|
|
|
362
|
-
def get_function_first_arg_dict_keys(func: Callable) ->
|
|
358
|
+
def get_function_first_arg_dict_keys(func: Callable) -> list[str] | None:
|
|
363
359
|
"""Get the keys of the first argument of a function if it is a dict.
|
|
364
360
|
|
|
365
361
|
Args:
|
|
366
362
|
func: The function to check.
|
|
367
363
|
|
|
368
364
|
Returns:
|
|
369
|
-
|
|
370
|
-
None otherwise.
|
|
365
|
+
The keys of the first argument if it is a dict, None otherwise.
|
|
371
366
|
"""
|
|
372
367
|
try:
|
|
373
368
|
code = inspect.getsource(func)
|
|
@@ -379,14 +374,14 @@ def get_function_first_arg_dict_keys(func: Callable) -> Optional[list[str]]:
|
|
|
379
374
|
return None
|
|
380
375
|
|
|
381
376
|
|
|
382
|
-
def get_lambda_source(func: Callable) ->
|
|
377
|
+
def get_lambda_source(func: Callable) -> str | None:
|
|
383
378
|
"""Get the source code of a lambda function.
|
|
384
379
|
|
|
385
380
|
Args:
|
|
386
381
|
func: a Callable that can be a lambda function.
|
|
387
382
|
|
|
388
383
|
Returns:
|
|
389
|
-
|
|
384
|
+
the source code of the lambda function.
|
|
390
385
|
"""
|
|
391
386
|
try:
|
|
392
387
|
name = func.__name__ if func.__name__ != "<lambda>" else None
|
|
@@ -410,7 +405,7 @@ def get_function_nonlocals(func: Callable) -> list[Any]:
|
|
|
410
405
|
func: The function to check.
|
|
411
406
|
|
|
412
407
|
Returns:
|
|
413
|
-
|
|
408
|
+
The nonlocal variables accessed by the function.
|
|
414
409
|
"""
|
|
415
410
|
try:
|
|
416
411
|
code = inspect.getsource(func)
|
|
@@ -453,7 +448,7 @@ def indent_lines_after_first(text: str, prefix: str) -> str:
|
|
|
453
448
|
prefix: Used to determine the number of spaces to indent.
|
|
454
449
|
|
|
455
450
|
Returns:
|
|
456
|
-
|
|
451
|
+
The indented text.
|
|
457
452
|
"""
|
|
458
453
|
n_spaces = len(prefix)
|
|
459
454
|
spaces = " " * n_spaces
|
|
@@ -521,31 +516,31 @@ class SupportsAdd(Protocol[_T_contra, _T_co]):
|
|
|
521
516
|
Addable = TypeVar("Addable", bound=SupportsAdd[Any, Any])
|
|
522
517
|
|
|
523
518
|
|
|
524
|
-
def add(addables: Iterable[Addable]) ->
|
|
519
|
+
def add(addables: Iterable[Addable]) -> Addable | None:
|
|
525
520
|
"""Add a sequence of addable objects together.
|
|
526
521
|
|
|
527
522
|
Args:
|
|
528
523
|
addables: The addable objects to add.
|
|
529
524
|
|
|
530
525
|
Returns:
|
|
531
|
-
|
|
526
|
+
The result of adding the addable objects.
|
|
532
527
|
"""
|
|
533
|
-
final:
|
|
528
|
+
final: Addable | None = None
|
|
534
529
|
for chunk in addables:
|
|
535
530
|
final = chunk if final is None else final + chunk
|
|
536
531
|
return final
|
|
537
532
|
|
|
538
533
|
|
|
539
|
-
async def aadd(addables: AsyncIterable[Addable]) ->
|
|
534
|
+
async def aadd(addables: AsyncIterable[Addable]) -> Addable | None:
|
|
540
535
|
"""Asynchronously add a sequence of addable objects together.
|
|
541
536
|
|
|
542
537
|
Args:
|
|
543
538
|
addables: The addable objects to add.
|
|
544
539
|
|
|
545
540
|
Returns:
|
|
546
|
-
|
|
541
|
+
The result of adding the addable objects.
|
|
547
542
|
"""
|
|
548
|
-
final:
|
|
543
|
+
final: Addable | None = None
|
|
549
544
|
async for chunk in addables:
|
|
550
545
|
final = chunk if final is None else final + chunk
|
|
551
546
|
return final
|
|
@@ -556,14 +551,14 @@ class ConfigurableField(NamedTuple):
|
|
|
556
551
|
|
|
557
552
|
id: str
|
|
558
553
|
"""The unique identifier of the field."""
|
|
559
|
-
name:
|
|
560
|
-
"""The name of the field.
|
|
561
|
-
description:
|
|
562
|
-
"""The description of the field.
|
|
563
|
-
annotation:
|
|
564
|
-
"""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. """
|
|
565
560
|
is_shared: bool = False
|
|
566
|
-
"""Whether the field is shared.
|
|
561
|
+
"""Whether the field is shared."""
|
|
567
562
|
|
|
568
563
|
@override
|
|
569
564
|
def __hash__(self) -> int:
|
|
@@ -579,12 +574,12 @@ class ConfigurableFieldSingleOption(NamedTuple):
|
|
|
579
574
|
"""The options for the field."""
|
|
580
575
|
default: str
|
|
581
576
|
"""The default value for the field."""
|
|
582
|
-
name:
|
|
583
|
-
"""The name of the field.
|
|
584
|
-
description:
|
|
585
|
-
"""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. """
|
|
586
581
|
is_shared: bool = False
|
|
587
|
-
"""Whether the field is shared.
|
|
582
|
+
"""Whether the field is shared."""
|
|
588
583
|
|
|
589
584
|
@override
|
|
590
585
|
def __hash__(self) -> int:
|
|
@@ -600,21 +595,21 @@ class ConfigurableFieldMultiOption(NamedTuple):
|
|
|
600
595
|
"""The options for the field."""
|
|
601
596
|
default: Sequence[str]
|
|
602
597
|
"""The default values for the field."""
|
|
603
|
-
name:
|
|
604
|
-
"""The name of the field.
|
|
605
|
-
description:
|
|
606
|
-
"""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. """
|
|
607
602
|
is_shared: bool = False
|
|
608
|
-
"""Whether the field is shared.
|
|
603
|
+
"""Whether the field is shared."""
|
|
609
604
|
|
|
610
605
|
@override
|
|
611
606
|
def __hash__(self) -> int:
|
|
612
607
|
return hash((self.id, tuple(self.options.keys()), tuple(self.default)))
|
|
613
608
|
|
|
614
609
|
|
|
615
|
-
AnyConfigurableField =
|
|
616
|
-
ConfigurableField
|
|
617
|
-
|
|
610
|
+
AnyConfigurableField = (
|
|
611
|
+
ConfigurableField | ConfigurableFieldSingleOption | ConfigurableFieldMultiOption
|
|
612
|
+
)
|
|
618
613
|
|
|
619
614
|
|
|
620
615
|
class ConfigurableFieldSpec(NamedTuple):
|
|
@@ -624,16 +619,16 @@ class ConfigurableFieldSpec(NamedTuple):
|
|
|
624
619
|
"""The unique identifier of the field."""
|
|
625
620
|
annotation: Any
|
|
626
621
|
"""The annotation of the field."""
|
|
627
|
-
name:
|
|
628
|
-
"""The name of the field.
|
|
629
|
-
description:
|
|
630
|
-
"""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. """
|
|
631
626
|
default: Any = None
|
|
632
|
-
"""The default value for the field.
|
|
627
|
+
"""The default value for the field. """
|
|
633
628
|
is_shared: bool = False
|
|
634
|
-
"""Whether the field is shared.
|
|
635
|
-
dependencies:
|
|
636
|
-
"""The dependencies of the field.
|
|
629
|
+
"""Whether the field is shared."""
|
|
630
|
+
dependencies: list[str] | None = None
|
|
631
|
+
"""The dependencies of the field. """
|
|
637
632
|
|
|
638
633
|
|
|
639
634
|
def get_unique_config_specs(
|
|
@@ -645,7 +640,7 @@ def get_unique_config_specs(
|
|
|
645
640
|
specs: The config specs.
|
|
646
641
|
|
|
647
642
|
Returns:
|
|
648
|
-
|
|
643
|
+
The unique config specs.
|
|
649
644
|
|
|
650
645
|
Raises:
|
|
651
646
|
ValueError: If the runnable sequence contains conflicting config specs.
|
|
@@ -672,12 +667,12 @@ class _RootEventFilter:
|
|
|
672
667
|
def __init__(
|
|
673
668
|
self,
|
|
674
669
|
*,
|
|
675
|
-
include_names:
|
|
676
|
-
include_types:
|
|
677
|
-
include_tags:
|
|
678
|
-
exclude_names:
|
|
679
|
-
exclude_types:
|
|
680
|
-
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,
|
|
681
676
|
) -> None:
|
|
682
677
|
"""Utility to filter the root event in the astream_events implementation.
|
|
683
678
|
|
|
@@ -732,8 +727,7 @@ def is_async_generator(
|
|
|
732
727
|
func: The function to check.
|
|
733
728
|
|
|
734
729
|
Returns:
|
|
735
|
-
|
|
736
|
-
an async generator, False otherwise.
|
|
730
|
+
`True` if the function is an async generator, `False` otherwise.
|
|
737
731
|
"""
|
|
738
732
|
return inspect.isasyncgenfunction(func) or (
|
|
739
733
|
hasattr(func, "__call__") # noqa: B004
|
|
@@ -750,8 +744,7 @@ def is_async_callable(
|
|
|
750
744
|
func: The function to check.
|
|
751
745
|
|
|
752
746
|
Returns:
|
|
753
|
-
|
|
754
|
-
False otherwise.
|
|
747
|
+
`True` if the function is async, `False` otherwise.
|
|
755
748
|
"""
|
|
756
749
|
return asyncio.iscoroutinefunction(func) or (
|
|
757
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,59 +47,57 @@ 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
|
-
If a key is not found, the corresponding value will be None
|
|
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.
|
|
104
|
-
If a key is not found, the corresponding value will be None
|
|
100
|
+
If a key is not found, the corresponding value will be `None`.
|
|
105
101
|
"""
|
|
106
102
|
return await run_in_executor(None, self.mget, keys)
|
|
107
103
|
|
|
@@ -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:
|
|
@@ -273,25 +243,22 @@ class InMemoryStore(InMemoryBaseStore[Any]):
|
|
|
273
243
|
"""In-memory store for any type of data.
|
|
274
244
|
|
|
275
245
|
Attributes:
|
|
276
|
-
store
|
|
277
|
-
the key-value pairs.
|
|
246
|
+
store: The underlying dictionary that stores the key-value pairs.
|
|
278
247
|
|
|
279
248
|
Examples:
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
# ['key2']
|
|
294
|
-
|
|
249
|
+
```python
|
|
250
|
+
from langchain.storage import InMemoryStore
|
|
251
|
+
|
|
252
|
+
store = InMemoryStore()
|
|
253
|
+
store.mset([("key1", "value1"), ("key2", "value2")])
|
|
254
|
+
store.mget(["key1", "key2"])
|
|
255
|
+
# ['value1', 'value2']
|
|
256
|
+
store.mdelete(["key1"])
|
|
257
|
+
list(store.yield_keys())
|
|
258
|
+
# ['key2']
|
|
259
|
+
list(store.yield_keys(prefix="k"))
|
|
260
|
+
# ['key2']
|
|
261
|
+
```
|
|
295
262
|
"""
|
|
296
263
|
|
|
297
264
|
|
|
@@ -299,25 +266,22 @@ class InMemoryByteStore(InMemoryBaseStore[bytes]):
|
|
|
299
266
|
"""In-memory store for bytes.
|
|
300
267
|
|
|
301
268
|
Attributes:
|
|
302
|
-
store
|
|
303
|
-
the key-value pairs.
|
|
269
|
+
store: The underlying dictionary that stores the key-value pairs.
|
|
304
270
|
|
|
305
271
|
Examples:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
# ['key2']
|
|
320
|
-
|
|
272
|
+
```python
|
|
273
|
+
from langchain.storage import InMemoryByteStore
|
|
274
|
+
|
|
275
|
+
store = InMemoryByteStore()
|
|
276
|
+
store.mset([("key1", b"value1"), ("key2", b"value2")])
|
|
277
|
+
store.mget(["key1", "key2"])
|
|
278
|
+
# [b'value1', b'value2']
|
|
279
|
+
store.mdelete(["key1"])
|
|
280
|
+
list(store.yield_keys())
|
|
281
|
+
# ['key2']
|
|
282
|
+
list(store.yield_keys(prefix="k"))
|
|
283
|
+
# ['key2']
|
|
284
|
+
```
|
|
321
285
|
"""
|
|
322
286
|
|
|
323
287
|
|