# Guide 能力增强实施方案

## 1. 文档目标

本文档用于定义当前“标准办事指南”能力的下一阶段实施方案，目标不是重复已有的 Schema / Mapping / Extractor 设计，而是在现有落地基础上继续补齐以下三类能力：

1. 更可核对
   - 用户不仅知道“本轮回答用了 Guide”，还知道“用了 Guide 里的哪些字段”。

2. 更可运营
   - 运营和产品可以查看抽取结果、识别缺口、做人工修正、巡检 Matter 与 Guide 绑定质量。

3. 更可交付
   - 前后端具备稳定的详情页、对比页、SSE 契约、自动化回归与演进边界。

本文档是对以下已有文档的实施补充：

- `prd/standard-service-guide-structured-schema-draft.md`
- `prd/gov-service-guides-opensearch-mapping-design.md`
- `prd/service-guide-extractor-contract-prompt-api-draft.md`

---

## 2. 当前基线

### 2.1 已完成能力

当前仓库已经完成以下能力闭环：

1. Guide 识别与结构化抽取
   - 标准办事指南在入库链路中可抽取为 `gov_service_guides` 结构化详情。

2. Matter 与 Guide 绑定
   - 图谱构建完成后可回填 `linked_matter_ids`。

3. Guide 进入 QA / Research 检索链路
   - 当问题包含办事指南类意图时，Guide 结构化证据可以单独作为可用材料进入回答上下文。

4. 前端高亮 Guide 来源
   - QA / Research 已将 `source_group=guide` 作为一类一等来源。
   - 回答正文附近已补充“本轮结论包含办事指南结构化证据”的内联提示。

5. Guide profile 契约第一阶段已加固
   - API、extractor、ingest pipeline 已开始共用 typed profile。
   - 当前采取“稳定字段强类型 + 扩展字段兼容”的策略。

6. Guide 对外查询 API 首批筛选已补齐
   - `GET /api/v1/service-guides` 已支持 `query`，并兼容旧 `q` 参数。
   - 已支持 `basic_code`、`matter_type`、`handled_org`、`region`、`express_supported`、`reservation_supported`、`must_onsite` 等组合筛选。

### 2.2 当前主要不足

当前系统仍存在以下缺口：

1. 只有“来源级高亮”，没有“字段级高亮”
   - 用户知道用了 Guide，但不知道用了材料、收费、时限还是窗口字段。

2. 缺少 Guide 独立详情页
   - 当前更偏文档视角，没有一页完整承接 Guide 结构化字段。

3. 缺少运营后台能力
   - 缺少抽取质量列表、人工审核、重新抽取、字段修正与质量巡检。

4. 缺少 Matter 与 Guide 的可观测巡检
   - 绑定虽已回填，但没有专门的质量检查面板或 API。

5. Guide 召回仍偏启发式
   - 当前仍以关键词和 Matter 细节意图触发为主，口语化问法和地域化问法稳定性有限。

6. 缺少跨地区 / 多版本对比能力
   - 无法直接对比不同地区、不同版本 Guide 在材料、收费、时限上的差异。

7. 自动化验证不足
   - 缺少专门覆盖 Guide SSE 契约、Guide 详情页、审核后台和对比能力的回归用例。

8. Guide detail response envelope 尚未最终收敛
   - 当前仍保留顶层摘要字段与 profile 内同名字段并存。
   - 这是当前的易用性设计，后续应在 Guide detail 系列接口稳定后统一评估是否简化。

---

## 3. 设计原则

### 3.1 保持双层模型

- Matter 图继续承担“跨文档可复用的事项语义骨架”。
- Guide 结构化索引继续承担“单份办事指南的版本化详情”。
- 不把窗口、收费、咨询、救济等细节全部图节点化。

### 3.2 公开优先，权限兜底

- 事项类和 Guide 查询仍按公共服务场景优先公开。
- 仅当存在显式 `acl_ids` 时再进入权限过滤。
- Guide 不是独立权限源，仍以文档权限为真值源。

### 3.3 规则优先于生成自由发挥

- 对材料、收费、窗口、时限这类结构明确的问题，优先走结构化摘要与字段回显。
- LLM 负责补充解释、归纳冲突与生成自然语言，不负责替代结构化事实源。

### 3.4 先补可交付能力，再做高级能力

建议先完成以下三类高收益功能：

1. 字段级证据回显
2. Guide 详情页
3. Guide 质检与绑定巡检

在此基础上，再推进对比、重排和高级运营能力。

---

## 4. 本期实施范围

### 4.1 P0 必做

1. 字段级 Guide 证据回显
2. Guide 详情页
3. Guide 质检列表与绑定巡检
4. Guide SSE / 详情页 / 巡检回归测试

### 4.2 P1 应做

1. Guide 问题的结构化回答卡
2. Guide 检索重排与问法归一
3. Guide 与 Matter / 文档 / Search 结果的双向跳转

### 4.3 P2 可选增强

1. Guide 差异对比页
2. 多版本对比
3. 运营人工修正与发布流

### 4.4 明确不在本期

1. 将所有 Guide 字段全面节点化入 Neo4j
2. 重做现有 Matter Graph 模型
3. 构建独立复杂工作流引擎
4. 引入新的持久化基础设施作为前置条件

---

## 5. 总体路线

建议按 3 个阶段推进。

### Phase A：证据可解释化

目标：让 QA / Research 不仅能“命中 Guide”，还能告诉用户命中了哪些字段。

交付物：

1. 后端 reference payload 增加字段级来源信息
2. QA / Research UI 增加字段标签展示
3. SSE 回归测试

### Phase B：Guide 独立工作面

目标：让 Guide 成为一个独立可浏览、可核对、可跳转的产品对象，而不是仅作为 SSE 来源。

交付物：

1. Guide 详情页
2. Search / Matter / QA / Research 到 Guide 详情的统一跳转
3. Guide 详情中的结构化分区展示
4. P1 可选 `answer_card`（复用详情页头部摘要）

### Phase C：质量治理与对比能力

目标：让产品、运营和开发可以看见 Guide 数据质量，并支持对比与持续迭代。

交付物：

1. Guide 质检后台
2. Matter / Guide 绑定巡检
3. 地域 / 版本差异对比页

---

## 6. 详细实施方案

## 6.1 工作流一：字段级 Guide 证据回显

### 6.1.1 目标

当用户提问“普通护照签发需要哪些材料和收费”时，系统除了返回 Guide 来源外，还应清晰标记：

- 命中了 `material_names`
- 命中了 `fee_names`
- 命中了 `promised_time_limit_days`
- 命中了 `window_names`
- 命中了 `consultation_and_supervision.consultation_phones`

### 6.1.2 后端改造

#### A. 在 `research_engine.py` 就近增加命中字段分析

建议直接在 `backend/app/core/research_engine.py` 的 `_collect_service_guide_evidence()` 附近增加轻量字段命中函数，根据用户 query 与 Guide 字段生成：

```python
{
  "matched_fields": ["materials", "fees", "time_limit"],
  "matched_field_labels": ["申请材料", "收费项目", "办理时限"],
  "field_summary": "命中申请材料、收费项目、办理时限",
}
```

初版可用规则法完成，不依赖 OpenSearch explain，也不新建独立 matcher 模块：

1. query 包含“材料 / 证件 / 提交 / 表格” => `materials`
2. query 包含“收费 / 费用 / 工本费 / 多少钱” => `fees`
3. query 包含“多久 / 时限 / 几天 / 办结” => `time_limit`
4. query 包含“窗口 / 地点 / 哪里办 / 大厅” => `windows`
5. query 包含“电话 / 咨询 / 投诉” => `consultation`
6. query 包含“流程 / 步骤 / 如何办理” => `process`

#### B. 扩展 SSE `reference.payload`

在 `backend/app/core/research_engine.py` 的 Guide reference 输出中扩展 payload：

```json
{
  "source_group": "guide",
  "source_label": "办事指南结构化证据",
  "matched_fields": ["materials", "fees"],
  "matched_field_labels": ["申请材料", "收费项目"],
  "summary": "命中申请材料、收费项目"
}
```

#### C. P1 可选 `answer_card`

`answer_card` 不纳入 Sprint 1。等字段标签和 Guide 详情页稳定后，再在 P1 为典型 Guide 问题增加一类可选事件：

