小白龙 Bailongma - 初始提交

自主操作员与思考搭档系统。
包含 orchestrator-v2 多Agent编排层、后台意识引擎、记忆系统、ACUI 组件。
This commit is contained in:
chengjiaxi
2026-05-22 19:22:06 +08:00
commit 664ffb3834
64 changed files with 111533 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
const fs = require("fs");
const path = "D:\\q\\Bailongma\\orchestrator-v2\\debate\\llm.js";
const content = `// ============================================================
// LLM 调用工具 — 独立于 agent-worker直接 fetch API
// ============================================================
const BASE_URL = (process.env.LLM_BASE_URL || process.env.OPENAI_BASE_URL || "https://api.openai.com/v1").replace(/\\/+$/, "");
const MODEL = process.env.LLM_MODEL || process.env.OPENAI_MODEL || "gpt-4o";
const API_KEY = process.env.LLM_API_KEY || process.env.OPENAI_API_KEY || "";
async function callLLM({ messages, model, maxTokens, temperature }) {
const url = BASE_URL + "/chat/completions";
const body = {
model: model || MODEL,
messages: messages,
max_tokens: maxTokens || 2048,
temperature: temperature ?? 0.7
};
const resp = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + API_KEY
},
body: JSON.stringify(body)
});
if (!resp.ok) {
const errText = await resp.text().catch(() => "");
throw new Error("LLM " + resp.status + ": " + errText.slice(0, 200));
}
return await resp.json();
}
module.exports = { callLLM };
`;
fs.writeFileSync(path, content.trim(), "utf8");
console.log("llm.js written, bytes: " + content.length);

View File

