Cистема для создания и эмуляции активных форумов IPB надо кому?
- Бесплатный доступ: Используйте модели Qwen без оплаты API-ключа
- Полная совместимость: Поддержка OpenAI-совместимого интерфейса для простой интеграции
- Возможность загрузки файлов и получение ссылки прямо из прокси
- 🆕 API v2: Обновлено на новый Qwen API с улучшенной системой контекста
- 🔥 25+ моделей: Поддержка всех современных моделей Qwen, включая Qwen 3.5
- 🎨 Генерация изображений: Поддержка Qwen Image API через DALL-E-совместимый интерфейс
- 💾 Автосохранение сессий: Умное управление контекстом для OpenWebUI
Что можно делать:
- Отправлять запросы к 18 моделям Qwen (включая qwen3-max, qwen3-coder-plus, qwq-32b и др.)
- Использовать OpenAI SDK без изменений -- просто поменяйте
baseURL - Вести диалоги с сохранением контекста на серверах Qwen (API v2)
- Загружать файлы и изображения для анализа
- Получать ответы в потоковом режиме (SSE streaming)
- Подключать несколько аккаунтов с автоматической ротацией
# Всё, что нужно -- обычный OpenAI-совместимый запрос
curl http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen-max-latest","messages":[{"role":"user","content":"Привет!"}]}'- Быстрый старт
- Docker
- Управление аккаунтами
- Авторизация API-ключами
- API Reference
- Работа с контекстом (API v2)
- Работа с изображениями
- OpenAI SDK
- Доступные модели
- Переменные окружения
- Структура проекта
git clone <repo-url>
cd AbuseQwenThroughtBrowserIEmulationXD
npm install
npm startПри первом запуске появится интерактивное меню:
███████ ██████ ███████ ███████ ██████ ██ ██ ███████ ███ ██ █████ ██████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
█████ ██████ █████ █████ ██ ██ ██ █ ██ █████ ██ ██ ██ ███████ ██████ ██
██ ██ ██ ██ ██ ██ ▄▄ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ███████ ███████ ██████ ███ ███ ███████ ██ ████ ██ ██ ██ ██
Список аккаунтов:
(пусто)
=== Меню ===
1 - Добавить новый аккаунт
2 - Перелогинить аккаунт с истекшим токеном
3 - Запустить прокси (по умолчанию)
4 - Удалить аккаунт
Ваш выбор (Enter = 3):
Порядок действий:
- Выберите
1-- откроется браузер Chromium - Войдите в свой аккаунт Qwen на открывшейся странице
- После входа токен извлечётся автоматически, браузер закроется
- Выберите
3(или нажмите Enter) -- сервер запустится
Сервер будет доступен по адресу http://localhost:3264/api.
Перед сборкой Docker-образа нужно добавить хотя бы один аккаунт, поскольку внутри контейнера нет GUI для интерактивного входа:
# 1. Добавляем аккаунт(ы) локально
npm run auth
# 2. Собираем и запускаем
docker compose up --build -dФайл docker-compose.yml:
services:
qwen-proxy:
build: .
container_name: qwen-proxy
environment:
- SKIP_ACCOUNT_MENU=true
- PORT=3264
ports:
- "3264:3264"
volumes:
- ./session:/app/session
- ./logs:/app/logs
- ./uploads:/app/uploads
restart: unless-stoppedПеременная SKIP_ACCOUNT_MENU=true (или NON_INTERACTIVE=true) пропускает интерактивное меню и сразу запускает сервер, используя ранее сохранённые токены из session/.
При запуске npm start без флага SKIP_ACCOUNT_MENU отображается меню с 4 пунктами:
| Пункт | Действие |
|---|---|
| 1 | Добавить новый аккаунт -- откроется браузер для входа |
| 2 | Перелогинить аккаунт -- обновить токен для аккаунта с истёкшей сессией |
| 3 | Запустить прокси -- стандартный запуск (по умолчанию) |
| 4 | Удалить аккаунт -- удалить сохранённый аккаунт |
| Статус | Значение |
|---|---|
| OK | Аккаунт активен, токен валиден |
| WAIT | Rate limit -- ожидание сброса (автоматический таймер на 24ч) |
| INVALID | Токен истёк или отозван -- требуется перелогин |
Если подключено несколько аккаунтов, сервер автоматически:
- Выбирает следующий активный аккаунт (round-robin)
- При получении HTTP 429 (rate limit) помечает аккаунт как WAIT и переключается на следующий
- При получении HTTP 401 (unauthorized) помечает аккаунт как INVALID и переключается на следующий
npm run authЗапускает скрипт авторизации без запуска сервера -- удобно для Docker-окружения, когда нужно добавить аккаунты перед сборкой.
session/
├── tokens.json # Реестр всех аккаунтов и их статусов
└── accounts/
├── acc_1234567890/
│ └── token.txt # Токен аккаунта
└── acc_9876543210/
└── token.txt
По умолчанию авторизация отключена -- API доступен всем. Для включения добавьте ключи в файл src/Authorization.txt:
# Один ключ на строку
d35ab3e1-a6f9-4d00-b1c2-example-key1
f2b1cd9c-1b2e-4a99-8c3d-example-key2
После этого каждый запрос к API должен содержать заголовок:
Authorization: Bearer d35ab3e1-a6f9-4d00-b1c2-example-key1
Пустые строки и строки, начинающиеся с #, игнорируются. Если файл пуст или содержит только комментарии -- авторизация отключена.
Все эндпоинты доступны по базовому пути /api. Версионирование (/v1, /v2) в URL опционально и автоматически удаляется -- /api/v1/chat/completions и /api/chat/completions эквивалентны.
Нативный формат запроса. Поддерживает текст, составные сообщения с изображениями, system message.
Запрос:
docker compose up --build -d- Приложение будет доступно на
http://localhost:3264/api.
⚙️ Контейнер запускается с переменной
SKIP_ACCOUNT_MENU=true, поэтому интерактивное меню не блокирует старт. Папкиsession/,logs/иuploads/примонтированы в контейнер как тома, что позволяет повторно использовать сохранённые токены и журналы.
⚠️ Важно: если файлsrc/Authorization.txtпустой, авторизация отключена.
-
Файл
src/Authorization.txt- Создаётся автоматически при первом запуске если его нет.
- Внутри уже есть подробный шаблон-инструкция.
- Один токен на строку. Пустые строки и строки, начинающиеся с
#, игнорируются.
-
Отключить авторизацию – оставьте файл пустым. Middleware пропустит все запросы.
-
Проверка на стороне клиента
Отправляйте HTTP-заголовок:
Authorization: Bearer <your_token>Пример cURL:
curl -X POST http://localhost:3264/api/chat \ -H "Content-Type: application/json" \ -H "Authorization: Bearer my-secret-token-123" \ -d '{"message":"Привет"}'
При старте npm start появляется интерактивное меню:
Список аккаунтов:
N | ID | Статус
1 | acc_1752745840684 | ✅ OK
2 | acc_1752745890062 | ❌ INVALID
=== Меню ===
1 - Добавить новый аккаунт
2 - Перелогинить аккаунт с истекшим токеном
3 - Запустить прокси (Enter по умолчанию)
4 - Удалить аккаунт
Статусы:
| Значок | Значение | Поведение |
|---|---|---|
| ✅ OK | токен активен | используется в ротации |
| ⏳ WAIT | токен временно заблокирован (RateLimited) | пропускается до истечения тайм-аута |
| ❌ INVALID | токен просрочен (401 Unauthorized) | недоступен, выберите пункт 2 для повторного входа |
Пункты меню:
- Добавить новый аккаунт – откроется браузер, авторизуйтесь, токен будет сохранён.
- Перелогинить аккаунт с истекшим токеном – выберите нужный ID, откроется браузер для повторного входа, статус сменится на ✅.
- Запустить прокси – доступно, если есть хотя бы один статус ✅ или ⏳.
- Удалить аккаунт – полностью удаляет токен и папку сессии.
Файлы:
session/accounts/<id>/token.txt– токен аккаунтаsession/tokens.json– реестр аккаунтов и состоянийnpm run auth– отдельный скрипт для управления аккаунтами без запуска сервера (то же меню, плюс CLI-аргументы--list,--add,--relogin,--remove)
| Переменная | Значение по умолчанию | Назначение |
|---|---|---|
PORT |
3264 |
Порт HTTP-сервера |
HOST |
0.0.0.0 |
Адрес привязки сервера |
SKIP_ACCOUNT_MENU |
false |
При значении true отключает интерактивное меню запуска (нужно для Docker/CI) |
SKIP_ACCOUNT_MENUавтоматически активирован в Docker Compose. Если при старте нет валидных токенов, сервер завершит работу с подсказкой запуститьnpm run auth.
Автоматическая ротация:
- запросы распределяются по токенам циклически.
- При ответе 429 RateLimited токен получает ⏳ WAIT на указанное время.
- При ответе 401 Unauthorized токен помечается ❌ INVALID.
- Если все токены недействительны – прокси завершает работу, запустите его и перелогиньтесь.
Этот проект позволяет:
- Использовать модели Qwen AI через локальный API
- Сохранять контекст диалогов между запросами
- Управлять диалогами через API
- Выбирать различные модели Qwen для генерации ответов
- Отправлять изображения для анализа моделью
- Использовать OpenAI-совместимый API с поддержкой streaming режима
- Генерировать изображения через Qwen Image API
Прокси поддерживает 25+ моделей Qwen через систему маппинга:
qwen-max/qwen-max-latest— наиболее мощная модельqwen-plus/qwen-plus-latest— сбалансированная модельqwen-turbo/qwen-turbo-latest— быстрая и лёгкая модель
qwen3.5-plus/qwen3.5-plus-latest— улучшенная версия Plusqwen3.5-flash/qwen3.5-flash-latest— быстрая модель Qwen 3.5qwen3.5-397b-a17b— сверхбольшая модель (397B параметров)qwen3.5-122b-a10b— большая модель (122B параметров)qwen3.5-27b— средняя модель (27B параметров)qwen3.5-35b-a3b— компактная модель (35B параметров)
qwen3— базовая модель Qwen 3qwen3-max— максимальная модель Qwen 3qwen3-plus— сбалансированная модель Qwen 3qwen3-omni-flash— быстрая мультимодальная модель
qwen3-coder-plus— модель для программированияqwen2.5-coder-32b-instruct— кодирование (32B)qwen2.5-coder-7b-instruct— кодирование (7B)qwen2.5-coder-3b-instruct— кодирование (3B)qwen2.5-coder-1.5b-instruct— кодирование (1.5B)qwen2.5-coder-0.5b-instruct— кодирование (0.5B)
qwen-vl-max/qwen-vl-max-latest— максимальная визуальная модельqwen-vl-plus/qwen-vl-plus-latest— сбалансированная визуальная модельqwen2.5-vl-32b-instruct— визуальная модель (32B)qwen2.5-vl-7b-instruct— визуальная модель (7B)
qvq-72b-preview-0310— предпросмотр QVQ (72B)qwen2.5-14b-instruct-1m— контекст 1M токеновqwen2.5-72b-instruct— большая языковая модель (72B)
Система маппинга: Прокси автоматически распознаёт алиасы моделей (например,
Qwen3.5-Plus,qwen3.5-flash-latest→ соответствующие канонические модели).
| Эндпоинт | Метод | Описание |
|---|---|---|
/api/chat |
POST | Отправка сообщения с поддержкой chatId и parentId |
/api/chat/completions |
POST | OpenAI-совместимый эндпоинт, возвращает chatId/parentId |
/api/models |
GET | Получение списка доступных моделей |
/api/status |
GET | Проверка статуса авторизации и аккаунтов |
/api/files/upload |
POST | Загрузка изображения для использования в запросах |
/api/chats |
POST | Создание нового чата на серверах Qwen |
GET /api/chats- список чатовGET /api/chats/:chatId- история чатаDELETE /api/chats/:chatId- удаление чатаPUT /api/chats/:chatId/rename- переименованиеPOST /api/chats/cleanup- автоудаление
Причина: чаты теперь управляются на серверах Qwen
| Эндпоинт | Использование контекста | Формат запроса | Совместимость |
|---|---|---|---|
/api/chat |
Контекст управляется через chatId + parentId. История хранится на серверах Qwen. |
Упрощённый message + chatId + parentId |
Нативный для прокси |
/api/chat/completions |
Поддерживает chatId + parentId в запросе. Возвращает их в ответе для продолжения. |
Массив messages (OpenAI format) + опционально chatId/parentId |
OpenAI SDK |
{
"message": "Текст сообщения",
"model": "qwen-max-latest",
"chatId": "идентификатор_чата",
"parentId": "response_id_из_предыдущего_ответа"
}{
"messages": [
{"role": "user", "content": "Привет, как дела?"}
],
"model": "qwen-max-latest",
"chatId": "идентификатор_чата",
"parentId": "response_id_из_предыдущего_ответа"
}Новая система:
- История хранится на серверах Qwen, не локально
- Контекст управляется через
chatId+parentId parentId- этоresponse_idиз предыдущего ответа
Пример диалога:
// 1. Первое сообщение
const res1 = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message: "Сколько будет 2+2?" })
});
const data1 = await res1.json();
// Ответ: { chatId: "abc-123", parentId: "xyz-789", ... }
// 2. Второе сообщение (с контекстом)
const res2 = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
message: "А результат плюс 3?",
chatId: data1.chatId, // Тот же чат
parentId: data1.parentId // Из предыдущего ответа!
})
});
// Модель помнит контекст и ответит "7"Новое в v2: Поддержка системных сообщений для настройки поведения модели!
Системные инструкции передаются через поле role: "system" в массиве messages. Это позволяет задать модели контекст, стиль общения, правила поведения и т.д.
Пример:
// Запрос с системной инструкцией
const response = await fetch('/api/chat/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
messages: [
{
role: "system",
content: "Ты - опытный программист на Python. Отвечай кратко и предоставляй примеры кода."
},
{
role: "user",
content: "Как отсортировать список в Python?"
}
],
model: "qwen-max-latest"
})
});Как работает:
systemmessage извлекается из массива и передаётся отдельным параметром в Qwen API v2- Может использоваться в обоих эндпоинтах:
/api/chatи/api/chat/completions - System message применяется ко всему чату и влияет на все последующие ответы
Примеры использования:
// 1. Ролевая инструкция
{
"messages": [
{"role": "system", "content": "Ты - эксперт по машинному обучению"},
{"role": "user", "content": "Объясни, что такое градиентный спуск"}
]
}
// 2. Стиль ответов
{
"messages": [
{"role": "system", "content": "Отвечай как пират"},
{"role": "user", "content": "Как дела?"}
]
}
// 3. Формат вывода
{
"messages": [
{"role": "system", "content": "Всегда отвечай в формате JSON"},
{"role": "user", "content": "Дай информацию о Python"}
]
}Прокси поддерживает отправку сообщений с изображениями:
{
"message": [
{
"type": "text",
"text": "Опишите объекты на этом изображении"
},
{
"type": "image",
"image": "URL_ИЗОБРАЖЕНИЯ"
}
],
"model": "qwen-vl-max",
"chatId": "идентификатор_чата",
"parentId": "response_id"
}POST http://localhost:3264/api/files/upload
Формат запроса: multipart/form-data
Параметры:
file- файл изображения (поддерживаются форматы: jpg, jpeg, png, gif, webp)
Пример использования с curl:
curl -X POST http://localhost:3264/api/files/upload \
-F "file=@/путь/к/изображению.jpg"Пример ответа:
{
"imageUrl": "https://cdn.qwenlm.ai/user-id/file-id_filename.jpg?key=..."
}Для отправки изображений через API прокси необходимо сначала получить URL изображения. Это можно сделать двумя способами:
Отправьте POST запрос на эндпоинт /api/files/upload для загрузки изображения, как описано выше.
- Загрузите изображение в официальном веб-интерфейсе Qwen (https://chat.qwen.ai/)
- Откройте инструменты разработчика в браузере (F12 или Ctrl+Shift+I)
- Перейдите на вкладку "Network" (Сеть)
- Найдите запрос к API Qwen, содержащий ваше изображение (обычно это запрос GetsToken)
- В теле запроса найдите URL изображения, который выглядит примерно так:
https://cdn.qwenlm.ai/user-id/file-id_filename.jpg?key=... - Скопируйте этот URL для использования в вашем API-запросе
POST http://localhost:3264/api/chats
Тело запроса:
{
"name": "Название диалога"
}Ответ:
{
"id": "chatcmpl-1739012345678",
"object": "chat.completion",
"created": 1739012345,
"model": "qwen-max-latest",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Квантовые вычисления — это тип вычислений, основанный на принципах квантовой механики..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 156,
"total_tokens": 168
},
"chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}Используйте chatId и parentId из предыдущего ответа:
curl -X POST http://localhost:3264/api/chat \
-H "Content-Type: application/json" \
-d '{
"message": "Приведи практические примеры",
"model": "qwen-max-latest",
"chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}'curl -X POST http://localhost:3264/api/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "system", "content": "Ты -- опытный Python-разработчик. Отвечай кратко, с примерами кода."},
{"role": "user", "content": "Как отсортировать словарь по значениям?"}
],
"model": "qwen-max-latest"
}'curl -X POST http://localhost:3264/api/chat \
-H "Content-Type: application/json" \
-d '{
"message": [
{"type": "text", "text": "Что изображено на этой картинке?"},
{"type": "image", "image": "https://example-oss-url.com/uploaded-image.png"}
],
"model": "qwen3-vl-plus"
}'OpenAI-совместимый формат. Используйте этот эндпоинт, если работаете с OpenAI SDK или любым инструментом, поддерживающим OpenAI API.
Запрос:
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [
{"role": "system", "content": "Отвечай кратко и по существу."},
{"role": "user", "content": "Столица Японии?"}
]
}'Ответ:
{
"message": "Привет, как тебя зовут?"
}- Ответ (содержит
chatId):
{
"chatId": "abcd-1234-5678",
"choices": [...]
}- Последующие запросы (с указанием полученного
chatId):
{
"message": "Сколько будет 2+2?",
"chatId": "abcd-1234-5678"
}Прокси поддерживает эндпоинт, совместимый с OpenAI API для подключения клиентов, которые работают с OpenAI API:
POST /api/chat/completions
-
No forced new chat per request: if
chatIdis omitted, the proxy first tries to restore chat context from the session (IP + User-Agent) or byconversation_id, and only then creates a new chat. -
Both id formats are supported:
chatId/parentIdandchat_id/parent_id. -
Force a fresh chat: send
newChat: trueornew_chat: true. -
System messages are supported:
role: "system"is passed through to the upstream model. -
Strict JSON parsing: invalid JSON (for example, single quotes instead of double quotes) returns
400 Invalid JSON. -
Method check:
GET /api/chat/completionsreturns405; usePOST.
System message request example:
{
"messages": [
{"role": "system", "content": "Ты эксперт по JavaScript. Отвечай только на вопросы о JavaScript."},
{"role": "user", "content": "Как создать класс в JavaScript?"}
],
"model": "qwen-max-latest"
}Прокси поддерживает режим потоковой передачи ответов (streaming), что позволяет получать ответы по частям в режиме реального времени. Стриминг доступен в обоих эндпоинтах:
{
"messages": [
{"role": "user", "content": "Напиши длинный рассказ о космосе"}
],
"model": "qwen-max-latest",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Токио."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 18,
"completion_tokens": 3,
"total_tokens": 21
},
"chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}{
"message": "Напиши длинный рассказ о космосе",
"model": "qwen-max-latest",
"stream": true
}При использовании streaming режима, ответ будет возвращаться постепенно в формате Server-Sent Events (SSE), совместимом с OpenAI API.
Прокси полностью поддерживает работу с OpenWebUI через streaming режим:
-
Настройка подключения в OpenWebUI:
- Base URL:
http://localhost:3264/api - API Key: любой (или оставьте пустым, если файл
Authorization.txtпустой)
- Base URL:
-
Формат запроса для OpenWebUI:
{
"messages": [
{"role": "user", "content": "Привет!"}
],
"model": "qwen-max-latest",
"stream": true
}-
Автоматическое сохранение контекста: Прокси автоматически сохраняет
chatIdиparentIdв сессии (на основе IP + User-Agent), поэтому OpenWebUI может продолжать диалог без явной передачи этих параметров. -
Детерминированные chatId: Для каждого уникального первого сообщения пользователя генерируется стабильный
chatId, что позволяет OpenWebUI корректно управлять историей диалогов. -
Поддержка всех эндпоинтов:
/api/chat/completions— OpenAI-совместимый эндпоинт/api/v1/chat/completions— альтернативный OpenAI-совместимый эндпоинт/api/chat— нативный эндпоинт прокси
-
Генерация изображений: Через OpenWebUI можно использовать генерацию изображений через эндпоинт
/api/images/generations(DALL-E-совместимый API).
Прокси поддерживает генерацию изображений через Qwen Image API:
Эндпоинт: POST /api/images/generations
{
"prompt": "Космический корабль на фоне туманности",
"model": "qwen-image-plus",
"n": 1,
"size": "1024x1024"
}Ответ:
{
"created": 1234567890,
"data": [
{
"url": "https://example.com/generated-image.png",
"revised_prompt": "Космический корабль на фоне туманности"
}
]
}Параметры:
prompt(обязательный) — текстовое описание изображенияmodel— модель генерации (qwen-image-plus,qwen-image-turbo)n— количество изображений (по умолчанию 1)size— размер (1024x1024,1024x1792,1792x1024,512x512,768x768,960x960)
Требуется API-ключ: Для генерации изображений необходимо установить переменную окружения
DASHSCOPE_API_KEY.
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [
{"role": "user", "content": "Напиши хайку о программировании"}
],
"stream": true
}'Ответ (SSE):
data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"content":"Строки кода бегут"},"finish_reason":null}]}
data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{"content":" —\nБаг затаился в ветвях"},"finish_reason":null}]}
data: {"id":"chatcmpl-stream","object":"chat.completion.chunk","created":1739012345,"model":"qwen-max-latest","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [
{"role": "user", "content": "Теперь на тему космоса"}
],
"chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"parentId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}'Возвращает список доступных моделей в формате OpenAI.
Запрос:
curl http://localhost:3264/api/modelsОтвет:
{
"object": "list",
"data": [
{"id": "qwen3-max", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
{"id": "qwen3-vl-plus", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
{"id": "qwen3-coder-plus", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
{"id": "qwq-32b", "object": "model", "created": 0, "owned_by": "qwen", "permission": []},
{"id": "qwen-max-latest", "object": "model", "created": 0, "owned_by": "qwen", "permission": []}
]
}Полный список всех 18 моделей -- см. раздел Доступные модели.
Проверяет статус авторизации и состояние всех аккаунтов. Для каждого аккаунта выполняется тестовый запрос к Qwen API.
Запрос:
curl http://localhost:3264/api/statusОтвет:
{
"authenticated": true,
"message": "Авторизация активна",
"accounts": [
{"id": "acc_1739012345678", "status": "OK", "resetAt": null},
{"id": "acc_1739098765432", "status": "WAIT", "resetAt": "2026-02-17T12:00:00.000Z"},
{"id": "acc_1739055555555", "status": "INVALID", "resetAt": null}
]
}| Поле | Описание |
|---|---|
authenticated |
true, если хотя бы один аккаунт активен |
accounts[].status |
OK -- активен, WAIT -- rate limit, INVALID -- токен недействителен |
accounts[].resetAt |
Время, после которого аккаунт станет доступен (для WAIT) |
Создаёт новый чат на серверах Qwen. Возвращает chatId, который можно использовать для ведения диалога с сохранением истории.
Запрос:
curl -X POST http://localhost:3264/api/chats \
-H "Content-Type: application/json" \
-d '{
"name": "Обсуждение архитектуры",
"model": "qwen-max-latest"
}'Ответ:
{
"chatId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"success": true
}Загружает файл через сервер в Qwen OSS. Поддерживаемые типы: изображения (jpg, png, gif, webp, bmp), документы (pdf, doc, docx, txt) и прочие файлы. Максимальный размер -- 10 МБ (настраивается через MAX_FILE_SIZE).
Запрос:
curl -X POST http://localhost:3264/api/files/upload \
-F "file=@/path/to/image.png"Ответ:
{
"success": true,
"file": {
"name": "image.png",
"url": "https://oss-bucket.aliyuncs.com/path/to/uploaded-image.png",
"size": 245760,
"type": "image/png"
}
}Полученный url можно использовать в запросе к /api/chat с составным сообщением (см. Работа с изображениями).
Возвращает STS-токен для прямой загрузки файла в Qwen OSS из клиентского кода. Для большинства случаев удобнее использовать /api/files/upload.
Запрос:
curl -X POST http://localhost:3264/api/files/getstsToken \
-H "Content-Type: application/json" \
-d '{
"filename": "document.pdf",
"filesize": 102400,
"filetype": "document"
}'Ответ:
{
"access_key_id": "STS.xxxxx",
"access_key_secret": "xxxxx",
"security_token": "CAISxxxxx...",
"region": "oss-cn-beijing",
"bucketname": "qwen-upload-bucket",
"file_path": "uploads/2026/02/16/document.pdf",
"file_url": "https://qwen-upload-bucket.oss-cn-beijing.aliyuncs.com/uploads/...",
"file_id": "file-abc123"
}| Поле | Описание |
|---|---|
filetype |
Тип файла: image (jpg, png, gif, webp, bmp), document (pdf, doc, docx, txt) или file |
API использует серверную историю чатов Qwen. Каждый ответ содержит chatId и parentId, которые нужно передать в следующий запрос для продолжения диалога.
1-й запрос (без chatId) ──> Ответ с chatId="abc", parentId="def"
│
2-й запрос (chatId="abc", parentId="def") ──> Ответ с parentId="ghi"
│
3-й запрос (chatId="abc", parentId="ghi") ──> Ответ с parentId="jkl"
Шаг 1 -- первое сообщение:
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [{"role": "user", "content": "Что такое Docker?"}]
}'{
"id": "chatcmpl-1739012345678",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "Docker — это платформа для контейнеризации приложений..."}, "finish_reason": "stop"}],
"chatId": "abc-123",
"parentId": "def-456"
}Шаг 2 -- продолжение (модель помнит контекст):
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [{"role": "user", "content": "Чем он отличается от виртуальных машин?"}],
"chatId": "abc-123",
"parentId": "def-456"
}'{
"id": "chatcmpl-1739012345679",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "Основные отличия Docker от виртуальных машин:\n1. Docker использует ядро хост-системы, а ВМ — полное гостевое ядро..."}, "finish_reason": "stop"}],
"chatId": "abc-123",
"parentId": "ghi-789"
}Шаг 3 -- ещё одно сообщение в том же диалоге:
curl -X POST http://localhost:3264/api/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-max-latest",
"messages": [{"role": "user", "content": "Покажи пример Dockerfile для Node.js"}],
"chatId": "abc-123",
"parentId": "ghi-789"
}'Обратите внимание:
parentIdкаждый раз берётся из предыдущего ответа, аchatIdостаётся одним и тем же на протяжении всего диалога.
Можно создать чат заранее через POST /api/chats и использовать полученный chatId с первого сообщения. Это удобно, если вы хотите задать имя чату.
Для анализа изображений используйте модели с поддержкой vision: qwen3-vl-plus, qwen2.5-vl-32b-instruct, qvq-72b-preview-0310, qwen2.5-omni-7b.
Шаг 1 -- загрузить изображение:
curl -X POST http://localhost:3264/api/files/upload \
-F "file=@photo.jpg"{
"success": true,
"file": {
"name": "photo.jpg",
"url": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg",
"size": 184320,
"type": "image/jpeg"
}
}Шаг 2 -- отправить запрос с изображением:
curl -X POST http://localhost:3264/api/chat \
-H "Content-Type: application/json" \
-d '{
"message": [
{"type": "text", "text": "Опиши, что изображено на фото. Какие объекты ты видишь?"},
{"type": "image", "image": "https://oss-bucket.aliyuncs.com/uploads/photo.jpg"}
],
"model": "qwen3-vl-plus"
}'Поле message принимает массив объектов:
[
{"type": "text", "text": "Ваш вопрос к изображению"},
{"type": "image", "image": "https://url-to-uploaded-image.com/image.png"}
]Прокси полностью совместим с официальным OpenAI SDK для JavaScript/TypeScript. Достаточно указать baseURL и любой непустой apiKey.
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'http://localhost:3264/api',
apiKey: 'any-string', // обязательно для SDK, но не проверяется (если Authorization.txt пуст)
});
const response = await client.chat.completions.create({
model: 'qwen-max-latest',
messages: [
{ role: 'user', content: 'Напиши 5 интересных фактов о космосе' }
],
});
console.log(response.choices[0].message.content);const stream = await client.chat.completions.create({
model: 'qwen-max-latest',
messages: [
{ role: 'user', content: 'Напиши короткую историю о роботе' }
],
stream: true,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || '';
process.stdout.write(text);
}const response = await client.chat.completions.create({
model: 'qwen-max-latest',
messages: [
{ role: 'system', content: 'Ты -- опытный DevOps-инженер. Отвечай с примерами команд.' },
{ role: 'user', content: 'Как настроить CI/CD для Node.js проекта?' }
],
});from openai import OpenAI
client = OpenAI(
base_url="http://localhost:3264/api",
api_key="any-string",
)
response = client.chat.completions.create(
model="qwen-max-latest",
messages=[
{"role": "user", "content": "Привет! Расскажи о себе."}
],
)
print(response.choices[0].message.content)Больше примеров -- в директории
examples/.
| Модель | Описание |
|---|---|
qwen3-max |
Флагманская модель Qwen 3 |
qwen3-vl-plus |
Vision-Language: работа с текстом и изображениями |
qwen3-coder-plus |
Специализация на коде |
qwen3-omni-flash |
Мультимодальная (текст, изображения, аудио) |
qwen-plus-2025-09-11 |
Qwen Plus (актуальная версия) |
qwen3-235b-a22b |
Qwen 3 -- 235B параметров (MoE, 22B активных) |
qwen3-30b-a3b |
Qwen 3 -- 30B параметров (MoE, 3B активных) |
qwen3-coder-30b-a3b-instruct |
Кодерская модель -- 30B (MoE) |
qwen-max-latest |
Qwen 2.5 Max |
qwen-plus-2025-01-25 |
Qwen 2.5 Plus |
qwq-32b |
QwQ -- модель для рассуждений (reasoning) |
qwen-turbo-2025-02-11 |
Быстрая модель для простых задач |
qwen2.5-omni-7b |
Мультимодальная 7B |
qvq-72b-preview-0310 |
QVQ -- vision + reasoning |
qwen2.5-vl-32b-instruct |
Vision-Language 32B |
qwen2.5-14b-instruct-1m |
14B с контекстом 1M токенов |
qwen2.5-coder-32b-instruct |
Кодерская модель 32B |
qwen2.5-72b-instruct |
Qwen 2.5 -- 72B |
Запрашивать модели можно по любому из поддерживаемых имён -- сервер автоматически подставит каноническое:
| Вы запрашиваете | Используется |
|---|---|
qwen-max |
qwen3-max |
qwen-vl-plus |
qwen3-vl-plus |
qwen3-coder |
qwen3-coder-plus |
qwq |
qwq-32b |
qwen-turbo |
qwen-turbo-2025-02-11 |
qwen2.5-max |
qwen-max-latest |
qwen2.5-plus |
qwen-plus-2025-01-25 |
qvq |
qvq-72b-preview-0310 |
qwen3 |
qwen3-235b-a22b |
qwen-plus |
qwen-plus-2025-09-11 |
Если запрошенная модель не найдена ни в списке, ни среди алиасов -- используется модель по умолчанию (
qwen-max-latest, настраивается черезDEFAULT_MODEL).
Все настройки читаются из переменных окружения с фоллбэками на значения по умолчанию. Полный список задаётся в src/config.js.
| Переменная | По умолчанию | Описание |
|---|---|---|
PORT |
3264 |
Порт HTTP-сервера |
HOST |
0.0.0.0 |
Адрес привязки |
DEFAULT_MODEL |
qwen-max-latest |
Модель, используемая если не указана в запросе |
| Переменная | По умолчанию | Описание |
|---|---|---|
SKIP_ACCOUNT_MENU |
false |
Пропустить интерактивное меню аккаунтов |
NON_INTERACTIVE |
false |
Аналог SKIP_ACCOUNT_MENU |
CHROME_PATH |
(авто) | Путь к исполняемому файлу Chromium/Chrome |
| Переменная | По умолчанию | Описание |
|---|---|---|
PAGE_TIMEOUT |
120000 (2 мин) |
Таймаут загрузки страниц |
AUTH_TIMEOUT |
120000 (2 мин) |
Таймаут ожидания авторизации |
NAVIGATION_TIMEOUT |
60000 (1 мин) |
Таймаут навигации браузера |
RETRY_DELAY |
2000 (2 сек) |
Задержка между повторными попытками |
STREAMING_CHUNK_DELAY |
20 (20 мс) |
Задержка между SSE-чанками при streaming |
| Переменная | По умолчанию | Описание |
|---|---|---|
PAGE_POOL_SIZE |
3 |
Размер пула страниц браузера |
MAX_FILE_SIZE |
10485760 (10 МБ) |
Максимальный размер загружаемого файла |
MAX_HISTORY_LENGTH |
100 |
Максимальное число записей в локальной истории |
MAX_RETRY_COUNT |
3 |
Максимальное число повторных попыток при ошибках |
| Переменная | По умолчанию | Описание |
|---|---|---|
LOG_LEVEL |
info |
Уровень логирования (error, warn, info, debug) |
LOG_MAX_SIZE |
5242880 (5 МБ) |
Максимальный размер файла лога |
LOG_MAX_FILES |
5 |
Количество ротируемых файлов логов |
| Переменная | По умолчанию | Описание |
|---|---|---|
VIEWPORT_WIDTH |
1920 |
Ширина viewport браузера |
VIEWPORT_HEIGHT |
1080 |
Высота viewport браузера |
USER_AGENT |
Chrome 131 | User-Agent строка |
| Переменная | По умолчанию | Описание |
|---|---|---|
SESSION_DIR |
session |
Директория для хранения сессий и токенов |
UPLOADS_DIR |
uploads |
Директория для временных файлов загрузки |
LOGS_DIR |
logs |
Директория для файлов логов |
| Переменная | По умолчанию | Описание |
|---|---|---|
QWEN_BASE_URL |
https://chat.qwen.ai |
Базовый URL Qwen |
CHAT_API_URL |
{base}/api/v2/chat/completions |
URL API чата |
CREATE_CHAT_URL |
{base}/api/v2/chats/new |
URL создания чата |
STS_TOKEN_API_URL |
{base}/api/v1/files/getstsToken |
URL получения STS-токена |
AUTH_SIGNIN_URL |
{base}/auth?action=signin |
URL страницы авторизации |
├── index.js # Точка входа: Express-сервер, меню аккаунтов
├── package.json
├── Dockerfile
├── docker-compose.yml
│
├── src/
│ ├── config.js # Центральный модуль конфигурации (env-переменные)
│ ├── AvailableModels.txt # Список доступных моделей
│ ├── Authorization.txt # API-ключи для авторизации запросов
│ │
│ ├── api/
│ │ ├── routes.js # Определение REST-эндпоинтов
│ │ ├── chat.js # Отправка сообщений к Qwen API, извлечение токенов
│ │ ├── chatHistory.js # Локальная история чатов
│ │ ├── fileUpload.js # Загрузка файлов в Qwen OSS
│ │ ├── modelMapping.js # Маппинг алиасов моделей
│ │ └── tokenManager.js # Управление токенами, ротация аккаунтов
│ │
│ ├── browser/
│ │ ├── browser.js # Инициализация Puppeteer, управление контекстом
│ │ ├── auth.js # Проверка авторизации в браузере
│ │ └── session.js # Сохранение/загрузка сессий
│ │
│ ├── logger/
│ │ └── index.js # Winston-логгер с ротацией файлов
│ │
│ └── utils/
│ ├── accountSetup.js # Интерактивное управление аккаунтами
│ └── prompt.js # Утилита для интерактивного ввода
│
├── scripts/
│ └── auth.js # CLI-скрипт авторизации (npm run auth)
│
├── examples/ # Примеры использования API
│ ├── openai-sdk/ # Примеры с OpenAI SDK
│ ├── direct-api/ # Примеры с fetch/axios
│ └── file-upload/ # Пример загрузки файлов
│
├── session/ # Данные сессий и аккаунтов (создаётся автоматически)
├── logs/ # Файлы логов (создаётся автоматически)
└── uploads/ # Временные файлы загрузки (создаётся автоматически)