From b5755e166fdef6862ac7178e0ccf717d2f1fe592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Tue, 7 Jul 2026 16:07:44 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=92=D0=9C=203060=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- вм3060.md | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 вм3060.md diff --git a/вм3060.md b/вм3060.md new file mode 100644 index 0000000..e511b71 --- /dev/null +++ b/вм3060.md @@ -0,0 +1,140 @@ +Список задач обновлен + +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 [](file:///home/naeel/.vscode-server/data/User/workspaceStorage/dc98ff3e658364e1826ee6585ebe4b5e/GitHub.copilot-chat/chat-session-resources/585b2f71-2acd-4452-9f61-eaaee2b850b9/toolu_vrtx_01WbGYNKNZbQkMB6hWcU9ugU__vscode-1782796726482/content.txt#1-1), 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 [](file:///home/naeel/.vscode-server/data/User/workspaceStorage/dc98ff3e658364e1826ee6585ebe4b5e/GitHub.copilot-chat/chat-session-resources/585b2f71-2acd-4452-9f61-eaaee2b850b9/toolu_vrtx_01ENsoQybksEi4HVM2uiznPZ__vscode-1782796726484/content.txt#1-1), lines 1 to 350 + +Теперь у меня всё что нужно. Читал реальный код, а не только описание. + +--- + +## Вердикт + +`rag_pkg/` — **нормальный, читаемый v2**, но в одном месте есть критический баг производительности, плюс пачка структурных проблем. + +--- + +## Что не так (по реальному коду) + +### 🔴 Критично + +**1. ChromaDB открывается на каждый запрос** +```python +# search.py — строка внутри search_all(): +client = chromadb.PersistentClient(path=CHROMA_DIR) +``` +Это открывает 6.7 GB SQLite-файл при каждом HTTP-запросе. Правильно — создать клиент один раз при старте и держать как синглтон. + +**2. DeepSeek вызывается ДО кэша** +```python +# api.py _process(): +question_en, question_ru = normalize(question_raw) # ← внешний API +cached = cache_get(question_ru) # ← только потом кэш +``` +Каждый запрос, даже закэшированный, делает платный HTTP-запрос к DeepSeek. Порядок должен быть обратный: кэш → нормализация только если промах. + +**3. API ключ в коде** +```python +# config.py +DEEPSEEK_KEY = "sk-78ec529c1eba4ba69995091046c9fa33" +``` +Hardcoded секрет. Нужен `os.environ.get("DEEPSEEK_KEY")`. + +**4. Двойной LLM-запрос при истории** +```python +# 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 строки) +```python +_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 строк изменений, которые уберут самые дорогие проблемы. \ No newline at end of file