AIパーソナル・ラーニング
と実践的なガイダンス

Qwen Chatでオープン/クローズドソースモデルのAPIをすべて無料で入手できます!

この記事は2025-01-18 11:46に更新されました。内容の一部は一刻を争うものですので、無効な場合はメッセージを残してください!

少し前に発表された海外版『知憲』問題 Qwenチャット クウェン・チャットは、その二次的な発展を利用している。 WebUIを開く チャット・インターフェースは、Qwenの一連の大きなモデルすべてにアクセスでき、Qwen2.5-plusのクローズドソースのモデリング能力は非常に優れており、あらゆる種類のタスクに使用できる。

注:QVQとQWQは似ている o1は複数ラウンドの対話をサポートしない。


Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

Qwen Chat All Models API の使用方法

Qwen API プロセスの取得

1.ラウンド・ダイアローグの実施

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

2.ブラウザの開発者ツールを開き、アプリケーション-ローカル・ストレージ・スペース-ウェブサイトを選択する。

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

3.アクセス トークン 以下、全文を転載する。

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

 

4.フルAPIアドレス

URL:https://chat.qwenlm.ai/api

KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRjZTBhNWIwLTgzYTUtNGQ3My04MmEzLWIyNmExMTcyZjY5MiIsImV4cCI6MTczOTA3ODEyOX0.PE5hjIPUa7XhcegjRRLtwlNjsIWR5MG32mIF0Pr1GoQ

 

5.オプション・モデル

千の質問モデルの標準モデル(qwen-plus-latest、qwen2.5-coder-32b-instructなど)を使用する。

 

QwenトランジットAPIの構築

インターフェイスをOpenAIフォーマットと互換性を持たせ、あらゆる例外のオリジナルアドレスの使用を避ける。cloudflareのワーカーリレーに依存し、プロセスの特定の登録と使用は省略されます。

1.次のコードを保存する

