在构建RAG系统时,需要为Dify配置本地的重排序(Rerank)服务。目标:部署一个稳定、支持中文优化的rerank服务,供Dify调用。
🔄 技术路线演进
第一阶段:LocalAI Docker方案(尝试后放弃)
初始尝试
1 2 3 4 5 6 7 8 9 10
| docker run -p 8035:8080 -v ./models:/models --name localai quay.io/go-skynet/local-ai:latest-ffmpeg
docker run -d -p 8035:8080 \ -v $(pwd)/models:/models \ -v $(pwd)/config:/config \ --name localai \ localai/localai:latest-aio-cpu
|
遇到的问题
- 后端缺失错误:
backend not found: bert-embeddings
- 模型加载失败:
failed to load model with internal loader
- 自动下载依赖:下载语音模型耗时极长(显示15小时)
部分成功发现
jina-reranker-v1-base-en 模型可以正常工作
- 但该模型对中文优化不足
1 2 3 4 5 6 7 8 9 10
| curl -X POST http://localhost:8035/v1/rerank \ -H "Content-Type: application/json" \ -d '{ "model": "jina-reranker-v1-base-en", "query": "What is AI?", "documents": ["doc1", "doc2"], "top_n": 3 }'
|
第二阶段:Python原生服务(最终采用)
核心实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| import os os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from fastapi import FastAPI, HTTPException from pydantic import BaseModel from sentence_transformers import CrossEncoder import uvicorn import logging
logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__)
app = FastAPI()
MODEL_MAP = { "bge-chinese": "BAAI/bge-reranker-v2-m3", "bge-base": "BAAI/bge-reranker-base", "minilm": "cross-encoder/ms-marco-MiniLM-L-6-v2" }
models = {}
def load_model(model_name="bge-chinese"): """加载模型,处理网络问题""" if model_name in models: return models[model_name] logger.info(f"加载模型: {model_name}") try: model_path = MODEL_MAP[model_name] models[model_name] = CrossEncoder(model_path) logger.info(f"模型加载成功: {model_name}") return models[model_name] except Exception as e: logger.error(f"模型加载失败: {e}") raise HTTPException(status_code=500, detail=f"模型加载失败: {e}")
class RerankRequest(BaseModel): model: str = "bge-chinese" query: str documents: list[str] top_n: int = None
@app.post("/v1/rerank") async def rerank(request: RerankRequest): """重排序API端点""" try: model = load_model(request.model) pairs = [(request.query, doc) for doc in request.documents] scores = model.predict(pairs).tolist() results = [] for i, (doc, score) in enumerate(zip(request.documents, scores)): results.append({ "index": i, "document": {"text": doc}, "relevance_score": float(score) }) results.sort(key=lambda x: x["relevance_score"], reverse=True) if request.top_n: results = results[:request.top_n] return { "model": request.model, "results": results, "usage": {"total_tokens": len(request.query) + sum(len(d) for d in request.documents)} } except Exception as e: logger.error(f"重排序失败: {e}") raise HTTPException(status_code=500, detail=str(e))
@app.get("/readyz") async def health(): return {"status": "ready"}
@app.get("/v1/models") async def list_models(): return { "object": "list", "data": [ {"id": "bge-chinese", "object": "model"}, {"id": "bge-base", "object": "model"}, {"id": "minilm", "object": "model"} ] }
if __name__ == "__main__": logger.info("启动BGE中文重排序服务...") uvicorn.run(app, host="0.0.0.0", port=8036)
|
部署与运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| pip install fastapi uvicorn sentence-transformers pydantic
python rerank_svr_fixed.py
curl http://localhost:8036/readyz curl http://localhost:8036/v1/models
curl -X POST http://localhost:8036/v1/rerank \ -H "Content-Type: application/json" \ -d '{ "model": "bge-chinese", "query": "什么是人工智能?", "documents": [ "人工智能是计算机科学的分支", "机器学习通过数据训练模型", "Python是编程语言" ], "top_n": 2 }'
|
🔑 关键问题与解决方案
1. 网络问题:HuggingFace连接失败
问题现象:
1
| SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol')
|
解决方案:
1 2
| import os os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
|
2. Docker网络连通性问题
问题现象:Dify容器无法访问宿主机服务
1
| Connection refused (Errno 111)
|
解决方案:
- 在Dify中使用:
http://host.docker.internal:8036/v1/rerank
- 不是:
http://localhost:8036/v1/rerank(容器内指向自己)
- 不是:
http://127.0.0.1:8036/v1/rerank
3. 服务管理脚本
1 2 3 4 5 6 7 8 9 10
| #!/bin/bash
export HF_ENDPOINT=https://hf-mirror.com nohup python rerank_svr_fixed.py > rerank.log 2>&1 &
curl http://localhost:8036/readyz
tail -f rerank.log
|
📋 在Dify中的配置
- 进入Dify设置:工具 → 外部API工具
- 配置参数:
- API地址:
http://host.docker.internal:8036/v1/rerank
- 模型名称:
bge-chinese
- API密钥:留空
- 测试连接:使用简单查询测试
🎯 模型对比实际测试结果
测试案例:中文查询
实际使用建议
- 中文场景:使用
bge-chinese (BAAI/bge-reranker-v2-m3)
- 英文场景:使用
minilm (cross-encoder/ms-marco-MiniLM-L-6-v2)
- 混合场景:使用
bge-base (BAAI/bge-reranker-base)
⚠️ 注意事项
- 首次运行:需要下载模型文件,国内网络需配置镜像
- 内存占用:BGE模型约占用1-2GB内存
- 端口冲突:确保8036端口未被占用
- 依赖版本:建议使用较新的sentence-transformers版本
✅ 验证服务正常
服务正常运行时应有以下特征:
- 启动日志显示模型加载成功
/readyz 端点返回 {"status": "ready"}
/v1/rerank 能返回合理的相关性分数
- 在Dify中测试连接成功
📝 总结
经过实践验证,Python原生服务方案相比LocalAI Docker方案更稳定可靠,主要原因:
- 依赖简单:仅需Python环境,无需复杂Docker配置
- 调试方便:错误信息清晰,容易排查
- 网络可控:可灵活配置镜像源
- 资源占用少:无额外的容器开销
当前方案已稳定运行,为Dify提供中文优化的重排序能力。后续可根据实际使用情况考虑性能优化和监控增强。
创建时间:2025-12-17 08:28