libs/core/langchain_core/runnables/base.py PYTHON 6,730 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 6,730.
1"""Base classes and utilities for `Runnable` objects."""23from __future__ import annotations45import asyncio6import collections7import contextlib8import functools9import inspect10import threading11from abc import ABC, abstractmethod12from collections.abc import (13    AsyncGenerator,14    AsyncIterator,15    Awaitable,16    Callable,17    Coroutine,18    Iterator,19    Mapping,20    Sequence,21)22from concurrent.futures import FIRST_COMPLETED, wait23from functools import wraps24from itertools import tee25from operator import itemgetter26from types import GenericAlias27from typing import (28    TYPE_CHECKING,29    Any,30    Generic,31    Literal,32    Protocol,33    TypeVar,34    cast,35    get_args,36    get_type_hints,37    overload,38)3940from pydantic import BaseModel, ConfigDict, Field, RootModel41from pydantic.fields import FieldInfo42from typing_extensions import override4344from langchain_core._api import beta_decorator45from langchain_core._api.deprecation import warn_deprecated46from langchain_core.callbacks.manager import AsyncCallbackManager, CallbackManager47from langchain_core.load.serializable import (48    Serializable,49    SerializedConstructor,50    SerializedNotImplemented,51)52from langchain_core.runnables.config import (53    RunnableConfig,54    acall_func_with_variable_args,55    call_func_with_variable_args,56    ensure_config,57    get_async_callback_manager_for_config,58    get_callback_manager_for_config,59    get_config_list,60    get_executor_for_config,61    merge_configs,62    patch_config,63    run_in_executor,64    set_config_context,65)66from langchain_core.runnables.utils import (67    AddableDict,68    AnyConfigurableField,69    ConfigurableField,70    ConfigurableFieldSpec,71    Input,72    Output,73    accepts_config,74    accepts_run_manager,75    coro_with_context,76    gated_coro,77    gather_with_concurrency,78    get_function_first_arg_dict_keys,79    get_function_nonlocals,80    get_lambda_source,81    get_unique_config_specs,82    indent_lines_after_first,83    is_async_callable,84    is_async_generator,85)86from langchain_core.tracers._streaming import _StreamingCallbackHandler87from langchain_core.tracers.event_stream import (88    _astream_events_implementation_v1,89    _astream_events_implementation_v2,90)91from langchain_core.tracers.log_stream import (92    LogStreamCallbackHandler,93    _astream_log_implementation,94)95from langchain_core.tracers.root_listeners import (96    AsyncRootListenersTracer,97    RootListenersTracer,98)99from langchain_core.utils._signature import _signature_parameters100from langchain_core.utils.aiter import aclosing, atee101from langchain_core.utils.iter import safetee102from langchain_core.utils.pydantic import (103    TypeBaseModel,104    create_model_v2,105    get_fields,106    model_json_schema,107)108109if TYPE_CHECKING:110    from pydantic.v1.fields import ModelField111112    from langchain_core.callbacks.manager import (113        AsyncCallbackManagerForChainRun,114        CallbackManagerForChainRun,115    )116    from langchain_core.prompts.base import BasePromptTemplate117    from langchain_core.runnables.fallbacks import (118        RunnableWithFallbacks as RunnableWithFallbacksT,119    )120    from langchain_core.runnables.graph import Graph121    from langchain_core.runnables.retry import ExponentialJitterParams122    from langchain_core.runnables.schema import StreamEvent123    from langchain_core.tools import BaseTool124    from langchain_core.tracers.log_stream import RunLog, RunLogPatch125    from langchain_core.tracers.root_listeners import AsyncListener126    from langchain_core.tracers.schemas import Run127128129Other = TypeVar("Other")130131_RUNNABLE_GENERIC_NUM_ARGS = 2  # Input and Output132133134class Runnable(ABC, Generic[Input, Output]):135    """A unit of work that can be invoked, batched, streamed, transformed and composed.136137    Key Methods138    ===========139140    - `invoke`/`ainvoke`: Transforms a single input into an output.141    - `batch`/`abatch`: Efficiently transforms multiple inputs into outputs.142    - `stream`/`astream`: Streams output from a single input as it's produced.143    - `astream_log`: Streams output and selected intermediate results from an144        input.145146    Built-in optimizations:147148    - **Batch**: By default, batch runs invoke() in parallel using a thread pool149        executor. Override to optimize batching.150151    - **Async**: Methods with `'a'` prefix are asynchronous. By default, they execute152        the sync counterpart using asyncio's thread pool.153        Override for native async.154155    All methods accept an optional config argument, which can be used to configure156    execution, add tags and metadata for tracing and debugging etc.157158    Runnables expose schematic information about their input, output and config via159    the `input_schema` property, the `output_schema` property and `config_schema`160    method.161162    Composition163    ===========164165    Runnable objects can be composed together to create chains in a declarative way.166167    Any chain constructed this way will automatically have sync, async, batch, and168    streaming support.169170    The main composition primitives are `RunnableSequence` and `RunnableParallel`.171172    **`RunnableSequence`** invokes a series of runnables sequentially, with173    one Runnable's output serving as the next's input. Construct using174    the `|` operator or by passing a list of runnables to `RunnableSequence`.175176    **`RunnableParallel`** invokes runnables concurrently, providing the same input177    to each. Construct it using a dict literal within a sequence or by passing a178    dict to `RunnableParallel`.179180181    For example,182183    ```python184    from langchain_core.runnables import RunnableLambda185186    # A RunnableSequence constructed using the `|` operator187    sequence = RunnableLambda(lambda x: x + 1) | RunnableLambda(lambda x: x * 2)188    sequence.invoke(1)  # 4189    sequence.batch([1, 2, 3])  # [4, 6, 8]190191192    # A sequence that contains a RunnableParallel constructed using a dict literal193    sequence = RunnableLambda(lambda x: x + 1) | {194        "mul_2": RunnableLambda(lambda x: x * 2),195        "mul_5": RunnableLambda(lambda x: x * 5),196    }197    sequence.invoke(1)  # {'mul_2': 4, 'mul_5': 10}198    ```199200    Standard Methods201    ================202203    All `Runnable`s expose additional methods that can be used to modify their204    behavior (e.g., add a retry policy, add lifecycle listeners, make them205    configurable, etc.).206207    These methods will work on any `Runnable`, including `Runnable` chains208    constructed by composing other `Runnable`s.209    See the individual methods for details.210211    For example,212213    ```python214    from langchain_core.runnables import RunnableLambda215216    import random217218    def add_one(x: int) -> int:219        return x + 1220221222    def buggy_double(y: int) -> int:223        \"\"\"Buggy code that will fail 70% of the time\"\"\"224        if random.random() > 0.3:225            print('This code failed, and will probably be retried!')  # noqa: T201226            raise ValueError('Triggered buggy code')227        return y * 2228229    sequence = (230        RunnableLambda(add_one) |231        RunnableLambda(buggy_double).with_retry( # Retry on failure232            stop_after_attempt=10,233            wait_exponential_jitter=False234        )235    )236237    print(sequence.input_schema.model_json_schema()) # Show inferred input schema238    print(sequence.output_schema.model_json_schema()) # Show inferred output schema239    print(sequence.invoke(2)) # invoke the sequence (note the retry above!!)240    ```241242    Debugging and tracing243    =====================244245    As the chains get longer, it can be useful to be able to see intermediate results246    to debug and trace the chain.247248    You can set the global debug flag to True to enable debug output for all chains:249250    ```python251    from langchain_core.globals import set_debug252253    set_debug(True)254    ```255256    Alternatively, you can pass existing or custom callbacks to any given chain:257258    ```python259    from langchain_core.tracers import ConsoleCallbackHandler260261    chain.invoke(..., config={"callbacks": [ConsoleCallbackHandler()]})262    ```263264    For a UI (and much more) checkout [LangSmith](https://docs.langchain.com/langsmith/home).265266    """267268    name: str | None269    """The name of the `Runnable`. Used for debugging and tracing."""270271    def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:272        """Get the name of the `Runnable`.273274        Args:275            suffix: An optional suffix to append to the name.276            name: An optional name to use instead of the `Runnable`'s name.277278        Returns:279            The name of the `Runnable`.280        """281        if name:282            name_ = name283        elif hasattr(self, "name") and self.name:284            name_ = self.name285        else:286            # Here we handle a case where the runnable subclass is also a pydantic287            # model.288            cls = self.__class__289            # Then it's a pydantic sub-class, and we have to check290            # whether it's a generic, and if so recover the original name.291            if (292                hasattr(293                    cls,294                    "__pydantic_generic_metadata__",295                )296                and "origin" in cls.__pydantic_generic_metadata__297                and cls.__pydantic_generic_metadata__["origin"] is not None298            ):299                name_ = cls.__pydantic_generic_metadata__["origin"].__name__300            else:301                name_ = cls.__name__302303        if suffix:304            if name_[0].isupper():305                return name_ + suffix.title()306            return name_ + "_" + suffix.lower()307        return name_308309    @property310    def InputType(self) -> type[Input]:  # noqa: N802311        """Input type.312313        The type of input this `Runnable` accepts specified as a type annotation.314315        Raises:316            TypeError: If the input type cannot be inferred.317        """318        # First loop through all parent classes and if any of them is319        # a Pydantic model, we will pick up the generic parameterization320        # from that model via the __pydantic_generic_metadata__ attribute.321        for base in self.__class__.mro():322            if hasattr(base, "__pydantic_generic_metadata__"):323                metadata = base.__pydantic_generic_metadata__324                if (325                    "args" in metadata326                    and len(metadata["args"]) == _RUNNABLE_GENERIC_NUM_ARGS327                ):328                    return cast("type[Input]", metadata["args"][0])329330        # If we didn't find a Pydantic model in the parent classes,331        # then loop through __orig_bases__. This corresponds to332        # Runnables that are not pydantic models.333        for cls in self.__class__.__orig_bases__:  # type: ignore[attr-defined]334            type_args = get_args(cls)335            if type_args and len(type_args) == _RUNNABLE_GENERIC_NUM_ARGS:336                return cast("type[Input]", type_args[0])337338        msg = (339            f"Runnable {self.get_name()} doesn't have an inferable InputType. "340            "Override the InputType property to specify the input type."341        )342        raise TypeError(msg)343344    @property345    def OutputType(self) -> type[Output]:  # noqa: N802346        """Output Type.347348        The type of output this `Runnable` produces specified as a type annotation.349350        Raises:351            TypeError: If the output type cannot be inferred.352        """353        # First loop through bases -- this will help generic354        # any pydantic models.355        for base in self.__class__.mro():356            if hasattr(base, "__pydantic_generic_metadata__"):357                metadata = base.__pydantic_generic_metadata__358                if (359                    "args" in metadata360                    and len(metadata["args"]) == _RUNNABLE_GENERIC_NUM_ARGS361                ):362                    return cast("type[Output]", metadata["args"][1])363364        for cls in self.__class__.__orig_bases__:  # type: ignore[attr-defined]365            type_args = get_args(cls)366            if type_args and len(type_args) == _RUNNABLE_GENERIC_NUM_ARGS:367                return cast("type[Output]", type_args[1])368369        msg = (370            f"Runnable {self.get_name()} doesn't have an inferable OutputType. "371            "Override the OutputType property to specify the output type."372        )373        raise TypeError(msg)374375    @property376    def input_schema(self) -> TypeBaseModel:377        """The type of input this `Runnable` accepts specified as a Pydantic model."""378        return self.get_input_schema()379380    def get_input_schema(381        self,382        config: RunnableConfig | None = None,383    ) -> TypeBaseModel:384        """Get a Pydantic model that can be used to validate input to the `Runnable`.385386        `Runnable` objects that leverage the `configurable_fields` and387        `configurable_alternatives` methods will have a dynamic input schema that388        depends on which configuration the `Runnable` is invoked with.389390        This method allows to get an input schema for a specific configuration.391392        Args:393            config: A config to use when generating the schema.394395        Returns:396            A Pydantic model that can be used to validate input.397        """398        _ = config399        root_type = self.InputType400401        if (402            inspect.isclass(root_type)403            and not isinstance(root_type, GenericAlias)404            and issubclass(root_type, BaseModel)405        ):406            return root_type407408        return create_model_v2(409            self.get_name("Input"),410            root=root_type,411            # create model needs access to appropriate type annotations to be412            # able to construct the Pydantic model.413            # When we create the model, we pass information about the namespace414            # where the model is being created, so the type annotations can415            # be resolved correctly as well.416            # self.__class__.__module__ handles the case when the Runnable is417            # being sub-classed in a different module.418            module_name=self.__class__.__module__,419        )420421    def get_input_jsonschema(422        self, config: RunnableConfig | None = None423    ) -> dict[str, Any]:424        """Get a JSON schema that represents the input to the `Runnable`.425426        Args:427            config: A config to use when generating the schema.428429        Returns:430            A JSON schema that represents the input to the `Runnable`.431432        Example:433            ```python434            from langchain_core.runnables import RunnableLambda435436437            def add_one(x: int) -> int:438                return x + 1439440441            runnable = RunnableLambda(add_one)442443            print(runnable.get_input_jsonschema())444            ```445446        !!! version-added "Added in `langchain-core` 0.3.0"447448        """449        return model_json_schema(self.get_input_schema(config))450451    @property452    def output_schema(self) -> TypeBaseModel:453        """Output schema.454455        The type of output this `Runnable` produces specified as a Pydantic model.456        """457        return self.get_output_schema()458459    def get_output_schema(460        self,461        config: RunnableConfig | None = None,462    ) -> TypeBaseModel:463        """Get a Pydantic model that can be used to validate output to the `Runnable`.464465        `Runnable` objects that leverage the `configurable_fields` and466        `configurable_alternatives` methods will have a dynamic output schema that467        depends on which configuration the `Runnable` is invoked with.468469        This method allows to get an output schema for a specific configuration.470471        Args:472            config: A config to use when generating the schema.473474        Returns:475            A Pydantic model that can be used to validate output.476        """477        _ = config478        root_type = self.OutputType479480        if (481            inspect.isclass(root_type)482            and not isinstance(root_type, GenericAlias)483            and issubclass(root_type, BaseModel)484        ):485            return root_type486487        return create_model_v2(488            self.get_name("Output"),489            root=root_type,490            # create model needs access to appropriate type annotations to be491            # able to construct the Pydantic model.492            # When we create the model, we pass information about the namespace493            # where the model is being created, so the type annotations can494            # be resolved correctly as well.495            # self.__class__.__module__ handles the case when the Runnable is496            # being sub-classed in a different module.497            module_name=self.__class__.__module__,498        )499500    def get_output_jsonschema(501        self, config: RunnableConfig | None = None502    ) -> dict[str, Any]:503        """Get a JSON schema that represents the output of the `Runnable`.504505        Args:506            config: A config to use when generating the schema.507508        Returns:509            A JSON schema that represents the output of the `Runnable`.510511        Example:512            ```python513            from langchain_core.runnables import RunnableLambda514515516            def add_one(x: int) -> int:517                return x + 1518519520            runnable = RunnableLambda(add_one)521522            print(runnable.get_output_jsonschema())523            ```524525        !!! version-added "Added in `langchain-core` 0.3.0"526527        """528        return model_json_schema(self.get_output_schema(config))529530    @property531    def config_specs(self) -> list[ConfigurableFieldSpec]:532        """List configurable fields for this `Runnable`."""533        return []534535    def config_schema(self, *, include: Sequence[str] | None = None) -> type[BaseModel]:536        """The type of config this `Runnable` accepts specified as a Pydantic model.537538        To mark a field as configurable, see the `configurable_fields`539        and `configurable_alternatives` methods.540541        Args:542            include: A list of fields to include in the config schema.543544        Returns:545            A Pydantic model that can be used to validate config.546547        """548        include = include or []549        config_specs = self.config_specs550        configurable = (551            create_model_v2(552                "Configurable",553                field_definitions={554                    spec.id: (555                        spec.annotation,556                        Field(557                            spec.default, title=spec.name, description=spec.description558                        ),559                    )560                    for spec in config_specs561                },562            )563            if config_specs564            else None565        )566567        # Many need to create a typed dict instead to implement NotRequired!568        all_fields = {569            **({"configurable": (configurable, None)} if configurable else {}),570            **{571                field_name: (field_type, None)572                for field_name, field_type in get_type_hints(RunnableConfig).items()573                if field_name in [i for i in include if i != "configurable"]574            },575        }576        return create_model_v2(self.get_name("Config"), field_definitions=all_fields)577578    def get_config_jsonschema(579        self, *, include: Sequence[str] | None = None580    ) -> dict[str, Any]:581        """Get a JSON schema that represents the config of the `Runnable`.582583        Args:584            include: A list of fields to include in the config schema.585586        Returns:587            A JSON schema that represents the config of the `Runnable`.588589        !!! version-added "Added in `langchain-core` 0.3.0"590591        """592        return self.config_schema(include=include).model_json_schema()593594    def get_graph(self, config: RunnableConfig | None = None) -> Graph:595        """Return a graph representation of this `Runnable`."""596        # Import locally to prevent circular import597        from langchain_core.runnables.graph import Graph  # noqa: PLC0415598599        graph = Graph()600        try:601            input_node = graph.add_node(self.get_input_schema(config))602        except TypeError:603            input_node = graph.add_node(create_model_v2(self.get_name("Input")))604        runnable_node = graph.add_node(605            self, metadata=config.get("metadata") if config else None606        )607        try:608            output_node = graph.add_node(self.get_output_schema(config))609        except TypeError:610            output_node = graph.add_node(create_model_v2(self.get_name("Output")))611        graph.add_edge(input_node, runnable_node)612        graph.add_edge(runnable_node, output_node)613        return graph614615    def get_prompts(616        self, config: RunnableConfig | None = None617    ) -> list[BasePromptTemplate[Any]]:618        """Return a list of prompts used by this `Runnable`."""619        # Import locally to prevent circular import620        from langchain_core.prompts.base import BasePromptTemplate  # noqa: PLC0415621622        return [623            node.data624            for node in self.get_graph(config=config).nodes.values()625            if isinstance(node.data, BasePromptTemplate)626        ]627628    @overload629    def __or__(630        self, other: Mapping[str, Any]631    ) -> RunnableSerializable[Input, dict[str, Any]]: ...632633    @overload634    def __or__(635        self,636        other: Callable[[Output], Runnable[Output, Other]]637        | Callable[[Output], Awaitable[Runnable[Output, Other]]],638    ) -> RunnableSerializable[Input, Other]: ...639640    @overload641    def __or__(642        self,643        other: Runnable[Output, Other]644        | Callable[[Iterator[Output]], Iterator[Other]]645        | Callable[[AsyncIterator[Output]], AsyncIterator[Other]]646        | Callable[[Output], Other],647    ) -> RunnableSerializable[Input, Other]: ...648649    def __or__(650        self,651        other: Runnable[Output, Other]652        | Callable[[Iterator[Output]], Iterator[Other]]653        | Callable[[AsyncIterator[Output]], AsyncIterator[Other]]654        | Callable[[Output], Other]655        | Mapping[str, Runnable[Output, Any] | Callable[[Output], Any] | Any],656    ) -> RunnableSerializable[Input, Any]:657        """Runnable "or" operator.658659        Compose this `Runnable` with another object to create a660        `RunnableSequence`.661662        Args:663            other: Another `Runnable` or a `Runnable`-like object.664665        Returns:666            A new `Runnable`.667668        Raises:669            TypeError: If `other` cannot be coerced to a `Runnable`. This method does670                not return `NotImplemented`, to avoid delegating LCEL composition to671                unrelated reflected `|` implementations. To interoperate, implement672                `Runnable`, make the object callable, or define `__or__` on the left.673        """674        return RunnableSequence(self, coerce_to_runnable(other))675676    @overload677    def __ror__(678        self,679        other: Mapping[str, Any],680    ) -> RunnableSerializable[Any, Output]: ...681682    @overload683    def __ror__(684        self,685        other: Callable[[Other], Runnable[Other, Input]]686        | Callable[[Other], Awaitable[Runnable[Other, Input]]],687    ) -> RunnableSerializable[Other, Output]: ...688689    @overload690    def __ror__(691        self,692        other: Runnable[Other, Input]693        | Callable[[Iterator[Other]], Iterator[Input]]694        | Callable[[AsyncIterator[Other]], AsyncIterator[Input]]695        | Callable[[Other], Input],696    ) -> RunnableSerializable[Other, Output]: ...697698    def __ror__(699        self,700        other: Runnable[Other, Input]701        | Callable[[Iterator[Other]], Iterator[Input]]702        | Callable[[AsyncIterator[Other]], AsyncIterator[Input]]703        | Callable[[Other], Any]704        | Mapping[str, Runnable[Other, Input] | Callable[[Other], Any] | Any],705    ) -> RunnableSerializable[Any, Output]:706        """Runnable "reverse-or" operator.707708        Compose this `Runnable` with another object to create a709        `RunnableSequence`.710711        Args:712            other: Another `Runnable` or a `Runnable`-like object.713714        Returns:715            A new `Runnable`.716717        Raises:718            TypeError: If `other` cannot be coerced to a `Runnable`. This method does719                not return `NotImplemented`, to avoid delegating LCEL composition to720                unrelated reflected `|` implementations. To interoperate, implement721                `Runnable`, make the object callable, or define `__or__` on the left.722        """723        return RunnableSequence(coerce_to_runnable(other), self)724725    def pipe(726        self,727        *others: Runnable[Any, Other] | Callable[[Any], Other],728        name: str | None = None,729    ) -> RunnableSerializable[Input, Other]:730        """Pipe `Runnable` objects.731732        Compose this `Runnable` with `Runnable`-like objects to make a733        `RunnableSequence`.734735        Equivalent to `RunnableSequence(self, *others)` or `self | others[0] | ...`736737        Example:738            ```python739            from langchain_core.runnables import RunnableLambda740741742            def add_one(x: int) -> int:743                return x + 1744745746            def mul_two(x: int) -> int:747                return x * 2748749750            runnable_1 = RunnableLambda(add_one)751            runnable_2 = RunnableLambda(mul_two)752            sequence = runnable_1.pipe(runnable_2)753            # Or equivalently:754            # sequence = runnable_1 | runnable_2755            # sequence = RunnableSequence(first=runnable_1, last=runnable_2)756            sequence.invoke(1)757            await sequence.ainvoke(1)758            # -> 4759760            sequence.batch([1, 2, 3])761            await sequence.abatch([1, 2, 3])762            # -> [4, 6, 8]763            ```764765        Args:766            *others: Other `Runnable` or `Runnable`-like objects to compose767            name: An optional name for the resulting `RunnableSequence`.768769        Returns:770            A new `Runnable`.771        """772        return RunnableSequence(self, *others, name=name)773774    def pick(self, keys: str | list[str]) -> RunnableSerializable[Any, Any]:775        """Pick keys from the output `dict` of this `Runnable`.776777        !!! example "Pick a single key"778779            ```python780            import json781782            from langchain_core.runnables import RunnableLambda, RunnableMap783784            as_str = RunnableLambda(str)785            as_json = RunnableLambda(json.loads)786            chain = RunnableMap(str=as_str, json=as_json)787788            chain.invoke("[1, 2, 3]")789            # -> {"str": "[1, 2, 3]", "json": [1, 2, 3]}790791            json_only_chain = chain.pick("json")792            json_only_chain.invoke("[1, 2, 3]")793            # -> [1, 2, 3]794            ```795796        !!! example "Pick a list of keys"797798            ```python799            from typing import Any800801            import json802803            from langchain_core.runnables import RunnableLambda, RunnableMap804805            as_str = RunnableLambda(str)806            as_json = RunnableLambda(json.loads)807808809            def as_bytes(x: Any) -> bytes:810                return bytes(x, "utf-8")811812813            chain = RunnableMap(814                str=as_str, json=as_json, bytes=RunnableLambda(as_bytes)815            )816817            chain.invoke("[1, 2, 3]")818            # -> {"str": "[1, 2, 3]", "json": [1, 2, 3], "bytes": b"[1, 2, 3]"}819820            json_and_bytes_chain = chain.pick(["json", "bytes"])821            json_and_bytes_chain.invoke("[1, 2, 3]")822            # -> {"json": [1, 2, 3], "bytes": b"[1, 2, 3]"}823            ```824825        Args:826            keys: A key or list of keys to pick from the output dict.827828        Returns:829            a new `Runnable`.830831        """832        # Import locally to prevent circular import833        from langchain_core.runnables.passthrough import RunnablePick  # noqa: PLC0415834835        return self | RunnablePick(keys)  # type: ignore[operator, no-any-return]836837    def assign(838        self,839        **kwargs: Runnable[dict[str, Any], Any]840        | Callable[[dict[str, Any]], Any]841        | Mapping[str, Runnable[dict[str, Any], Any] | Callable[[dict[str, Any]], Any]],842    ) -> RunnableSerializable[Any, Any]:843        """Assigns new fields to the `dict` output of this `Runnable`.844845        ```python846        from langchain_core.language_models.fake import FakeStreamingListLLM847        from langchain_core.output_parsers import StrOutputParser848        from langchain_core.prompts import SystemMessagePromptTemplate849        from langchain_core.runnables import Runnable850        from operator import itemgetter851852        prompt = (853            SystemMessagePromptTemplate.from_template("You are a nice assistant.")854            + "{question}"855        )856        model = FakeStreamingListLLM(responses=["foo-lish"])857858        chain: Runnable = prompt | model | {"str": StrOutputParser()}859860        chain_with_assign = chain.assign(hello=itemgetter("str") | model)861862        print(chain_with_assign.input_schema.model_json_schema())863        # {'title': 'PromptInput', 'type': 'object', 'properties':864        {'question': {'title': 'Question', 'type': 'string'}}}865        print(chain_with_assign.output_schema.model_json_schema())866        # {'title': 'RunnableSequenceOutput', 'type': 'object', 'properties':867        {'str': {'title': 'Str',868        'type': 'string'}, 'hello': {'title': 'Hello', 'type': 'string'}}}869        ```870871        Args:872            **kwargs: A mapping of keys to `Runnable` or `Runnable`-like objects873                that will be invoked with the entire output dict of this `Runnable`.874875        Returns:876            A new `Runnable`.877878        """879        # Import locally to prevent circular import880        from langchain_core.runnables.passthrough import RunnableAssign  # noqa: PLC0415881882        return self | RunnableAssign(RunnableParallel[dict[str, Any]](kwargs))  # type: ignore[operator, no-any-return]883884    """ --- Public API --- """885886    @abstractmethod887    def invoke(888        self,889        input: Input,890        config: RunnableConfig | None = None,891        **kwargs: Any,892    ) -> Output:893        """Transform a single input into an output.894895        Args:896            input: The input to the `Runnable`.897            config: A config to use when invoking the `Runnable`.898899                The config supports standard keys like `'tags'`, `'metadata'` for900                tracing purposes, `'max_concurrency'` for controlling how much work to901                do in parallel, and other keys.902903                Please refer to `RunnableConfig` for more details.904905        Returns:906            The output of the `Runnable`.907        """908909    async def ainvoke(910        self,911        input: Input,912        config: RunnableConfig | None = None,913        **kwargs: Any,914    ) -> Output:915        """Transform a single input into an output.916917        Args:918            input: The input to the `Runnable`.919            config: A config to use when invoking the `Runnable`.920921                The config supports standard keys like `'tags'`, `'metadata'` for922                tracing purposes, `'max_concurrency'` for controlling how much work to923                do in parallel, and other keys.924925                Please refer to `RunnableConfig` for more details.926927        Returns:928            The output of the `Runnable`.929        """930        return await run_in_executor(config, self.invoke, input, config, **kwargs)931932    def batch(933        self,934        inputs: list[Input],935        config: RunnableConfig | list[RunnableConfig] | None = None,936        *,937        return_exceptions: bool = False,938        **kwargs: Any | None,939    ) -> list[Output]:940        """Default implementation runs invoke in parallel using a thread pool executor.941942        The default implementation of batch works well for IO bound runnables.943944        Subclasses must override this method if they can batch more efficiently;945        e.g., if the underlying `Runnable` uses an API which supports a batch mode.946947        Args:948            inputs: A list of inputs to the `Runnable`.949            config: A config to use when invoking the `Runnable`. The config supports950                standard keys like `'tags'`, `'metadata'` for951                tracing purposes, `'max_concurrency'` for controlling how much work952                to do in parallel, and other keys.953954                Please refer to `RunnableConfig` for more details.955            return_exceptions: Whether to return exceptions instead of raising them.956            **kwargs: Additional keyword arguments to pass to the `Runnable`.957958        Returns:959            A list of outputs from the `Runnable`.960        """961        if not inputs:962            return []963964        configs = get_config_list(config, len(inputs))965966        def invoke(input_: Input, config: RunnableConfig) -> Output | Exception:967            if return_exceptions:968                try:969                    return self.invoke(input_, config, **kwargs)970                except Exception as e:971                    return e972            else:973                return self.invoke(input_, config, **kwargs)974975        # If there's only one input, don't bother with the executor976        if len(inputs) == 1:977            return cast("list[Output]", [invoke(inputs[0], configs[0])])978979        with get_executor_for_config(configs[0]) as executor:980            return cast("list[Output]", list(executor.map(invoke, inputs, configs)))981982    @overload983    def batch_as_completed(984        self,985        inputs: Sequence[Input],986        config: RunnableConfig | Sequence[RunnableConfig] | None = None,987        *,988        return_exceptions: Literal[False] = False,989        **kwargs: Any,990    ) -> Iterator[tuple[int, Output]]: ...991992    @overload993    def batch_as_completed(994        self,995        inputs: Sequence[Input],996        config: RunnableConfig | Sequence[RunnableConfig] | None = None,997        *,998        return_exceptions: Literal[True],999        **kwargs: Any,1000    ) -> Iterator[tuple[int, Output | Exception]]: ...10011002    def batch_as_completed(1003        self,1004        inputs: Sequence[Input],1005        config: RunnableConfig | Sequence[RunnableConfig] | None = None,1006        *,1007        return_exceptions: bool = False,1008        **kwargs: Any | None,1009    ) -> Iterator[tuple[int, Output | Exception]]:1010        """Run `invoke` in parallel on a list of inputs.10111012        Yields results as they complete.10131014        Args:1015            inputs: A list of inputs to the `Runnable`.1016            config: A config to use when invoking the `Runnable`.10171018                The config supports standard keys like `'tags'`, `'metadata'` for1019                tracing purposes, `'max_concurrency'` for controlling how much work to1020                do in parallel, and other keys.10211022                Please refer to `RunnableConfig` for more details.1023            return_exceptions: Whether to return exceptions instead of raising them.1024            **kwargs: Additional keyword arguments to pass to the `Runnable`.10251026        Yields:1027            Tuples of the index of the input and the output from the `Runnable`.10281029        """1030        if not inputs:1031            return10321033        configs = get_config_list(config, len(inputs))10341035        def invoke(1036            i: int, input_: Input, config: RunnableConfig1037        ) -> tuple[int, Output | Exception]:1038            if return_exceptions:1039                try:1040                    out: Output | Exception = self.invoke(input_, config, **kwargs)1041                except Exception as e:1042                    out = e1043            else:1044                out = self.invoke(input_, config, **kwargs)10451046            return (i, out)10471048        if len(inputs) == 1:1049            yield invoke(0, inputs[0], configs[0])1050            return10511052        with get_executor_for_config(configs[0]) as executor:1053            futures = {1054                executor.submit(invoke, i, input_, config)1055                for i, (input_, config) in enumerate(zip(inputs, configs, strict=False))1056            }10571058            try:1059                while futures:1060                    done, futures = wait(futures, return_when=FIRST_COMPLETED)1061                    while done:1062                        yield done.pop().result()1063            finally:1064                for future in futures:1065                    future.cancel()10661067    async def abatch(1068        self,1069        inputs: list[Input],1070        config: RunnableConfig | list[RunnableConfig] | None = None,1071        *,1072        return_exceptions: bool = False,1073        **kwargs: Any | None,1074    ) -> list[Output]:1075        """Default implementation runs `ainvoke` in parallel using `asyncio.gather`.10761077        The default implementation of `batch` works well for IO bound runnables.10781079        Subclasses must override this method if they can batch more efficiently;1080        e.g., if the underlying `Runnable` uses an API which supports a batch mode.10811082        Args:1083            inputs: A list of inputs to the `Runnable`.1084            config: A config to use when invoking the `Runnable`.10851086                The config supports standard keys like `'tags'`, `'metadata'` for1087                tracing purposes, `'max_concurrency'` for controlling how much work to1088                do in parallel, and other keys.10891090                Please refer to `RunnableConfig` for more details.1091            return_exceptions: Whether to return exceptions instead of raising them.1092            **kwargs: Additional keyword arguments to pass to the `Runnable`.10931094        Returns:1095            A list of outputs from the `Runnable`.10961097        """1098        if not inputs:1099            return []11001101        configs = get_config_list(config, len(inputs))11021103        async def ainvoke(value: Input, config: RunnableConfig) -> Output | Exception:1104            if return_exceptions:1105                try:1106                    return await self.ainvoke(value, config, **kwargs)1107                except Exception as e:1108                    return e1109            else:1110                return await self.ainvoke(value, config, **kwargs)11111112        coros = map(ainvoke, inputs, configs)1113        return await gather_with_concurrency(configs[0].get("max_concurrency"), *coros)11141115    @overload1116    def abatch_as_completed(1117        self,1118        inputs: Sequence[Input],1119        config: RunnableConfig | Sequence[RunnableConfig] | None = None,1120        *,1121        return_exceptions: Literal[False] = False,1122        **kwargs: Any | None,1123    ) -> AsyncIterator[tuple[int, Output]]: ...11241125    @overload1126    def abatch_as_completed(1127        self,1128        inputs: Sequence[Input],1129        config: RunnableConfig | Sequence[RunnableConfig] | None = None,1130        *,1131        return_exceptions: Literal[True],1132        **kwargs: Any | None,1133    ) -> AsyncIterator[tuple[int, Output | Exception]]: ...11341135    async def abatch_as_completed(1136        self,1137        inputs: Sequence[Input],1138        config: RunnableConfig | Sequence[RunnableConfig] | None = None,1139        *,1140        return_exceptions: bool = False,1141        **kwargs: Any | None,1142    ) -> AsyncIterator[tuple[int, Output | Exception]]:1143        """Run `ainvoke` in parallel on a list of inputs.11441145        Yields results as they complete.11461147        Args:1148            inputs: A list of inputs to the `Runnable`.1149            config: A config to use when invoking the `Runnable`.11501151                The config supports standard keys like `'tags'`, `'metadata'` for1152                tracing purposes, `'max_concurrency'` for controlling how much work to1153                do in parallel, and other keys.11541155                Please refer to `RunnableConfig` for more details.1156            return_exceptions: Whether to return exceptions instead of raising them.1157            **kwargs: Additional keyword arguments to pass to the `Runnable`.11581159        Yields:1160            A tuple of the index of the input and the output from the `Runnable`.11611162        """1163        if not inputs:1164            return11651166        configs = get_config_list(config, len(inputs))1167        # Get max_concurrency from first config, defaulting to None (unlimited)1168        max_concurrency = configs[0].get("max_concurrency") if configs else None1169        semaphore = asyncio.Semaphore(max_concurrency) if max_concurrency else None11701171        async def ainvoke_task(1172            i: int, input_: Input, config: RunnableConfig1173        ) -> tuple[int, Output | Exception]:1174            if return_exceptions:1175                try:1176                    out: Output | Exception = await self.ainvoke(1177                        input_, config, **kwargs1178                    )1179                except Exception as e:1180                    out = e1181            else:1182                out = await self.ainvoke(input_, config, **kwargs)1183            return (i, out)11841185        coros = [1186            gated_coro(semaphore, ainvoke_task(i, input_, config))1187            if semaphore1188            else ainvoke_task(i, input_, config)1189            for i, (input_, config) in enumerate(zip(inputs, configs, strict=False))1190        ]11911192        for coro in asyncio.as_completed(coros):1193            yield await coro11941195    def stream(1196        self,1197        input: Input,1198        config: RunnableConfig | None = None,1199        **kwargs: Any | None,1200    ) -> Iterator[Output]:1201        """Default implementation of `stream`, which calls `invoke`.12021203        Subclasses must override this method if they support streaming output.12041205        Args:1206            input: The input to the `Runnable`.1207            config: The config to use for the `Runnable`.1208            **kwargs: Additional keyword arguments to pass to the `Runnable`.12091210        Yields:1211            The output of the `Runnable`.12121213        """1214        yield self.invoke(input, config, **kwargs)12151216    async def astream(1217        self,1218        input: Input,1219        config: RunnableConfig | None = None,1220        **kwargs: Any | None,1221    ) -> AsyncIterator[Output]:1222        """Default implementation of `astream`, which calls `ainvoke`.12231224        Subclasses must override this method if they support streaming output.12251226        Args:1227            input: The input to the `Runnable`.1228            config: The config to use for the `Runnable`.1229            **kwargs: Additional keyword arguments to pass to the `Runnable`.12301231        Yields:1232            The output of the `Runnable`.12331234        """1235        yield await self.ainvoke(input, config, **kwargs)12361237    @overload1238    def astream_log(1239        self,1240        input: Any,1241        config: RunnableConfig | None = None,1242        *,1243        diff: Literal[True] = True,1244        with_streamed_output_list: bool = True,1245        include_names: Sequence[str] | None = None,1246        include_types: Sequence[str] | None = None,1247        include_tags: Sequence[str] | None = None,1248        exclude_names: Sequence[str] | None = None,1249        exclude_types: Sequence[str] | None = None,1250        exclude_tags: Sequence[str] | None = None,1251        **kwargs: Any,1252    ) -> AsyncIterator[RunLogPatch]: ...12531254    @overload1255    def astream_log(1256        self,1257        input: Any,1258        config: RunnableConfig | None = None,1259        *,1260        diff: Literal[False],1261        with_streamed_output_list: bool = True,1262        include_names: Sequence[str] | None = None,1263        include_types: Sequence[str] | None = None,1264        include_tags: Sequence[str] | None = None,1265        exclude_names: Sequence[str] | None = None,1266        exclude_types: Sequence[str] | None = None,1267        exclude_tags: Sequence[str] | None = None,1268        **kwargs: Any,1269    ) -> AsyncIterator[RunLog]: ...12701271    async def astream_log(1272        self,1273        input: Any,1274        config: RunnableConfig | None = None,1275        *,1276        diff: bool = True,1277        with_streamed_output_list: bool = True,1278        include_names: Sequence[str] | None = None,1279        include_types: Sequence[str] | None = None,1280        include_tags: Sequence[str] | None = None,1281        exclude_names: Sequence[str] | None = None,1282        exclude_types: Sequence[str] | None = None,1283        exclude_tags: Sequence[str] | None = None,1284        **kwargs: Any,1285    ) -> AsyncIterator[RunLogPatch] | AsyncIterator[RunLog]:1286        """Stream all output from a `Runnable`, as reported to the callback system.12871288        This includes all inner runs of LLMs, Retrievers, Tools, etc.12891290        Output is streamed as Log objects, which include a list of1291        Jsonpatch ops that describe how the state of the run has changed in each1292        step, and the final state of the run.12931294        The Jsonpatch ops can be applied in order to construct state.12951296        Args:1297            input: The input to the `Runnable`.1298            config: The config to use for the `Runnable`.1299            diff: Whether to yield diffs between each step or the current state.1300            with_streamed_output_list: Whether to yield the `streamed_output` list.1301            include_names: Only include logs with these names.1302            include_types: Only include logs with these types.1303            include_tags: Only include logs with these tags.1304            exclude_names: Exclude logs with these names.1305            exclude_types: Exclude logs with these types.1306            exclude_tags: Exclude logs with these tags.1307            **kwargs: Additional keyword arguments to pass to the `Runnable`.13081309        Yields:1310            A `RunLogPatch` or `RunLog` object.13111312        """1313        warn_deprecated(1314            since="1.3.3",1315            message=("astream_log is deprecated. Use astream instead."),1316            removal="2.0.0",1317        )1318        stream = LogStreamCallbackHandler(1319            auto_close=False,1320            include_names=include_names,1321            include_types=include_types,1322            include_tags=include_tags,1323            exclude_names=exclude_names,1324            exclude_types=exclude_types,1325            exclude_tags=exclude_tags,1326            _schema_format="original",1327        )13281329        # Mypy isn't resolving the overloads here1330        # Likely an issue b/c `self` is being passed through1331        # and it's can't map it to Runnable[Input,Output]?1332        async for item in _astream_log_implementation(  # type: ignore[call-overload]1333            self,1334            input,1335            config,1336            diff=diff,1337            stream=stream,1338            with_streamed_output_list=with_streamed_output_list,1339            **kwargs,1340        ):1341            yield item13421343    @overload1344    def astream_events(1345        self,1346        input: Any,1347        config: RunnableConfig | None = None,1348        *,1349        version: Literal["v1", "v2"] = "v2",1350        include_names: Sequence[str] | None = None,1351        include_types: Sequence[str] | None = None,1352        include_tags: Sequence[str] | None = None,1353        exclude_names: Sequence[str] | None = None,1354        exclude_types: Sequence[str] | None = None,1355        exclude_tags: Sequence[str] | None = None,1356        **kwargs: Any,1357    ) -> AsyncIterator[StreamEvent]: ...13581359    @overload1360    def astream_events(1361        self,1362        input: Any,1363        config: RunnableConfig | None = None,1364        *,1365        version: Literal["v3"],1366        **kwargs: Any,1367    ) -> Awaitable[Any]: ...13681369    def astream_events(1370        self,1371        input: Any,1372        config: RunnableConfig | None = None,1373        *,1374        version: Literal["v1", "v2", "v3"] = "v2",1375        include_names: Sequence[str] | None = None,1376        include_types: Sequence[str] | None = None,1377        include_tags: Sequence[str] | None = None,1378        exclude_names: Sequence[str] | None = None,1379        exclude_types: Sequence[str] | None = None,1380        exclude_tags: Sequence[str] | None = None,1381        **kwargs: Any,1382    ) -> AsyncIterator[StreamEvent] | Awaitable[Any]:1383        """Generate a stream of events.13841385        Use to create an iterator over `StreamEvent` that provide real-time information1386        about the progress of the `Runnable`, including `StreamEvent` from intermediate1387        results.13881389        A `StreamEvent` is a dictionary with the following schema:13901391        - `event`: Event names are of the format:1392            `on_[runnable_type]_(start|stream|end)`.1393        - `name`: The name of the `Runnable` that generated the event.1394        - `run_id`: Randomly generated ID associated with the given execution of the1395            `Runnable` that emitted the event. A child `Runnable` that gets invoked as1396            part of the execution of a parent `Runnable` is assigned its own unique ID.1397        - `parent_ids`: The IDs of the parent runnables that generated the event. The1398            root `Runnable` will have an empty list. The order of the parent IDs is from1399            the root to the immediate parent. Only available for v2 version of the API.1400            The v1 version of the API will return an empty list.1401        - `tags`: The tags of the `Runnable` that generated the event.1402        - `metadata`: The metadata of the `Runnable` that generated the event.1403        - `data`: The data associated with the event. The contents of this field1404            depend on the type of event. See the table below for more details.14051406        Below is a table that illustrates some events that might be emitted by various1407        chains. Metadata fields have been omitted from the table for brevity.1408        Chain definitions have been included after the table.14091410        !!! note1411            This reference table is for the v2 version of the schema.14121413        | event                  | name                 | chunk                               | input                                             | output                                              |1414        | ---------------------- | -------------------- | ----------------------------------- | ------------------------------------------------- | --------------------------------------------------- |1415        | `on_chat_model_start`  | `'[model name]'`     |                                     | `{"messages": [[SystemMessage, HumanMessage]]}`   |                                                     |1416        | `on_chat_model_stream` | `'[model name]'`     | `AIMessageChunk(content="hello")`   |                                                   |                                                     |1417        | `on_chat_model_end`    | `'[model name]'`     |                                     | `{"messages": [[SystemMessage, HumanMessage]]}`   | `AIMessageChunk(content="hello world")`             |1418        | `on_llm_start`         | `'[model name]'`     |                                     | `{'input': 'hello'}`                              |                                                     |1419        | `on_llm_stream`        | `'[model name]'`     | `'Hello' `                          |                                                   |                                                     |1420        | `on_llm_end`           | `'[model name]'`     |                                     | `'Hello human!'`                                  |                                                     |1421        | `on_chain_start`       | `'format_docs'`      |                                     |                                                   |                                                     |1422        | `on_chain_stream`      | `'format_docs'`      | `'hello world!, goodbye world!'`    |                                                   |                                                     |1423        | `on_chain_end`         | `'format_docs'`      |                                     | `[Document(...)]`                                 | `'hello world!, goodbye world!'`                    |1424        | `on_tool_start`        | `'some_tool'`        |                                     | `{"x": 1, "y": "2"}`                              |                                                     |1425        | `on_tool_end`          | `'some_tool'`        |                                     |                                                   | `{"x": 1, "y": "2"}`                                |1426        | `on_retriever_start`   | `'[retriever name]'` |                                     | `{"query": "hello"}`                              |                                                     |1427        | `on_retriever_end`     | `'[retriever name]'` |                                     | `{"query": "hello"}`                              | `[Document(...), ..]`                               |1428        | `on_prompt_start`      | `'[template_name]'`  |                                     | `{"question": "hello"}`                           |                                                     |1429        | `on_prompt_end`        | `'[template_name]'`  |                                     | `{"question": "hello"}`                           | `ChatPromptValue(messages: [SystemMessage, ...])`   |14301431        In addition to the standard events, users can also dispatch custom events (see example below).14321433        Custom events will be only be surfaced with in the v2 version of the API!14341435        A custom event has following format:14361437        | Attribute   | Type   | Description                                                                                               |1438        | ----------- | ------ | --------------------------------------------------------------------------------------------------------- |1439        | `name`      | `str`  | A user defined name for the event.                                                                        |1440        | `data`      | `Any`  | The data associated with the event. This can be anything, though we suggest making it JSON serializable.  |14411442        Here are declarations associated with the standard events shown above:14431444        `format_docs`:14451446        ```python1447        def format_docs(docs: list[Document]) -> str:1448            '''Format the docs.'''1449            return ", ".join([doc.page_content for doc in docs])145014511452        format_docs = RunnableLambda(format_docs)1453        ```14541455        `some_tool`:14561457        ```python1458        @tool1459        def some_tool(x: int, y: str) -> dict:1460            '''Some_tool.'''1461            return {"x": x, "y": y}1462        ```14631464        `prompt`:14651466        ```python1467        template = ChatPromptTemplate.from_messages(1468            [1469                ("system", "You are Cat Agent 007"),1470                ("human", "{question}"),1471            ]1472        ).with_config({"run_name": "my_template", "tags": ["my_template"]})1473        ```14741475        !!! example14761477            ```python1478            from langchain_core.runnables import RunnableLambda147914801481            async def reverse(s: str) -> str:1482                return s[::-1]148314841485            chain = RunnableLambda(func=reverse)14861487            events = [1488                event async for event in chain.astream_events("hello", version="v2")1489            ]14901491            # Will produce the following events1492            # (run_id, and parent_ids has been omitted for brevity):1493            [1494                {1495                    "data": {"input": "hello"},1496                    "event": "on_chain_start",1497                    "metadata": {},1498                    "name": "reverse",1499                    "tags": [],1500                },1501                {1502                    "data": {"chunk": "olleh"},1503                    "event": "on_chain_stream",1504                    "metadata": {},1505                    "name": "reverse",1506                    "tags": [],1507                },1508                {1509                    "data": {"output": "olleh"},1510                    "event": "on_chain_end",1511                    "metadata": {},1512                    "name": "reverse",1513                    "tags": [],1514                },1515            ]1516            ```15171518        ```python title="Dispatch custom event"1519        from langchain_core.callbacks.manager import (1520            adispatch_custom_event,1521        )1522        from langchain_core.runnables import RunnableLambda, RunnableConfig1523        import asyncio152415251526        async def slow_thing(some_input: str, config: RunnableConfig) -> str:1527            \"\"\"Do something that takes a long time.\"\"\"1528            await asyncio.sleep(1) # Placeholder for some slow operation1529            await adispatch_custom_event(1530                "progress_event",1531                {"message": "Finished step 1 of 3"},1532                config=config # Must be included for python < 3.101533            )1534            await asyncio.sleep(1) # Placeholder for some slow operation1535            await adispatch_custom_event(1536                "progress_event",1537                {"message": "Finished step 2 of 3"},1538                config=config # Must be included for python < 3.101539            )1540            await asyncio.sleep(1) # Placeholder for some slow operation1541            return "Done"15421543        slow_thing = RunnableLambda(slow_thing)15441545        async for event in slow_thing.astream_events("some_input", version="v2"):1546            print(event)1547        ```15481549        Args:1550            input: The input to the `Runnable`.1551            config: The config to use for the `Runnable`.1552            version: The version of the schema to use. One of `'v1'`, `'v2'`,1553                or `'v3'`.15541555                Most callers should use `'v2'` (the default), which yields1556                `StreamEvent` dicts and supports custom events.15571558                `'v3'` selects the typed, content-block-centric streaming1559                protocol and is only supported on `Runnable` subclasses that1560                implement it (currently `BaseChatModel` and1561                `langgraph.CompiledGraph`); on a generic `Runnable` it raises1562                `NotImplementedError`. The `'v3'` API is in beta and may1563                change. See the subclass override (e.g.1564                `BaseChatModel.astream_events`) for the v3 return shape.15651566                `'v1'` is retained for backwards compatibility and will be1567                deprecated in `0.4.0`. Custom events are only surfaced in1568                `'v2'` / `'v3'`.1569            include_names: Only include events from `Runnable` objects with matching names.1570            include_types: Only include events from `Runnable` objects with matching types.1571            include_tags: Only include events from `Runnable` objects with matching tags.1572            exclude_names: Exclude events from `Runnable` objects with matching names.1573            exclude_types: Exclude events from `Runnable` objects with matching types.1574            exclude_tags: Exclude events from `Runnable` objects with matching tags.1575            **kwargs: Additional keyword arguments to pass to the `Runnable`.15761577        Yields:1578            An async stream of `StreamEvent`.15791580        Raises:1581            NotImplementedError: If the version is not `'v1'`, `'v2'`, or `'v3'`, or1582                if `'v3'` is requested on a `Runnable` that does not implement the v31583                streaming protocol.15841585        """  # noqa: E5011586        if version == "v3":1587            return self._astream_events_v3_unsupported()1588        return self._astream_events_v1_v2(1589            input,1590            config=config,1591            version=version,1592            include_names=include_names,1593            include_types=include_types,1594            include_tags=include_tags,1595            exclude_names=exclude_names,1596            exclude_types=exclude_types,1597            exclude_tags=exclude_tags,1598            **kwargs,1599        )16001601    async def _astream_events_v3_unsupported(self) -> Any:1602        """Coroutine that raises when v3 isn't implemented on this Runnable.16031604        Lets the public `astream_events(version="v3")` return an awaitable1605        whose error surfaces on `await`, matching the v3 contract on1606        subclasses that do implement the protocol.1607        """1608        msg = (1609            "astream_events(version='v3') is only supported on Runnable "1610            "subclasses that implement the v3 streaming protocol "1611            "(BaseChatModel, CompiledGraph). "1612            f"Got: {type(self).__name__}"1613        )1614        raise NotImplementedError(msg)16151616    async def _astream_events_v1_v2(1617        self,1618        input: Any,1619        config: RunnableConfig | None = None,1620        *,1621        version: Literal["v1", "v2"] = "v2",1622        include_names: Sequence[str] | None = None,1623        include_types: Sequence[str] | None = None,1624        include_tags: Sequence[str] | None = None,1625        exclude_names: Sequence[str] | None = None,1626        exclude_types: Sequence[str] | None = None,1627        exclude_tags: Sequence[str] | None = None,1628        **kwargs: Any,1629    ) -> AsyncIterator[StreamEvent]:1630        if version == "v2":1631            event_stream = _astream_events_implementation_v2(1632                self,1633                input,1634                config=config,1635                include_names=include_names,1636                include_types=include_types,1637                include_tags=include_tags,1638                exclude_names=exclude_names,1639                exclude_types=exclude_types,1640                exclude_tags=exclude_tags,1641                **kwargs,1642            )1643        elif version == "v1":1644            warn_deprecated(1645                since="1.3.3",1646                message=(1647                    "astream_events version='v1' is deprecated. "1648                    "Use version='v2' or astream instead."1649                ),1650                removal="2.0.0",1651            )1652            # First implementation, built on top of astream_log API1653            # This implementation will be deprecated as of 0.2.01654            event_stream = _astream_events_implementation_v1(1655                self,1656                input,1657                config=config,1658                include_names=include_names,1659                include_types=include_types,1660                include_tags=include_tags,1661                exclude_names=exclude_names,1662                exclude_types=exclude_types,1663                exclude_tags=exclude_tags,1664                **kwargs,1665            )1666        else:1667            msg = f"Unsupported version: {version!r}. Expected 'v1', 'v2', or 'v3'."  # type: ignore[unreachable]1668            raise NotImplementedError(msg)16691670        async with aclosing(event_stream):1671            async for event in event_stream:1672                yield event16731674    @overload1675    def stream_events(1676        self,1677        input: Any,1678        config: RunnableConfig | None = None,1679        *,1680        version: Literal["v1", "v2"] = "v2",1681        include_names: Sequence[str] | None = None,1682        include_types: Sequence[str] | None = None,1683        include_tags: Sequence[str] | None = None,1684        exclude_names: Sequence[str] | None = None,1685        exclude_types: Sequence[str] | None = None,1686        exclude_tags: Sequence[str] | None = None,1687        **kwargs: Any,1688    ) -> Iterator[StreamEvent]: ...16891690    @overload1691    def stream_events(1692        self,1693        input: Any,1694        config: RunnableConfig | None = None,1695        *,1696        version: Literal["v3"],1697        **kwargs: Any,1698    ) -> Iterator[Any]: ...16991700    def stream_events(1701        self,1702        input: Any,1703        config: RunnableConfig | None = None,1704        *,1705        version: Literal["v1", "v2", "v3"] = "v2",1706        include_names: Sequence[str] | None = None,1707        include_types: Sequence[str] | None = None,1708        include_tags: Sequence[str] | None = None,1709        exclude_names: Sequence[str] | None = None,1710        exclude_types: Sequence[str] | None = None,1711        exclude_tags: Sequence[str] | None = None,1712        **kwargs: Any,1713    ) -> Iterator[StreamEvent] | Iterator[Any]:1714        """Generate a stream of events synchronously.17151716        Synchronous counterpart to `astream_events`. For `version='v3'`, subclasses1717        that implement the v3 streaming protocol (`BaseChatModel`, `CompiledGraph`)1718        override this method. All other versions and base-class calls raise1719        `NotImplementedError`.17201721        Args:1722            input: The input to the `Runnable`.1723            config: The config to use for the `Runnable`.1724            version: The version of the schema to use. `'v3'` requires a subclass1725                that implements the v3 streaming protocol. `'v1'` and `'v2'` are not1726                supported on the sync path.1727            include_names: Only include events from `Runnable` objects with matching1728                names.1729            include_types: Only include events from `Runnable` objects with matching1730                types.1731            include_tags: Only include events from `Runnable` objects with matching1732                tags.1733            exclude_names: Exclude events from `Runnable` objects with matching names.1734            exclude_types: Exclude events from `Runnable` objects with matching types.1735            exclude_tags: Exclude events from `Runnable` objects with matching tags.1736            **kwargs: Additional keyword arguments to pass to the `Runnable`.17371738        Raises:1739            NotImplementedError: Always. Subclasses override this method for supported1740                versions.17411742        """1743        # Base impl always raises; consume args so they don't trip ARG002.1744        del input, config, include_names, include_types, include_tags1745        del exclude_names, exclude_types, exclude_tags, kwargs1746        if version == "v3":1747            msg = (1748                "stream_events(version='v3') is only supported on Runnable subclasses "1749                "that implement the v3 streaming protocol "1750                "(BaseChatModel, CompiledGraph). "1751                f"Got: {type(self).__name__}"1752            )1753            raise NotImplementedError(msg)1754        msg = (1755            f"stream_events(version={version!r}) is not supported. "1756            "Use astream_events() for v1/v2, or stream_events(version='v3') "1757            "on a supported subclass."1758        )1759        raise NotImplementedError(msg)17601761    def transform(1762        self,1763        input: Iterator[Input],1764        config: RunnableConfig | None = None,1765        **kwargs: Any | None,1766    ) -> Iterator[Output]:1767        """Transform inputs to outputs.17681769        Default implementation of transform, which buffers input and calls `astream`.17701771        Subclasses must override this method if they can start producing output while1772        input is still being generated.17731774        Args:1775            input: An iterator of inputs to the `Runnable`.1776            config: The config to use for the `Runnable`.1777            **kwargs: Additional keyword arguments to pass to the `Runnable`.17781779        Yields:1780            The output of the `Runnable`.17811782        """1783        final: Input1784        got_first_val = False17851786        for ichunk in input:1787            # The default implementation of transform is to buffer input and1788            # then call stream.1789            # It'll attempt to gather all input into a single chunk using1790            # the `+` operator.1791            # If the input is not addable, then we'll assume that we can1792            # only operate on the last chunk,1793            # and we'll iterate until we get to the last chunk.1794            if not got_first_val:1795                final = ichunk1796                got_first_val = True1797            else:1798                try:1799                    final = final + ichunk  # type: ignore[operator]1800                except TypeError:1801                    final = ichunk18021803        if got_first_val:1804            yield from self.stream(final, config, **kwargs)18051806    async def atransform(1807        self,1808        input: AsyncIterator[Input],1809        config: RunnableConfig | None = None,1810        **kwargs: Any | None,1811    ) -> AsyncIterator[Output]:1812        """Transform inputs to outputs.18131814        Default implementation of atransform, which buffers input and calls `astream`.18151816        Subclasses must override this method if they can start producing output while1817        input is still being generated.18181819        Args:1820            input: An async iterator of inputs to the `Runnable`.1821            config: The config to use for the `Runnable`.1822            **kwargs: Additional keyword arguments to pass to the `Runnable`.18231824        Yields:1825            The output of the `Runnable`.18261827        """1828        final: Input1829        got_first_val = False18301831        async for ichunk in input:1832            # The default implementation of transform is to buffer input and1833            # then call stream.1834            # It'll attempt to gather all input into a single chunk using1835            # the `+` operator.1836            # If the input is not addable, then we'll assume that we can1837            # only operate on the last chunk,1838            # and we'll iterate until we get to the last chunk.1839            if not got_first_val:1840                final = ichunk1841                got_first_val = True1842            else:1843                try:1844                    final = final + ichunk  # type: ignore[operator]1845                except TypeError:1846                    final = ichunk18471848        if got_first_val:1849            async for output in self.astream(final, config, **kwargs):1850                yield output18511852    def bind(self, **kwargs: Any) -> Runnable[Input, Output]:1853        """Bind arguments to a `Runnable`, returning a new `Runnable`.18541855        Useful when a `Runnable` in a chain requires an argument that is not1856        in the output of the previous `Runnable` or included in the user input.18571858        Args:1859            **kwargs: The arguments to bind to the `Runnable`.18601861        Returns:1862            A new `Runnable` with the arguments bound.18631864        Example:1865            ```python1866            from langchain_ollama import ChatOllama1867            from langchain_core.output_parsers import StrOutputParser18681869            model = ChatOllama(model="llama3.1")18701871            # Without bind1872            chain = model | StrOutputParser()18731874            chain.invoke("Repeat quoted words exactly: 'One two three four five.'")1875            # Output is 'One two three four five.'18761877            # With bind1878            chain = model.bind(stop=["three"]) | StrOutputParser()18791880            chain.invoke("Repeat quoted words exactly: 'One two three four five.'")1881            # Output is 'One two'1882            ```1883        """1884        return RunnableBinding(bound=self, kwargs=kwargs, config={})18851886    def with_config(1887        self,1888        config: RunnableConfig | None = None,1889        # Sadly Unpack is not well-supported by mypy so this will have to be untyped1890        **kwargs: Any,1891    ) -> Runnable[Input, Output]:1892        """Bind config to a `Runnable`, returning a new `Runnable`.18931894        Args:1895            config: The config to bind to the `Runnable`.1896            **kwargs: Additional keyword arguments to pass to the `Runnable`.18971898        Returns:1899            A new `Runnable` with the config bound.19001901        """1902        return RunnableBinding(1903            bound=self,1904            config=cast(1905                "RunnableConfig",1906                {**(config or {}), **kwargs},1907            ),1908            kwargs={},1909        )19101911    def with_listeners(1912        self,1913        *,1914        on_start: Callable[[Run], None]1915        | Callable[[Run, RunnableConfig], None]1916        | None = None,1917        on_end: Callable[[Run], None]1918        | Callable[[Run, RunnableConfig], None]1919        | None = None,1920        on_error: Callable[[Run], None]1921        | Callable[[Run, RunnableConfig], None]1922        | None = None,1923    ) -> Runnable[Input, Output]:1924        """Bind lifecycle listeners to a `Runnable`, returning a new `Runnable`.19251926        The Run object contains information about the run, including its `id`,1927        `type`, `input`, `output`, `error`, `start_time`, `end_time`, and1928        any tags or metadata added to the run.19291930        Args:1931            on_start: Called before the `Runnable` starts running, with the `Run`1932                object.1933            on_end: Called after the `Runnable` finishes running, with the `Run`1934                object.1935            on_error: Called if the `Runnable` throws an error, with the `Run`1936                object.19371938        Returns:1939            A new `Runnable` with the listeners bound.19401941        Example:1942            ```python1943            from langchain_core.runnables import RunnableLambda1944            from langchain_core.tracers.schemas import Run19451946            import time194719481949            def test_runnable(time_to_sleep: int):1950                time.sleep(time_to_sleep)195119521953            def fn_start(run_obj: Run):1954                print("start_time:", run_obj.start_time)195519561957            def fn_end(run_obj: Run):1958                print("end_time:", run_obj.end_time)195919601961            chain = RunnableLambda(test_runnable).with_listeners(1962                on_start=fn_start, on_end=fn_end1963            )1964            chain.invoke(2)1965            ```1966        """1967        return RunnableBinding(1968            bound=self,1969            config_factories=[1970                lambda config: {1971                    "callbacks": [1972                        RootListenersTracer(1973                            config=config,1974                            on_start=on_start,1975                            on_end=on_end,1976                            on_error=on_error,1977                        )1978                    ],1979                }1980            ],1981        )19821983    def with_alisteners(1984        self,1985        *,1986        on_start: AsyncListener | None = None,1987        on_end: AsyncListener | None = None,1988        on_error: AsyncListener | None = None,1989    ) -> Runnable[Input, Output]:1990        """Bind async lifecycle listeners to a `Runnable`.19911992        Returns a new `Runnable`.19931994        The Run object contains information about the run, including its `id`,1995        `type`, `input`, `output`, `error`, `start_time`, `end_time`, and1996        any tags or metadata added to the run.19971998        Args:1999            on_start: Called asynchronously before the `Runnable` starts running,2000                with the `Run` object.

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.

Generated by searchcode.com · powered by code_get_file + code_get_findings