2
0

quick-spec-json-render-system-prompt.md 5.0 KB


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()` 方法

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`

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` 组件!后端旧代码引用的是不存在的组件。