qwen-api-proxy 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,2054 @@
1
+ # FreeQwenApi
2
+
3
+ > **🐳 Docker Hub:** https://hub.docker.com/r/endykaufman/qwen-api-proxy
4
+ > **🔧 Форк:** https://github.com/EndyKaufman/FreeQwenApi
5
+ > **🌐 Оригинал:** https://github.com/y13sint/FreeQwenApi
6
+
7
+ ## 🌟 О этом форке
8
+
9
+ Это **улучшенная версия** оригинального проекта FreeQwenApi со значительными улучшениями для production использования и лучшего пользовательского опыта.
10
+
11
+
12
+ <table>
13
+ <tr>
14
+ <td><img src="docs/images/stats.png" alt="информация о подсистемах" width="100%"/></td>
15
+ <td><img src="docs/images/help.png" alt="справка" width="100%"/></td>
16
+ <td><img src="docs/images/chat.png" alt="режим чата" width="100%"/></td>
17
+ </tr>
18
+ </table>
19
+
20
+ ### ⭐ Ключевые отличия от оригинала
21
+
22
+ | Функция | Оригинал | Этот форк |
23
+ |---------|----------|-----------|
24
+ | **Telegram бот** | ❌ Нет | ✅ Полная интеграция + генерация изображений |
25
+ | **LLM чат** | ❌ Нет | ✅ AI ассистент через Telegram |
26
+ | **Генерация изображений** | ❌ Нет | ✅ Text-to-image + image-to-image |
27
+ | **Проксирование LLM** | ❌ Нет | ✅ Qwen API через Telegram |
28
+ | **Управление сессиями** | Только вручную | ✅ Загрузка через Telegram (.zip/.7z) |
29
+ | **Прокси поддержка** | ❌ Нет для Telegram | ✅ HTTP/HTTPS/SOCKS |
30
+ | **Проверка здоровья** | ❌ Нет | ✅ При старте + каждые 4 часа |
31
+ | **Проверка прав доступа** | ❌ Нет | ✅ Автоматическая при старте |
32
+ | **Система логов** | Базовая консоль | ✅ Winston с ротацией |
33
+ | **Распаковка архивов** | Вручную | ✅ Автоматически с backup |
34
+ | **Обработка ошибок** | Базовая | ✅ Fault-tolerant extraction |
35
+ | **Работа без токенов** | ❌ Нет | ✅ Режим только бота |
36
+ | **Документация** | Базовая | ✅ ~2000 строк руководств |
37
+ | **Docker поддержка** | Базовая | ✅ Production-оптимизация |
38
+ | **Автоматическая .env** | ❌ Нет | ✅ dotenv integration |
39
+
40
+ ### 🚀 Новые функции в этом форке
41
+
42
+ 1. **Интеграция Telegram бота**
43
+ - Загрузка архивов сессий напрямую через Telegram
44
+ - Мониторинг статуса сервиса в реальном времени
45
+ - Чат с AI ассистентом (LLM режим)
46
+ - Генерация изображений через Telegram (photo-to-photo + текст)
47
+ - Автоматический backup сессий перед обновлениями
48
+ - Graceful перезапуски сервиса
49
+ - Проксирование запросов к Qwen LLM через бота
50
+ - Команды: `/help`, `/status`, `/chat`, `/model`, `/clear`, `/restart`
51
+
52
+ 2. **Повышенная надёжность**
53
+ - Автоматическая распаковка архивов при запуске
54
+ - Fault-tolerant извлечение файлов (продолжает при ошибках)
55
+ - Комплексные проверки здоровья при запуске
56
+ - Периодические проверки каждые 4 часа
57
+ - Отчёты о статусе системы в Telegram
58
+ - Умная обработка rate limits (отдельно для чата и медиа)
59
+ - **Автоматическая проверка прав доступа** при старте с командами для исправления
60
+
61
+ 3. **Улучшенная безопасность**
62
+ - Безопасная обработка credentials (никогда не логируются)
63
+ - Прокси поддержка для Telegram API (HTTP/HTTPS/SOCKS)
64
+ - Контроль доступа по whitelist
65
+ - Безопасное управление правами файлов
66
+ - Автоматическая загрузка .env
67
+ - Multipart file upload с валидацией
68
+
69
+ 4. **Гибкость работы**
70
+ - Работает как Telegram бот даже без токенов Qwen
71
+ - Добавление первого аккаунта через Telegram
72
+ - Поддержка множества прокси протоколов
73
+ - Конфигурация через .env файл
74
+ - Динамический выбор модели без перезапуска
75
+
76
+ ---
77
+
78
+ ### 📚 Руководство
79
+
80
+ - **Бесплатный доступ**: Используйте модели Qwen без оплаты API-ключа
81
+ - **Полная совместимость**: Поддержка OpenAI-совместимого интерфейса для простой интеграции
82
+ - **Возможность загрузки файлов и получение ссылки прямо из прокси**
83
+ - **🆕 API v2**: Обновлено на новый Qwen API с улучшенной системой контекста
84
+ - **🔥 25+ моделей**: Поддержка всех современных моделей Qwen, включая Qwen 3.5
85
+ - **🎨 Генерация изображений**: Text-to-image + Image-to-image через Qwen + DashScope API
86
+ - **📸 Multipart Upload**: Загрузка файлов напрямую через API
87
+ - **💾 Автосохранение сессий**: Умное управление контекстом для OpenWebUI
88
+ - **🔄 Rate Limit Intelligence**: Отдельные лимиты для чата и генерации медиа
89
+
90
+ **Что можно делать:**
91
+
92
+ - Отправлять запросы к моделям Qwen (включая qwen3-max, qwen3-coder-plus, qwq-32b и др.)
93
+ - Использовать OpenAI SDK без изменений -- просто поменяйте `baseURL`
94
+ - Вести диалоги с сохранением контекста на серверах Qwen (API v2)
95
+ - Загружать файлы и изображения для анализа
96
+ - Получать ответы в потоковом режиме (SSE streaming)
97
+ - Подключать несколько аккаунтов с автоматической ротацией
98
+
99
+ ```bash
100
+ # Всё, что нужно -- обычный OpenAI-совместимый запрос
101
+ # Модель будет взята из настроек бота (bot_settings.json)
102
+ curl http://localhost:3264/api/chat/completions \
103
+ -H "Content-Type: application/json" \
104
+ -d '{"messages":[{"role":"user","content":"Привет!"}]}'
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Содержание
110
+
111
+ 1. [Быстрый старт](#быстрый-старт)
112
+ 2. [Docker Hub](#docker-hub) 🆕
113
+ 3. [Docker](#docker)
114
+ 4. [Управление аккаунтами](#управление-аккаунтами)
115
+ 5. [Авторизация API-ключами](#авторизация-api-ключами)
116
+ 6. [API Reference](#api-reference)
117
+ - [POST /api/chat](#post-apichat)
118
+ - [POST /api/chat/completions](#post-apichatcompletions)
119
+ - [GET /api/models](#get-apimodels)
120
+ - [GET /api/status](#get-apistatus)
121
+ - [POST /api/chats](#post-apichats)
122
+ - [POST /api/files/upload](#post-apifilesupload)
123
+ - [POST /api/files/getstsToken](#post-apifilesgetststoken)
124
+ - [POST /api/images/generations](#post-apiimagesgenerations)
125
+ 7. [Работа с контекстом (API v2)](#работа-с-контекстом-api-v2)
126
+ 8. [Работа с изображениями](#работа-с-изображениями)
127
+ 9. [Генерация изображений](#генерация-изображений) 🆕
128
+ 10. [OpenAI SDK](#openai-sdk)
129
+ 11. [Python](#python-альтернативная-реализация)
130
+ 12. [Доступные модели](#доступные-модели)
131
+ 13. [Переменные окружения](#переменные-окружения)
132
+ 14. [Структура проекта](#структура-проекта)
133
+
134
+ ---
135
+
136
+ ## Быстрый старт
137
+
138
+ ```bash
139
+ # Node.js (Основной)
140
+ git clone https://github.com/y13sint/FreeQwenApi
141
+ cd FreeQwenApi
142
+ npm install
143
+ npm start
144
+
145
+ # Python (Альтернативный)
146
+ git clone https://github.com/y13sint/FreeQwenApi
147
+ cd FreeQwenApi
148
+ python -m venv venv
149
+ # Windows:
150
+ # venv\Scripts\activate
151
+ # Linux/macOS:
152
+ # source venv/bin/activate
153
+ pip install -r requirements.txt
154
+ playwright install chromium
155
+ python main.py
156
+ ```
157
+
158
+ При первом запуске появится интерактивное меню:
159
+
160
+ ```
161
+ ███████ ██████ ███████ ███████ ██████ ██ ██ ███████ ███ ██ █████ ██████ ██
162
+ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
163
+ █████ ██████ █████ █████ ██ ██ ██ █ ██ █████ ██ ██ ██ ███████ ██████ ██
164
+ ██ ██ ██ ██ ██ ██ ▄▄ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██
165
+ ██ ██ ██ ███████ ███████ ██████ ███ ███ ███████ ██ ████ ██ ██ ██ ██
166
+
167
+ Список аккаунтов:
168
+ (пусто)
169
+
170
+ === Меню ===
171
+ 1 - Добавить новый аккаунт
172
+ 2 - Перелогинить аккаунт с истекшим токеном
173
+ 3 - Запустить прокси (по умолчанию)
174
+ 4 - Удалить аккаунт
175
+ Ваш выбор (Enter = 3):
176
+ ```
177
+
178
+ **Порядок действий:**
179
+
180
+ 1. Выберите `1` -- откроется браузер Chromium
181
+ 2. Войдите в свой аккаунт Qwen на открывшейся странице
182
+ 3. После входа токен извлечётся автоматически, браузер закроется
183
+ 4. Выберите `3` (или нажмите Enter) -- сервер запустится
184
+
185
+ Сервер будет доступен по адресу `http://localhost:3264/api`.
186
+
187
+ ---
188
+
189
+ ## Docker Hub
190
+
191
+ Готовый Docker образ доступен на Docker Hub:
192
+
193
+ **🐳 https://hub.docker.com/r/endykaufman/qwen-api-proxy**
194
+
195
+ ### Быстрый запуск с Docker Hub
196
+
197
+ ```bash
198
+ # 1. Создаём .env файл
199
+ cp .env.example .env
200
+ nano .env # Настраиваем переменные
201
+
202
+ # 2. Запускаем контейнер
203
+ docker run -d \
204
+ --name qwen-proxy \
205
+ --env-file .env \
206
+ -p 3264:3264 \
207
+ -v $(pwd)/session:/app/session \
208
+ -v $(pwd)/logs:/app/logs \
209
+ -v $(pwd)/uploads:/app/uploads \
210
+ -v $(pwd)/temp:/app/temp \
211
+ endykaufman/qwen-api-proxy:1.0.10
212
+
213
+ # 3. Смотрим логи
214
+ docker logs -f qwen-proxy
215
+ ```
216
+
217
+ ### Доступные теги
218
+
219
+ - `latest` - последняя стабильная версия
220
+ - `1.0.10` - текущая версия
221
+ - `1.0.x` - предыдущие версии
222
+
223
+ > **💡 Важно:** Перед первым запуском добавьте аккаунт через `npm run auth` или загрузите сессию через Telegram бота.
224
+
225
+ ### 📖 Что такое Docker Compose?
226
+
227
+ **Docker Compose** - это инструмент для запуска многоконтейнерных приложений через файл `docker-compose.yml`.
228
+
229
+ **Установка:**
230
+ - **Windows/macOS**: Входит в Docker Desktop (установлен по умолчанию)
231
+ - **Linux**: `sudo apt install docker-compose-plugin`
232
+ - **Проверка**: `docker compose version`
233
+
234
+ > 💡 Если у вас установлен Docker Desktop - Compose уже есть!
235
+
236
+ ### Docker Compose с готовым образом
237
+
238
+ ```yaml
239
+ services:
240
+ qwen-proxy:
241
+ image: endykaufman/qwen-api-proxy:1.0.10
242
+ container_name: qwen-proxy
243
+ env_file:
244
+ - .env
245
+ ports:
246
+ - "${PORT:-3264}:3264"
247
+ volumes:
248
+ - ./session:/app/session
249
+ - ./logs:/app/logs
250
+ - ./uploads:/app/uploads
251
+ - ./temp:/app/temp
252
+ restart: unless-stopped
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Docker
258
+
259
+ Перед сборкой Docker-образа нужно добавить хотя бы один аккаунт, поскольку внутри контейнера нет GUI для интерактивного входа:
260
+
261
+ ```bash
262
+ # 1. Добавляем аккаунт(ы) локально
263
+ npm run auth
264
+
265
+ # 2. Создаём .env файл
266
+ cp .env.example .env
267
+ nano .env # Редактируем переменные
268
+
269
+ # 3. Собираем и запускаем
270
+
271
+ # Вариант A: С Docker Compose
272
+ docker compose build --no-cache
273
+ docker compose up -d
274
+
275
+ # Вариант B: Без Docker Compose (обычный Docker)
276
+ docker build -t qwen-proxy .
277
+ docker run -d \
278
+ --name qwen-proxy \
279
+ --env-file .env \
280
+ -p 3264:3264 \
281
+ -v $(pwd)/session:/app/session \
282
+ -v $(pwd)/logs:/app/logs \
283
+ -v $(pwd)/uploads:/app/uploads \
284
+ -v $(pwd)/temp:/app/temp \
285
+ qwen-proxy
286
+
287
+ # ИЛИ используем готовый образ с Docker Hub
288
+ docker run -d \
289
+ --name qwen-proxy \
290
+ --env-file .env \
291
+ -p 3264:3264 \
292
+ -v $(pwd)/session:/app/session \
293
+ -v $(pwd)/logs:/app/logs \
294
+ -v $(pwd)/uploads:/app/uploads \
295
+ -v $(pwd)/temp:/app/temp \
296
+ endykaufman/qwen-api-proxy:1.0.10
297
+ ```
298
+
299
+ Файл `docker-compose.yml`:
300
+
301
+ ```yaml
302
+ services:
303
+ qwen-proxy:
304
+ build: .
305
+ image: endykaufman/qwen-api-proxy:1.0.10
306
+ container_name: qwen-proxy
307
+ env_file:
308
+ - .env # Автоматическая загрузка переменных
309
+ environment:
310
+ - NODE_ENV=production
311
+ - PORT=${PORT:-3264}
312
+ - HOST=0.0.0.0
313
+ - SKIP_ACCOUNT_MENU=true
314
+ - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
315
+ - TELEGRAM_USER_IDS=${TELEGRAM_USER_IDS:-}
316
+ - TELEGRAM_PROXY=${TELEGRAM_PROXY:-}
317
+ - TELEGRAM_PROXY_URL=${TELEGRAM_PROXY_URL:-}
318
+ - TOKEN_EXPIRY_WARNING_MS=${TOKEN_EXPIRY_WARNING_MS:-3600000}
319
+ - DEFAULT_MODEL=${DEFAULT_MODEL:-qwen3.5-plus}
320
+ ports:
321
+ - "${PORT:-3264}:3264"
322
+ volumes:
323
+ - ./session:/app/session
324
+ - ./logs:/app/logs
325
+ - ./uploads:/app/uploads
326
+ restart: unless-stopped
327
+ ```
328
+
329
+ Переменная `SKIP_ACCOUNT_MENU=true` (или `NON_INTERACTIVE=true`) пропускает интерактивное меню и сразу запускает сервер, используя ранее сохранённые токены из `session/`.
330
+
331
+
332
+ ### Тома Docker и структура директорий
333
+
334
+ Проект использует следующие тома для сохранения данных между перезапусками:
335
+
336
+ ```yaml
337
+ volumes:
338
+ - ./session_backup:/app/session_backup # Backup сессий перед обновлениями
339
+ - ./session:/app/session # Токены и аккаунты Qwen
340
+ - ./logs:/app/logs # Файлы логов (Winston)
341
+ - ./uploads:/app/uploads # Временные загруженные файлы
342
+ - ./temp:/app/temp # Временная папка для распаковки архивов
343
+ ```
344
+
345
+ #### Зачем нужны `.gitkeep` и `.gitignore`?
346
+
347
+ Каждая из этих директорий содержит `.gitkeep` файл по важным причинам:
348
+
349
+ **1. Сохранение пустых директорий в Git**
350
+ - Git не отслеживает пустые папки
351
+ - `.gitkeep` гарантирует, что директории существуют после клонирования репозитория
352
+ - Без этого Docker не сможет монтировать несуществующие тома
353
+
354
+ **2. Игнорирование содержимого в Git**
355
+ Каждая директория также имеет `.gitignore` для игнорирования содержимого:
356
+
357
+ ```gitignore
358
+ # session/.gitignore
359
+ *
360
+ !.gitkeep
361
+ !.gitignore
362
+
363
+ # logs/.gitignore
364
+ *.log
365
+ !.gitkeep
366
+ !.gitignore
367
+
368
+ # uploads/.gitignore
369
+ *
370
+ !.gitkeep
371
+ !.gitignore
372
+
373
+ # temp/.gitignore
374
+ *
375
+ !.gitkeep
376
+ !.gitignore
377
+
378
+ # session_backup/.gitignore
379
+ *
380
+ !.gitkeep
381
+ !.gitignore
382
+ ```
383
+
384
+ **Почему это важно:**
385
+ - ✅ Токены и сессии не попадают в репозиторий (безопасность!)
386
+ - ✅ Логи не раздувают размер репозитория
387
+ - ✅ Временные файлы не коммитятся
388
+ - ✅ Backup'ы остаются локальными
389
+ - ✅ При клонировании все папки создаются автоматически
390
+
391
+ **3. Автоматическое создание при первом запуске**
392
+
393
+ При первом запуске приложение создаёт необходимые структуры:
394
+
395
+ ```bash
396
+ # Структура session/
397
+ session/
398
+ ├── .gitkeep
399
+ ├── .gitignore
400
+ ├── accounts/ # Создаётся автоматически
401
+ │ ├── acc_123456/
402
+ │ │ └── token.txt
403
+ │ └── acc_789012/
404
+ │ └── token.txt
405
+ └── tokens.json # Реестр всех аккаунтов
406
+
407
+ # Структура logs/
408
+ logs/
409
+ ├── .gitkeep
410
+ ├── .gitignore
411
+ ├── combined.log # Создаётся Winston
412
+ ├── error.log
413
+ └── http.log
414
+ ```
415
+
416
+ **4. Docker и права доступа**
417
+
418
+ При использовании Docker важно:
419
+ - Том создаётся на хост-машине (не в контейнере)
420
+ - Файлы сохраняются между перезапусками контейнера
421
+ - При удалении контейнера данные остаются на хосте
422
+ - Можно делать backup копированием папок
423
+
424
+ ```bash
425
+ # Backup всех данных
426
+ cp -r session/ session_backup_$(date +%Y%m%d)/
427
+ cp -r logs/ logs_backup_$(date +%Y%m%d)/
428
+
429
+ # Восстановление
430
+ cp -r session_backup_20260510/ session/
431
+ ```
432
+
433
+ **5. Автоматическая проверка прав доступа**
434
+
435
+ При запуске сервер автоматически проверяет права доступа ко всем директориям и файлам:
436
+
437
+ ```bash
438
+ # При запуске
439
+ npm start
440
+
441
+ # Вывод:
442
+ # 🔍 Проверка прав доступа к директориям и файлам...
443
+ # ✅ Все директории и файлы доступны для записи
444
+ ```
445
+
446
+ Если обнаружены проблемы:
447
+
448
+ ```bash
449
+ # ❌ Обнаружены проблемы с правами доступа (3):
450
+ # 📁 session/accounts (directory)
451
+ # Ошибка: EACCES: permission denied
452
+ # Решение:
453
+ # sudo chown -R $USER:$USER /path/to/session/accounts
454
+ # sudo chmod -R 755 /path/to/session/accounts
455
+ #
456
+ # 🔧 Быстрое решение:
457
+ # sudo chown -R $USER:$USER session uploads logs temp session_backup
458
+ # sudo chmod -R 755 session uploads logs temp session_backup
459
+ ```
460
+
461
+ **Ручная проверка и исправление:**
462
+
463
+ ```bash
464
+ # Проверить права
465
+ npm run check-permissions
466
+
467
+ # Автоматически исправить все проблемы
468
+ npm run fix-permissions
469
+
470
+ # Или вручную
471
+ bash fix-permissions.sh
472
+ ```
473
+
474
+ 📖 **Полная документация:** [PERMISSION_CHECKING.md](PERMISSION_CHECKING.md)
475
+
476
+ ---
477
+
478
+ ## Управление аккаунтами
479
+
480
+ ### Интерактивное меню
481
+
482
+ При запуске `npm start` без флага `SKIP_ACCOUNT_MENU` отображается меню с 4 пунктами:
483
+
484
+ | Пункт | Действие |
485
+ |-------|----------|
486
+ | 1 | Добавить новый аккаунт -- откроется браузер для входа |
487
+ | 2 | Перелогинить аккаунт -- обновить токен для аккаунта с истёкшей сессией |
488
+ | 3 | Запустить прокси -- стандартный запуск (по умолчанию) |
489
+ | 4 | Удалить аккаунт -- удалить сохранённый аккаунт |
490
+
491
+ ### Статусы аккаунтов
492
+
493
+ | Статус | Значение |
494
+ |--------|----------|
495
+ | OK | Аккаунт активен, токен валиден |
496
+ | WAIT | Rate limit -- ожидание сброса (автоматический таймер на 24ч) |
497
+ | INVALID | Токен истёк или отозван -- требуется перелогин |
498
+
499
+ ### Ротация аккаунтов
500
+
501
+ Если подключено несколько аккаунтов, сервер автоматически:
502
+ - Выбирает следующий активный аккаунт (round-robin)
503
+ - При получении HTTP 429 (rate limit) помечает аккаунт как WAIT и переключается на следующий
504
+ - При получении HTTP 401 (unauthorized) помечает аккаунт как INVALID и переключается на следующий
505
+
506
+ ### Отдельный CLI для авторизации
507
+
508
+ ```bash
509
+ npm run auth
510
+ ```
511
+
512
+ Запускает скрипт авторизации без запуска сервера -- удобно для Docker-окружения, когда нужно добавить аккаунты перед сборкой.
513
+
514
+ ### Файлы аккаунтов
515
+
516
+ ```
517
+ session/
518
+ ├── tokens.json # Реестр всех аккаунтов и их статусов
519
+ └── accounts/
520
+ ├── acc_1234567890/
521
+ │ └── token.txt # Токен аккаунта
522
+ └── acc_9876543210/
523
+ └── token.txt
524
+ ```
525
+
526
+ ---
527
+
528
+ ## Авторизация API-ключами
529
+
530
+ По умолчанию авторизация отключена -- API доступен всем. Для включения добавьте ключи в файл `src/Authorization.txt`:
531
+
532
+ ```
533
+ # Один ключ на строку
534
+ d35ab3e1-a6f9-4d00-b1c2-example-key1
535
+ f2b1cd9c-1b2e-4a99-8c3d-example-key2
536
+ ```
537
+
538
+ После этого каждый запрос к API должен содержать заголовок:
539
+
540
+ ```
541
+ Authorization: Bearer d35ab3e1-a6f9-4d00-b1c2-example-key1
542
+ ```
543
+
544
+ Пустые строки и строки, начинающиеся с `#`, игнорируются. Если файл пуст или содержит только комментарии -- авторизация отключена.
545
+
546
+ ---
547
+
548
+ ## Доступные модели
549
+
550
+ Прокси поддерживает **25+ моделей Qwen** через систему маппинга:
551
+
552
+ ### Стандартные модели
553
+ - `qwen-max` / `qwen-max-latest` — наиболее мощная модель
554
+ - `qwen-plus` / `qwen-plus-latest` — сбалансированная модель
555
+ - `qwen-turbo` / `qwen-turbo-latest` — быстрая и лёгкая модель
556
+
557
+ ### Модели Qwen 3.5 ✨
558
+ - `qwen3.5-plus` / `qwen3.5-plus-latest` — улучшенная версия Plus
559
+ - `qwen3.5-flash` / `qwen3.5-flash-latest` — быстрая модель Qwen 3.5
560
+ - `qwen3.5-397b-a17b` — сверхбольшая модель (397B параметров)
561
+ - `qwen3.5-122b-a10b` — большая модель (122B параметров)
562
+ - `qwen3.5-27b` — средняя модель (27B параметров)
563
+ - `qwen3.5-35b-a3b` — компактная модель (35B параметров)
564
+
565
+ ### Модели Qwen 3
566
+ - `qwen3` — базовая модель Qwen 3
567
+ - `qwen3-max` — максимальная модель Qwen 3
568
+ - `qwen3-plus` — сбалансированная модель Qwen 3
569
+ - `qwen3-omni-flash` — быстрая мультимодальная модель
570
+
571
+ ### Модели для кодинга
572
+ - `qwen3-coder-plus` — модель для программирования
573
+ - `qwen2.5-coder-32b-instruct` — кодирование (32B)
574
+ - `qwen2.5-coder-7b-instruct` — кодирование (7B)
575
+ - `qwen2.5-coder-3b-instruct` — кодирование (3B)
576
+ - `qwen2.5-coder-1.5b-instruct` — кодирование (1.5B)
577
+ - `qwen2.5-coder-0.5b-instruct` — кодирование (0.5B)
578
+
579
+ ### Визуальные модели
580
+ - `qwen-vl-max` / `qwen-vl-max-latest` — максимальная визуальная модель
581
+ - `qwen-vl-plus` / `qwen-vl-plus-latest` — сбалансированная визуальная модель
582
+ - `qwen2.5-vl-32b-instruct` — визуальная модель (32B)
583
+ - `qwen2.5-vl-7b-instruct` — визуальная модель (7B)
584
+
585
+ ### Другие модели
586
+ - `qvq-72b-preview-0310` — предпросмотр QVQ (72B)
587
+ - `qwen2.5-14b-instruct-1m` — контекст 1M токенов
588
+ - `qwen2.5-72b-instruct` — большая языковая модель (72B)
589
+
590
+ > **Система маппинга:** Прокси автоматически распознаёт алиасы моделей (например, `Qwen3.5-Plus`, `qwen3.5-flash-latest` → соответствующие канонические модели).
591
+
592
+ ### Система алиасов
593
+
594
+ Запрашивать модели можно по любому из поддерживаемых имён -- сервер автоматически подставит каноническое:
595
+
596
+ | Вы запрашиваете | Используется |
597
+ |-----------------|-------------|
598
+ | `qwen-max` | `qwen3-max` |
599
+ | `qwen-vl-plus` | `qwen3-vl-plus` |
600
+ | `qwen3-coder` | `qwen3-coder-plus` |
601
+ | `qwq` | `qwq-32b` |
602
+ | `qwen-turbo` | `qwen-turbo-2025-02-11` |
603
+ | `qwen2.5-max` | `qwen-max-latest` |
604
+ | `qwen2.5-plus` | `qwen-plus-2025-01-25` |
605
+ | `qvq` | `qvq-72b-preview-0310` |
606
+ | `qwen3` | `qwen3-235b-a22b` |
607
+ | `qwen-plus` | `qwen-plus-2025-09-11` |
608
+
609
+ > Если запрошенная модель не найдена ни в списке, ни среди алиасов -- используется активная модель из настроек бота (приоритет: `bot_settings.json` → `.env` → первая модель из `AvailableModels.txt`).
610
+
611
+ ### 🎯 Система выбора модели
612
+
613
+ Проект использует **динамическую систему выбора модели** с централизованным управлением через настройки бота.
614
+
615
+ #### Приоритет выбора модели
616
+
617
+ ```
618
+ 1. Запрошенная модель в запросе (параметр `model`) ← ВЫСШИЙ ПРИОРИТЕТ
619
+ ↓ (если не указана)
620
+ 2. bot_settings.json (activeModel) ← Устанавливается через /model в Telegram
621
+ ↓ (если не задана)
622
+ 3. .env файл (DEFAULT_MODEL)
623
+ ↓ (если не задана)
624
+ 4. AvailableModels.txt (первая модель) = "qwen3.5-plus"
625
+ ↓ (если файл недоступен)
626
+ 5. Fallback = "qwen3.5-plus" ← НИЗШИЙ ПРИОРИТЕТ
627
+ ```
628
+
629
+ #### Управление моделью
630
+
631
+ **Через Telegram бота:**
632
+ ```bash
633
+ # Установить модель
634
+ /model qwen3.5-plus
635
+
636
+ # Показать текущую модель
637
+ /model
638
+
639
+ # Сбросить на настройки по умолчанию
640
+ /clear
641
+ ```
642
+
643
+ **Через .env файл:**
644
+ ```bash
645
+ # В файле .env
646
+ DEFAULT_MODEL=qwen3.5-flash
647
+ ```
648
+
649
+ **Программно:**
650
+ ```javascript
651
+ // Модель берётся из настроек автоматически
652
+ const response = await fetch('http://localhost:3264/api/chat/completions', {
653
+ method: 'POST',
654
+ headers: { 'Content-Type': 'application/json' },
655
+ body: JSON.stringify({
656
+ // model можно не указывать - будет использована активная модель
657
+ messages: [{ role: 'user', content: 'Привет!' }]
658
+ })
659
+ });
660
+ ```
661
+
662
+ #### Файл настроек
663
+
664
+ Настройки хранятся в `session/bot_settings.json`:
665
+ ```json
666
+ {
667
+ "activeModel": "qwen3.5-plus",
668
+ "llmChatEnabled": true,
669
+ "lastUpdated": "2026-05-31T18:59:48.000Z"
670
+ }
671
+ ```
672
+
673
+ > **💡 Преимущество:** Изменение модели через Telegram бота применяется **мгновенно** без перезапуска сервиса!
674
+
675
+ ---
676
+
677
+ ---
678
+
679
+
680
+ ## API Reference
681
+
682
+ ### Основные эндпоинты
683
+
684
+ | Эндпоинт | Метод | Описание |
685
+ |----------|-------|----------|
686
+ | `/api/chat` | POST | Отправка сообщения с поддержкой `chatId` и `parentId` |
687
+ | `/api/chat/completions` | POST | OpenAI-совместимый эндпоинт, возвращает `chatId`/`parentId` |
688
+ | `/api/models` | GET | Получение списка доступных моделей |
689
+ | `/api/status` | GET | Проверка статуса авторизации и аккаунтов |
690
+ | `/api/chats` | POST | Создание нового чата на серверах Qwen |
691
+ | `/api/files/upload` | POST | Загрузка файла через multipart/form-data |
692
+ | `/api/files/getstsToken` | POST | Получение STS-токена для прямой загрузки |
693
+ | `/api/images/generations` | POST | Генерация изображений (DALL-E-совместимый) 🆕 |
694
+
695
+ **⚠️ Удалённые эндпоинты (v2):**
696
+ - `GET /api/chats` - список чатов
697
+ - `GET /api/chats/:chatId` - история чата
698
+ - `DELETE /api/chats/:chatId` - удаление чата
699
+ - `PUT /api/chats/:chatId/rename` - переименование
700
+ - `POST /api/chats/cleanup` - автоудаление
701
+
702
+ *Причина: чаты теперь управляются на серверах Qwen*
703
+
704
+ ### Выбор эндпоинтов
705
+
706
+ | Эндпоинт | Использование контекста | Формат запроса | Совместимость |
707
+ |----------|--------------------------|----------------|---------------|
708
+ | `/api/chat` | Контекст управляется через `chatId` + `parentId`. История хранится на серверах Qwen. | Упрощённый `message` + `chatId` + `parentId` | Нативный для прокси |
709
+ | `/api/chat/completions` | Поддерживает `chatId` + `parentId` в запросе. Возвращает их в ответе для продолжения. | Массив `messages` (OpenAI format) + опционально `chatId`/`parentId` | OpenAI SDK |
710
+
711
+
712
+ ### POST /api/chat
713
+
714
+ Нативный формат запроса. Поддерживает текст, составные сообщения с изображениями и system message.
715
+
716
+
717
+ ### Форматы запросов
718
+
719
+ #### 1. Упрощенный формат с параметром `message`
720
+
721
+ ```json
722
+ {
723
+ "message": "Текст сообщения",
724
+ "model": "qwen3.5-plus", // Optional - uses active model from settings
725
+ "chatId": "идентификатор_чата",
726
+ "parentId": "response_id_из_предыдущего_ответа"
727
+ }
728
+ ```
729
+
730
+ #### 2. Формат, совместимый с OpenAI API
731
+
732
+ ```json
733
+ {
734
+ "messages": [
735
+ {"role": "user", "content": "Привет, как дела?"}
736
+ ],
737
+ "model": "qwen3.5-plus", // Optional - uses active model from settings
738
+ "chatId": "идентификатор_чата",
739
+ "parentId": "response_id_из_предыдущего_ответа"
740
+ }
741
+ ```
742
+
743
+ ### Работа с контекстом (API v2)
744
+
745
+ **Новая система:**
746
+ - История хранится на серверах Qwen, не локально
747
+ - Контекст управляется через `chatId` + `parentId`
748
+ - `parentId` - это `response_id` из предыдущего ответа
749
+
750
+ **Пример диалога:**
751
+
752
+ ```javascript
753
+ // 1. Первое сообщение
754
+ const res1 = await fetch('/api/chat', {
755
+ method: 'POST',
756
+ body: JSON.stringify({ message: "Сколько будет 2+2?" })
757
+ });
758
+ const data1 = await res1.json();
759
+ // Ответ: { chatId: "abc-123", parentId: "xyz-789", ... }
760
+
761
+ // 2. Второе сообщение (с контекстом)
762
+ const res2 = await fetch('/api/chat', {
763
+ method: 'POST',
764
+ body: JSON.stringify({
765
+ message: "А результат плюс 3?",
766
+ chatId: data1.chatId, // Тот же чат
767
+ parentId: data1.parentId // Из предыдущего ответа!
768
+ })
769
+ });
770
+ // Модель помнит контекст и ответит "7"
771
+ ```
772
+
773
+ ### Системные инструкции (System Messages)
774
+
775
+ **Новое в v2:** Поддержка системных сообщений для настройки поведения модели!
776
+
777
+ Системные инструкции передаются через поле `role: "system"` в массиве `messages`. Это позволяет задать модели контекст, стиль общения, правила поведения и т.д.
778
+
779
+ **Пример:**
780
+
781
+ ```javascript
782
+ // Запрос с системной инструкцией
783
+ const response = await fetch('/api/chat/', {
784
+ method: 'POST',
785
+ headers: { 'Content-Type': 'application/json' },
786
+ body: JSON.stringify({
787
+ messages: [
788
+ {
789
+ role: "system",
790
+ content: "Ты - опытный программист на Python. Отвечай кратко и предоставляй примеры кода."
791
+ },
792
+ {
793
+ role: "user",
794
+ content: "Как отсортировать список в Python?"
795
+ }
796
+ ],
797
+ model: "qwen3.5-plus" // Optional - uses active model from settings
798
+ })
799
+ });
800
+ ```
801
+
802
+ **Как работает:**
803
+ - `system` message извлекается из массива и передаётся отдельным параметром в Qwen API v2
804
+ - Может использоваться в обоих эндпоинтах: `/api/chat` и `/api/chat/completions`
805
+ - System message применяется ко всему чату и влияет на все последующие ответы
806
+
807
+ **Примеры использования:**
808
+
809
+ ```json
810
+ // 1. Ролевая инструкция
811
+ {
812
+ "messages": [
813
+ {"role": "system", "content": "Ты - эксперт по машинному обучению"},
814
+ {"role": "user", "content": "Объясни, что такое градиентный спуск"}
815
+ ]
816
+ }
817
+
818
+ // 2. Стиль ответов
819
+ {
820
+ "messages": [
821
+ {"role": "system", "content": "Отвечай как пират"},
822
+ {"role": "user", "content": "Как дела?"}
823
+ ]
824
+ }
825
+
826
+ // 3. Формат вывода
827
+ {
828
+ "messages": [
829
+ {"role": "system", "content": "Всегда отвечай в формате JSON"},
830
+ {"role": "user", "content": "Дай информацию о Python"}
831
+ ]
832
+ }
833
+ ```
834
+
835
+ ### Работа с изображениями
836
+
837
+ Прокси поддерживает отправку сообщений с изображениями:
838
+
839
+ #### Формат `message` с изображением
840
+
841
+ ```json
842
+ {
843
+ "message": [
844
+ {
845
+ "type": "text",
846
+ "text": "Опишите объекты на этом изображении"
847
+ },
848
+ {
849
+ "type": "image",
850
+ "image": "URL_ИЗОБРАЖЕНИЯ"
851
+ }
852
+ ],
853
+ "model": "qwen-vl-max",
854
+ "chatId": "идентификатор_чата",
855
+ "parentId": "response_id"
856
+ }
857
+ ```
858
+
859
+ ### Загрузка файлов
860
+
861
+ #### Загрузка изображения
862
+
863
+ ```
864
+ POST http://localhost:3264/api/files/upload
865
+ ```
866
+
867
+ **Формат запроса:** `multipart/form-data`
868
+
869
+ **Параметры:**
870
+
871
+ - `file` - файл изображения (поддерживаются форматы: jpg, jpeg, png, gif, webp)
872
+
873
+ **Пример использования с curl:**
874
+
875
+ ```bash
876
+ curl -X POST http://localhost:3264/api/files/upload \
877
+ -F "file=@/путь/к/изображению.jpg"
878
+ ```
879
+
880
+ **Пример ответа:**
881
+
882
+ ```json
883
+ {
884
+ "imageUrl": "https://cdn.qwenlm.ai/user-id/file-id_filename.jpg?key=..."
885
+ }
886
+ ```
887
+
888
+ #### Получение URL изображения
889
+
890
+ Для отправки изображений через API прокси необходимо сначала получить URL изображения. Это можно сделать двумя способами:
891
+
892
+ ##### Способ 1: Загрузка через API прокси
893
+
894
+ Отправьте POST запрос на эндпоинт `/api/files/upload` для загрузки изображения, как описано выше.
895
+
896
+ ##### Способ 2: Получение URL через веб-интерфейс Qwen
897
+
898
+ 1. Загрузите изображение в официальном веб-интерфейсе Qwen (<https://chat.qwen.ai/>)
899
+ 2. Откройте инструменты разработчика в браузере (F12 или Ctrl+Shift+I)
900
+ 3. Перейдите на вкладку "Network" (Сеть)
901
+ 4. Найдите запрос к API Qwen, содержащий ваше изображение (обычно это запрос GetsToken)
902
+ 5. В теле запроса найдите URL изображения, который выглядит примерно так: `https://cdn.qwenlm.ai/user-id/file-id_filename.jpg?key=...`
903
+ 6. Скопируйте этот URL для использования в вашем API-запросе
904
+
905
+ ### Управление диалогами
906
+
907
+ #### Создание нового диалога
908
+
909
+ ```
910
+ POST http://localhost:3264/api/chats
911
+ ```
912
+
913
+ **Тело запроса:**
914
+
915
+ ```json
916
+ {
917
+ "name": "Название диалога"
918
+ }
919
+ ```
920
+
921
+ **Ответ:**
922
+
923
+ ```json
924
+ {
925
+ "id": "chatcmpl-1739012345678",
926
+ "object": "chat.completion",
927
+ "created": 1739012345,
928
+ "model": "qwen3.5-plus", // Or whatever model was used
929
+ "choices": [
930
+ {
931
+ "index": 0,
932
+ "message": {
933
+ "role": "assistant",
934
+ "content": "Квантовые вычисления — это тип вычислений, основанный на принципах квантовой механики..."
935
+ },
936
+ "finish_reason": "stop"
937
+ }
938
+ ],
939
+ "usage": {
940
+ "prompt_tokens": 12,
941
+ "completion_tokens": 156,
942
+ "total_tokens": 168
943
+ },
944
+ "chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
945
+ "parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
946
+ }
947
+ ```
948
+
949
+ #### Продолжение диалога (с контекстом)
950
+
951
+ Используйте `chatId` и `parentId` из предыдущего ответа:
952
+
953
+ ```bash
954
+ curl -X POST http://localhost:3264/api/chat \
955
+ -H "Content-Type: application/json" \
956
+ -d '{
957
+ "message": "Приведи практические примеры",
958
+ "model": "qwen3.5-plus", // Or whatever model was used
959
+ "chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
960
+ "parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
961
+ }'
962
+ ```
963
+
964
+ #### С system message через массив messages
965
+
966
+ ```bash
967
+ curl -X POST http://localhost:3264/api/chat \
968
+ -H "Content-Type: application/json" \
969
+ -d '{
970
+ "messages": [
971
+ {"role": "system", "content": "Ты -- опытный Python-разработчик. Отвечай кратко, с примерами кода."},
972
+ {"role": "user", "content": "Как отсортировать словарь по значениям?"}
973
+ ],
974
+ "model": "qwen-max-latest"
975
+ }'
976
+ ```
977
+
978
+ #### С изображением
979
+
980
+ ```bash
981
+ curl -X POST http://localhost:3264/api/chat \
982
+ -H "Content-Type: application/json" \
983
+ -d '{
984
+ "message": [
985
+ {"type": "text", "text": "Что изображено на этой картинке?"},
986
+ {"type": "image", "image": "https://example-oss-url.com/uploaded-image.png"}
987
+ ],
988
+ "model": "qwen3-vl-plus"
989
+ }'
990
+ ```
991
+
992
+ ---
993
+
994
+ ### POST /api/chat/completions
995
+
996
+ OpenAI-совместимый формат. Используйте этот эндпоинт, если работаете с OpenAI SDK или любым инструментом, поддерживающим OpenAI API.
997
+
998
+ #### Обычный запрос (без streaming)
999
+
1000
+ **Запрос:**
1001
+
1002
+ ```bash
1003
+ curl -X POST http://localhost:3264/api/chat/completions \
1004
+ -H "Content-Type: application/json" \
1005
+ -d '{
1006
+ "model": "qwen3.5-plus", // Or whatever model was used
1007
+ "messages": [
1008
+ {"role": "system", "content": "Отвечай кратко и по существу."},
1009
+ {"role": "user", "content": "Столица Японии?"}
1010
+ ]
1011
+ }'
1012
+ ```
1013
+
1014
+ **Ответ:**
1015
+
1016
+ ```json
1017
+ {
1018
+ "id": "chatcmpl-1739012345678",
1019
+ "object": "chat.completion",
1020
+ "created": 1739012345,
1021
+ "model": "qwen3.5-plus", // Or whatever model was used
1022
+ "choices": [
1023
+ {
1024
+ "index": 0,
1025
+ "message": {
1026
+ "role": "assistant",
1027
+ "content": "Токио."
1028
+ },
1029
+ "finish_reason": "stop"
1030
+ }
1031
+ ],
1032
+ "chatId": "abcd-1234-5678",
1033
+ "parentId": "efgh-5678-9012"
1034
+ }
1035
+ ```
1036
+
1037
+ **Последующие запросы** (с указанием полученного `chatId`):
1038
+
1039
+ ```json
1040
+ {
1041
+ "model": "qwen3.5-plus", // Or whatever model was used
1042
+ "messages": [
1043
+ {"role": "user", "content": "Сколько будет 2+2?"}
1044
+ ],
1045
+ "chatId": "abcd-1234-5678",
1046
+ "parentId": "efgh-5678-9012"
1047
+ }
1048
+ ```
1049
+
1050
+ ---
1051
+
1052
+ ## 🔌 Совместимость с OpenAI API
1053
+
1054
+ Прокси поддерживает эндпоинт, совместимый с OpenAI API для подключения клиентов, которые работают с OpenAI API:
1055
+
1056
+ ```
1057
+ POST /api/chat/completions
1058
+ ```
1059
+
1060
+ ### Behavior
1061
+
1062
+ 1. **Isolated by default:** if `chatId` is omitted and `conversation_id` is not provided, the proxy does not restore global session context (IP + User-Agent), so chats do not leak into each other.
1063
+
1064
+ 2. **Conversation-aware routing:** if `conversation_id`/`chat_id` is provided, the proxy keeps context inside that scoped conversation.
1065
+
1066
+ 3. **Legacy global restore is optional:** set `ALLOW_UNSCOPED_SESSION_CHAT_RESTORE=true` to return to old behavior (restore by IP + User-Agent when ids are omitted).
1067
+
1068
+ 4. **Both id formats are supported:** `chatId`/`parentId` and `chat_id`/`parent_id`.
1069
+
1070
+ 5. **Force a fresh chat:** send `newChat: true` or `new_chat: true`.
1071
+
1072
+ 6. **System messages are supported:** `role: "system"` is passed through to the upstream model.
1073
+
1074
+ 7. **Strict JSON parsing:** invalid JSON (for example, single quotes instead of double quotes) returns `400 Invalid JSON`.
1075
+
1076
+ 8. **Method check:** `GET /api/chat/completions` returns `405`; use `POST`.
1077
+
1078
+ **System message request example:**
1079
+
1080
+ ```json
1081
+ {
1082
+ "messages": [
1083
+ {"role": "system", "content": "Ты эксперт по JavaScript. Отвечай только на вопросы о JavaScript."},
1084
+ {"role": "user", "content": "Как создать класс в JavaScript?"}
1085
+ ],
1086
+ "model": "qwen-max-latest"
1087
+ }
1088
+ ```
1089
+
1090
+ ### Поддержка streaming режима
1091
+
1092
+ Прокси поддерживает режим потоковой передачи ответов (streaming), что позволяет получать ответы по частям в режиме реального времени. Стриминг доступен в обоих эндпоинтах:
1093
+
1094
+ #### Эндпоинт `/api/chat/completions` (OpenAI-совместимый)
1095
+
1096
+ ```json
1097
+ {
1098
+ "messages": [
1099
+ {"role": "user", "content": "Напиши длинный рассказ о космосе"}
1100
+ ],
1101
+ "model": "qwen3.5-plus", // Or whatever model was used
1102
+ "stream": true
1103
+ }
1104
+ ```
1105
+
1106
+ #### Эндпоинт `/api/chat` (нативный)
1107
+
1108
+ ```json
1109
+ {
1110
+ "message": "Напиши длинный рассказ о космосе",
1111
+ "model": "qwen3.5-plus", // Or whatever model was used
1112
+ "stream": true
1113
+ }
1114
+ ```
1115
+
1116
+ При использовании streaming режима, ответ будет возвращаться постепенно в формате Server-Sent Events (SSE), совместимом с OpenAI API.
1117
+
1118
+ ### 🔥 Поддержка OpenWebUI
1119
+
1120
+ Прокси полностью поддерживает работу с **OpenWebUI** через streaming режим:
1121
+
1122
+ 1. **Настройка подключения в OpenWebUI:**
1123
+ - Base URL: `http://localhost:3264/api`
1124
+ - API Key: любой (или оставьте пустым, если файл `Authorization.txt` пустой)
1125
+
1126
+ 2. **Формат запроса для OpenWebUI:**
1127
+
1128
+ ```json
1129
+ {
1130
+ "messages": [
1131
+ {"role": "user", "content": "Привет!"}
1132
+ ],
1133
+ "model": "qwen3.5-plus", // Or whatever model was used
1134
+ "stream": true
1135
+ }
1136
+ ```
1137
+
1138
+ 3. **Изоляция чатов по умолчанию:** без `conversation_id`/`chatId` прокси не восстанавливает общий контекст по IP + User-Agent, чтобы исключить «память» между разными чатами.
1139
+
1140
+ 4. **Scoped-контекст для OpenWebUI:** если OpenWebUI передаёт `conversation_id` (или `chat_id`), контекст продолжается внутри этого конкретного диалога.
1141
+
1142
+ 5. **Legacy fallback при необходимости:** можно вернуть старое поведение через `ALLOW_UNSCOPED_SESSION_CHAT_RESTORE=true`.
1143
+
1144
+ 6. **Поддержка всех эндпоинтов:**
1145
+ - `/api/chat/completions` — OpenAI-совместимый эндпоинт
1146
+ - `/api/v1/chat/completions` — альтернативный OpenAI-совместимый эндпоинт
1147
+ - `/api/chat` — нативный эндпоинт прокси
1148
+
1149
+ 7. **Генерация изображений:** Через OpenWebUI можно использовать генерацию изображений через эндпоинт `/api/images/generations` (DALL-E-совместимый API).
1150
+
1151
+ ---
1152
+
1153
+ ### 🎨 Генерация изображений
1154
+
1155
+ Прокси поддерживает генерацию изображений через Qwen Image API:
1156
+
1157
+ **Эндпоинт:** `POST /api/images/generations`
1158
+
1159
+ ```json
1160
+ {
1161
+ "prompt": "Космический корабль на фоне туманности",
1162
+ "model": "qwen-image-plus",
1163
+ "n": 1,
1164
+ "size": "1024x1024"
1165
+ }
1166
+ ```
1167
+
1168
+ **Ответ:**
1169
+
1170
+ ```json
1171
+ {
1172
+ "created": 1234567890,
1173
+ "data": [
1174
+ {
1175
+ "url": "https://example.com/generated-image.png",
1176
+ "revised_prompt": "Космический корабль на фоне туманности"
1177
+ }
1178
+ ]
1179
+ }
1180
+ ```
1181
+
1182
+ **Параметры:**
1183
+ - `prompt` (обязательный) — текстовое описание изображения
1184
+ - `model` — модель генерации (`qwen-image-plus`, `qwen-image-turbo`)
1185
+ - `n` — количество изображений (по умолчанию 1)
1186
+ - `size` — размер (`1024x1024`, `1024x1792`, `1792x1024`, `512x512`, `768x768`, `960x960`)
1187
+
1188
+ > **Требуется API-ключ:** Для генерации изображений необходимо установить переменную окружения `DASHSCOPE_API_KEY`.
1189
+
1190
+ ### Примеры использования с OpenAI SDK
1191
+
1192
+ ```bash
1193
+ curl -X POST http://localhost:3264/api/chat/completions \
1194
+ -H "Content-Type: application/json" \
1195
+ -d '{
1196
+ "model": "qwen3.5-plus", // Or whatever model was used
1197
+ "messages": [
1198
+ {"role": "user", "content": "Напиши хайку о программировании"}
1199
+ ],
1200
+ "stream": true
1201
+ }'
1202
+ ```
1203
+
1204
+ **Ответ (SSE):**
1205
+
1206
+ ```
1207
+ data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
1208
+
1209
+ data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"content":"Строки кода бегут"},"finish_reason":null}]}
1210
+
1211
+ data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"content":" —\nБаг затаился в ветвях"},"finish_reason":null}]}
1212
+
1213
+ data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
1214
+
1215
+ data: [DONE]
1216
+ ```
1217
+
1218
+ #### С продолжением диалога
1219
+
1220
+ ```bash
1221
+ curl -X POST http://localhost:3264/api/chat/completions \
1222
+ -H "Content-Type: application/json" \
1223
+ -d '{
1224
+ "model": "qwen3.5-plus", // Or whatever model was used
1225
+ "messages": [
1226
+ {"role": "user", "content": "Теперь на тему космоса"}
1227
+ ],
1228
+ "chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
1229
+ "parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
1230
+ }'
1231
+ ```
1232
+
1233
+ ---
1234
+
1235
+ ### GET /api/models
1236
+
1237
+ Возвращает список доступных моделей в формате OpenAI.
1238
+
1239
+ **Запрос:**
1240
+
1241
+ ```bash
1242
+ curl http://localhost:3264/api/models
1243
+ ```
1244
+
1245
+ **Ответ:**
1246
+
1247
+ ```json
1248
+ {
1249
+ "object": "list",
1250
+ "data": [
1251
+ {"id": "qwen3-max", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
1252
+ {"id": "qwen3-vl-plus", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
1253
+ {"id": "qwen3-coder-plus", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
1254
+ {"id": "qwq-32b", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
1255
+ {"id": "qwen-max-latest", "object": "model", "created": 0, "owned_by": "qwen", "permission": []}
1256
+ ]
1257
+ }
1258
+ ```
1259
+
1260
+ > Полный список поддерживаемых моделей -- см. раздел [Доступные модели](#доступные-модели).
1261
+
1262
+ ---
1263
+
1264
+ ### GET /api/status
1265
+
1266
+ Проверяет статус авторизации и состояние всех аккаунтов. Для каждого аккаунта выполняется тестовый запрос к Qwen API.
1267
+
1268
+ **Запрос:**
1269
+
1270
+ ```bash
1271
+ curl http://localhost:3264/api/status
1272
+ ```
1273
+
1274
+ **Ответ:**
1275
+
1276
+ ```json
1277
+ {
1278
+ "authenticated": true,
1279
+ "message": "Авторизация активна",
1280
+ "accounts": [
1281
+ {"id": "acc_1739012345678", "status": "OK", "resetAt": null},
1282
+ {"id": "acc_1739098765432", "status": "WAIT", "resetAt": "2026-02-17T12:00:00.000Z"},
1283
+ {"id": "acc_1739055555555", "status": "INVALID", "resetAt": null}
1284
+ ]
1285
+ }
1286
+ ```
1287
+
1288
+ | Поле | Описание |
1289
+ |------|----------|
1290
+ | `authenticated` | `true`, если хотя бы один аккаунт активен |
1291
+ | `accounts[].status` | `OK` -- активен, `WAIT` -- rate limit, `INVALID` -- токен недействителен |
1292
+ | `accounts[].resetAt` | Время, после которого аккаунт станет доступен (для WAIT) |
1293
+
1294
+ ---
1295
+
1296
+ ### POST /api/chats
1297
+
1298
+ Создаёт новый чат на серверах Qwen. Возвращает `chatId`, который можно использовать для ведения диалога с сохранением истории.
1299
+
1300
+ **Запрос:**
1301
+
1302
+ ```bash
1303
+ curl -X POST http://localhost:3264/api/chats \
1304
+ -H "Content-Type: application/json" \
1305
+ -d '{
1306
+ "name": "Обсуждение архитектуры",
1307
+ "model": "qwen-max-latest"
1308
+ }'
1309
+ ```
1310
+
1311
+ **Ответ:**
1312
+
1313
+ ```json
1314
+ {
1315
+ "chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
1316
+ "success": true
1317
+ }
1318
+ ```
1319
+
1320
+ ---
1321
+
1322
+ ### POST /api/files/upload
1323
+
1324
+ Загружает файл через сервер в Qwen OSS. Поддерживаемые типы: изображения (jpg, png, gif, webp, bmp), документы (pdf, doc, docx, txt) и прочие файлы. Максимальный размер -- 10 МБ (настраивается через `MAX_FILE_SIZE`).
1325
+
1326
+ **Запрос:**
1327
+
1328
+ ```bash
1329
+ curl -X POST http://localhost:3264/api/files/upload \
1330
+ -F "file=@/path/to/image.png"
1331
+ ```
1332
+
1333
+ **Ответ:**
1334
+
1335
+ ```json
1336
+ {
1337
+ "success": true,
1338
+ "file": {
1339
+ "name": "image.png",
1340
+ "url": "https://oss-bucket.aliyuncs.com/path/to/uploaded-image.png",
1341
+ "size": 245760,
1342
+ "type": "image/png"
1343
+ }
1344
+ }
1345
+ ```
1346
+
1347
+ Полученный `url` можно использовать в запросе к `/api/chat` с составным сообщением (см. [Работа с изображениями](#работа-с-изображениями)).
1348
+
1349
+ ---
1350
+
1351
+ ### POST /api/files/getstsToken
1352
+
1353
+ Возвращает STS-токен для прямой загрузки файла в Qwen OSS из клиентского кода. Для большинства случаев удобнее использовать `/api/files/upload`.
1354
+
1355
+ **Запрос:**
1356
+
1357
+ ```bash
1358
+ curl -X POST http://localhost:3264/api/files/getstsToken \
1359
+ -H "Content-Type: application/json" \
1360
+ -d '{
1361
+ "filename": "document.pdf",
1362
+ "filesize": 102400,
1363
+ "filetype": "document"
1364
+ }'
1365
+ ```
1366
+
1367
+ **Ответ:**
1368
+
1369
+ ```json
1370
+ {
1371
+ "access_key_id": "STS.xxxxx",
1372
+ "access_key_secret": "xxxxx",
1373
+ "security_token": "CAISxxxxx...",
1374
+ "region": "oss-cn-beijing",
1375
+ "bucketname": "qwen-upload-bucket",
1376
+ "file_path": "uploads/2026/02/16/document.pdf",
1377
+ "file_url": "https://qwen-upload-bucket.oss-cn-beijing.aliyuncs.com/uploads/...",
1378
+ "file_id": "file-abc123"
1379
+ }
1380
+ ```
1381
+
1382
+ | Поле | Описание |
1383
+ |------|----------|
1384
+ | `filetype` | Тип файла: `image` (jpg, png, gif, webp, bmp), `document` (pdf, doc, docx, txt) или `file` |
1385
+
1386
+ ---
1387
+
1388
+ ### POST /api/images/generations 🆕
1389
+
1390
+ Генерация изображений через Qwen Image API + DashScope API. DALL-E-совместимый интерфейс.
1391
+
1392
+ **Поддерживаемые режимы:**
1393
+ - **Text-to-Image**: Генерация изображения из текстового описания
1394
+ - **Image-to-Image**: Трансформация загруженного изображения по описанию
1395
+
1396
+ #### Text-to-Image
1397
+
1398
+ **Запрос:**
1399
+
1400
+ ```bash
1401
+ curl -X POST http://localhost:3264/api/images/generations \
1402
+ -H "Content-Type: application/json" \
1403
+ -d '{
1404
+ "prompt": "Космический корабль на фоне туманности, цифровое искусство",
1405
+ "model": "qwen-image-plus",
1406
+ "n": 1,
1407
+ "size": "1024x1024"
1408
+ }'
1409
+ ```
1410
+
1411
+ **Ответ:**
1412
+
1413
+ ```json
1414
+ {
1415
+ "created": 1234567890,
1416
+ "data": [
1417
+ {
1418
+ "url": "https://example.com/generated-image.png",
1419
+ "revised_prompt": "Космический корабль на фоне туманности, цифровое искусство"
1420
+ }
1421
+ ]
1422
+ }
1423
+ ```
1424
+
1425
+ #### Image-to-Image
1426
+
1427
+ **Запрос:**
1428
+
1429
+ ```bash
1430
+ # Сначала загружаем изображение
1431
+ curl -X POST http://localhost:3264/api/files/upload \
1432
+ -F "file=@photo.jpg"
1433
+
1434
+ # Получаем URL и используем для генерации
1435
+ curl -X POST http://localhost:3264/api/images/generations \
1436
+ -H "Content-Type: application/json" \
1437
+ -d '{
1438
+ "prompt": "Сделай изображение в стиле импрессионизма",
1439
+ "image_url": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg",
1440
+ "model": "qwen-image-plus",
1441
+ "n": 1,
1442
+ "size": "1024x1024"
1443
+ }'
1444
+ ```
1445
+
1446
+ **Параметры:**
1447
+
1448
+ | Параметр | Тип | Обязательный | Описание |
1449
+ |----------|------|-------------|----------|
1450
+ | `prompt` | string | ✅ | Текстовое описание желаемого изображения |
1451
+ | `model` | string | ❌ | Модель генерации (`qwen-image-plus`, `qwen-image-turbo`) |
1452
+ | `n` | integer | ❌ | Количество изображений (по умолчанию 1) |
1453
+ | `size` | string | ❌ | Размер: `1024x1024`, `1024x1792`, `1792x1024`, `512x512`, `768x768`, `960x960` |
1454
+ | `image_url` | string | ❌ | URL исходного изображения для image-to-image |
1455
+
1456
+ > **⚠️ Требуется API-ключ:** Для генерации изображений необходимо установить переменную окружения `DASHSCOPE_API_KEY`.
1457
+
1458
+ #### Генерация через Telegram бота
1459
+
1460
+ **Text-to-Image:**
1461
+ ```
1462
+ /imagens Космический корабль на фоне туманности
1463
+ ```
1464
+
1465
+ **Image-to-Image:**
1466
+ 1. Отправьте фото боту
1467
+ 2. Добавьте подпись с описанием желаемого результата
1468
+ 3. Бот автоматически сгенерирует новое изображение
1469
+
1470
+ > 📖 **Подробная документация:** [docs/IMAGE_GENERATION.md](docs/IMAGE_GENERATION.md), [docs/IMAGE_GENERATION_MODES.md](docs/IMAGE_GENERATION_MODES.md)
1471
+
1472
+ ---
1473
+
1474
+ ## Работа с контекстом (API v2)
1475
+
1476
+ API использует серверную историю чатов Qwen. Каждый ответ содержит `chatId` и `parentId`, которые нужно передать в следующий запрос для продолжения диалога.
1477
+
1478
+ ### Как это работает
1479
+
1480
+ ```
1481
+ 1-й запрос (без chatId) ──> Ответ с chatId="abc", parentId="def"
1482
+
1483
+ 2-й запрос (chatId="abc", parentId="def") ──> Ответ с parentId="ghi"
1484
+
1485
+ 3-й запрос (chatId="abc", parentId="ghi") ──> Ответ с parentId="jkl"
1486
+ ```
1487
+
1488
+ ### Полный пример диалога
1489
+
1490
+ **Шаг 1 -- первое сообщение:**
1491
+
1492
+ ```bash
1493
+ curl -X POST http://localhost:3264/api/chat/completions \
1494
+ -H "Content-Type: application/json" \
1495
+ -d '{
1496
+ "model": "qwen3.5-plus", // Or whatever model was used
1497
+ "messages": [{"role": "user", "content": "Что такое Docker?"}]
1498
+ }'
1499
+ ```
1500
+
1501
+ ```json
1502
+ {
1503
+ "id": "chatcmpl-1739012345678",
1504
+ "choices": [{"index": 0, "message": {"role": "assistant", "content": "Docker — это платформа для контейнеризации приложений..."}, "finish_reason": "stop"}],
1505
+ "chatId": "abc-123",
1506
+ "parentId": "def-456"
1507
+ }
1508
+ ```
1509
+
1510
+ **Шаг 2 -- продолжение (модель помнит контекст):**
1511
+
1512
+ ```bash
1513
+ curl -X POST http://localhost:3264/api/chat/completions \
1514
+ -H "Content-Type: application/json" \
1515
+ -d '{
1516
+ "model": "qwen3.5-plus", // Or whatever model was used
1517
+ "messages": [{"role": "user", "content": "Чем он отличается от виртуальных машин?"}],
1518
+ "chatId": "abc-123",
1519
+ "parentId": "def-456"
1520
+ }'
1521
+ ```
1522
+
1523
+ ```json
1524
+ {
1525
+ "id": "chatcmpl-1739012345679",
1526
+ "choices": [{"index": 0, "message": {"role": "assistant", "content": "Основные отличия Docker от виртуальных машин:\n1. Docker использует ядро хост-системы, а ВМ — полное гостевое ядро..."}, "finish_reason": "stop"}],
1527
+ "chatId": "abc-123",
1528
+ "parentId": "ghi-789"
1529
+ }
1530
+ ```
1531
+
1532
+ **Шаг 3 -- ещё одно сообщение в том же диалоге:**
1533
+
1534
+ ```bash
1535
+ curl -X POST http://localhost:3264/api/chat/completions \
1536
+ -H "Content-Type: application/json" \
1537
+ -d '{
1538
+ "model": "qwen3.5-plus", // Or whatever model was used
1539
+ "messages": [{"role": "user", "content": "Покажи пример Dockerfile для Node.js"}],
1540
+ "chatId": "abc-123",
1541
+ "parentId": "ghi-789"
1542
+ }'
1543
+ ```
1544
+
1545
+ > Обратите внимание: `parentId` каждый раз берётся из **предыдущего** ответа, а `chatId` остаётся одним и тем же на протяжении всего диалога.
1546
+
1547
+ ### Предварительное создание чата
1548
+
1549
+ Можно создать чат заранее через `POST /api/chats` и использовать полученный `chatId` с первого сообщения. Это удобно, если вы хотите задать имя чату.
1550
+
1551
+ ---
1552
+
1553
+ ## Работа с изображениями
1554
+
1555
+ Для анализа изображений используйте модели с поддержкой vision: `qwen3-vl-plus`, `qwen2.5-vl-32b-instruct`, `qvq-72b-preview-0310`, `qwen2.5-omni-7b`.
1556
+
1557
+ ### Полный flow: загрузка + анализ
1558
+
1559
+ **Шаг 1 -- загрузить изображение:**
1560
+
1561
+ ```bash
1562
+ curl -X POST http://localhost:3264/api/files/upload \
1563
+ -F "file=@photo.jpg"
1564
+ ```
1565
+
1566
+ ```json
1567
+ {
1568
+ "success": true,
1569
+ "file": {
1570
+ "name": "photo.jpg",
1571
+ "url": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg",
1572
+ "size": 184320,
1573
+ "type": "image/jpeg"
1574
+ }
1575
+ }
1576
+ ```
1577
+
1578
+ **Шаг 2 -- отправить запрос с изображением:**
1579
+
1580
+ ```bash
1581
+ curl -X POST http://localhost:3264/api/chat \
1582
+ -H "Content-Type: application/json" \
1583
+ -d '{
1584
+ "message": [
1585
+ {"type": "text", "text": "Опиши, что изображено на фото. Какие объекты ты видишь?"},
1586
+ {"type": "image", "image": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg"}
1587
+ ],
1588
+ "model": "qwen3-vl-plus"
1589
+ }'
1590
+ ```
1591
+
1592
+ ### Формат составного сообщения
1593
+
1594
+ Поле `message` принимает массив объектов:
1595
+
1596
+ ```json
1597
+ [
1598
+ {"type": "text", "text": "Ваш вопрос к изображению"},
1599
+ {"type": "image", "image": "https://url-to-uploaded-image.com/image.png"}
1600
+ ]
1601
+ ```
1602
+
1603
+ ---
1604
+
1605
+ ## Генерация изображений 🆕
1606
+
1607
+ Проект поддерживает генерацию изображений через **двойной бэкенд**: Qwen Image API + DashScope API.
1608
+
1609
+ ### 🎯 Режимы генерации
1610
+
1611
+ #### 1. Text-to-Image (Текст → Изображение)
1612
+
1613
+ Генерация изображения из текстового описания:
1614
+
1615
+ **Через API:**
1616
+ ```bash
1617
+ curl -X POST http://localhost:3264/api/images/generations \
1618
+ -H "Content-Type: application/json" \
1619
+ -d '{
1620
+ "prompt": "Красивый закат над океаном, фотореалистично",
1621
+ "model": "qwen-image-plus",
1622
+ "n": 1,
1623
+ "size": "1024x1024"
1624
+ }'
1625
+ ```
1626
+
1627
+ **Через Telegram бота:**
1628
+ ```
1629
+ /imagens Красивый закат над океаном, фотореалистично
1630
+ ```
1631
+
1632
+ #### 2. Image-to-Image (Изображение → Изображение)
1633
+
1634
+ Трансформация загруженного изображения по описанию:
1635
+
1636
+ **Через API:**
1637
+ ```bash
1638
+ # 1. Загружаем изображение
1639
+ curl -X POST http://localhost:3264/api/files/upload \
1640
+ -F "file=@photo.jpg"
1641
+
1642
+ # 2. Генерируем на основе загруженного
1643
+ curl -X POST http://localhost:3264/api/images/generations \
1644
+ -H "Content-Type: application/json" \
1645
+ -d '{
1646
+ "prompt": "Сделай в стиле аниме",
1647
+ "image_url": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg",
1648
+ "model": "qwen-image-plus",
1649
+ "n": 1
1650
+ }'
1651
+ ```
1652
+
1653
+ **Через Telegram бота:**
1654
+ 1. Отправьте фото боту
1655
+ 2. Добавьте подпись: "Сделай в стиле аниме"
1656
+ 3. Бот автоматически сгенерирует новое изображение
1657
+
1658
+ ### 🛠 Доступные модели
1659
+
1660
+ | Модель | Описание | Скорость | Качество |
1661
+ |--------|----------|----------|----------|
1662
+ | `qwen-image-plus` | Высокое качество | Средняя | Отличное |
1663
+ | `qwen-image-turbo` | Быстрая генерация | Быстрая | Хорошее |
1664
+
1665
+ ### 📐 Поддерживаемые размеры
1666
+
1667
+ - `1024x1024` — квадрат (по умолчанию)
1668
+ - `1024x1792` — портретный
1669
+ - `1792x1024` — ландшафтный
1670
+ - `512x512` — маленький квадрат
1671
+ - `768x768` — средний квадрат
1672
+ - `960x960` — большой квадрат
1673
+
1674
+ ### 🔧 Настройка
1675
+
1676
+ **Требуется API-ключ:**
1677
+ ```bash
1678
+ # В файле .env
1679
+ DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
1680
+ ```
1681
+
1682
+ **Лимиты:**
1683
+ - Отдельный rate limit для генерации медиа (не влияет на чат)
1684
+ - Автоматическая ротация аккаунтов при превышении лимитов
1685
+ - Максимум 5 изображений за один запрос
1686
+
1687
+ ### 📝 Примеры использования
1688
+
1689
+ **OpenAI SDK:**
1690
+ ```javascript
1691
+ import OpenAI from 'openai';
1692
+
1693
+ const client = new OpenAI({
1694
+ baseURL: 'http://localhost:3264/api',
1695
+ apiKey: 'any-string',
1696
+ });
1697
+
1698
+ const response = await client.images.generate({
1699
+ model: 'qwen-image-plus',
1700
+ prompt: 'Футуристический город в неоновых огнях',
1701
+ n: 1,
1702
+ size: '1024x1024',
1703
+ });
1704
+
1705
+ console.log(response.data[0].url);
1706
+ ```
1707
+
1708
+ **Python:**
1709
+ ```python
1710
+ from openai import OpenAI
1711
+
1712
+ client = OpenAI(
1713
+ base_url="http://localhost:3264/api",
1714
+ api_key="any-string"
1715
+ )
1716
+
1717
+ response = client.images.generate(
1718
+ model="qwen-image-plus",
1719
+ prompt="Космический корабль над планетой",
1720
+ n=1,
1721
+ size="1024x1024"
1722
+ )
1723
+
1724
+ print(response.data[0].url)
1725
+ ```
1726
+
1727
+ ### 🆚 Сравнение режимов
1728
+
1729
+ | Функция | Text-to-Image | Image-to-Image |
1730
+ |---------|---------------|----------------|
1731
+ | **Вход** | Текстовый промпт | Изображение + промпт |
1732
+ | **API параметр** | `prompt` | `prompt` + `image_url` |
1733
+ | **Telegram** | `/imagens промпт` | Фото + подпись |
1734
+ | **Использование** | Создание с нуля | Стилизация/трансформация |
1735
+
1736
+ > 📖 **Подробная документация:**
1737
+ > - [docs/IMAGE_GENERATION.md](docs/IMAGE_GENERATION.md) - полное руководство
1738
+ > - [docs/IMAGE_GENERATION_MODES.md](docs/IMAGE_GENERATION_MODES.md) - режимы генерации
1739
+ > - [docs/TELEGRAM_IMAGE_GENERATION.md](docs/TELEGRAM_IMAGE_GENERATION.md) - генерация в Telegram
1740
+
1741
+ ---
1742
+
1743
+ ## OpenAI SDK
1744
+
1745
+ Прокси полностью совместим с официальным OpenAI SDK для JavaScript/TypeScript. Достаточно указать `baseURL` и любой непустой `apiKey`.
1746
+
1747
+ ### Простой запрос
1748
+
1749
+ ```javascript
1750
+ import OpenAI from 'openai';
1751
+
1752
+ const client = new OpenAI({
1753
+ baseURL: 'http://localhost:3264/api',
1754
+ apiKey: 'any-string', // обязательно для SDK, но не проверяется (если Authorization.txt пуст)
1755
+ });
1756
+
1757
+ const response = await client.chat.completions.create({
1758
+ model: 'qwen-max-latest',
1759
+ messages: [
1760
+ { role: 'user', content: 'Напиши 5 интересных фактов о космосе' }
1761
+ ],
1762
+ });
1763
+
1764
+ console.log(response.choices[0].message.content);
1765
+ ```
1766
+
1767
+ ### Потоковый режим
1768
+
1769
+ ```javascript
1770
+ const stream = await client.chat.completions.create({
1771
+ model: 'qwen-max-latest',
1772
+ messages: [
1773
+ { role: 'user', content: 'Напиши короткую историю о роботе' }
1774
+ ],
1775
+ stream: true,
1776
+ });
1777
+
1778
+ for await (const chunk of stream) {
1779
+ const text = chunk.choices[0]?.delta?.content || '';
1780
+ process.stdout.write(text);
1781
+ }
1782
+ ```
1783
+
1784
+ ### С system message
1785
+
1786
+ ```javascript
1787
+ const response = await client.chat.completions.create({
1788
+ model: 'qwen-max-latest',
1789
+ messages: [
1790
+ { role: 'system', content: 'Ты -- опытный DevOps-инженер. Отвечай с примерами команд.' },
1791
+ { role: 'user', content: 'Как настроить CI/CD для Node.js проекта?' }
1792
+ ],
1793
+ });
1794
+ ```
1795
+
1796
+ ---
1797
+
1798
+ ## Python (Альтернативная реализация)
1799
+
1800
+ Проект также включает полную реализацию на Python, которая работает независимо от Node.js.
1801
+
1802
+ ### Установка и запуск
1803
+ ```bash
1804
+ python -m venv venv
1805
+ # Windows:
1806
+ # venv\Scripts\activate
1807
+ # Linux/macOS:
1808
+ # source venv/bin/activate
1809
+ pip install -r requirements.txt
1810
+ playwright install chromium
1811
+ python main.py
1812
+ ```
1813
+
1814
+ ### Возможности Python-версии
1815
+ * **main.py**: Полноценный прокси-сервер на FastAPI и менеджер аккаунтов.
1816
+ * **Интерактивное меню**: Тот же интерфейс, что и в Node.js версии.
1817
+ * **Playwright**: Автоматизация браузера для входа и получения токенов.
1818
+ * **OpenAI Compatibility**: Полная поддержка OpenAI SDK (`baseURL: http://localhost:3264/api`).
1819
+
1820
+ ### Python примеры (как в Node.js)
1821
+
1822
+ В проект добавлены отдельные Python-примеры, аналогичные Node.js примерам:
1823
+
1824
+ - OpenAI SDK: `examples/python-sdk/`
1825
+ - Прямые HTTP запросы: `examples/python-direct/`
1826
+
1827
+ Установка зависимостей для примеров:
1828
+
1829
+ ```bash
1830
+ python -m venv venv
1831
+ # Windows:
1832
+ # venv\Scripts\activate
1833
+ # Linux/macOS:
1834
+ # source venv/bin/activate
1835
+ pip install -r requirements.txt
1836
+ ```
1837
+
1838
+ OpenAI SDK примеры:
1839
+
1840
+ ```bash
1841
+ python examples/python-sdk/simple.py
1842
+ python examples/python-sdk/streaming.py
1843
+ python examples/python-sdk/system_message.py
1844
+ python examples/python-sdk/image_analysis.py
1845
+ python examples/python-sdk/conversation.py
1846
+ python examples/python-sdk/openai_compatibility.py
1847
+ ```
1848
+
1849
+ Direct API примеры:
1850
+
1851
+ ```bash
1852
+ python examples/python-direct/httpx_example.py
1853
+ python examples/python-direct/httpx_streaming.py
1854
+ ```
1855
+
1856
+ > Перед запуском примеров убедитесь, что сервер уже запущен на `http://localhost:3264`.
1857
+
1858
+ ---
1859
+
1860
+ ## Переменные окружения
1861
+
1862
+ Все настройки читаются из переменных окружения с фоллбэками на значения по умолчанию. Полный список задаётся в `src/config.js`.
1863
+
1864
+ > **💡 Совет:** Создайте `.env` файл на основе `.env.example` для удобной настройки.
1865
+ > Файл `.env` загружается автоматически при старте.
1866
+
1867
+ ### Сервер
1868
+
1869
+ | Переменная | По умолчанию | Описание |
1870
+ |-----------|-------------|----------|
1871
+ | `PORT` | `3264` | Порт HTTP-сервера |
1872
+ | `HOST` | `0.0.0.0` | Адрес привязки |
1873
+ | `DEFAULT_MODEL` | `qwen3.5-plus` | Модель по умолчанию (если не задана в `bot_settings.json`) |
1874
+ | `ALLOW_UNSCOPED_SESSION_CHAT_RESTORE` | `false` | Разрешить legacy-восстановление контекста по IP + User-Agent, даже без `conversation_id`/`chatId` |
1875
+ | `FORCE_NEW_CHAT_PER_REQUEST` | `false` | Создавать новый диалог для каждого запроса (как OpenAI API). `true` = всегда новый чат, `false` = восстанавливать предыдущий |
1876
+
1877
+ ### Telegram бот 🤖
1878
+
1879
+ | Переменная | По умолчанию | Описание |
1880
+ |-----------|-------------|----------|
1881
+ | `TELEGRAM_BOT_TOKEN` | *(нет)* | Токен бота от @BotFather |
1882
+ | `TELEGRAM_USER_IDS` | *(нет)* | ID авторизованных пользователей (через запятую) |
1883
+ | `TELEGRAM_PROXY` | *(нет)* | Прокси для Telegram API (HTTP/SOCKS) |
1884
+ | `TELEGRAM_PROXY_URL` | *(нет)* | Альтернативная переменная для прокси |
1885
+
1886
+ **Пример:**
1887
+ ```bash
1888
+ TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
1889
+ TELEGRAM_USER_IDS=102375526,123456789
1890
+ TELEGRAM_PROXY=http://user:pass@proxy.example.com:8080
1891
+ ```
1892
+
1893
+ 📖 **Документация:** [docs/TELEGRAM_PROXY.md](docs/TELEGRAM_PROXY.md)
1894
+
1895
+ ### Токены и уведомления
1896
+
1897
+ | Переменная | По умолчанию | Описание |
1898
+ |-----------|-------------|----------|
1899
+ | `TOKEN_EXPIRY_WARNING_MS` | `3600000` (1 час) | Время предупреждения об истечении токена |
1900
+
1901
+ **Пример:**
1902
+ ```bash
1903
+ # Предупреждать за 2 часа до истечения
1904
+ TOKEN_EXPIRY_WARNING_MS=7200000
1905
+ ```
1906
+
1907
+ ### Прокси
1908
+
1909
+ | Переменная | По умолчанию | Описание |
1910
+ |-----------|-------------|----------|
1911
+ | `QWEN_PROXY` | *(нет)* | Прокси для Qwen API (HTTP/HTTPS/SOCKS) |
1912
+ | `FILE_DOWNLOAD_PROXY` | *(нет)* | Прокси для скачивания файлов по HTTP/HTTPS |
1913
+
1914
+ **Пример:**
1915
+ ```bash
1916
+ QWEN_PROXY=http://user:pass@proxy.example.com:8080
1917
+ FILE_DOWNLOAD_PROXY=socks5://proxy.example.com:1080
1918
+ ```
1919
+
1920
+ ### Режимы запуска
1921
+
1922
+ | Переменная | По умолчанию | Описание |
1923
+ |-----------|-------------|----------|
1924
+ | `SKIP_ACCOUNT_MENU` | `false` | Пропустить интерактивное меню аккаунтов |
1925
+ | `NON_INTERACTIVE` | `false` | Аналог `SKIP_ACCOUNT_MENU` |
1926
+ | `CHROME_PATH` | *(авто)* | Путь к исполняемому файлу Chromium/Chrome |
1927
+
1928
+ ### Таймауты
1929
+
1930
+ | Переменная | По умолчанию | Описание |
1931
+ |-----------|-------------|----------|
1932
+ | `PAGE_TIMEOUT` | `120000` (2 мин) | Таймаут загрузки страниц |
1933
+ | `AUTH_TIMEOUT` | `120000` (2 мин) | Таймаут ожидания авторизации |
1934
+ | `NAVIGATION_TIMEOUT` | `60000` (1 мин) | Таймаут навигации браузера |
1935
+ | `RETRY_DELAY` | `2000` (2 сек) | Задержка между повторными попытками |
1936
+ | `STREAMING_CHUNK_DELAY` | `20` (20 мс) | Задержка между SSE-чанками при streaming |
1937
+
1938
+ ### Лимиты
1939
+
1940
+ | Переменная | По умолчанию | Описание |
1941
+ |-----------|-------------|----------|
1942
+ | `PAGE_POOL_SIZE` | `3` | Размер пула страниц браузера |
1943
+ | `MAX_FILE_SIZE` | `10485760` (10 МБ) | Максимальный размер загружаемого файла |
1944
+ | `MAX_HISTORY_LENGTH` | `100` | Максимальное число записей в локальной истории |
1945
+ | `MAX_RETRY_COUNT` | `3` | Максимальное число повторных попыток при ошибках |
1946
+
1947
+ ### Логирование
1948
+
1949
+ | Переменная | По умолчанию | Описание |
1950
+ |-----------|-------------|----------|
1951
+ | `LOG_LEVEL` | `info` | Уровень логирования (error, warn, info, debug) |
1952
+ | `LOG_MAX_SIZE` | `5242880` (5 МБ) | Максимальный размер файла лога |
1953
+ | `LOG_MAX_FILES` | `5` | Количество ротируемых файлов логов |
1954
+
1955
+ ### Браузер
1956
+
1957
+ | Переменная | По умолчанию | Описание |
1958
+ |-----------|-------------|----------|
1959
+ | `VIEWPORT_WIDTH` | `1920` | Ширина viewport браузера |
1960
+ | `VIEWPORT_HEIGHT` | `1080` | Высота viewport браузера |
1961
+ | `USER_AGENT` | Chrome 131 | User-Agent строка |
1962
+
1963
+ ### Пути
1964
+
1965
+ | Переменная | По умолчанию | Описание |
1966
+ |-----------|-------------|----------|
1967
+ | `SESSION_DIR` | `session` | Директория для хранения сессий и токенов |
1968
+ | `UPLOADS_DIR` | `uploads` | Директория для временных файлов загрузки |
1969
+ | `LOGS_DIR` | `logs` | Директория для файлов логов |
1970
+
1971
+ ### API URLs (для продвинутых)
1972
+
1973
+ | Переменная | По умолчанию | Описание |
1974
+ |-----------|-------------|----------|
1975
+ | `QWEN_BASE_URL` | `https://chat.qwen.ai` | Базовый URL Qwen |
1976
+ | `CHAT_API_URL` | `{base}/api/v2/chat/completions` | URL API чата |
1977
+ | `CREATE_CHAT_URL` | `{base}/api/v2/chats/new` | URL создания чата |
1978
+ | `CHAT_PAGE_URL` | `{base}/` | URL главной страницы чата |
1979
+ | `TASK_STATUS_URL` | `{base}/api/v1/tasks/status` | URL статуса задач |
1980
+ | `STS_TOKEN_API_URL` | `{base}/api/v1/files/getstsToken` | URL получения STS-токена |
1981
+ | `AUTH_SIGNIN_URL` | `{base}/auth?action=signin` | URL страницы авторизации |
1982
+ | `OSS_SDK_URL` | `https://gosspublic.alicdn.com/aliyun-oss-sdk-6.20.0.min.js` | URL Aliyun OSS SDK |
1983
+ | `MODELS_API_URL` | `{base}/api/v2/models` | URL API моделей |
1984
+
1985
+ ### Генерация изображений 🎨
1986
+
1987
+ | Переменная | По умолчанию | Описание |
1988
+ |-----------|-------------|----------|
1989
+ | `IMAGE_GENERATION_MODE` | `dashscope` | Режим генерации: `dashscope` (через API ключ) или `browser` (через браузер) |
1990
+ | `DASHSCOPE_API_KEY` | *(нет)* | API ключ DashScope (требуется при `IMAGE_GENERATION_MODE=dashscope`) |
1991
+
1992
+ **Пример:**
1993
+ ```bash
1994
+ # Режим браузера (не требует API ключа)
1995
+ IMAGE_GENERATION_MODE=browser
1996
+
1997
+ # Или режим DashScope (требует API ключ)
1998
+ IMAGE_GENERATION_MODE=dashscope
1999
+ DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
2000
+ ```
2001
+
2002
+ 📖 **Документация:** [docs/IMAGE_GENERATION.md](docs/IMAGE_GENERATION.md), [docs/IMAGE_GENERATION_MODES.md](docs/IMAGE_GENERATION_MODES.md)
2003
+
2004
+ ---
2005
+
2006
+ ## Структура проекта
2007
+
2008
+ ```
2009
+ ├── main.py # Python FastAPI реализация прокси + интерактивное меню
2010
+ ├── requirements.txt # Python зависимости
2011
+ ├── index.js # Точка входа: Express-сервер, меню аккаунтов
2012
+ ├── package.json
2013
+ ├── Dockerfile
2014
+ ├── docker-compose.yml
2015
+
2016
+ ├── src/
2017
+ │ ├── config.js # Центральный модуль конфигурации (env-переменные)
2018
+ │ ├── AvailableModels.txt # Список доступных моделей
2019
+ │ ├── Authorization.txt # API-ключи для авторизации запросов
2020
+ │ │
2021
+ │ ├── api/
2022
+ │ │ ├── routes.js # Определение REST-эндпоинтов
2023
+ │ │ ├── chat.js # Отправка сообщений к Qwen API, извлечение токенов
2024
+ │ │ ├── chatHistory.js # Локальная история чатов
2025
+ │ │ ├── fileUpload.js # Загрузка файлов в Qwen OSS
2026
+ │ │ ├── modelMapping.js # Маппинг алиасов моделей
2027
+ │ │ └── tokenManager.js # Управление токенами, ротация аккаунтов
2028
+ │ │
2029
+ │ ├── browser/
2030
+ │ │ ├── browser.js # Инициализация Puppeteer, управление контекстом
2031
+ │ │ ├── auth.js # Проверка авторизации в браузере
2032
+ │ │ └── session.js # Сохранение/загрузка сессий
2033
+ │ │
2034
+ │ ├── logger/
2035
+ │ │ └── index.js # Winston-логгер с ротацией файлов
2036
+ │ │
2037
+ │ └── utils/
2038
+ │ ├── accountSetup.js # Интерактивное управление аккаунтами
2039
+ │ └── prompt.js # Утилита для интерактивного ввода
2040
+
2041
+ ├── scripts/
2042
+ │ └── auth.js # CLI-скрипт авторизации (npm run auth)
2043
+
2044
+ ├── examples/ # Примеры использования API
2045
+ │ ├── openai-sdk/ # Примеры с OpenAI SDK
2046
+ │ ├── direct-api/ # Примеры с fetch/axios
2047
+ │ ├── file-upload/ # Пример загрузки файлов
2048
+ │ ├── python-sdk/ # Python примеры с OpenAI SDK
2049
+ │ └── python-direct/ # Python примеры с httpx
2050
+
2051
+ ├── session/ # Данные сессий и аккаунтов (создаётся автоматически)
2052
+ ├── logs/ # Файлы логов (создаётся автоматически)
2053
+ └── uploads/ # Временные файлы загрузки (создаётся автоматически)
2054
+ ```