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/.env.example +49 -0
- package/LICENSE +21 -0
- package/README.md +2054 -0
- package/bin/qwen-api-proxy.js +414 -0
- package/index.js +444 -0
- package/package.json +85 -0
- package/src/Authorization.txt +17 -0
- package/src/AvailableModels.txt +26 -0
- package/src/api/chat.js +1392 -0
- package/src/api/chatHistory.js +344 -0
- package/src/api/fileUpload.js +182 -0
- package/src/api/imageGeneration.js +459 -0
- package/src/api/modelMapping.js +274 -0
- package/src/api/routes.js +2160 -0
- package/src/api/tokenManager.js +382 -0
- package/src/browser/auth.js +171 -0
- package/src/browser/browser.js +233 -0
- package/src/browser/session.js +134 -0
- package/src/config.js +116 -0
- package/src/logger/index.js +89 -0
- package/src/utils/accountSetup.js +153 -0
- package/src/utils/botSettings.js +231 -0
- package/src/utils/permissionChecker.js +205 -0
- package/src/utils/prompt.js +11 -0
- package/src/utils/proxy.js +255 -0
- package/src/utils/telegramBot.js +2977 -0
- package/src/utils/telegramNotifier.js +94 -0
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
|
+
```
|