8.4 KiB
Список задач обновлен
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'
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'
Теперь у меня всё что нужно. Читал реальный код, а не только описание.
Вердикт
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 строк изменений, которые уберут самые дорогие проблемы.