Log the 2026-08-24 session: F3 fix live, audit filled, corpus re-ingest scoped

This commit is contained in:
2026-08-24 15:07:30 +07:00
parent f3eaab0948
commit 33b16c885b
7 changed files with 575 additions and 11 deletions
+15 -2
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
import json
import uuid
from typing import Annotated, Any, Literal, Protocol
@@ -161,6 +162,18 @@ def _section_retriever(request: Request) -> SectionListRetriever:
router = APIRouter(prefix="/v1/rag", tags=["rag"])
def _json_attr(text: str) -> str:
"""Langfuse expects `observation.input`/`output` as a JSON string.
Passing raw text silently maps to nothing: verified live 2026-08-21, the
span carried the attribute and Langfuse showed empty input/output columns
while `langfuse.session.id` -- a plain string by contract -- mapped fine
from the same annotate call. No error anywhere; the field simply stays
blank, which is the failure mode worth remembering.
"""
return json.dumps(text, ensure_ascii=False)
def _clip(text: str | None, limit: int = 2000) -> str:
"""Bounded text for a span attribute.
@@ -686,8 +699,8 @@ def query_rag(
# exposure is bounded -- but it is a change, not an oversight, and
# the text is truncated rather than unbounded.
"langfuse.trace.name": f"rag.{decision}",
"langfuse.observation.input": _clip(payload.query),
"langfuse.observation.output": _clip(answer),
"langfuse.observation.input": _json_attr(_clip(payload.query)),
"langfuse.observation.output": _json_attr(_clip(answer)),
"langfuse.trace.metadata.decision": decision,
"langfuse.trace.metadata.reason": reason,
"langfuse.trace.metadata.resolved_drug_id": resolved_drug_id or "",