mirror of
https://github.com/hwchase17/langchain.git
synced 2026-07-16 00:19:35 +00:00
Apply patch [skip ci]
This commit is contained in:
@@ -161,3 +161,185 @@ async def test_run_in_executor() -> None:
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
await run_in_executor(None, raises_stop_iter)
|
||||
|
||||
|
||||
def test_inherit_run_name_default_behavior() -> None:
|
||||
"""Test that by default, run_name is NOT inherited to child runs."""
|
||||
from langchain_core.runnables import RunnableLambda
|
||||
from langchain_core.runnables.config import patch_config
|
||||
|
||||
# Create a mock callback manager
|
||||
class MockCallbackManager:
|
||||
def get_child(self, tag: str = None) -> "MockCallbackManager":
|
||||
return MockCallbackManager()
|
||||
|
||||
# Test default behavior (inherit_run_name not set or False)
|
||||
config: RunnableConfig = {
|
||||
"run_name": "parent_run",
|
||||
"callbacks": MockCallbackManager(),
|
||||
}
|
||||
|
||||
# When callbacks are replaced, run_name should be deleted by default
|
||||
patched = patch_config(config, callbacks=MockCallbackManager())
|
||||
assert "run_name" not in patched, "run_name should be deleted by default"
|
||||
|
||||
# Explicitly set inherit_run_name to False
|
||||
config_explicit_false: RunnableConfig = {
|
||||
"run_name": "parent_run",
|
||||
"inherit_run_name": False,
|
||||
"callbacks": MockCallbackManager(),
|
||||
}
|
||||
|
||||
patched_explicit = patch_config(config_explicit_false, callbacks=MockCallbackManager())
|
||||
assert "run_name" not in patched_explicit, "run_name should be deleted when inherit_run_name=False"
|
||||
|
||||
|
||||
def test_inherit_run_name_enabled() -> None:
|
||||
"""Test that when inherit_run_name=True, run_name is preserved for child runs."""
|
||||
from langchain_core.runnables.config import patch_config
|
||||
|
||||
# Create a mock callback manager
|
||||
class MockCallbackManager:
|
||||
def get_child(self, tag: str = None) -> "MockCallbackManager":
|
||||
return MockCallbackManager()
|
||||
|
||||
# Test with inherit_run_name=True
|
||||
config: RunnableConfig = {
|
||||
"run_name": "parent_run",
|
||||
"inherit_run_name": True,
|
||||
"callbacks": MockCallbackManager(),
|
||||
}
|
||||
|
||||
# When callbacks are replaced, run_name should be preserved
|
||||
patched = patch_config(config, callbacks=MockCallbackManager())
|
||||
assert "run_name" in patched, "run_name should be preserved when inherit_run_name=True"
|
||||
assert patched["run_name"] == "parent_run", "run_name value should be unchanged"
|
||||
assert patched.get("inherit_run_name") is True, "inherit_run_name should be preserved"
|
||||
|
||||
|
||||
def test_inherit_run_name_with_chain() -> None:
|
||||
"""Test inherit_run_name behavior in a chain of runnables."""
|
||||
from typing import List
|
||||
from langchain_core.callbacks.base import BaseCallbackHandler
|
||||
from langchain_core.runnables import RunnableLambda
|
||||
|
||||
# Track run names through callbacks
|
||||
captured_names: List[str] = []
|
||||
|
||||
class TestCallbackHandler(BaseCallbackHandler):
|
||||
def on_chain_start(self, serialized: dict, inputs: Any, **kwargs: Any) -> None:
|
||||
name = kwargs.get("name", "unnamed")
|
||||
captured_names.append(name)
|
||||
|
||||
# Create a simple chain
|
||||
def identity(x: Any) -> Any:
|
||||
return x
|
||||
|
||||
def process(x: Any) -> str:
|
||||
return f"processed: {x}"
|
||||
|
||||
chain = RunnableLambda(identity) | RunnableLambda(process)
|
||||
|
||||
# Test 1: Default behavior (run_name not inherited)
|
||||
captured_names.clear()
|
||||
config_default: RunnableConfig = {
|
||||
"run_name": "custom_chain_run",
|
||||
"callbacks": [TestCallbackHandler()],
|
||||
}
|
||||
result = chain.invoke("test", config=config_default)
|
||||
assert result == "processed: test"
|
||||
# First run should have custom name, child runs should have default names
|
||||
assert captured_names[0] == "custom_chain_run", "Root run should have custom name"
|
||||
# Child runs should NOT have the custom name (they'll have their default names)
|
||||
for i in range(1, len(captured_names)):
|
||||
assert captured_names[i] != "custom_chain_run", f"Child run {i} should not inherit run_name by default"
|
||||
|
||||
# Test 2: With inherit_run_name=True
|
||||
captured_names.clear()
|
||||
config_inherit: RunnableConfig = {
|
||||
"run_name": "inherited_chain_run",
|
||||
"inherit_run_name": True,
|
||||
"callbacks": [TestCallbackHandler()],
|
||||
}
|
||||
result = chain.invoke("test", config=config_inherit)
|
||||
assert result == "processed: test"
|
||||
# All runs should have the same custom name when inherit_run_name=True
|
||||
assert captured_names[0] == "inherited_chain_run", "Root run should have custom name"
|
||||
# With inherit_run_name=True, child runs should also have the custom name
|
||||
for i in range(1, len(captured_names)):
|
||||
assert captured_names[i] == "inherited_chain_run", f"Child run {i} should inherit run_name when inherit_run_name=True"
|
||||
|
||||
|
||||
def test_inherit_run_name_with_override() -> None:
|
||||
"""Test that per-step with_config can override inherited run_name."""
|
||||
from typing import List
|
||||
from langchain_core.callbacks.base import BaseCallbackHandler
|
||||
from langchain_core.runnables import RunnableLambda
|
||||
|
||||
# Track run names through callbacks
|
||||
captured_names: List[str] = []
|
||||
|
||||
class TestCallbackHandler(BaseCallbackHandler):
|
||||
def on_chain_start(self, serialized: dict, inputs: Any, **kwargs: Any) -> None:
|
||||
name = kwargs.get("name", "unnamed")
|
||||
captured_names.append(name)
|
||||
|
||||
# Create a chain where one step has its own run_name
|
||||
def identity(x: Any) -> Any:
|
||||
return x
|
||||
|
||||
def process(x: Any) -> str:
|
||||
return f"processed: {x}"
|
||||
|
||||
# Middle step has explicit run_name override
|
||||
chain = (
|
||||
RunnableLambda(identity) |
|
||||
RunnableLambda(process).with_config(run_name="step_override") |
|
||||
RunnableLambda(identity)
|
||||
)
|
||||
|
||||
captured_names.clear()
|
||||
config: RunnableConfig = {
|
||||
"run_name": "global_run",
|
||||
"inherit_run_name": True,
|
||||
"callbacks": [TestCallbackHandler()],
|
||||
}
|
||||
|
||||
result = chain.invoke("test", config=config)
|
||||
assert result == "processed: test"
|
||||
|
||||
# Check that the override is present
|
||||
assert "step_override" in captured_names, "Step with explicit run_name should override inherited value"
|
||||
assert "global_run" in captured_names, "Global run_name should still be present for other steps"
|
||||
|
||||
|
||||
def test_inherit_run_name_merge_configs() -> None:
|
||||
"""Test that inherit_run_name is properly handled in merge_configs."""
|
||||
from langchain_core.runnables.config import merge_configs
|
||||
|
||||
# Test merging with inherit_run_name
|
||||
base: RunnableConfig = {
|
||||
"run_name": "base_run",
|
||||
"inherit_run_name": False,
|
||||
}
|
||||
|
||||
override: RunnableConfig = {
|
||||
"inherit_run_name": True,
|
||||
}
|
||||
|
||||
merged = merge_configs(base, override)
|
||||
assert merged.get("inherit_run_name") is True, "inherit_run_name should be overridden"
|
||||
assert merged.get("run_name") == "base_run", "run_name should be preserved from base"
|
||||
|
||||
# Test that inherit_run_name passes through ensure_config
|
||||
from langchain_core.runnables.config import ensure_config
|
||||
|
||||
config_with_inherit: RunnableConfig = {
|
||||
"run_name": "test_run",
|
||||
"inherit_run_name": True,
|
||||
}
|
||||
|
||||
ensured = ensure_config(config_with_inherit)
|
||||
assert ensured.get("inherit_run_name") is True, "inherit_run_name should pass through ensure_config"
|
||||
assert ensured.get("run_name") == "test_run", "run_name should be preserved"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user