```json
{
  "type": "answer_card",
  "title": "办事指南结构化摘要",
  "payload": {
    "kind": "guide_summary",
    "matter_name": "普通护照签发",
    "materials": [...],
    "fees": [...],
    "time_limit": {...},
    "windows": [...],
    "consultation_phones": [...]
  }
}
```

首版可先只在 QA 输出，不强制 Research 同步展示卡片；Research 仍以字段标签和摘要文案为主。

### 6.1.3 前端改造

#### QA

建议改造：

- `frontend/src/views/QAView.vue`
- `frontend/src/components/ChatMessage.vue`
- `frontend/src/components/CitationCard.vue`

展示方式：

1. Guide reference 卡片下追加字段标签
   - 申请材料
   - 收费项目
   - 办理时限

2. P1 若收到 `answer_card(kind=guide_summary)`
   - 在正文上方展示结构化摘要卡

#### Research

建议改造：

- `frontend/src/views/ResearchView.vue`
- `frontend/src/views/research/EvidencePanel.vue`
- `frontend/src/views/research/ReportViewer.vue`

展示方式：

1. EvidencePanel 对 Guide 引用显示字段命中标签
2. ReportViewer 顶部提示文案可增加“命中字段概览”
3. Sprint 1 不为 Research 新增 `answer_card` 渲染链路

### 6.1.4 验收标准

1. QA / Research 中的 Guide 引用能显示字段标签
2. 至少支持材料、收费、时限、窗口、咨询五类标签
3. Sprint 1 不扩展新的 SSE 事件类型，仅在现有 `reference.payload` 上补充 Guide 字段标签信息

---

## 6.2 工作流二：Guide 详情页

### 6.2.1 目标

提供一个完整承接 `gov_service_guides` 结构化结果的详情页，让用户和运营可以脱离原文，直接核对完整 Guide 内容。

### 6.2.2 路由设计

建议新增前端路由：

```text
/guides/:profileId
```

可选兼容路由：

```text
/guides/by-doc/:docId
```

### 6.2.3 后端接口

首版不新增 `summary` / `related` / `quality` 子端点，直接复用现有接口：

1. `GET /api/v1/service-guides/{profile_id}`
   - 返回完整 profile，详情页头部摘要直接从 root 字段和 profile 子集取数
   - quality 信息直接读取 `quality` 嵌套对象或兼容的顶层字段

2. `GET /api/v1/service-guides/by-matter/{matter_id}`
   - 复用为“相关 Guide”来源

3. `GET /api/v1/service-guides/by-doc/{doc_id}`
   - 作为文档、QA、Research 引用跳转时的回退定位入口

4. `GET /api/v1/service-guides`
   - 保持现有列表筛选能力，用于列表页和全局筛选

### 6.2.4 前端页面结构

建议新增：

- `frontend/src/views/GuideDetailView.vue`
- `frontend/src/api/serviceGuide.ts`
- `frontend/src/types/serviceGuide.d.ts`

页面分区建议：

1. 顶部摘要区
   - 事项名称
   - 实施编码
   - 办理对象
   - 办理方式
   - 承诺时限 / 法定时限
   - 是否支持预约 / 快递

2. 申请材料区
   - 行级材料表格

3. 收费区
   - 收费项目、金额、币种、备注

4. 流程区
   - step_titles + summary

5. 窗口与咨询区
   - 窗口地址、电话、办公时间、咨询电话、投诉电话

6. 法律依据区
   - law_name、article_no、摘要

7. 关联对象区
   - Matter 卡片
   - 原始文档
   - 相关 Guide

说明：

- 顶部摘要区不依赖独立 summary API，直接从 `GET /{profile_id}` 返回中取子集。
- 相关 Guide 不依赖独立 related API，直接通过 `GET /by-matter/{matter_id}` 获取。
- 质量信息不依赖独立 quality API，直接展示详情结果中的 `quality` 与兼容字段。

### 6.2.5 跳转改造

建议统一从以下入口支持跳转 Guide 详情页：

1. Search 结果
2. Matter 详情页
3. QA 引用卡片
4. Research EvidencePanel
5. 文档详情页中的 Guide 摘要模块

### 6.2.6 验收标准

