Skip to content

Commit

Permalink
[Python] Pass through IO (#796)
Browse files Browse the repository at this point in the history
When loading from runnable config
  • Loading branch information
hinthornw authored Jun 17, 2024
1 parent 33b260a commit 8e151ed
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Install dependencies
run: |
poetry install --with dev,lint
poetry run pip install -U langchain
poetry run pip install -U langchain langchain-core
- name: Build ${{ matrix.python-version }}
run: poetry build
- name: Lint ${{ matrix.python-version }}
Expand Down
4 changes: 4 additions & 0 deletions python/langsmith/run_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ def from_runnable_config(
if (run := tracer.run_map.get(str(cb.parent_run_id))) and run.dotted_order:
dotted_order = run.dotted_order
kwargs["run_type"] = run.run_type
kwargs["inputs"] = run.inputs
kwargs["outputs"] = run.outputs
kwargs["start_time"] = run.start_time
kwargs["end_time"] = run.end_time
elif hasattr(tracer, "order_map") and cb.parent_run_id in tracer.order_map:
dotted_order = tracer.order_map[cb.parent_run_id][1]
else:
Expand Down
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langsmith"
version = "0.1.77"
version = "0.1.78"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
authors = ["LangChain <support@langchain.dev>"]
license = "MIT"
Expand Down
63 changes: 60 additions & 3 deletions python/tests/unit_tests/test_run_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def _get_calls(
) -> list:
calls = []
for _ in range(attempts):
time.sleep(0.1)
calls = [
c
for c in mock_client.session.request.mock_calls # type: ignore
Expand All @@ -43,6 +42,7 @@ def _get_calls(
return calls
if minimum is not None and len(calls) > minimum:
break
time.sleep(0.1)
return calls


Expand Down Expand Up @@ -185,9 +185,9 @@ def foo(kwargs: int, *, b: int, c: int, **some_other_kwargs: Any) -> None:
}


def _get_mock_client() -> Client:
def _get_mock_client(**kwargs: Any) -> Client:
mock_session = MagicMock()
client = Client(session=mock_session, api_key="test")
client = Client(session=mock_session, api_key="test", **kwargs)
return client


Expand Down Expand Up @@ -1059,3 +1059,60 @@ def my_tool(text: str) -> str:
mock_client = _get_mock_client()
tracer = LangChainTracer(client=mock_client)
my_tool.invoke({"text": "hello"}, {"callbacks": [tracer]})


def test_io_interops():
try:
from langchain.callbacks.tracers import LangChainTracer
from langchain.schema.runnable import RunnableLambda
except ImportError:
pytest.skip("Skipping test that requires langchain")
tracer = LangChainTracer(client=_get_mock_client(auto_batch_tracing=False))
stage_added = {
"parent_input": {"original_input": "original_input_value"},
"child_input": {"parent_input": "parent_input_value"},
"child_output": {"child_output": "child_output_value"},
"parent_output": {"parent_output": "parent_output_value"},
}

@RunnableLambda
def child(inputs: dict) -> dict:
return {**stage_added["child_output"], **inputs}

@RunnableLambda
def parent(inputs: dict) -> dict:
return {
**stage_added["parent_output"],
**child.invoke({**stage_added["child_input"], **inputs}),
}

expected_at_stage = {}
current = {}
for stage in stage_added:
current = {**current, **stage_added[stage]}
expected_at_stage[stage] = current
parent_result = parent.invoke(stage_added["parent_input"], {"callbacks": [tracer]})
assert parent_result == expected_at_stage["parent_output"]
mock_posts = _get_calls(tracer.client, minimum=2)
assert len(mock_posts) == 2
datas = [json.loads(mock_post.kwargs["data"]) for mock_post in mock_posts]
assert datas[0]["name"] == "parent"
assert datas[0]["inputs"] == expected_at_stage["parent_input"]
assert not datas[0]["outputs"]
assert datas[1]["name"] == "child"
assert datas[1]["inputs"] == expected_at_stage["child_input"]
assert not datas[1]["outputs"]
parent_uid = datas[0]["id"]
child_uid = datas[1]["id"]

# Check the patch requests
mock_patches = _get_calls(tracer.client, verbs={"PATCH"}, minimum=2)
assert len(mock_patches) == 2
child_patch = json.loads(mock_patches[0].kwargs["data"])
assert child_patch["id"] == child_uid
assert child_patch["outputs"] == expected_at_stage["child_output"]
assert child_patch["inputs"] == expected_at_stage["child_input"]
parent_patch = json.loads(mock_patches[1].kwargs["data"])
assert parent_patch["id"] == parent_uid
assert parent_patch["outputs"] == expected_at_stage["parent_output"]
assert parent_patch["inputs"] == expected_at_stage["parent_input"]

0 comments on commit 8e151ed

Please sign in to comment.