docs: ВМ 3060 notes
This commit is contained in:
@@ -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 строк изменений, которые уберут самые дорогие проблемы.
|
||||||
Reference in New Issue
Block a user