From 70910b82d2ff5b62f5170120156c0950be648bfd Mon Sep 17 00:00:00 2001 From: grigo Date: Tue, 16 Jun 2026 10:07:06 +0300 Subject: [PATCH] =?UTF-8?q?fix=20=D0=9A=D0=A4=D0=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/memory/service.py | 24 +++++++++++++++--- backend/app/rag/ingest.py | 28 +++++++++++++-------- backend/app/rag/migrate_memory_to_qdrant.py | 9 ++++++- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/backend/app/memory/service.py b/backend/app/memory/service.py index fc9a9de..61e2149 100644 --- a/backend/app/memory/service.py +++ b/backend/app/memory/service.py @@ -1,5 +1,6 @@ import asyncio import json +import logging import threading from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timezone @@ -20,6 +21,9 @@ DEFAULT_PROFILE: dict[str, Any] = { } +logger = logging.getLogger(__name__) + + class MemoryService: def __init__(self, db: Session, user_id: int): self.db = db @@ -38,10 +42,24 @@ class MemoryService: @staticmethod def _schedule_rag(coro) -> None: def runner() -> None: - asyncio.run(coro) + try: + asyncio.run(coro) + except Exception: + logger.exception("RAG background task failed") threading.Thread(target=runner, daemon=True).start() + @staticmethod + def _rag_fact_payload(fact: MemoryFact) -> dict[str, Any]: + return { + "fact_id": int(fact.id), + "user_id": int(fact.user_id), + "content": fact.content, + "category": fact.category, + "importance": int(fact.importance), + "active": bool(fact.active), + } + def get_profile(self) -> dict[str, Any]: row = self.db.scalar(select(UserProfile).where(UserProfile.user_id == self.user_id).limit(1)) if not row: @@ -114,7 +132,7 @@ class MemoryService: self.db.commit() from app.rag.ingest import index_memory_fact - self._schedule_rag(index_memory_fact(existing)) + self._schedule_rag(index_memory_fact(**self._rag_fact_payload(existing))) result = { "ok": True, "action": "updated", @@ -139,7 +157,7 @@ class MemoryService: self.db.refresh(fact) from app.rag.ingest import index_memory_fact - self._schedule_rag(index_memory_fact(fact)) + self._schedule_rag(index_memory_fact(**self._rag_fact_payload(fact))) result = { "ok": True, "action": "created", diff --git a/backend/app/rag/ingest.py b/backend/app/rag/ingest.py index 451cc14..b79a58e 100644 --- a/backend/app/rag/ingest.py +++ b/backend/app/rag/ingest.py @@ -10,7 +10,7 @@ from sqlalchemy import select from sqlalchemy.orm import Session from app.config import get_settings -from app.db.models import ChatSession, Document, DocumentChunk, MemoryFact +from app.db.models import ChatSession, Document, DocumentChunk from app.rag import embeddings from app.rag.chunker import chunk_text from app.rag.store import ( @@ -22,25 +22,33 @@ from app.rag.store import ( ) -async def index_memory_fact(fact: MemoryFact) -> None: +async def index_memory_fact( + *, + fact_id: int, + user_id: int, + content: str, + category: str, + importance: int, + active: bool = True, +) -> None: settings = get_settings() - if not settings.rag_enabled or not fact.active: + if not settings.rag_enabled or not active: return - vectors = await embeddings.embed_texts([fact.content]) + vectors = await embeddings.embed_texts([content]) if not vectors: return upsert_points( COLLECTION_FACTS, [ qm.PointStruct( - id=int(fact.id), + id=int(fact_id), vector=vectors[0], payload={ - "user_id": fact.user_id, - "fact_id": fact.id, - "category": fact.category, - "content": fact.content, - "importance": fact.importance, + "user_id": user_id, + "fact_id": fact_id, + "category": category, + "content": content, + "importance": importance, }, ) ], diff --git a/backend/app/rag/migrate_memory_to_qdrant.py b/backend/app/rag/migrate_memory_to_qdrant.py index e137d35..dec137f 100644 --- a/backend/app/rag/migrate_memory_to_qdrant.py +++ b/backend/app/rag/migrate_memory_to_qdrant.py @@ -23,7 +23,14 @@ async def main() -> None: try: facts = db.scalars(select(MemoryFact).where(MemoryFact.active.is_(True))).all() for fact in facts: - await index_memory_fact(fact) + await index_memory_fact( + fact_id=int(fact.id), + user_id=int(fact.user_id), + content=fact.content, + category=fact.category, + importance=int(fact.importance), + active=bool(fact.active), + ) summaries = db.scalars(select(SessionSummary)).all() for row in summaries: if row.summary: