Files
st-react/docs/优化方案.md
2026-02-28 15:11:12 +08:00

17 KiB
Raw Blame History

SillyTavern 完全兼容优化方案Go + Gin + Postgres + React

目标:基于现有 Go + React 系统,构建一个与 SillyTavern下称 ST高度兼容的角色卡 / 世界书 / 正则 / 预设 / 对话平台。


1. 总体目标与设计原则

  • 技术栈统一所有核心功能角色卡、世界书、正则、预设、聊天、AI 集成)全部收敛到:
    • 后端server/ 下的 Go + Gin + PostgreSQL
    • 前端projects/web-app 下的 React + TypeScript + Tailwind
  • SillyTavern 完全兼容
    • 支持 ST 角色卡 V2/V3chara_card_v2 / v3导入导出
    • 支持 ST 世界书字段及触发逻辑keys/secondary_keys/regex/depth/sticky/cooldown/probability/position 等);
    • 支持 ST Regex Scripts 配置placement/runOnEdit/markdownOnly/promptOnly/substituteRegex/min/max depth
    • 支持 ST 风格预设与 prompt 注入顺序prompt_order / injection depth/position
  • 单一真相来源SSOT
    • 数据库即真相Postgres 负责持久化所有 ST 相关实体;
    • 前端只是 UIReact 只做编辑/展示,请求都经过 API不再有“前端内存版预设/世界书”。
  • 可扩展性
    • 提前为插件系统预留 HookonUserInput/onWorldInfoScan/beforePromptBuild/onAssistantDone 等);
    • 方便接入未来的 WebSocket/SSE 流式聊天、统计系统、市场/分享功能。

2. 当前 Go + React 系统现状(基于现有文档与代码)

2.1 后端server/