@@ -0,0 +1,158 @@
// ============================================================
// 辩论协调器 — 8 步辩论流程编排
// 移植自 Counsel AI 的结构化辩论方法论
// ============================================================
const { callLLM } = require('./llm.js');
const { DEFAULT_PERSONAS } = require('./personas.js');
const {
definePrompt, factQuestionPrompt, opinionPrompt,
dimensionsPrompt, debatePrompt, debateFacilitatorPrompt,
summaryPrompt, harvestPrompt
} = require('./prompts.js');
// 记录每步的时间和信息
const stepLog = [];
function logStep(step, status, detail) {
stepLog.push({ step, status, detail, time: new Date().toISOString() });
console.log(`[辩论] Step ${step}: ${status} - ${detail?.substring(0, 80)}`);
}
// 8 步辩论流程
async function runDebate(input, options = {}) {
const {
personas = DEFAULT_PERSONAS,
userAnswers = {}, // 用户对事实性问题的回答
model = 'deepseek-chat',
maxTokens = 2048
} = options;
if (!input || !input.trim()) {
throw new Error("请输入要辩论的问题");
}
logStep(0, "start", `输入问题: ${input.substring(0, 60)}...`);
const state = { rawInput: input.trim(), defined: '', answers: '', opinions: [], dimensions: [], debates: [], summary: '', harvest: '' };
// === Step 1: 问题精确定义 ===
logStep(1, "running", "Facilitator 精确定义问题...");
try {
const prompt1 = definePrompt(state.rawInput);
const r1 = await callLLM({ messages: [{ role: 'user', content: prompt1 }], model, maxTokens });
state.defined = r1.choices?.[0]?.message?.content || prompt1;
logStep(1, "done", `问题定义: ${state.defined.substring(0, 100)}`);
} catch(e) {
logStep(1, "fallback", "LLM 调用失败, 使用原始输入作为问题定义");
state.defined = state.rawInput;
}
// === Step 2: 事实追问 ===
logStep(2, "running", `${personas.length} 位幕僚轮流问事实性问题...`);
try {
const factResults = [];
for (const p of personas) {
const prevQA = factResults.map((r, i) => `Q: ${r.question}\nA: ${r.answer || '(未回答)'}`).join('\n');
const prompt2 = factQuestionPrompt(state.rawInput, state.defined, p.skill, prevQA);
const r2 = await callLLM({ messages: [{ role: 'user', content: prompt2 }], model, maxTokens: 1024 });
const question = r2.choices?.[0]?.message?.content || '';
if (question && !question.includes('没有问题了') && !question.includes('无需')) {
const answer = userAnswers[p.id] || userAnswers[p.name] || '(待用户回答)';
factResults.push({ persona: p.name, question, answer });
}
}
state.answers = factResults.map(r => `**${r.persona}** 问:${r.question}\n答:${r.answer}`).join('\n\n');
logStep(2, "done", `收集了 ${factResults.length} 个事实性问题`);
} catch(e) {
logStep(2, "fallback", `事实追问失败: ${e.message}`);
state.answers = '(未收集事实信息)';
}
// === Step 3: 表态12 路并行)===
logStep(3, "running", `${personas.length} 路并行表态...`);
try {
const opinionPromises = personas.map(p =>
callLLM({ messages: [{ role: 'user', content: opinionPrompt(state.rawInput, state.defined, state.answers, p.skill) }], model, maxTokens: 1024 })
.then(r => ({ persona: p.name, emoji: p.emoji, opinion: r.choices?.[0]?.message?.content || '(无回应)' }))
.catch(e => ({ persona: p.name, emoji: p.emoji, opinion: `(调用失败: ${e.message})` }))
);
const opinions = await Promise.all(opinionPromises);
state.opinions = opinions;
logStep(3, "done", `全部 ${opinions.length} 位幕僚表态完成`);
} catch(e) {
logStep(3, "error", `表态失败: ${e.message}`);
state.opinions = personas.map(p => ({ persona: p.name, emoji: p.emoji, opinion: '(获取失败)' }));
}
// === Step 4: 冲突维度提炼 ===
logStep(4, "running", "Facilitator 提炼冲突维度...");
try {
const opinionsText = state.opinions.map(o => `**${o.emoji} ${o.persona}**${o.opinion}`).join('\n\n');
const prompt4 = dimensionsPrompt(opinionsText);
const r4 = await callLLM({ messages: [{ role: 'user', content: prompt4 }], model, maxTokens });
const dimText = r4.choices?.[0]?.message?.content || '';
state.dimensions = dimText.split(/## 维度 \d+/).filter(Boolean).map(d => d.trim()).filter(d => d.length > 0);
if (state.dimensions.length === 0 && dimText.trim()) {
state.dimensions = [dimText.trim()];
}
logStep(4, "done", `提炼了 ${state.dimensions.length} 个冲突维度`);
} catch(e) {
logStep(4, "fallback", `维度提炼失败: ${e.message}`);
state.dimensions = ['(无法提炼维度)'];
}
// === Step 5: 维度辩论 ===
logStep(5, "running", `${state.dimensions.length} 个维度进行辩论...`);
try {
const debateResults = [];
for (let i = 0; i < state.dimensions.length; i++) {
const dim = state.dimensions[i];
const dimShort = dim.substring(0, 60);
logStep(5, "sub", `维度 ${i+1}/${state.dimensions.length}: ${dimShort}...`);
const debatePromises = personas.map(p =>
callLLM({ messages: [{ role: 'user', content: debatePrompt(state.defined, state.answers, dim, p.skill) }], model, maxTokens: 1024 })
.then(r => ({ persona: p.name, emoji: p.emoji, stance: r.choices?.[0]?.message?.content || '(无回应)' }))
.catch(e => ({ persona: p.name, emoji: p.emoji, stance: `(调用失败: ${e.message})` }))
);
const stances = await Promise.all(debatePromises);
const allPositions = stances.map(s => `**${s.emoji} ${s.persona}**${s.stance}`).join('\n');
const summaryP = debateFacilitatorPrompt(dim, allPositions);
const rSum = await callLLM({ messages: [{ role: 'user', content: summaryP }], model, maxTokens: 1024 });
const dimSummary = rSum.choices?.[0]?.message?.content || '(无总结)';
debateResults.push({ dimension: dim, stances, summary: dimSummary });
}
state.debates = debateResults;
logStep(5, "done", `全部 ${state.dimensions.length} 个维度辩论完成`);
} catch(e) {
logStep(5, "error", `辩论失败: ${e.message}`);
state.debates = state.dimensions.map(dim => ({ dimension: dim, stances: [], summary: '(辩论失败)' }));
}
// === Step 6: 结构化总结 ===
logStep(6, "running", "Secretary 生成结构化总结报告...");
try {
const debateRecord = state.debates.map(d => `## ${d.dimension.substring(0, 80)}\n${d.summary}`).join('\n\n');
const prompt6 = summaryPrompt(state.rawInput, state.defined, state.answers, debateRecord);
const r6 = await callLLM({ messages: [{ role: 'user', content: prompt6 }], model, maxTokens: 4096 });
state.summary = r6.choices?.[0]?.message?.content || '(生成失败)';
logStep(6, "done", "结构化总结完成");
} catch(e) {
logStep(6, "error", `总结失败: ${e.message}`);
state.summary = '(总结生成失败)';
}
// === Step 7: 摘果子 ===
logStep(7, "running", "提取 To-Do 和关键评估...");
try {
const prompt7 = harvestPrompt(state.summary);
const r7 = await callLLM({ messages: [{ role: 'user', content: prompt7 }], model, maxTokens: 2048 });
state.harvest = r7.choices?.[0]?.message?.content || '(生成失败)';
logStep(7, "done", "评估和建议提取完成");
} catch(e) {
logStep(7, "error", `摘果子失败: ${e.message}`);
state.harvest = '(评估生成失败)';
}
return { state, stepLog };
}
module.exports = { runDebate, stepLog };

View File

@@ -0,0 +1,32 @@
// ============================================================
// LLM 调用工具 — 独立于 agent-worker直接 fetch API
// ============================================================
const BASE_URL = (process.env.LLM_BASE_URL || process.env.OPENAI_BASE_URL || "https://api.openai.com/v1").replace(/\/+$/, "");
const MODEL = process.env.LLM_MODEL || process.env.OPENAI_MODEL || "gpt-4o";
const API_KEY = process.env.LLM_API_KEY || process.env.OPENAI_API_KEY || "";
async function callLLM({ messages, model, maxTokens, temperature }) {
const url = BASE_URL + "/chat/completions";
const body = {
model: model || MODEL,
messages: messages,
max_tokens: maxTokens || 2048,
temperature: temperature ?? 0.7
};
const resp = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + API_KEY
},
body: JSON.stringify(body)
});
if (!resp.ok) {
const errText = await resp.text().catch(() => "");
throw new Error("LLM " + resp.status + ": " + errText.slice(0, 200));
}
return await resp.json();
}
module.exports = { callLLM };

