A comprehensive AI customer service system built with LangGraph, RAG (Retrieval-Augmented Generation), Milvus vector database, and Elasticsearch.
User Question
↓
LangGraph Agent (Routing)
↓
Question Classification
↓
Knowledge Base Needed?
↓
LlamaIndex RAG
↓
Milvus (Vector Search) + Elasticsearch (Keyword Search)
↓
LLM Summary (ZhipuAI GLM-4)
↓
Return Answer
- 智能问题路由: 自动将问题分类为知识库查询或普通聊天
- 混合检索: 结合向量搜索 (Milvus) 和关键词搜索 (Elasticsearch) 获得更好的结果
- 多格式支持: 支持 PDF、TXT 和 Markdown 文档
- 流式响应: 实时流式聊天回复
- FastAPI: 现代异步 Web 框架,自动生成 API 文档
- 智谱 AI 集成: 使用 GLM-4 提供智能回复
本系统采用混合检索策略,结合两种互补的搜索引擎来提供最佳的检索结果。
┌─────────────────────────────────────────────────────────────────┐
│ HybridRetriever (混合检索) │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ Milvus (向量搜索) │ │ Elasticsearch (BM25) │ │
│ │ │ │ │ │
│ │ • 语义相似度匹配 │ + │ • 关键词精确匹配 │ │
│ │ • 理解查询意图 │ │ • 专业术语查找 │ │
│ │ • 权重: 60% │ │ • 权重: 40% │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ ↓ ↓ │
│ └──────────┬───────────────────┘ │
│ ↓ │
│ Score Fusion (分数融合 + 去重) │
│ ↓ │
│ 返回 Top-K 最相关结果 │
└─────────────────────────────────────────────────────────────────┘
| 维度 | Milvus (向量搜索) | Elasticsearch (关键词搜索) |
|---|---|---|
| 匹配方式 | 语义相似度 | 关键词精确匹配 |
| 擅长场景 | "怎么退货?" → 找到退货政策 | "错误代码 E5001" → 精确找到该错误 |
| 算法 | Embedding 向量 + 余弦相似度 | BM25/TF-IDF |
用户问:"退款要多久?"
| 检索方式 | 可能返回的结果 |
|---|---|
| Milvus 单独 | "退款流程"、"退款政策"、"退货说明"(语义相关) |
| ES 单独 | 包含"退款"、"多久"关键词的文档(可能漏掉"处理时效"等表述) |
| 混合检索 | 结合两者:既找到语义相关的退款政策,又匹配到具体时效说明 |
混合检索器位于 app/rag/retrievers.py:
class HybridRetriever:
def __init__(self, vector_weight=0.6, keyword_weight=0.4):
# 60% 向量搜索权重,40% 关键词搜索权重
def _retrieve(self, query):
# 1. 同时从两个系统检索
milvus_results = self._milvus_retriever.retrieve(query)
es_results = self._es_retriever.retrieve(query)
# 2. 分数归一化并融合
# 3. 去重(同一个文档只保留一次)
# 4. 返回 Top-K 结果这种混合策略确保:
- 模糊问题通过语义理解处理 (Milvus)
- 精确术语(产品名、错误代码)精确匹配 (Elasticsearch)
- 结果排序综合考虑两种相似度分数
agent-demo/
├── app/
│ ├── api/chat.py # FastAPI endpoints
│ ├── core/
│ │ ├── config.py # Configuration management
│ │ └── llm.py # ZhipuAI client wrapper
│ ├── graph/
│ │ ├── agent.py # LangGraph agent definition
│ │ ├── nodes.py # Agent node implementations
│ │ └── state.py # Agent state definition
│ ├── rag/
│ │ ├── index.py # Index management
│ │ ├── loaders.py # Document loaders
│ │ └── retrievers.py # Hybrid retriever
│ ├── models/schemas.py # Pydantic models
│ └── main.py # FastAPI application entry
├── data/documents/ # Knowledge base documents
├── docker-compose.yml # Infrastructure services
├── requirements.txt # Python dependencies
└── pyproject.toml # Project configuration
- Python 3.10+
- Docker & Docker Compose
- ZhipuAI API Key
# Copy environment variables
cp .env.example .env
# Edit .env and set your ZHIPUAI_API_KEYdocker-compose up -dThis starts:
- Milvus (vector database) on port 19530
- Elasticsearch on port 9200
pip install -r requirements.txtpython -m app.mainThe API will be available at http://localhost:8000
API documentation: http://localhost:8000/docs
curl -X POST "http://localhost:8000/api/chat" \
-H "Content-Type: application/json" \
-d '{"message": "如何使用这个产品?"}'Response:
{
"answer": "根据产品文档,您可以通过以下步骤使用...",
"sources": [
{"source": "user-guide.pdf", "page": "5", "title": "User Guide"}
],
"question_type": "knowledge",
"session_id": null
}curl -X POST "http://localhost:8000/api/documents/index" \
-H "Content-Type: application/json" \
-d '{"path": "data/documents", "show_progress": true}'curl -X POST "http://localhost:8000/api/documents/upload" \
-F "file=@document.pdf"curl "http://localhost:8000/api/documents/stats"Edit .env to configure:
# Application
APP_NAME=agent-demo
DEBUG=true
HOST=0.0.0.0
PORT=8000
# ZhipuAI
ZHIPUAI_API_KEY=your_key_here
ZHIPUAI_MODEL=glm-4
ZHIPUAI_TEMPERATURE=0.7
# Milvus
MILVUS_HOST=localhost
MILVUS_PORT=19530
MILVUS_DIMENSION=768
# Elasticsearch
ES_HOST=localhost
ES_PORT=9200
# RAG
EMBEDDING_MODEL=sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
CHUNK_SIZE=512
TOP_K=5pytest tests/black app/
ruff check app/MIT License