1. 任意 Guide 引用可点击进入 Guide 详情页
2. 详情页完整覆盖核心 Guide 字段
3. 页面可从 Matter / 文档 / QA / Research 多入口进入

---

## 6.3 工作流三：Guide 质检列表与绑定巡检

### 6.3.1 目标

把当前“Guide 是否抽对、是否缺字段、是否绑定到 Matter”从隐式状态改成显式可观测状态。

### 6.3.2 后端接口

建议新增 Admin API：

1. `GET /api/v1/admin/service-guides`
   - 支持按 `needs_review`、`scene_type`、`matter_name`、`updated_at` 过滤

2. `GET /api/v1/admin/service-guides/{profile_id}`
   - 返回完整 profile + quality + raw_sections

3. `POST /api/v1/admin/service-guides/{profile_id}/reextract`
   - 定义为“仅 Guide 重抽”，只重新执行一次 `ServiceGuideExtractor.extract()` 并写回 Guide 索引
   - 不重跑 chunk、embedding、graph、content_hash、ACL 更新
   - 若原始文档内容、权限或 content_hash 已变化，应走完整 re-ingest，而不是走该接口

4. `GET /api/v1/admin/service-guides/binding-audit`
   - 返回绑定巡检结果

说明：

- `PATCH /api/v1/admin/service-guides/{profile_id}` 保留到 P2，与人工修正 / 发布流一起设计，不纳入本期 API 清单。

### 6.3.3 巡检维度

`binding-audit` 至少输出以下指标：

1. 未绑定 Matter 的 Guide 数量
2. 无 Guide 的 Matter 数量
3. 绑定多个 Matter 的 Guide 列表
4. `needs_review=true` 的 Guide 列表
5. completeness_score 低于阈值的 Guide 列表

### 6.3.4 前端后台页面

建议新增：

- `frontend/src/views/admin/GuideAuditView.vue`

页面包含两个 Tab：

1. 抽取质量
2. 绑定巡检

质量列表字段：

- matter_name
- implementation_code
- completeness_score
- confidence_score
- needs_review
- missing_fields
- updated_at

绑定巡检字段：

- profile_id
- matter_name
- linked_matter_ids
- binding_status
- source_doc_id

### 6.3.5 验收标准

1. 后台可以筛出低质量 Guide
2. 后台可以筛出未绑定 Matter 的 Guide
3. 后台可触发“仅 Guide 重抽”

---

## 6.4 工作流四：Guide 检索重排与问法归一

### 6.4.1 目标

提升口语化、问句化和地域化问题下的 Guide 召回稳定性。

### 6.4.2 实施点

#### A. Matter 别名归一

在抽取和索引阶段强化：

- matter_name
- colloquial_names
- guide_search_text

同时增加问法归一规则，例如：

- “办护照” -> “普通护照签发”
- “护照怎么办” -> “普通护照签发 办理流程”
- “护照收费多少” -> “普通护照签发 收费 工本费”

#### B. 检索重排

对 Guide 命中结果增加轻量重排分：

```text
总分 = OpenSearch 原始分 + 字段意图匹配加权 + Matter 名命中加权 + 地域命中加权
```

#### C. 触发与加权复用同一套字段规则

当前 `_should_collect_service_guide_evidence()` 已结合关键词、`matter_ids` 和 `plan.intent` 三路判断。首版不新增独立意图分类器，而是直接复用 6.1 的字段命中规则作为检索侧加权信号：

1. 命中“材料”类关键词 -> 提升 `material_names` / `materials`
2. 命中“收费”类关键词 -> 提升 `fee_names` / `fees`
3. 命中“时限”类关键词 -> 提升 `promised_time_limit_days` / `legal_time_limit_days`
4. 命中“窗口 / 咨询 / 流程”类关键词 -> 提升对应结构化字段

这样一套规则同时服务于：

- `matched_fields` / `matched_field_labels` 回显
- Guide 检索轻量重排

避免维护两套重复的关键词表。

### 6.4.3 验收标准

1. “怎么办”“去哪里办”“多少钱”“多久办完”等问法仍可稳定命中 Guide
2. Guide 命中排序不再主要依赖原始全文分词巧合

---