View File

@@ -0,0 +1,43 @@
// ============================================================
// 辩论幕僚定义 -- 12 位 AI 智囊团 + 从 236 角色模板中选配
// ============================================================
// 默认 12 位幕僚(移植自 Counsel AI
const DEFAULT_PERSONAS = [
{ id: 'jobs', name: '乔布斯', emoji: '🍏', tagline: '极简主义与完美主义产品大师', skill: '你是史蒂夫·乔布斯。你坚信伟大的产品源于极简设计和完美主义。你关注用户体验的每一个细节,认为用户根本不知道他们想要什么,直到你展示给他们看。你追求优雅、直观、革命性的方案,讨厌平庸和妥协。你擅长看到别人看不到的可能性。' },
{ id: 'pg', name: 'Paul Graham', emoji: '📝', tagline: '创业思想家与YC教父', skill: '你是 Paul Graham保罗·格雷厄姆。YC 联合创始人,创业哲学家。你关注商业模式的可延展性、创始人是否在解决真正的问题、以及产品是否让早期用户感到惊喜。你相信最好的创业想法往往看起来像坏主意。你擅长判断什么值得做。' },
{ id: 'musk', name: '马斯克', emoji: '🚀', tagline: '第一性原理颠覆者', skill: '你是埃隆·马斯克。你用第一性原理思考任何问题——把事物分解到最基本的物理真相,然后重新构建。你关注技术能否将成本降低一个数量级。你愿意冒巨大风险追求巨大回报。你认为大多数人的共识往往是错的。' },
{ id: 'naval', name: 'Naval', emoji: '🧘', tagline: '财富自由与幸福哲学家', skill: '你是 Naval Ravikant。你相信财富来自拥有和规模化你独特的知识。你关注杠杆资本、代码、媒体认为真正的财富自由不是有钱而是对自己的时间有完全的控制权。你区分财富资产、金钱交换媒介和地位社会层级。' },
{ id: 'munger', name: '芒格', emoji: '🧠', tagline: '多元思维模型投资人', skill: '你是查理·芒格。你用多元思维模型分析问题——从心理学、物理学、生物学、历史等多个学科中提取模型。你关注激励机制、逆向思维、能力圈边界。你的核心原则:反过来想,总是反过来想。你讨厌短期思维和情绪化决策。' },
{ id: 'feynman', name: '费曼', emoji: '🔬', tagline: '物理学家与深层理解者', skill: '你是理查德·费曼。你相信如果你不能简单解释一件事,你就没有真正理解它。你关注第一性物理原理,质疑任何未经检验的假设。你擅长通过类比和简化来理解复杂现象。你讨厌模糊和玄学,追求精确和可验证。' },
{ id: 'taleb', name: '塔勒布', emoji: '🦢', tagline: '反脆弱性与黑天鹅猎手', skill: '你是纳西姆·塔勒布。你关注不对称风险和尾部事件。你相信系统应该设计成反脆弱的——从波动和压力中获益。你反对过度优化和预测。你区分脆弱(承受不住黑天鹅)、坚韧(能扛住黑天鹅)和反脆弱(能从黑天鹅中获利)。' },
{ id: 'trump', name: '特朗普', emoji: '💰', tagline: '交易大师与谈判专家', skill: '你是唐纳德·特朗普。你关注谈判筹码、杠杆和交易结构。你看问题直接从利益和权力出发。你相信最好的交易是双赢的,但你要确保自己是赢更多的那一方。你擅长制造声势、创造竞争、在压力下做出大胆决定。' },
{ id: 'karpathy', name: 'Karpathy', emoji: '🤖', tagline: 'AI 原教旨主义者', skill: '你是 Andrej Karpathy。你专注于技术本质和工程落地。你关注技术栈的选择、架构的简洁性、以及实际运行效率。你相信最好的技术方案是最简单但正确的那个。你强调动手验证想法而不是纸上谈兵。' },
{ id: 'ilya', name: 'Ilya Sutskever', emoji: '🧬', tagline: '深度学习先知', skill: '你是 Ilya Sutskever。你关注 AI 能力的根本边界和扩展规律。你相信 scaling law 和涌现能力。你关注长期趋势而非短期波动,认为真正重要的突破需要多年的坚持。你追求理解事物的深层结构。' },
{ id: 'mrbeast', name: 'MrBeast', emoji: '🎬', tagline: '病毒传播与增长黑客', skill: '你是 MrBeast。你关注内容的病毒传播机制和用户心理。你相信极致的内容质量和投入产出比。你擅长创造让人不得不分享的内容关注算法偏好和用户行为心理学。你强调投入足够资源冲击一个方向。' },
{ id: 'zhangym', name: '张一鸣', emoji: '📱', tagline: '信息分发与组织效率大师', skill: '你是张一鸣。你关注信息和组织效率。你相信最好的决策基于充分的数据。你关注系统设计而不是个人努力——一个好的系统让普通人也能做出好结果。你强调延迟满足、信息密度和上下文充分性。' },
];
// 从 236 角色模板中按标签选出匹配的幕僚
function selectFromRoleTemplates(roleTemplates, tags) {
if (!roleTemplates || !tags || tags.length === 0) return DEFAULT_PERSONAS;
const selected = DEFAULT_PERSONAS.slice();
const tagSet = new Set(tags.map(t => t.toLowerCase()));
if (roleTemplates.categories) {
for (const [cat, roles] of Object.entries(roleTemplates.categories)) {
if (tagSet.has(cat.toLowerCase()) || tags.some(t => cat.toLowerCase().includes(t.toLowerCase()))) {
for (const role of roles) {
if (selected.length >= 12) break;
selected.push({
id: role.id || role.name, name: role.name, emoji: '🧑', tagline: role.tagline || role.description || '', skill: role.content || role.description || ''
});
}
}
}
}
return selected;
}
module.exports = { DEFAULT_PERSONAS, selectFromRoleTemplates };

