From f520aba397e0ad3ed3d7cd713b01376264337138 Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Mon, 16 Mar 2026 14:03:25 +0000 Subject: [PATCH] Fix KB distillation fallback and SpecVersion type annotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - knowledge_base_service.py: wrap Gemini distillation call in try/except to fall back to fallback_client/fallback_model if primary times out, matching the fallback behaviour in GeminiService._generate_content() - models.py: fix SpecVersion.source_document_ids ORM type annotation from Mapped[Optional[dict]] to Mapped[Optional[list]] — the field stores a JSON array of document ID strings, not an object Co-Authored-By: Claude Sonnet 4.6 --- backend/app/models/models.py | 2 +- backend/app/services/knowledge_base_service.py | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/app/models/models.py b/backend/app/models/models.py index 4511eb5..f71a237 100755 --- a/backend/app/models/models.py +++ b/backend/app/models/models.py @@ -261,7 +261,7 @@ class SpecVersion(Base): ) version_number: Mapped[int] = mapped_column(Integer, nullable=False) content: Mapped[str] = mapped_column(Text, nullable=False) - source_document_ids: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) + source_document_ids: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True) generated_by_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True) generated_by_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) processing_job_id: Mapped[Optional[uuid.UUID]] = mapped_column( diff --git a/backend/app/services/knowledge_base_service.py b/backend/app/services/knowledge_base_service.py index bfcabaa..7863184 100644 --- a/backend/app/services/knowledge_base_service.py +++ b/backend/app/services/knowledge_base_service.py @@ -292,10 +292,17 @@ class KnowledgeBaseService: prompt = prompt_template.format(combined_markdown=combined_markdown) logger.info(f"[KB_SERVICE] Sending {len(combined_markdown)} chars to Gemini for distillation") - response = await self.gemini.primary_client.aio.models.generate_content( - model=self.gemini.model, - contents=prompt, - ) + try: + response = await self.gemini.primary_client.aio.models.generate_content( + model=self.gemini.model, + contents=prompt, + ) + except Exception as e: + logger.warning(f"[KB_SERVICE] Primary model failed: {e}. Retrying with fallback.") + response = await self.gemini.fallback_client.aio.models.generate_content( + model=self.gemini.fallback_model, + contents=prompt, + ) spec_content = response.text.strip() logger.info(f"[KB_SERVICE] Distillation complete: {len(spec_content)} chars")