This commit is contained in:
2025-08-02 14:55:41 +00:00
commit 187bcc61bd
6 changed files with 165 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/app/.gradio
/app/core
/models
/cache

40
Dockerfile Normal file
View File

@@ -0,0 +1,40 @@
# Базовый образ с поддержкой CUDA
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04
# Установка метаданных
LABEL maintainer="dr.holyblack@gmail.com"
LABEL description="Qwen3-8B-AWQ with Gradio interface"
# Установка системных зависимостей
RUN apt-get update && \
apt-get install -y --no-install-recommends \
python3.10 \
python3-pip \
git \
curl \
wget \
libgl1 \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# Установка Python 3.10 как основного
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1 && \
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.10 1
# Установка базовых Python-зависимостей
RUN pip install --upgrade pip && \
pip install setuptools wheel
WORKDIR /app
# Копируем только requirements.txt для кэширования слоя
COPY offline_packages/requirements.txt /app/requirements.txt
# Установка зависимостей (включая GPU-версии)
RUN pip install --no-cache-dir -r /app/requirements.txt
# Копируем приложение
COPY app /app
# Запуск приложения
CMD ["python", "main.py"]

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
Для запуска используй команду:
docker compose up -d --configure

77
app/main.py Normal file
View File

@@ -0,0 +1,77 @@
import gradio as gr
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
import torch
import threading
# Пути к модели
model_name = "/models/Qwen3-4B-Base"
# Загрузка токенизатора и модели (один раз при старте)
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="cuda",
trust_remote_code=True
)
# Отключим кэширование в истории, чтобы каждый запрос был независимым
def generate_response(message, history):
# Форматируем диалог: используем только текущую историю
prompt = ""
for human, assistant in history:
prompt += f"<|im_start|>user\n{human}<|im_end|>\n<|im_start|>assistant\n{assistant}<|im_end|>\n"
prompt += f"<|im_start|>user\n{message}<|im_end|>\n<|im_start|>assistant\n"
# Токенизация
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
# Создаём уникальный streamer для каждого запроса
streamer = TextIteratorStreamer(
tokenizer,
skip_prompt=True,
skip_special_tokens=True
)
# Параметры генерации
generation_kwargs = {
"input_ids": inputs["input_ids"],
"max_new_tokens": 1024,
"temperature": 0.6,
"top_p": 0.9,
"do_sample": True,
"pad_token_id": tokenizer.eos_token_id,
"streamer": streamer,
}
# Запускаем генерацию в отдельном потоке
thread = threading.Thread(target=model.generate, kwargs=generation_kwargs)
thread.start()
# Постепенно возвращаем результат
buffer = ""
for new_text in streamer:
buffer += new_text
yield buffer.strip()
# Создаем интерфейс
demo = gr.ChatInterface(
fn=generate_response,
title="Qwen3-4B-Base Chat",
description="Общайтесь с моделью Qwen3-4B-Base в режиме реального времени с потоковой генерацией",
examples=[
"Объясни, как работает квантование AWQ?",
"Напиши стихотворение про ИИ",
"Какие преимущества у Qwen3 перед предыдущими версиями?"
],
theme="soft",
)
if __name__ == "__main__":
# ВАЖНО: используем .queue() для поддержки асинхронной обработки
demo.queue(max_size=20, default_concurrency_limit=10).launch(
server_port=8080,
server_name="0.0.0.0",
share=False,
# Можно добавить: max_batch_size=1, concurrency_count=4
)

36
docker-compose.yml Normal file
View File

@@ -0,0 +1,36 @@
services:
llm-chat:
build:
context: .
dockerfile: Dockerfile
platform: linux/amd64
privileged: true
container_name: llm-chat
restart: always
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
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
ports:
- "8080:8080"
networks:
- apps
networks:
apps:
name: apps
driver: bridge
ipam:
driver: default
config:
- subnet: "172.100.0.0/24"
gateway: "172.100.0.1"

View File

@@ -0,0 +1,5 @@
torch>=2.6.0
transformers>=4.50.0
gradio>=4.29.0
safetensors>=0.4.3
accelerate>=0.29.3