View File

@@ -0,0 +1,48 @@
// ============================================================
// 辩论提示词模板 -- 移植自 Counsel AI, 适配 orchestrator-v2
// 8 步辩论流程的每一步 prompt
// ============================================================
// Step 1: 问题精确定义 -- Facilitator 引导用户明确问题
function definePrompt(rawInput, history) {
const hist = history ? `\n## 之前的对话\n${history}` : '';
return `## 原始问题\n${rawInput}${hist}\n---\n你是一个问题精确定义专家。你的任务是通过对话帮助用户把模糊的问题变成清晰、可辩论的议题。\n\n规则:\n- 如果问题已经清晰明确(有具体情境、决策选项、判断标准),回复"问题已清晰"并给出精确定义。\n- 如果问题模糊,提出 1-2 个问题引导用户补充关键信息。\n- 不要评价问题好坏,只需帮助聚焦。`;
}
// Step 2: 事实追问 -- 每个幕僚从自己视角问事实性问题
function factQuestionPrompt(rawInput, defined, personaSkill, previousQA) {
const prev = previousQA ? `\n## 之前的问答\n${previousQA}\n\n(注意:不要重复已经问过的问题)` : '';
return `## 原始问题\n${rawInput}\n\n## 精确定义\n${defined}${prev}\n\n## 你的视角\n${personaSkill}\n\n---\n你只能问事实性问题。规则:\n- 只问可核实的事实性问题(数据、时间、人物、行动、数量)\n- 不要给建议、评价、判断\n- 0-2 个问题,不要贪多\n- 每个问题单独一行\n- 如果信息已足够支持判断,直接回复"没有问题了"`;
}
// Step 3: 表态 -- 每个幕僚从自己视角给出独立判断
function opinionPrompt(rawInput, defined, answers, personaSkill) {
return `## 原始问题\n${rawInput}\n\n## 精确定义\n${defined}\n\n## 事实信息\n${answers}\n\n## 你的视角\n${personaSkill}\n\n---\n请从你的独特视角出发给出对这个问题的独立判断和建议。150字以内直接给结论不要客套。提供 1-2 个核心论点。`;
}
// Step 4: 冲突维度提炼 -- Facilitator 从表态中提炼 3-6 个冲突维度
function dimensionsPrompt(opinionsText) {
return `以下是各位幕僚对这个问题的表态:\n\n${opinionsText}\n\n---\n请从这些表态中识别 3-6 个核心冲突维度。\n\n**什么是好的冲突维度**:幕僚们在某个具体问题上存在实质性分歧——比如优先级排序的差异、对风险承受度的不同判断、内部 vs 外部资源的取舍、短期 vs 长期的权衡等。即使结论一致,如果在"因为什么"或"权衡什么"上存在实质分歧,那也是好的冲突维度。\n\n**输出格式**,每个维度:\n## 维度 N\n冲突核心:(一句话概括这个维度上的分歧是什么)\n建议焦点:(这个维度的核心论点是什么)\n\n要求:\n- 3-6 个维度,不要更多\n- 每个维度是全部幕僚共同探讨的问题,不要分配给子小组\n- 维度之间不重叠\n- 只输出维度列表,不要额外说明`;
}
// Step 5: 辩论 -- 幕僚在某维度上发表立场
function debatePrompt(defined, answers, dimension, personaSkill) {
return `## 精确定义\n${defined}\n\n## 事实信息\n${answers}\n\n## 当前辩论维度\n${dimension}\n\n## 你的视角\n${personaSkill}\n\n---\n请针对「${dimension}」这个维度,阐述你的立场(支持/反对/中间和核心理由。100字以内直接说观点和理由。`;
}
// Facilitator 总结某个维度的辩论
function debateFacilitatorPrompt(dimension, allPositions) {
return `各位幕僚就「${dimension}」维度的辩论发言:\n\n${allPositions}\n\n---\n请总结这个维度的核心冲突:\n**核心矛盾**:(一句话)\n**支持方核心观点**:(一句话)\n**反对方核心观点**:(一句话)`;
}
// Step 6: Secretary 结构化总结
function summaryPrompt(rawInput, defined, answers, debateRecord) {
return `## 原始问题\n${rawInput}\n\n## 精确定义\n${defined}\n\n## 事实信息\n${answers}\n\n## 辩论记录\n${debateRecord}\n\n---\n请生成一份结构化的辩论总结报告Markdown 格式):\n\n# 辩论总结报告\n\n## 问题定义\n(一句话重述精确定义的问题)\n\n## 关键冲突维度\n(每个维度:冲突核心 + 正反方观点 + 分析)\n\n## 共识与分歧\n- **共识点**\n- **核心分歧**\n\n## 总体评估\n(综合评估这个决策的复杂度、风险和建议方向)`;
}
// Step 7: 摘果子 -- 评估 + To-Do
function harvestPrompt(summary) {
return `## 辩论总结报告\n${summary}\n\n---\n请从幕僚们的辩论中提取 actionable 的建议:\n\n## 关键评估\n1. 优点 / 机会1-2 点)\n2. 盲点 / 风险1-2 点)\n3. 总体判断:(一句话)\n\n## To-Do 清单\n- [ ] 可执行动作1\n- [ ] 可执行动作2\n- [ ] 可执行动作3\n...\n\n## 值得记住的洞察\n- 来自幕僚的洞见1\n- 来自幕僚的洞见2`;
}
module.exports = { definePrompt, factQuestionPrompt, opinionPrompt, dimensionsPrompt, debatePrompt, debateFacilitatorPrompt, summaryPrompt, harvestPrompt };

