Dify 外部知识库集成 Milvus 实战指南
版本信息
- Dify: 1.10.0
- Milvus: 2.6.0-rc.1
🎯 集成概述
本文详细介绍如何将 Dify 与 Milvus 向量数据库集成,通过 Spring Boot 代理服务实现外部知识库功能。
🔄 集成架构
Dify → Spring Boot API Proxy → Milvus Vector Database
🔧 API 代理服务开发
参考文档
2.1 Controller 层实现
⚠️ 重要提示 :
@RequestBody(required = false)是必须的,否则 Dify 创建外部知识库时会出现 500 错误且难以排查。
java
@RestController
@RequestMapping("/api")
public class MilvusController {
private static final Logger logger = LoggerFactory.getLogger(MilvusController.class);
// 生产环境请使用安全的 API 密钥管理方式
private static final String VALID_API_KEY = "your-valid-api-key";
@Autowired
private MilvusService milvusService;
@PostMapping("/retrieval")
public ResponseEntity<?> retrieval(
HttpServletRequest request,
@RequestBody(required = false) RetrievalRequest retrievalRequest
) {
try {
// 在 Dify 中创建外部知识库时,request body 为空
if (retrievalRequest == null) {
return ResponseEntity.ok(new RetrievalResponse());
}
// 执行 Milvus 搜索
RetrievalResponse response = milvusService.search(retrievalRequest);
return ResponseEntity.ok(response);
} catch (Exception e) {
logger.error("处理检索请求时发生错误", e);
ErrorResponse errorResponse = new ErrorResponse(500, "内部服务器错误: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
}
}
}
2.2 Service 层实现
核心功能:
- 🧠 对查询文本进行 Embedding 编码
- 🔍 在 Milvus 中执行相似度搜索
⚠️ 关键注意事项: 返回的 JSON 中 metadata 不能为空,否则会出现召回测试有数据但工作流中无数据的问题!
java
@Service
public class MilvusService {
@Value("${milvus.host}")
private String milvusHost;
@Value("${milvus.port}")
private int milvusPort;
public RetrievalResponse search(RetrievalRequest request) {
MilvusClientV2 client = null;
try {
// 建立 Milvus 连接
client = MilvusConnectionUtil.connectStatic(milvusConfig);
String collectionName = request.getKnowledge_id().trim();
// 加载集合到内存
client.loadCollection(LoadCollectionReq.builder()
.collectionName(collectionName)
.build());
// 获取查询文本
String query = request.getQuery();
logger.debug("查询内容: {}", query);
// 生成 Embedding 向量
List<Float> embeddings = getEmbeddingByQwen(query);
logger.debug("Embedding 向量长度: {}", embeddings.size());
// 构建搜索参数
FloatVec floatVec = new FloatVec(embeddings);
List<BaseVector> baseVectors = Collections.singletonList(floatVec);
// 执行向量搜索
SearchResp searchResp = client.search(SearchReq.builder()
.collectionName(collectionName)
.data(baseVectors)
.topK(request.getRetrieval_setting().getTop_k())
.outputFields(Collections.singletonList("*"))
.build()
);
logger.debug("搜索结果: {}", searchResp.toString());
// 处理搜索结果
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
List<RetrievalResponse.Record> records = new ArrayList<>();
for (List<SearchResp.SearchResult> results : searchResults) {
for (SearchResp.SearchResult result : results) {
RetrievalResponse.Record record = new RetrievalResponse.Record();
// 解析元数据
JsonObject metaData = (JsonObject) result.getEntity().get("metadata");
// 设置记录内容
record.setContent(metaData.get("text").getAsString());
record.setScore(result.getScore());
record.setTitle(metaData.get("title").getAsString());
// 构建元数据映射(确保不为空)
Map<String, Object> recordMetaData = new HashMap<>();
recordMetaData.put("path", metaData.get("url").getAsString());
recordMetaData.put("description", metaData.get("description").getAsString());
record.setMetadata(recordMetaData);
records.add(record);
}
}
RetrievalResponse response = new RetrievalResponse();
response.setRecords(records);
return response;
} catch (Exception e) {
logger.error("Milvus 搜索失败", e);
throw new RuntimeException("搜索失败: " + e.getMessage(), e);
} finally {
if (client != null) {
try {
client.close();
} catch (Exception e) {
logger.warn("关闭 Milvus 客户端连接时出错", e);
}
}
}
}
}
🚀 部署使用
3.1 创建外部 API 连接
在 Dify 管理界面中:
知识库 → 外部知识库API → 添加新连接
| 参数 | 值 |
|---|---|
| Name | test |
| API Endpoint | http://your-server-ip/api/retrieval |
| API Key | ••••••••••••• |
3.2 创建外部知识库
在 Dify 中创建外部知识库时,需要指定外部知识库 ID,该 ID 应与 Milvus 中的 Collection Name 保持一致。
💡 最佳实践
✅ 成功要点
- 确保 API 接口支持空 Body 请求
- metadata 字段不能为空
- 正确配置 Milvus 连接参数
- 合理设置 Top-K 搜索参数
🔧 常见问题排查
- 500 错误 : 检查
@RequestBody(required = false) - 工作流无数据: 检查 metadata 是否正确填充
- 连接失败: 验证 Milvus 服务状态和网络连通性
📝 总结
通过本文的集成方案,您可以成功将 Dify 与 Milvus 向量数据库连接,实现高效的外部知识库功能。这种架构既保证了系统的灵活性,又充分利用了 Milvus 的高性能向量检索能力。
💬 如有问题或建议,欢迎在评论区交流!