// Qwen API 配置
const QWEN_API_URL = 'https://chat.qwenlm.ai/api/chat/completions';
const QWEN_MODELS_URL = 'https://chat.qwenlm.ai/api/models';
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000; // 1秒
const TIMEOUT_DURATION = 30000; // 30秒超时
const MAX_BUFFER_SIZE = 1024 * 1024; // 1MB 缓冲区限制
const MAX_CONCURRENT_REQUESTS = 100; // 最大并发请求数
const MODELS_CACHE_TTL = 3600000; // 模型缓存时间 1小时
// 缓存对象
let modelsCache = {
data: null,
timestamp: 0
};
// 并发计数
let currentRequests = 0;
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 获取模型列表(带缓存)
async function getModels(authHeader) {
const now = Date.now();
if (modelsCache.data && (now - modelsCache.timestamp) < MODELS_CACHE_TTL) {
return modelsCache.data;
}
const response = await fetchWithRetry(QWEN_MODELS_URL, {
headers: { 'Authorization': authHeader }
});
const data = await response.text();
modelsCache = {
data,
timestamp: now
};
return data;
}
async function fetchWithRetry(url, options, retries = MAX_RETRIES) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_DURATION);
options.signal = controller.signal;
let lastError;
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
const responseClone = response.clone();
const responseText = await responseClone.text();
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html') || response.status === 500) {
lastError = {
status: response.status,
contentType,
responseText: responseText.slice(0, 1000),
headers: Object.fromEntries(response.headers.entries())
};
if (i < retries - 1) {
await sleep(RETRY_DELAY * Math.pow(2, i)); // 指数退避
続ける;
}
}
clearTimeout(timeoutId);
return new Response(responseText, {
status: response.status,
headers: {
'Content-Type': contentType || 'application/json',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
});
} catch (error) {
lastError = error;
if (i < retries - 1) {
await sleep(RETRY_DELAY * Math.pow(2, i));
continue;
}
}
}
clearTimeout(timeoutId);
throw new Error(JSON.stringify({
error: true,
message: 'All retry attempts failed',
lastError,
retries
}));
}
// 响应压缩
async function compressResponse(response, request) {
const acceptEncoding = request.headers.get('Accept-Encoding') || '';
const contentType = response.headers.get('Content-Type') || '';
// 只对文本和 JSON 响应进行压缩
if (!contentType.includes('text/') && !contentType.includes('application/json')) {
return response;
}
const content = await response.text();
const encoder = new TextEncoder();
const bytes = encoder.encode(content);
if (acceptEncoding.includes('br')) {
// 使用 Brotli 压缩
const compressed = new Uint8Array(bytes.buffer);
return new Response(compressed, {
headers: {
...Object.fromEntries(response.headers),
'Content-Encoding': 'br',
'Content-Type': contentType
}
});
}
return response;
}
async function processLine(line, writer, previousContent) {
const encoder = new TextEncoder();
try {
const data = JSON.parse(line.slice(6));
if (data.choices?.[0]?.delta?.content) {
const currentContent = data.choices[0].delta.content;
let newContent = currentContent;
if (currentContent.startsWith(previousContent) && previousContent.length > 0) {
newContent = currentContent.slice(previousContent.length);
}
const newData = {
...data,
choices: [{
...data.choices[0],
delta: {
...data.choices[0].delta,
content: newContent
}
}]
};
await writer.write(encoder.encode(`data: ${JSON.stringify(newData)}\n\n`));
return currentContent;
} else {
await writer.write(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
return previousContent;
}
} catch (e) {
await writer.write(encoder.encode(`${line}\n\n`));
return previousContent;
}
}
// 处理流
async function handleStream(reader, writer, previousContent, timeout) {
const encoder = new TextEncoder();
let buffer = '';
let lastProcessTime = Date.now();
try {
while (true) {
// 检查超时
if (Date.now() - lastProcessTime > TIMEOUT_DURATION) {
throw new Error('Stream processing timeout');
}
const { done, value } = await reader.read();
if (done) {
clearTimeout(timeout);
if (buffer) {
const lines = buffer.split('\n');
for (const line of lines) {
if (line.trim().startsWith('data: ')) {
await processLine(line, writer, previousContent);
}
}
}
await writer.write(encoder.encode('data: [DONE]\n\n'));
await writer.close();
break;
}
lastProcessTime = Date.now();
const chunk = new TextDecoder().decode(value);
buffer += chunk;
// 检查缓冲区大小
if (buffer.length > MAX_BUFFER_SIZE) {
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim().startsWith('data: ')) {
const result = await processLine(line, writer, previousContent);
if (result) {
previousContent = result;
}
}
}
}
// 处理完整的行
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim().startsWith('data: ')) {
const result = await processLine(line, writer, previousContent);
if (result) {
previousContent = result;
}
}
}
}
} catch (error) {
clearTimeout(timeout);
await writer.write(encoder.encode(`data: {"error":true,"message":"${error.message}"}\n\n`));
await writer.write(encoder.encode('data: [DONE]\n\n'));
await writer.close();
}
}
// 错误处理
const ERROR_TYPES = {
TIMEOUT: 'timeout_error',
NETWORK: 'network_error',
AUTH: 'auth_error',
RATE_LIMIT: 'rate_limit_error',
VALIDATION: 'validation_error'
};
async function handleError(error, request) {
const errorContext = {
type: error.type || ERROR_TYPES.NETWORK,
timestamp: Date.now(),
url: request.url,
headers: Object.fromEntries(request.headers),
message: error.message
};
return new Response(JSON.stringify({
error: true,
error_type: errorContext.type,
message: error.message
}), {
status: error.status || 500,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
}
});
}
async function handleRequest(request) {
// 并发控制
if (currentRequests >= MAX_CONCURRENT_REQUESTS) {
return new Response(JSON.stringify({
error: true,
error_type: ERROR_TYPES.RATE_LIMIT,
message: 'Too Many Requests'
}), {
status: 429,
headers: {
'Content-Type': 'application/json',
'Retry-After': '5',
'Cache-Control': 'no-cache'
}
});
}
currentRequests++;
try {
// 处理获取模型列表的请求
if (request.method === 'GET' && new URL(request.url).pathname === '/v1/models') {
const authHeader = request.headers.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
throw {
type: ERROR_TYPES.AUTH,
status: 401,
message: 'Unauthorized'
};
}
try {
const modelsResponse = await getModels(authHeader);
return await compressResponse(new Response(modelsResponse, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
}), request);
} catch (error) {
throw {
type: ERROR_TYPES.NETWORK,
status: 500,
message: error.message
};
}
}
if (request.method !== 'POST') {
throw {
type: ERROR_TYPES.VALIDATION,
status: 405,
message: 'Method not allowed'
};
}
const authHeader = request.headers.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
throw {
type: ERROR_TYPES.AUTH,
status: 401,
message: 'Unauthorized'
};
}
const requestData = await request.json();
const { messages, stream = false, model, max_tokens } = requestData;
if (!model) {
throw {
type: ERROR_TYPES.VALIDATION,
status: 400,
message: 'Model parameter is required'
};
}
// 构建请求
const qwenRequest = {
model,
messages,
stream
};
if (max_tokens !== undefined) {
qwenRequest.max_tokens = max_tokens;
}
// 设置超时
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_DURATION);
try {
const response = await fetch(QWEN_API_URL, {
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify(qwenRequest),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw {
type: ERROR_TYPES.NETWORK,
status: response.status,
message: `Qwen API error: ${response.status}`
};
}
if (stream) {
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const reader = response.body.getReader();
const streamTimeout = setTimeout(() => controller.abort(), TIMEOUT_DURATION);
handleStream(reader, writer, '', streamTimeout);
return new Response(readable, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
});
} else {
const responseData = await response.text();
return await compressResponse(new Response(responseData, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
}), request);
}
} catch (error) {
clearTimeout(timeoutId);
throw {
type: error.name === 'AbortError' ? ERROR_TYPES.TIMEOUT : ERROR_TYPES.NETWORK,
status: 500,
message: error.message
};
}
} catch (error) {
return handleError(error, request);
} finally {
currentRequests--;
}
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});

 

2. 新しい worker.js にコードを貼り付けて保存します。

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

3.cloudflareのドメイン名は国内から直接アクセスできないので、ドメイン名をバインドするには

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

4.開くと、トランジットAPIが正常にデプロイされたことを示す以下の情報が表示される。

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

クライアントでの Qwen API の設定

には ルー・クライン 一例を挙げよう:

URLは次のようにも書ける: https://qwenapi.aishare.us.kg/v1

没入型翻訳URL充填フォーマット:https://qwenapi.aishare.us.kg/v1/chat/completions

Qwen Chatを使用して、すべてのオープン/クローズド・ソース・モデルを無料で取得 API-1

 

もっとChat2API:APIインターフェースへの自由な対話マクロモデル反転のコレクション

無断転載を禁じます:チーフAIシェアリングサークル " Qwen Chatでオープン/クローズドソースモデルのAPIをすべて無料で入手できます!

チーフAIシェアリングサークル

チーフAIシェアリングサークルは、AI学習に焦点を当て、包括的なAI学習コンテンツ、AIツール、実践指導を提供しています。私たちの目標は、高品質のコンテンツと実践的な経験の共有を通じて、ユーザーがAI技術を習得し、AIの無限の可能性を一緒に探求することです。AI初心者でも上級者でも、知識を得てスキルを向上させ、イノベーションを実現するための理想的な場所です。

お問い合わせ
ja日本語