Files
2026-07-07 16:07:44 +04:00

8.4 KiB
Raw Permalink Blame History

Список задач обновлен

Ran terminal command: ssh -i ~/.ssh/id_ed25519 -o ConnectTimeout=10 -o BatchMode=yes naeel@192.168.1.49 'ls -la /home/naeel/nubes/ 2>/dev/null || ls -la /home/naeel/ | head -40'

Ran terminal command: ssh -i ~/.ssh/id_ed25519 -o ConnectTimeout=10 -o BatchMode=yes naeel@192.168.1.49 'echo "=== rag_pkg ===" && ls -la /home/naeel/nubes/rag_pkg/ && ls -la /home/naeel/nubes/rag_pkg/*/ 2>/dev/null && echo "=== rag dir ===" && ls -la /home/naeel/nubes/rag/ && echo "=== chroma_db ===" && ls -la /home/naeel/nubes/chroma_db/ && du -sh /home/naeel/nubes/chroma_db/ && echo "=== data ===" && ls -la /home/naeel/nubes/data/ && echo "=== LLM-UI ===" && ls -la /home/naeel/nubes/LLM-UI/'

Ran terminal command: ssh -i ~/.ssh/id_ed25519 -o ConnectTimeout=10 -o BatchMode=yes naeel@192.168.1.49 'echo "=== server.py ===" && cat /home/naeel/nubes/server.py && echo "=== rag_pkg/config.py ===" && cat /home/naeel/nubes/rag_pkg/config.py && echo "=== rag_pkg/__init_.py ===" && cat /home/naeel/nubes/rag_pkg/__init_.py && echo "=== rag_pkg/server.py ===" && cat /home/naeel/nubes/rag_pkg/server.py'

Ran terminal command: ssh -i ~/.ssh/id_ed25519 -o ConnectTimeout=10 -o BatchMode=yes naeel@192.168.1.49 'echo "=== rag_pkg/search.py ===" && cat /home/naeel/nubes/rag_pkg/search.py && echo "=== rag_pkg/llm.py ===" && cat /home/naeel/nubes/rag_pkg/llm.py && echo "=== rag_pkg/normalize.py ===" && cat /home/naeel/nubes/rag_pkg/normalize.py'

Read , lines 1 to 300

Ran terminal command: ssh -i ~/.ssh/id_ed25519 -o ConnectTimeout=10 -o BatchMode=yes naeel@192.168.1.49 'echo "=== rag_pkg/api.py ===" && cat /home/naeel/nubes/rag_pkg/api.py && echo "=== rag_pkg/cache.py ===" && cat /home/naeel/nubes/rag_pkg/cache.py'

Read , lines 1 to 350

Теперь у меня всё что нужно. Читал реальный код, а не только описание.


Вердикт

rag_pkg/нормальный, читаемый v2, но в одном месте есть критический баг производительности, плюс пачка структурных проблем.


Что не так (по реальному коду)

🔴 Критично

1. ChromaDB открывается на каждый запрос

# search.py — строка внутри search_all():
client = chromadb.PersistentClient(path=CHROMA_DIR)

Это открывает 6.7 GB SQLite-файл при каждом HTTP-запросе. Правильно — создать клиент один раз при старте и держать как синглтон.

2. DeepSeek вызывается ДО кэша

# api.py _process():
question_en, question_ru = normalize(question_raw)  # ← внешний API
cached = cache_get(question_ru)                      # ← только потом кэш

Каждый запрос, даже закэшированный, делает платный HTTP-запрос к DeepSeek. Порядок должен быть обратный: кэш → нормализация только если промах.

3. API ключ в коде

# config.py
DEEPSEEK_KEY = "sk-78ec529c1eba4ba69995091046c9fa33"

Hardcoded секрет. Нужен os.environ.get("DEEPSEEK_KEY").

4. Двойной LLM-запрос при истории

# api.py: если есть история — ask_qwen вызывается ДВАЖДЫ
answer = ask_qwen(context, question_en)        # первый
...
answer = ask_qwen(f"{context}\n\nPrevious...", question_en)  # второй

Первый вызов — выброшенные деньги GPU.

🟡 Важно

5. Однопоточный HTTP-сервер BaseHTTPRequestHandler — один запрос за раз. Qwen отвечает ~5-10 секунд. Два пользователя — второй ждёт пока не ответит первый.

6. 5 UUID-папок при 3 коллекциях

chroma_db/
  4d714608-...   ← ?
  c9642ebb-...   ← ?
  d75d10f2-...   ← ?
  e523b5de-...   ← ?
  eb89df10-...   ← ?

Пять директорий, три коллекции. Старые удалённые коллекции остались на диске, раздувают SQLite.

7. Нет супервизора для llama.cpp Два сервера на портах 8080/8081 — запущены руками, нет автоперезапуска. Упал — никто не знает.

8. Старые файлы в корне засоряют пространство rag_ingest*.py × 6, patch_*.py × 7, fix_*.py, trans_*.py, .bak × 2 — это история разработки, которая лежит в продакшн-директории.


Что хорошо

  • rag_pkg/ — чистая структура: config / normalize / search / llm / cache / api — каждый модуль делает одно
  • Комментарии ПОЧЕМУ в каждом модуле — редкость, реально помогает
  • Билингвальный поиск — правильное архитектурное решение, хорошо обоснованное
  • Кэш по нормализованному ключу — умно, разные формулировки → один кэш-хит
  • Fallback на DeepSeek — разумная деградация без краша
  • История диалога на клиенте — для single-user сервиса это правильно, не засоряет серверную память

Куда двигаться (конкретно)

1. Вынести ChromaDB в синглтон (search.py, 3 строки)

_client = chromadb.PersistentClient(path=CHROMA_DIR)  # модульный уровень

2. Поменять порядок в _process() — кэш первым, нормализация только при промахе. Сэкономит деньги и ~500мс на каждом повторном запросе.

3. Убрать секрет из кодаDEEPSEEK_KEY = os.environ.get("DEEPSEEK_KEY", ""), запуск через .env или systemd Environment=.

4. Сделать systemd-юниты для llama.cpp :8080 и :8081 + самого server.py. Три .service файла — и сервис переживает ребут и падения.

5. Убрать дублирующий LLM-вызов — передавать историю в первый ask_qwen, а не делать два запроса.


Если делать с нуля — как?

Стек тот же (llama.cpp + ChromaDB), но структура иная:

rag/
  config.py          ← env-переменные, без секретов
  db.py              ← ChromaDB синглтон + функции поиска
  llm.py             ← Qwen + DeepSeek fallback
  normalize.py       ← нормализация
  cache.py           ← SQLite кэш
  pipeline.py        ← оркестратор: normalize→cache→search→llm
  api.py             ← FastAPI (или хотя бы ThreadingHTTPServer)
  ingest/
    elsa.py
    vwts.py
    kia.py
    base.py          ← общая логика чанкинга/эмбеддинга
systemd/
  llama-embed.service
  llama-qwen.service
  rag-api.service

LangChain/LlamaIndex — не нужны. Для этой задачи они добавят 300MB зависимостей и абстракций поверх того что уже хорошо работает. Велосипед здесь оправдан — он понятный и контролируемый.

Главное что реально нужно сделать сейчас — исправления 1-2-3-5 выше. Это ~20 строк изменений, которые уберут самые дорогие проблемы.