Skip to content

Commit daf2c6c

Browse files
committed
feat(chatbot,chatengine): 文档拆分功能粒度细化demo
1 parent 5168868 commit daf2c6c

26 files changed

+2767
-121
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# ChatEngine 示例说明
2+
3+
本目录包含 ChatEngine 对话引擎的所有示例代码,按照从简单到复杂的顺序组织,方便用户循序渐进地学习。
4+
5+
## 📚 示例索引
6+
7+
### 快速开始(1个)
8+
9+
| 示例文件 | 示例名称 | 学习目标 | 代码量 |
10+
|---------|---------|---------|--------|
11+
| `basic.tsx` | 快速开始 | useChat Hook 基本用法 | ~78行 |
12+
13+
### 基础用法(3个)
14+
15+
| 示例文件 | 示例名称 | 学习目标 | 代码量 |
16+
|---------|---------|---------|--------|
17+
| `messages.tsx` | 消息管理 | 初始化、更新、历史回填 | ~141行 |
18+
| `custom-ui.tsx` | 自定义 UI | 自定义样式、操作按钮 | ~156行 |
19+
| `lifecycle.tsx` | 生命周期 | 状态监听、事件回调 | ~162行 |
20+
21+
### AG-UI 协议(3个)
22+
23+
| 示例文件 | 示例名称 | 学习目标 | 代码量 |
24+
|---------|---------|---------|--------|
25+
| `agui-basic.tsx` | AG-UI 基础 | 开启协议支持、文本消息 | ~92行 |
26+
| `agui-toolcall.tsx` | 工具调用 | useAgentToolcall、状态管理 | ~645行 |
27+
| `agui-comprehensive.tsx` | 综合示例 | 完整的多步骤任务规划 | ~400行+ |
28+
29+
### 其他示例
30+
31+
| 示例文件 | 示例名称 | 说明 |
32+
|---------|---------|------|
33+
| `hookComponent.tsx` | 旧版综合示例 | 已被拆分为多个示例 |
34+
| `agui.tsx` | 旧版 AG-UI 示例 | 已重构为 agui-basic.tsx |
35+
36+
## 🎯 学习路径
37+
38+
### 第一步:快速开始
39+
1. `basic.tsx` - 了解 useChat Hook 的基本用法
40+
41+
### 第二步:基础用法
42+
2. `messages.tsx` - 学习消息管理
43+
3. `custom-ui.tsx` - 掌握 UI 定制
44+
4. `lifecycle.tsx` - 理解生命周期
45+
46+
### 第三步:AG-UI 协议
47+
5. `agui-basic.tsx` - 了解 AG-UI 协议基础
48+
6. `agui-toolcall.tsx` - 学习工具调用和状态管理
49+
7. `agui-comprehensive.tsx` - 查看完整的实战案例
50+
51+
## 📖 示例特点
52+
53+
### ✅ 循序渐进
54+
- 从最简单的 78 行代码开始
55+
- 逐步增加复杂度
56+
- 每个示例聚焦单一功能点
57+
58+
### ✅ 功能聚焦
59+
- 每个示例只展示一个核心功能
60+
- 避免功能混杂
61+
- 易于理解和查找
62+
63+
### ✅ 代码简洁
64+
- 基础示例控制在 78-162 行
65+
- 添加详细注释
66+
- 突出关键代码
67+
68+
### ✅ 实用性强
69+
- 基于真实使用场景
70+
- 提供完整可运行代码
71+
- 包含调试技巧
72+
73+
## 🔍 快速查找
74+
75+
### 我想实现...
76+
77+
**基础功能**
78+
- **最简单的对话界面**`basic.tsx`
79+
- **初始化消息**`messages.tsx`
80+
- **加载历史消息**`messages.tsx`
81+
- **自定义消息样式**`custom-ui.tsx`
82+
- **添加操作按钮**`custom-ui.tsx`
83+
- **监听状态变化**`lifecycle.tsx`
84+
- **处理生命周期事件**`lifecycle.tsx`
85+
86+
**AG-UI 协议**
87+
- **开启 AG-UI 协议**`agui-basic.tsx`
88+
- **工具调用**`agui-toolcall.tsx`
89+
- **状态管理**`agui-toolcall.tsx`
90+
- **多步骤任务规划**`agui-comprehensive.tsx`
91+
- **人机协作**`agui-comprehensive.tsx`
92+
93+
## 💡 ChatEngine vs Chatbot
94+
95+
### ChatEngine 适用场景
96+
- ✅ 需要完全自定义 UI 结构
97+
- ✅ 需要精细控制消息处理流程
98+
- ✅ 需要集成 AG-UI 协议的高级特性
99+
- ✅ 需要构建复杂的智能体应用
100+
101+
### Chatbot 适用场景
102+
- ✅ 快速搭建标准对话界面
103+
- ✅ 使用内置的 UI 和交互逻辑
104+
- ✅ 不需要深度定制
105+
106+
## 📝 旧示例说明
107+
108+
以下示例已被重新组织:
109+
110+
- `hookComponent.tsx` → 已拆分为 `basic.tsx``messages.tsx``custom-ui.tsx`
111+
- `agui.tsx` → 已重构为 `agui-basic.tsx`
112+
- `videoclipState.tsx` → 重命名为 `agui-toolcall.tsx`
113+
- `travelToolcall.tsx` → 重命名为 `agui-comprehensive.tsx`
114+
115+
建议使用新的示例文件进行学习。
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React, { useState } from 'react';
2+
import {
3+
ChatList,
4+
ChatSender,
5+
ChatMessage,
6+
type TdChatSenderParams,
7+
type ChatRequestParams,
8+
} from '@tdesign-react/chat';
9+
import { useChat } from '../index';
10+
11+
/**
12+
* AG-UI 协议基础示例
13+
*
14+
* 学习目标:
15+
* - 开启 AG-UI 协议支持(protocol: 'agui')
16+
* - 理解 AG-UI 协议的自动解析机制
17+
* - 处理文本消息事件(TEXT_MESSAGE_*)
18+
*
19+
* AG-UI 协议说明:
20+
* AG-UI(Agent-User Interface)是专为 AI Agent 与前端应用交互设计的轻量级协议,
21+
* 专注于实时交互、状态流式传输和人机协作。
22+
*
23+
* 组件会自动解析以下标准事件:
24+
* - TEXT_MESSAGE_START/CHUNK/COMPLETE: 文本消息
25+
* - THINKING_START/CHUNK/COMPLETE: 思考过程
26+
* - TOOL_CALL_START/CHUNK/COMPLETE: 工具调用
27+
* - STATE_START/CHUNK/COMPLETE: 状态更新
28+
* 等等...
29+
*/
30+
export default function AguiBasicExample() {
31+
const [inputValue, setInputValue] = useState('AG-UI协议的作用是什么');
32+
33+
const { chatEngine, messages, status } = useChat({
34+
defaultMessages: [],
35+
chatServiceConfig: {
36+
endpoint: 'https://1257786608-9i9j1kpa67.ap-guangzhou.tencentscf.com/sse/agui-simple',
37+
// 开启 AG-UI 协议解析支持
38+
protocol: 'agui',
39+
stream: true,
40+
// 自定义请求参数
41+
onRequest: (params: ChatRequestParams) => ({
42+
headers: {
43+
'Content-Type': 'application/json',
44+
'X-Requested-With': 'XMLHttpRequest',
45+
},
46+
body: JSON.stringify({
47+
uid: 'agui-demo',
48+
prompt: params.prompt,
49+
}),
50+
}),
51+
// 生命周期回调
52+
onStart: (chunk) => {
53+
console.log('AG-UI 流式传输开始:', chunk);
54+
},
55+
onComplete: (aborted, params, event) => {
56+
console.log('AG-UI 流式传输完成:', { aborted, event });
57+
},
58+
onError: (err) => {
59+
console.error('AG-UI 错误:', err);
60+
},
61+
},
62+
});
63+
64+
const handleSend = async (e: CustomEvent<TdChatSenderParams>) => {
65+
const { value } = e.detail;
66+
await chatEngine.sendUserMessage({ prompt: value });
67+
setInputValue('');
68+
};
69+
70+
return (
71+
<div style={{ height: '500px', display: 'flex', flexDirection: 'column' }}>
72+
<ChatList style={{ flex: 1 }}>
73+
{messages.map((message) => (
74+
<ChatMessage
75+
key={message.id}
76+
message={message}
77+
placement={message.role === 'user' ? 'right' : 'left'}
78+
variant={message.role === 'user' ? 'base' : 'text'}
79+
/>
80+
))}
81+
</ChatList>
82+
83+
<ChatSender
84+
value={inputValue}
85+
placeholder="请输入内容,体验 AG-UI 协议"
86+
loading={status === 'pending' || status === 'streaming'}
87+
onChange={(e) => setInputValue(e.detail)}
88+
onSend={handleSend}
89+
onStop={() => chatEngine.abortChat()}
90+
/>
91+
</div>
92+
);
93+
}

