mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-22 14:49:29 +00:00
Support runnable factories in .configurable_alts() (#12065)
<!-- Thank you for contributing to LangChain! Replace this entire comment with: - **Description:** a description of the change, - **Issue:** the issue # it fixes (if applicable), - **Dependencies:** any dependencies required for this change, - **Tag maintainer:** for a quicker response, tag the relevant maintainer (see below), - **Twitter handle:** we announce bigger features on Twitter. If your PR gets announced, and you'd like a mention, we'll gladly shout you out! Please make sure your PR is passing linting and testing before submitting. Run `make format`, `make lint` and `make test` to check this locally. See contribution guidelines for more information on how to write/run tests, lint, etc: https://github.com/langchain-ai/langchain/blob/master/.github/CONTRIBUTING.md If you're adding a new integration, please include: 1. a test for the integration, preferably unit tests that do not rely on network access, 2. an example notebook showing its use. It lives in `docs/extras` directory. If no one reviews your PR within a few days, please @-mention one of @baskaryan, @eyurtsev, @hwchase17. -->
This commit is contained in:
parent
b01a443ee5
commit
5fee61a207
@ -1013,7 +1013,7 @@ class RunnableSerializable(Serializable, Runnable[Input, Output]):
|
|||||||
self,
|
self,
|
||||||
which: ConfigurableField,
|
which: ConfigurableField,
|
||||||
default_key: str = "default",
|
default_key: str = "default",
|
||||||
**kwargs: Runnable[Input, Output],
|
**kwargs: Union[Runnable[Input, Output], Callable[[], Runnable[Input, Output]]],
|
||||||
) -> RunnableSerializable[Input, Output]:
|
) -> RunnableSerializable[Input, Output]:
|
||||||
from langchain.schema.runnable.configurable import (
|
from langchain.schema.runnable.configurable import (
|
||||||
RunnableConfigurableAlternatives,
|
RunnableConfigurableAlternatives,
|
||||||
|
@ -6,6 +6,7 @@ from abc import abstractmethod
|
|||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
AsyncIterator,
|
AsyncIterator,
|
||||||
|
Callable,
|
||||||
Dict,
|
Dict,
|
||||||
Iterator,
|
Iterator,
|
||||||
List,
|
List,
|
||||||
@ -287,7 +288,10 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|||||||
|
|
||||||
which: ConfigurableField
|
which: ConfigurableField
|
||||||
|
|
||||||
alternatives: Dict[str, RunnableSerializable[Input, Output]]
|
alternatives: Dict[
|
||||||
|
str,
|
||||||
|
Union[Runnable[Input, Output], Callable[[], Runnable[Input, Output]]],
|
||||||
|
]
|
||||||
|
|
||||||
default_key: str = "default"
|
default_key: str = "default"
|
||||||
|
|
||||||
@ -314,7 +318,12 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|||||||
default=self.default_key,
|
default=self.default_key,
|
||||||
),
|
),
|
||||||
*self.default.config_specs,
|
*self.default.config_specs,
|
||||||
] + [s for alt in self.alternatives.values() for s in alt.config_specs]
|
] + [
|
||||||
|
s
|
||||||
|
for alt in self.alternatives.values()
|
||||||
|
if isinstance(alt, RunnableSerializable)
|
||||||
|
for s in alt.config_specs
|
||||||
|
]
|
||||||
|
|
||||||
def configurable_fields(
|
def configurable_fields(
|
||||||
self, **kwargs: AnyConfigurableField
|
self, **kwargs: AnyConfigurableField
|
||||||
@ -333,7 +342,11 @@ class RunnableConfigurableAlternatives(DynamicRunnable[Input, Output]):
|
|||||||
if which == self.default_key:
|
if which == self.default_key:
|
||||||
return self.default
|
return self.default
|
||||||
elif which in self.alternatives:
|
elif which in self.alternatives:
|
||||||
return self.alternatives[which]
|
alt = self.alternatives[which]
|
||||||
|
if isinstance(alt, Runnable):
|
||||||
|
return alt
|
||||||
|
else:
|
||||||
|
return alt()
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown alternative: {which}")
|
raise ValueError(f"Unknown alternative: {which}")
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from functools import partial
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
@ -925,6 +926,17 @@ def test_configurable_fields() -> None:
|
|||||||
).invoke({"name": "John"}) == {"llm1": "c", "llm2": "c", "llm3": "d"}
|
).invoke({"name": "John"}) == {"llm1": "c", "llm2": "c", "llm3": "d"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_configurable_alts_factory() -> None:
|
||||||
|
fake_llm = FakeListLLM(responses=["a"]).configurable_alternatives(
|
||||||
|
ConfigurableField(id="llm", name="LLM"),
|
||||||
|
chat=partial(FakeListLLM, responses=["b"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert fake_llm.invoke("...") == "a"
|
||||||
|
|
||||||
|
assert fake_llm.with_config(configurable={"llm": "chat"}).invoke("...") == "b"
|
||||||
|
|
||||||
|
|
||||||
def test_configurable_fields_example() -> None:
|
def test_configurable_fields_example() -> None:
|
||||||
fake_chat = FakeListChatModel(responses=["b"]).configurable_fields(
|
fake_chat = FakeListChatModel(responses=["b"]).configurable_fields(
|
||||||
responses=ConfigurableFieldMultiOption(
|
responses=ConfigurableFieldMultiOption(
|
||||||
|
Loading…
Reference in New Issue
Block a user