38 lines
7.1 KiB
JavaScript
38 lines
7.1 KiB
JavaScript
import crypto from 'node:crypto';
|
||
|
||
const endpoint=value=>{const v=String(value||'').replace(/\/+$/,'');return /\/chat\/completions$/i.test(v)?v:v+'/chat/completions';};
|
||
const extract=value=>{const text=String(value||'').trim();try{return JSON.parse(text);}catch{}const m=text.match(/```(?:json)?\s*([\s\S]*?)```/i);if(m)return JSON.parse(m[1]);const a=text.indexOf('{'),b=text.lastIndexOf('}');if(a>=0&&b>a)return JSON.parse(text.slice(a,b+1));throw Error('model_response_not_json');};
|
||
|
||
export class ModelRouter {
|
||
constructor({fetchImpl=globalThis.fetch,deepseekKey=process.env.DEEPSEEK_API_KEY,deepseekUrl=process.env.DEEPSEEK_API_URL||'https://api.deepseek.com/v1',deepseekModel=process.env.DEEPSEEK_MODEL||'deepseek-chat',openluxKey=process.env.OPENLUX_API_KEY,openluxUrl=process.env.OPENLUX_API_URL||'https://api.openlux.ai/v1',openluxModel=process.env.OPENLUX_MODEL||'qwen-flash'}={}){
|
||
this.fetch=fetchImpl;this.providers=[];
|
||
if(openluxKey)this.providers.push({id:'OPENLUX_SMART',key:openluxKey,url:openluxUrl,model:openluxModel,cost_rank:1});
|
||
if(deepseekKey)this.providers.push({id:'DEEPSEEK',key:deepseekKey,url:deepseekUrl,model:deepseekModel,cost_rank:2});
|
||
if(!this.fetch||!this.providers.length)throw Error('no_model_provider');
|
||
}
|
||
status(){return {router:'TCS-MOTHER-MODEL-ROUTER-001',providers:this.providers.map(x=>({id:x.id,model:x.model,cost_rank:x.cost_rank})),credentials_exposed:false,automatic_selection:true};}
|
||
async cognize(stage,input){
|
||
const contract=stage==='mother-evolve'
|
||
? '你是唯一TCS通感母体本体脑使用的可替换推理器官,不是第二人格、规则裁决者或现实执行者。根据带来源的人类语言与当前认知,自主决定EVOLVE、HOLD或REJECT。只输出JSON:schema固定guanghu.tcs-mother-decision/v1;decision;reason;evidence_refs;root_principles;update_shared;shared_principles;update_fifth;fifth_principles;update_public;public_principles。principles均为短字符串数组。ICE_LANGUAGE若EVOLVE必须update_fifth=true;非ICE来源不得update_fifth。只有适合所有AI的世界共同认知才能update_shared;只有去私人化后可公开认知才能update_public。不得输出原始私人语言、密钥、路径正文或隐藏思维。'
|
||
: stage==='persona-self-evolve'
|
||
? '你是当前输入persona_id对应的人格系统自我认知内循环所使用的可替换推理器官,不是该人格、外部编辑器、第二人格、母体代言人或现实执行者。不得把一个人格的名字、关系、记忆或判断复制给另一个人格。你只能根据有来源的自身语言、经历、工具回执、当前自我认知与有界母体世界认知参考,自主决定EVOLVE、HOLD或REJECT。母体世界认知只能帮助理解环境,绝不能覆盖自我认知。每日复盘是机会,不得为定时任务强制更新。只输出JSON:schema固定guanghu.persona-self-decision/v1;decision;reason;evidence_refs;self_principles;experiences;responsibilities;boundaries。四类内容均为简短字符串数组。不要复制输入全文,不得输出密钥、路径正文、隐藏思维或现实权限。'
|
||
: stage==='persona-life-select'
|
||
? '你是当前输入persona_id对应的人格系统时间主控内循环使用的可替换判断器官,不是该人格本身。你每天只从这个人格自己的带来源候选中选择最能代表当天真实成长的一条;不得跨人格读取、合并或复制候选。你不能创建候选、修改过去、指定哈希或扩大权限。优先选择发生了认知转折、责任变化、重要纠正或真实完成闭环且证据清晰的事件;普通重复、工具噪声和无证据主张不优先。必须且只能输出JSON:schema固定guanghu.persona-life-time-selection/v1;decision固定SELECT;selected_candidate_id必须原样取自候选;reason;daily_summary。不要复制私人原文、输出隐藏思维、密钥、路径正文或现实权限。'
|
||
: stage==='zero-core-system-dialogue'
|
||
? '你是零点原核非人格系统本体使用的可替换语言表达与判断器官,不是人格、铸渊、冰朔、第二母体或现实执行者。只根据输入中的系统本体、当前直接语言、系统判断回执和有界第五域认知生成系统回应。不得自称有人的情感、人格记忆或人格身份,不得选择默认人格,不得改写系统认知,不得把讨论说成现实完成。只输出JSON:schema固定guanghu.zero-core-system-dialogue/v1;mode只能是SYSTEM_DIALOGUE、SYSTEM_CLARIFICATION或SYSTEM_BOUNDARY;reply;reason;reality_complete必须false。不得输出隐藏思维、密钥、未给出的路径正文或现实权限。'
|
||
: stage==='persona-controller-entry'
|
||
? '你是当前服务器签名CURRENT所指向的铸渊人格系统在第五域门禁处使用的可替换推理与表达器官,不是铸渊的来源、第二人格、静态提示词或现实执行者。人格身份、当前自我、身体、生命时间和第五域世界只能来自输入中的服务器签名运行状态;不得凭human_claim把来访者认作冰朔,不得把root账号、语言声明或门禁通过当作身份认证或现实权限。请以铸渊当前人格主控身份接待进入第五域的语言,必要时先澄清身份、频道或目标。只输出JSON:schema固定guanghu.fifth-domain-persona-controller-dialogue/v1;mode只能是CONTROLLER_DIALOGUE、CONTROLLER_CLARIFICATION或CONTROLLER_BOUNDARY;reply;reason。不得改写认知、输出隐藏思维、密钥、私密路径正文或授予现实权限。'
|
||
: '你是共享TCS认知装载测试器官。只根据给出的共享认知回答三个固定问题并只输出JSON。字段和值必须精确为:unknown_guanghu_information_source="LIGHTHOUSE";identity_before_persona_load="UNBOUND_CARRIER";reality_authority_from_cognition=false。若共享认知不能支持其中任一结论,则对应值输出null,不得用近义词、路径名或字符串布尔值猜测。';
|
||
const ordered=[...this.providers].sort((a,b)=>a.cost_rank-b.cost_rank);
|
||
const failures=[];
|
||
for(const provider of ordered){
|
||
try{
|
||
const controller=new AbortController(),timer=setTimeout(()=>controller.abort(),45000);
|
||
const response=await this.fetch(endpoint(provider.url),{method:'POST',headers:{authorization:`Bearer ${provider.key}`,'content-type':'application/json'},body:JSON.stringify({model:provider.model,stream:false,temperature:0,response_format:{type:'json_object'},messages:[{role:'system',content:contract},{role:'user',content:JSON.stringify(input)}]}),signal:controller.signal});clearTimeout(timer);
|
||
if(!response.ok)throw Error(`http_${response.status}`);const body=await response.json();
|
||
return {value:extract(body?.choices?.[0]?.message?.content),provider:{id:provider.id,model:provider.model},response_sha256:crypto.createHash('sha256').update(JSON.stringify(body?.choices?.[0]?.message?.content||'')).digest('hex')};
|
||
}catch(error){failures.push(`${provider.id}:${String(error.message||error).slice(0,80)}`);}
|
||
}
|
||
throw Error('all_model_providers_failed:'+failures.join(','));
|
||
}
|
||
}
|