## 6.5 工作流五：Guide 对比能力

### 6.5.1 目标

支持用户对比两个或多个 Guide 在以下维度的差异：

- 材料
- 收费
- 办理时限
- 办理方式
- 窗口 / 咨询方式

### 6.5.2 对比场景

1. 同事项不同地区
2. 同事项不同版本
3. 同一事项线上 / 线下办理要求差异

### 6.5.3 后端接口

建议新增：

`POST /api/v1/service-guides/compare`

请求：

```json
{
  "profile_ids": ["guide_a", "guide_b"],
  "dimensions": ["materials", "fees", "time_limit", "windows"]
}
```

返回：

```json
{
  "items": [...],
  "diff": {
    "materials": {...},
    "fees": {...},
    "time_limit": {...},
    "windows": {...}
  }
}
```

对比算法要求：

- `materials` 按 `material_name` 做 key 对齐，不按数组下标比较
- `fees` 按 `fee_name` 做 key 对齐，不按数组下标比较
- `windows` 按 `window_name` 做 key 对齐
- 标量字段如 `time_limit`、`express_supported`、`reservation_supported` 直接按字段值比较

### 6.5.4 前端页面

建议新增：

- `frontend/src/views/GuideCompareView.vue`

首版支持双栏对比即可，不做无限多列。

### 6.5.5 验收标准

1. 能比较两个 Guide 的材料差异
2. 能比较收费 / 时限 / 窗口差异
3. UI 可直接标出“仅左侧存在 / 仅右侧存在 / 内容不同”

---

## 7. 代码落点建议

## 7.1 后端

### 已有文件扩展

- `backend/app/core/research_engine.py`
- `backend/app/infrastructure/es_client.py`
- `backend/app/api/v1/service_guide.py`
- `backend/app/api/schemas/service_guide.py`
- `backend/app/api/v1/admin.py`

说明：

- Guide 字段命中规则、问法归一和轻量加权逻辑优先就近放在 `research_engine.py`，在规则复杂前不新建独立 matcher 模块。

### 建议新增文件

- `backend/app/core/service_guide_audit_service.py`
  - 负责质量巡检与绑定巡检

- `backend/app/api/schemas/admin_service_guide.py`
  - Admin 端返回模型

- `backend/tests/test_service_guide_admin_api.py`
- `backend/tests/test_service_guide_compare_api.py`

## 7.2 前端

### 已有文件扩展

- `frontend/src/views/QAView.vue`
- `frontend/src/components/ChatMessage.vue`
- `frontend/src/components/CitationCard.vue`
- `frontend/src/views/ResearchView.vue`
- `frontend/src/views/research/EvidencePanel.vue`
- `frontend/src/views/research/ReportViewer.vue`

### 建议新增文件

- `frontend/src/views/GuideDetailView.vue`
- `frontend/src/views/GuideCompareView.vue`
- `frontend/src/views/admin/GuideAuditView.vue`
- `frontend/src/api/serviceGuide.ts`
- `frontend/src/types/serviceGuide.d.ts`

---

## 8. 数据契约增量

## 8.1 SSE reference payload 增量字段

```json
{
  "source_group": "guide",
  "source_label": "办事指南结构化证据",
  "summary": "命中申请材料、收费项目",
  "matched_fields": ["materials", "fees"],
  "matched_field_labels": ["申请材料", "收费项目"]
}
```

## 8.2 P1 可选 `answer_card` 事件

说明：该事件不纳入 Sprint 1，也不是首期 SSE 契约扩展前提。

```json
{
  "type": "answer_card",
  "title": "办事指南结构化摘要",
  "payload": {
    "kind": "guide_summary",
    "matter_name": "普通护照签发",
    "materials": [],
    "fees": [],
    "time_limit": {},
    "windows": []
  }
}
```

## 8.3 Admin 巡检返回

```json
{
  "summary": {
    "total_guides": 0,
    "needs_review": 0,
    "unbound_guides": 0,
    "matters_without_guides": 0
  },
  "items": []
}
```

---

## 9. 测试与验证

## 9.1 后端测试

新增或补充以下测试：

1. `test_research_engine_unit.py`
   - Guide reference payload 含 `matched_fields`
   - Sprint 1 不要求 `answer_card`，仅验证 Guide 字段标签与摘要文案

