Add Langfuse as a self-hosted eval and trace viewer
This commit is contained in:
@@ -22,6 +22,11 @@ class RetrievalTrace:
|
||||
otel_trace_id: str | None = None
|
||||
conversation_id: str | None = None
|
||||
created_at: datetime | None = None
|
||||
# The full assistant turn (answer text, blocks, plan, ...) — see
|
||||
# `PostgresTraceRepository.save`'s `response_payload` param. None for
|
||||
# rows persisted before that column existed, or when persistence raced
|
||||
# a legacy caller that never passed it.
|
||||
response_payload: dict[str, Any] | None = None
|
||||
|
||||
|
||||
class FeedbackTraceNotFound(LookupError):
|
||||
@@ -65,6 +70,7 @@ class PostgresTraceRepository:
|
||||
correlation_id: str | None = None,
|
||||
otel_trace_id: str | None = None,
|
||||
conversation_id: str | None = None,
|
||||
response_payload: dict[str, Any] | None = None,
|
||||
) -> str:
|
||||
import psycopg
|
||||
|
||||
@@ -75,13 +81,17 @@ class PostgresTraceRepository:
|
||||
INSERT INTO rag_retrieval_trace (
|
||||
trace_id, query_text, subject_scope, query_intent,
|
||||
decision, reason, resolved_drug_id, citations,
|
||||
correlation_id, otel_trace_id, conversation_id
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s::jsonb, %s, %s, %s)
|
||||
correlation_id, otel_trace_id, conversation_id,
|
||||
response_payload
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s::jsonb, %s, %s, %s, %s::jsonb)
|
||||
""",
|
||||
(
|
||||
trace_id, query, subject_scope, intent, decision, reason,
|
||||
resolved_drug_id, json.dumps(citations, ensure_ascii=False),
|
||||
correlation_id, otel_trace_id, conversation_id,
|
||||
json.dumps(response_payload, ensure_ascii=False)
|
||||
if response_payload is not None
|
||||
else None,
|
||||
),
|
||||
)
|
||||
return trace_id
|
||||
@@ -94,7 +104,8 @@ class PostgresTraceRepository:
|
||||
"""
|
||||
SELECT trace_id::text, query_text, subject_scope, query_intent,
|
||||
decision, reason, resolved_drug_id, citations,
|
||||
correlation_id, otel_trace_id, conversation_id, created_at
|
||||
correlation_id, otel_trace_id, conversation_id, created_at,
|
||||
response_payload
|
||||
FROM rag_retrieval_trace WHERE trace_id = %s
|
||||
""",
|
||||
(trace_id,),
|
||||
@@ -105,7 +116,7 @@ class PostgresTraceRepository:
|
||||
trace_id=row[0], query=row[1], subject_scope=row[2], intent=row[3],
|
||||
decision=row[4], reason=row[5], resolved_drug_id=row[6],
|
||||
citations=tuple(row[7]), correlation_id=row[8], otel_trace_id=row[9],
|
||||
conversation_id=row[10], created_at=row[11],
|
||||
conversation_id=row[10], created_at=row[11], response_payload=row[12],
|
||||
)
|
||||
|
||||
def list_by_conversation(
|
||||
@@ -115,10 +126,11 @@ class PostgresTraceRepository:
|
||||
cứu), most recent first. Scoped to `conversation_id` on purpose:
|
||||
this system has no auth anywhere (`apps/api-gateway`/`auth-service`
|
||||
are unbuilt — see README), so an unscoped listing would mix every
|
||||
browser's/user's queries together. Citations/answer text are NOT
|
||||
persisted here (only decision/reason/resolved_drug_id) — a history
|
||||
entry is for re-running the same query, not replaying its old
|
||||
answer verbatim.
|
||||
browser's/user's queries together. Each row's full replayable
|
||||
answer, when one was persisted, rides along in `response_payload` —
|
||||
see `routers/rag.py`'s `/transcript` endpoint, which is what turns
|
||||
this into an actual resumable conversation rather than just a
|
||||
re-run-the-query shortcut.
|
||||
"""
|
||||
import psycopg
|
||||
|
||||
@@ -127,7 +139,8 @@ class PostgresTraceRepository:
|
||||
"""
|
||||
SELECT trace_id::text, query_text, subject_scope, query_intent,
|
||||
decision, reason, resolved_drug_id, citations,
|
||||
correlation_id, otel_trace_id, conversation_id, created_at
|
||||
correlation_id, otel_trace_id, conversation_id, created_at,
|
||||
response_payload
|
||||
FROM rag_retrieval_trace
|
||||
WHERE conversation_id = %s
|
||||
ORDER BY created_at DESC
|
||||
@@ -140,7 +153,7 @@ class PostgresTraceRepository:
|
||||
trace_id=row[0], query=row[1], subject_scope=row[2], intent=row[3],
|
||||
decision=row[4], reason=row[5], resolved_drug_id=row[6],
|
||||
citations=tuple(row[7]), correlation_id=row[8], otel_trace_id=row[9],
|
||||
conversation_id=row[10], created_at=row[11],
|
||||
conversation_id=row[10], created_at=row[11], response_payload=row[12],
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user