Skip to content

Commit 795fdc4

Browse files
committed
fix(ui): make pipeline trace Arrow-safe
1 parent 9b08dca commit 795fdc4

2 files changed

Lines changed: 113 additions & 4 deletions

File tree

‎app/components/show_working.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ def render_show_working(result: PipelineRunResult) -> None:
2020
{
2121
"node": str(entry.get("node", "?")),
2222
"model": str(entry.get("model", "—")),
23-
"tokens_in": entry.get("input_tokens", "—"),
24-
"tokens_out": entry.get("output_tokens", "—"),
25-
"confidence": entry.get("confidence", "—"),
23+
"tokens_in": str(entry.get("input_tokens", "—")),
24+
"tokens_out": str(entry.get("output_tokens", "—")),
25+
"confidence": str(entry.get("confidence", "—")),
2626
}
2727
)
2828
if trace_rows:
2929
st.markdown(f"**{t('trace_header')}**")
3030
st.dataframe(
3131
pd.DataFrame(trace_rows),
32-
use_container_width=True,
32+
width="stretch",
3333
hide_index=True,
3434
)
3535

‎tests/app/test_show_working.py‎

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from __future__ import annotations
2+
3+
import sys
4+
import types
5+
from contextlib import nullcontext
6+
from pathlib import Path
7+
from types import SimpleNamespace
8+
from typing import Any
9+
10+
import pyarrow as pa
11+
import pytest
12+
13+
APP_DIR = Path(__file__).resolve().parents[2] / "app"
14+
15+
16+
class _RecordingStreamlit(types.ModuleType):
17+
def __init__(self) -> None:
18+
super().__init__("streamlit")
19+
self.dataframes: list[Any] = []
20+
self.dataframe_kwargs: list[dict[str, Any]] = []
21+
22+
def expander(self, *_: Any, **__: Any) -> Any:
23+
return nullcontext()
24+
25+
def columns(self, count: int) -> list[Any]:
26+
return [nullcontext() for _ in range(count)]
27+
28+
def dataframe(self, frame: Any, **kwargs: Any) -> None:
29+
self.dataframes.append(frame)
30+
self.dataframe_kwargs.append(kwargs)
31+
32+
def markdown(self, *_: Any, **__: Any) -> None:
33+
pass
34+
35+
def write(self, *_: Any, **__: Any) -> None:
36+
pass
37+
38+
def error(self, *_: Any, **__: Any) -> None:
39+
pass
40+
41+
42+
@pytest.fixture
43+
def show_working_module(monkeypatch: pytest.MonkeyPatch) -> Any:
44+
fake_st = _RecordingStreamlit()
45+
fake_i18n = types.ModuleType("i18n")
46+
fake_i18n.t = lambda key: key # type: ignore[attr-defined]
47+
fake_output = types.ModuleType("components.output")
48+
fake_output.confidence_label = lambda confidence: str(confidence) # type: ignore[attr-defined]
49+
50+
for name in [
51+
module_name
52+
for module_name in sys.modules
53+
if module_name == "components" or module_name.startswith("components.")
54+
]:
55+
monkeypatch.delitem(sys.modules, name, raising=False)
56+
monkeypatch.setitem(sys.modules, "streamlit", fake_st)
57+
monkeypatch.setitem(sys.modules, "i18n", fake_i18n)
58+
monkeypatch.setitem(sys.modules, "components.output", fake_output)
59+
monkeypatch.syspath_prepend(str(APP_DIR))
60+
61+
from components import show_working as show_working_mod # type: ignore[import-not-found]
62+
63+
return show_working_mod, fake_st
64+
65+
66+
def _result_with_mixed_trace_tokens() -> SimpleNamespace:
67+
return SimpleNamespace(
68+
trace=[
69+
{"node": "retrieve_context"},
70+
{
71+
"node": "generate_sql",
72+
"model": "codestral-latest",
73+
"input_tokens": 3376,
74+
"output_tokens": 62,
75+
"confidence": 1.0,
76+
},
77+
{
78+
"node": "explain_trace",
79+
"model": "codestral-latest",
80+
"input_tokens": 169,
81+
"output_tokens": 12,
82+
},
83+
],
84+
confidence=1.0,
85+
repair_attempted=False,
86+
db_id="chinook",
87+
outcome=None,
88+
rationale="",
89+
error_kind=None,
90+
)
91+
92+
93+
def test_trace_dataframe_is_arrow_serializable(show_working_module: Any) -> None:
94+
show_working_mod, fake_st = show_working_module
95+
96+
show_working_mod.render_show_working(_result_with_mixed_trace_tokens())
97+
98+
assert len(fake_st.dataframes) == 1
99+
pa.Table.from_pandas(fake_st.dataframes[0], preserve_index=False)
100+
101+
102+
def test_trace_dataframe_uses_current_streamlit_width_api(
103+
show_working_module: Any,
104+
) -> None:
105+
show_working_mod, fake_st = show_working_module
106+
107+
show_working_mod.render_show_working(_result_with_mixed_trace_tokens())
108+
109+
assert fake_st.dataframe_kwargs == [{"width": "stretch", "hide_index": True}]

0 commit comments

Comments
 (0)