Skip to content

Knowledge base (RAG) — administration

Administrators populate the medical knowledge base used by the AI Tutor. UI: AdminKnowledge base (RAG) at http://localhost:8001/admin (Russian label: База знаний (RAG)).

Roles

Form upload and POST /api/tutor/knowledge/ingest require admin or super_admin. Learning users may call status; the Admin page itself is admin-only.

Prerequisites

MEDICAL_ASSISTANT_ENABLED=true
RAG_ENABLED=true
RAG_COLLECTION_NAME=medical_knowledge
RAG_MODE=local          # local | external | hybrid
RAG_EXTERNAL_URL=       # for external / hybrid
RAG_EXTERNAL_API_KEY=
RAG_EXTERNAL_TIMEOUT_SECONDS=8.0
RAG_HYBRID_LOCAL_WEIGHT=0.5

Local Docker stack: aima-* containers, app on port 8001, Redis on host port 6380.

Admin UI ingest form

  1. Open /admin and find База знаний (RAG) / Knowledge base (RAG).
  2. Switch the EN or RU language tab — the document is stored only in that lane.
  3. Fill in:
  4. Title — short heading;
  5. Category — guidelines / diseases / medications / admin;
  6. Text — full chunk text.
  7. Submit. Success shows upserted (local) and external_upserted (if an external API is configured).

Documents land in the MedicalRAG index and are mirrored to storage/rag_uploads/user_knowledge.json for reseeding / mock.

One lane at a time

Do not mix Russian and English in one document. Create two chunks: one EN, one RU.

Knowledge status

Status loading calls GET /api/tutor/knowledge/status and shows:

Field Meaning
enabled RAG is on
mode local / external / hybrid
collection Chroma collection name
external_configured Whether RAG_EXTERNAL_URL is set
admin_uploads Count of form uploads
admin_uploads_by_language Counts for en / ru
languages Allowed languages: en, ru

RAG_MODE modes

Mode Behavior
local Search Chroma / memory (default)
external POST {RAG_EXTERNAL_URL}/search; soft-fallback to local if empty
hybrid Merge local + external with RAG_HYBRID_LOCAL_WEIGHT

External search contract:

POST …/search
{"query": "troponin", "limit": 3}

 {"results":[{"id","text","title","category","language","similarity"}]}

External ingest (when URL is set): POST …/ingest with {"documents":[…]}.

Seed script

From the app container:

# Local JSON → index (+ optional DB)
docker compose exec app python scripts/seed_medical_knowledge.py --also-db

# ETL from an external dump
docker compose exec app python scripts/seed_medical_knowledge.py \
  --from-url https://kb.example.com/export/documents.json \
  --api-key "$RAG_EXTERNAL_API_KEY" \
  --skip-local-files

Default files: app/data/medical_knowledge/{guidelines,diseases,medications}.json.

Demo mock RAG

For development without a real external KB:

docker compose --profile mock-rag up -d mock_rag
RAG_MODE=external
RAG_EXTERNAL_URL=http://mock_rag:8090/v1
# MOCK_RAG_API_KEY=dev-mock-key
# RAG_EXTERNAL_API_KEY=dev-mock-key

Or on the host:

python scripts/mock_rag_server.py
# RAG_EXTERNAL_URL=http://127.0.0.1:8090/v1

Smoke check:

curl -s http://127.0.0.1:8090/health
curl -s -X POST http://127.0.0.1:8090/v1/search \
  -H 'Content-Type: application/json' \
  -d '{"query":"troponin","limit":3}'

API ingest (scripts / ETL)

curl -s -X POST http://localhost:8001/api/tutor/knowledge/ingest \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [{
      "title": "ACS — initial steps",
      "category": "guidelines",
      "language": "en",
      "text": "Obtain ECG within 10 minutes..."
    }]
  }'

Requires admin roles and RAG enabled. Response: upserted, external_upserted, ids, mode.

Post-deploy checklist

  1. Set MEDICAL_ASSISTANT_ENABLED and RAG_ENABLED to true.
  2. Run the seed script.
  3. Verify status in Admin UI.
  4. Ask a test question on /tutor in EN and RU.
  5. For external/hybrid, confirm mock or prod KB is reachable from the aima-* container network.