113 lines
4.1 KiB
JavaScript
113 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
/**
|
|
* 验证 RAG + 引用:创建临时 AI Assistant → 调 preview API 问一个问题 → 打印命中来源 → 删除。
|
|
* 用法:node scripts/verify-rag.js "What is the minimum order value?"
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
const question = process.argv.slice(2).join(' ') || 'What is the minimum order value?';
|
|
|
|
function loadEnv(file) {
|
|
const out = {};
|
|
for (const line of fs.readFileSync(file, 'utf8').split('\n')) {
|
|
const t = line.trim();
|
|
if (!t || t.startsWith('#')) continue;
|
|
const eq = t.indexOf('=');
|
|
if (eq < 0) continue;
|
|
let v = t.slice(eq + 1).trim();
|
|
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
|
|
out[t.slice(0, eq).trim()] = v;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function createClient(baseURL) {
|
|
const cookies = new Map();
|
|
let csrf = '';
|
|
const cookieHeader = () => [...cookies.entries()].map(([k, v]) => `${k}=${v}`).join('; ');
|
|
function store(res) {
|
|
const list = typeof res.headers.getSetCookie === 'function' ? res.headers.getSetCookie() : [res.headers.get('set-cookie')].filter(Boolean);
|
|
for (const c of list) {
|
|
const [pair] = c.split(';');
|
|
const eq = pair.indexOf('=');
|
|
if (eq > 0) {
|
|
const k = pair.slice(0, eq).trim();
|
|
const v = pair.slice(eq + 1).trim();
|
|
cookies.set(k, v);
|
|
if (k === 'csrf_token') csrf = v;
|
|
}
|
|
}
|
|
}
|
|
async function req(method, p, body) {
|
|
const headers = { Accept: 'application/json' };
|
|
if (cookies.size) headers.Cookie = cookieHeader();
|
|
if (body !== undefined && !(body instanceof FormData)) headers['Content-Type'] = 'application/json';
|
|
if (csrf && method !== 'GET') headers['X-CSRFTOKEN'] = csrf;
|
|
const res = await fetch(baseURL + p, {
|
|
method,
|
|
headers,
|
|
body: body === undefined ? undefined : (body instanceof FormData ? body : JSON.stringify(body)),
|
|
});
|
|
store(res);
|
|
const text = await res.text();
|
|
let json = null;
|
|
try { json = text ? JSON.parse(text) : null; } catch { /* ignore */ }
|
|
if (!res.ok) throw new Error(`${method} ${p} -> HTTP ${res.status}: ${(json && json.message) || text.slice(0, 400)}`);
|
|
return json;
|
|
}
|
|
return { get: (p) => req('GET', p), post: (p, b) => req('POST', p, b), del: (p) => req('DELETE', p) };
|
|
}
|
|
|
|
async function main() {
|
|
const env = loadEnv(path.join(ROOT, '.env'));
|
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
|
const c = createClient(base);
|
|
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
|
|
|
const data = {
|
|
name: `KB Verify ${Date.now()}`,
|
|
description: 'temporary assistant for RAG verification',
|
|
instructions: 'Answer from the knowledge base. If the knowledge base has no answer, say you could not find it.',
|
|
guardrails: '',
|
|
expectation: '',
|
|
tone: 'professional',
|
|
response_length: 'balanced',
|
|
max_turns: 5,
|
|
fallback_team_id: null,
|
|
citations_enabled: true,
|
|
handoff_enabled: false,
|
|
languages: [],
|
|
enabled: true,
|
|
tool_ids: [],
|
|
};
|
|
const form = new FormData();
|
|
form.append('data', JSON.stringify(data));
|
|
const created = await c.post('/api/v1/ai/assistants', form);
|
|
const assistant = created.data;
|
|
console.log(`临时 Assistant #${assistant.id} 创建成功`);
|
|
|
|
try {
|
|
const preview = await c.post(`/api/v1/ai/assistants/${assistant.id}/preview`, { message: question });
|
|
const out = preview.data || {};
|
|
console.log(`\n问题: ${question}`);
|
|
console.log(`回复:\n${out.reply}\n`);
|
|
console.log('命中来源:');
|
|
for (const s of out.sources || []) {
|
|
console.log(` - [${s.type}] #${s.id} score=${(s.score || 0).toFixed(3)} ${s.title || ''}${s.url ? ' ' + s.url : ''}`);
|
|
}
|
|
if (!(out.sources || []).length) console.log(' (无命中)');
|
|
} finally {
|
|
await c.del(`/api/v1/ai/assistants/${assistant.id}`);
|
|
console.log(`\n临时 Assistant #${assistant.id} 已删除`);
|
|
}
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('[verify-rag]', err.message);
|
|
process.exit(1);
|
|
});
|