Add Cloud Tour Libo knowledge graph platform

This commit is contained in:
2026-07-30 10:08:04 +08:00
parent 9e05b09a38
commit bae5197d62
103 changed files with 14036 additions and 160 deletions

View File

@@ -6,12 +6,18 @@ FastAPI 会自动生成交互式 API 文档。启动服务后访问:
http://localhost:8102/docs
```
所有后台接口统一挂载在:
后台管理接口统一挂载在:
```text
/v1/admin
```
第三方系统对接接口统一挂载在:
```text
/v1/openapi
```
## 常用接口
| 接口 | 方法 | 说明 |
@@ -31,7 +37,8 @@ http://localhost:8102/docs
| `/v1/admin/plaza/overview` | `GET` | 图谱广场概览 |
| `/v1/admin/manual-ingest/extract` | `POST` | 手动抽取 |
| `/v1/admin/travel/assistant-query` | `POST` | 旅行客服问答 |
| `/v1/admin/travel/customer-service-query` | `POST` | 百姓惠智能客服外部问答接口 |
| `/v1/openapi/knowledge-qa/query` | `POST` | 百姓惠智能客服第三方问答接口 |
| `/v1/admin/travel/customer-service-query` | `POST` | 兼容旧版外部问答接口 |
| `/v1/admin/super-agent/run` | `POST` | Super Agent 任务 |
| `/v1/admin/roles` | `GET/POST` | 角色管理 |
| `/v1/admin/users` | `GET/POST` | 用户管理 |
@@ -76,30 +83,38 @@ curl http://localhost:8102/v1/admin/travel/assistant-query \
## 百姓惠智能客服外部接口
该接口用于对接外部客服系统。调用方传入用户自然语言问题,服务端默认选择百姓惠旅行社知识图谱,先召回图谱线路、报价口径、费用、酒店、餐饮、车辆和证据,再用 LLM 融合成客服可直接使用的话术。没有配置 LLM 时会自动退回图谱模板回答
该接口用于对接外部客服系统。调用方传入用户自然语言问题,服务端默认选择百姓惠旅行社知识图谱,按“LLM 生成只读 Cypher -> FalkorDB 图查询 -> LLM 基于证据组织答案”的链路返回客服话术和图谱证据。生产环境需要配置问答环节 LLM
认证方式使用接口 Key,默认本地开发值来自 `.env` / `docker-compose.yml``INGEST_API_KEYS`
认证方式使用接口 Key。Key 可以在后台 `系统 -> Agent 设置 -> 外部图谱问答 API` 维护;同时兼容 `.env` / `docker-compose.yml``INGEST_API_KEYS`。同一模块底部可以配置“问答环节 LLM 模型”,外部客服话术融合会优先使用该模型,未填写时继承全局 LLM
```bash
curl http://localhost:8102/v1/admin/travel/customer-service-query \
curl http://localhost:8102/v1/openapi/knowledge-qa/query \
-H 'Content-Type: application/json' \
-H 'X-KG-API-Key: dev-key-1' \
-d '{
"request_id": "crm-msg-20260610-0001",
"question": "黄小西三日游多少钱?",
"knowledge_graph": "百姓惠",
"graph_name": "baixinghui_travel_agency",
"session_id": "demo-session-001",
"channel": "online_service",
"customer_id": "customer-001",
"use_llm": true,
"llm_fusion": true
}'
```
新系统请优先使用 `/v1/openapi/knowledge-qa/query``/v1/admin/travel/customer-service-query` 仅用于兼容已经接入的内部/旧系统。
常用入参:
| 字段 | 说明 |
| --- | --- |
| `request_id` / `message_id` | 外部系统请求或消息 ID可选不传时服务端生成 |
| `question` / `text` | 用户原始咨询内容,必填 |
| `knowledge_graph` / `graph_name` | 知识图谱名称,可传 `百姓惠``bxh``baixinghui_travel_agency` |
| `graph_name` / `knowledge_graph` | 知识图谱名称;不传时使用后台默认图谱。百姓惠可传 `百姓惠``bxh``baixinghui_travel_agency` |
| `session_id` | 外部客服会话 ID可选 |
| `channel` | 来源渠道,如 `web``wechat``online_service`,可选 |
| `customer_id` / `external_user_id` | 外部客户 ID可选 |
| `customer_context` | 外部系统附带的客户上下文,可选 |
| `use_llm` | 是否启用 LLM 意图解析,默认 `true` |
| `llm_fusion` | 是否启用 LLM 话术融合,默认 `true` |
@@ -109,6 +124,8 @@ curl http://localhost:8102/v1/admin/travel/customer-service-query \
| 字段 | 说明 |
| --- | --- |
| `request_id` | 外部请求 ID原样回传或由服务端生成 |
| `trace_id` | 服务端链路追踪 ID排查问题时使用 |
| `answer` | 给外部系统展示的完整回答 |
| `customer_reply` | 可直接发给客户的话术 |
| `confidence` | 本次回答置信度 |
@@ -119,6 +136,26 @@ curl http://localhost:8102/v1/admin/travel/customer-service-query \
| `routing.intent` | 解析出的客户需求 |
| `trace` | 响应耗时、召回规模、质量检查摘要 |
认证请求头支持三种写法,推荐第一种:
```text
X-KG-API-Key: <api-key>
X-API-Key: <api-key>
Authorization: Bearer <api-key>
```
生产环境必须至少配置一个 API Key未配置时对外问答接口会返回 `503`,表示接口尚未启用。
不要使用 `dev-key-1` 这类弱密钥作为生产 Key建议使用高强度随机字符串按周期轮换并优先通过环境变量 `INGEST_API_KEYS` 或后台配置统一管理。
常见错误码:
| 状态码 | 说明 |
| --- | --- |
| `400` | 请求体缺少 `question` |
| `401` | API Key 缺失或无效 |
| `502` | 图查询、LLM 生成 Cypher 或答案合成失败 |
| `503` | 后台未配置接口 API Key |
## 前端调用
React 管理后台通过 `admin-web/src/api.ts` 访问同源 API。Docker 部署时前端和 API 同在 `http://localhost:8102`,因此无需额外配置跨域代理。

View File

@@ -0,0 +1,568 @@
# 百姓惠智能客服 MCP Server 打包说明
本文档说明如何将当前百姓惠旅行社知识图谱智能客服能力封装为一个 MCP Server供 DeerFlow、Agent 平台或其他支持 MCP 的智能体调用。
## 1. 改造目标
当前系统已经提供普通 HTTP 问答接口:
```text
POST http://8.163.40.99:8102/v1/openapi/knowledge-qa/query
```
MCP Server 不需要重写现有问答 engine只需要在现有接口外增加一层适配
```text
Agent / DeerFlow
-> MCP Client
-> 百姓惠 MCP Server
-> 现有智能客服问答 API
-> 知识图谱 / FalkorDB / LLM
```
这层 MCP Server 负责:
- 暴露 Agent 可调用的 tools。
- 将 tool call 转换为当前项目已有 HTTP API 请求。
- 将智能客服 API 返回值整理成稳定的 MCP tool result。
- 统一处理鉴权、超时、错误、日志和审计。
## 2. MCP Server 推荐入口
建议新增远程 HTTP MCP Server
```text
http://8.163.40.99:8102/mcp
```
如果后续需要 SSE
```text
http://8.163.40.99:8102/mcp/sse
```
推荐优先使用 `http` 类型,便于 DeerFlow 或企业 Agent 平台远程接入。
## 3. DeerFlow 接入配置示例
`extensions_config.json` 示例:
```json
{
"mcpServers": {
"baixinghui_customer_service": {
"enabled": true,
"type": "http",
"url": "http://8.163.40.99:8102/mcp",
"headers": {
"Authorization": "Bearer $BXH_MCP_TOKEN"
},
"description": "百姓惠旅行社知识图谱智能客服 MCP 工具"
}
},
"skills": {}
}
```
环境变量示例:
```bash
export BXH_MCP_TOKEN="<MCP_SERVER_TOKEN>"
```
说明:
- `BXH_MCP_TOKEN` 是 MCP Server 的访问令牌。
- MCP Server 内部再使用当前系统配置的 `X-KG-API-Key` 调用现有问答 API。
- 不建议让 DeerFlow 或 Agent 直接持有现有 `X-KG-API-Key`
## 4. MCP Server 内部调用的现有接口
MCP Server 内部统一调用:
```text
POST http://127.0.0.1:8102/v1/openapi/knowledge-qa/query
```
请求头:
```http
Content-Type: application/json
X-KG-API-Key: <INTERNAL_KG_API_KEY>
```
如果 MCP Server 与业务 API 分开部署,则改为:
```text
POST http://8.163.40.99:8102/v1/openapi/knowledge-qa/query
```
## 5. MCP 工具设计原则
不要暴露通用工具,例如:
```text
call_api
execute_cypher
execute_sql
request_url
```
推荐暴露明确、受控的业务工具:
| 工具名 | 用途 | 读/写 | 风险等级 |
| --- | --- | --- | --- |
| `ask_customer_service` | 通用智能客服问答 | 读 | 低 |
| `query_route_price` | 查询线路价格 | 读 | 低 |
| `list_travel_routes` | 查询旅行线路清单 | 读 | 低 |
| `query_route_detail` | 查询线路天数、景区、酒店等详情 | 读 | 低 |
| `compare_routes` | 对比线路适配度或景点数量 | 读 | 中 |
当前阶段建议全部为只读工具,不提供写操作。
## 6. Tool 1ask_customer_service
### 用途
通用客服问答工具。Agent 不确定该调用哪个细分工具时,可以使用该工具。
### Tool 定义
```json
{
"name": "ask_customer_service",
"description": "向百姓惠旅行社知识图谱智能客服提问。适用于线路价格、行程天数、景区、酒店、费用、车型、线路推荐和复杂多跳问答。该工具只读,不承诺最终价格、余位、房型或景区政策。",
"inputSchema": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": "用户自然语言问题"
},
"session_id": {
"type": "string",
"description": "外部会话 ID可选"
},
"request_id": {
"type": "string",
"description": "外部请求 ID可选"
},
"customer_context": {
"type": "object",
"description": "客户上下文,例如人数、预算、出发日期、偏好,可选"
}
},
"required": ["question"]
}
}
```
### 内部 API 请求示例
```json
{
"request_id": "mcp-req-0001",
"session_id": "mcp-session-a01",
"channel": "mcp",
"graph_name": "baixinghui_travel_agency",
"question": "轻奢黄小西纯玩3日游多少钱可以玩几天期间可以去哪些景区小七孔附近可以入住什么酒店"
}
```
### MCP Tool Result 示例
```json
{
"success": true,
"data": {
"customer_reply": "亲轻奢黄小西纯玩3日游是3天线路成人参考610-2350元/人儿童参考340-700元/人;可玩多彩贵州风、荔波小七孔景区、西江千户苗寨景区、黄果树旅游景区;附近可参考荔波天泰酒店、三力丽呈、荔波滨江。具体价格、房型和余位需要按出发日期再确认。",
"answer": "完整回答内容",
"confidence": 0.88,
"follow_up_questions": ["请提供出发日期和人数。"],
"risk_notes": ["价格、余位、房型和景区政策需按具体团期二次核实。"],
"evidence": [],
"plans": [],
"response_mode": "fast_graph_template"
},
"trace_id": "trc_xxx"
}
```
## 7. Tool 2query_route_price
### 用途
专门查询某条线路价格,例如成人价、儿童价、单房差。
### Tool 定义
```json
{
"name": "query_route_price",
"description": "查询百姓惠旅行社指定线路的参考价格、成人价、儿童价和单房差。该工具返回图谱参考价,最终价格需按出发日期、人数和住宿档位二次核实。",
"inputSchema": {
"type": "object",
"properties": {
"route_name": {
"type": "string",
"description": "线路名称或关键词,例如 黄小西、轻奢黄小西纯玩3日游"
},
"days": {
"type": "integer",
"description": "行程天数,可选"
},
"request_id": {
"type": "string",
"description": "请求 ID可选"
}
},
"required": ["route_name"]
}
}
```
### 内部 question 生成规则
```text
{route_name}{days_text}多少钱?成人价、儿童价和单房差是多少?
```
示例:
```json
{
"question": "黄小西3日游多少钱成人价、儿童价和单房差是多少"
}
```
## 8. Tool 3list_travel_routes
### 用途
查询当前图谱中有哪些旅行线路。
### Tool 定义
```json
{
"name": "list_travel_routes",
"description": "查询百姓惠旅行社当前图谱中的旅行线路清单。",
"inputSchema": {
"type": "object",
"properties": {
"keyword": {
"type": "string",
"description": "线路关键词,可选,例如 黄小西、小西镇梵、旅行车"
},
"request_id": {
"type": "string",
"description": "请求 ID可选"
}
}
}
}
```
### 内部 question 生成规则
无关键词:
```text
旅行车线路有哪些?
```
有关键词:
```text
{keyword}相关线路有哪些?
```
## 9. Tool 4query_route_detail
### 用途
查询某条线路的天数、价格、途经景区、某景区附近酒店等多跳图谱信息。
### Tool 定义
```json
{
"name": "query_route_detail",
"description": "查询指定线路的价格、行程天数、途经景区和景区附近酒店。适合多跳图谱问题。",
"inputSchema": {
"type": "object",
"properties": {
"route_name": {
"type": "string",
"description": "线路名称或关键词"
},
"scenic_name": {
"type": "string",
"description": "需要查询附近酒店的景区名称,可选,例如 小七孔、西江、黄果树"
},
"request_id": {
"type": "string",
"description": "请求 ID可选"
}
},
"required": ["route_name"]
}
}
```
### 内部 question 生成规则
```text
{route_name}多少钱,可以玩几天,期间可以去哪些景区,{scenic_name}附近可以入住什么酒店?
```
示例:
```json
{
"question": "轻奢黄小西纯玩3日游多少钱可以玩几天期间可以去哪些景区小七孔附近可以入住什么酒店"
}
```
## 10. Tool 5compare_routes
### 用途
对比两条或多条线路,例如哪个更适合老人小孩、哪个景点更多、哪个更轻松。
### Tool 定义
```json
{
"name": "compare_routes",
"description": "对比百姓惠旅行社线路的适配度、景区数量、轻松程度、老人小孩适合度等。只做图谱证据对比,不做最终承诺。",
"inputSchema": {
"type": "object",
"properties": {
"route_names": {
"type": "array",
"items": {"type": "string"},
"description": "需要对比的线路关键词,例如 [\"黄小西\", \"小西镇梵\"]"
},
"compare_focus": {
"type": "string",
"description": "对比重点,例如 老人小孩适合度、景点数量、价格、轻松程度"
},
"request_id": {
"type": "string",
"description": "请求 ID可选"
}
},
"required": ["route_names", "compare_focus"]
}
}
```
### 内部 question 生成规则
```text
{route_names}哪个更适合{compare_focus},为什么?
```
示例:
```json
{
"question": "黄小西和小西镇梵哪个更适合老人小孩、不要太累,为什么?"
}
```
## 11. 统一 MCP Tool Result 格式
所有工具建议统一返回:
```json
{
"success": true,
"data": {
"customer_reply": "客服可直接发送的话术",
"answer": "完整回答",
"confidence": 0.88,
"follow_up_questions": [],
"risk_notes": [],
"plans": [],
"evidence": [],
"response_mode": "fast_graph_template",
"latency_ms": 35
},
"trace_id": "trc_xxx"
}
```
失败时返回:
```json
{
"success": false,
"error": {
"code": "CUSTOMER_SERVICE_QUERY_FAILED",
"message": "智能客服查询失败",
"retryable": true
},
"trace_id": "trc_xxx"
}
```
如果业务 API 返回受控兜底,也建议作为 `success: true` 返回,并在 `data.response_mode` 中标记:
```json
{
"success": true,
"data": {
"customer_reply": "亲,这个问题当前图谱暂未查到可确认答案,需要补充更具体的线路、景区或套餐名称后再核实。",
"response_mode": "llm_graph_qa_controlled_failure",
"risk_notes": ["当前回复为受控兜底,不代表图谱已有明确业务证据。"]
},
"trace_id": "trc_xxx"
}
```
## 12. MCP Server 环境变量
建议 MCP Server 使用以下环境变量:
```bash
export BXH_MCP_TOKEN="<MCP_SERVER_TOKEN>"
export BXH_KG_API_BASE="http://127.0.0.1:8102"
export BXH_KG_API_KEY="<INTERNAL_KG_API_KEY>"
export BXH_DEFAULT_GRAPH="baixinghui_travel_agency"
export BXH_MCP_TIMEOUT_SECONDS="15"
```
说明:
| 变量名 | 说明 |
| --- | --- |
| `BXH_MCP_TOKEN` | 外部 Agent 调用 MCP Server 的鉴权令牌 |
| `BXH_KG_API_BASE` | 当前项目 HTTP API 地址 |
| `BXH_KG_API_KEY` | 当前项目外部图谱问答 API Key |
| `BXH_DEFAULT_GRAPH` | 默认图谱 |
| `BXH_MCP_TIMEOUT_SECONDS` | MCP Server 调用业务 API 的超时时间 |
## 13. 安全要求
- MCP Server 只暴露业务工具,不暴露任意 URL、任意 SQL、任意 Cypher。
- 所有工具当前均为只读工具。
- MCP Server 必须校验 `Authorization` 或其他服务令牌。
- 不向 Agent 返回内部 API Key、数据库地址、原始异常栈。
- `risk_notes` 必须保留给 Agent用于提示价格、余位、房型、政策需二次核实。
- 记录工具调用日志,至少包含 tool name、request id、trace id、耗时、调用结果。
## 14. 超时和重试建议
| 场景 | 建议 |
| --- | --- |
| MCP Server 调用业务 API 超时 | 15 秒 |
| 高频模板问题 | 通常几十毫秒到数百毫秒 |
| LLM 长尾问题 | 可能数秒,超过预算返回受控兜底 |
| Agent 重试 | 仅对网络错误或 `retryable: true` 的错误重试 |
| 空结果 | 不建议重试,应追问用户补充信息 |
## 15. 最小验收用例
### 15.1 查询线路价格
工具:
```text
query_route_price
```
输入:
```json
{
"route_name": "黄小西",
"days": 3
}
```
预期:
- 返回 `success: true`
- `data.customer_reply` 有客服话术
- `data.risk_notes` 提醒价格需二次核实
### 15.2 查询线路详情和酒店
工具:
```text
query_route_detail
```
输入:
```json
{
"route_name": "轻奢黄小西纯玩3日游",
"scenic_name": "小七孔"
}
```
预期:
- 返回线路天数
- 返回参考价格
- 返回途经景区
- 返回小七孔附近酒店
### 15.3 对比线路适配度
工具:
```text
compare_routes
```
输入:
```json
{
"route_names": ["黄小西", "小西镇梵"],
"compare_focus": "老人小孩、不要太累"
}
```
预期:
- 返回更推荐的线路
- 返回推荐理由
- 提醒最终需按团期和客户情况核实
### 15.4 长尾无命中问题
工具:
```text
ask_customer_service
```
输入:
```json
{
"question": "美酒中秋有什么活动或者套餐?"
}
```
预期:
- 返回 `success: true`
- `data.response_mode` 可能为 `llm_graph_qa_controlled_failure`
- `customer_reply` 提示补充更具体信息
## 16. 推荐结论
当前项目不需要把现有智能客服接口重写为 MCP。推荐方式是新增一个轻量 MCP Server 适配层,把现有:
```text
/v1/openapi/knowledge-qa/query
```
封装为多个明确的 MCP tools。这样 Agent 可以稳定调用百姓惠知识图谱客服能力同时业务系统仍保留自己的鉴权、超时、图谱查询、LLM 兜底和审计边界。

View File

@@ -148,6 +148,11 @@ LLM_API_BASE=你的OpenAI兼容模型地址
LLM_API_KEY=你的模型Key
```
部署后也可以在后台 `系统 -> Agent 设置` 中配置:
- `全局 LLM 配置`:填写 OpenAI 兼容模型地址、模型 ID、LLM API Key。
- `外部图谱问答 API`:位于页面底部,维护给其他系统调用的 `X-KG-API-Key`,设置默认图谱、默认 LLM 策略和“问答环节 LLM 模型”。该模型优先用于外部客服问答,留空则继承全局 LLM。
| 变量 | 说明 |
| --- | --- |
| `POSTGRES_USER``POSTGRES_PASSWORD``POSTGRES_DB` | PostgreSQL 容器账号、密码、库名 |
@@ -173,33 +178,41 @@ LLM_API_KEY=你的模型Key
给外部系统对接时,只开放这个接口即可:
```text
POST http://8.163.40.99:8102/v1/admin/travel/customer-service-query
POST http://8.163.40.99:8102/v1/openapi/knowledge-qa/query
```
`/v1/admin/travel/customer-service-query` 会继续保留为兼容旧调用,新接入的第三方系统建议统一使用 `/v1/openapi/knowledge-qa/query`
服务器安全组需要放行 TCP `8102`。如果服务器本机 `curl http://127.0.0.1:8102/v1/admin/health` 正常,但外部访问 `http://8.163.40.99:8102` 超时,优先检查云控制台安全组/防火墙入方向规则。
不要把 `5433``6380``3002` 暴露到公网;默认 Compose 已把这些数据端口绑定到 `127.0.0.1`
生产环境必须在后台 `外部图谱问答 API` 或环境变量 `INGEST_API_KEYS` 中配置至少一个接口 Key未配置时对外问答接口会返回 `503`,避免无鉴权开放。
接口 Key 是给第三方系统调用本接口用的访问凭证;问答环节 LLM 的 API Key 是本系统调用大模型用的凭证,两者不要混用。
请求示例:
```bash
curl http://8.163.40.99:8102/v1/admin/travel/customer-service-query \
curl http://8.163.40.99:8102/v1/openapi/knowledge-qa/query \
-H 'Content-Type: application/json' \
-H 'X-KG-API-Key: 你的INGEST_API_KEYS之一' \
-d '{
"request_id": "crm-msg-20260610-0001",
"question": "黄小西三日游多少钱?",
"knowledge_graph": "百姓惠",
"graph_name": "baixinghui_travel_agency",
"session_id": "demo-001",
"channel": "online_service",
"use_llm": true,
"llm_fusion": true
}'
```
`llm_fusion=true` 需要配置 `LLM_API_BASE``LLM_API_KEY`。未配置 key 时,接口仍会返回图谱模板答案,但不会调用 LLM 融合
默认问答链路需要配置问答环节 LLM可在后台 `外部图谱问答 API -> 问答环节 LLM 模型` 单独配置,也可以继承全局 LLM。
主要返回字段:
| 字段 | 说明 |
| --- | --- |
| `request_id` | 外部请求 ID原样回传或由服务端生成 |
| `trace_id` | 服务端链路追踪 ID |
| `answer` | 给外部系统展示的完整回答 |
| `customer_reply` | 可以直接发给客户的话术 |
| `follow_up_questions` | 建议追问 |

View File

@@ -0,0 +1,282 @@
# MCP 工具未暴露问题修复与验证说明
## 1. 问题现象
MCP 客户端配置了服务地址:
```text
http://8.163.40.99:8102/mcp
```
但页面显示:
```text
工具 0
该服务还没有发现工具
```
直接访问服务也返回:
```text
404 Not Found
```
说明当前系统只有普通 HTTP 问答接口,还没有真正实现 MCP Server 的工具发现协议。
## 2. 问题归类
这不是知识图谱数据问题,也不是 LLM 问答引擎问题。
这是:
```text
MCP Server 适配层未实现 / tools/list 未暴露
```
已有能力:
```text
POST /v1/openapi/knowledge-qa/query
```
缺少能力:
```text
POST /mcp
initialize
ping
tools/list
tools/call
```
## 3. 修复方式
新增 FastAPI MCP 适配层:
```text
app/api/mcp_server.py
```
并在主应用挂载:
```text
app.include_router(mcp_router)
```
MCP 层不重写业务逻辑,只把 MCP 工具调用转换成现有百姓惠客服问答接口的内部调用:
```text
MCP Client
-> POST /mcp tools/call
-> ask_customer_service 等工具
-> 现有百姓惠客服问答 engine
-> FalkorDB / 图谱 / LLM
```
## 4. 已暴露工具
当前 `/mcp` 暴露 5 个只读工具:
| 工具名 | 作用 |
| --- | --- |
| `ask_customer_service` | 通用百姓惠智能客服问答 |
| `query_route_price` | 查询线路参考价格 |
| `list_travel_routes` | 查询旅行线路清单 |
| `query_route_detail` | 查询线路天数、景区、酒店、费用等详情 |
| `compare_routes` | 对比两条线路适配度、景点数量、轻松程度等 |
## 5. MCP 初始化验证
请求:
```bash
curl -sS http://8.163.40.99:8102/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "manual-check",
"version": "1.0.0"
}
}
}'
```
预期返回:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": {
"listChanged": false
}
},
"serverInfo": {
"name": "baixinghui-customer-service-mcp",
"version": "0.1.0"
}
}
}
```
## 6. 工具发现验证
请求:
```bash
curl -sS http://8.163.40.99:8102/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'
```
预期结果:
```text
tools 数量 = 5
```
并能看到:
```text
ask_customer_service
query_route_price
list_travel_routes
query_route_detail
compare_routes
```
## 7. 工具调用验证
请求:
```bash
curl -sS http://8.163.40.99:8102/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "ask_customer_service",
"arguments": {
"question": "黄小西三日游多少钱?",
"session_id": "mcp-test-session"
}
}
}'
```
预期返回结构:
```json
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "客服可直接回复的话术"
}
],
"structuredContent": {
"customer_reply": "客服可直接回复的话术",
"answer": "完整答案",
"knowledge": {
"plans": [],
"evidence": []
},
"trace_id": "排查链路 ID"
},
"isError": false
}
}
```
## 8. 客户端侧证明
修复后MCP 客户端刷新服务配置,应从:
```text
工具 0
该服务还没有发现工具
```
变为:
```text
工具 5
```
如果客户端仍显示 0按顺序检查
1. 服务地址是否为 `http://8.163.40.99:8102/mcp`
2. 服务是否已经重新构建并重启。
3. 客户端是否点击了“刷新”或重新检查连接。
4. 如果启用了鉴权,客户端是否带了正确的 `Authorization: Bearer <token>`
## 9. 鉴权说明
当前 MCP 适配层支持可选鉴权。
未设置环境变量时:
```text
BXH_MCP_TOKEN 为空
```
`/mcp` 不强制鉴权,方便内测。
如果设置:
```bash
export BXH_MCP_TOKEN="<your-token>"
```
客户端需要传:
```http
Authorization: Bearer <your-token>
```
或:
```http
X-MCP-API-Key: <your-token>
```
## 10. 结论
这次修复解决的是 MCP 协议层工具暴露问题。
修复前:
```text
/mcp 404
tools/list 无法执行
客户端工具数 0
```
修复后:
```text
/mcp 可响应 JSON-RPC
tools/list 返回 5 个工具
tools/call 可调用百姓惠客服问答 engine
```

View File

@@ -0,0 +1,82 @@
# MarkItDown 转换评测方法
本项目已经接入 Microsoft MarkItDown但上线判断不能只看“能不能转”。推荐用一组真实业务样本文档做可重复评测。
## 评测维度
1. 转换成功率:不同格式是否稳定返回 Markdown。
2. 信息保真度:关键字段、价格、日期、地点、人名、产品 ID 是否还在。
3. 结构保留度:标题、表格、列表、链接是否保留为 Markdown 结构。
4. 噪声控制:乱码、超长行、残留 HTML、空文本、重复内容是否明显。
5. 下游效果:把转换后的 Markdown 送入知识抽取后,实体、关系、证据覆盖是否提升。
## 准备样本
把测试文件放到:
```bash
data/markitdown_eval/input/
```
建议每类至少 5 份:
- PDF普通 PDF、扫描 PDF、复杂表格 PDF
- Word合同、行程单、产品说明
- Excel价格表、团期表、资源表
- PPT介绍资料、图文页
- HTML/Markdown/CSV/JSON/XML
- 图片或截图类资料
## Manifest 示例
创建 `data/markitdown_eval/manifest.json`
```json
{
"cases": [
{
"case_id": "travel_product_docx_001",
"file": "travel_product.docx",
"must_terms": ["产品ID", "成人价", "儿童价", "费用包含", "退费政策"],
"forbidden_terms": ["<22>"],
"expected_headings_min": 2,
"expected_tables_min": 1,
"expected_lists_min": 3,
"expected_links_min": 0,
"min_chars": 800,
"notes": "旅行社产品说明 Word"
}
]
}
```
## 运行评测
```bash
python3 scripts/evaluate_markitdown_conversion.py \
--input-dir data/markitdown_eval/input \
--manifest data/markitdown_eval/manifest.json \
--output-dir outputs/markitdown_eval \
--fail-under 0.70
```
输出:
- `outputs/markitdown_eval/converted/*.markitdown.md`
- `outputs/markitdown_eval/markitdown_eval_report.json`
- `outputs/markitdown_eval/markitdown_eval_report.md`
## 判定建议
- 平均分 `>= 0.85`:可作为默认转换方案,但仍抽检复杂文件。
- `0.70 - 0.85`:可用,但要看缺失字段和结构损失,必要时加 OCR 或人工校正。
- `< 0.70`:不建议直接进入自动知识抽取,应启用替代方案。
## 进一步增强
当前接入是 MarkItDown 本地转换。若样本中大量是扫描 PDF、图片文字、复杂表格、音视频建议再评估
- MarkItDown OCR plugin
- Azure Document Intelligence
- Azure Content Understanding
- 针对旅行社/城市知识图谱的自定义后处理规则

212
docs/接口文档.md Normal file
View File

@@ -0,0 +1,212 @@
# 智能客服问答接口使用说明
本文档仅说明第三方系统如何调用百姓惠智能客服问答接口。
## 1. 接口地址
推荐接口:
```text
POST http://8.163.40.99:8102/v1/openapi/knowledge-qa/query
```
兼容旧接口:
```text
POST http://8.163.40.99:8102/v1/admin/travel/customer-service-query
```
## 2. 请求头
```http
Content-Type: application/json
X-KG-API-Key: <API_KEY>
```
也兼容:
```http
X-API-Key: <API_KEY>
Authorization: Bearer <API_KEY>
```
`<API_KEY>` 由系统管理员提供,不要写在前端代码里。
## 3. 请求参数
| 字段 | 必填 | 示例 | 说明 |
| --- | --- | --- | --- |
| `question` | 是 | `黄小西三日游多少钱?` | 用户自然语言问题 |
| `request_id` | 否 | `crm-msg-0001` | 第三方请求 ID |
| `session_id` | 否 | `sess-a01` | 会话 ID |
| `channel` | 否 | `crm` | 来源渠道 |
| `customer_id` | 否 | `u_10086` | 第三方客户 ID |
| `graph_name` | 否 | `baixinghui_travel_agency` | 默认可不传 |
## 4. 最小请求示例
```bash
curl -X POST 'http://8.163.40.99:8102/v1/openapi/knowledge-qa/query' \
-H 'Content-Type: application/json' \
-H 'X-KG-API-Key: <API_KEY>' \
-d '{
"question": "黄小西三日游多少钱?"
}'
```
## 5. 完整请求示例
```bash
curl -X POST 'http://8.163.40.99:8102/v1/openapi/knowledge-qa/query' \
-H 'Content-Type: application/json' \
-H 'X-KG-API-Key: <API_KEY>' \
-d '{
"request_id": "crm-msg-20260610-0001",
"session_id": "sess-20260610-a01",
"channel": "crm",
"customer_id": "u_10086",
"graph_name": "baixinghui_travel_agency",
"question": "轻奢黄小西纯玩3日游多少钱可以玩几天期间可以去哪些景区小七孔附近可以入住什么酒店"
}'
```
## 6. JavaScript 调用示例
```javascript
const response = await fetch("http://8.163.40.99:8102/v1/openapi/knowledge-qa/query", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-KG-API-Key": "<API_KEY>"
},
body: JSON.stringify({
request_id: "crm-msg-20260610-0001",
session_id: "sess-20260610-a01",
channel: "crm",
question: "黄小西三日游多少钱?",
graph_name: "baixinghui_travel_agency"
})
});
const data = await response.json();
console.log(data.customer_reply);
```
## 7. Python 调用示例
```python
import requests
url = "http://8.163.40.99:8102/v1/openapi/knowledge-qa/query"
headers = {
"Content-Type": "application/json",
"X-KG-API-Key": "<API_KEY>",
}
payload = {
"request_id": "crm-msg-20260610-0001",
"session_id": "sess-20260610-a01",
"channel": "crm",
"question": "黄小西三日游多少钱?",
"graph_name": "baixinghui_travel_agency",
}
resp = requests.post(url, headers=headers, json=payload, timeout=15)
data = resp.json()
print(data["customer_reply"])
```
## 8. 返回示例
```json
{
"status": "ok",
"service": "baixinghui_customer_service",
"request_id": "crm-msg-20260610-0001",
"trace_id": "trc_xxx",
"session_id": "sess-20260610-a01",
"channel": "crm",
"question": "黄小西三日游多少钱?",
"graph_name": "baixinghui_travel_agency",
"answer": "完整回答,适合后台查看。",
"customer_reply": "客服可直接发送给客户的简短话术。",
"confidence": 0.88,
"follow_up_questions": [
"请提供出发日期和人数。"
],
"risk_notes": [
"价格、余位、房型和景区政策需按具体团期二次核实。"
],
"knowledge": {
"plans": [],
"evidence": []
},
"routing": {
"response_mode": "fast_graph_template",
"method": "fast_price_quote_graph_template_v1"
},
"trace": {
"latency_ms": 35,
"stage_timings_ms": {
"graph_query": 20,
"answer_synthesis": 0
}
}
}
```
## 9. 第三方主要读取字段
| 字段 | 说明 |
| --- | --- |
| `customer_reply` | 给客户展示或发送的客服话术 |
| `answer` | 完整答案,适合后台查看 |
| `confidence` | 置信度 |
| `follow_up_questions` | 建议继续追问的问题 |
| `risk_notes` | 需要人工核实的提示 |
| `knowledge.evidence` | 图谱证据 |
| `routing.response_mode` | 当前问答链路 |
| `trace_id` | 排查问题时提供给系统维护人员 |
## 10. 常见测试问题
```json
{
"question": "黄小西三日游多少钱?"
}
```
```json
{
"question": "旅行车线路有哪些?"
}
```
```json
{
"question": "轻奢黄小西纯玩3日游多少钱可以玩几天期间可以去哪些景区小七孔附近可以入住什么酒店"
}
```
```json
{
"question": "黄小西和小西镇梵哪个更适合老人小孩、不要太累,为什么?"
}
```
## 11. 错误码
| HTTP 状态 | 说明 |
| --- | --- |
| `200` | 请求成功 |
| `400` | 缺少 `question` 或请求格式错误 |
| `401` | API Key 缺失或无效 |
| `503` | 服务端未配置 API Key |
| `500/502` | 服务异常,记录 `request_id` 联系维护人员 |
## 12. 接入建议
- 第三方系统后端调用接口,不要在前端暴露 API Key。
- 给客户优先展示 `customer_reply`
- 如果 `risk_notes` 非空,客服应按提示二次核实。
- 建议 HTTP 超时设置为 `15` 秒。