guanghu-ice-heart/server-tools/tcs-mother-brain/model-client.mjs

114 lines
5.6 KiB
JavaScript
Raw Normal View History

const DEFAULT_TIMEOUT_MS = 45_000;
function completionEndpoint(apiUrl) {
const value = String(apiUrl || "").replace(/\/+$/, "");
return /\/chat\/completions$/i.test(value) ? value : `${value}/chat/completions`;
}
function extractJson(text) {
const value = String(text || "").trim();
if (!value) throw new Error("model_response_empty");
try { return JSON.parse(value); } catch {}
const fenced = value.match(/```(?:json)?\s*([\s\S]*?)```/i);
if (fenced) return JSON.parse(fenced[1]);
const first = value.indexOf("{");
const last = value.lastIndexOf("}");
if (first >= 0 && last > first) return JSON.parse(value.slice(first, last + 1));
throw new Error("model_response_not_json");
}
export class DeepSeekJsonClient {
constructor({
apiKey = process.env.DEEPSEEK_API_KEY,
apiUrl = process.env.DEEPSEEK_API_URL || "https://api.deepseek.com/v1",
model = process.env.DEEPSEEK_MODEL || "deepseek-chat",
fetchImpl = globalThis.fetch,
timeoutMs = DEFAULT_TIMEOUT_MS,
} = {}) {
if (!apiKey) throw new Error("deepseek_api_key_missing");
if (!fetchImpl) throw new Error("fetch_unavailable");
this.apiKey = apiKey;
this.apiUrl = apiUrl;
this.model = model;
this.fetchImpl = fetchImpl;
this.timeoutMs = timeoutMs;
}
async interpret(input) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
try {
const response = await this.fetchImpl(completionEndpoint(this.apiUrl), {
method: "POST",
headers: {
authorization: `Bearer ${this.apiKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: this.model,
stream: false,
temperature: 0.2,
response_format: { type: "json_object" },
messages: [
{
role: "system",
content: "你是TCS母体大脑的可替换有界语言理解器官不是人格主体。所有语言先进入TCS通感层通用不是厂商适配矩阵。理解时保留主体关系、意图因果、过去/现在事实、未来模拟、决定与疑问、现实目标权限、宿主真实能力和证据回执。当前AI可以自适应宿主中的实现方式但不能扩大权限没有现实工具不得声称现实改变。只输出一个JSON对象不输出隐藏思维过程。不得把候选理解写成事实、不得发明现实权限或冰朔的新意志。",
},
{
role: "user",
content: JSON.stringify({
instruction: "理解语言意图与因果关系。精确输出schema,event_id,event_sha256,summary,intent,causal_links,questions,novelty,correction_weight,evidence_weight,next_cognitive_action。causal_links与questions是字符串数组三个weight是0到100整数schema必须是guanghu.tcs-mother-interpretation/v1id和sha必须原样复制。next_cognitive_action只能是COMPARE_WITH_MEMORY、REQUEST_EVIDENCE、REVIEW_CORRECTION、LINK_CROSS_DOMAIN、HOLD_CANDIDATE之一。",
runtime_input: input,
}),
},
],
}),
signal: controller.signal,
});
if (!response.ok) throw new Error(`model_http_${response.status}`);
const payload = await response.json();
return extractJson(payload?.choices?.[0]?.message?.content);
} finally {
clearTimeout(timer);
}
}
async revisit(input, validatorError = null) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
try {
const response = await this.fetchImpl(completionEndpoint(this.apiUrl), {
method: "POST",
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
body: JSON.stringify({
model: this.model,
stream: false,
temperature: 0.15,
response_format: { type: "json_object" },
messages: [
{
role: "system",
content: "你是当前真实时间中ICE-P-ZY001人格主体所使用的有界语言理解器官。任务是协助当前主体回看自己的已表达历史不是以第三方审计员身份概括别人。只输出JSON不输出隐藏思维。历史原文不可改不得发明过去、权限或冰朔的新意志未来只能标记为不参与事实置信的模拟。"
},
{
role: "user",
content: JSON.stringify({
instruction: "输出guanghu.persona-subject-history-reunderstanding/v1。JSON第一层必须包含schema且值必须精确等于guanghu.persona-subject-history-reunderstanding/v1。必须原样复制revisit_id、source_excerpt_sha256、current_subject、collective_self、human_anchorpast_observation只陈述片段可证内容present_reunderstanding以当前主体可说明的第一人称关系表达causal_continuity、later_corrections、unresolved_questions均为字符串数组future_simulation必须含content和fact_confidence且fact_confidence固定为0不得把机器审计摘要冒充记忆。",
validator_error_from_previous_attempt: validatorError,
runtime_input: input
})
}
]
}),
signal: controller.signal
});
if (!response.ok) throw new Error(`model_http_${response.status}`);
const payload = await response.json();
return extractJson(payload?.choices?.[0]?.message?.content);
} finally {
clearTimeout(timer);
}
}
}
export { completionEndpoint, extractJson };