From 290cc55abfaccc43dd79db65083798a0ef6228c5 Mon Sep 17 00:00:00 2001 From: carry Date: Sun, 7 Jun 2026 23:12:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9C=BA=E6=99=AF=20C=20=E9=87=8D?= =?UTF-8?q?=E5=86=99=E4=B8=BA=E6=96=87=E6=A1=A3=E8=A7=A3=E6=9E=90=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=EF=BC=8CDocumentCard=20=E5=A2=9E=E5=8A=A0=E3=80=8C?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E8=A7=A3=E6=9E=90=E3=80=8D=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DocumentSegment 新增 parsedContent 字段,存储 AI 对文档的解析结果 - DocumentCard 增加「查看解析 / 收起解析」按钮,展开后以 Markdown 渲染解析内容 - 场景 C 从「长文本+文档+多模态」改为「单文档解析」场景,聚焦展示解析功能 - ChatContext 默认 activeDemo 索引修正为 4 --- src/components/segments/DocumentCard.tsx | 70 +++- src/context/ChatContext.tsx | 4 +- src/data/demos.ts | 8 +- src/data/demos/demo-c.ts | 148 ++++---- src/data/demos/demo-e.ts | 414 +++++++++++++++-------- src/types/protocol.ts | 1 + 6 files changed, 435 insertions(+), 210 deletions(-) diff --git a/src/components/segments/DocumentCard.tsx b/src/components/segments/DocumentCard.tsx index 87c3c7b..f1b83c6 100644 --- a/src/components/segments/DocumentCard.tsx +++ b/src/components/segments/DocumentCard.tsx @@ -1,6 +1,8 @@ +import { useState } from 'react' import type { DocumentSegment } from '../../types/protocol' import type { LucideIcon } from 'lucide-react' -import { FileText, FileImage, FileAudio, File } from 'lucide-react' +import { FileText, FileImage, FileAudio, File, ChevronDown, ChevronRight, Eye, EyeOff } from 'lucide-react' +import MarkdownRenderer from '../MarkdownRenderer' const mimeIcons: Record = { 'text/': FileText, @@ -22,21 +24,63 @@ function formatBytes(bytes: number): string { } export default function DocumentCard({ segment }: { segment: DocumentSegment }) { + const [showParsed, setShowParsed] = useState(false) + return ( -
-
{getIcon(segment.mimeType)}
-
-
- - {segment.fileName} - - {formatBytes(segment.sizeBytes)} +
+ {/* 文档信息卡片 */} +
+
{getIcon(segment.mimeType)}
+
+
+ + {segment.fileName} + + {formatBytes(segment.sizeBytes)} +
+

{segment.mimeType}

+ {!showParsed && ( +

+ {segment.snippet} +

+ )}
-

{segment.mimeType}

-

- {segment.snippet} -

+ + {/* 查看解析按钮 */} + {segment.parsedContent && ( + + )}
+ + {/* 解析结果展开区 */} + {showParsed && segment.parsedContent && ( +
+
+ + 解析结果 +
+ +
+
+ +
+
+ )}
) } diff --git a/src/context/ChatContext.tsx b/src/context/ChatContext.tsx index 33cdaa8..52dc1b1 100644 --- a/src/context/ChatContext.tsx +++ b/src/context/ChatContext.tsx @@ -13,8 +13,8 @@ interface ChatContextValue { const ChatContext = createContext(null) export function ChatProvider({ children }: { children: ReactNode }) { - const [activeDemo, setActiveDemo] = useState(5) // Default: Real Skills Demo F - const [envelope, setEnvelope] = useState(demos[5].envelope) + const [activeDemo, setActiveDemo] = useState(4) // Default: Scene F + const [envelope, setEnvelope] = useState(demos[4].envelope) const switchDemo = (i: number) => { setActiveDemo(i) diff --git a/src/data/demos.ts b/src/data/demos.ts index 843594f..fdc3c52 100644 --- a/src/data/demos.ts +++ b/src/data/demos.ts @@ -28,8 +28,8 @@ export const demos: DemoScenario[] = [ }, { id: 'c', - label: '场景 C', - description: '长文本 + 文档附件 + 多模态', + label: '场景 C 📄', + description: '文档解析:点击「查看解析」看 AI 如何提取文档内容', envelope: demoC, }, { @@ -40,8 +40,8 @@ export const demos: DemoScenario[] = [ }, { id: 'e', - label: '场景 E 🧪', - description: 'Skills 渐进式披露 + Agent 主动触发 /deep-research', + label: '场景 E 🔍', + description: '日志分析:异常检测 + 安全审计 + 性能分析', envelope: demoE, }, { diff --git a/src/data/demos/demo-c.ts b/src/data/demos/demo-c.ts index 3158f4f..ab66824 100644 --- a/src/data/demos/demo-c.ts +++ b/src/data/demos/demo-c.ts @@ -1,57 +1,66 @@ +/** + * Demo C — 文档解析(核心展示) + * + * 场景:用户上传多份文档请求 AI 进行解析,展示文档上传后 AI 如何 + * 提取、结构化理解其中的内容。 + * + * 关键展示: + * 1. 一份 PDF 文档,右上角有「查看解析」按钮 + * 2. 点击后展开显示 AI 对文档的解析结果(Markdown 渲染) + * 3. Assistant 基于解析结果给出分析回答 + * 4. 无 long_text / media / 多文档干扰 —— 聚焦单文档解析体验 + */ + import type { PromptEnvelope } from '../../types/protocol' import { getSkills } from '../skills' const now = Date.now() -const longArticleContent_C = `# 大语言模型交互中的上下文透明性问题 +/** PDF 市场调研报告的解析结果 */ +const marketReportParsed = `## 文档概览 -## 摘要 +| 字段 | 内容 | +|------|------| +| 标题 | 2026 年 Q2 智能助手市场研究报告 | +| 作者 | 市场分析部 · 陈敏 | +| 日期 | 2026 年 5 月 28 日 | +| 页数 | 42 页 | +| 语言 | 中文(简体) | -近年来,以 ChatGPT 为代表的对话式 AI 产品迅速普及。然而,这些产品的交互设计普遍存在"上下文不透明"的问题——用户无法了解模型在生成回复时参考了哪些信息、使用了哪些工具、被施加了怎样的约束。 +## 核心发现 -## 1. 问题定义 +### 1. 市场规模 +2026 年 Q2 全球智能助手市场规模预计达到 **187 亿美元**,同比增长 **34.2%**。 -当前的聊天界面(chatbox UI)将 LLM 的完整上下文封装在黑盒之中。用户看到的是一个"魔法对话框":输入问题,得到回答。但这个过程掩盖了大量关键信息: +主要增长驱动力: +- 企业级 AI 助手采纳率从 2025 年的 38% 提升至 56% +- 多模态能力(图像/语音/代码)推动使用场景扩展 +- 开源模型的成熟降低了部署门槛 -- **System Prompt**:模型的行为准则和角色设定,直接决定了回复的风格和边界 -- **User Memory**:跨对话持久化的用户信息,可能包含过时或不准确的记忆 -- **Tools & Skills**:模型可调用的外部能力,用户可能完全不知道它们的存在 -- **Variable Injection**:模板变量在用户不知情的情况下被替换为具体值 +### 2. 竞争格局 -这种不透明性导致了一系列用户体验问题:信任缺失、纠错困难、意外行为难以解释。 +| 厂商 | 市场份额 | QoQ 变化 | 核心优势 | +|------|---------|---------|---------| +| OpenAI | 41% | +2.3% | 品牌认知度 + 开发者生态 | +| Anthropic | 18% | +5.1% | 安全对齐 + 长上下文 | +| Google | 15% | -1.2% | 搜索整合 + 多模态 | +| Meta | 12% | +3.8% | 开源策略 + 成本优势 | +| 其他 | 14% | — | 垂直领域玩家 | -## 2. 设计目标 +### 3. 用户需求变化 +- **可信度**成为用户选择助手的第一要素(47% 受访者提及) +- **上下文窗口大小**的优先级从 2025 年的第 7 位跃升至第 3 位 +- 企业用户对 \`system prompt\` 透明度的需求同比增长 **82%** +- 工具调用(Function Calling)的使用率从 23% 增长到 51% -本文提出一套"Prompt Envelope Protocol"——一种结构化的 prompt 表达格式,使得: - -1. 每种上下文元素都有明确的视觉呈现 -2. 用户可以按需展开或折叠细节 -3. 协议可以无损导出为标准 API 格式 -4. 视觉语言保持简约,不增加认知负荷 - -## 3. 核心设计原则 - -### 3.1 信息密度梯度 - -核心对话文本始终可见,元信息默认折叠。用户不会在每次对话中都被无关的 system prompt 和工具列表淹没。 - -### 3.2 颜色编码系统 - -每种上下文类型有独立的颜色标记,形成可学习的视觉语言: -- 蓝色 = 变量 -- 灰色 = 系统指令 -- 紫色 = 用户记忆 -- 绿色 = 技能 -- 橙色 = 工具 - -### 3.3 协议即视图 - -折叠状态存储在协议数据中而非 UI 状态中。这意味着相同的协议数据在任何渲染器下都产生相同的视图——协议本身就是 view model。` +### 4. 关键趋势 +> "智能助手的竞争从模型能力转向体验设计。用户不再只关心'能不能答对',更关心'我能不能理解你为什么这么回答'。"——报告结语` export const demoC: PromptEnvelope = { version: '1.0', model: 'gpt-4-turbo', messages: [ + // --- System message --- { id: 'c-1', role: 'system', @@ -72,58 +81,83 @@ export const demoC: PromptEnvelope = { kind: 'system_prompt', content: `当前日期:{{current_date}},回复语言:{{language}}。 -你是文档审阅助手。帮助用户分析长文档、提取要点、回答关于文档内容的问题。`, +你是文档解析助手。帮助用户分析上传的文档、提取关键信息、回答关于文档内容的问题。 + +解析文档后,你会输出结构化的解析结果,并在回复中注明关键发现。`, collapsed: true, }, { kind: 'skills', description: - 'Skills 是模型可调用的内置能力(slash commands)。输入 / 开头即可触发,无需等待模型推理。当前对话中启用以下 skills:', + 'Skills 是模型可调用的内置能力(slash commands)。当前对话中启用以下 skills:', items: getSkills(['summarize', 'translate', 'qa']), collapsed: true, }, ], timestamp: now - 150000, }, + // --- User 上传文档请求解析 --- { id: 'c-2', role: 'user', segments: [ { kind: 'text', - content: '帮我审阅这篇论文草稿,看看结构上有什么问题:', - }, - { - kind: 'long_text', - content: longArticleContent_C, - charCount: longArticleContent_C.length, - collapsed: true, + content: '帮我解析这份市场研究报告,看看有什么关键发现。', }, { kind: 'document', - fileName: 'hci-paper-draft.pdf', + fileName: '2026-Q2-智能助手市场报告.pdf', mimeType: 'application/pdf', - snippet: - '# 大语言模型交互中的上下文透明性问题\n\n## 摘要\n\n近年来,以 ChatGPT 为代表的对话式 AI 产品迅速普及。然而,这些产品的交互设计普遍存在"上下文不透明"的问题——用户无法了解模型在生成回复时参考了哪些信息...', - sizeBytes: 245760, - }, - { - kind: 'media', - mediaType: 'image', - url: '', - altText: '论文框架图:Context Layers 分层示意图', + sizeBytes: 2_845_000, + snippet: '# 2026 年 Q2 智能助手市场研究报告\n\n## 摘要\n\n2026 年 Q2 全球智能助手市场规模预计达到 187 亿美元,同比增长 34.2%。主要增长驱动力包括企业级 AI 助手采纳率提升…', + parsedContent: marketReportParsed, }, ], timestamp: now - 120000, }, + // --- Assistant 综合回复 --- { id: 'c-3', role: 'assistant', segments: [ { kind: 'text', - content: - '我读完了你的草稿。整体框架很清晰,但有几个建议:\n\n1. **第3节的设计原则**是目前最强的部分,可以考虑将这部分提前到第2节\n2. "信息密度梯度"这个概念很有原创性,建议在摘要中就提及\n3. 缺少用户研究部分——如果你有做可用性测试的计划,可以加一节"4. 评估方法"\n4. 颜色编码系统部分写得很好,可以加一个视觉化的表格来展示颜色-类型映射\n\n需要我展开其中某一点吗?', + content: `文档已解析完成。以下是报告中的关键发现: + +--- + +## 📊 核心发现 + +### 1. 市场规模与增长 +2026 年 Q2 全球智能助手市场规模预计达到 **187 亿美元**,同比增长 **34.2%**。 + +主要驱动力: +- 企业级 AI 助手采纳率从 38% 提升至 **56%** +- 多模态能力推动使用场景扩展 +- 开源模型降低了部署门槛 + +### 2. 竞争格局变化 + +| 厂商 | 份额 | 环比变化 | 核心优势 | +|------|------|---------|---------| +| OpenAI | 41% | +2.3% | 品牌 + 开发者生态 | +| Anthropic | 18% | **+5.1%** | 安全对齐 + 长上下文 | +| Google | 15% | -1.2% | 搜索整合 + 多模态 | +| Meta | 12% | +3.8% | 开源 + 成本优势 | + +Anthropic 的增长最快(+5.1%),说明 **安全对齐** 正在成为关键竞争力。 + +### 3. 值得关注的趋势 + +- **可信度** 是用户选择助手的首要因素(47% 受访者提及) +- 企业用户对 \`system prompt\` 透明度的需求同比增长 **82%** +- 工具调用(Function Calling)使用率从 23% 增长到 51% +- 报告结语指出:**竞争正从模型能力转向体验设计** + +--- + +需要我深入分析某个方面吗?点击文档的 **「查看解析」** 按钮可以看到 AI 提取的完整结构化内容。`, }, ], timestamp: now - 60000, diff --git a/src/data/demos/demo-e.ts b/src/data/demos/demo-e.ts index e21a02a..e04f011 100644 --- a/src/data/demos/demo-e.ts +++ b/src/data/demos/demo-e.ts @@ -1,13 +1,53 @@ +/** + * Demo E — 日志分析(无文档传入) + * + * 场景:用户分享一段 Nginx 访问日志,请求 AI 助手帮忙分析 + * 异常模式和潜在安全风险。 + * + * 关键展示: + * 1. long_text 用于展示原始日志全文(折叠态仅显示前2行) + * 2. tool_call_request/result 展示日志分析工具的调用过程 + * 3. static_var 注入服务器环境和分析参数 + * 4. memory 记录用户的系统环境和分析偏好 + * 5. 无 document/media 段 —— 突出"纯文本日志分析"场景 + */ + import type { PromptEnvelope } from '../../types/protocol' import { getSkills } from '../skills' const now = Date.now() +const sampleLog = `192.168.1.10 - - [07/Jun/2026:10:15:23 +0800] "GET /api/users HTTP/1.1" 200 1234 "-" "curl/7.88.1" +192.168.1.20 - - [07/Jun/2026:10:15:25 +0800] "POST /api/login HTTP/1.1" 302 0 "-" "Mozilla/5.0" +10.0.0.5 - - [07/Jun/2026:10:15:28 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28" +192.168.1.10 - - [07/Jun/2026:10:16:01 +0800] "GET /api/orders HTTP/1.1" 200 8921 "-" "curl/7.88.1" +203.0.113.42 - - [07/Jun/2026:10:16:05 +0800] "GET /admin HTTP/1.1" 403 189 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:06 +0800] "GET /admin/config HTTP/1.1" 404 153 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:07 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:08 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:09 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:10 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:11 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +192.168.1.30 - - [07/Jun/2026:10:17:00 +0800] "GET /api/products?page=1 HTTP/1.1" 200 15420 "-" "Mozilla/5.0" +192.168.1.30 - - [07/Jun/2026:10:17:02 +0800] "GET /api/products?page=2 HTTP/1.1" 200 14893 "-" "Mozilla/5.0" +192.168.1.30 - - [07/Jun/2026:10:17:04 +0800] "GET /api/products?page=3 HTTP/1.1" 200 15102 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:30 +0800] "GET / HTTP/1.1" 200 5678 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:32 +0800] "GET /static/css/main.css HTTP/1.1" 200 28491 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:33 +0800] "GET /static/js/app.js HTTP/1.1" 200 128034 "-" "Mozilla/5.0" +10.0.0.5 - - [07/Jun/2026:10:20:00 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28" +192.168.1.10 - - [07/Jun/2026:10:21:15 +0800] "GET /api/users HTTP/1.1" 200 1234 "-" "curl/7.88.1" +192.168.1.10 - - [07/Jun/2026:10:21:16 +0800] "GET /api/orders HTTP/1.1" 200 8921 "-" "curl/7.88.1" +192.168.1.10 - - [07/Jun/2026:10:21:17 +0800] "GET /api/products HTTP/1.1" 200 15420 "-" "curl/7.88.1" +10.0.0.6 - - [07/Jun/2026:10:22:00 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:05 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:10 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:15 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28"` + export const demoE: PromptEnvelope = { version: '1.0', model: 'claude-opus-4-8', messages: [ - // --- System message: 加载 skills + memory + tools --- + // --- System message --- { id: 'e-1', role: 'system', @@ -20,45 +60,56 @@ export const demoE: PromptEnvelope = { }, { kind: 'static_var', - name: 'language', - value: '中文(简体)', - description: '模型回复的首选语言', + name: 'server_name', + value: 'production-api-01', + description: '目标服务器名称', }, { kind: 'static_var', - name: 'knowledge_cutoff', - value: '2026年1月', - description: '模型训练数据截止日期', + name: 'analysis_depth', + value: '全面(异常检测 + 安全审计 + 性能分析)', + description: '日志分析的范围深度', }, { kind: 'system_prompt', content: `当前日期:{{current_date}} -回复语言:{{language}} -知识截止:{{knowledge_cutoff}} +目标服务器:{{server_name}} +分析范围:{{analysis_depth}} -你是 HCI 课程设计助手,具备 Anthropic Skills 机制。 +你是日志分析专家助手。你的核心能力: -你有以下 skills 可用。用户输入以 / 开头的命令时会直接触发对应 skill。你也可以在分析用户意图后,主动建议合适的 skill。 +1. **异常检测** — 识别错误状态码(4xx/5xx)、请求突增、响应时间异常 +2. **安全审计** — 发现暴力破解尝试、路径探测、SQL 注入尝试 +3. **性能分析** — 统计端点响应分布、慢请求排查、热点资源识别 +4. **趋势报告** — 按时间窗口聚合,生成可读性高的分析摘要 -回复风格:简洁、有结构、给出可操作建议。`, +分析原则: +- 优先发现模式而非孤立事件 +- 区分误报和真正的问题 +- 每个发现标注严重等级和置信度 +- 在工具调用中执行计算分析,回复中给出解读`, collapsed: true, }, { kind: 'memory', description: - '以下是从过往对话中总结的关于你的信息,模型会参考这些记忆来个性化回复。', + '以下是你对用户的了解,参考这些记录来提供个性化的日志分析服务。', items: [ { - title: '用户背景', - content: '小明,设计系研二,HCI 方向。正在做课程设计,课题是 LLM 上下文透明性。', + title: '用户身份', + content: '小陈,后端开发工程师,负责生产环境的运维监控。', }, { - title: '当前进度', - content: '已完成 MVP 开发(React + TypeScript 聊天界面),展示了 9 种 Segment 的差异化渲染。', + title: '系统环境', + content: 'Kubernetes 集群上的微服务架构,API 网关使用 Nginx。生产环境有三台节点。', }, { - title: '关注点', - content: '关心 Anthropic Skills 的渐进式披露机制能否作为 HCI 课程中的交互设计案例。', + title: '分析偏好', + content: '偏好先看整体概览再深入细节。对安全相关告警特别敏感,需要高亮标注。', + }, + { + title: '上次分析记录', + content: '上周分析过同一台服务器的日志,发现了一个定时任务导致的 503 抖动。', }, ], collapsed: true, @@ -66,190 +117,285 @@ export const demoE: PromptEnvelope = { { kind: 'skills', description: - 'Skills 是模型可调用的内置能力。输入 / 触发,或根据对话上下文由 Agent 自动判断并调用。当前可用以下 skills:', - items: getSkills(['deep-research', 'code-review', 'verify', 'simplify', 'loop']), + '以下是可用的技能助手,通过 /skill_name 触发:', + items: getSkills(['summarize', 'qa', 'translate']), collapsed: true, }, { kind: 'tool_overview', items: [ { - name: 'run_skill', - description: '执行一个 Skill(slash command)', - parameters: 'skill_name: string, input: string', + name: 'run_code', + description: '在沙箱中执行 Python/Shell 代码进行日志解析和统计', + parameters: 'language: string, code: string', schema: { type: 'object', properties: { - skill_name: { type: 'string', description: 'Skill 名称' }, - input: { type: 'string', description: '传递给 skill 的用户输入' }, + language: { type: 'string', enum: ['python', 'bash'], description: '执行语言' }, + code: { type: 'string', description: '要执行的代码' }, }, - required: ['skill_name', 'input'], + required: ['language', 'code'], + }, + }, + { + name: 'search_knowledge', + description: '搜索已知的漏洞模式和安全公告', + parameters: 'query: string', + schema: { + type: 'object', + properties: { + query: { type: 'string', description: '搜索关键词' }, + }, + required: ['query'], }, }, ], collapsed: true, }, ], - timestamp: now - 360000, + timestamp: now - 600000, }, - // --- User message: 触发 research 需求 --- + // --- User 请求日志分析 --- { id: 'e-2', role: 'user', segments: [ { kind: 'text', - content: '我想深入了解 Anthropic Skills 的渐进式披露机制(Progressive Disclosure),作为我的 HCI 课程论文的案例研究对象。请帮我调研一下这个机制的设计原理、交互模式和学术界相关讨论。', + content: '生产环境 API 服务器刚刚的访问日志,帮我看一下有没有异常。我自己扫了一遍,感觉有几个可疑的 IP 在尝试访问 /admin 路径,但不太确定是不是误报。另外 /health 端点偶尔返回 503 的情况也需要你分析一下。', + }, + { + kind: 'long_text', + content: sampleLog, + charCount: sampleLog.length, + collapsed: true, }, ], - timestamp: now - 300000, + timestamp: now - 500000, }, - // --- Assistant: 判断需要 research,主动触发 /deep-research --- + // --- Assistant 初始分析回复 --- { id: 'e-3', role: 'assistant', segments: [ { kind: 'text', - content: `你的课程论文选题很棒!Anthropic Skills 的渐进式披露机制确实是一个很好的 HCI 案例分析对象——它以 **三阶段信息展开**(overview → detail → full instructions)来降低认知负荷,同时保持功能的可发现性。 + content: `我来分析这份日志。先快速概览一下整体情况: -让我用 \`/deep-research\` skill 做一个系统性调研:`, +从格式看是标准的 Nginx combined 格式,时间窗口约 **10:15–10:22**(约 7 分钟),共 **25 条**请求记录。几家不同的客户端: + +- **192.168.1.10** — 内部 API 调用(curl) +- **192.168.1.20** — 正常浏览器登录 +- **10.0.0.5** — K8s 健康检查 +- **192.168.1.30** — 浏览器浏览商品页面 +- **198.51.100.7** — 正常用户访问首页 +- **10.0.0.6** — 另一台节点的健康检查 +- **203.0.113.42** — ⚠️ 可疑 IP + +我先用 \`run_code\` 对请求做聚合统计,确认模式后再深入分析可疑流量。`, }, { kind: 'tool_call_request', - toolName: 'run_skill', + toolName: 'run_code', arguments: { - skill_name: 'deep-research', - input: 'Anthropic Skills progressive disclosure mechanism — design principles, interaction patterns, HCI academic discussions, related concepts (progressive disclosure in UX, Nielsen\'s heuristics, information architecture patterns for AI interfaces)', + language: 'python', + code: `from collections import Counter, defaultdict +import re + +log_text = """192.168.1.10 - - [07/Jun/2026:10:15:23 +0800] "GET /api/users HTTP/1.1" 200 1234 "-" "curl/7.88.1" +192.168.1.20 - - [07/Jun/2026:10:15:25 +0800] "POST /api/login HTTP/1.1" 302 0 "-" "Mozilla/5.0" +10.0.0.5 - - [07/Jun/2026:10:15:28 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28" +192.168.1.10 - - [07/Jun/2026:10:16:01 +0800] "GET /api/orders HTTP/1.1" 200 8921 "-" "curl/7.88.1" +203.0.113.42 - - [07/Jun/2026:10:16:05 +0800] "GET /admin HTTP/1.1" 403 189 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:06 +0800] "GET /admin/config HTTP/1.1" 404 153 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:07 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:08 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:09 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:10 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +203.0.113.42 - - [07/Jun/2026:10:16:11 +0800] "POST /admin/login HTTP/1.1" 401 198 "-" "python-requests/2.31.0" +192.168.1.30 - - [07/Jun/2026:10:17:00 +0800] "GET /api/products?page=1 HTTP/1.1" 200 15420 "-" "Mozilla/5.0" +192.168.1.30 - - [07/Jun/2026:10:17:02 +0800] "GET /api/products?page=2 HTTP/1.1" 200 14893 "-" "Mozilla/5.0" +192.168.1.30 - - [07/Jun/2026:10:17:04 +0800] "GET /api/products?page=3 HTTP/1.1" 200 15102 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:30 +0800] "GET / HTTP/1.1" 200 5678 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:32 +0800] "GET /static/css/main.css HTTP/1.1" 200 28491 "-" "Mozilla/5.0" +198.51.100.7 - - [07/Jun/2026:10:18:33 +0800] "GET /static/js/app.js HTTP/1.1" 200 128034 "-" "Mozilla/5.0" +10.0.0.5 - - [07/Jun/2026:10:20:00 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28" +192.168.1.10 - - [07/Jun/2026:10:21:15 +0800] "GET /api/users HTTP/1.1" 200 1234 "-" "curl/7.88.1" +192.168.1.10 - - [07/Jun/2026:10:21:16 +0800] "GET /api/orders HTTP/1.1" 200 8921 "-" "curl/7.88.1" +192.168.1.10 - - [07/Jun/2026:10:21:17 +0800] "GET /api/products HTTP/1.1" 200 15420 "-" "curl/7.88.1" +10.0.0.6 - - [07/Jun/2026:10:22:00 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:05 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:10 +0800] "GET /health HTTP/1.1" 503 57 "-" "Kubernetes/1.28" +10.0.0.6 - - [07/Jun/2026:10:22:15 +0800] "GET /health HTTP/1.1" 200 2 "-" "Kubernetes/1.28""" + +# 解析日志 +pattern = r'(\\S+) - - \\[(.+?)\\] "(.+?)" (\\d+) (\\d+) ".*?" "(.*?)"' +records = [] +for line in log_text.strip().split('\\n'): + m = re.match(pattern, line) + if m: + records.append({ + 'ip': m.group(1), + 'time': m.group(2), + 'request': m.group(3), + 'status': int(m.group(4)), + 'size': int(m.group(5)), + 'ua': m.group(6) + }) + +# 1. IP 统计 +print("=== 按 IP 请求量统计 ===") +ip_counter = Counter(r['ip'] for r in records) +for ip, count in ip_counter.most_common(): + print(f" {ip:20s} → {count} 次请求") + +# 2. 状态码分布 +print("\\n=== 状态码分布 ===") +status_counter = Counter(r['status'] for r in records) +for code, count in sorted(status_counter.items()): + print(f" {code} → {count} 次") + +# 3. 可疑 IP 分析 +print("\\n=== 可疑 IP: 203.0.113.42 的请求序列 ===") +for r in records: + if r['ip'] == '203.0.113.42': + print(f" [{r['time']}] {r['request']} → {r['status']}") + +# 4. /health 端点分析 +print("\\n=== /health 端点状态 ===") +for r in records: + if '/health' in r['request']: + print(f" {r['ip']:15s} [{r['time']}] → {r['status']} (UA: {r['ua']})") + +# 5. 非 2xx 占比 +total = len(records) +errors = sum(1 for r in records if r['status'] >= 400) +print(f"\\n=== 总结 ===") +print(f" 总请求数: {total}") +print(f" 错误请求: {errors} ({errors/total*100:.1f}%)") +print(f" 正常请求: {total - errors} ({(total-errors)/total*100:.1f}%)")`, }, collapsed: false, }, ], - timestamp: now - 280000, + timestamp: now - 480000, }, - // --- Skill 触发:指令以 tool_call_result 形式追加到对话 --- + // --- Tool 调用结果 --- { id: 'e-4', role: 'assistant', segments: [ { kind: 'tool_call_result', - toolName: 'run_skill', + toolName: 'run_code', success: true, - result: `[/deep-research 已触发] + result: `=== 按 IP 请求量统计 === + 192.168.1.10 → 5 次请求 + 203.0.113.42 → 7 次请求 + 198.51.100.7 → 3 次请求 + 10.0.0.5 → 2 次请求 + 10.0.0.6 → 4 次请求 + 192.168.1.20 → 1 次请求 + 192.168.1.30 → 3 次请求 -深度研究工作流程: -1. 分析用户问题,拆解为 3-5 个子问题 -2. 对每个子问题执行多源搜索(学术 + 行业 + 新闻) -3. 抓取高相关性页面全文 -4. 交叉验证:至少两个独立来源确认同一关键事实 -5. 生成报告格式:摘要 → 分项发现 → 证据表 → 限定说明 -6. 每声明标注来源和可信度评级`, - collapsed: true, +=== 状态码分布 === + 200 → 14 次 + 302 → 1 次 + 401 → 5 次 + 403 → 1 次 + 404 → 1 次 + 503 → 3 次 + +=== 可疑 IP: 203.0.113.42 的请求序列 === + [07/Jun/2026:10:16:05 +0800] GET /admin → 403 + [07/Jun/2026:10:16:06 +0800] GET /admin/config → 404 + [07/Jun/2026:10:16:07 +0800] POST /admin/login → 401 + [07/Jun/2026:10:16:08 +0800] POST /admin/login → 401 + [07/Jun/2026:10:16:09 +0800] POST /admin/login → 401 + [07/Jun/2026:10:16:10 +0800] POST /admin/login → 401 + [07/Jun/2026:10:16:11 +0800] POST /admin/login → 401 + +=== /health 端点状态 === + 10.0.0.5 [07/Jun/2026:10:15:28 +0800] → 200 (UA: Kubernetes/1.28) + 10.0.0.5 [07/Jun/2026:10:20:00 +0800] → 200 (UA: Kubernetes/1.28) + 10.0.0.6 [07/Jun/2026:10:22:00 +0800] → 503 (UA: Kubernetes/1.28) + 10.0.0.6 [07/Jun/2026:10:22:05 +0800] → 503 (UA: Kubernetes/1.28) + 10.0.0.6 [07/Jun/2026:10:22:10 +0800] → 503 (UA: Kubernetes/1.28) + 10.0.0.6 [07/Jun/2026:10:22:15 +0800] → 503 (UA: Kubernetes/1.28) + +=== 总结 === + 总请求数: 25 + 错误请求: 10 (40.0%) + 非 2xx 响应占比高达 40%, + 主要集中在两个异常模式上。`, + collapsed: false, }, ], - timestamp: now - 270000, + timestamp: now - 460000, }, - // --- Skill execution result --- + // --- Assistant 综合报告 --- { id: 'e-5', role: 'assistant', - segments: [ - { - kind: 'tool_call_result', - toolName: 'run_skill', - success: true, - result: `[/deep-research] 执行完成 · 搜索 12 个来源 · 抓取 8 篇全文 · 交叉验证通过 - -## 摘要 - -Anthropic Skills 的渐进式披露机制是一种三层信息架构,专门为 AI 代理的可扩展功能系统设计。核心思想:"仅在用户需要时才展示细节",与 Nielsen 的经典可用性原则高度一致。 - -## 分项发现 - -### 1. 三层披露模型 - -| 层次 | 内容 | 触发时机 | -|------|------|---------| -| L1 概览 | 名称 + 一句话描述 | 始终可见(skills 面板) | -| L2 详情 | 功能说明 + 触发条件 + 参数 | 用户点击展开 | -| L3 指令 | 完整 system prompt 正文 | 用户再次点击"查看注入指令" | - -**设计原理**:这是 "information on demand" 模式的实现——信息存在但不喧嚣。L1 提供识别(recognition),L2 提供评估(evaluation),L3 提供理解(understanding)。 - -### 2. 与经典 HCI 理论的对应 - -- **Nielsen 的 Flexibility & Efficiency heuristics**:L1 满足新手(可识别),L3 满足专家(可审阅) -- **Shneiderman 的 Visual Information Seeking Mantra**:"Overview first, zoom and filter, then details-on-demand"——三层模型完美映射到 overview → zoom → details 流程 -- **Cognitive Load Theory (Sweller)**:L1 层只占用工作记忆的极小空间,L2/L3 按需加载 - -### 3. 与其他 AI 产品的对比 - -- **OpenAI GPTs**:配置页是扁平表单,缺乏渐进式展开 → 认知负荷高 -- **Gemini Gems**:类似 GPTs,所有配置信息同时可见 -- **Anthropic Skills**:三层的文件系统式浏览——/ 触发、描述预览、then 深入 - -### 4. 交互模式创新 - -Skills 采用了 **slash command + 自然语言** 的双模触发: -- 显式触发:用户输入 \`/skill-name\` -- 隐式触发:Agent 根据对话上下文判断并建议使用 skill - -这在 HCI 上称为 "mixed-initiative interaction"。 - -### 5. 学术相关文献 - -1. "Progressive Disclosure in Mobile UI" (CHI 2016) — 实验证明渐进式展开减少 37% 的错误操作 -2. "Designing for Mixed-Initiative Interaction" (TOCHI 2020) — Agent 主动建议 vs 用户显式触发的用户偏好研究 -3. "Information Scent in AI Interfaces" (CSCW 2024) — 讨论了 skills 描述如何帮助用户形成"信息气味" - -## 证据表 - -| 声明 | 来源 | 可信度 | -|------|------|--------| -| 三层披露模型 | Anthropic Agent SDK 文档 | ★★★★★ | -| 37% 错误减少 | CHI 2016 实验 | ★★★★ | -| Mixed-initiative | TOCHI 2020 | ★★★★ | - -## 限定说明 - -Anthropic Skills 机制仍在快速迭代中。上述分析基于 2026 年 6 月的公开文档和代码。建议在论文中标注版本时间。`, - collapsed: false, - }, - ], - timestamp: now - 260000, - }, - // --- Assistant: 综合报告 --- - { - id: 'e-6', - role: 'assistant', segments: [ { kind: 'text', - content: `## 调研结论 + content: `## 日志分析报告 -基于 \`/deep-research\` 的交叉验证结果,我建议你的论文从以下角度分析 Skills 渐进式披露: +### 🔴 高危:暴力破解尝试 -### 🎯 最佳分析框架 +**IP: 203.0.113.42**(来源:外部,UA: python-requests) -**Shneiderman 的 "Overview first, zoom and filter, then details-on-demand"** 是最贴切的理论框架——Skills 的三层模型几乎是对这个 mantra 的精确工程实现。 +在 **10:16:05–10:16:11** 的 6 秒内向 /admin 路径连续发送了 **7 次请求**,典型的暴力破解模式: -### 📐 可量化的 HCI 指标 +| 时间 | 请求 | 状态 | 说明 | +|------|------|------|------| +| +0s | GET /admin | 403 | 探路——发现 /admin 存在 | +| +1s | GET /admin/config | 404 | 试图访问敏感配置 | +| +2~6s | POST /admin/login ×5 | 401 | 连续尝试登录——5 次均失败 | -1. **信息可发现性**:L1 概览层——用户能否快速识别需要的 skill(recognition over recall) -2. **认知负荷**:对比"全量展示"vs"渐进式披露"的工作记忆占用 -3. **操作效率**:slash command 显式触发 vs Agent 隐式建议的完成时间对比 +**建议措施:** +- 🔒 立即对该 IP 加入 WAF 黑名单 +- 📋 检查 fail2ban 或类似自动封禁机制是否正常运行 +- 🚨 确认 admin 端点的访问控制策略(当前 403 正确拦截,但暴力破解仍消耗服务器资源) -### 🔗 建议引用的关键文献 +--- -- CHI 2016 的渐进式披露实验(有量化数据支持你的设计论点) -- TOCHI 2020 的 mixed-initiative 研究(对应双模触发机制) -- Anthropic 2025 的 Skills Architecture RFC(一手来源) +### 🟡 中危:/health 端点间歇 503 -需要我帮你生成论文的文献综述部分吗?`, +**节点 10.0.0.6** 在 **10:22:00–10:22:10** 的 10 秒内连续返回 503,随后恢复 200。而 **10.0.0.5** 一直正常。 + +这与上周分析中定时任务导致的 503 抖动模式一致。建议检查该节点上是否在整点前后有定时任务(如日志轮转、缓存预热等)。 + +**建议措施:** +- ⏰ 检查 10.0.0.6 的 cron 配置 +- 📊 添加更细粒度的 /health 监控(响应耗时 + 组件健康分别上报) +- 🔄 考虑滚动重启使两个节点的健康检查窗口错开 + +--- + +### 🟢 常规观察 + +- **192.168.1.10** — 内部 API 客户端,访问模式正常(用户/订单/商品查询) +- **192.168.1.20** — 一次正常登录(POST /api/login → 302 重定向) +- **198.51.100.7** — 正常用户访问,加载了首页 + CSS + JS +- **192.168.1.30** — 分页浏览商品,行为正常 +- 无性能异常(无超时记录或慢请求) + +--- + +### 📋 总结优先级 + +| 优先级 | 问题 | 影响 | +|--------|------|------| +| P0 | 203.0.113.42 暴力破解 | 安全风险,立即封禁 | +| P1 | 10.0.0.6 间歇 503 | 稳定性风险,排查定时任务 | +| P3 | 整体 40% 非 2xx | 排除以上两者后正常 | + +需要我进一步分析某个方面吗?比如用 search_knowledge 查询 203.0.113.42 是否在已知攻击数据库中出现过?`, }, ], - timestamp: now - 240000, + timestamp: now - 420000, }, ], } diff --git a/src/types/protocol.ts b/src/types/protocol.ts index ab2019e..410b8ea 100644 --- a/src/types/protocol.ts +++ b/src/types/protocol.ts @@ -132,6 +132,7 @@ export interface DocumentSegment { mimeType: string snippet: string // 前 200 字符预览 sizeBytes: number + parsedContent?: string // 解析后的完整文本内容(点击"查看解析"时展示) } export interface LongTextSegment {