Files
Toolbox/dev_test_scripts/debug/debug_probe_max_tokens.js
T

88 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
* debug_probe_max_tokens.js —— 探测 chat 模型可接受的 max_tokens 上限
*
* 背景:「游山玩水」整份行程 JSON 约 1.2-1.6 万 output token,
* 用 qwen-plus-latest + max_tokens=8000 会截断(finish_reason=length)。
* 本脚本用极短的 prompt 试不同 max_tokens,找出模型实际能接受的上限,
* 顺便列出可用 chat 模型。
*
* 运行:node dev_test_scripts/debug/debug_probe_max_tokens.js
* 说明:只读探测,用极短 prompt(输出 1-2 个 token),几乎不产生费用。
* ============================================================ */
const fs = require('fs')
const path = require('path')
const envPath = path.join(process.env.USERPROFILE || 'C:\\Users\\Administrator', 'Toolbox_local_creds.env.local')
if (fs.existsSync(envPath)) {
for (const line of fs.readFileSync(envPath, 'utf8').split(/\r?\n/)) {
if (!line || /^\s*#/.test(line)) continue
const i = line.indexOf('=')
if (i < 0) continue
const k = line.slice(0, i).trim()
const v = line.slice(i + 1).trim().replace(/^["']|["']$/g, '')
if (k && !(k in process.env)) process.env[k] = v
}
}
const HOST = (process.env.DASHSCOPE_API_HOST_FOR_OPENAI || '').replace(/\/+$/, '')
const KEY = process.env.DASHSCOPE_API_KEY || ''
const URL = HOST ? HOST + '/chat/completions' : ''
const MODELS = [
'qwen-plus-latest',
'qwen-max-latest',
'qwen3-max',
'qwen3.5-plus',
'qwen3.5-plus-latest',
'qwen-turbo-latest'
]
const BUDGETS = [8192, 16384, 32000]
const tryOne = async (model, maxTokens) => {
try {
const r = await fetch(URL, {
method: 'POST',
headers: { Authorization: 'Bearer ' + KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ model, messages: [{ role: 'user', content: '只回复两个字:好的' }], max_tokens: maxTokens }),
signal: AbortSignal.timeout(60000)
})
const t = await r.text()
let j = null
try { j = JSON.parse(t) } catch {}
if (r.status === 200 && j && j.choices) {
const u = j.usage || {}
return { ok: true, note: 'completion=' + (u.completion_tokens === undefined ? '?' : u.completion_tokens) }
}
return { ok: false, note: 'HTTP ' + r.status + ' ' + String((j && j.message) || t).slice(0, 130) }
} catch (e) {
return { ok: false, note: 'ERR ' + e.message }
}
}
const main = async () => {
console.log('host:', HOST ? '已配置' : '缺失', ' key:', KEY ? '已加载' : '缺失')
console.log('\n===== 可用 chat 模型(MaaS 声明) =====')
try {
const r = await fetch(HOST + '/models', { headers: { Authorization: 'Bearer ' + KEY } })
const j = JSON.parse(await r.text())
const ids = (j.data || []).map((m) => m.id)
const chat = ids.filter((id) => /qwen|deepseek|glm|kimi|llama|gpt/i.test(id) && !/image|vl|audio|asr|tts|voice|video|t2i|t2v|embed/i.test(id))
console.log('chat 类候选共 ' + chat.length + ' 个:\n ' + chat.slice(0, 50).join('\n '))
} catch (e) {
console.log('列模型失败:' + e.message)
}
console.log('\n===== max_tokens 上限探测 =====')
for (const m of MODELS) {
const line = []
for (const b of BUDGETS) {
const r = await tryOne(m, b)
line.push(b + ':' + (r.ok ? '✓' : '✗'))
if (!r.ok) { line.push('(' + r.note.slice(0, 90) + ')'); break }
}
console.log(' ' + m.padEnd(20) + ' ' + line.join(' '))
}
}
main().catch((e) => console.error('FATAL', e && e.message))