packages/pro-components/chat/chat-engine/_example/travelToolcall.tsx renamed to packages/pro-components/chat/chat-engine/_example/agui-comprehensive.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export default function TravelPlannerChat() {
7878

7979
// 创建聊天服务配置
8080
const createChatServiceConfig = () => ({
81+
defaultMessages: [],
8182
// 对话服务地址 - 使用 POST 请求
8283
endpoint: `https://1257786608-9i9j1kpa67.ap-guangzhou.tencentscf.com/sse/agui`,
8384
protocol: 'agui' as const,

packages/pro-components/chat/chat-engine/_example/videoclipState.tsx renamed to packages/pro-components/chat/chat-engine/_example/agui-toolcall.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ export default function VideoClipAgentChatWithSubscription() {
441441
endpoint: `https://1257786608-9i9j1kpa67.ap-guangzhou.tencentscf.com/sse/videoclip`,
442442
protocol: 'agui' as const,
443443
stream: true,
444+
defaultMessages: [],
444445
// 流式对话结束
445446
onComplete: (isAborted: boolean, params?: RequestInit, parsed?: any) => {
446447
if (parsed?.result?.status === 'user_aborted') {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, { useRef, useState } from 'react';
2+
import {
3+
ChatList,
4+
ChatSender,
5+
ChatMessage,
6+
type SSEChunkData,
7+
type AIMessageContent,
8+
type TdChatSenderParams,
9+
} from '@tdesign-react/chat';
10+
import { useChat } from '@tdesign-react/chat';
11+
12+
/**
13+
* 快速开始示例
14+
*
15+
* 学习目标:
16+
* - 使用 useChat Hook 创建聊天引擎
17+
* - 组合 ChatList、ChatMessage、ChatSender 组件
18+
* - 理解 chatEngine、messages、status 的作用
19+
*/
20+
export default function BasicExample() {
21+
const [inputValue, setInputValue] = useState('');
22+
23+
// 使用 useChat Hook 创建聊天引擎
24+
const { chatEngine, messages, status } = useChat({
25+
defaultMessages: [],
26+
chatServiceConfig: {
27+
endpoint: 'https://1257786608-9i9j1kpa67.ap-guangzhou.tencentscf.com/sse/normal',
28+
stream: true,
29+
// 数据转换
30+
onMessage: (chunk: SSEChunkData): AIMessageContent => {
31+
const { type, ...rest } = chunk.data;
32+
return {
33+
type: 'markdown',
34+
data: rest?.msg || '',
35+
};
36+
},
37+
},
38+
});
39+
40+
// 发送消息
41+
const handleSend = async (e: CustomEvent<TdChatSenderParams>) => {
42+
const { value } = e.detail;
43+
await chatEngine.sendUserMessage({ prompt: value });
44+
setInputValue('');
45+
};
46+
47+
// 停止生成
48+
const handleStop = () => {
49+
chatEngine.abortChat();
50+
};
51+
52+
return (
53+
<div style={{ height: '500px', display: 'flex', flexDirection: 'column' }}>
54+
{/* 消息列表 */}
55+
<ChatList style={{ flex: 1 }}>
56+
{messages.map((message) => (
57+
<ChatMessage
58+
key={message.id}
59+
message={message}
60+
placement={message.role === 'user' ? 'right' : 'left'}
61+
variant={message.role === 'user' ? 'base' : 'text'}
62+
/>
63+
))}
64+
</ChatList>
65+
66+
{/* 输入框 */}
67+
<ChatSender
68+
value={inputValue}
69+
placeholder="请输入内容"
70+
loading={status === 'pending' || status === 'streaming'}
71+
onChange={(e) => setInputValue(e.detail)}
72+
onSend={handleSend}
73+
onStop={handleStop}
74+
/>
75+
</div>
76+
);
77+
}

0 commit comments

Comments
 (0)