Phase 23: WebUI separation — api.py + youlbot-webui project
- api.py: /chat SSE done event now includes run_id for feedback linking
(format: data: {"__done": true, "run_id": "uuid"})
- api.py: Add POST /feedback endpoint with LangSmith integration
- ROADMAP.md: Add Phase 23 documentation
Note: youlbot-webui/ created at /Users/sal/workspace/youlbot-webui/
(separate project, tracked independently)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,12 @@
|
||||
json={"message": "안녕", "user_id": "홍길동"},
|
||||
headers=headers, timeout=120) as r:
|
||||
for line in r.iter_lines():
|
||||
if line.startswith("data: ") and line != "data: [DONE]":
|
||||
print(json.loads(line[6:]), end="", flush=True)
|
||||
if not line.startswith("data: "):
|
||||
continue
|
||||
payload = json.loads(line[6:])
|
||||
if isinstance(payload, dict) and payload.get("__done"):
|
||||
break # run_id = payload["run_id"]
|
||||
print(payload, end="", flush=True)
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
@@ -72,6 +76,14 @@ class ChatRequest(BaseModel):
|
||||
show_thinking: bool = False
|
||||
|
||||
|
||||
class FeedbackRequest(BaseModel):
|
||||
user_id: str = "default"
|
||||
user_msg: str
|
||||
asst_msg: str
|
||||
rating: int
|
||||
run_id: str | None = None
|
||||
|
||||
|
||||
# ── 엔드포인트 ────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -88,11 +100,26 @@ async def chat(req: ChatRequest, _=Depends(_auth)):
|
||||
async def generate():
|
||||
async for token in agent.stream_response(req.message, show_thinking=req.show_thinking):
|
||||
yield f"data: {json.dumps(token, ensure_ascii=False)}\n\n"
|
||||
yield "data: [DONE]\n\n"
|
||||
yield f"data: {json.dumps({'__done': True, 'run_id': agent.last_run_id}, ensure_ascii=False)}\n\n"
|
||||
|
||||
return StreamingResponse(generate(), media_type="text/event-stream")
|
||||
|
||||
|
||||
@app.post("/feedback")
|
||||
async def save_feedback(req: FeedbackRequest, _=Depends(_auth)):
|
||||
"""👍/👎 피드백 저장. LangSmith 트레이싱 활성화 시 자동 연동."""
|
||||
_container.feedback_repository().save_feedback(
|
||||
req.user_id, req.user_msg, req.asst_msg, req.rating, req.run_id
|
||||
)
|
||||
if req.run_id and os.getenv("LANGCHAIN_TRACING_V2") == "true":
|
||||
try:
|
||||
from langsmith import Client
|
||||
Client().create_feedback(run_id=req.run_id, key="user_feedback", score=req.rating)
|
||||
except Exception:
|
||||
pass
|
||||
return {"saved": True}
|
||||
|
||||
|
||||
@app.post("/reset")
|
||||
async def reset(user_id: str = "default", _=Depends(_auth)):
|
||||
"""대화 이력 초기화."""
|
||||
|
||||
Reference in New Issue
Block a user