Files
2026-07-13 13:22:34 +08:00

132 lines
3.8 KiB
Python

import random
from _data import generate_trace_data
from pytest_benchmark.fixture import BenchmarkFixture
import mlflow
from mlflow.entities.span import SpanType
from mlflow.store.tracking.sqlalchemy_store import SqlAlchemyStore
DEFAULT_SPANS = 100
INGEST_ROUNDS = 20
INGEST_WARMUP = 3
def test_ingest(benchmark: BenchmarkFixture, store: SqlAlchemyStore, experiment_id: str) -> None:
rng = random.Random(42)
def setup():
ti, sp = generate_trace_data(experiment_id, DEFAULT_SPANS, rng)
return (ti, sp), {}
def do(ti, sp):
store.start_trace(ti)
store.log_spans(experiment_id, sp)
benchmark.pedantic(
do, setup=setup, iterations=1, rounds=INGEST_ROUNDS, warmup_rounds=INGEST_WARMUP
)
def test_search_by_tag(
benchmark: BenchmarkFixture,
store: SqlAlchemyStore,
experiment_id: str,
seeded: list[str],
) -> None:
benchmark(
store.search_traces,
locations=[experiment_id],
max_results=100,
filter_string="tag.env = 'prod'",
)
def test_search_by_state(
benchmark: BenchmarkFixture,
store: SqlAlchemyStore,
experiment_id: str,
seeded: list[str],
) -> None:
benchmark(
store.search_traces,
locations=[experiment_id],
max_results=100,
filter_string="status = 'ERROR'",
)
def test_search_by_name_like(
benchmark: BenchmarkFixture,
store: SqlAlchemyStore,
experiment_id: str,
seeded: list[str],
) -> None:
benchmark(
store.search_traces,
locations=[experiment_id],
max_results=100,
filter_string="name LIKE 'rag_pipeline%'",
)
def test_search_by_timestamp(
benchmark: BenchmarkFixture,
store: SqlAlchemyStore,
experiment_id: str,
seeded: list[str],
) -> None:
benchmark(
store.search_traces,
locations=[experiment_id],
max_results=100,
filter_string="timestamp > 0",
order_by=["timestamp DESC"],
)
def _run_agent_workflow(num_tools: int, num_docs: int, query: str) -> None:
with mlflow.start_span(name="agent_run", span_type=SpanType.AGENT) as root:
root.set_inputs({"query": query})
with mlflow.start_span(name="retrieve", span_type=SpanType.RETRIEVER) as retr:
retr.set_inputs({"query": query})
docs = [
{"id": f"doc_{i}", "score": 0.9 - i * 0.01, "text": f"doc text {i} " * 10}
for i in range(num_docs)
]
retr.set_outputs({"documents": docs})
with mlflow.start_span(name="plan", span_type=SpanType.CHAIN) as planner:
planner.set_inputs({"query": query, "num_docs": len(docs)})
steps = [f"step_{i}" for i in range(num_tools)]
planner.set_outputs({"steps": steps})
tool_results = []
for step in steps:
with mlflow.start_span(name=f"tool:{step}", span_type=SpanType.TOOL) as tool:
tool.set_inputs({"step": step})
result = {"step": step, "status": "ok", "value": len(step)}
tool.set_outputs(result)
tool_results.append(result)
with mlflow.start_span(name="summarize", span_type=SpanType.LLM) as summ:
summ.set_inputs({"query": query, "tool_results": tool_results})
response = f"Answer to {query!r} using {num_docs} docs and {num_tools} tool calls."
summ.set_outputs({"response": response})
summ.set_attribute("model", "gpt-test")
summ.set_attribute("usage.input_tokens", 1234)
summ.set_attribute("usage.output_tokens", 567)
root.set_outputs({"response": response})
def test_e2e_agent(benchmark: BenchmarkFixture, e2e_setup: None) -> None:
counter = [0]
def do():
_run_agent_workflow(num_tools=20, num_docs=20, query=f"q-{counter[0]}")
counter[0] += 1
benchmark(do)