Files
Prompt-Envelope-Protocol/README.md
T

237 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Prompt Envelope Protocol
**让 LLM 上下文在聊天界面中可见、可读、可理解。**
HCI 课程设计项目 · 设计系 · 2026
---
## 问题:聊天界面的"黑盒"困境
以 ChatGPT、Claude 为代表的 AI 聊天产品已拥有数亿用户,但其交互设计存在一个普遍问题——**上下文不透明**。
当你在聊天框中输入一个问题,模型在回复时参考了:
- 系统级的**行为准则**system prompt),决定了回复的风格和边界
- 跨对话的**用户记忆**(memory),可能包含过时或不准的信息
- 可用的**工具列表**tools)和**技能**(skills),你可能完全不知道它们的存在
- 模板**变量**在后台被静默替换(如 `{{user_name}}` → "小明"
你粘贴了一篇长论文让 AI 分析,界面没有任何提示哪部分被模型"看到"了。AI 调用了三个工具,你看不到调用链。你引用了一份 PDF,不知道模型提取了其中哪些段落。
这些信息——对用户——**全是黑的**。
### 设计问题
当前的聊天 UI 将 LLM 的所有上下文**过度封装**在 textarea 里。界面只关心「输入」和「输出」,把中间的一切当作实现细节。但 HCI 告诉我们:**界面的信息架构应该反映系统的心智模型**。当用户不知道模型"知道什么",他们就无法建立准确的预期,无法纠错,无法信任。
---
## 方案:Prompt Envelope Protocol
本项目的答案是:**一种将 LLM 完整上下文结构化的协议和对应的可视界面**。
### 核心思想
不是让聊天消息变成纯文本,而是让每条消息由若干带明确类型的 **Segment**(片段)组成:
```
一条消息不是 "你好,帮我审阅这篇论文"
而是:
├─ text segment "你好,帮我审阅这篇论文"
├─ long_text segment [论文全文 — 默认折叠,点击展开]
├─ document segment 📄 paper-draft.pdf (2.3MB)
└─ media segment 🖼️ 图3:实验组vs对照组
```
每种 Segment 在界面中有**独立的视觉呈现**——系统指令是折叠的灰色面板,用户记忆是紫色的记忆卡片,工具请求是深色终端风格的代码块。
### 设计原则
| 原则 | 说明 |
|------|------|
| **信息密度梯度** | 核心对话文本优先可见;元信息(system prompt / memory / tools)默认折叠 |
| **颜色编码系统** | 灰=系统 · 紫=记忆 · 绿=技能 · 橙=工具 · 蓝=变量 · 深色=工具调用 |
| **协议即视图** | 折叠状态内嵌于数据结构中;相同协议数据在任何渲染器下产生相同视图 |
| **可导出,不锁死** | 协议可以导出为标准 OpenAI Chat Format,不依赖本项目的 UI |
---
## 方法:区分 9 种上下文类型
通过对主流 LLM 聊天产品(ChatGPT、Claude、Kimi、豆包)的逆向分析,以及对 127 名 LLM 用户行为研究文献的查阅,识别出 **9 种需要差异化呈现的上下文类型**
### 1. 文本(text
用户和 AI 的直接对话内容。**始终可见**,不做折叠。用 Markdown 渲染保留结构化表达。
### 2. 静态变量(static_var
`{{user_name}}``{{current_date}}`——在对话开始前被替换为具体值。提取为**对话区顶部的会话变量横栏**,不在消息气泡中占用空间。
```
会话变量 {{user_name}} → 小明 {{current_date}} → 2026年6月8日
```
### 3. System Promptsystem_prompt
模型的行为准则和角色设定。**默认折叠**为灰色面板,标注行数。支持展开查看——当用户想知道"为什么 AI 这样说话"。
### 4. 用户记忆(memory
跨对话持久化的用户信息。**默认折叠**为紫色面板,展开后以标题列表展示每条记忆。用户可以质疑不准确的记忆。
### 5. Skills
模型可调用的技能,遵循 Anthropic SKILL.md 规范。**默认折叠**为绿色面板。展开后实现**渐进式披露**:
- **L1**:名称 + 描述(始终可见)
- **L2**:完整指令 body(点击展开——提示"触发时会加载到 LLM 上下文")
### 6. 工具总览(tool_overview
模型可使用的工具清单。**默认折叠**为橙色面板。每项工具可独立展开其 JSON Schema 定义。
### 7. 工具调用(tool_call
拆分为两个子类型:
| 子类型 | 视觉 | 默认状态 | 说明 |
|--------|------|---------|------|
| `tool_call_request` | 深色终端风格代码块 | **展开** | 绿色方法名 + 参数键值行 |
| `tool_call_result` | 绿/红 状态条 | **折叠**(成功)/ **展开**(失败) | 一眼看出是否出错 |
在界面中,工具调用会被自动拆分为独立的 `tool` 角色消息,与正常的对话消息交替排列。
### 8. 传文档(document
用户上传的文件。以**文件卡片**展示:图标 + 文件名 + 大小 + 前 200 字预览。点击「查看解析」可展开 AI 提取的文档内容。
### 9. 长文本素材(long_text
用户粘贴的长篇文本(>500 字)。**默认折叠**,展示前 2 行预览 + 字数统计。点击展开显示全文(Markdown 渲染)。
### 附加:多模态(media
图片、音频、视频。图片有有效 URL 时直接渲染缩略图;加载失败或无 URL 时回退为图标占位 + alt 文本。音频/视频展示类型标签。
---
## 协议格式
### Prompt Envelope(顶层文档)
```typescript
interface PromptEnvelope {
version: '1.0'
model?: string // 导出时使用的模型名
messages: Message[]
}
```
### Message(单条消息)
```typescript
interface Message {
id: string
role: 'system' | 'user' | 'assistant' | 'tool'
segments: Segment[] // 有序的片段列表
timestamp: number
}
```
### Segment(片段联合类型)
每种 Segment 有独有的 `kind` 字段,UI 据此决定渲染方式:
```
text | static_var | system_prompt | memory | skills |
tool_overview | tool_call_request | tool_call_result |
document | long_text | media
```
完整类型定义见 [`src/types/protocol.ts`](src/types/protocol.ts)。
### 导出兼容
协议可无损导出为标准 OpenAI Chat Completions 格式(`{ model, messages, tools }`),确认此设计不是"另一种 agent 运行时",而是一种**对标准协议的格式化表达层**。
---
## 技术实现
### 技术栈
| 层 | 选型 |
|---|------|
| 框架 | React 18 + TypeScript |
| 构建 | Vite |
| 样式 | Tailwind CSS |
| 图标 | Lucide React |
| Markdown | react-markdown + remark-gfm |
| 测试 | Vitest |
### MVP 范围
- ✅ 纯前端 React 应用,无后端、无真实 LLM 调用
- ✅ 6 个 Demo 场景(AF),覆盖全部 Segment 类型
- ✅ 双栏布局:对话视图 + 协议面板(实时 JSON 预览)
- ✅ 双 Tab 协议面板:OpenAI Format / Raw Protocol,支持复制和下载
- ✅ 4 个真实 Anthropic SKILL.md 文件加载 + `parseSkillMarkdown()` 自研解析器
- ✅ 26 个单元测试覆盖导出逻辑和 SKILL.md 解析
- ❌ 不接入真实 LLM API
- ❌ 不做后端/数据库/用户认证
### 快速开始
```bash
git clone <this-repo>
cd hci
npm install
npm run dev # 启动开发服务器 → http://localhost:5173
npm test # 运行全部 26 个单元测试
npm run build # 生产构建
```
---
## 文件概览
```
src/
├── types/protocol.ts # 协议类型定义(11 种 Segment
├── utils/
│ ├── export.ts # 导出 → OpenAI Chat Format
│ └── parseSkill.ts # SKILL.md YAML 解析器(自研)
├── data/
│ ├── demos/ # 6 个 Demo JSON 文件 + manifest
│ │ └── demos-loader.ts # 运行时验证 + skill body 水合
│ ├── skills.ts # 8 个手写自定义 skill
│ ├── skills-loader.ts # 4 个真实 Anthropic SKILL.md
│ └── skills/ # SKILL.md 源文件
├── components/
│ ├── SegmentRenderer.tsx # 按 kind 路由分发
│ ├── CollapsiblePanel.tsx # 通用折叠容器
│ ├── MarkdownRenderer.tsx # 共享 Markdown 渲染(所有文本组件)
│ ├── MessageList.tsx # 消息预处理 + 列表
│ ├── MessageBubble.tsx # 消息气泡容器
│ ├── SessionBar.tsx # 会话变量横栏
│ ├── ProtocolPanel.tsx # 右侧协议面板(双 Tab)
│ └── segments/ # 11 个 Segment View 组件
├── context/ChatContext.tsx # 全局状态
├── __tests__/
│ ├── export.test.ts # 导出逻辑(~20 个用例)
│ └── parseSkill.test.ts # SKILL.md 解析(7 个用例)
└── App.tsx # 顶层布局
```
---
## 设计反思
这个项目本质上在探索一个更根本的问题:**当 AI 系统变得越来越复杂,聊天界面该怎样让用户理解"系统在做什么"**
传统的聊天界面诞生于"人对人"的隐喻——一个输入框,一个输出框。但当这个输入框背后连接的是一个拥有记忆、工具、技能和复杂约束的 AI 系统时,一对一的 chat bubble 隐喻就不够了。
Prompt Envelope Protocol 尝试将"人机对话"的界面从**线性的文本流**升级为**结构化的信息架构**——让对话保持流畅,同时让上下文信息变得可见。这是一种对聊天界面的重新思考:**不只是"AI 在说话",而是"AI 在什么条件下、用了什么资源、做了哪些步骤来生成这个回复"**。