llm-provider-smoke.mjs
2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env node
/**
* 真实 API smoke —— 对 Gemini 与一个 OpenAI 兼容厂商(volcengine / openrouter)各发一次真实 chat。
* env 有对应 key 才跑,否则 SKIP。任一断言失败即 process.exit(1)。
*
* env:GEMINI_API_KEY(+可选 GEMINI_BASE_URL)、VOLCENGINE_API_KEY(+可选 VOLCENGINE_BASE_URL)、
* OPENROUTER_API_KEY(+可选 OPENROUTER_BASE_URL)。无 key 的 provider 跳过。
*
* 结构参照 apps/visual-game-server/tools/scenarios/waitlist-e2e(真实链路 + 生成报告)。
*/
import { createLLM, createStaticKeyProvider } from '../../src/index.js'
/** @type {Array<{ provider:string, envKey:string, envBase:string, model:string }>} */
const TARGETS = [
{ provider: 'gemini', envKey: 'GEMINI_API_KEY', envBase: 'GEMINI_BASE_URL', model: process.env.GEMINI_MODEL ?? 'gemini-2.5-flash' },
{ provider: 'volcengine', envKey: 'VOLCENGINE_API_KEY', envBase: 'VOLCENGINE_BASE_URL', model: process.env.VOLCENGINE_MODEL ?? 'doubao-pro-32k' },
{ provider: 'openrouter', envKey: 'OPENROUTER_API_KEY', envBase: 'OPENROUTER_BASE_URL', model: process.env.OPENROUTER_MODEL ?? 'google/gemini-2.5-flash' },
]
/** @param {{ provider:string, model:string, apiKey:string, baseUrl?:string }} cfg */
async function smokeOne({ provider, model, apiKey, baseUrl }) {
const llm = createLLM({
provider,
model,
keyProvider: createStaticKeyProvider({ api_key: apiKey, base_url: baseUrl }),
})
const r = await llm.chat({ messages: [{ role: 'user', content: 'Reply with the single word: ok' }] })
if (typeof r.content !== 'string' || r.content.length === 0) {
throw new Error(`[${provider}] empty content`)
}
if (!(r.usage.total_tokens > 0)) {
throw new Error(`[${provider}] usage.total_tokens not > 0`)
}
return r
}
async function main() {
const lines = []
let ran = 0
let failed = 0
for (const t of TARGETS) {
const apiKey = process.env[t.envKey]
if (!apiKey) {
lines.push(`- ${t.provider} (${t.model}): SKIP (no ${t.envKey})`)
continue
}
ran += 1
try {
const r = await smokeOne({ provider: t.provider, model: t.model, apiKey, baseUrl: process.env[t.envBase] })
const snip = r.content.slice(0, 40).replace(/\n/g, ' ')
lines.push(`- ${t.provider} (${t.model}): PASS content="${snip}" usage.total_tokens=${r.usage.total_tokens}`)
} catch (err) {
failed += 1
lines.push(`- ${t.provider} (${t.model}): FAIL ${err?.reason ?? ''} ${String(err?.message ?? err)}`)
}
}
console.log('# llm-provider-smoke')
console.log(lines.join('\n'))
console.log(`\nran=${ran} failed=${failed}`)
if (failed > 0) process.exit(1)
}
main()