Calculate trace_id and dotted_order client side (#15351)

<!-- Thank you for contributing to LangChain!

Please title your PR "<package>: <description>", where <package> is
whichever of langchain, community, core, experimental, etc. is being
modified.

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,
- **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` from the root
of the package you've modified to check this locally.

See contribution guidelines for more information on how to write/run
tests, lint, etc: https://python.langchain.com/docs/contributing/

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/docs/integrations` directory.

If no one reviews your PR within a few days, please @-mention one of
@baskaryan, @eyurtsev, @hwchase17.
 -->
This commit is contained in:
Ankush Gola 2024-01-02 10:13:34 -08:00 committed by GitHub
parent a8f6f33cd9
commit f50dba12ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 8 deletions

View File

@ -73,6 +73,7 @@ class BaseTracer(BaseCallbackHandler, ABC):
def _start_trace(self, run: Run) -> None: def _start_trace(self, run: Run) -> None:
"""Start a trace for a run.""" """Start a trace for a run."""
current_dotted_order = run.start_time.strftime("%Y%m%dT%H%M%S%fZ") + str(run.id)
if run.parent_run_id: if run.parent_run_id:
parent_run = self.run_map.get(str(run.parent_run_id)) parent_run = self.run_map.get(str(run.parent_run_id))
if parent_run: if parent_run:
@ -80,8 +81,23 @@ class BaseTracer(BaseCallbackHandler, ABC):
parent_run.child_execution_order = max( parent_run.child_execution_order = max(
parent_run.child_execution_order, run.child_execution_order parent_run.child_execution_order, run.child_execution_order
) )
run.trace_id = parent_run.trace_id
if parent_run.dotted_order:
run.dotted_order = (
parent_run.dotted_order + "." + current_dotted_order
)
else: else:
# Something wrong with tracer parent run has no dotted_order
logger.debug(
f"Parent run with UUID {run.parent_run_id} has no dotted_order."
)
else:
# Something wrong with tracer, parent run not found
# Calculate the trace_id and dotted_order server side
logger.debug(f"Parent run with UUID {run.parent_run_id} not found.") logger.debug(f"Parent run with UUID {run.parent_run_id} not found.")
else:
run.trace_id = run.id
run.dotted_order = current_dotted_order
self.run_map[str(run.id)] = run self.run_map[str(run.id)] = run
self._on_run_create(run) self._on_run_create(run)

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from uuid import UUID
from langsmith.schemas import RunBase as BaseRunV2 from langsmith.schemas import RunBase as BaseRunV2
@ -16,6 +17,8 @@ class Run(BaseRunV2):
child_runs: List[Run] = Field(default_factory=list) child_runs: List[Run] = Field(default_factory=list)
tags: Optional[List[str]] = Field(default_factory=list) tags: Optional[List[str]] = Field(default_factory=list)
events: List[Dict[str, Any]] = Field(default_factory=list) events: List[Dict[str, Any]] = Field(default_factory=list)
trace_id: Optional[UUID] = None
dotted_order: Optional[str] = None
@root_validator(pre=True) @root_validator(pre=True)
def assign_name(cls, values: dict) -> dict: def assign_name(cls, values: dict) -> dict:

View File

@ -70,6 +70,8 @@ def test_tracer_llm_run() -> None:
outputs=LLMResult(generations=[[]]), outputs=LLMResult(generations=[[]]),
error=None, error=None,
run_type="llm", run_type="llm",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -103,6 +105,8 @@ def test_tracer_chat_model_run() -> None:
outputs=LLMResult(generations=[[]]), outputs=LLMResult(generations=[[]]),
error=None, error=None,
run_type="llm", run_type="llm",
trace_id=run_managers[0].run_id,
dotted_order=f"20230101T000000000000Z{run_managers[0].run_id}",
) )
for run_manager in run_managers: for run_manager in run_managers:
run_manager.on_llm_end(response=LLMResult(generations=[[]])) run_manager.on_llm_end(response=LLMResult(generations=[[]]))
@ -139,6 +143,8 @@ def test_tracer_multiple_llm_runs() -> None:
outputs=LLMResult(generations=[[]]), outputs=LLMResult(generations=[[]]),
error=None, error=None,
run_type="llm", run_type="llm",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -170,6 +176,8 @@ def test_tracer_chain_run() -> None:
outputs={}, outputs={},
error=None, error=None,
run_type="chain", run_type="chain",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -198,6 +206,8 @@ def test_tracer_tool_run() -> None:
outputs={"output": "test"}, outputs={"output": "test"},
error=None, error=None,
run_type="tool", run_type="tool",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
tracer.on_tool_start(serialized={"name": "tool"}, input_str="test", run_id=uuid) tracer.on_tool_start(serialized={"name": "tool"}, input_str="test", run_id=uuid)
@ -257,6 +267,8 @@ def test_tracer_nested_run() -> None:
inputs={}, inputs={},
outputs={}, outputs={},
run_type="chain", run_type="chain",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}",
child_runs=[ child_runs=[
Run( Run(
id=tool_uuid, id=tool_uuid,
@ -275,6 +287,8 @@ def test_tracer_nested_run() -> None:
outputs=dict(output="test"), outputs=dict(output="test"),
error=None, error=None,
run_type="tool", run_type="tool",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{tool_uuid}",
child_runs=[ child_runs=[
Run( Run(
id=str(llm_uuid1), id=str(llm_uuid1),
@ -293,6 +307,8 @@ def test_tracer_nested_run() -> None:
inputs=dict(prompts=[]), inputs=dict(prompts=[]),
outputs=LLMResult(generations=[[]]), outputs=LLMResult(generations=[[]]),
run_type="llm", run_type="llm",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{tool_uuid}.20230101T000000000000Z{llm_uuid1}",
) )
], ],
), ),
@ -313,6 +329,8 @@ def test_tracer_nested_run() -> None:
inputs=dict(prompts=[]), inputs=dict(prompts=[]),
outputs=LLMResult(generations=[[]]), outputs=LLMResult(generations=[[]]),
run_type="llm", run_type="llm",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{llm_uuid2}",
), ),
], ],
) )
@ -342,6 +360,8 @@ def test_tracer_llm_run_on_error() -> None:
outputs=None, outputs=None,
error=repr(exception), error=repr(exception),
run_type="llm", run_type="llm",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -373,6 +393,8 @@ def test_tracer_llm_run_on_error_callback() -> None:
outputs=None, outputs=None,
error=repr(exception), error=repr(exception),
run_type="llm", run_type="llm",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
class FakeTracerWithLlmErrorCallback(FakeTracer): class FakeTracerWithLlmErrorCallback(FakeTracer):
@ -410,6 +432,8 @@ def test_tracer_chain_run_on_error() -> None:
outputs=None, outputs=None,
error=repr(exception), error=repr(exception),
run_type="chain", run_type="chain",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -441,6 +465,8 @@ def test_tracer_tool_run_on_error() -> None:
action="{'name': 'tool'}", action="{'name': 'tool'}",
error=repr(exception), error=repr(exception),
run_type="tool", run_type="tool",
trace_id=uuid,
dotted_order=f"20230101T000000000000Z{uuid}",
) )
tracer = FakeTracer() tracer = FakeTracer()
@ -511,6 +537,8 @@ def test_tracer_nested_runs_on_error() -> None:
inputs={}, inputs={},
outputs=None, outputs=None,
run_type="chain", run_type="chain",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}",
child_runs=[ child_runs=[
Run( Run(
id=str(llm_uuid1), id=str(llm_uuid1),
@ -529,6 +557,8 @@ def test_tracer_nested_runs_on_error() -> None:
inputs=dict(prompts=[]), inputs=dict(prompts=[]),
outputs=LLMResult(generations=[[]], llm_output=None), outputs=LLMResult(generations=[[]], llm_output=None),
run_type="llm", run_type="llm",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{llm_uuid1}",
), ),
Run( Run(
id=str(llm_uuid2), id=str(llm_uuid2),
@ -547,6 +577,8 @@ def test_tracer_nested_runs_on_error() -> None:
inputs=dict(prompts=[]), inputs=dict(prompts=[]),
outputs=LLMResult(generations=[[]], llm_output=None), outputs=LLMResult(generations=[[]], llm_output=None),
run_type="llm", run_type="llm",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{llm_uuid2}",
), ),
Run( Run(
id=str(tool_uuid), id=str(tool_uuid),
@ -565,6 +597,8 @@ def test_tracer_nested_runs_on_error() -> None:
inputs=dict(input="test"), inputs=dict(input="test"),
outputs=None, outputs=None,
action="{'name': 'tool'}", action="{'name': 'tool'}",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{tool_uuid}",
child_runs=[ child_runs=[
Run( Run(
id=str(llm_uuid3), id=str(llm_uuid3),
@ -583,6 +617,8 @@ def test_tracer_nested_runs_on_error() -> None:
inputs=dict(prompts=[]), inputs=dict(prompts=[]),
outputs=None, outputs=None,
run_type="llm", run_type="llm",
trace_id=chain_uuid,
dotted_order=f"20230101T000000000000Z{chain_uuid}.20230101T000000000000Z{tool_uuid}.20230101T000000000000Z{llm_uuid3}",
) )
], ],
run_type="tool", run_type="tool",

File diff suppressed because one or more lines are too long

View File

@ -101,6 +101,17 @@ class FakeTracer(BaseTracer):
return self.uuids_map[uuid] return self.uuids_map[uuid]
def _copy_run(self, run: Run) -> Run: def _copy_run(self, run: Run) -> Run:
if run.dotted_order:
levels = run.dotted_order.split(".")
processed_levels = []
for level in levels:
timestamp, run_id = level.split("Z")
new_run_id = self._replace_uuid(UUID(run_id))
processed_level = f"{timestamp}Z{new_run_id}"
processed_levels.append(processed_level)
new_dotted_order = ".".join(processed_levels)
else:
new_dotted_order = None
return run.copy( return run.copy(
update={ update={
"id": self._replace_uuid(run.id), "id": self._replace_uuid(run.id),
@ -110,6 +121,8 @@ class FakeTracer(BaseTracer):
"child_runs": [self._copy_run(child) for child in run.child_runs], "child_runs": [self._copy_run(child) for child in run.child_runs],
"execution_order": None, "execution_order": None,
"child_execution_order": None, "child_execution_order": None,
"trace_id": self._replace_uuid(run.trace_id) if run.trace_id else None,
"dotted_order": new_dotted_order,
} }
) )