根据 projects/docs/development-progress.md

  • 用户系统 已完成2024-02-26
    • 模型:AppUser, AppUserSession
    • API/app/auth/register, /app/auth/login, /app/auth/refresh, /app/auth/logout, /app/auth/userinfo
    • JWT、会话、用户资料、密码修改均已实现
  • 角色卡管理AICharacter 已完成:
    • 模型:AICharacter(完全兼容 ST V2 格式),使用 JSONB 存储 tags/alternateGreetings/characterBook/extensions 等复杂结构
    • API
      • POST /app/character
      • GET /app/character(分页、搜索、标签筛选)
      • GET /app/character/:id
      • PUT /app/character/:id
      • DELETE /app/character/:id
      • POST /app/character/uploadPNG/JSON 角色卡)
      • GET /app/character/:id/export(导出 JSON
    • 工具:utils/character_card.goPNG tEXt chunk / ST V2 工具)
  • 🚧 预设管理
    • 前端页面 /presets 已完成(导入 JSON、复制、导出、编辑参数
    • 后端预设 API 尚未实现(development-progress.md 已给出规划端点)。
  • 📋 对话系统 & AI 集成
    • 前端基础 UI 已完成(/chat + 侧边栏 + 输入框)。
    • 后端对话 API、AI 流式集成、世界书/正则逻辑尚在规划阶段。

2.2 前端(projects/web-app

  • 用户系统前端LoginPage/RegisterPage/ForgotPasswordPage/ProfilePage 已完成,api/client.ts + api/auth.ts 已完成 token 注入与刷新。
  • 角色卡管理前端CharacterManagePage + api/character.ts
    • 功能:
      • 上传 PNG/JSON 角色卡(调用 /app/character/upload
      • 编辑角色卡核心字段、内嵌 characterBook(世界书)字段
      • 导出 JSON调用 /app/character/:id/export
      • 搜索、分页、删除
  • 预设管理前端PresetManagePage
    • 当前为 前端内存里的假数据 + 文件导入/导出;尚未接入真实后端 /app/preset
  • 聊天前端ChatPage + Sidebar + ChatArea + CharacterPanel + SettingsPanel
    • 已实现基础布局、会话切换、角色选择、背景图/主题色设置等 UI。
    • 消息发送、历史加载、预设切换、世界书/正则开关还需后端配合。
  • AI 配置前端api/aiConfig.ts(对应 /app/ai-config 系列)。

结论:角色卡链路基本打通,用户系统成熟;预设/对话/AI/世界书/正则目前主要停留在前端 UI 或规划层面,正好适合作为“集中下沉到 Go 后端”的突破口。


3. 目标架构SillyTavern 兼容实现)

3.1 核心领域模型(后端)

建议在现有 model/app 中引入或规范以下模型(部分已存在,可扩展):

  • AICharacter(已存在)
    • ST 角色卡 V2/V3 的标准化版本 + 原始 JSON 存档。
  • Worldbook & WorldbookEntry
    • 支持角色内世界书与全局世界书。
  • RegexScript
    • 支持 scopeglobal | character | preset
  • Preset & PresetPrompt & PresetRegexBinding
    • 表达 ST preset 的参数、prompt 列表和 regex 绑定。
  • Conversation & Message
    • 对话与消息记录,支持与 AICharacterPreset 和 AI 配置关联。

3.2 运行时 Pipeline

所有客户端(现阶段只有 React Web将来可增加其他统一通过 Go 后端完成以下流程:

  1. 输入正则脚本处理global/character/preset
  2. 世界书扫描keys/secondary_keys/regex/depth/sticky/cooldown 等)
  3. Prompt 构建(角色 system + world info + preset prompts + 历史消息)
  4. AI 调用OpenAI/Anthropic/custom via /app/ai-config
  5. 输出正则脚本处理
  6. 持久化消息与统计

React 前端只负责:

  • 提供管理与编辑界面;
  • 将用户选择的 preset/worldbook/regex 传给后端;
  • 使用 SSE/WebSocket 将 AI 流输出展示给用户。

4. 后端详细优化方案Go + Gin + Postgres

4.1 模型与数据库设计(概念级)

不强制你立刻改现有表名与字段;这部分作为“目标状态”,可通过迁移脚本或视图逐步对齐。

  • AICharacter(已有)
    • 新增/规范字段:
      • raw_card_json JSONB:存原始 ST 角色卡,用于无损导出。
      • bound_worldbook_ids UUID[]:角色绑定世界书 ID 列表(可选)。
      • bound_regex_ids UUID[]:角色绑定正则脚本 ID 列表(可选)。
  • Worldbook / WorldbookEntry
    • Worldbookid, name, owner_char_id (nullable), meta JSONB, created_at, updated_at
    • WorldbookEntry包含 ST 全字段:
      • uid, keys, secondary_keys, comment, content, constant, disabled, use_regex, case_sensitive, match_whole_words, selective, selective_logic, position, depth, order, probability, sticky, cooldown, delay, group, extra JSONB
  • RegexScript
    • id, name, find_regex, replace_with, trim_string
    • placement INT[]
    • disabled, markdown_only, run_on_edit, prompt_only
    • substitute_regex, min_depth, max_depth
    • scope, owner_char_id, owner_preset_id, raw_json
  • Preset / PresetPrompt / PresetRegexBinding
    • 基本采样参数 + prompt 列表 + regex 绑定。
  • Conversation / Message
    • Conversationid, user_id, character_id, preset_id, ai_config_id, title, settings JSONB, created_at, updated_at
    • Messageid, conversation_id, role, content, token_count, created_at

4.2 角色卡导入/导出(巩固现有实现)

development-progress.md 看,/app/character 模块已经“完全兼容 ST V2”这里更多是规范与扩展。

  • 导入 /app/character/upload 已具备
    • PNG使用 utils/character_card.go 提取 chara tEXt chunk → JSON。
    • JSON直接解析填充 AICharacter
  • 优化点:
    • 当角色卡中包含 character_book 时:
      • 自动在 worldbooks/worldbook_entries 中创建对应记录;
      • 将 worldbook.id 写入 AICharacter.bound_worldbook_ids(或冗余到 characterBook 字段中)。
    • 当包含 extensions.regex_scripts 时:
      • 自动创建 RegexScriptscope=character, owner_char_id=该角色)。
      • 将脚本 id 写入 AICharacter.bound_regex_idsextensions 中。
  • 导出 /app/character/:id/export
    • raw_card_json 存在,优先以它为基础;将 DB 中新增的信息 patch 回去(例如补上最新的 worldbook/regex 变更)。
    • 若不存在,则按 ST V2 规范组装 JSON兼容 V1/V3 的 data 字段)。

