MedicalRAG — руководство разработчика¶
Сервис app/services/rag_engine.py реализует класс MedicalRAG: индекс и поиск медицинской базы знаний для AI Medical Assistant.
Репозиторий: https://github.com/valera7623/AI-medical-assistant.
Включение¶
from app.services.rag_engine import is_rag_enabled, rag_mode, get_medical_rag
is_rag_enabled() # RAG_ENABLED and MEDICAL_ASSISTANT_ENABLED
rag_mode() # local | external | hybrid (invalid → local)
Глобальный singleton: get_medical_rag() (потокобезопасная ленивая инициализация).
Режимы¶
RAG_MODE |
Chroma | External POST …/search |
Примечания |
|---|---|---|---|
local |
да | нет | memory fallback, если Chroma недоступна |
external |
пропускается | да | soft-fallback на local при пустом результате |
hybrid |
да | да | merge_hits с RAG_HYBRID_LOCAL_WEIGHT |
Переменные:
| Env | Назначение |
|---|---|
RAG_COLLECTION_NAME |
Имя коллекции |
RAG_EXTERNAL_URL |
База внешнего API (…/v1) |
RAG_EXTERNAL_API_KEY |
Bearer (опционально) |
RAG_EXTERNAL_TIMEOUT_SECONDS |
Таймаут HTTP |
RAG_HYBRID_LOCAL_WEIGHT |
Вес local в hybrid (0–1) |
CHROMA_PERSIST_DIR |
Путь персистентности Chroma |
Фильтр языка¶
Только две дорожки: en и ru.
from app.services.rag_engine import normalize_rag_language, VALID_RAG_LANGUAGES
normalize_rag_language("ru-RU") # → "ru"
normalize_rag_language("en_US") # → "en"
normalize_rag_language(None) # → DEFAULT_LANGUAGE нормализованный к en|ru
Поиск отбрасывает хиты, чей language не совпадает с запрошенным. UI и seed должны проставлять language явно.
Документ в индексе¶
Ожидаемая структура после нормализации:
{
"id": "guidelines:acs-en",
"title": "ACS — initial steps",
"category": "guidelines",
"language": "en",
"text": "...",
"metadata": {
"title": "...",
"category": "guidelines",
"language": "en",
"source_file": "guidelines.json"
}
}
Методы:
upsert_documents(docs) → int— запись в local (и вызов из admin ingest дополнительно шлёт во внешний/ingest);search(query, *, language, limit=5) → list[hit]— нормализованные хиты сsimilarity,source.
Форма hit после _normalize_hit:
{
"text": "...",
"title": "...",
"category": "...",
"language": "en",
"similarity": 0.82,
"source": "local", # local | external | hybrid
"id": "..."
}
Слияние hybrid¶
merge_hits(local, external, limit=5, local_weight=0.5):
- Масштабирует similarity весами local / external.
- Дедуплицирует по
idили хэшу текста. - Сортирует по убыванию similarity.
Unit-тесты: tests/test_rag_engine.py.
Seed¶
Скрипт scripts/seed_medical_knowledge.py:
# В контейнере aima-app
docker compose exec app python scripts/seed_medical_knowledge.py --also-db
docker compose exec app python scripts/seed_medical_knowledge.py \
--from-url http://mock_rag:8090/v1/documents.json \
--api-key "$RAG_EXTERNAL_API_KEY" \
--skip-local-files
Источники:
app/data/medical_knowledge/guidelines.jsonapp/data/medical_knowledge/diseases.jsonapp/data/medical_knowledge/medications.json- опционально JSON dump с
--from-url
Mock external API¶
scripts/mock_rag_server.py и Compose profile mock-rag (контейнер aima-mock-rag):
docker compose --profile mock-rag up -d mock_rag
Эндпоинты: /health, POST /v1/search, POST /v1/ingest, GET /v1/documents.json.
Для app в той же сети: RAG_EXTERNAL_URL=http://mock_rag:8090/v1.
Интеграция с репетитором¶
app/services/ai_tutor.py вызывает MedicalRAG при ответе; маршруты:
| Путь | Назначение |
|---|---|
POST /api/tutor/ask |
Ответ + sources |
POST /api/tutor/knowledge/ingest |
Admin upsert |
GET /api/tutor/knowledge/status |
Конфиг без секретов |
Флаг MEDICAL_ASSISTANT_ENABLED гейтит все learning API (/api/tutor, /api/cases, /api/exam, /api/progress).
Локальный стенд¶
| Сервис | Порт / имя |
|---|---|
| App | http://localhost:8001 (APP_PORT) |
| Redis host | 6380 |
| Контейнеры | aima-* |
| Mock RAG | 8090 (profile mock-rag) |
Расширение¶
- Добавляйте документы с явным
language. - Для нового внешнего KB соблюдайте контракт
/searchи опционально/ingest. - Не коммитьте секреты (
RAG_EXTERNAL_API_KEY) — только.env.example. - После смены
RAG_MODEперезапустите app-контейнер и перезалейте seed при необходимости.