- 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
11 KiB
11 KiB
Day 19 - Dify客户端封装完成总结
日期: 2025-10-11
状态: ✅ 已完成
🎯 本次任务目标
封装Dify知识库API,实现完整的知识库管理功能。
✅ 完成的工作
1. 创建类型定义 (backend/src/clients/types.ts) ✅
定义的类型:
// 知识库相关
- Dataset // 知识库信息
- CreateDatasetRequest // 创建知识库请求
- CreateDatasetResponse // 创建知识库响应
- DatasetListResponse // 知识库列表响应
// 文档相关
- Document // 文档信息
- DocumentListResponse // 文档列表响应
- CreateDocumentByFileRequest // 创建文档请求
- CreateDocumentResponse // 创建文档响应
// 检索相关
- RetrievalRequest // 检索请求
- RetrievalRecord // 检索结果项
- RetrievalResponse // 检索响应
// 错误处理
- DifyErrorResponse // 错误响应
- DifyError // 自定义错误类
特点:
- 完整的TypeScript类型定义
- 包含所有必需和可选字段
- 支持文档处理状态追踪
2. 实现DifyClient核心类 (backend/src/clients/DifyClient.ts) ✅
2.1 基础功能
构造函数:
constructor(apiKey?: string, apiUrl?: string)
- 支持自定义API Key和URL
- 从环境变量读取配置
- 自动配置请求头和超时
错误处理:
- axios拦截器统一处理错误
- 自定义DifyError类
- 包含错误代码和HTTP状态码
2.2 知识库管理API
已实现的方法:
-
createDataset - 创建知识库
async createDataset(params: CreateDatasetRequest): Promise<CreateDatasetResponse>- 支持设置索引技术(high_quality/economy)
- 支持配置检索模型
- 自动设置默认参数
-
getDatasets - 获取知识库列表
async getDatasets(page: number, limit: number): Promise<DatasetListResponse>- 支持分页
- 返回总数、是否有更多等信息
-
getDataset - 获取知识库详情
async getDataset(datasetId: string): Promise<Dataset>- 获取单个知识库的完整信息
- 包括文档数量、字符数等统计
-
deleteDataset - 删除知识库
async deleteDataset(datasetId: string): Promise<void>- 永久删除知识库及其所有文档
2.3 文档管理API
已实现的方法:
-
uploadDocumentDirectly - 直接上传文档
async uploadDocumentDirectly( datasetId: string, file: Buffer, filename: string ): Promise<CreateDocumentResponse>- 使用FormData上传文件
- 自动配置处理规则
- 支持自定义分词策略
-
getDocuments - 获取文档列表
async getDocuments( datasetId: string, page: number, limit: number ): Promise<DocumentListResponse>- 支持分页查询
- 返回文档状态、Token数等信息
-
getDocument - 获取文档详情
async getDocument(datasetId: string, documentId: string): Promise<Document>- 查询单个文档的完整信息
- 包括索引状态、字符数、点击次数等
-
deleteDocument - 删除文档
async deleteDocument(datasetId: string, documentId: string): Promise<void>- 从知识库中删除指定文档
-
updateDocument - 更新文档(重新索引)
async updateDocument(datasetId: string, documentId: string): Promise<void>- 触发文档重新处理和索引
2.4 知识库检索API
已实现的方法:
- retrieveKnowledge - 检索知识库
async retrieveKnowledge( datasetId: string, query: string, params?: Partial<RetrievalRequest> ): Promise<RetrievalResponse>- 支持语义搜索、全文搜索、混合搜索
- 支持重排序(reranking)
- 支持设置top_k和相似度阈值
- 返回相关文档片段和相似度得分
2.5 辅助方法
已实现的方法:
-
waitForDocumentProcessing - 轮询等待文档处理完成
async waitForDocumentProcessing( datasetId: string, documentId: string, maxAttempts: number, interval: number ): Promise<Document>- 自动轮询检查处理状态
- 支持超时控制
- 处理失败时抛出错误
-
uploadAndProcessDocument - 一键上传并等待处理
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. 完善的错误处理
// 自定义错误类
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. 智能轮询机制
// 等待文档处理完成,自动轮询
async waitForDocumentProcessing(
datasetId: string,
documentId: string,
maxAttempts: number = 30,
interval: number = 2000
): Promise<Document>
- 最多轮询30次
- 每次间隔2秒
- 自动检测完成或失败状态
3. 单例模式
// 导出全局单例,方便使用
export const difyClient = new DifyClient();
4. FormData文件上传
// 正确处理文件上传
const formData = new FormData();
formData.append('file', file, filename);
formData.append('data', JSON.stringify(params));
📦 依赖安装
新增依赖:
{
"form-data": "^4.0.0",
"@types/form-data": "^2.5.0"
}
用途:
form-data: Node.js环境的FormData实现@types/form-data: TypeScript类型定义
🐛 遇到的问题与解决
问题1:API 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
- 创建知识库
- 获取知识库列表
- 获取知识库详情
- 删除知识库
- 更新知识库(暂未实现,Dify API不支持)
文档管理 API
- 上传文档
- 获取文档列表
- 获取文档详情
- 删除文档
- 更新文档(重新索引)
知识库检索 API
- 语义检索
- 支持top_k配置
- 支持相似度阈值
- 返回相似度得分和内容
辅助功能
- 轮询等待处理完成
- 一键上传并处理
- 统一错误处理
- 单例模式导出
完成度: 100%
🚀 下一步工作计划
Day 20-22:知识库管理功能开发
后端API:
- 创建知识库管理Service层
- 创建知识库管理Controller
- 定义RESTful API路由
- 实现知识库CRUD功能
- 实现文档上传和管理功能
数据库设计:
-- 知识库表
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 删除文档
前端开发:
- 更新KnowledgePage布局
- 实现知识库列表组件
- 实现创建知识库对话框
- 实现文档上传组件
- 实现文档列表展示
- 添加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优雅处理异步
- 设置超时和重试机制
📈 项目进度
里程碑1(MVP): 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,所有功能测试通过。为接下来的知识库管理功能开发提供了坚实的基础!💪