Tony20100/langchain_full huggingface dataset:
return first_param.annotation
            else:
                return Any
        except ValueError:
            return Any
[docs]    def get_input_schema(
        self, config: Optional[RunnableConfig] = None
    ) -> Type[BaseModel]:
        """The pydantic schema for the input to this runnable."""
        func = getattr(self, "func", None) or getattr(self, "afunc")
        if isinstance(func, itemgetter):
            # This is terrible, but afaict it's not possible to access _items
            # on itemgetter objects, so we have to parse the repr
            items = str(func).replace("operator.itemgetter(", "")[:-1].split(", ")
            if all(
                item[0] == "'" and item[-1] == "'" and len(item) > 2 for item in items
            ):
                # It's a dict, lol
                return create_model(
                    self.get_name("Input"),
                    **{item[1:-1]: (Any, None) for item in items},  # type: ignore
                )
            else:
                return create_model(
                    self.get_name("Input"),
                    __root__=(List[Any], None),
                )
        if self.InputType != Any:
            return super().get_input_schema(config)
        if dict_keys := get_function_first_arg_dict_keys(func):
            return create_model(
                self.get_name("Input"),
                **{key: (Any, None) for key in dict_keys},  # type: ignore
            )
        return super().get_input_schema(config)
    @property
    def OutputType(self) -> Any:
        """The type of the output of this runnable as a type annotation."""
"""The type of the output of this runnable as a type annotation."""
        func = getattr(self, "func", None) or getattr(self, "afunc")
        try:
            sig = inspect.signature(func)
            if sig.return_annotation != inspect.Signature.empty:
                # unwrap iterator types
                if getattr(sig.return_annotation, "__origin__", None) in (
                    collections.abc.Iterator,
                    collections.abc.AsyncIterator,
                ):
                    return getattr(sig.return_annotation, "__args__", (Any,))[0]
                return sig.return_annotation
            else:
                return Any
        except ValueError:
            return Any
    @property
    def deps(self) -> List[Runnable]:
        """The dependencies of this runnable."""
        if hasattr(self, "func"):
            objects = get_function_nonlocals(self.func)
        elif hasattr(self, "afunc"):
            objects = get_function_nonlocals(self.afunc)
        else:
            objects = []
        deps: List[Runnable] = []
        for obj in objects:
            if isinstance(obj, Runnable):
                deps.append(obj)
            elif isinstance(getattr(obj, "__self__", None), Runnable):
                deps.append(obj.__self__)
        return deps
    @property
    def config_specs(self) -> List[ConfigurableFieldSpec]:
        return get_unique_config_specs(
            spec for dep in self.deps for spec in dep.config_specs
        )
[docs]    def get_graph(self, config: RunnableConfig | None = None) -> Graph:
        if deps := self.deps:
            graph = Graph()
            input_node = graph.add_node(self.get_input_schema(config))
            output_node = graph.add_node(self.get_output_schema(config))
            for dep in deps:
for dep in deps:
                dep_graph = dep.get_graph()
                dep_graph.trim_first_node()
                dep_graph.trim_last_node()
                if not dep_graph:
                    graph.add_edge(input_node, output_node)
                else:
                    dep_first_node, dep_last_node = graph.extend(dep_graph)
                    if not dep_first_node:
                        raise ValueError(f"Runnable {dep} has no first node")
                    if not dep_last_node:
                        raise ValueError(f"Runnable {dep} has no last node")
                    graph.add_edge(input_node, dep_first_node)
                    graph.add_edge(dep_last_node, output_node)
        else:
            graph = super().get_graph(config)
        return graph
    def __eq__(self, other: Any) -> bool:
        if isinstance(other, RunnableLambda):
            if hasattr(self, "func") and hasattr(other, "func"):
                return self.func == other.func
            elif hasattr(self, "afunc") and hasattr(other, "afunc"):
                return self.afunc == other.afunc
            else:
                return False
        else:
            return False
    def __repr__(self) -> str:
        """A string representation of this runnable."""
        if hasattr(self, "func") and isinstance(self.func, itemgetter):
            return f"RunnableLambda({str(self.func)[len('operator.'):]})"
        elif hasattr(self, "func"):
            return f"RunnableLambda({get_lambda_source(self.func) or '...'})"
        elif hasattr(self, "afunc"):
            return f"RunnableLambda(afunc={get_lambda_source(self.afunc) or '...'})"
        else:
            return "RunnableLambda(...)"
    def _invoke(
        self,
        input: Input,
def _invoke(
        self,
        input: Input,
        run_manager: CallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> Output:
        if inspect.isgeneratorfunction(self.func):
            output: Optional[Output] = None
            for chunk in call_func_with_variable_args(
                cast(Callable[[Input], Iterator[Output]], self.func),
                input,
                config,
                run_manager,
                **kwargs,
            ):
                if output is None:
                    output = chunk
                else:
                    try:
                        output = output + chunk  # type: ignore[operator]
                    except TypeError:
                        output = chunk
        else:
            output = call_func_with_variable_args(
                self.func, input, config, run_manager, **kwargs
            )
        # If the output is a runnable, invoke it
        if isinstance(output, Runnable):
            recursion_limit = config["recursion_limit"]
            if recursion_limit <= 0:
                raise RecursionError(
                    f"Recursion limit reached when invoking {self} with input {input}."
                )
            output = output.invoke(
                input,
                patch_config(
                    config,
                    callbacks=run_manager.get_child(),
                    recursion_limit=recursion_limit - 1,
                ),
            )
        return cast(Output, output)
    async def _ainvoke(
        self,
        input: Input,
        run_manager: AsyncCallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> Output:
        if hasattr(self, "afunc"):
            afunc = self.afunc
        else:
            if inspect.isgeneratorfunction(self.func):
                def func(
else:
            if inspect.isgeneratorfunction(self.func):
                def func(
                    input: Input,
                    run_manager: AsyncCallbackManagerForChainRun,
                    config: RunnableConfig,
                    **kwargs: Any,
                ) -> Output:
                    output: Optional[Output] = None
                    for chunk in call_func_with_variable_args(
                        cast(Callable[[Input], Iterator[Output]], self.func),
                        input,
                        config,
                        run_manager.get_sync(),
                        **kwargs,
                    ):
                        if output is None:
                            output = chunk
                        else:
                            try:
                                output = output + chunk  # type: ignore[operator]
                            except TypeError:
                                output = chunk
                    return cast(Output, output)
            else:
                def func(
                    input: Input,
                    run_manager: AsyncCallbackManagerForChainRun,
                    config: RunnableConfig,
                    **kwargs: Any,
                ) -> Output:
                    return call_func_with_variable_args(
                        self.func, input, config, run_manager.get_sync(), **kwargs
                    )
            @wraps(func)
            async def f(*args, **kwargs):  # type: ignore[no-untyped-def]
                return await run_in_executor(config, func, *args, **kwargs)
            afunc = f
        if is_async_generator(afunc):
            output: Optional[Output] = None
            async for chunk in cast(
                AsyncIterator[Output],
                acall_func_with_variable_args(
                    cast(Callable, afunc),
                    input,
                    config,
                    run_manager,
                    **kwargs,
                ),
            ):
                if output is None:
                    output = chunk
                else:
                    try:
if output is None:
                    output = chunk
                else:
                    try:
                        output = output + chunk  # type: ignore[operator]
                    except TypeError:
                        output = chunk
        else:
            output = await acall_func_with_variable_args(
                cast(Callable, afunc), input, config, run_manager, **kwargs
            )
        # If the output is a runnable, invoke it
        if isinstance(output, Runnable):
            recursion_limit = config["recursion_limit"]
            if recursion_limit <= 0:
                raise RecursionError(
                    f"Recursion limit reached when invoking {self} with input {input}."
                )
            output = await output.ainvoke(
                input,
                patch_config(
                    config,
                    callbacks=run_manager.get_child(),
                    recursion_limit=recursion_limit - 1,
                ),
            )
        return cast(Output, output)
    def _config(
        self, config: Optional[RunnableConfig], callable: Callable[..., Any]
    ) -> RunnableConfig:
        return ensure_config(config)
[docs]    def invoke(
        self,
        input: Input,
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> Output:
        """Invoke this runnable synchronously."""
        if hasattr(self, "func"):
            return self._call_with_config(
                self._invoke,
                input,
                self._config(config, self.func),
                **kwargs,
            )
        else:
            raise TypeError(
                "Cannot invoke a coroutine function synchronously."
                "Use `ainvoke` instead."
            )
[docs]    async def ainvoke(
        self,
        input: Input,
[docs]    async def ainvoke(
        self,
        input: Input,
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> Output:
        """Invoke this runnable asynchronously."""
        the_func = self.afunc if hasattr(self, "afunc") else self.func
        return await self._acall_with_config(
            self._ainvoke,
            input,
            self._config(config, the_func),
            **kwargs,
        )
    def _transform(
        self,
        input: Iterator[Input],
        run_manager: CallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> Iterator[Output]:
        final: Input
        got_first_val = False
        for ichunk in input:
            # By definitions, RunnableLambdas consume all input before emitting output.
            # If the input is not addable, then we'll assume that we can
            # only operate on the last chunk.
            # So we'll iterate until we get to the last chunk!
            if not got_first_val:
                final = ichunk
                got_first_val = True
            else:
                try:
                    final = final + ichunk  # type: ignore[operator]
                except TypeError:
                    final = ichunk
        if inspect.isgeneratorfunction(self.func):
            output: Optional[Output] = None
            for chunk in call_func_with_variable_args(
                self.func, cast(Input, final), config, run_manager, **kwargs
            ):
                yield chunk
                if output is None:
                    output = chunk
                else:
                    try:
                        output = output + chunk
                    except TypeError:
                        output = chunk
        else:
except TypeError:
                        output = chunk
        else:
            output = call_func_with_variable_args(
                self.func, cast(Input, final), config, run_manager, **kwargs
            )
        # If the output is a runnable, use its stream output
        if isinstance(output, Runnable):
            recursion_limit = config["recursion_limit"]
            if recursion_limit <= 0:
                raise RecursionError(
                    f"Recursion limit reached when invoking "
                    f"{self} with input {final}."
                )
            for chunk in output.stream(
                final,
                patch_config(
                    config,
                    callbacks=run_manager.get_child(),
                    recursion_limit=recursion_limit - 1,
                ),
            ):
                yield chunk
        elif not inspect.isgeneratorfunction(self.func):
            # Otherwise, just yield it
            yield cast(Output, output)
[docs]    def transform(
        self,
        input: Iterator[Input],
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> Iterator[Output]:
        if hasattr(self, "func"):
            for output in self._transform_stream_with_config(
                input,
                self._transform,
                self._config(config, self.func),
                **kwargs,
            ):
                yield output
        else:
            raise TypeError(
                "Cannot stream a coroutine function synchronously."
                "Use `astream` instead."
            )
[docs]    def stream(
        self,
        input: Input,
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> Iterator[Output]:
        return self.transform(iter([input]), config, **kwargs)
return self.transform(iter([input]), config, **kwargs)
    async def _atransform(
        self,
        input: AsyncIterator[Input],
        run_manager: AsyncCallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> AsyncIterator[Output]:
        final: Input
        got_first_val = False
        async for ichunk in input:
            # By definitions, RunnableLambdas consume all input before emitting output.
            # If the input is not addable, then we'll assume that we can
            # only operate on the last chunk.
            # So we'll iterate until we get to the last chunk!
            if not got_first_val:
                final = ichunk
                got_first_val = True
            else:
                try:
                    final = final + ichunk  # type: ignore[operator]
                except TypeError:
                    final = ichunk
        if hasattr(self, "afunc"):
            afunc = self.afunc
        else:
            if inspect.isgeneratorfunction(self.func):
                raise TypeError(
                    "Cannot stream from a generator function asynchronously."
                    "Use .stream() instead."
                )
            def func(
                input: Input,
                run_manager: AsyncCallbackManagerForChainRun,
                config: RunnableConfig,
                **kwargs: Any,
            ) -> Output:
                return call_func_with_variable_args(
                    self.func, input, config, run_manager.get_sync(), **kwargs
                )
            @wraps(func)
            async def f(*args, **kwargs):  # type: ignore[no-untyped-def]
                return await run_in_executor(config, func, *args, **kwargs)
            afunc = f
        if is_async_generator(afunc):
afunc = f
        if is_async_generator(afunc):
            output: Optional[Output] = None
            async for chunk in cast(
                AsyncIterator[Output],
                acall_func_with_variable_args(
                    cast(Callable, afunc),
                    cast(Input, final),
                    config,
                    run_manager,
                    **kwargs,
                ),
            ):
                yield chunk
                if output is None:
                    output = chunk
                else:
                    try:
                        output = output + chunk  # type: ignore[operator]
                    except TypeError:
                        output = chunk
        else:
            output = await acall_func_with_variable_args(
                cast(Callable, afunc), cast(Input, final), config, run_manager, **kwargs
            )
        # If the output is a runnable, use its astream output
        if isinstance(output, Runnable):
            recursion_limit = config["recursion_limit"]
            if recursion_limit <= 0:
                raise RecursionError(
                    f"Recursion limit reached when invoking "
                    f"{self} with input {final}."
                )
            async for chunk in output.astream(
                final,
                patch_config(
                    config,
                    callbacks=run_manager.get_child(),
                    recursion_limit=recursion_limit - 1,
                ),
            ):
                yield chunk
        elif not is_async_generator(afunc):
            # Otherwise, just yield it
            yield cast(Output, output)
[docs]    async def atransform(
        self,
        input: AsyncIterator[Input],
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> AsyncIterator[Output]:
        async for output in self._atransform_stream_with_config(
async for output in self._atransform_stream_with_config(
            input,
            self._atransform,
            self._config(config, self.afunc if hasattr(self, "afunc") else self.func),
            **kwargs,
        ):
            yield output
[docs]    async def astream(
        self,
        input: Input,
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> AsyncIterator[Output]:
        async def input_aiter() -> AsyncIterator[Input]:
            yield input
        async for chunk in self.atransform(input_aiter(), config, **kwargs):
            yield chunk
[docs]class RunnableEachBase(RunnableSerializable[List[Input], List[Output]]):
    """Runnable that delegates calls to another Runnable
    with each element of the input sequence.
    Use only if creating a new RunnableEach subclass with different __init__ args.
    See documentation for RunnableEach for more details.
    """
    bound: Runnable[Input, Output]
    class Config:
        arbitrary_types_allowed = True
    @property
    def InputType(self) -> Any:
        return List[self.bound.InputType]  # type: ignore[name-defined]
[docs]    def get_input_schema(
        self, config: Optional[RunnableConfig] = None
    ) -> Type[BaseModel]:
        return create_model(
            self.get_name("Input"),
            __root__=(
                List[self.bound.get_input_schema(config)],  # type: ignore
                None,
            ),
        )
    @property
    def OutputType(self) -> Type[List[Output]]:
        return List[self.bound.OutputType]  # type: ignore[name-defined]
return List[self.bound.OutputType]  # type: ignore[name-defined]
[docs]    def get_output_schema(
        self, config: Optional[RunnableConfig] = None
    ) -> Type[BaseModel]:
        schema = self.bound.get_output_schema(config)
        return create_model(
            self.get_name("Output"),
            __root__=(
                List[schema],  # type: ignore
                None,
            ),
        )
    @property
    def config_specs(self) -> List[ConfigurableFieldSpec]:
        return self.bound.config_specs
[docs]    def get_graph(self, config: Optional[RunnableConfig] = None) -> Graph:
        return self.bound.get_graph(config)
[docs]    @classmethod
    def is_lc_serializable(cls) -> bool:
        return True
[docs]    @classmethod
    def get_lc_namespace(cls) -> List[str]:
        """Get the namespace of the langchain object."""
        return ["langchain", "schema", "runnable"]
    def _invoke(
        self,
        inputs: List[Input],
        run_manager: CallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> List[Output]:
        configs = [
            patch_config(config, callbacks=run_manager.get_child()) for _ in inputs
        ]
        return self.bound.batch(inputs, configs, **kwargs)
[docs]    def invoke(
        self, input: List[Input], config: Optional[RunnableConfig] = None, **kwargs: Any
    ) -> List[Output]:
        return self._call_with_config(self._invoke, input, config, **kwargs)
    async def _ainvoke(
        self,
        inputs: List[Input],
async def _ainvoke(
        self,
        inputs: List[Input],
        run_manager: AsyncCallbackManagerForChainRun,
        config: RunnableConfig,
        **kwargs: Any,
    ) -> List[Output]:
        configs = [
            patch_config(config, callbacks=run_manager.get_child()) for _ in inputs
        ]
        return await self.bound.abatch(inputs, configs, **kwargs)
[docs]    async def ainvoke(
        self, input: List[Input], config: Optional[RunnableConfig] = None, **kwargs: Any
    ) -> List[Output]:
        return await self._acall_with_config(self._ainvoke, input, config, **kwargs)
[docs]    async def astream_events(
        self,
        input: Input,
        config: Optional[RunnableConfig] = None,
        **kwargs: Optional[Any],
    ) -> AsyncIterator[StreamEvent]:
        for _ in range(1):
            raise NotImplementedError(
                "RunnableEach does not support astream_events yet."
            )
            yield
[docs]class RunnableEach(RunnableEachBase[Input, Output]):
    """Runnable that delegates calls to another Runnable
    with each element of the input sequence.
    It allows you to call multiple inputs with the bounded Runnable.
    RunnableEach makes it easy to run multiple inputs for the runnable.
    In the below example, we associate and run three inputs
    with a Runnable:
        .. code-block:: python
            from langchain_core.runnables.base import RunnableEach
            from langchain_openai import ChatOpenAI
            from langchain_core.prompts import ChatPromptTemplate
            from langchain_core.output_parsers import StrOutputParser
            prompt = ChatPromptTemplate.from_template("Tell me a short joke about