Files
AIclinicalresearch/docs/05-每日进度/Day19-Dify客户端封装完成.md
AI Clinical Dev Team 239c7ea85e feat: Day 21-22 - knowledge base frontend completed, fix CORS and file upload issues
- Complete knowledge base list and detail pages
- Complete document upload component
- Fix CORS config (add PUT/DELETE method support)
- Fix file upload issues (disabled state and beforeUpload return value)
- Add detailed debug logs (cleaned up)
- Create Day 21-22 completion summary document
2025-10-11 15:40:12 +08:00

496 lines
11 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.
# Day 19 - Dify客户端封装完成总结
**日期**: 2025-10-11
**状态**: ✅ 已完成
---
## 🎯 本次任务目标
封装Dify知识库API实现完整的知识库管理功能。
---
## ✅ 完成的工作
### 1. 创建类型定义 (`backend/src/clients/types.ts`) ✅
**定义的类型**
```typescript
// 知识库相关
- Dataset // 知识库信息
- CreateDatasetRequest // 创建知识库请求
- CreateDatasetResponse // 创建知识库响应
- DatasetListResponse // 知识库列表响应
// 文档相关
- Document // 文档信息
- DocumentListResponse // 文档列表响应
- CreateDocumentByFileRequest // 创建文档请求
- CreateDocumentResponse // 创建文档响应
// 检索相关
- RetrievalRequest // 检索请求
- RetrievalRecord // 检索结果项
- RetrievalResponse // 检索响应
// 错误处理
- DifyErrorResponse // 错误响应
- DifyError // 自定义错误类
```
**特点**
- 完整的TypeScript类型定义
- 包含所有必需和可选字段
- 支持文档处理状态追踪
---
### 2. 实现DifyClient核心类 (`backend/src/clients/DifyClient.ts`) ✅
#### 2.1 基础功能
**构造函数**
```typescript
constructor(apiKey?: string, apiUrl?: string)
- API Key和URL
-
-
```
**错误处理**
- axios拦截器统一处理错误
- 自定义DifyError类
- 包含错误代码和HTTP状态码
---
#### 2.2 知识库管理API
**已实现的方法**
1. **createDataset** - 创建知识库
```typescript
async createDataset(params: CreateDatasetRequest): Promise<CreateDatasetResponse>
```
- 支持设置索引技术high_quality/economy
- 支持配置检索模型
- 自动设置默认参数
2. **getDatasets** - 获取知识库列表
```typescript
async getDatasets(page: number, limit: number): Promise<DatasetListResponse>
```
- 支持分页
- 返回总数、是否有更多等信息
3. **getDataset** - 获取知识库详情
```typescript
async getDataset(datasetId: string): Promise<Dataset>
```
- 获取单个知识库的完整信息
- 包括文档数量、字符数等统计
4. **deleteDataset** - 删除知识库
```typescript
async deleteDataset(datasetId: string): Promise<void>
```
- 永久删除知识库及其所有文档
---
#### 2.3 文档管理API
**已实现的方法**
1. **uploadDocumentDirectly** - 直接上传文档
```typescript
async uploadDocumentDirectly(
datasetId: string,
file: Buffer,
filename: string
): Promise<CreateDocumentResponse>
```
- 使用FormData上传文件
- 自动配置处理规则
- 支持自定义分词策略
2. **getDocuments** - 获取文档列表
```typescript
async getDocuments(
datasetId: string,
page: number,
limit: number
): Promise<DocumentListResponse>
```
- 支持分页查询
- 返回文档状态、Token数等信息
3. **getDocument** - 获取文档详情
```typescript
async getDocument(datasetId: string, documentId: string): Promise<Document>
```
- 查询单个文档的完整信息
- 包括索引状态、字符数、点击次数等
4. **deleteDocument** - 删除文档
```typescript
async deleteDocument(datasetId: string, documentId: string): Promise<void>
```
- 从知识库中删除指定文档
5. **updateDocument** - 更新文档(重新索引)
```typescript
async updateDocument(datasetId: string, documentId: string): Promise<void>
```
- 触发文档重新处理和索引
---
#### 2.4 知识库检索API
**已实现的方法**
1. **retrieveKnowledge** - 检索知识库
```typescript
async retrieveKnowledge(
datasetId: string,
query: string,
params?: Partial<RetrievalRequest>
): Promise<RetrievalResponse>
```
- 支持语义搜索、全文搜索、混合搜索
- 支持重排序reranking
- 支持设置top_k和相似度阈值
- 返回相关文档片段和相似度得分
---
#### 2.5 辅助方法
**已实现的方法**
1. **waitForDocumentProcessing** - 轮询等待文档处理完成
```typescript
async waitForDocumentProcessing(
datasetId: string,
documentId: string,
maxAttempts: number,
interval: number
): Promise<Document>
```
- 自动轮询检查处理状态
- 支持超时控制
- 处理失败时抛出错误
2. **uploadAndProcessDocument** - 一键上传并等待处理
```typescript
async uploadAndProcessDocument(
datasetId: string,
file: Buffer,
filename: string
): Promise<Document>
```
- 上传文档 + 等待处理完成
- 返回完全处理好的文档
- 简化了常见使用场景
---
### 3. 测试脚本 (`backend/src/scripts/test-dify-client.ts`) ✅
**测试内容**
| 测试项 | 功能 | 状态 |
|--------|------|------|
| 测试1 | 创建知识库 | ✅ 通过 |
| 测试2 | 获取知识库列表 | ✅ 通过 |
| 测试3 | 获取知识库详情 | ✅ 通过 |
| 测试4 | 上传文档 | ✅ 通过 |
| 测试5 | 获取文档列表 | ✅ 通过 |
| 测试6 | 知识库检索 | ✅ 通过 |
| 测试7 | 删除文档 | ✅ 通过 |
| 测试8 | 删除知识库 | ✅ 通过 |
**测试结果**
```
✅ 所有测试通过!
测试耗时约15秒
```
**测试数据**
- 创建知识库ID: `a2e844c8-6296-42eb-8f1e-18c6c919420b`
- 上传文档: `test-document.txt` (247 tokens, 148字符)
- 检索结果: 找到1条相似度0.4420
---
## 🔧 技术亮点
### 1. 完善的错误处理
```typescript
// 自定义错误类
export class DifyError extends Error {
code: string;
status: number;
}
// axios拦截器自动转换错误
this.client.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
if (error.response?.data) {
throw new DifyError(error.response.data);
}
throw error;
}
);
```
### 2. 智能轮询机制
```typescript
// 等待文档处理完成,自动轮询
async waitForDocumentProcessing(
datasetId: string,
documentId: string,
maxAttempts: number = 30,
interval: number = 2000
): Promise<Document>
```
- 最多轮询30次
- 每次间隔2秒
- 自动检测完成或失败状态
### 3. 单例模式
```typescript
// 导出全局单例,方便使用
export const difyClient = new DifyClient();
```
### 4. FormData文件上传
```typescript
// 正确处理文件上传
const formData = new FormData();
formData.append('file', file, filename);
formData.append('data', JSON.stringify(params));
```
---
## 📦 依赖安装
**新增依赖**
```json
{
"form-data": "^4.0.0",
"@types/form-data": "^2.5.0"
}
```
**用途**
- `form-data`: Node.js环境的FormData实现
- `@types/form-data`: TypeScript类型定义
---
## 🐛 遇到的问题与解决
### 问题1API Key认证失败401
**症状**
```
Access token is invalid
HTTP状态码: 401
```
**原因**
- 使用了应用API Key`app-xxx`
- 知识库管理需要服务API Key`dataset-xxx`
**解决**
- 在Dify控制台创建服务API密钥
- 更新`.env`配置:`DIFY_API_KEY=dataset-mfvdiKvQ2l3NvxWm7RoYMN3c`
---
### 问题2文本嵌入模型未配置400
**症状**
```
Default model not found for text-embedding
HTTP状态码: 400
```
**原因**
- Dify需要配置文本嵌入模型才能创建知识库
**解决**
- 在Dify控制台配置默认的embedding模型
- 用户已成功配置
---
### 问题3文件上传API路径错误
**原因**
- 最初使用了`/files/upload`分两步上传
- Dify实际支持直接上传到知识库
**解决**
- 改为直接调用`/datasets/{id}/document/create_by_file`
- 使用FormData直接上传文件和参数
- 简化了流程只需一次API调用
---
## 📊 API完整性检查
### 知识库管理 API
- [x] 创建知识库
- [x] 获取知识库列表
- [x] 获取知识库详情
- [x] 删除知识库
- [ ] 更新知识库暂未实现Dify API不支持
### 文档管理 API
- [x] 上传文档
- [x] 获取文档列表
- [x] 获取文档详情
- [x] 删除文档
- [x] 更新文档(重新索引)
### 知识库检索 API
- [x] 语义检索
- [x] 支持top_k配置
- [x] 支持相似度阈值
- [x] 返回相似度得分和内容
### 辅助功能
- [x] 轮询等待处理完成
- [x] 一键上传并处理
- [x] 统一错误处理
- [x] 单例模式导出
**完成度**: 100%
---
## 🚀 下一步工作计划
### Day 20-22知识库管理功能开发
**后端API**
1. 创建知识库管理Service层
2. 创建知识库管理Controller
3. 定义RESTful API路由
4. 实现知识库CRUD功能
5. 实现文档上传和管理功能
**数据库设计**
```sql
-- 知识库表
CREATE TABLE knowledge_bases (
id VARCHAR PRIMARY KEY,
name VARCHAR NOT NULL,
description TEXT,
user_id VARCHAR NOT NULL,
dify_dataset_id VARCHAR NOT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- 文档表
CREATE TABLE documents (
id VARCHAR PRIMARY KEY,
knowledge_base_id VARCHAR NOT NULL,
name VARCHAR NOT NULL,
dify_document_id VARCHAR NOT NULL,
file_url VARCHAR,
status VARCHAR,
tokens INTEGER,
word_count INTEGER,
created_at TIMESTAMP
);
```
**API设计**
```
POST /api/v1/knowledge-bases 创建知识库
GET /api/v1/knowledge-bases 获取知识库列表
GET /api/v1/knowledge-bases/:id 获取知识库详情
DELETE /api/v1/knowledge-bases/:id 删除知识库
POST /api/v1/knowledge-bases/:id/documents 上传文档
GET /api/v1/knowledge-bases/:id/documents 获取文档列表
DELETE /api/v1/documents/:id 删除文档
```
**前端开发**
1. 更新KnowledgePage布局
2. 实现知识库列表组件
3. 实现创建知识库对话框
4. 实现文档上传组件
5. 实现文档列表展示
6. 添加loading状态和错误处理
---
## 📝 相关文档
- **DifyClient源码**`backend/src/clients/DifyClient.ts`
- **类型定义**`backend/src/clients/types.ts`
- **测试脚本**`backend/src/scripts/test-dify-client.ts`
- **Dify官方文档**https://docs.dify.ai
---
## 🎓 技术收获
### 1. Dify API使用经验
- 理解了服务API Key和应用API Key的区别
- 掌握了知识库的创建和管理流程
- 学习了文档上传和索引的机制
- 了解了RAG检索的实现方式
### 2. TypeScript类型设计
- 完整定义了复杂的API类型
- 使用Partial类型支持可选参数
- 自定义错误类增强错误处理
### 3. Node.js文件上传
- 使用form-data处理文件上传
- 正确设置Content-Type和Authorization
- 处理Buffer类型的文件数据
### 4. 异步流程控制
- 实现轮询机制等待异步任务完成
- 使用Promise和async/await优雅处理异步
- 设置超时和重试机制
---
## 📈 项目进度
**里程碑1MVP**: **87%** 完成
```
✅ Day 4-5: 环境搭建
✅ Day 6: 前端基础架构
✅ Day 7: 前端完整布局
✅ Day 8-9: 项目管理API
✅ Day 10-11: 智能体配置系统
✅ Day 12-13: LLM适配器与对话系统
✅ Day 14-17: 前端对话界面
✅ Day 18: Dify平台部署
✅ Day 19: Dify客户端封装 ← 今天完成
🔄 Day 20-22: 知识库管理功能 ← 即将开始
⏳ Day 23-24: @知识库集成与RAG验证
```
---
**总结**: Day 19的Dify客户端封装工作圆满完成实现了完整的知识库管理API所有功能测试通过。为接下来的知识库管理功能开发提供了坚实的基础💪