feat(ai): integrate local Ollama AI for in-context sentence translation and caching (Task 13)

This commit is contained in:
2026-10-06 15:05:24 +03:00
parent 0c5951df8d
commit 37a1f1ab35
12 changed files with 605 additions and 15 deletions
+36
View File
@@ -29,6 +29,8 @@ from app.dictionary import lookup_term, USER_AGENT, close_http_client
from app.export import export_csv, export_json, export_anki_tsv, export_markdown
from app.srs import calculate_sm2, generate_quiz_options, build_activity_heatmap, calculate_cefr_level
from app.reader import parse_epub, parse_text, parse_pdf, count_words
from app.ai import translate_sentence_ai, get_ollama_status
@asynccontextmanager
@@ -153,6 +155,12 @@ class BookProgressRequest(BaseModel):
position: Optional[float] = None
class SentenceTranslateRequest(BaseModel):
sentence: str = Field(..., min_length=1)
target_word: Optional[str] = ""
# ---------------------------------------------------------------------------
# PWA Static Endpoints
# ---------------------------------------------------------------------------
@@ -321,6 +329,34 @@ async def api_audio_proxy():
return Response(status_code=204)
# ---------------------------------------------------------------------------
# Local AI Sentence Translation & In-Context Word Lookup
# ---------------------------------------------------------------------------
@app.post("/api/translate-sentence")
async def api_translate_sentence(
req: SentenceTranslateRequest,
user: dict = Depends(require_user)
):
"""
Translates a sentence using local AI with in-context meaning of the target word.
Uses SQLite sentence_translations cache for sub-millisecond retrieval on repeat queries.
"""
clean_s = req.sentence.strip()
if not clean_s:
raise HTTPException(status_code=400, detail="Sentence cannot be empty")
return await translate_sentence_ai(clean_s, req.target_word or "")
@app.get("/api/ai/status")
async def api_ai_status(user: dict = Depends(require_user)):
"""
Returns local AI status and available models.
"""
return await get_ollama_status()
# ---------------------------------------------------------------------------
# Collections
# ---------------------------------------------------------------------------