fix: AgentChatPage dependencies and Spin component warning
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
# Day 23-24:知识库检索 + @引用功能完成 ✅
|
||||
|
||||
**开发时间**: Day 23-24
|
||||
**开发人员**: AI助手
|
||||
**任务状态**: ✅ 已完成(里程碑1核心功能完成!)
|
||||
|
||||
---
|
||||
|
||||
## 📋 任务概述
|
||||
|
||||
实现对话中引用知识库的完整功能,用户可以通过 `@知识库` 引用已上传的文献,AI基于文献内容进行精准回答。
|
||||
|
||||
---
|
||||
|
||||
## ✅ 已完成功能
|
||||
|
||||
### 1. 知识库检索API(后端)
|
||||
**文件**: `backend/src/services/knowledgeBaseService.ts`
|
||||
|
||||
- ✅ Day 20已实现Dify检索API集成
|
||||
- ✅ 支持语义检索,返回最相关的文档片段
|
||||
- ✅ 返回相似度分数,便于质量评估
|
||||
|
||||
**API接口**:
|
||||
```
|
||||
GET /api/v1/knowledge-bases/:id/search?query=骨质疏松&top_k=3
|
||||
```
|
||||
|
||||
**返回数据**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"query": { "content": "骨质疏松" },
|
||||
"records": [
|
||||
{
|
||||
"segment": {
|
||||
"id": "xxx",
|
||||
"content": "相关文档内容...",
|
||||
"document_id": "xxx"
|
||||
},
|
||||
"score": 0.85
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 前端@知识库选择器
|
||||
**文件**: `frontend/src/pages/AgentChatPage.tsx`
|
||||
|
||||
**核心改动**:
|
||||
```typescript
|
||||
// 1. 引入知识库Store
|
||||
import { useKnowledgeBaseStore } from '../stores/useKnowledgeBaseStore'
|
||||
|
||||
// 2. 加载知识库列表
|
||||
const { knowledgeBases, fetchKnowledgeBases } = useKnowledgeBaseStore()
|
||||
|
||||
useEffect(() => {
|
||||
fetchKnowledgeBases()
|
||||
}, [])
|
||||
|
||||
// 3. 传递给MessageInput组件
|
||||
<MessageInput
|
||||
onSend={handleSendMessage}
|
||||
loading={sending}
|
||||
knowledgeBases={knowledgeBases} // ✅ 知识库列表
|
||||
placeholder={`向${agent.name}提问...`}
|
||||
/>
|
||||
```
|
||||
|
||||
**UI功能**:
|
||||
- ✅ 点击"@知识库"按钮弹出下拉菜单
|
||||
- ✅ 显示用户所有知识库列表
|
||||
- ✅ 支持多选知识库(蓝色标签显示)
|
||||
- ✅ 可移除已选择的知识库
|
||||
|
||||
---
|
||||
|
||||
### 3. 对话集成知识库检索(后端)
|
||||
**文件**: `backend/src/services/conversationService.ts`
|
||||
|
||||
**核心实现**:
|
||||
```typescript
|
||||
// 1. 导入知识库服务
|
||||
import * as knowledgeBaseService from './knowledgeBaseService.js';
|
||||
|
||||
// 2. 发送消息时检索知识库
|
||||
if (knowledgeBaseIds && knowledgeBaseIds.length > 0) {
|
||||
const knowledgeResults: string[] = [];
|
||||
|
||||
// 对每个知识库进行检索
|
||||
for (const kbId of knowledgeBaseIds) {
|
||||
const searchResult = await knowledgeBaseService.searchKnowledgeBase(
|
||||
userId,
|
||||
kbId,
|
||||
content, // 用户问题作为检索query
|
||||
3 // 每个知识库返回3个最相关段落
|
||||
);
|
||||
|
||||
// 格式化检索结果
|
||||
if (searchResult.records && searchResult.records.length > 0) {
|
||||
const kbInfo = await prisma.knowledgeBase.findUnique({
|
||||
where: { id: kbId },
|
||||
select: { name: true },
|
||||
});
|
||||
|
||||
knowledgeResults.push(
|
||||
`【知识库:${kbInfo?.name || '未命名'}】\n` +
|
||||
searchResult.records
|
||||
.map((record: any, index: number) => {
|
||||
const score = (record.score * 100).toFixed(1);
|
||||
return `${index + 1}. [相关度${score}%] ${record.segment.content}`;
|
||||
})
|
||||
.join('\n\n')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (knowledgeResults.length > 0) {
|
||||
knowledgeBaseContext = knowledgeResults.join('\n\n---\n\n');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**工作流程**:
|
||||
1. 用户选择知识库并发送问题
|
||||
2. 后端对每个知识库调用Dify检索API
|
||||
3. 获取最相关的文档片段(top_k=3)
|
||||
4. 格式化检索结果(包含知识库名称和相关度)
|
||||
5. 将检索结果注入到LLM上下文
|
||||
6. LLM基于文献内容生成回答
|
||||
|
||||
---
|
||||
|
||||
### 4. 上下文组装优化
|
||||
**文件**: `backend/src/services/conversationService.ts` - `assembleContext()`
|
||||
|
||||
**智能上下文注入**:
|
||||
```typescript
|
||||
// 第一条消息:使用完整模板(包含项目背景 + 知识库上下文)
|
||||
if (isFirstMessage) {
|
||||
userPromptContent = agentService.renderUserPrompt(agentId, {
|
||||
projectBackground,
|
||||
userInput,
|
||||
knowledgeBaseContext,
|
||||
});
|
||||
}
|
||||
// 后续消息:只发送用户输入 + 知识库上下文
|
||||
else {
|
||||
if (knowledgeBaseContext) {
|
||||
userPromptContent = `${userInput}\n\n## 参考文献(来自知识库)\n${knowledgeBaseContext}`;
|
||||
} else {
|
||||
userPromptContent = userInput;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- ✅ 节省token消耗(避免重复发送项目背景)
|
||||
- ✅ 动态注入知识库内容(只在需要时添加)
|
||||
- ✅ 保持对话上下文连贯性
|
||||
|
||||
---
|
||||
|
||||
## 🔄 完整工作流程
|
||||
|
||||
```
|
||||
用户操作流程:
|
||||
1. 进入智能体对话页面
|
||||
2. 点击"@知识库"按钮
|
||||
3. 选择一个或多个知识库
|
||||
4. 输入问题(如"AI在临床研究中有哪些应用?")
|
||||
5. 点击发送
|
||||
|
||||
系统处理流程:
|
||||
[前端] 发送消息 + knowledgeBaseIds[]
|
||||
↓
|
||||
[后端] 接收消息请求
|
||||
↓
|
||||
[后端] 对每个知识库调用Dify检索API
|
||||
↓
|
||||
[Dify] 语义检索返回最相关文档片段
|
||||
↓
|
||||
[后端] 格式化检索结果(知识库名 + 相关度 + 内容)
|
||||
↓
|
||||
[后端] 组装上下文:系统提示 + 历史消息 + 用户问题 + 文献内容
|
||||
↓
|
||||
[LLM] DeepSeek-V3基于文献生成回答
|
||||
↓
|
||||
[后端] 流式返回AI回答
|
||||
↓
|
||||
[前端] 实时显示流式输出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心技术亮点
|
||||
|
||||
### 1. RAG(检索增强生成)完整实现
|
||||
- ✅ 用户问题 → 语义检索 → 相关文档 → LLM生成
|
||||
- ✅ 提高AI回答的准确性和可信度
|
||||
- ✅ 支持引用来源追溯
|
||||
|
||||
### 2. 多知识库联合检索
|
||||
- ✅ 支持同时选择多个知识库
|
||||
- ✅ 分别检索后合并结果
|
||||
- ✅ 标注知识库来源
|
||||
|
||||
### 3. 相关度评分展示
|
||||
- ✅ Dify返回0-1的相似度分数
|
||||
- ✅ 转换为百分比展示(如"相关度85.3%")
|
||||
- ✅ 帮助用户评估引用质量
|
||||
|
||||
### 4. 错误容错机制
|
||||
- ✅ 单个知识库检索失败不影响其他知识库
|
||||
- ✅ 检索失败不阻断对话(降级为无文献回答)
|
||||
- ✅ 详细的错误日志记录
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据流示例
|
||||
|
||||
**用户输入**:
|
||||
```
|
||||
问题: "AI在临床研究中有哪些应用?"
|
||||
选择知识库: ["我的研究文献"]
|
||||
```
|
||||
|
||||
**检索结果(注入LLM上下文)**:
|
||||
```
|
||||
## 参考文献(来自知识库)
|
||||
|
||||
【知识库:我的研究文献】
|
||||
|
||||
1. [相关度92.3%] AI临床研究文献解决方案主要包括以下几个方向:
|
||||
- 智能诊断:利用深度学习分析医学影像...
|
||||
- 药物研发:通过AI预测药物分子结构...
|
||||
|
||||
2. [相关度87.5%] 在临床试验设计中,AI可以优化患者招募...
|
||||
|
||||
3. [相关度81.2%] AI辅助的临床决策支持系统能够...
|
||||
```
|
||||
|
||||
**LLM回答**(基于检索内容):
|
||||
```
|
||||
根据您上传的文献,AI在临床研究中主要有以下应用:
|
||||
|
||||
1. **智能诊断**: 利用深度学习分析医学影像,可以提高诊断准确率...
|
||||
2. **药物研发**: 通过AI预测药物分子结构,加速新药研发...
|
||||
3. **临床试验优化**: AI可以优化患者招募流程...
|
||||
...
|
||||
|
||||
📄 以上内容来自您的知识库"我的研究文献"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试建议
|
||||
|
||||
### 1. 基础功能测试
|
||||
- [ ] 点击"@知识库"能否正常显示知识库列表
|
||||
- [ ] 选择知识库后是否出现蓝色标签
|
||||
- [ ] 能否移除已选择的知识库
|
||||
- [ ] 发送消息后AI是否基于文献回答
|
||||
|
||||
### 2. 多知识库测试
|
||||
- [ ] 同时选择2-3个知识库
|
||||
- [ ] 验证AI回答是否整合多个来源
|
||||
|
||||
### 3. 相关性测试
|
||||
- [ ] 问与文献相关的问题(应精准回答)
|
||||
- [ ] 问与文献无关的问题(应说明文献中无相关内容)
|
||||
|
||||
### 4. 边界情况测试
|
||||
- [ ] 知识库为空时的处理
|
||||
- [ ] 不选择知识库的普通对话
|
||||
- [ ] 检索失败时的降级处理
|
||||
|
||||
---
|
||||
|
||||
## 📁 涉及文件清单
|
||||
|
||||
### 后端修改
|
||||
- `backend/src/services/conversationService.ts` - 集成知识库检索
|
||||
- 添加 `knowledgeBaseService` 导入
|
||||
- 实现检索逻辑(流式和非流式)
|
||||
- 格式化检索结果注入上下文
|
||||
|
||||
### 前端修改
|
||||
- `frontend/src/pages/AgentChatPage.tsx` - 加载知识库列表
|
||||
- 引入 `useKnowledgeBaseStore`
|
||||
- 添加 `fetchKnowledgeBases()` 调用
|
||||
- 传递 `knowledgeBases` 给 `MessageInput`
|
||||
|
||||
### 前端已有组件(Day 18-19已实现)
|
||||
- `frontend/src/components/chat/MessageInput.tsx` - @知识库UI
|
||||
- `frontend/src/stores/useKnowledgeBaseStore.ts` - 知识库状态管理
|
||||
|
||||
---
|
||||
|
||||
## 🎉 里程碑1 - 完成度评估
|
||||
|
||||
### ✅ 已完成核心功能(100%)
|
||||
1. ✅ 用户认证与项目管理
|
||||
2. ✅ 12个AI智能体配置与调用
|
||||
3. ✅ 多轮对话上下文管理
|
||||
4. ✅ 流式输出(打字机效果)
|
||||
5. ✅ 模型切换(DeepSeek-V3/Qwen3-72b/Gemini-Pro)
|
||||
6. ✅ 个人知识库管理(创建/上传/删除)
|
||||
7. ✅ @知识库检索与RAG集成 ⭐ **今日完成**
|
||||
|
||||
### 🚀 下一步工作
|
||||
|
||||
**里程碑2预览**(预计2-3天):
|
||||
1. 项目协作功能(成员管理、权限控制)
|
||||
2. 对话历史管理(查看、搜索、导出)
|
||||
3. AI回答评价与反馈
|
||||
4. 引用溯源优化(点击引用查看原文)
|
||||
|
||||
---
|
||||
|
||||
## 💡 技术收获
|
||||
|
||||
### 1. RAG系统设计经验
|
||||
- 检索质量直接影响AI回答质量
|
||||
- top_k参数需要平衡相关性和上下文长度
|
||||
- 多知识库检索需要合并策略
|
||||
|
||||
### 2. LLM上下文管理
|
||||
- 第一条消息注入完整背景
|
||||
- 后续消息动态添加知识库内容
|
||||
- 控制token消耗同时保持连贯性
|
||||
|
||||
### 3. 错误处理最佳实践
|
||||
- 外部API调用必须有容错
|
||||
- 降级策略保证基础功能可用
|
||||
- 详细日志便于问题排查
|
||||
|
||||
---
|
||||
|
||||
## 📝 用户测试指南
|
||||
|
||||
### 前置条件
|
||||
1. 确保Dify服务运行正常
|
||||
2. 已创建知识库并上传至少1个文档
|
||||
3. 文档已完成索引(Dify后台显示"已完成")
|
||||
|
||||
### 测试步骤
|
||||
|
||||
**Step 1: 清空浏览器缓存**
|
||||
```
|
||||
1. 按 Ctrl+F5 硬刷新页面
|
||||
2. 或使用无痕模式访问 http://localhost:3000
|
||||
```
|
||||
|
||||
**Step 2: 进入对话页面**
|
||||
```
|
||||
1. 访问首页
|
||||
2. 选择任意智能体(推荐"话题评估专家")
|
||||
```
|
||||
|
||||
**Step 3: 使用@知识库**
|
||||
```
|
||||
1. 点击输入框下方的"@知识库"按钮
|
||||
2. 从下拉菜单选择知识库(如"我的研究文献")
|
||||
3. 看到蓝色标签显示已选择
|
||||
4. 输入问题,例如:
|
||||
- "AI在临床研究中有哪些应用?"
|
||||
- "这篇文献的主要结论是什么?"
|
||||
- "请总结文献中的研究方法"
|
||||
5. 点击发送
|
||||
```
|
||||
|
||||
**Step 4: 观察AI回答**
|
||||
```
|
||||
✅ 正常情况:
|
||||
- AI回答与文档内容高度相关
|
||||
- 引用文档中的具体信息
|
||||
- 回答比不@知识库更精准
|
||||
|
||||
❌ 异常情况请反馈:
|
||||
- AI回答完全不相关
|
||||
- 提示"检索失败"
|
||||
- 页面报错
|
||||
```
|
||||
|
||||
**Step 5: 查看后端日志**
|
||||
```
|
||||
后端控制台应能看到:
|
||||
- 检索知识库的日志
|
||||
- 返回的相关文档数量
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 已知问题
|
||||
|
||||
无
|
||||
|
||||
---
|
||||
|
||||
## 🔗 相关文档
|
||||
|
||||
- [Day 18: Dify部署完成](./Day18-Dify部署完成.md)
|
||||
- [Day 19-20: 知识库API完成](./Day19-20-知识库API完成.md)
|
||||
- [Day 21-22: 知识库前端开发与问题修复](./Day21-22-知识库前端开发与问题修复.md)
|
||||
- [产品需求文档](../00-项目概述/产品需求文档\(PRD\).md)
|
||||
- [开发里程碑](../04-开发计划/开发里程碑.md)
|
||||
|
||||
---
|
||||
|
||||
**文档创建时间**: 2025-10-11
|
||||
**最后更新**: 2025-10-11
|
||||
|
||||
|
||||
@@ -15,22 +15,18 @@ const AgentChatPage = () => {
|
||||
const { currentProject } = useProjectStore()
|
||||
const { knowledgeBases, fetchKnowledgeBases } = useKnowledgeBaseStore()
|
||||
|
||||
// 智能体相关状态
|
||||
const [agent, setAgent] = useState<AgentConfig | null>(null)
|
||||
// 智能体相关状� const [agent, setAgent] = useState<AgentConfig | null>(null)
|
||||
const [agentLoading, setAgentLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
// 对话相关状态
|
||||
const [conversation, setConversation] = useState<Conversation | null>(null)
|
||||
// 对è¯<EFBFBD>相关状æ€? const [conversation, setConversation] = useState<Conversation | null>(null)
|
||||
const [messages, setMessages] = useState<Message[]>([])
|
||||
const [selectedModel, setSelectedModel] = useState<ModelType>('deepseek-v3')
|
||||
|
||||
// 消息发送状态
|
||||
const [sending, setSending] = useState(false)
|
||||
// 消æ<EFBFBD>¯å<EFBFBD>‘é€<EFBFBD>状æ€? const [sending, setSending] = useState(false)
|
||||
const [streamingContent, setStreamingContent] = useState('')
|
||||
|
||||
// 加载智能体配置
|
||||
useEffect(() => {
|
||||
// åŠ è½½æ™ºèƒ½ä½“é…<EFBFBD>ç½? useEffect(() => {
|
||||
const fetchAgent = async () => {
|
||||
if (!agentId) return
|
||||
|
||||
@@ -45,8 +41,8 @@ const AgentChatPage = () => {
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load agent:', err)
|
||||
setError('加载智能体配置失败')
|
||||
message.error('加载智能体配置失败')
|
||||
setError('åŠ è½½æ™ºèƒ½ä½“é…<EFBFBD>置失è´?)
|
||||
message.error('åŠ è½½æ™ºèƒ½ä½“é…<EFBFBD>置失è´?)
|
||||
} finally {
|
||||
setAgentLoading(false)
|
||||
}
|
||||
@@ -55,22 +51,19 @@ const AgentChatPage = () => {
|
||||
fetchAgent()
|
||||
}, [agentId])
|
||||
|
||||
// 加载知识库列表
|
||||
useEffect(() => {
|
||||
// åŠ è½½çŸ¥è¯†åº“åˆ—è¡? useEffect(() => {
|
||||
fetchKnowledgeBases()
|
||||
}, [])
|
||||
|
||||
// 创建或加载对话
|
||||
useEffect(() => {
|
||||
// åˆ›å»ºæˆ–åŠ è½½å¯¹è¯? useEffect(() => {
|
||||
const initConversation = async () => {
|
||||
if (!agent || !currentProject) return
|
||||
|
||||
try {
|
||||
// 创建新对话
|
||||
const response = await conversationApi.createConversation({
|
||||
// 创建新对� const response = await conversationApi.createConversation({
|
||||
projectId: currentProject.id,
|
||||
agentId: agent.id,
|
||||
title: `与${agent.name}的对话`,
|
||||
title: `ä¸?{agent.name}的对è¯<C3A8>`,
|
||||
})
|
||||
|
||||
setConversation(response.data.data || null)
|
||||
@@ -84,15 +77,13 @@ const AgentChatPage = () => {
|
||||
initConversation()
|
||||
}, [agent, currentProject])
|
||||
|
||||
// 发送消息(流式)
|
||||
const handleSendMessage = async (content: string, knowledgeBaseIds: string[]) => {
|
||||
// å<EFBFBD>‘é€<EFBFBD>消æ<EFBFBD>¯ï¼ˆæµ<EFBFBD>å¼<EFBFBD>ï¼? const handleSendMessage = async (content: string, knowledgeBaseIds: string[]) => {
|
||||
if (!conversation || sending) return
|
||||
|
||||
setSending(true)
|
||||
setStreamingContent('')
|
||||
|
||||
// 添加用户消息到列表
|
||||
const userMessage: Message = {
|
||||
// æ·»åŠ ç”¨æˆ·æ¶ˆæ<EFBFBD>¯åˆ°åˆ—è¡? const userMessage: Message = {
|
||||
id: `temp-${Date.now()}`,
|
||||
conversationId: conversation.id,
|
||||
role: 'user',
|
||||
@@ -118,8 +109,7 @@ const AgentChatPage = () => {
|
||||
},
|
||||
// onComplete
|
||||
() => {
|
||||
// 流式完成后,添加完整的助手消息
|
||||
const assistantMessage: Message = {
|
||||
// æµ<EFBFBD>å¼<EFBFBD>完æˆ<EFBFBD>å<EFBFBD>Žï¼Œæ·»åŠ å®Œæ•´çš„åŠ©æ‰‹æ¶ˆæ<EFBFBD>? const assistantMessage: Message = {
|
||||
id: `temp-assistant-${Date.now()}`,
|
||||
conversationId: conversation.id,
|
||||
role: 'assistant',
|
||||
@@ -141,7 +131,7 @@ const AgentChatPage = () => {
|
||||
)
|
||||
} catch (err) {
|
||||
console.error('Failed to send message:', err)
|
||||
message.error('发送消息失败')
|
||||
message.error('å<EFBFBD>‘é€<EFBFBD>消æ<EFBFBD>¯å¤±è´?)
|
||||
setStreamingContent('')
|
||||
setSending(false)
|
||||
}
|
||||
@@ -159,7 +149,7 @@ const AgentChatPage = () => {
|
||||
return (
|
||||
<Alert
|
||||
message="请先选择项目"
|
||||
description="请在侧边栏选择一个项目后再开始对话"
|
||||
description="请在侧边æ <C3A6>选择一个项目å<C2AE>Žå†<C3A5>开始对è¯?
|
||||
type="info"
|
||||
showIcon
|
||||
/>
|
||||
@@ -190,7 +180,7 @@ const AgentChatPage = () => {
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
||||
{/* 顶部工具栏 - 紧凑设计 */}
|
||||
{/* 顶部工具æ ?- 紧凑设计 */}
|
||||
<div style={{
|
||||
padding: '12px 24px',
|
||||
background: '#fff',
|
||||
@@ -212,7 +202,7 @@ const AgentChatPage = () => {
|
||||
</div>
|
||||
</Space>
|
||||
|
||||
{/* 模型选择器 */}
|
||||
{/* 模型选择�*/}
|
||||
<ModelSelector
|
||||
value={selectedModel}
|
||||
onChange={setSelectedModel}
|
||||
@@ -236,17 +226,15 @@ const AgentChatPage = () => {
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: 0, // 重要:确保可以滚动
|
||||
overflow: 'hidden',
|
||||
minHeight: 0, // é‡<C3A9>è¦<C3A8>:确ä¿<C3A4>å<EFBFBD>¯ä»¥æ»šåŠ? overflow: 'hidden',
|
||||
}}>
|
||||
{messages.length === 0 && !sending ? (
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#fafafa' }}>
|
||||
<div style={{ textAlign: 'center', color: '#999' }}>
|
||||
<RobotOutlined style={{ fontSize: 64, marginBottom: 16 }} />
|
||||
<div style={{ fontSize: 16 }}>开始对话,我将为您提供专业的研究建议</div>
|
||||
<div style={{ fontSize: 16 }}>开始对è¯<EFBFBD>,我将为您æ<EFBFBD><EFBFBD>ä¾›ä¸“ä¸šçš„ç ”ç©¶å»ºè®?/div>
|
||||
<div style={{ fontSize: 14, marginTop: 8 }}>
|
||||
您可以直接输入问题,或使用@知识库功能引用文献
|
||||
</div>
|
||||
您å<EFBFBD>¯ä»¥ç›´æŽ¥è¾“入问题,或使用@知识库功能引用文çŒ? </div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -263,7 +251,7 @@ const AgentChatPage = () => {
|
||||
onSend={handleSendMessage}
|
||||
loading={sending}
|
||||
knowledgeBases={knowledgeBases}
|
||||
placeholder={`向${agent.name}提问...(Shift+Enter换行,Enter发送)`}
|
||||
placeholder={`å<EFBFBD>?{agent.name}æ<><C3A6>é—®...(Shift+Enteræ<72>¢è¡Œï¼ŒEnterå<72>‘é€<C3A9>)`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
0
一键启动前后端.bat
Normal file
0
一键启动前后端.bat
Normal file
Reference in New Issue
Block a user