feat(langfuse): 목록 한 줄 = 채팅(질문/답/토큰), 트리 = OpenCode 도구 호출(SAP 조회·위키 read·grep) 순서대로
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
07d733ea30
commit
c9cc6b7eeb
@@ -78,7 +78,10 @@ async def test_finalize_sends_user_trace(lf_server, django_user_model, monkeypat
|
||||
from common.opencode_service import opencode_service
|
||||
|
||||
async def _msgs(_sid):
|
||||
return [{"info": {"role": "assistant", "tokens": {"input": 3, "output": 4, "reasoning": 1}, "time": {"created": 1000, "completed": 1500}}, "parts": [{"type": "text", "text": "답"}]}]
|
||||
tool = {"type": "tool", "tool": "sap-icf_get_program_source", "state": {"status": "completed", "input": {"program_name": "ZTEST"}, "output": "REPORT ztest.", "title": "ZTEST", "time": {"start": 1100, "end": 1300}}}
|
||||
bad = {"type": "tool", "tool": "read", "state": {"status": "error", "input": {"filePath": "x"}, "error": "no such file", "time": {"start": 1300, "end": 1310}}}
|
||||
return [{"info": {"role": "assistant"}, "parts": [tool, bad]},
|
||||
{"info": {"role": "assistant", "tokens": {"input": 3, "output": 4, "reasoning": 1}, "time": {"created": 1000, "completed": 1500}}, "parts": [{"type": "text", "text": "답"}]}]
|
||||
|
||||
async def _sess(_sid):
|
||||
return {"title": "MARA 조회"}
|
||||
@@ -92,10 +95,15 @@ async def test_finalize_sends_user_trace(lf_server, django_user_model, monkeypat
|
||||
await asyncio.gather(*list(langfuse._pending))
|
||||
assert len(lf_server) == 1
|
||||
spans = lf_server[0]["body"]["resourceSpans"][0]["scopeSpans"][0]["spans"]
|
||||
t, g = _attrs(spans[0]), _attrs(spans[1])
|
||||
assert [sp["name"] for sp in spans] == ["chat", "sap-icf_get_program_source", "read"]
|
||||
t = _attrs(spans[0])
|
||||
assert t["langfuse.user.id"] == "u@x.com" and t["langfuse.session.id"] == "ses_1"
|
||||
assert t["langfuse.trace.input"] == "질문" and t["langfuse.trace.output"] == "답"
|
||||
assert spans[1]["parentSpanId"] == spans[0]["spanId"]
|
||||
assert json.loads(g["langfuse.observation.usage_details"]) == {"input": 3, "output": 5, "total": 8}
|
||||
assert g["langfuse.observation.level"] == "DEFAULT" and spans[1]["status"]["code"] == 1
|
||||
assert t["langfuse.observation.type"] == "generation" # 루트가 곧 답변 — 토큰은 여기
|
||||
assert json.loads(t["langfuse.observation.usage_details"]) == {"input": 3, "output": 5, "total": 8}
|
||||
a1, a2 = _attrs(spans[1]), _attrs(spans[2])
|
||||
assert spans[1]["parentSpanId"] == spans[0]["spanId"] and a1["langfuse.observation.type"] == "tool"
|
||||
assert json.loads(a1["langfuse.observation.input"]) == {"program_name": "ZTEST"} and a1["langfuse.observation.output"] == "REPORT ztest."
|
||||
assert spans[1]["startTimeUnixNano"] == "1100000000" and spans[1]["endTimeUnixNano"] == "1300000000"
|
||||
assert spans[2]["status"] == {"code": 2, "message": "no such file"} and a2["langfuse.observation.level"] == "ERROR"
|
||||
assert stream_mod is not None
|
||||
|
||||
Reference in New Issue
Block a user