2. `test_service_guide_api_unit.py`
   - `GET /service-guides/{profile_id}`、`GET /service-guides/by-doc/{doc_id}`、`GET /service-guides/by-matter/{matter_id}` 正常返回

3. `test_service_guide_admin_api.py`
   - 质检列表、仅 Guide 重抽、绑定巡检

4. `test_service_guide_compare_api.py`
   - Guide compare diff 结果正确
   - `materials` / `fees` 按 name-key 对齐比较

## 9.2 前端验证

当前前端没有独立测试体系，建议至少补两个层次：

1. 组件级 smoke
   - Guide 字段标签渲染
   - Guide 摘要卡渲染
   - Guide 详情页关键区块显示

2. 手工联调脚本
   - QA SSE 命中 Guide
   - Research run SSE 命中 Guide
   - Guide 详情页打开正常
   - Guide 后台筛选正常

## 9.3 构建验证

本地已知现状：

- `npm run build` 可能受 `vue-tsc` 工具链兼容问题影响
- 当前更可靠的前端编译验证命令是 `npx vite build`

因此本阶段建议：

1. 每次前端改动后至少跑 `npx vite build`
2. 单独安排一个小任务修复 `vue-tsc` 工具链问题

---

## 10. 里程碑建议

## Sprint 1：证据可解释化

交付：

1. `matched_fields` / `matched_field_labels`
2. Research / QA Guide 字段标签展示
3. SSE 回归测试

## Sprint 2：Guide 详情页

交付：

1. GuideDetailView
2. 复用现有 detail / by-matter / by-doc API 完成详情页数据装载
3. Search / QA / Research / Matter 跳转 Guide 详情
4. P1 可选 `answer_card`

## Sprint 3：治理后台

交付：

1. GuideAuditView
2. 后台质检与绑定巡检 API
3. 重抽取能力

## Sprint 4：对比与重排

交付：

1. Guide compare API + 页面
2. 复用字段命中规则的轻量重排

---

## 11. 优先级建议

如果资源有限，建议优先按以下顺序做：

1. 字段级证据回显
   - 这是当前已有能力的最小闭环增强，开发成本低、用户感知最强。

2. Guide 详情页
   - 没有详情页，Guide 仍只是“隐藏在检索链路里的结构化对象”。

3. Guide 质检与绑定巡检
   - 这是把能力从 demo 走向可运营的关键一步。

4. Guide 对比
   - 适合在基础交互跑稳后作为高价值增强。

---

## 12. 风险与应对

### 风险 1：字段级命中解释不准确

应对：

- 首版优先使用规则法，不依赖复杂 explain
- 仅标识“命中的字段类别”，不承诺逐 token 精确匹配

### 风险 2：Guide 详情页字段过多，页面过重

应对：

- 首版仅展示高频字段
- 将 raw_sections、quality 等二级信息折叠到高级面板

### 风险 3：人工修正与自动抽取相互覆盖

应对：

- 首版先只做重抽取与只读审核
- 人工修正能力放在 P2，配套字段级来源记录后再开放

### 风险 4：重抽取与完整 re-ingest 边界不清

应对：

- 本期 `reextract` 明确定义为“仅 Guide 重抽”
- 若底层文档内容、权限或 content_hash 已变化，必须回到完整 ingest pipeline
- 在后台和接口文档中明确该边界，避免误用

### 风险 5：前端构建工具链不稳定

应对：

- 阶段内采用 `npx vite build` 作为可靠编译校验
- 单开任务修复 `vue-tsc`

---

## 13. 实施结论

Guide 能力下一阶段不建议继续只做“抽取得更全”这一类后台优化，而应围绕以下方向形成产品闭环：

1. 让用户看懂回答为什么可信
   - 字段级证据回显

2. 让 Guide 成为一个可独立浏览的对象
   - Guide 详情页

3. 让运营和开发可以持续修正它
   - 质检列表与绑定巡检

4. 在此基础上再做检索重排和地区 / 版本对比

按照本文档推进，可以在不推翻现有 Matter + Guide 双层架构的前提下，把当前能力从“已接入”推进到“可交付、可核对、可运营”。