Refine story summary prompts and vector sync

This commit is contained in:
2026-01-30 00:55:04 +08:00
parent 6aaed2af4a
commit d87c8a0207
7 changed files with 1174 additions and 432 deletions

View File

@@ -1,6 +1,7 @@
<!-- story-summary.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
@@ -8,6 +9,7 @@
<title>剧情总结 · Story Summary</title>
<link rel="stylesheet" href="story-summary.css">
</head>
<body>
<div class="container">
<!-- Header -->
@@ -37,18 +39,19 @@
<div class="controls">
<label class="chk-label">
<input type="checkbox" id="hide-summarized">
<span>聊天时隐藏已总结 · <strong id="summarized-count">0</strong> 楼(保留<input type="number" id="keep-visible-count" min="0" max="50" value="3">楼)</span>
<span>隐藏已总结 · <strong id="summarized-count">0</strong> 楼(保留<input type="number" id="keep-visible-count"
min="0" max="50" value="3">楼)</span>
</label>
<span class="spacer"></span>
<div class="btn-group">
<button class="btn btn-icon" id="btn-settings">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
<circle cx="12" cy="12" r="3" />
<path
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
</svg>
<span>设置</span>
</button>
<button class="btn btn-recall" id="btn-recall">涌现</button>
<button class="btn" id="btn-clear">清空</button>
<button class="btn btn-p" id="btn-generate">总结</button>
</div>
@@ -92,8 +95,10 @@
<div class="sec-title">人物关系</div>
<div class="sec-actions">
<button class="sec-btn sec-icon" id="btn-fullscreen-relations" title="全屏查看">
<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
<svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor"
stroke-width="2">
<path
d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" />
</svg>
</button>
<button class="sec-btn" data-section="characters">编辑</button>
@@ -132,7 +137,8 @@
<h2 id="editor-title">编辑</h2>
<button class="modal-close" id="editor-close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
</div>
@@ -152,319 +158,398 @@
<!-- Settings Modal -->
<div class="modal" id="settings-modal">
<div class="modal-bg" id="settings-backdrop"></div>
<div class="modal-box">
<div class="modal-box settings-modal-box">
<div class="modal-head">
<h2>设置</h2>
<div class="settings-tabs">
<div class="settings-tab active" data-tab="tab-summary">总结设置</div>
<div class="settings-tab" data-tab="tab-vector">向量设置</div>
<div class="settings-tab" data-tab="tab-debug">调试</div>
</div>
<button class="modal-close" id="settings-close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
</div>
<div class="modal-body">
<!-- API Config -->
<div class="settings-section">
<div class="settings-section-title">API 配置</div>
<div class="settings-row">
<div class="settings-field">
<label>渠道</label>
<select id="api-provider">
<option value="st">酒馆主 API沿用当前</option>
<option value="openai">OpenAI 兼容</option>
<option value="google">Google (Gemini)</option>
<option value="claude">Claude (Anthropic)</option>
<option value="custom">自定义</option>
</select>
</div>
</div>
<div class="settings-row hidden" id="api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="api-url" placeholder="https://api.openai.com 或代理地址">
<div class="settings-hint">不同渠道默认端点OpenAI 用 /v1Gemini 用 /v1betaClaude 用 /v1</div>
</div>
</div>
<div class="settings-row hidden" id="api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="api-key" placeholder="仅保存在本地,不会上传">
</div>
</div>
<div class="settings-row hidden" id="api-model-manual-row">
<div class="settings-field full">
<label>模型</label>
<input type="text" id="api-model-text" placeholder="如 gemini-1.5-pro、claude-3-haiku">
</div>
</div>
<div class="settings-row hidden" id="api-model-select-row">
<div class="settings-field full">
<label>可用模型</label>
<select id="api-model-select">
<option value="">请先拉取模型列表</option>
</select>
</div>
</div>
<div class="settings-btn-row hidden" id="api-connect-row">
<button class="btn btn-sm btn-p" id="btn-connect">连接 / 拉取模型列表</button>
</div>
</div>
<!-- Gen Params -->
<div class="settings-section">
<div class="settings-section-title">生成参数</div>
<div class="settings-row">
<div class="settings-field">
<label>Temperature</label>
<input type="number" id="gen-temp" step="0.01" min="0" max="2" placeholder="未设置">
</div>
<div class="settings-field">
<label>Top P</label>
<input type="number" id="gen-top-p" step="0.01" min="0" max="1" placeholder="未设置">
</div>
<div class="settings-field">
<label>Top K</label>
<input type="number" id="gen-top-k" step="1" min="1" placeholder="未设置">
</div>
</div>
<div class="settings-row">
<div class="settings-field">
<label>存在惩罚</label>
<input type="number" id="gen-presence" step="0.01" min="-2" max="2" placeholder="未设置">
</div>
<div class="settings-field">
<label>频率惩罚</label>
<input type="number" id="gen-frequency" step="0.01" min="-2" max="2" placeholder="未设置">
</div>
</div>
</div>
<!-- Trigger Settings -->
<div class="settings-section">
<div class="settings-section-title">总结设置</div>
<div class="settings-row">
<div class="settings-field">
<label>注入角色</label>
<select id="trigger-role">
<option value="system">System</option>
<option value="user">User</option>
<option value="assistant">Assistant</option>
</select>
</div>
</div>
<div class="settings-row">
<div class="settings-field">
<label>自动总结间隔(楼)</label>
<input type="number" id="trigger-interval" min="1" max="30" step="1" value="20">
</div>
<div class="settings-field">
<label>触发时机</label>
<select id="trigger-timing">
<option value="after_ai">AI 回复后</option>
<option value="before_user" selected>用户发送前</option>
<option value="manual">仅手动</option>
</select>
</div>
<div class="settings-field">
<label>单次最大总结(楼)</label>
<select id="trigger-max-per-run">
<option value="50">50</option>
<option value="100" selected>100</option>
<option value="150">150</option>
<option value="200">200</option>
</select>
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>头部包裹词应对NoAss配置</label>
<input type="text" id="trigger-wrapper-head" placeholder="添加到开头">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>尾部包裹词应对NoAss配置</label>
<input type="text" id="trigger-wrapper-tail" placeholder="添加到结尾">
</div>
</div>
<div class="settings-row">
<div class="settings-field-inline">
<input type="checkbox" id="trigger-enabled">
<label for="trigger-enabled">启用自动总结</label>
</div>
<div class="settings-field-inline">
<input type="checkbox" id="trigger-stream" checked>
<label for="trigger-stream">启用流式生成</label>
</div>
<div class="settings-field-inline">
<input type="checkbox" id="trigger-insert-at-end">
<label for="trigger-insert-at-end">强制插入到聊天最后</label>
</div>
</div>
<div class="settings-hint" style="margin-top:8px">若 API 不支持非流式请求,请勾选"启用流式生成"</div>
</div>
<!-- Vector Settings -->
<div class="settings-section">
<div class="settings-section-title">智能记忆(向量检索)</div>
<div class="settings-row">
<div class="settings-field-inline">
<input type="checkbox" id="vector-enabled">
<label for="vector-enabled">启用向量检索</label>
</div>
</div>
<div id="vector-config-area" class="hidden">
<div class="settings-row" style="margin-top:16px">
<div class="settings-field full">
<label>Embedding 引擎</label>
<div class="engine-selector">
<label class="engine-option">
<input type="radio" name="vector-engine" value="local">
<span>本地模型</span>
</label>
<label class="engine-option">
<input type="radio" name="vector-engine" value="online" checked>
<span>在线服务</span>
</label>
</div>
</div>
</div>
<!-- Local Engine -->
<div id="local-engine-area" class="engine-area hidden">
<div class="model-select-row">
<select id="local-model-select">
<option value="bge-small-zh">中文轻量 (51MB)</option>
<option value="bge-base-zh">中文标准 (102MB)</option>
<option value="e5-small">多语言 (118MB)</option>
<!-- Tab 1: Summary Settings -->
<div class="tab-pane active" id="tab-summary">
<!-- API Config & Gen Params Combined -->
<div class="settings-section">
<div class="settings-section-title">API 配置</div>
<div class="settings-row">
<div class="settings-field">
<label>渠道</label>
<select id="api-provider">
<option value="st">酒馆主 API沿用当前</option>
<option value="openai">OpenAI 兼容</option>
<option value="google">Google (Gemini)</option>
<option value="claude">Claude (Anthropic)</option>
<option value="custom">自定义</option>
</select>
</div>
<div class="model-desc" id="local-model-desc">手机/低配适用</div>
<div class="engine-status" id="local-model-status">
<span class="status-dot"></span>
<span class="status-text">检查中...</span>
</div>
<div class="engine-progress hidden" id="local-model-progress">
<div class="progress-bar"><div class="progress-inner"></div></div>
<span class="progress-text">0%</span>
</div>
<div class="engine-actions" id="local-model-actions">
<button class="btn btn-sm btn-p" id="btn-download-model">下载模型</button>
<button class="btn btn-sm" id="btn-cancel-download" style="display:none">取消下载</button>
<button class="btn btn-sm btn-del" id="btn-delete-model" style="display:none">删除缓存</button>
</div>
</div>
<!-- Online Engine -->
<div id="online-engine-area" class="engine-area">
<div class="settings-row">
<div class="settings-field full">
<label>服务渠道</label>
<select id="online-provider">
<option value="siliconflow">硅基流动(推荐)</option>
<option value="cohere">Cohere</option>
<option value="openai">OpenAI 兼容(可自建)</option>
</select>
</div>
</div>
<div class="settings-row" id="online-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="vector-api-url" placeholder="https://api.siliconflow.cn">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>API Key</label>
<input type="password" id="vector-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>模型</label>
<div style="display:flex;gap:8px">
<select id="vector-model-select" style="flex:1">
<option value="">请选择模型</option>
</select>
<button class="btn btn-sm" id="btn-fetch-models" style="display:none">拉取</button>
</div>
</div>
</div>
<div class="engine-status" id="online-api-status">
<span class="status-dot"></span>
<span class="status-text">未测试</span>
</div>
<div class="settings-btn-row" style="justify-content:center">
<button class="btn btn-sm" id="btn-test-vector-api">测试连接</button>
</div>
<div class="provider-hint" id="provider-hint">
💡 <a href="https://siliconflow.cn" target="_blank">硅基流动</a> 免费、速度快、质量好,推荐 BAAI/bge-m3
</div>
</div>
<!-- 文本过滤规则 -->
<div class="settings-row" style="margin-top:16px">
<div class="settings-row hidden" id="api-url-row">
<div class="settings-field full">
<label>文本过滤规则</label>
<p class="settings-hint" style="margin-bottom:8px">
遇到「起始」后跳过,直到「结束」。起始或结束可单独留空。用于过滤思考标签等干扰内容。
</p>
<div id="filter-rules-list" style="display:flex;flex-direction:column;gap:6px"></div>
<button class="btn btn-sm" id="btn-add-filter-rule" style="margin-top:8px"> 添加规则</button>
<label>API URL</label>
<input type="text" id="api-url" placeholder="https://api.openai.com 或代理地址">
<div class="settings-hint">默认端点OpenAI/v1Gemini/v1betaClaude/v1</div>
</div>
</div>
<div class="settings-row hidden" id="api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="api-key" placeholder="仅保存在本地,不会上传">
</div>
</div>
<div class="settings-row hidden" id="api-model-manual-row">
<div class="settings-field full">
<label>模型</label>
<input type="text" id="api-model-text" placeholder="如 gemini-1.5-pro、claude-3-haiku">
</div>
</div>
<div class="settings-row hidden" id="api-model-select-row">
<div class="settings-field full">
<label>可用模型</label>
<select id="api-model-select">
<option value="">请先拉取模型列表</option>
</select>
</div>
</div>
<div class="settings-btn-row hidden" id="api-connect-row"
style="display: flex; gap: 12px; align-items: center; justify-content: space-between;">
<button class="btn btn-sm btn-p" id="btn-connect" style="flex: 4;">连接 / 拉取模型列表</button>
<label class="chk-label compact"
style="margin: 0; flex: 1; display: flex; align-items: center; gap: 6px; white-space: nowrap; justify-content: center;">
<input type="checkbox" id="trigger-stream" checked>
<span>流式</span>
</label>
</div>
<!-- Vector Stats -->
<div class="vector-chat-section">
<div class="settings-row">
<div class="settings-field full">
<label>当前聊天向量</label>
<div class="vector-stats" id="vector-stats">
<span>事件向量: <strong id="vector-event-count">0</strong>/<strong id="vector-event-total">0</strong></span>
<span>·</span>
<span>Chunks: <strong id="vector-chunk-count">0</strong> 个(<span id="vector-chunk-floors">0</span>/<span id="vector-chunk-total">0</span> 层)</span>
<span>·</span>
<span>消息: <strong id="vector-message-count">0</strong></span>
</div>
<div class="vector-mismatch-warning hidden" id="vector-mismatch-warning">
⚠ 引擎/模型已变更,需重新生成向量
</div>
</div>
<!-- Collapsible Gen Params -->
<div class="settings-collapse">
<div class="settings-collapse-header" id="gen-params-toggle">
<span>生成参数</span>
<svg class="collapse-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div>
<div class="engine-progress hidden" id="vector-gen-progress-l1">
<div style="font-size:.75rem;color:var(--txt3);margin-bottom:4px">L1 片段</div>
<div class="progress-bar"><div class="progress-inner"></div></div>
<span class="progress-text">0/0</span>
</div>
<div class="engine-progress hidden" id="vector-gen-progress-l2">
<div style="font-size:.75rem;color:var(--txt3);margin-bottom:4px">L2 事件</div>
<div class="progress-bar"><div class="progress-inner"></div></div>
<span class="progress-text">0/0</span>
</div>
<div class="settings-hint" id="vector-perf-l1"></div>
<div class="settings-hint" id="vector-perf-l2"></div>
<div class="settings-btn-row" id="vector-action-row">
<button class="btn btn-sm btn-p" id="btn-gen-vectors">生成向量</button>
<button class="btn btn-sm btn-del" id="btn-clear-vectors">清除向量</button>
<button class="btn btn-sm hidden" id="btn-cancel-vectors">取消</button>
</div>
<div class="settings-hint" style="margin-top:8px">首次生成向量可能耗时较久,页面短暂卡顿属正常。若本地模型重进酒馆后需重下。</div>
<!-- 向量导入导出 -->
<div class="vector-io-section" style="border-top:1px solid var(--bdr);padding-top:16px;margin-top:16px">
<div class="settings-collapse-content hidden" id="gen-params-content">
<div class="settings-row">
<div class="settings-field full">
<label>向量迁移(跨设备 / 防清缓存)</label>
<div class="settings-hint" style="margin-bottom:8px">导出/导入均为 zip 格式,勿解压</div>
<div class="settings-btn-row" id="vector-io-row" style="margin-top:8px">
<button class="btn btn-sm" id="btn-export-vectors">导出向量</button>
<button class="btn btn-sm" id="btn-import-vectors">导入向量</button>
<div class="settings-field">
<label>Temperature</label>
<input type="number" id="gen-temp" step="0.01" min="0" max="2"
placeholder="未设置">
</div>
<div class="settings-field">
<label>Top P</label>
<input type="number" id="gen-top-p" step="0.01" min="0" max="1"
placeholder="未设置">
</div>
<div class="settings-field">
<label>Top K</label>
<input type="number" id="gen-top-k" step="1" min="1" placeholder="未设置">
</div>
</div>
<div class="settings-hint" id="vector-io-status"></div>
<div class="settings-row">
<div class="settings-field">
<label>存在惩罚</label>
<input type="number" id="gen-presence" step="0.01" min="-2" max="2"
placeholder="未设置">
</div>
<div class="settings-field">
<label>频率惩罚</label>
<input type="number" id="gen-frequency" step="0.01" min="-2" max="2"
placeholder="未设置">
</div>
</div>
</div>
</div>
</div>
<!-- Trigger Settings -->
<div class="settings-section">
<div class="settings-section-title">总结设置</div>
<div class="settings-row">
<div class="settings-field">
<label>注入角色</label>
<select id="trigger-role">
<option value="system">System</option>
<option value="user">User</option>
<option value="assistant">Assistant</option>
</select>
</div>
<div class="settings-field">
<label>单次最大总结(楼)</label>
<select id="trigger-max-per-run">
<option value="50">50</option>
<option value="100" selected>100</option>
<option value="150">150</option>
<option value="200">200</option>
</select>
</div>
</div>
<!-- Auto Summary with sub-options -->
<div class="settings-checkbox-group">
<label class="settings-checkbox">
<input type="checkbox" id="trigger-enabled">
<span class="checkbox-mark"></span>
<span class="checkbox-label">启用自动总结</span>
</label>
<div class="settings-sub-options hidden" id="auto-summary-options">
<div class="settings-row">
<div class="settings-field">
<label>自动总结间隔(楼)</label>
<input type="number" id="trigger-interval" min="1" max="30" step="1" value="20">
</div>
<div class="settings-field">
<label>触发时机</label>
<select id="trigger-timing">
<option value="after_ai">AI 回复后</option>
<option value="before_user" selected>用户发送前</option>
<option value="manual">仅手动</option>
</select>
</div>
</div>
</div>
</div>
<!-- Force Insert with wrapper options -->
<div class="settings-checkbox-group">
<label class="settings-checkbox">
<input type="checkbox" id="trigger-insert-at-end">
<span class="checkbox-mark"></span>
<span class="checkbox-label">强制插入到聊天最后(插件冲突用)</span>
</label>
<div class="settings-sub-options hidden" id="insert-wrapper-options">
<div class="settings-row">
<div class="settings-field full">
<label>头部包裹词</label>
<input type="text" id="trigger-wrapper-head" placeholder="添加到开头应对NoAss配置">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>尾部包裹词</label>
<input type="text" id="trigger-wrapper-tail" placeholder="添加到结尾应对NoAss配置">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab 2: Vector Settings -->
<div class="tab-pane" id="tab-vector">
<div class="settings-section">
<div class="settings-section-title">智能记忆(向量检索)</div>
<div class="settings-checkbox-group">
<label class="settings-checkbox">
<input type="checkbox" id="vector-enabled">
<span class="checkbox-mark"></span>
<span class="checkbox-label">启用向量检索</span>
</label>
</div>
<div id="vector-config-area" class="hidden">
<div class="settings-row" style="margin-top:16px">
<div class="settings-field full">
<label>Embedding 引擎</label>
<div class="engine-selector">
<label class="engine-option">
<input type="radio" name="vector-engine" value="local">
<span>本地模型</span>
</label>
<label class="engine-option">
<input type="radio" name="vector-engine" value="online" checked>
<span>在线服务</span>
</label>
</div>
</div>
</div>
<!-- Local Engine -->
<div id="local-engine-area" class="engine-area hidden">
<div class="model-select-row">
<select id="local-model-select">
<option value="bge-small-zh">中文轻量 (51MB)</option>
<option value="bge-base-zh">中文标准 (102MB)</option>
<option value="e5-small">多语言 (118MB)</option>
</select>
</div>
<div class="model-desc" id="local-model-desc">手机/低配适用</div>
<div class="engine-status-row">
<div class="engine-status" id="local-model-status">
<span class="status-dot"></span>
<span class="status-text">检查中...</span>
</div>
<div class="engine-actions" id="local-model-actions">
<button class="btn btn-sm btn-p" id="btn-download-model">下载</button>
<button class="btn btn-sm" id="btn-cancel-download"
style="display:none">取消</button>
<button class="btn btn-sm btn-del" id="btn-delete-model"
style="display:none">删除</button>
</div>
</div>
<div class="engine-progress hidden" id="local-model-progress" style="margin-top: 8px;">
<div class="progress-bar">
<div class="progress-inner"></div>
</div>
<span class="progress-text">0%</span>
</div>
</div>
<!-- Online Engine -->
<div id="online-engine-area" class="engine-area">
<div class="settings-row">
<div class="settings-field full">
<label>服务渠道</label>
<select id="online-provider">
<option value="siliconflow">硅基流动(推荐)</option>
<option value="cohere">Cohere</option>
<option value="openai">OpenAI 兼容(可自建)</option>
</select>
</div>
</div>
<div class="settings-row" id="online-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="vector-api-url" placeholder="https://api.siliconflow.cn">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>API Key</label>
<input type="password" id="vector-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row">
<div class="settings-field full">
<label>模型</label>
<div style="display:flex;gap:8px">
<select id="vector-model-select" style="flex:1">
<option value="">请选择模型</option>
</select>
<button class="btn btn-sm" id="btn-fetch-models"
style="display:none">拉取</button>
</div>
</div>
</div>
<div class="engine-status-row">
<div class="engine-status" id="online-api-status">
<span class="status-dot"></span>
<span class="status-text">未测试</span>
</div>
<button class="btn btn-sm" id="btn-test-vector-api">测试连接</button>
</div>
<div class="provider-hint" id="provider-hint">
💡 <a href="https://siliconflow.cn" target="_blank">硅基流动</a> 免费、速度快、质量好,推荐
BAAI/bge-m3
</div>
</div>
<!-- 文本过滤规则 - Redesigned for mobile -->
<div class="filter-rules-section">
<div class="filter-rules-header">
<label>文本过滤规则</label>
<button class="btn btn-sm btn-add" id="btn-add-filter-rule">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none"
stroke="currentColor" stroke-width="2">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
添加
</button>
</div>
<p class="settings-hint">过滤干扰内容(如思考标签):遇到「起始」跳过直到「结束」</p>
<div id="filter-rules-list" class="filter-rules-list"></div>
</div>
<!-- Vector Stats -->
<div class="vector-chat-section">
<div class="settings-row">
<div class="settings-field full">
<label>当前聊天向量</label>
<div class="vector-stats" id="vector-stats">
<div class="vector-stat-col">
<span class="vector-stat-label">事件向量:</span>
<span class="vector-stat-value"><strong
id="vector-event-count">0</strong>/<strong
id="vector-event-total">0</strong></span>
</div>
<span class="vector-stat-sep">·</span>
<div class="vector-stat-col">
<span class="vector-stat-label">Chunks:</span>
<span class="vector-stat-value"><strong
id="vector-chunk-count">0</strong>
个(<span id="vector-chunk-floors">0</span>/<span
id="vector-chunk-total">0</span> 层)</span>
</div>
<span class="vector-stat-sep">·</span>
<div class="vector-stat-col">
<span class="vector-stat-label">消息:</span>
<span class="vector-stat-value"><strong
id="vector-message-count">0</strong></span>
</div>
</div>
<div class="vector-mismatch-warning hidden" id="vector-mismatch-warning">
⚠ 引擎/模型已变更,需重新生成向量
</div>
</div>
</div>
<div class="engine-progress hidden" id="vector-gen-progress-l1">
<div style="font-size:.75rem;color:var(--txt3);margin-bottom:4px">L1 片段</div>
<div class="progress-bar">
<div class="progress-inner"></div>
</div>
<span class="progress-text">0/0</span>
</div>
<div class="engine-progress hidden" id="vector-gen-progress-l2">
<div style="font-size:.75rem;color:var(--txt3);margin-bottom:4px">L2 事件</div>
<div class="progress-bar">
<div class="progress-inner"></div>
</div>
<span class="progress-text">0/0</span>
</div>
<div class="settings-hint" id="vector-perf-l1"></div>
<div class="settings-hint" id="vector-perf-l2"></div>
<div class="settings-btn-row" id="vector-action-row">
<button class="btn btn-sm btn-p" id="btn-gen-vectors">生成向量</button>
<button class="btn btn-sm btn-del" id="btn-clear-vectors">清除向量</button>
<button class="btn btn-sm hidden" id="btn-cancel-vectors">取消</button>
</div>
<div class="settings-hint" style="margin-top:8px">首次生成向量可能耗时较久,页面短暂卡顿属正常。若本地模型重进酒馆后需重下。
</div>
<!-- 向量导入导出 -->
<div class="vector-io-section">
<div class="settings-row">
<div class="settings-field full">
<label>向量迁移(跨设备 / 防清缓存)</label>
<div class="settings-hint" style="margin-bottom:8px">导出/导入均为 zip 格式,勿解压
</div>
<div class="settings-btn-row" id="vector-io-row" style="margin-top:8px">
<button class="btn btn-sm" id="btn-export-vectors">导出向量</button>
<button class="btn btn-sm" id="btn-import-vectors">导入向量</button>
</div>
<div class="settings-hint" id="vector-io-status"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab 3: Debug -->
<div class="tab-pane" id="tab-debug">
<div class="debug-log-header">
<div class="debug-title">🔧 记忆召回日志</div>
<div class="settings-hint">显示最近一次 AI 生成时的向量检索详情</div>
</div>
<pre id="recall-log-content" class="debug-log-viewer"></pre>
</div>
</div>
<div class="modal-foot">
@@ -482,7 +567,8 @@
<h2>人物关系图</h2>
<button class="modal-close" id="rel-fs-close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
</div>
@@ -500,7 +586,8 @@
<h2>🤗 Hugging Face Space 部署指南</h2>
<button class="modal-close" id="hf-guide-close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
</div>
@@ -508,25 +595,10 @@
</div>
</div>
<!-- Recall Log Modal -->
<div class="modal" id="recall-log-modal">
<div class="modal-bg" id="recall-log-backdrop"></div>
<div class="modal-box" style="max-width:900px">
<div class="modal-head">
<h2>✨ 涌现 · 记忆召回日志</h2>
<button class="modal-close" id="recall-log-close">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
</div>
<div class="modal-body" style="padding:0">
<pre id="recall-log-content"></pre>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script src="story-summary-ui.js"></script>
</body>
</html>