73 lines
2.4 KiB
JavaScript
73 lines
2.4 KiB
JavaScript
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|||
|
|
// vector/llm/llm-service.js
|
|||
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
import { xbLog } from '../../../../core/debug-core.js';
|
|||
|
|
|
|||
|
|
const MODULE_ID = 'vector-llm-service';
|
|||
|
|
|
|||
|
|
// 唯一 ID 计数器
|
|||
|
|
let callCounter = 0;
|
|||
|
|
|
|||
|
|
function getStreamingModule() {
|
|||
|
|
const mod = window.xiaobaixStreamingGeneration;
|
|||
|
|
return mod?.xbgenrawCommand ? mod : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function generateUniqueId(prefix = 'llm') {
|
|||
|
|
callCounter = (callCounter + 1) % 100000;
|
|||
|
|
return `${prefix}-${callCounter}-${Date.now().toString(36)}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function b64UrlEncode(str) {
|
|||
|
|
const utf8 = new TextEncoder().encode(String(str));
|
|||
|
|
let bin = '';
|
|||
|
|
utf8.forEach(b => bin += String.fromCharCode(b));
|
|||
|
|
return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 统一LLM调用 - 走酒馆后端(非流式)
|
|||
|
|
*/
|
|||
|
|
export async function callLLM(messages, options = {}) {
|
|||
|
|
const {
|
|||
|
|
temperature = 0.2,
|
|||
|
|
max_tokens = 500,
|
|||
|
|
} = options;
|
|||
|
|
|
|||
|
|
const mod = getStreamingModule();
|
|||
|
|
if (!mod) throw new Error('生成模块未加载');
|
|||
|
|
|
|||
|
|
const top64 = b64UrlEncode(JSON.stringify(messages));
|
|||
|
|
|
|||
|
|
// ★ 每次调用用唯一 ID,避免 session 冲突
|
|||
|
|
const uniqueId = generateUniqueId('l0');
|
|||
|
|
|
|||
|
|
const args = {
|
|||
|
|
as: 'user',
|
|||
|
|
nonstream: 'true',
|
|||
|
|
top64,
|
|||
|
|
id: uniqueId,
|
|||
|
|
temperature: String(temperature),
|
|||
|
|
max_tokens: String(max_tokens),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 非流式直接返回结果
|
|||
|
|
const result = await mod.xbgenrawCommand(args, '');
|
|||
|
|
return String(result ?? '');
|
|||
|
|
} catch (e) {
|
|||
|
|
xbLog.error(MODULE_ID, 'LLM调用失败', e);
|
|||
|
|
throw e;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function parseJson(text) {
|
|||
|
|
if (!text) return null;
|
|||
|
|
let s = text.trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim();
|
|||
|
|
try { return JSON.parse(s); } catch { }
|
|||
|
|
const i = s.indexOf('{'), j = s.lastIndexOf('}');
|
|||
|
|
if (i !== -1 && j > i) try { return JSON.parse(s.slice(i, j + 1)); } catch { }
|
|||
|
|
return null;
|
|||
|
|
}
|