Files
Genarrative/scripts/test-ve-llm.mjs
T
kdletters d7d98acfd4 接入VectorEngine画布Agent规划
切换画布 Agent 与通用 LLM 代理到 VectorEngine gpt-5.4-mini。

为画布 Agent 注入上一轮生成结果并默认承接上一张图编辑。

补齐规范图工具分流、规范展板 prompt 要求和 JSON 残片回复兜底。

同步前后端契约、测试脚本、环境示例和项目文档。
2026-07-05 17:42:27 +08:00

164 lines
5.4 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.
import { readFileSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, '..');
function loadEnv(path) {
const content = readFileSync(path, 'utf-8');
const env = {};
for (const line of content.split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const eqIndex = trimmed.indexOf('=');
if (eqIndex === -1) continue;
const key = trimmed.slice(0, eqIndex).trim();
let value = trimmed.slice(eqIndex + 1).trim();
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
env[key] = value;
}
return env;
}
const env = loadEnv(resolve(root, '.env.secrets.local'));
const BASE = env.VECTOR_ENGINE_BASE_URL?.replace(/\/+$/, '') || 'https://api.vectorengine.cn';
const KEY = env.VECTOR_ENGINE_API_KEY || '';
if (!KEY) {
console.error('未找到 VECTOR_ENGINE_API_KEY');
process.exit(1);
}
const TIMEOUT_MS = 60_000;
async function test(name, method, path, body = null) {
const url = `${BASE}${path}`;
const start = Date.now();
try {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
const headers = {
'Authorization': `Bearer ${KEY}`,
'Content-Type': 'application/json',
};
const options = { method, headers, signal: controller.signal };
if (body) options.body = JSON.stringify(body);
const resp = await fetch(url, options);
clearTimeout(timer);
const elapsed = Date.now() - start;
const text = await resp.text();
let json = null;
try { json = JSON.parse(text); } catch {}
if (resp.ok) {
const model = json?.model || json?.data?.[0]?.id || '?';
const summary = json?.choices?.[0] ? `choices[0]: ${json.choices[0].message?.content?.slice(0, 80)}` :
json?.output_text ? `output_text: ${json.output_text.slice(0, 80)}` :
json?.data ? `${json.data.length} models` : JSON.stringify(json).slice(0, 120);
return { ok: true, elapsed, code: resp.status, model, summary };
} else {
const errMsg = json?.error?.message || json?.message || text.slice(0, 200);
return { ok: false, elapsed, code: resp.status, error: errMsg };
}
} catch (e) {
const elapsed = Date.now() - start;
return { ok: false, elapsed, code: 0, error: e.name === 'AbortError' ? `超时(${TIMEOUT_MS / 1000}s)` : e.message };
}
}
console.log(`VectorEngine LLM 能力探测`);
console.log(`目标: ${BASE}\n`);
const tests = [
// 1. 探测 /v1/models - 基础连通性 + 列出可用模型
{ name: 'GET /v1/models (列出可用模型)', method: 'GET', path: '/v1/models' },
// 2. Chat Completions - 最标准协议,项目已有 LlmProvider::OpenAiCompatible 支持
{
name: 'POST /v1/chat/completions (Chat)',
method: 'POST',
path: '/v1/chat/completions',
body: {
model: 'gpt-5.4-mini',
messages: [{ role: 'user', content: '回复 ok,不要解释' }],
max_tokens: 10,
},
},
// 3. Responses - 仅作兼容探测,creative_agent 默认走 Chat Completions
{
name: 'POST /v1/responses (Responses)',
method: 'POST',
path: '/v1/responses',
body: {
model: 'gpt-5.4-mini',
input: [
{ role: 'user', content: [{ type: 'input_text', text: '回复 ok,不要解释' }] },
],
},
},
// 4. 测试 gpt-5.4-mini (creative_agent 模型)
{
name: 'POST /v1/chat/completions (gpt-5.4-mini, Chat)',
method: 'POST',
path: '/v1/chat/completions',
body: {
model: 'gpt-5.4-mini',
messages: [{ role: 'user', content: '回复 ok' }],
max_tokens: 10,
},
},
// 5. 抓大鹅生成需要的 JSON 输出能力验证
{
name: 'POST /v1/chat/completions (JSON 输出: 抓大鹅物品)',
method: 'POST',
path: '/v1/chat/completions',
body: {
model: 'gpt-5.4-mini',
messages: [
{ role: 'system', content: '你是抓大鹅游戏编辑,只返回 JSON。' },
{ role: 'user', content: '题材:水果。请生成 JSON{"gameName":"水果切切乐","items":[{"name":"苹果","itemSize":"中"},{"name":"西瓜","itemSize":"大"}]}' },
],
max_tokens: 200,
},
},
];
let pass = 0;
let fail = 0;
for (let i = 0; i < tests.length; i++) {
const t = tests[i];
console.log(`[${i + 1}/${tests.length}] ${t.name}`);
const result = await test(t.name, t.method, t.path, t.body);
if (result.ok) {
console.log(` ✅ HTTP ${result.code} ${result.elapsed}ms model: ${result.model}`);
console.log(` ${result.summary}`);
pass++;
} else {
const codeStr = result.code === 0 ? 'NET' : `HTTP ${result.code}`;
console.log(` ❌ ${codeStr} ${result.elapsed}ms ${result.error}`);
fail++;
}
console.log();
}
console.log(`=== 结果: ${pass}/${tests.length} 通过, ${fail}/${tests.length} 失败 ===`);
// 结论
if (pass >= 3) {
console.log('\n✅ VectorEngine 支持 LLM 文本调用,可替代 Apimart。');
console.log(' 将 .env.secrets.local 中 VECTOR_ENGINE_BASE_URL / VECTOR_ENGINE_API_KEY 配好即可。');
} else if (pass <= 1) {
console.log('\n❌ VectorEngine 不支持 LLM 文本调用。');
} else {
console.log('\n⚠️ 部分支持,需进一步评估。');
}