内容
# 企业知识助手
一款异步、基于 LangGraph 的企业级助手,它结合了您自己的文档的 **RAG**、**MCP 工具**(工单、员工查询、公司政策、内部知识)、**自我 RAG / CRAG 验证**,以及带有实时工具可见性和流式、打字式回答的 **Streamlit 聊天界面**。
```
问题 → 分类(LLM)→ ┬─ 直接路径 → 普通知识回答
├─ 检索路径 → pgvector RAG(+ CRAG 备用网络搜索)
├─ 工具路径 → MCP 工具(工单 / 政策 / 员工 / 知识)
└─ 组合路径 → RAG + MCP 工具,并行运行,合并
↓
自我 RAG 验证(重试循环,有限)
↓
答案 + 来源 + 持久化线程历史
```
## 功能
- **异步 LangGraph 工作流** — 每个节点都是一个协程;单个图运行永远不会阻塞事件循环,因此 FastAPI 服务器可以在无需线程黑客的情况下提供并发聊天服务。
- **查询分类** — LLM 决定每个问题是否需要文档检索、MCP 工具、两者或两者都不需要(`graph/nodes.py:classify_query`)。
- **CRAG 风格检索** — 检索的文档会根据相关性进行评分;如果没有相关文档,则会重写查询并进行网络搜索,带有有限重试循环(`app.config.max_verification_retries`)。
- **自我 RAG 验证** — 最终答案会在发送之前根据其上下文进行检查;未经验证的答案会触发重写/重试。
- **MCP 工具层** (通过 [FastMCP](https://github.com/jlowin/fastmcp)):
- `create_ticket` — 提起工单(标题、描述、优先级、指派人)
- `list_tickets` — 无过滤工单列表
- `query_tickets` — 过滤工单搜索(指派人、创建人、状态、优先级、日期范围 - 例如 "今天由我指派的工单")
- `get_employee_details` — 员工查询
- `fetch_company_policy` — 请假 / 远程工作 / 离职期政策查询
- `search_internal_knowledge` — 入职 / 安全 / VPN 知识库
- `web_search` — DuckDuckGo 备用搜索
- **基于词干的工具路由器** (`mcp_server/client.py`) — 一个轻量级、非 LLM 路由器,分离 CREATE 与 LIST 与 QUERY 工单意图(因此 "显示打开的工单" 不会意外创建工单),并直接从查询文本中解析 "今天" / "昨天"、"指派给我" 与 "由我指派"、状态和优先级。
- **工具使用透明度** — 每个 MCP 调用返回 `{tool_used, arguments, result}`,通过 API 响应和 Streamlit 界面作为实时 "🔧 运行 `tool_name(args)`" 徽章显示。
- **流式、打字式回答** — `POST /chat/stream` (SSE)流式传输路由信息、工具调用(如果有)和答案 token-by-token 通过 `llm.astream()`。
- **持久化聊天线程** — 会话存储在 Postgres 中,可以从侧边栏浏览和恢复。
- **PDF 导入** — 上传 PDF,PDF 会被分割、嵌入并存储在 pgvector 中以供检索。
## 技术栈
| 层 | 技术 |
|--------------|------|
| 协调层 | [LangGraph](https://github.com/langchain-ai/langgraph) (异步) |
| LLM | [Groq](https://groq.com/) 通过 `langchain-groq` |
| 嵌入层 | `sentence-transformers/all-MiniLM-L6-v2` 通过 `langchain-huggingface` |
| 向量存储 | PostgreSQL + [pgvector](https://github.com/pgvector/pgvector) |
| 聊天/线程数据库 | PostgreSQL 通过 SQLAlchemy(异步,`asyncpg`) |
| MCP 工具 | [FastMCP](https://github.com/jlowin/fastmcp) + SQLite (`aiosqlite`) |
| API | FastAPI |
| 前端 | Streamlit |
| 网络搜索 | `duckduckgo-search` |
## 项目结构
```
app/
main.py FastAPI 应用 + 路由器注册
config.py 集中式设置(环境变量驱动)
logging_config.py
api/
routes_chat.py POST /chat, POST /chat/stream (SSE)
routes_ingest.py POST /ingest (PDF 上传)
routes_threads.py 线程历史端点
schemas.py Pydantic 请求/响应模型
graph/
state.py 共享 LangGraph 状态(TypedDict)
nodes.py 所有节点实现(分类、检索、评分、生成、工具路由、验证、持久化)
routing.py 纯条件边决策函数
workflow.py 构建 + 编译 LangGraph 图
mcp_server/
server.py FastMCP 服务器:工具定义 + SQLite 架构
client.py 基于词干的路由器 + 工具调用包装器
core/
llm.py 缓存 ChatGroq 客户端
embeddings.py 缓存 HuggingFace 嵌入客户端
text_processing.py 关键词路由的 Porter-stemmer 助手
db/
models.py SQLAlchemy 模型(文档、线程、消息)
session.py 异步引擎/会话工厂
vector_repository.py pgvector 相似性搜索 + 存储
thread_repository.py 线程/消息 CRUD
ingestion/
pdf_ingestor.py PDF → 分割 → 嵌入 → pgvector
web_search.py 异步 DuckDuckGo 包装器
frontend/
streamlit_app.py 聊天界面:历史侧边栏、PDF 上传、流式回答,带有实时工具徽章
```
## 设置
### 先决条件
- Python 3.12+
- 已启用 [pgvector](https://github.com/pgvector/pgvector) 扩展的 PostgreSQL
- [Groq API 密钥](https://console.groq.com/)
### 1. 安装依赖
```bash
pip install -r requirements.txt
# 或,如果使用 uv/pyproject per-package:
pip install -e .
```
> `mcp_server/` FastMCP 层仅需要 `fastmcp` 和 `aiosqlite`;应用的其他依赖项(`langgraph`、`langchain-groq`、`langchain-huggingface`、`sqlalchemy[asyncio]`、`asyncpg`、`pgvector`、`fastapi`、`uvicorn`、`streamlit`、`httpx`、`duckduckgo-search`、`nltk`)用于 `app/`、`graph/`、`core/`、`db/`、`ingestion/`。
### 2. 配置环境
在仓库根目录下创建 `.env` 文件:
```env
# LLM
GROQ_API_KEY=your_groq_api_key
GROQ_MODEL=llama-3.3-70b-versatile
# 嵌入层
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
EMBEDDING_DIM=384
# Postgres(必须启用 pgvector 扩展)
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/ai_db
# 应用
APP_HOST=0.0.0.0
APP_PORT=8000
LOG_LEVEL=INFO
MAX_VERIFICATION_RETRIES=2
# MCP(SQLite,与 Postgres 知识库分开)
MCP_SQLITE_PATH=enterprise_mcp.db
MCP_DEFAULT_USER_ID=E001
# Streamlit
BACKEND_URL=http://localhost:8000
```
### 3. 在 Postgres 数据库上启用 pgvector
```sql
CREATE EXTENSION IF NOT EXISTS vector;
```
表(`documents`、`threads`、`messages`)由 SQLAlchemy 在首次使用时自动创建;MCP `tickets`/`employees` 表(SQLite)在首次工具调用时自动创建和迁移。
### 4. 运行后端
```bash
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```
### 5. 运行前端
```bash
streamlit run frontend/streamlit_app.py
```
然后打开 Streamlit 打印的 URL(通常为 `http://localhost:8501`)。
## API 参考
| 方法 | 路径 | 描述 |
|--------|-----------------------------------|--------------|
| GET | `/health` | 健康检查 |
| POST | `/api/v1/chat` | 提问;返回完整验证的答案、来源和运行的工具 |
| POST | `/api/v1/chat/stream` | 与上述相同,但作为 SSE 流式传输(`routing` → `tool_calls` → `token`× N → `done`)。跳过 CRAG 重试循环以立即开始流式传输。 |
| POST | `/api/v1/ingest` | 上传一个或多个 PDF 到知识库中 |
| GET | `/api/v1/threads` | 列出聊天线程 |
| GET | `/api/v1/threads/{id}/messages` | 获取线程的消息历史 |
| PATCH | `/api/v1/threads/{id}` | 重命名线程 |
| DELETE | `/api/v1/threads/{id}` | 删除线程 |
### 示例:`/api/v1/chat`
```bash
curl -X POST http://localhost:8000/api/v1/chat \
-H "Content-Type: application/json" \
-d '{"question": "show tickets assigned to me today"}'
```
```json
{
"question": "show tickets assigned to me today",
"answer": "...",
"sources": ["external_tools:query_tickets"],
"tool_used": "query_tickets",
"verification": "YES",
"thread_id": "..."
}
```
## 👨💻 贡献者
- [@ash-iiiiish](https://github.com/ash-iiiiish)
## 🤝 贡献
欢迎贡献!请 fork 此仓库并提交拉取请求。
---
## 📄 许可证
该项目根据 MIT 许可证授权 — 请参阅 [LICENSE](LICENSE) 文件以获取详细信息.............
---
连接信息
猜你喜欢
暂无推荐服务器