kb-mcp-server
by Doy369
README.md
# KB MCP Server · 企业级 B2B 客服工单知识库 RAG 系统
> 基于 **MCP 协议 + Python 3.13** 的可调用外部 API 的知识库。给 Agent 一套「检索知识 + 调用实时数据 + 结构化合成答复」的工具,让客服工单场景的问答既**有据可依**(知识库)、又**实时准确**(订单/库存等外部系统)。
🌐 **在线演示**:<https://Doy369.github.io/kb-mcp-server/>
> 演示为离线模式(本地私有化检索 + mock 实时数据),无需任何外部依赖,开箱即跑。
> (页面挂在 GitHub Pages;后端 Render 可选——见「演示部署」章节。静态部署模式下侧边栏会显示"📦 静态演示"。)
---
## ✨ 特性
- **MCP 工具化**:通过 MCP 协议把知识库能力暴露给任意 MCP 客户端(Claude Desktop、自研 Agent 等)。
- **混合检索(RAG)**:向量语义召回 + 关键词,命中片段带相似度分数与可解释来源。
- **知识图谱(P6 · GraphRAG)**:摄取时自动抽取三元组建图;问答时语义召回与图谱多跳**并行**,答复附带**可解释关系路径**(路径即证据)。
- **实时数据接入(P4)**:内置订单状态 / 库存适配器,按问题意图自动调用外部 API,合成为「知识 + 实时数据」结构化答复(含置信度与轨迹)。
- **多格式摄取**:`.md / .txt / .docx`(零依赖解析),支持单文档、文件夹批量、文件上传。
- **可切换存储 / 嵌入**:
- 存储:`memory`(纯 Python 离线开发)⇄ `pgvector`(生产,Postgres + 向量索引)。
- 嵌入:`dev`(离线条目哈希,零依赖)⇄ `bge`(sentence-transformers 本地模型,数据不出域)。
- **Web 控制台**:内置前端(`static/index.html`),知识摄取、检索、指标、知识图谱、Agent 协作、接口配置、对话一体。
- **生产加固(P5)**:可选 Bearer 鉴权、按 IP 限流、结构化访问日志、`/api/metrics` 指标。
- **桌面客户端**:可用 PyInstaller 打包为单文件 exe,原生窗口承载控制台(pywebview)。
---
## 🏗 架构
```
MCP Client ──▶ MCP Server (FastMCP)
(Agent / IDE) ingest · search · ask_with_live
graph_query · graph_expand · graph_paths
│
▼
┌──────────────────────────────────────────────────┐
│ KB MCP Server 核心 │
│ │
│ Ingestion ──┬─▶ Embeddings ────▶ 向量库 │
│ └─▶ TripleExtractor ▶ 知识图谱 │
│ │
│ Retrieval(向量+BM25) ─┐ │
│ graph.expand_facts ───┼─▶ Synthesis 合成答复 │
│ Adapters(实时数据) ───┘ │
└────┬──────────────┬───────────────┬─────────────┘
│ │ │
▼ ▼ ▼
memory / pgvector memory / AGE 订单 · 库存 · CRM
(向量:管语义) (图谱:管关系) (实时数据)
└──────── 同一个 PostgreSQL 实例 ─────────┘
│
▼
Web 控制台 (app.py → static/index.html)
知识库 / 检索·指标 / 知识图谱 / 接口配置 / 对话
```
> **GraphRAG 的分工**:向量检索回答「哪段话像这个问题」,知识图谱回答「这些实体之间什么关系、能推出什么」。
> 两者互补——图谱是向量库的**关系增强层**,不是替代品。
---
## 📁 目录结构
```
kb-mcp-server/
├── kb_mcp_server/ # 核心包
│ ├── server.py # MCP Server(FastMCP 工具定义,含图谱与多 agent 工具)
│ ├── config.py # 配置(环境变量 + 运行时配置持久化)
│ ├── embeddings.py # 嵌入层(DevEmbedder / BGEEmbedder)
│ ├── storage.py # 向量存储(MemoryVectorStore / PGVectorStore)
│ ├── graph.py # 知识图谱(本体 / 双后端 / 三元组抽取 / 多跳查询)
│ ├── llmclient.py # 本地 LLM 客户端(代理绕过 + 60s 熔断,三处调用共用)
│ ├── ingestion.py # 摄取管线(切片 + 嵌入 + 写入,顺带抽取三元组入图)
│ ├── retrieval.py # 混合检索
│ ├── synthesis.py # 合成层(知识 + 图谱 + 实时数据 → 结构化答复)
│ ├── adapters.py # 外部 API 适配器(订单/库存)
│ ├── agents/ # 多 agent 协作层(P7)
│ │ ├── base.py # AgentContext 黑板 + BaseAgent 模板(计时/异常兜底)
│ │ ├── workers.py # GraphBuilder / Retriever / GraphReasoner / LiveData / Synthesizer
│ │ └── orchestrator.py # 编排器(deterministic / llm 路由,三路并行)
│ └── __main__.py
├── app.py # Web 控制台(HTTP 服务 + 前端)
├── run_demo.py # 演示入口(离线播种,用于云端/演示部署)
├── client.py # 桌面客户端(pywebview 原生窗口)
├── static/index.html # 前端控制台页面(含知识图谱面板)
├── demo_offline.py # 离线自检脚本(摄取→检索整条链路)
├── demo_graph.py # 图谱自检脚本(建图→多跳→推理路径→融合答复)
├── demo_agents.py # 多 agent 自检脚本(补图→并行召回→合成→轨迹)
├── setup_db.py # pgvector 建表初始化(--graph 额外初始化 AGE 图)
├── make_samples.py # 生成多格式测试样本
├── fake_order_api.py # 本地假订单后端(验证字段映射用)
├── requirements.txt
├── .env.example # 全部配置项示例
└── samples/ test-docs/ # 示例知识库文档
```
---
## 🚀 快速开始(离线模式)
### 1. 环境
- Python 3.13+
- 离线默认模式**零额外依赖**(仅 `pydantic`、`python-dotenv`)
```bash
pip install pydantic python-dotenv
# 生产模式按需:pip install "psycopg[binary]" pgvector
```
### 2. 运行 Web 控制台(最直观)
```bash
python app.py
# 自动打开浏览器:http://localhost:8000
```
控制台包含:
- **📚 知识库**:粘贴文本入库 / 载入示例 FAQ / 选择文件夹或输入路径批量导入(自动建图)。
- **🔍 检索 · 指标**:测试查询、查看命中片段与相似度、查看 `/api/metrics` 运行指标。
- **🕸 知识图谱**:图谱统计、实体列表、点实体查多跳路径、用问题试关系侧召回、一键重建。
- **🤝 Agent 协作**:agent 团队清单、协作问答——答复附带每个 agent 的耗时/成败/摘要轨迹。
- **⚙ 接口配置**:在页面上填写外部 API 地址、鉴权、字段路径等,立即生效并持久化。
- **💬 对话**:多轮问答,自动召回知识 + 图谱路径 + 拉取实时数据(订单/库存)合成答复。
### 3. 运行 MCP Server
```bash
python -m kb_mcp_server.server
# 也可 mcp.run() 默认 stdio 传输,供 MCP 客户端连接
```
### 4. 演示 / 云端部署入口
```bash
python run_demo.py
# 强制离线默认 + 重新播种示例知识库 + mock 实时数据
# 端口优先读 $PORT,回退 $KB_WEB_PORT,再回退 8000
```
---
## 🧰 MCP 工具一览
| 工具 | 说明 |
|------|------|
| `ping` | 健康检查 |
| `ingest_document(doc_id, text, chunk_size, overlap)` | 把文档灌入知识库,返回切片数 |
| `search_knowledge(query, top_k, mode)` | 混合检索,返回带相似度分数的知识片段 |
| `ask_with_live_data(question, top_k, order_id, sku, history)` | 检索 + 调外部 API + 查图谱 + 合成结构化答复(含置信度/关系路径/轨迹),支持多轮 `history` |
| `list_documents()` | 列出知识库所有文档(含片段数与预览) |
| `delete_document(doc_id)` | 删除某篇文档及其全部片段,并清理它在图谱中抽出的关系 |
#### 知识图谱工具(P6)
| 工具 | 说明 |
|------|------|
| `graph_expand(query, top_k, depth)` | **GraphRAG 关系侧召回**:从问题抽实体 → 查图谱多跳邻居 → 返回可解释路径 |
| `graph_query(entity, relation, direction, depth)` | 查某实体的关联(1-4 跳),返回每个邻居的**完整路径** |
| `graph_paths(src, dst, max_depth)` | 查两实体间的推理路径,例如「物流配送」到「全额退款」走了几跳 |
| `graph_entities(name, node_type, limit)` | 列出图谱实体(模糊匹配 / 按类型过滤),按关联度排序 |
| `graph_stats()` | 图谱概况:节点/边数量、类型分布、本体定义 |
| `graph_rebuild()` | 用向量库已有文档重新抽取建图(存量知识补建 / 换本体后重建) |
#### 多 agent 协作工具(P7)
| 工具 | 说明 |
|------|------|
| `multi_agent_ask(question, top_k, order_id, sku, history)` | **多 agent 协作问答**:编排器调度 4 个职责 agent,答复附带每个 agent 的耗时/成败/摘要轨迹 |
| `agent_status()` | agent 清单与当前编排模式 |
---
## 🕸 知识图谱(GraphRAG 关系层)
### 它解决什么问题
纯向量检索答不准**关系型多跳问题**——「这个客户的问题是不是和前几单同一根因」
「这条产品线适用哪条 SLA 例外条款」。这类问题的答案不在任何一段文本里,而在**实体之间的关系**里。
知识图谱就是把这层关系显式建出来,给向量检索补上「推理 + 可解释」。
### 本体(最小可行:8 类节点 / 7 类关系)
本体驱动的意义:抽取与查询都在这个边界内,不合规的三元组**直接丢弃**,图谱不会发散。
节点类型:
| 类型 | 含义 | 类型 | 含义 |
|------|------|------|------|
| `IssueCategory` | 问题类别 | `Product` | 产品 |
| `SLAClause` | SLA 条款 | `RootCause` | 根因 |
| `Solution` | 解决方案 | `Ticket` | 工单 |
| `Document` | 文档(知识来源) | `Customer` | 客户 |
关系(带主宾类型约束):
| 关系 | 含义 | 主语 → 宾语 |
|------|------|-------------|
| `GOVERNED_BY` | 适用条款 | 问题类别 → SLA 条款 |
| `SOLVED_BY` | 解决方案为 | 问题类别 → 解决方案 |
| `CAUSED_BY` | 根因为 | 问题类别/工单 → 根因 |
| `ABOUT_PRODUCT` | 涉及产品 | 问题类别/工单 → 产品 |
| `CATEGORY_OF` | 归类为 | 工单 → 问题类别 |
| `SUBMITTED_BY` | 由…提交 | 工单 → 客户 |
| `MENTIONS` | 提及 | 文档 → 各类实体 |
### 三元组怎么来的
- **本地 LLM 抽取**(`KB_LLM_ENABLED=1`):按本体约束输出 JSON 三元组,数据不出域。
- **规则词典兜底**(默认,离线零依赖):关键词/正则匹配问题类别、SLA 时限、解决方案、产品、根因。
例:「付款后 48 小时内发货」→ `(物流配送) --适用条款--> (48小时内发货)`。
- 抽取挂在摄取管线上:**每摄入一篇文档顺带把三元组写进图**,不需要额外步骤。
图谱失败绝不阻断摄取——向量库写成功即算成功。
### 三种用法
1. **MCP 工具**(给任意 agent):`graph_expand` / `graph_query` / `graph_paths`。
2. **Web 控制台**:侧栏「🕸 知识图谱」——看统计、翻实体、点实体查多跳、用问题试关系侧召回。
3. **代码**:
```python
from kb_mcp_server.graph import get_graph_store, expand_facts
g = get_graph_store()
g.add_triples(triples) # 建图(本体校验内置)
facts = expand_facts(g, "物流超时怎么赔偿") # 关系侧召回,返回带路径的事实
```
### 自检
```bash
python demo_graph.py
```
跑完整链路:4 篇示例文档摄取建图 → 图谱统计 → 多跳查询 → 推理路径 → GraphRAG 融合答复。
实测输出(memory 后端、离线零依赖):
```
节点 34 / 边 34
按类型: Document 4, IssueCategory 6, SLAClause 12, Solution 6, Product 4, RootCause 2
─
物流配送 --适用条款--> 48小时内发货
退款退货 --解决方案为--> 全额退款
退款退货 --提及--> sla_policy ; sla_policy --提及--> 服务响应 ; 服务响应 --解决方案为--> 全额退款
```
最后一行正是图谱的价值所在:两段知识在向量空间里毫无相似之处,图谱却把它们串成了一条
**跨文档、可解释的推理链**——这就是「路径即证据」。
---
## 🤝 多 agent 协作(P7)
### 架构:按职责切分,共享同一张图
```
Orchestrator(编排 · 路由)
│ 增量补图
▼
GraphBuilder ──写入──▶ 知识图谱
│
┌───────────┼───────────┐ (三个无依赖 worker 并行执行)
▼ ▼ ▼
Retriever GraphReasoner LiveData ← 各自只写黑板(AgentContext)里自己的字段
语义召回 图谱多跳 订单/库存
└───────────┼───────────┘
▼
Synthesizer ──▶ 结构化答复 + agent 轨迹
```
- **按职责切,不按知识域切**(初期知识域太小,按域切会切出一堆空 agent)。
- 协作靠共享黑板(`AgentContext`)传递中间结果,**不引入消息总线**——协议仍然是 MCP(决策 D6)。
- 每个 agent 只写自己负责的字段;单个 agent 失败只降级、不阻断链路(沿用全项目的降级约定)。
### 两种编排模式(`KB_AGENT_MODE`)
| 模式 | 行为 | 适用 |
|------|------|------|
| `deterministic`(默认) | 固定流水线,零 LLM 依赖 | 离线演示 / 生产兜底 |
| `llm` | 本地 LLM 判断要不要查图 / 查实时数据,裁剪流水线 | LLM 可用时降低延迟;失败自动回退 deterministic |
### 轨迹即可观测性
`multi_agent_ask` 的返回里带 `agents.trace`——每个 agent 的名称、耗时、成败、一句话摘要:
```
[OK] GraphBuilder 10ms 图谱已是最新(4 篇已入图)
[OK] Retriever 18ms 召回 1 个片段
[OK] GraphReasoner 18ms 命中 1 个实体,10 条关系事实
[OK] LiveData 1ms 取到 1 条实时数据
[OK] Synthesizer 1ms 合成完成(template,置信度高,5 条关系路径)
```
### 自检
```bash
python demo_agents.py
```
完整演示「知识只入向量库 → GraphBuilder 自动补图 → 三路并行召回 → 合成 → 第二轮秒回」。
LLM 不可达时自动熔断(60s 内不再重试)并回退规则/模板,链路照常跑通。
---
## ⚙️ 配置
复制 `.env.example` 为 `.env` 后按需修改,关键项:
| 分组 | 变量 | 说明 |
|------|------|------|
| 存储 | `KB_STORAGE_BACKEND` | `memory`(离线) / `pgvector`(生产) |
| 图谱 | `KB_GRAPH_BACKEND` | `memory`(离线纯 Python 图) / `age`(Postgres + Apache AGE,与 pgvector 同库) |
| 图谱 | `KB_GRAPH_ENABLED` | 总开关,摄取时是否自动抽取三元组入图(默认 `1`) |
| 图谱 | `KB_GRAPH_NAME` | AGE 模式下的图名(默认 `kb_graph`) |
| 嵌入 | `KB_EMBEDDING_BACKEND` | `dev`(零依赖) / `bge`(本地模型) |
| 合成 | `KB_LLM_ENABLED` / `KB_LLM_BASE_URL` / `KB_LLM_MODEL` | 本地 LLM(OpenAI 兼容,如 Ollama),失败自动回退模板 |
| 实时 API | `KB_API_MOCK` / `KB_ORDER_API_URL` / `KB_INVENTORY_API_URL` / 字段路径 | `KB_API_MOCK=1` 走样例;配 URL 且 `=0` 走真实 HTTP |
| 加固 | `KB_API_TOKEN` / `KB_RATE_LIMIT` / `KB_LOG_FILE` | Bearer 鉴权 / 每 IP 限流 / 结构化日志 |
> 页面「接口配置」提交的配置会持久化到 `runtime_config.json`,优先级高于 `.env`。
---
## 🏭 生产部署
1. **存储切 pgvector**
```bash
pip install "psycopg[binary]" pgvector
# 目标 PG 安装 vector 扩展后:
KB_STORAGE_BACKEND=pgvector KB_DATABASE_URL=postgresql://user:pass@host:5432/kb python setup_db.py
```
1. **图谱切 AGE(可选,与 pgvector 同库,不额外引入数据库)**
```bash
# 前提:目标 PG 已安装 age 扩展(CREATE EXTENSION age 可用)
KB_STORAGE_BACKEND=pgvector KB_GRAPH_BACKEND=age \
KB_DATABASE_URL=postgresql://user:pass@host:5432/kb python setup_db.py --graph
```
> AGE 不可用时会自动回退 `memory` 图并在日志里说明,主链路不受影响。
2. **嵌入切 bge(数据不出域)**
```bash
pip install sentence-transformers
KB_EMBEDDING_BACKEND=bge # 默认 BAAI/bge-large-zh-v1.5
```
3. **启用本地 LLM 合成**:`KB_LLM_ENABLED=1` + 可达的 `KB_LLM_BASE_URL`(如 Ollama `http://localhost:11434/v1`)。
4. **接真实外部 API**:在 `.env` 配 `KB_ORDER_API_URL` / `KB_INVENTORY_API_URL` + 字段路径,并设 `KB_API_MOCK=0`。
5. **加固**:设置 `KB_API_TOKEN` 启用 Bearer 鉴权,`KB_RATE_LIMIT` 限流,`KB_LOG_FILE` 落结构化日志。
### 演示部署 · GitHub Pages(仅前端,零成本)
> 适合作品集/汇报/界面预览。零成本、零后端,但功能受限——页面上按钮可点,但
> 摄取/检索/对话等 API 调用会返回 404(页面顶部会出现"📦 静态演示模式"蓝色横幅提示)。
**Step 1 · 启用 GitHub Pages**
仓库 → **Settings** → **Pages**:
- **Source**: Deploy from a branch
- **Branch**: `main` · **Folder**: `/docs`
- Save
几分钟后站点出现在 `https://<user>.github.io/kb-mcp-server/`(默认 Doy369 用户)。
无需修改任何代码——`docs/index.html` 里 `window.KB_API_BASE` 保持空字符串即可。
---
---
## 📌 备注
- `runtime_config.json`、`kb_store.json`、`.env` 均已 gitignore,不进仓库(含本地私有数据)。
- 离线 `dev` 嵌入为条目哈希实现,语义召回能力有限,仅用于跑通管线与演示;生产请用 `bge`。
- 外部 API 适配器为可扩展框架:继承 `APIAdapter` 实现 `call()` + `_mock()`,在 `build_registry` 注册即可新增后端(CRM / 工单系统等)。
---
## 📄 License
内部 B2B 项目,使用请遵循团队内部约定。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues