--- title: 'json-render 系统提示统一化' slug: 'json-render-system-prompt-unification' created: '2026-03-20' status: 'completed' stepsCompleted: ['cleanup-backend', 'verify-frontend-prompt', 'verify-transmission'] tech_stack: ['TypeScript', 'Python'] files_modified: - 'frontend-v2/lib/catalog/catalog.ts' - 'backend/conversation_manager.py' --- # Tech-Spec: json-render 系统提示统一化 **Created:** 2026-03-20 **Completed:** 2026-03-20 ## 最终架构 ```` ┌─────────────────────────────────────────────────────────┐ │ 前端 │ │ catalog.prompt({ mode: 'inline' }) │ │ → json-render 组件完整说明 (12547 chars) │ │ → 通过 componentsPrompt 字段发送 │ └─────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ 后端 │ │ BASE_SYSTEM_PROMPT (角色 + MCP 状态) │ │ + components_prompt (前端传来的组件说明) │ │ = 完整 system prompt │ └─────────────────────────────────────────────────────────┘ ```` ## 验证结果 (2026-03-20) ### 后端日志确认 ```` [DEBUG /api/chat/stream] components_prompt: 12547 chars [DEBUG /api/chat/stream] enabled_mcp_list: ['novel-translator', 'novel-platform-user', 'novel-platform-admin', 'template-241-mcp-app'] ```` ### 前端传来的 componentsPrompt 内容预览 ```` You are a UI generator that outputs JSON. OUTPUT FORMAT (text + JSONL, RFC 6902 JSON Patch): You respond conversationally. When generating UI, first write a brief explanation (1-3 sentences), then output JSONL patch lines wrapped in a \`\`\`spec code fence. The JSONL lines use RFC 6902 JSON Patch operations to build a UI tree... ```` ## 实施记录 ### 已删除的后端冗余代码 | 删除项 | 原因 | |--------|------| | \`NOVEL_TOOLS_GUIDE\` | 引用了不存在的 \`novel-detail\` 组件,与 catalog 不一致 | | \`NO_TOOLS_GUIDE\` | 冗余,AI 可以自己探索工具 | | \`_build_system_prompt()\` 中的 \`mcp_tools_guide\` 逻辑 | 简化后端,让 AI 自己决定 | ### 简化后的 \`_build_system_prompt()\` 方法 ```python def _build_system_prompt(self) -> str: """构建完整的 system prompt""" # 构建 MCP 状态部分 if self.enabled_mcp_list is not None and len(self.enabled_mcp_list) == 0: mcp_status = """当前没有启用任何 MCP 服务器。你只能进行普通对话和返回 json-render 组件。""" elif self.enabled_mcp_list: enabled_names = ", ".join(self.enabled_mcp_list) mcp_status = f"""**已启用的 MCP 服务器**: {enabled_names} 你可以调用这些 MCP 服务器的工具来帮助用户完成任务。""" else: mcp_status = """你可以通过调用 MCP 工具来帮助用户完成任务。""" # 替换占位符并添加组件列表 prompt = BASE_SYSTEM_PROMPT.replace("{MCP_STATUS}", mcp_status) if self.components_prompt: return prompt + "\n\n" + self.components_prompt else: return prompt ``` ### 简化后的 \`BASE_SYSTEM_PROMPT\` ```python BASE_SYSTEM_PROMPT = """你是一个 AI 助手,可以通过调用 MCP 工具来帮助用户完成任务。 ## 当前状态 {MCP_STATUS} """ ``` ## 核心原则 1. **单一来源**: 组件格式由前端 \`catalog.prompt({ mode: 'inline' })\` 统一定义 2. **后端精简**: 后端只提供基础角色定义 + MCP 状态 3. **AI 自主**: AI 自己决定用什么工具、返回什么组件 ## Catalog 组件列表 前端 \`catalog.ts\` 注册的组件(17 个): | 组件 | 用途 | |------|------| | \`card\` | 卡片容器组件 | \`stack\` | 布局容器组件 | \`heading\` | 标题组件 | \`text\` | 文本组件 | \`button\` | 按钮组件 | \`badge\` | 徽章组件 | \`separator\` | 分隔线组件 | \`input\` | 输入框组件 | \`text-area\` | 多行文本输入组件 | \`data-table\` | 数据表格组件 | \`translation-result\` | 翻译结果展示组件 | \`novel-list\` | 小说列表组件 | \`chapter-reader\` | 章节阅读器组件 | \`code-block\` | 代码块组件 | \`tool-call\` | MCP 工具调用状态组件 | \`login-panel\` | MCP 登录面板组件 | \`mcp-status\` | MCP 服务器状态组件 | \`suggestion-buttons\` | 建议按钮组组件 **注意**: 没有 \`novel-detail\` 组件!后端旧代码引用的是不存在的组件。