mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
Simplify message trace panels
This commit is contained in:
184
panel.js
184
panel.js
@@ -2720,10 +2720,6 @@ function _renderMessageTraceWorkspace(state) {
|
||||
return `
|
||||
<div class="bme-task-tab-body">
|
||||
<div class="bme-task-toolbar-row">
|
||||
<div class="bme-task-note">
|
||||
这里看的是最近一轮真实运行留下的痕迹,不是静态配置推演。你关心的两个问题会直接拆开:
|
||||
“最后注入给主 AI 的记忆文本” 和 “最后送去提取模型的实际请求”。
|
||||
</div>
|
||||
<span class="bme-task-pill">${_escHtml(_formatTaskProfileTime(updatedAt))}</span>
|
||||
</div>
|
||||
|
||||
@@ -2747,10 +2743,11 @@ function _renderMessageTraceRecallCard(state) {
|
||||
: [];
|
||||
const triggeredUserMessage =
|
||||
_extractTriggeredUserMessageFromRecentMessages(recentMessages) ||
|
||||
_findMarkdownSectionContent(
|
||||
_getLastDebugMessageContent(recallLlmRequest?.messages, "user"),
|
||||
["用户最新输入"],
|
||||
);
|
||||
_getLastDebugMessageContent(recallLlmRequest?.messages, "user");
|
||||
const hostPayloadText = _buildMainAiTraceText(
|
||||
triggeredUserMessage,
|
||||
injectionSnapshot?.injectionText || "",
|
||||
);
|
||||
|
||||
if (!injectionSnapshot) {
|
||||
return `
|
||||
@@ -2765,50 +2762,24 @@ function _renderMessageTraceRecallCard(state) {
|
||||
<div class="bme-config-card-head">
|
||||
<div>
|
||||
<div class="bme-config-card-title">最后注入给主 AI 的内容</div>
|
||||
<div class="bme-config-card-subtitle">
|
||||
这里展示的不是候选记忆,而是这一轮真正拼进主模型上下文的记忆文本。
|
||||
</div>
|
||||
</div>
|
||||
<span class="bme-task-pill">${_escHtml(_formatTaskProfileTime(injectionSnapshot.updatedAt))}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-list">
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">触发来源</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(injectionSnapshot.sourceLabel || injectionSnapshot.source || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">触发钩子</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(injectionSnapshot.hookName || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">触发用户输入</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(triggeredUserMessage || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">选中记忆数</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(String(injectionSnapshot.selectedNodeIds?.length ?? 0))}</span>
|
||||
</div>
|
||||
</div>
|
||||
${_renderMessageTraceTextBlock(
|
||||
"最终注入文本",
|
||||
injectionSnapshot.injectionText || "",
|
||||
"这次没有生成可注入的记忆文本。",
|
||||
"发送给主 AI 的内容",
|
||||
hostPayloadText,
|
||||
"这次没有捕获到主 AI 侧的注入内容。",
|
||||
)}
|
||||
${_renderDebugDetails(
|
||||
"召回参考上下文",
|
||||
recentMessages.length ? recentMessages.join("\n") : "",
|
||||
)}
|
||||
${_renderDebugDetails(
|
||||
"召回精排实际消息序列",
|
||||
_stringifyTraceMessages(recallLlmRequest?.messages),
|
||||
)}
|
||||
${_renderDebugDetails("原始注入快照", injectionSnapshot)}
|
||||
`;
|
||||
}
|
||||
|
||||
function _renderMessageTraceExtractCard(state) {
|
||||
const extractLlmRequest = state.extractLlmRequest || null;
|
||||
const extractPromptBuild = state.extractPromptBuild || null;
|
||||
const extractPayloadText = _buildTraceMessagePayloadText(
|
||||
extractLlmRequest?.messages,
|
||||
extractPromptBuild,
|
||||
);
|
||||
|
||||
if (!extractLlmRequest && !extractPromptBuild) {
|
||||
return `
|
||||
@@ -2819,56 +2790,20 @@ function _renderMessageTraceExtractCard(state) {
|
||||
`;
|
||||
}
|
||||
|
||||
const systemPrompt =
|
||||
_getLastDebugMessageContent(extractLlmRequest?.messages, "system") ||
|
||||
extractPromptBuild?.systemPrompt ||
|
||||
"";
|
||||
const userPrompt = _getLastDebugMessageContent(extractLlmRequest?.messages, "user");
|
||||
const dialogueText =
|
||||
_findMarkdownSectionContent(userPrompt, ["当前对话内容"]) || userPrompt;
|
||||
|
||||
return `
|
||||
<div class="bme-config-card-head">
|
||||
<div>
|
||||
<div class="bme-config-card-title">最后送去提取模型的内容</div>
|
||||
<div class="bme-config-card-subtitle">
|
||||
这里看的是自动提取真正下发给记忆模型的请求,不只是任务预设模板。
|
||||
</div>
|
||||
</div>
|
||||
<span class="bme-task-pill">${_escHtml(
|
||||
_formatTaskProfileTime(extractLlmRequest?.updatedAt || extractPromptBuild?.updatedAt),
|
||||
)}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-list">
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">预设</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(extractPromptBuild?.profileName || extractPromptBuild?.profileId || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">模型路由</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(extractLlmRequest?.effectiveRoute?.llm || extractLlmRequest?.route || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">模型</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(extractLlmRequest?.model || "—")}</span>
|
||||
</div>
|
||||
<div class="bme-debug-kv-item">
|
||||
<span class="bme-debug-kv-key">消息条数</span>
|
||||
<span class="bme-debug-kv-value">${_escHtml(String(_normalizeDebugMessages(extractLlmRequest?.messages).length))}</span>
|
||||
</div>
|
||||
</div>
|
||||
${_renderMessageTraceTextBlock(
|
||||
"送去提取的对话正文",
|
||||
dialogueText,
|
||||
"这次没有捕获到提取用户提示词。",
|
||||
"发送去提取模型的内容",
|
||||
extractPayloadText,
|
||||
"这次没有捕获到提取请求内容。",
|
||||
)}
|
||||
${_renderDebugDetails("提取系统提示词(兼容视图)", systemPrompt)}
|
||||
${_renderDebugDetails("提取用户提示词(完整)", userPrompt)}
|
||||
${_renderDebugDetails(
|
||||
"提取实际消息序列",
|
||||
_stringifyTraceMessages(extractLlmRequest?.messages),
|
||||
)}
|
||||
${_renderDebugDetails("提取 Prompt 组装快照", extractPromptBuild)}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -2916,11 +2851,49 @@ function _stringifyTraceMessages(messages = []) {
|
||||
|
||||
return normalizedMessages
|
||||
.map(
|
||||
(message, index) => `[${index + 1}] ${message.role}\n${message.content}`,
|
||||
(message) => `【${message.role}】\n${message.content}`,
|
||||
)
|
||||
.join("\n\n---\n\n");
|
||||
}
|
||||
|
||||
function _buildMainAiTraceText(triggeredUserMessage = "", injectionText = "") {
|
||||
const sections = [];
|
||||
const normalizedUserMessage = String(triggeredUserMessage || "").trim();
|
||||
const normalizedInjectionText = String(injectionText || "").trim();
|
||||
|
||||
if (normalizedUserMessage) {
|
||||
sections.push(`【user】\n${normalizedUserMessage}`);
|
||||
}
|
||||
if (normalizedInjectionText) {
|
||||
sections.push(`【memory injection】\n${normalizedInjectionText}`);
|
||||
}
|
||||
|
||||
return sections.join("\n\n---\n\n").trim();
|
||||
}
|
||||
|
||||
function _buildTraceMessagePayloadText(messages = [], promptBuild = null) {
|
||||
const normalizedMessages = _normalizeDebugMessages(messages);
|
||||
if (normalizedMessages.length) {
|
||||
return _stringifyTraceMessages(normalizedMessages);
|
||||
}
|
||||
|
||||
const fallbackMessages = [];
|
||||
const fallbackSystemPrompt = String(promptBuild?.systemPrompt || "").trim();
|
||||
if (fallbackSystemPrompt) {
|
||||
fallbackMessages.push({ role: "system", content: fallbackSystemPrompt });
|
||||
}
|
||||
|
||||
for (const message of promptBuild?.privateTaskMessages || []) {
|
||||
if (!message || typeof message !== "object") continue;
|
||||
const role = String(message.role || "").trim().toLowerCase();
|
||||
const content = String(message.content || "").trim();
|
||||
if (!role || !content) continue;
|
||||
fallbackMessages.push({ role, content });
|
||||
}
|
||||
|
||||
return _stringifyTraceMessages(fallbackMessages);
|
||||
}
|
||||
|
||||
function _extractTriggeredUserMessageFromRecentMessages(recentMessages = []) {
|
||||
if (!Array.isArray(recentMessages)) return "";
|
||||
|
||||
@@ -2934,55 +2907,6 @@ function _extractTriggeredUserMessageFromRecentMessages(recentMessages = []) {
|
||||
return "";
|
||||
}
|
||||
|
||||
function _extractMarkdownSections(text = "") {
|
||||
const normalized = String(text || "");
|
||||
if (!normalized.trim()) return [];
|
||||
|
||||
const headingRegex = /^#{1,6}\s*(.+?)\s*$/gm;
|
||||
const sections = [];
|
||||
let currentTitle = "";
|
||||
let bodyStart = 0;
|
||||
let match = headingRegex.exec(normalized);
|
||||
|
||||
while (match) {
|
||||
if (currentTitle) {
|
||||
sections.push({
|
||||
title: currentTitle,
|
||||
content: normalized.slice(bodyStart, match.index).trim(),
|
||||
});
|
||||
}
|
||||
currentTitle = String(match[1] || "").trim();
|
||||
bodyStart = headingRegex.lastIndex;
|
||||
match = headingRegex.exec(normalized);
|
||||
}
|
||||
|
||||
if (currentTitle) {
|
||||
sections.push({
|
||||
title: currentTitle,
|
||||
content: normalized.slice(bodyStart).trim(),
|
||||
});
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
function _findMarkdownSectionContent(text = "", titleHints = []) {
|
||||
const hints = Array.isArray(titleHints)
|
||||
? titleHints.map((item) => String(item || "").trim()).filter(Boolean)
|
||||
: [];
|
||||
if (!hints.length) return "";
|
||||
|
||||
const sections = _extractMarkdownSections(text);
|
||||
for (const section of sections) {
|
||||
const title = String(section?.title || "");
|
||||
if (hints.some((hint) => title.includes(hint))) {
|
||||
return String(section?.content || "").trim();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function _patchTaskProfiles(taskProfiles, extraPatch = {}, options = {}) {
|
||||
return _patchSettings(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user