59014f6fe7
Full implementations replacing stubs: speakers CRUD with utterance count, rooms list + mute/unmute via pipeline, FTS5-based search, RAG /ask and /summary endpoints. 15 route tests (8 new) all passing; 35 total. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
import sqlite3
|
|
import httpx
|
|
from typing import Optional
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
from app.shared.config import Settings
|
|
|
|
|
|
class AskRequest(BaseModel):
|
|
question: str
|
|
date: Optional[str] = None
|
|
|
|
|
|
def make_router(settings: Settings, db_factory):
|
|
router = APIRouter(prefix="/api")
|
|
|
|
@router.post("/ask")
|
|
def ask(body: AskRequest):
|
|
db: sqlite3.Connection = db_factory()
|
|
rows = db.execute("""
|
|
SELECT u.start_time, u.transcript, r.name as room_name, s.name as speaker_name
|
|
FROM utterances u
|
|
JOIN rooms r ON u.room_id = r.id
|
|
LEFT JOIN speakers s ON u.speaker_id = s.id
|
|
WHERE date(u.start_time) = date(?)
|
|
ORDER BY u.start_time ASC
|
|
LIMIT 200
|
|
""", (body.date or "now",)).fetchall()
|
|
|
|
context_lines = [
|
|
f"[{r['room_name']} {r['start_time']}] {r['speaker_name'] or 'Unknown'}: {r['transcript']}"
|
|
for r in rows
|
|
]
|
|
context = "\n".join(context_lines) if context_lines else "(no transcripts for this date)"
|
|
|
|
prompt = (
|
|
f"You are a helpful assistant with access to household conversation transcripts.\n\n"
|
|
f"Transcripts:\n{context}\n\n"
|
|
f"Question: {body.question}\n\n"
|
|
f"Answer based only on the transcripts above. Cite the time and room when relevant."
|
|
)
|
|
|
|
resp = httpx.post(
|
|
f"{settings.ollama_url}/api/chat",
|
|
json={
|
|
"model": settings.ollama_model,
|
|
"messages": [{"role": "user", "content": prompt}],
|
|
"stream": False,
|
|
},
|
|
timeout=60.0,
|
|
)
|
|
resp.raise_for_status()
|
|
answer = resp.json()["message"]["content"]
|
|
return {"answer": answer, "context_count": len(rows)}
|
|
|
|
@router.get("/summary/{date}")
|
|
def get_summary(date: str):
|
|
db: sqlite3.Connection = db_factory()
|
|
row = db.execute(
|
|
"SELECT * FROM daily_summaries WHERE date=?", (date,)
|
|
).fetchone()
|
|
if not row:
|
|
raise HTTPException(404, f"No summary for {date}")
|
|
return dict(row)
|
|
|
|
return router
|