4.3 世界书World Info引擎

  1. 世界书激活来源
    • 全局启用列表per-user 或全局 settings 中的 active_worldbook_ids)。
    • 角色绑定:AICharacter.bound_worldbook_ids
    • 会话特定选项:conversation.settings.activeWorldbookIds(从前端设置面板传入)。
  2. 触发与过滤算法
    • 遍历所有激活 worldbook 的 entries
      • 忽略 disabled 的 entry。
      • constant=true:无视关键词匹配,直接进入候选(仍受 sticky/cooldown/delay/probability 控制)。
      • keys 匹配:
        • use_regex=true:将每个 key 作为正则(考虑 caseSensitivematchWholeWords 标志)。
        • 否则:普通字符串包含匹配(可选大小写敏感)。
      • selective=true:根据 selectiveLogic 结合 secondary_keys
        • 0=ANDsecondary_keys 至少一个命中;
        • 1=OR:主 keys 或 secondary_keys 任一命中;
        • 2=NOT:主 keys 命中,但 secondary_keys 不命中。
      • depth仅在最近 entry.depth 条消息(或 tokens中搜索关键字。
      • sticky/cooldown/delay基于会话级状态比如 Redis/内存/DB存储 entry 上次触发时间或 sticky 状态。
      • probability按百分比随机决定最终是否注入。
  3. 注入到 prompt 中
    • 简化版:将所有命中 entry.content 拼接为 [World Info] 段,附加在 system prompt 后;
    • 高级版:按 ST 行为,依据 position/depth/order放到不同位置角色描述前/后、历史中等)。

4.4 正则脚本Regex Scripts引擎

  1. 脚本来源
    • Globalscope='global'disabled=false
    • Characterscope='character' AND owner_char_id=当前角色
    • Presetpreset_regex_bindings 中绑定到当前 preset 的脚本。
  2. 执行阶段placement
    • 输入阶段placement=1用户消息入库前
    • 输出阶段placement=2模型输出生成后、入库/返回前;
    • 世界书阶段placement=3扫描 / 注入 world info 内容前;
    • 推理阶段placement=4如有单独 reasoning prompt可在构建 reasoning 时处理。
  3. 实现细节Go
    • 解析 JS 风格正则 /pattern/flags,支持 i/m/s
    • 替换宏:
      • substitute_regex=1 → 用当前用户名称替换 {{user}}
      • =2 → 用当前角色名替换 {{char}}
    • trim_string:按行定义需要从文本中删掉的子串。
    • minDepth/maxDepth结合消息历史深度决定是否执行脚本。
    • runOnEdit在“消息编辑接口”中也调用该脚本集。
    • markdownOnly/promptOnly通过标志决定作用在 UI 文本 or prompt 文本。

4.5 Prompt Pipeline 与对话 API

