11 Commits

Author SHA1 Message Date
4a6b8097f1 update main.py 2025-08-04 21:42:50 +07:00
4c4d2ae635 update readme.md 2025-08-04 13:03:28 +07:00
ec32fadec3 edit git clone repo for models 2025-08-04 13:01:33 +07:00
6ec3b0ed04 edit respond 2025-08-04 12:59:11 +07:00
82b7be53e6 this is work. First prompt 2025-08-04 02:38:23 +00:00
711ad223a5 add vllm 2025-08-04 02:06:07 +00:00
370a11a463 minimal fix 2025-08-03 16:19:10 +00:00
957903d190 revert 5c585544d3
revert add base_llm.py
2025-08-03 18:10:03 +07:00
5c585544d3 add base_llm.py 2025-08-03 18:09:27 +07:00
cd2c2d235d add sample data 2025-08-03 10:46:06 +00:00
fd4eef8e7f Merge pull request 'compilation' (#1) from compilation into main
Reviewed-on: http://192.168.3.3:3030/drholy/llm/pulls/1
2025-08-03 17:10:34 +07:00
24 changed files with 483 additions and 86 deletions

1
.gitignore vendored
View File

@@ -2,7 +2,6 @@
/app/core
/app/data/chroma_db
/app/data/parsed_json/
/app/data/docs/
/app/__pycache__
/models
/cache

View File

@@ -15,6 +15,10 @@ RUN apt-get update && \
wget \
libgl1 \
libglib2.0-0 \
build-essential \
python3.10-dev \
python3.10-distutils \
libpython3-dev gcc g++ make \
&& rm -rf /var/lib/apt/lists/*
# Установка Python 3.10 как основного
@@ -28,7 +32,7 @@ RUN pip install --upgrade pip && \
WORKDIR /app
# Копируем только requirements.txt для кэширования слоя
COPY offline_packages/requirements.txt /app/requirements.txt
COPY requirements.txt /app/requirements.txt
# Установка зависимостей (включая GPU-версии)
RUN pip install --no-cache-dir -r /app/requirements.txt
@@ -37,4 +41,4 @@ RUN pip install --no-cache-dir -r /app/requirements.txt
COPY app /app
# Запуск приложения
CMD ["python", "main.py"]
#CMD ["python", "main.py"]

View File

@@ -207,7 +207,7 @@ df -h
### Клонирование базовой версии Qwen3-4B
```bash
git clone https://huggingface.co/Qwen/Qwen3-4B-Base
git clone https://huggingface.co/Qwen/Qwen3-4B
```
---
@@ -334,7 +334,7 @@ history > history.md
Был успешно выполнен полный цикл:
- Установка Docker и поддержки GPU
- Настройка NVIDIA Container Toolkit
- Загрузка моделей **Qwen3-8B** и **Qwen3-4B-Base**
- Загрузка моделей **Qwen3-4B**
- Развёртывание LLM-приложения через Docker Compose
- Отладка и пересборка контейнера
- Подготовка офлайн-образа для переноса

View File

@@ -1,5 +1,4 @@
import os
from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -10,11 +9,11 @@ class Config(BaseSettings):
PARSED_JSON_PATH: str = os.path.join(BASE_DIR, "data", "parsed_json")
DOCS_CHROMA_PATH: str = os.path.join(BASE_DIR, "data", "chroma_db")
DOCS_COLLECTION_NAME: str = "docs"
MAX_CHUNK_SIZE: int = 512
MAX_CHUNK_SIZE: int = 2048
CHUNK_OVERLAP: int = 50
LM_MODEL_NAME: str = "/models/paraphrase-multilingual-MiniLM-L12-v2"
LM_MODEL_NAME: str = "/models/Qwen3-Embedding-0.6B"
LOCAL_LLM_NAME: str = "/models/Qwen3-4B"
QWEN_MODEL_NAME: str = "qwen3-chat"
QWEN_MODEL_NAME: str = "Qwen3-8B"
settings = Config() # type: ignore

18
app/data/docs/1-1.md Normal file
View File

@@ -0,0 +1,18 @@
### Как определить цели и требования для домашнего сервера**
Перед сборкой сервера чётко сформулируйте, зачем он вам нужен. Это определит выбор железа.
#### **Ключевые параметры:**
- **Оперативная память:** минимум 32 ГБ, желательно до 64 ГБ (с запасом на будущее).
- **Процессор:** 8+ потоков. Приоритет — количество ядер, а не высокая частота.
- **Диски:** минимум 6 слотов для HDD, лучше 8 и более.
- **Габариты:** высота до ~30 см (чтобы влез на полку).
- **Расширяемость:** возможность добавить:
- Видеокарту (для транскодинга видео)
- 10 Гбит сеть
- SATA-контроллер
- **Энергопотребление:** не более 100150 Вт под нагрузкой.
- **Тишина:** не должен шуметь как пылесос.
- **Бюджет:** до 50 000 ₽ (с учётом продажи старого оборудования).
> ✅ **Итог:** Вы получите чёткий список требований, по которому можно выбирать комплектующие.

40
app/data/docs/1-2.md Normal file
View File

@@ -0,0 +1,40 @@
### Подбор комплектующих для домашнего сервера**
На основе требований выберите совместимые и эффективные компоненты.
#### **1. Корпус — Fractal Design Node 804**
- Поддерживает до 8 дисков (6×3.5" + 2×2.5").
- Удобные салазки для HDD.
- Совет: ставьте корпус боком (дисками наружу) — легче менять диски.
#### **2. Материнская плата — ASRock X470D4U**
- Сокет AM4, поддержка до 128 ГБ RAM.
- 8 SATA-портов — не нужен дополнительный контроллер.
- 2× гигабитных LAN, IPMI, встроенная графика.
- Минусы: только 4 USB-порта, M.2 работает на PCIe 3.0 x2.
#### **3. Процессор — AMD Ryzen 7 3700 (8 ядер / 16 потоков)**
- Энергоэффективный (~65 Вт).
- Поддерживается материнкой без проблем (в отличие от R7 1700).
#### **4. Охлаждение — DeepCool GAMMAXX 300**
- Достаточно для R7 3700.
- Тихий, дешёвый, эффективный.
#### **5. Оперативная память — 32 ГБ (2×16 ГБ DDR4 2666 MHz)**
- UDIMM — совместима с ASRock X470D4U.
- Без ECC (экономия), но можно апгрейдить до 64+ ГБ.
#### **6. Блок питания — be quiet! Pure Power 11, 400500 Вт**
- Расчёт: ~100 Вт (CPU) + 80 Вт (HDD) + 100 Вт (материнка, SSD) + запас = 400 Вт хватит.
#### **7. Диски — 33 ТБ (перенос со старого сервера)**
- HDD: 8×2, 6×1, 5×1, 3×2 ТБ.
- SSD: 2×12 ТБ — под кэш, Docker, VM.
#### **8. Дополнительно (по мере необходимости)**
- SATA-контроллер в M.2 (чтобы не тратить PCI-E слот).
- Видеокарта (позже, для транскодинга).
- 10 Гбит сеть — не сейчас.
> ✅ **Итог:** Вы собрали список проверенных и совместимых комплектующих с учётом будущего апгрейда.

21
app/data/docs/1-3.md Normal file
View File

@@ -0,0 +1,21 @@
### Сборка сервера — пошагово**
Соберите сервер, не повредив компоненты.
#### **Шаги:**
1. **Установите материнскую плату** в корпус.
2. **Вставьте CPU** в сокет, закройте фиксатор.
3. **Нанесите термопасту**, установите кулер.
4. **Установите RAM** в слоты (2×16 ГБ).
5. **Подключите питание**:
- 24-pin от БП к материнке.
- 8-pin CPU к материнке.
6. **Установите диски** в салазки, подключите:
- SATA-кабели к материнке.
- Питание от БП.
7. **Подключите переднюю панель** (USB, аудио, кнопки включения).
8. **Установите блок питания**, закрепите.
9. **Подключите все компоненты**, проверьте, нет ли болтающих проводов.
10. **Включите, проверьте запуск.**
> ✅ **Итог:** Сервер собран, готов к установке ОС.

24
app/data/docs/1-4.md Normal file
View File

@@ -0,0 +1,24 @@
### Финансы и итоговая конфигурация**
Проверьте бюджет и оцените результат.
#### **Затраты:**
- Корпус: 12 000 ₽
- Материнка: 22 000 ₽
- CPU: 9 000 ₽
- Память (замена на десктопе): ~10 000 ₽
- Кулер (замена на десктопе): ~3 000 ₽
- **Итого: ~56 000 ₽**
#### **Компенсация:**
- Продажа старого HP Microserver: ~30 000 ₽
- Скидка в магазине
- **Чистые затраты: ~1015 000 ₽**
#### **Итоговая конфигурация:**
- **Производительность:** Ryzen 7 3700 + 32 ГБ RAM → мощнее старого Xeon.
- **Хранение:** 33 ТБ + SSD-кэш.
- **Гибкость:** 8+ дисков, M.2, PCI-E, IPMI.
- **Расширяемость:** можно добавить GPU, 10 Гбит, больше RAM.
> ✅ **Итог:** Вы получили мощный, тихий, энергоэффективный сервер за разумные деньги. Готов к установке Unraid, Proxmox или другой ОС.

22
app/data/docs/2-1.md Normal file
View File

@@ -0,0 +1,22 @@
### Как выбрать ОС для домашнего сервера**
При замене Windows Server нужно выбрать современную, гибкую систему, сочетающую NAS, виртуализацию и контейнеры.
#### **Варианты:**
| Система | Подходит, если… | Минусы |
|--------|------------------|--------|
| **Unraid** | Нужна гибкость, Docker, VM, диски любого объёма | Платная лицензия |
| **TrueNAS** | Важна отказоустойчивость (ZFS), энтерпрайз-подход | Требователен к RAM, неудобен с разными дисками |
| **OpenMediaVault** | Хочется лёгкий Linux-сервер | Устаревший интерфейс, меньше интеграций |
| **Proxmox VE** | Серьёзная виртуализация — основная задача | Неудобный веб-интерфейс |
| **ESXi / XCP-ng** | Работа в enterprise-среде | Сложность, неудобство для домашнего использования |
#### **Финальный выбор — Unraid:**
- ✅ Поддержка дисков **любого объёма**
- ✅ Встроенная **отказоустойчивость (parity)**
- ✅ Удобный **Docker** и **виртуализация (KVM)**
- ✅ Проброс GPU, USB, SATA
- ✅ SSD-кэш, плагины, Community Appstore
- ❌ Платно: 89$ (до 12 дисков)
> ✅ **Итог:** Unraid — лучший баланс между простотой, функциональностью и гибкостью для домашнего сервера.

29
app/data/docs/2-2.md Normal file
View File

@@ -0,0 +1,29 @@
### Настройка дискового массива в Unraid**
Unraid позволяет собрать массив из дисков разного объёма с защитой от сбоев.
#### **Ключевые понятия:**
- **Data-диски** — хранят данные.
- **Parity-диск** — один или два диска для защиты от потери (аналог RAID).
- **Кэш-диск (SSD)** — ускоряет запись и доступ.
- **Флешка** — хранит ОС и настройки (не участвует в массиве).
#### **Как настроить:**
1. Подключите все диски.
2. В веб-интерфейсе (`http://tower`) назначьте:
- Один диск как **Parity**
- Остальные как **Data**
- SSD — как **Cache**
3. Запустите массив.
#### **Гибкость:**
- Можно добавлять, удалять, заменять диски.
- Замена: только на диск **равного или большего объёма**.
- При разборе массива данные остаются на дисках.
#### **Важно:**
- **Ребилд parity** занимает 1218 часов (при 8 ТБ).
- Во время ребилда массив **без защиты**.
- Для экономии времени: можно сначала собрать массив **без parity**, заполнить данными, потом добавить parity и сделать ребилд.
> ✅ **Итог:** Unraid даёт максимальную гибкость в управлении дисками при наличии отказоустойчивости.

23
app/data/docs/2-3.md Normal file
View File

@@ -0,0 +1,23 @@
### Миграция сервисов на Unraid**
Перенесите ключевые сервисы со старого сервера в Docker и виртуальные машины.
#### **Как заменить каждый сервис:**
| Было | Стало | Как настроить |
|------|-------|----------------|
| **Файловое хранилище** | SMB в Unraid | Создайте шары (shared folders), включите SMB |
| **Торрент-клиент** | qBittorrent / Deluge (Docker) | Через Community Appstore |
| **Медиасервер** | Plex (Docker) | Подключите старую базу, укажите пути |
| **Резервное копирование** | Duplicati → OneDrive | Docker-контейнер, шифрование, версии |
| **Синхронизация** | Robocopy / GoodSync | Syncthing (Docker) — для ноутбуков |
| **Виртуальные машины** | VirtualBox | KVM в Unraid (поддержка проброса GPU/USB) |
| **Удалённый доступ** | RDP | Виртуалка с Windows + RDP |
| **Хостинг (Bitwarden и др.)** | Виртуалки | Docker-контейнеры (проще и надёжнее) |
#### **Советы:**
- Используйте **Community Applications** для установки контейнеров.
- Для управления множеством Docker — поставьте **Portainer**.
- Проброс USB-флешки: через `/dev/disk/by-id/...` как raw-устройство.
> ✅ **Итог:** Все сервисы легко переносятся в Unraid с помощью Docker и KVM.

33
app/data/docs/2-4.md Normal file
View File

@@ -0,0 +1,33 @@
### Планирование улучшений и бэкапов**
Unraid — это основа. Его можно расширять по мере роста потребностей.
#### **Что добавить позже:**
- **Видеокарта** — NVIDIA с NVENC для аппаратного транскодинга (Plex/Jellyfin).
- **10 Гбит сеть** — при обновлении роутера и кабелей.
- **Portainer** — для удобного управления Docker-контейнерами.
- **ZFS через плагин** — если понадобится (не основная ФС).
- **Автоматизация** — через плагины `CA User Scripts` или `Dynamix`.
#### **Обязательные бэкапы:**
1. **Конфигурация Unraid:**
- Экспортируйте: `Settings → Flash → Backup`
- Сохраните на флешку или в облако.
2. **Папки:**
- `/config` — настройки сервера
- `/docker` — контейнеры
- `/vm` — виртуальные машины
3. **Внешние бэкапы:**
- Используйте **Duplicati (Docker)** → OneDrive, Mail.ru, Backblaze.
- Настройте хранение: ежедневно (неделя), еженедельно (месяц), ежемесячно (год).
#### **Итоговая архитектура:**
```
Unraid
├── Массив: 6× HDD + 1× Parity + SSD Cache
├── Docker: Plex, qBittorrent, Duplicati, Syncthing
├── VM: Windows (RDP), Linux (тесты)
└── Плагины: Community Apps, Dynamix, CA User Scripts
```
> ✅ **Итог:** Unraid легко масштабируется. Главное — регулярно бэкапить конфигурацию и данные.

15
app/data/docs/3-1.md Normal file
View File

@@ -0,0 +1,15 @@
### Проверка совместимости и выбор процессора**
Перед запуском сервера убедитесь, что железо работает стабильно.
#### **Ключевые шаги:**
1. Проверьте **официальную поддержку CPU** материнской платой.
- Пример: Ryzen 7 1700 на ASRock X470D4U работал с зависаниями при нагрузке (например, `rsync`).
2. Если процессор не в списке поддержки — ожидайте проблем.
3. Замените нестабильный CPU на официально поддерживаемый:
- Успешный выбор: **Ryzen 7 3700** (8 ядер, 16 потоков, AM4).
4. После замены:
- Обновите BIOS, если нужно.
- Проверьте стабильность под нагрузкой (чтение/запись массива, запуск VM).
> ✅ **Итог:** Используйте только проверенные и поддерживаемые процессоры — это основа стабильной работы.

15
app/data/docs/3-2.md Normal file
View File

@@ -0,0 +1,15 @@
### Организация охлаждения**
Правильное охлаждение критично для долговечности HDD и CPU.
#### **Схема вентиляции:**
- **Передняя панель:** 120 мм вентилятор на **вдув**.
- **Задняя панель:** 140 мм вентилятор на **выдув**.
- **Верх корпуса:** 140 мм вентилятор на **выдув** — для отвода горячего воздуха от CPU-кулера.
#### **Требования:**
- Все вентиляторы — **4-pin PWM** (ASRock X470D4U не управляет 3-pin).
- Кулер: **DeepCool GAMMAXX 300** — подходит для Ryzen 3700.
- Цель: температура HDD под нагрузкой — **не выше 40°C**.
> ✅ **Итог:** Трёхвентиляторная схема обеспечивает стабильную температуру даже в жару.

21
app/data/docs/3-3.md Normal file
View File

@@ -0,0 +1,21 @@
### Энергопотребление и реальные цифры**
Знайте, сколько сервер потребляет, чтобы оценить стоимость эксплуатации.
#### **Измерения (конфигурация):**
- CPU: Ryzen 7 3700 @3.6 ГГц
- RAM: 32 ГБ
- Диски: 6× HDD, 2× SSD
#### **Потребление:**
| Состояние | Потребление |
|----------|-------------|
| Выключен (IPMI работает) | 46 Вт |
| Пик при включении | 120 Вт |
| Холостой ход (диски крутятся) | 7073 Вт |
| Холостой ход (диски остановлены) | 4243 Вт |
| Работа (массив, VM, Docker) | 8083 Вт |
| Проверка parity | 9095 Вт |
| Максимальная нагрузка | 120125 Вт |
> ✅ **Итог:** Среднее потребление — **~100 Вт**, что даёт около **300 руб/мес** при непрерывной работе.

34
app/data/docs/3-4.md Normal file
View File

@@ -0,0 +1,34 @@
### Установка аддонов и аккуратная укладка кабелей**
Оптимизируйте внутреннее пространство и добавьте удобные доработки.
#### **1. SATA-контроллер в M.2**
- Задача: не тратить PCI-E слот.
- Решение: M.2 → 5× SATA контроллер (PCIe 2.0 x4).
- Скорость: до 900 МБ/с — хватает для HDD.
- Подключение: второй корзине HDD.
#### **2. Внутренний свитч (временное решение)**
- Проблема: 2 порта на материнке, но 1 свободный на роутере.
- Решение:
- Установите 5-портовый свитч **внутри корпуса**.
- Запитайте от БП.
- Подключите: LAN + IPMI → свитч → роутер.
- Минус: при выключении питания — свитч гаснет.
#### **3. USB-хаб**
- Проблема: всего 4 USB-порта.
- Решение:
- Используйте **внешний хаб** в задних USB-портах.
- Закрепите на корпусе.
- Передние порты — подключите напрямую к материнке.
#### **4. Укладка кабелей**
- **Питание HDD:** 40 см кабели с 4 разъёмами — удобно для корзин.
- **SATA-шлейфы:** 50 см, 4 разъёма — меньше мусора.
- **Трассировка:**
- Не пересекайте кабели.
- Используйте штатные стяжки.
- Оставьте запас для извлечения корзин.
> ✅ **Итог:** Аккуратная сборка упрощает обслуживание и улучшает охлаждение.

17
app/data/docs/4-1.md Normal file
View File

@@ -0,0 +1,17 @@
### Установка Unraid и первоначальная настройка**
Начните с установки ОС и базовой конфигурации.
#### **Шаги:**
1. Скачайте образ Unraid с официального сайта.
2. Запишите его на USB-флешку (через Rufus, Balena Etcher и т.п.).
3. Вставьте флешку в сервер, включите — загрузитесь с неё.
4. Откройте в браузере: `http://tower` (или IP сервера).
5. Настройте:
- Пароль администратора.
- Сетевые интерфейсы (LAN, IPMI — при необходимости).
- Подключите диски (они появятся в интерфейсе).
> **Важно:** Unraid загружается в RAM, вся конфигурация хранится на флешке.
> ✅ **Совет:** Используйте свежие гайды от **SpaceInvader One** или **iBracorp** — они покрывают все основы.

22
app/data/docs/4-2.md Normal file
View File

@@ -0,0 +1,22 @@
### Настройка дискового массива и parity**
Организуйте надёжное хранилище с защитой от сбоев.
#### **Основные шаги:**
1. Назначьте один диск как **Parity** (желательно CMR, например, Toshiba 8 ТБ).
2. Остальные диски — как **Data**.
3. (Опционально) Добавьте второй **Parity** — защита от двух сбоев.
4. Назначьте SSD как **Cache** (ускоряет запись и доступ к Docker/VM).
5. Запустите массив.
#### **Гибкость:**
- Диски могут быть **разного объёма**.
- Можно добавлять, удалять, заменять без потери данных.
- При удалении: остановите массив → пересоздайте без диска → ребилд parity.
#### **Добавление диска (без очистки):**
1. Подключите диск как **Unassigned Device**.
2. Отформатируйте в XFS.
3. Остановите массив → извлеките parity → добавьте диск → верните parity → дождитесь ребилда.
> ✅ **Совет:** Для экономии времени сначала соберите массив **без parity**, заполните данными, потом добавьте parity.

19
app/data/docs/4-3.md Normal file
View File

@@ -0,0 +1,19 @@
### Установка и настройка ключевых сервисов**
Разверните основные сервисы через Docker и виртуальные машины.
#### **Какие сервисы и как:**
| Сервис | Решение |
|--------|--------|
| **Торрент-клиент** | `qBittorrent` или `Deluge` (Docker) |
| **Медиасервер** | `Plex` (Docker) — подключите старую базу и укажите новые пути |
| **Резервное копирование** | `Duplicati` (Docker) → OneDrive (шифрование, версии) |
| | Увеличьте размер архива (до 300 МБ) для больших файлов (RAW-фото) |
| | Проблема: `/tmp` заполняется → смонтируйте внешнюю папку |
| **Синхронизация** | `Syncthing` (Docker) — для ноутбуков, авто-сброс при отключении |
| **Удалённый доступ** | Виртуалка с Windows + RDP или `Apache Guacamole` (Docker) — веб-доступ |
| **Внутренний хостинг** | `Bitwarden`, `Nginx Proxy Manager` (Docker) |
| | Проброс портов: 80/443 |
> ✅ **Совет:** Установите **Portainer** — он упрощает управление множеством контейнеров.

23
app/data/docs/4-4.md Normal file
View File

@@ -0,0 +1,23 @@
### Плагины, бэкапы и полезные доработки**
Настройте расширения и защитите конфигурацию.
#### **Полезные плагины:**
- **Community Applications** — App Store для Docker и плагинов.
- **Unassigned Devices** — управление дисками вне массива.
- **Dynamix** — мониторинг температур, дисков, настройка.
- **CA User Scripts** — автоматизация (бэкапы, запуск скриптов).
- **Unbalance** — перенос данных с диска перед удалением.
#### **Бэкап конфигурации (обязательно!):**
1. Экспортируйте:
- `Settings → Flash → Backup` (вся конфигурация).
- Папки: `/config`, `/docker`, `/vm`.
2. Храните на внешней флешке или в облаке.
#### **Дополнительно:**
- Настройте **rclone** → подключите Mail.ru (1 ТБ) как диск (O:).
- Используйте для синхронизации музыки, книг, видео.
- Расшарьте через веб или виртуалку.
> ✅ **Итог:** Unraid становится мощной и надёжной платформой. Главное — регулярно бэкапьте конфигурацию.

View File

@@ -1,13 +1,14 @@
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, AsyncGenerator
import gradio as gr
import uuid
import torch
import threading
import asyncio
from transformers import AutoTokenizer as HFTokenizer
from loguru import logger
from langchain_chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
# Предполагается, что у тебя есть config.py с settings
from vllm import AsyncLLMEngine, SamplingParams
from vllm.engine.arg_utils import AsyncEngineArgs
from config import settings
@@ -21,22 +22,24 @@ class ChatWithAI:
)
if provider == "qwen3":
model_name = getattr(settings, "LOCAL_LLM_NAME", "/models/Qwen3-4B")
logger.info(f"Загрузка локальной модели: {model_name}")
model_name = getattr(settings, "LOCAL_LLM_NAME", "/models/Qwen3-8B")
logger.info(f"Инициализация vLLM движка с моделью: {model_name}")
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float32,
device_map="cuda",
)
# Streamer для потоковой генерации
self.streamer = TextIteratorStreamer(
self.tokenizer,
skip_prompt=True,
skip_special_tokens=True
# Аргументы для асинхронного движка vLLM
engine_args = AsyncEngineArgs(
model=model_name,
tokenizer=model_name,
tokenizer_mode="auto",
trust_remote_code=True,
dtype=torch.bfloat16, # float16
gpu_memory_utilization=0.65,
max_model_len=32768,
enable_prefix_caching=True,
tensor_parallel_size=1, # Увеличь, если у тебя несколько GPU
enable_chunked_prefill=False,
)
self.engine = AsyncLLMEngine.from_engine_args(engine_args)
self.tokenizer = HFTokenizer.from_pretrained(settings.LM_MODEL_NAME, trust_remote_code=True)
else:
raise ValueError(f"Неподдерживаемый провайдер: {provider}")
@@ -46,7 +49,7 @@ class ChatWithAI:
collection_name=settings.DOCS_COLLECTION_NAME,
)
def get_relevant_context(self, query: str, k: int = 3) -> List[Dict[str, Any]]:
def get_relevant_context(self, query: str, k: int = 5) -> List[Dict[str, Any]]:
"""Получение релевантного контекста из базы данных."""
try:
results = self.chroma_db.similarity_search(query, k=k)
@@ -71,8 +74,8 @@ class ChatWithAI:
)
return "\n---\n".join(formatted_context)
def generate_response_stream(self, query: str):
"""Генерация ответа с потоковой передачей токенов."""
async def generate_response_stream(self, query: str) -> AsyncGenerator[str, None]:
"""Генерация ответа с потоковой передачей токенов через vLLM."""
try:
logger.info(f"Пользовательский запрос: {query}")
context = self.get_relevant_context(query)
@@ -85,17 +88,17 @@ class ChatWithAI:
messages = [
{
"role": "system",
"content": """Ты — внутренний менеджер компании Mazban. Отвечаешь по делу без лишних вступлений.
"content": """Ты — внутренний менеджер помощи пользоваткля по вопросам настройки сервера. Отвечаешь по делу без лишних вступлений.
Правила:
1. Сразу переходи к сути, без фраз типа "На основе контекста"
2. Используй только факты. Если точных данных нет — отвечай общими фразами об Marzban, но не придумывай конкретику
3. Используй обычный текст без форматирования
2. Используй только факты. Если точных данных нет — отвечай общими фразами об настройки сервера, но не придумывай конкретику
3. Используй текст с форматированием.
4. Включай ссылки только если они есть в контексте
5. Говори от первого лица множественного числа: "Мы предоставляем", "У нас есть"
6. При упоминании файлов делай это естественно, например: "Я прикреплю инструкцию, где подробно описаны шаги"
7. На приветствия отвечай доброжелательно, на негатив — с легким юмором
8. Можешь при ответах использовать общую информацию из открытых источников по Marzban, но опирайся на контекст
8. Можешь при ответах использовать общую информацию из открытых источников по настройке сервера, но опирайся на контекст
9. Если пользователь спрашивает о ценах, планах или технических характеристиках — давай конкретные ответы из контекста
10. При технических вопросах предлагай практические решения
@@ -115,37 +118,36 @@ class ChatWithAI:
enable_thinking=False
)
# Подготавливаем вход
inputs = self.tokenizer(prompt, return_tensors="pt").to("cuda")
# Очищаем streamer и запускаем генерацию в отдельном потоке
self.streamer = TextIteratorStreamer(
self.tokenizer,
skip_prompt=True,
skip_special_tokens=True
# Параметры генерации
sampling_params = SamplingParams(
temperature=0.3,
top_p=0.9,
max_tokens=2048,
stop_token_ids=[], # можно добавить, если нужно
)
generate_kwargs = {
"input_ids": inputs["input_ids"],
"max_new_tokens": 512,
"temperature": 0.7,
"do_sample": True,
"top_p": 0.9,
"pad_token_id": self.tokenizer.eos_token_id,
"streamer": self.streamer,
}
thread = threading.Thread(target=self.model.generate, kwargs=generate_kwargs)
thread.start()
# Потоковая передача токенов
# Генерация через vLLM
final_output = ""
buffer = ""
for token in self.streamer:
buffer += token
yield buffer # Отправляем частичный ответ
# Генерируем асинхронно
request_id = str(uuid.uuid4())
try:
async for output in self.engine.generate(prompt, sampling_params, request_id):
if output.outputs:
text = output.outputs[0].text
# Отправляем только новые токены
new_text = text[len(final_output):]
final_output = text
if new_text:
buffer += new_text
yield buffer # Постепенно возвращаем накопленный текст
except Exception as e:
logger.error(f"Ошибка при генерации vLLM: {e}")
yield "Произошла ошибка при генерации ответа."
except Exception as e:
logger.error(f"Ошибка при генерации ответа: {e}")
logger.error(f"Неожиданная ошибка: {e}")
yield "Произошла ошибка при генерации ответа."
@@ -153,23 +155,30 @@ class ChatWithAI:
def main():
chat = ChatWithAI(provider="qwen3")
def respond(message, history):
async def respond(message, history):
# Генерируем ответ по частям
for token in chat.generate_response_stream(message):
yield token
try:
async for token in chat.generate_response_stream(message):
yield token
except Exception as e:
logger.error(f"Ошибка в respond: {e}")
yield "Извините, произошла ошибка при обработке запроса."
demo = gr.ChatInterface(
fn=respond,
title="Помощник настройки Marzban",
title="Помощник настройки сервера и подбора железа",
description="Задайте вопрос — получите ответ от внутреннего менеджера.",
examples=[
"Как подключить Marzban?",
"Как настроить telegram бота?",
"Что такое marzban?"
"Как определить цели и требования для домашнего сервера?",
"Как выбрать ОС для домашнего сервера?",
"Проверка совместимости и выбор процессора",
"Установка Unraid и первоначальная настройка"
],
)
demo.launch(server_name="0.0.0.0", server_port=8080, share=False)
demo.queue(max_size=20, default_concurrency_limit=10).launch(
server_name="0.0.0.0", server_port=8080, share=False
)
if __name__ == "__main__":
main()
main()

View File

@@ -17,10 +17,7 @@ services:
volumes:
- ./app:/app
- ./models:/models
- ./cache/cache:/root/.cache
- ./cache/site-packages:/usr/local/lib/python3.10/site-packages
- ./offline_packages:/offline_packages
# entrypoint: sleep 1000000 #./app/entrypoint.sh
entrypoint: sleep 1000000 #./app/entrypoint.sh
ports:
- "8080:8080"
networks:

View File

@@ -9,17 +9,6 @@ echo \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
echo \
'{ \
"runtimes": { \
"nvidia": { \
"path": "nvidia-container-runtime", \
"runtimeArgs": [] \
} \
}, \
"default-runtime": "nvidia" \
}' > /etc/docker/daemon.json
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg && \
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
@@ -38,5 +27,25 @@ apt-get install -y \
git lfs install
echo \
'{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
},
"default-runtime": "nvidia"
}' > /etc/docker/daemon.json
mkdir models/
cd models
git clone https://huggingface.co/Qwen/Qwen3-4B
git clone https://huggingface.co/Qwen/Qwen3-Embedding-0.6B
ls
lspci -k | grep -EA2 'VGA|3D'
nvidia-smi

View File

@@ -11,4 +11,8 @@ chromadb==0.6.3
sentence-transformers==3.4.1
langchain-chroma==0.2.2
pydantic-settings==2.8.1
langchain-text-splitters==0.3.7
langchain-text-splitters==0.3.7
vllm>=0.4.2
aiohttp>=3.8.0
fastapi>=0.100.0
starlette>=0.27.0