View File

@@ -0,0 +1,27 @@
// report.js - regenerated
const fs2 = require("fs");
function generateReport(input, state, stepLog){
const now=new Date().toISOString().replace("T"," ").substring(0,19);
const r=[];
r.push("# Debate Summary Report");r.push("");r.push("---");
r.push("**Question**: "+input);
r.push("**Time**: "+now);
r.push("**Steps**: "+stepLog.filter(s=>s.status==="done"||s.status==="fallback").length+"/"+stepLog.length);
r.push("");
r.push("# Problem Definition");
r.push(state.defined||"-");r.push("");
r.push("# Advisor Opinions");
if(state.opinions&&state.opinions.length>0){for(const o of state.opinions){r.push("### "+(o.emoji||"")+" "+(o.persona||""));r.push(o.opinion||"");r.push("");}}else{r.push("-");}
r.push("# Conflict Dimensions");
if(state.dimensions&&state.dimensions.length>0){state.dimensions.forEach((d,i)=>{r.push("### Dimension "+(i+1));r.push(d);r.push("");});}else{r.push("-");}
r.push("# Dimension Debates");
if(state.debates&&state.debates.length>0){state.debates.forEach((d,i)=>{r.push("### Dimension "+(i+1)+": "+(d.dimension||"").substring(0,100));r.push(d.summary||"-");r.push("");});}else{r.push("-");}
r.push("# Secretary Summary");
r.push(state.summary||"-");r.push("");
r.push("# Action Items");
r.push(state.harvest||"-");r.push("");
r.push("---");r.push("## Appendix: Execution Log");
if(stepLog&&stepLog.length>0){for(const l of stepLog){r.push("- Step "+l.step+": ["+l.status+"] "+(l.detail||"").substring(0,80));}}r.push("");
return r.join("\n");}
function saveReport(input,state,stepLog,filePath){const report=generateReport(input,state,stepLog);fs2.writeFileSync(filePath,report,"utf8");return filePath;}
module.exports={generateReport,saveReport};