将现有/规划中的对话 API 统一收敛到一个 pipeline例如 /app/conversation/:id/message(或 /conversations/:id/messages,按统一风格即可):

  1. 接收请求
{
  "content": "用户输入文本",
  "options": {
    "presetId": "uuid-xxx",
    "overrideModel": "gpt-4",
    "stream": true
  }
}
  1. 管线步骤
    1. 根据 conversationId 加载:
      • Conversation、AICharacter、Preset、AI 配置、世界书/正则等上下文;
      • 合并 settings会话内 + 用户全局)。
    2. 输入文本经过 regex 引擎placement=1
    3. 写入一条 user message 到 DB。
    4. 从最近 N 条消息构造 world info 触发文本,调用世界书引擎得到 entries。
    5. 构建 prompt
      • system角色 system + scenario + authorsNote + preset.systemPrompt + world info
      • history最近若干 user/assistant 消息;
      • preset.prompts按 depth/position 注入额外 messages。
    6. 调用 AI 服务(依据 /app/ai-config 中 baseUrl/apiKey/model
      • 支持流式:通过 SSE/WebSocket 对前端推送 tokens。
    7. 将完整 assistant 输出经过 regex 引擎placement=2
    8. 写入一条 assistant message 到 DB。
    9. 返回响应给前端(同步返回最终内容 + 可选流式过程)。

5. 前端详细优化方案React projects/web-app

5.1 角色卡管理CharacterManagePage

目标:完全对齐 ST 角色卡 V2/V3 字段,并为世界书/正则后端拆分打好基础。

优化点:

  • 字段映射明确化
    • 确保 Character 接口与后端模型一致,并在注释中标明 ST 对应字段:
      • firstMesfirst_mes
      • mesExamplemes_example
      • systemPromptsystem_prompt
      • postHistoryInstructionspost_history_instructions
      • characterBookcharacter_book
      • extensionsextensions
  • 世界书编辑 UI 扩展
    • 目前 WorldBookEntry 较简化keys/content/enabled/insertion_order/position
    • 建议增加更多高级属性编辑项(可以先折叠到“高级设置”中):
      • secondary_keys / constant / use_regex / case_sensitive / match_whole_words
      • selective / selective_logic
      • depth / order / probability / sticky / cooldown / delay / group
    • 保存时将这些字段一并放入 characterBook.entries,后端负责拆分入 DB。
  • 导入/导出保持 ST 兼容
    • 当前上传/导出流程基本正确;随着后端增强,无需大改,只要保证前端不破坏 JSON 结构即可。

5.2 预设管理PresetManagePage

目标:把当前的“前端内存预设”完全改造成后端驱动的 ST 预设系统

实施步骤:

  1. 后端按 development-progress.md 规划实现 /app/preset API
POST   /app/preset
GET    /app/preset
GET    /app/preset/:id
PUT    /app/preset/:id
DELETE /app/preset/:id
POST   /app/preset/import
GET    /app/preset/:id/export
  1. 前端新建 src/api/preset.ts 对应这些端点。
  2. PresetManagePage 中的 useState 初始数据删除,改为:
    • const { data } = await presetApi.getPresetList()
    • 导入、导出、编辑、删除全部通过后端。
  3. 预设 JSON 的读写字段与 ST 对齐:
    • temperature/top_p/top_k/frequency_penalty/presence_penalty/system_prompt/stop_sequences/...

5.3 聊天与设置面板ChatPage / SettingsPanel / CharacterPanel

目标:把“选 preset / 选世界书 / 选正则”的入口统一放到设置面板,并通过 conversation.settings 与后端 pipeline 串联。

建议:

  • SettingsPanel 中增加:
    • 当前会话使用的 preset 选择器(下拉 list来自 /app/preset)。
    • 可选的世界书列表(来自未来的 /app/worldbook,初期可只展示角色内 worldbook
    • 可选的全局正则脚本列表(来自未来的 /app/regex)。
  • 保存时调用 /app/conversation/:id/settings(或 PUT /app/conversation/:id
settings: {
  backgroundImage: string
  themeColor: string
  presetId?: string
  activeWorldbookIds?: string[]
  activeRegexIds?: string[]
}
  • 发送消息时,前端不再参与世界书/正则逻辑,只负责传 content,后端从 conversation/preset/character 中解析所有配置。

6. 分阶段落地路线图(仅 Go + React

阶段 1打通所有核心 CRUD 与数据流(短期)

  • 后端:
    • 巩固 /app/character 模块(确保 ST V2/V3 完全兼容)。
    • 实现 /app/preset 模块CRUD + 导入/导出)。
    • 设计并实现 worldbooks/worldbook_entriesregex_scripts 的数据结构与基础 API。
  • 前端:
    • 改造 PresetManagePage 接入真实 API。
    • CharacterManagePage 中补全世界书 entry 字段,保持 ST 兼容。

阶段 2实现 Prompt Pipeline 与对话 API中期

  • 后端:
    • 聚合世界书与正则逻辑,形成独立的 chatPipeline service。
    • /app/conversation/:id/message(或 /conversations/:id/messages)中调用 pipeline完成一次“完整的 ST 风格对话请求”。
    • 引入流式输出SSE 或 WebSocket
  • 前端:
    • ChatPage/SettingsPanel 中增加 preset/worldbook/regex 的选择与设置保存。
    • 调整 ChatArea 接收流式输出并实时渲染。

阶段 3高级特性与插件系统长期

  • 后端:
    • 引入插件概念(plugins 表 + manifest + hooks
    • 实现插件执行沙箱WASM 或 goja并在 pipeline 中注入插件 hooks。
    • 增加统计、日志与审计功能。
  • 前端:
    • 增加插件管理页面与可视化配置。
    • 对接统计与调试视图(例如:查看某次回复中哪些 world info/regex/插件生效)。

7. 总结

  • 你当前的 Go + React 系统已经完成:
    • 用户系统(认证/资料);
    • 角色卡管理(完整 ST V2 兼容导入/导出);
    • 预设管理与对话 UI 的前端骨架
  • 接下来最重要的三件事是:
    • 在后端固化 ST 兼容的领域模型与 Prompt Pipeline
    • /app/conversation 成为唯一的“对话真相源”React 只是 UI 壳