diff --git a/libs/core/Makefile b/libs/core/Makefile index 90e0642e728..69494679107 100644 --- a/libs/core/Makefile +++ b/libs/core/Makefile @@ -13,7 +13,7 @@ tests: poetry run pytest $(TEST_FILE) test_watch: - poetry run ptw --snapshot-update --now . -- -vv tests/unit_tests + poetry run ptw --snapshot-update --now . -- -vv $(TEST_FILE) test_profile: poetry run pytest -vv tests/unit_tests/ --profile-svg diff --git a/libs/core/langchain_core/runnables/utils.py b/libs/core/langchain_core/runnables/utils.py index fb4708dd03d..712ba0372eb 100644 --- a/libs/core/langchain_core/runnables/utils.py +++ b/libs/core/langchain_core/runnables/utils.py @@ -393,7 +393,9 @@ def get_function_nonlocals(func: Callable) -> List[Any]: visitor = FunctionNonLocals() visitor.visit(tree) values: List[Any] = [] - for k, v in inspect.getclosurevars(func).nonlocals.items(): + closure = inspect.getclosurevars(func) + candidates = {**closure.globals, **closure.nonlocals} + for k, v in candidates.items(): if k in visitor.nonlocals: values.append(v) for kk in visitor.nonlocals: diff --git a/libs/core/tests/unit_tests/runnables/test_utils.py b/libs/core/tests/unit_tests/runnables/test_utils.py index b309287f0b2..be6b3567249 100644 --- a/libs/core/tests/unit_tests/runnables/test_utils.py +++ b/libs/core/tests/unit_tests/runnables/test_utils.py @@ -1,5 +1,5 @@ import sys -from typing import Callable, Dict +from typing import Callable, Dict, Tuple import pytest @@ -41,6 +41,9 @@ def test_indent_lines_after_first(text: str, prefix: str, expected_output: str) assert indented_text == expected_output +global_agent = RunnableLambda(lambda x: x * 3) + + def test_nonlocals() -> None: agent = RunnableLambda(lambda x: x * 2) @@ -53,7 +56,23 @@ def test_nonlocals() -> None: def my_func3(input: str) -> str: return agent.invoke(input) + def my_func4(input: str) -> str: + return global_agent.invoke(input) + + def my_func5() -> Tuple[Callable[[str], str], RunnableLambda]: + global_agent = RunnableLambda(lambda x: x * 3) + + def my_func6(input: str) -> str: + return global_agent.invoke(input) + + return my_func6, global_agent + assert get_function_nonlocals(my_func) == [] assert get_function_nonlocals(my_func2) == [] assert get_function_nonlocals(my_func3) == [agent.invoke] + assert get_function_nonlocals(my_func4) == [global_agent.invoke] + func, nl = my_func5() + assert get_function_nonlocals(func) == [nl.invoke] assert RunnableLambda(my_func3).deps == [agent] + assert RunnableLambda(my_func4).deps == [global_agent] + assert RunnableLambda(func).deps == [nl]