- /api/ai/ask: the stub answer is reachable only under DEBUG or RAG_FORCE_MOCK. Without RAG keys on the server it used to return 200 with "this is a stub, set OPENAI_API_KEY" and spend the student's quota; now 503. - /api/home: the `grade` alias is gone and sending it is a 400 instead of a silent fallback to the user's own grade. No client sent it. - activate_subscription logs ERROR when the paid order's plan no longer exists (it silently became 30 days). - resolve_grade_title logs instead of `except: pass`; curriculum_io no longer reads an `intro_text` key no file contains. - CLAUDE.md: "No silent fallbacks" rules for future agents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.6 KiB
Python
59 lines
2.6 KiB
Python
"""
|
|
تنظیماتِ RAG و همخوانیِ نامِ collection با دادهٔ موجودِ تیمِ دیگر.
|
|
|
|
در Rag_backend نامِ collection اینطور ساخته میشه:
|
|
f"{subject.name} {subject.grade.title}".lower()
|
|
قالبِ نام و نگاشتِ گرید از settings قابلِ تنظیمان چون اسمِ دقیقِ گرید حساسه
|
|
(کاربر قبلاً با اسمِ نادرست به مشکل خورده بود). کلیدِ فیلترِ درس/فصل خودکار
|
|
از روی subject انتخاب میشه — نگاه کنید به rag/services/known_collections.py.
|
|
"""
|
|
import logging
|
|
|
|
from django.conf import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def rag_is_configured() -> bool:
|
|
return bool(
|
|
settings.OPENAI_API_KEY
|
|
and settings.QDRANT_API_KEY
|
|
and not settings.RAG_FORCE_MOCK
|
|
)
|
|
|
|
|
|
def resolve_grade_title(grade_id, fallback: str = '') -> str:
|
|
"""
|
|
gradeId → عنوانِ گرید همانطور که در نامِ collectionِ تیمِ دیگه اومده.
|
|
|
|
⚠️ عنوانِ Grade در دیتابیسِ ما «پایه نهم» است ولی نامِ collection «ریاضی
|
|
نهم»؛ بدونِ نرمالسازی، build_collection_name رشتهی «ریاضی پایه نهم» را
|
|
میساخت که وجود ندارد و کلِ retrieval از مسیرِ gradeId بیسروصدا خالی
|
|
برمیگشت. مسیرِ lessonId خودش نرمال میکرد، این یکی نه.
|
|
"""
|
|
overrides = getattr(settings, 'RAG_GRADE_TITLE_OVERRIDES', {}) or {}
|
|
if grade_id in overrides:
|
|
return str(overrides[grade_id])
|
|
if grade_id is not None:
|
|
try:
|
|
from content.models import Grade
|
|
|
|
from .lesson_context import normalize_grade_title
|
|
|
|
grade = Grade.objects.filter(pk=grade_id).only('title').first()
|
|
if grade is not None:
|
|
return normalize_grade_title(grade.title)
|
|
except Exception: # noqa: BLE001
|
|
# پیشتر `pass` بود: خطای دیتابیس retrieval را بیصدا خالی میکرد.
|
|
logger.exception('resolve_grade_title: خواندنِ پایهی %s شکست خورد', grade_id)
|
|
return fallback
|
|
|
|
|
|
def build_collection_name(subject: str, grade_title: str) -> str:
|
|
template = getattr(settings, 'RAG_COLLECTION_NAME_TEMPLATE', '{subject} {grade}')
|
|
return template.format(subject=(subject or '').strip(), grade=(grade_title or '').strip()).lower()
|
|
|
|
|
|
def retrieval_top_k() -> int:
|
|
return int(getattr(settings, 'RAG_RETRIEVAL_TOP_K', 4))
|