- BFF 薄适配层(FastAPI,8090):QA 代理/SSE 中继/Neo4j 直连/抽取代理/会话持久化 - Vue3 前端:五相位检索流水线、文献来源与证据链、知识图谱、提取任务四 tab - 四档响应式(桌面/笔记本/平板/手机)、深浅主题 - 81 个 FR 全部实现,测试追溯矩阵 81/81,后端 121 测/前端 156 测 - 真实凭据已脱敏,运行时配置在 backend/.env(不入 git) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
346 lines
31 KiB
Markdown
346 lines
31 KiB
Markdown
# 发现报告 — PlantAI RAG BFF 上游探测
|
||
|
||
> 探测日期:2026-08-24 至 2026-08-25(远程机 `100.109.52.26`,SSH 用户 xzq)
|
||
> 本文件为团队事实基线。所有结构均来自真实探测响应或源码/OpenAPI,不是猜测。
|
||
> 未能确认的事项集中在第 6 节,明确标注,勿当作事实使用。
|
||
|
||
---
|
||
|
||
## 1. 摘要与关键结论
|
||
|
||
1. **Neo4j 选型:`neo4j-plant-srt-direct-v1-full`**(bolt `bolt://127.0.0.1:18788`,HTTP `http://127.0.0.1:18575`,db `neo4j`,用户 `neo4j`,密码 `<neo4j-password-in-.env>`)。
|
||
- 这是 QA 服务 7920 实际使用的实例(进程 `/proc/2586988/environ` 中 `NEO4J_URI=bolt://127.0.0.1:18788`),是权威答案。
|
||
- 该实例 schema 为 **canonical**(`QA_V1_GRAPH_SCHEMA=canonical`):实体标签 `SRT2CanonicalEntity`(3,820,996 节点),断言标签 `SRT2CanonicalAssertion`(8,246,875),关系 `SRT2_CANONICAL_ASSERTS` / `SRT2_SUPPORTED_BY`(共 16,449,159 条边)。
|
||
- **任务书假设的 `:Entity` / `[:RELATION]` / `entity_name_ftx` 全文索引在本实例不存在**。名字检索走 `name_norm` RANGE 索引(`srt2_canonical_entity_name_norm`),实测 0.09–0.10s。全文检索需求用 `STARTS WITH`/`CONTAINS` + name_norm 索引即可。
|
||
2. **抽取接口 8000 可用**:`/health` 返回 `{"status":"healthy"}`。`extract-jobs` 有 49 个历史任务(22 completed / 27 failed)。状态枚举为 `queued → running → completed/failed`(stage 相应为 `queued → mineru → llm → completed/failed`)。**注意:`processing-status`、`progress`、`summary` 均返回 `{"rows":[]}`**(因为当前 `METHODOLOGY_BATCH_DIR` 默认指向 `methodology_batch_llm` 目录且该目录不存在,见第 6 节)。`run-log` 返回 JSON `{"text":""}`(不是纯文本)。
|
||
3. **QA 7920 检索接口正常**:search 返回 31 个顶层键(见第 4 节),一次检索耗时约 91.9s(其中 88.8s 是 native_graph_chain_retrieval)。**当前 LLM 余额不足(DeepSeek HTTP 402 Insufficient Balance)**,`degraded_execution=true`,所有 LLM 阶段走 deterministic recovery,`answer` 为空或为 fallback 文案。这影响 chat/stream 的最终答案质量,但不影响 retrieval-only search 的证据输出。
|
||
4. **SSE 阶段序列(有序,五阶段 UI 映射基准)**:
|
||
`understanding_started → entities_identified → related_search_started → concepts_found → subquestion_retrieved → agent_review_started → evidence_accepted → answer_generation_started → completed`,随后 `event: complete` + 完整 JSON(与 search 同构)。有 `: keepalive` 注释帧(实测 2 次)。
|
||
5. **端口 8090、5180 空闲**。node v18.19.1 / npm 9.2.0,`npm ping` 通(573ms),Playwright chromium 下载可行(约 150MB,未实际下载)。
|
||
6. **7900 是加密打包容器**(`plantai-protected-rag-1`,镜像 `plantai-rag-protected:1.0.0`),其 `/api/v1/kg/*` 路由指向空的 `plantai-protected-neo4j-1`(0 节点),kg/stats 全零、kg/query 空结果——**7900 的 kg 路由目前实质不可用**。其 methodology 路由可用但数据为空。
|
||
|
||
---
|
||
|
||
## 2. Neo4j 实例探测
|
||
|
||
### 2.1 对比表
|
||
|
||
| 属性 | `neo4j-plant-srt-pc2025-v3-20260817-normalized` | `neo4j-plant-srt-direct-v1-full` | `plantai-protected-neo4j-1` |
|
||
|---|---|---|---|
|
||
| bolt | 127.0.0.1:19788 | 127.0.0.1:18788 | 127.0.0.1:17687 |
|
||
| http | 127.0.0.1:19575 | 127.0.0.1:18575 | 127.0.0.1:17474 |
|
||
| 镜像 | neo4j:5.15.0-community | neo4j:5.15.0-community | neo4j:5.15.0-community |
|
||
| 用户名/密码 | neo4j / `<normalized-neo4j-password-in-.env>` | neo4j / `<neo4j-password-in-.env>`(容器 NEO4J_AUTH 原始值为 `password`,运行中已被改) | neo4j / `test1234` |
|
||
| 数据卷 | `/home/xzq/phase2b-5090-staging-20260823T191150Z/plant_srt_pc2025_merge_20260817_v3_normalized/databases/neo4j/data` | `/home/xzq/home/wutx/gene-family-mas-v2/data/neo4j_plant_srt_direct_v1_docker/data` | docker 匿名卷 `/var/lib/docker/volumes/68af.../` + `/home/xzq/5090/PlanAI-cooperate/hsj-workspace/encryption-test/.../service_data/neo4j` |
|
||
| heap 设置 | initial 16G / max 32G / pagecache 64G | initial 4G / max 12G / pagecache 24G | 无自定义(默认) |
|
||
| 标签 | `Entity`(6,316,654), `Paper`(96,648) | `SRT2CanonicalEntity`(3,820,996), `SRT2CanonicalAssertion`(8,246,875), `SRT2Paper`(31,207) | **空库(0 节点)** |
|
||
| 关系类型 | `ASSERTS`(12,963,472), `SUPPORTED_BY`(13,012,368) | `SRT2_CANONICAL_ASSERTS`, `SRT2_SUPPORTED_BY`(合计 16,449,159) | 无 |
|
||
| 名字索引 | 无 name_norm 索引(CONTAINS 全扫 0.19s;name_norm 等值 6.81s——**很慢**) | `srt2_canonical_entity_name_norm` RANGE 索引(等值 0.10s / 前缀 0.09s) | 无 |
|
||
| 全文索引 `entity_name_ftx` | **不存在** | **不存在** | 不存在 |
|
||
| QA 7920 是否使用 | 否 | **是(bolt://127.0.0.1:18788)** | 否 |
|
||
| 上游所属 | normalized 版(phase2b staging) | gene-family-mas-v2 直接版(QA 生产) | 加密保护产品线(空) |
|
||
|
||
### 2.2 节点与关系真实属性
|
||
|
||
**direct-v1-full(当选实例)**
|
||
|
||
- `SRT2CanonicalEntity` 节点属性:`entity_type`(gene/gene_family/phenotype/process/protein/experimental_material/method/compound/sequence_feature/genotype/trait/… 共 24+ 类)、`canonical_id`(`cent_*`)、`name`、`name_norm`(小写规范化)、`rule`(如 `exact_name_norm_same_type`、`alias_config_exact`)、`support_count`。
|
||
- `SRT2CanonicalAssertion` 节点属性(BFF 证据核心,样例见下):
|
||
`assertion_id`(`cass_*`)、`source`、`source_type`、`source_canonical_id`、`target`、`target_type`、`target_canonical_id`、`relation_norm`、`relation_category`、`best_evidence`、`best_paper_id`、`best_score`、`support_count`、`paper_count`、`title`、`doi`、`pmid`、`publication_year`、`journal`。
|
||
- `SRT2_CANONICAL_ASSERTS` 关系属性:`assertion_id`、`best_score`、`relation_category`、`relation_norm`、`support_count`、`paper_count`。
|
||
- `SRT2_SUPPORTED_BY` 关系:**无属性**(`{}`)。
|
||
- `SRT2Paper` 节点属性:`paper_id`、`title`、`doi`、`pmid`、`journal`、`publication_year`、`metadata_lookup_status`、`metadata_sources`、`metadata_checked_at`。
|
||
- 数据库列表:仅 `neo4j`(默认库)+ `system`。
|
||
|
||
**normalized(备选实例)**
|
||
|
||
- `Entity`:`entity_type`、`name`、`name_norm`、`canonical_id`、`layer`。
|
||
- `ASSERTS` 关系属性:仅 `source_system`、`assertion_id`、`relation_category`、`relation_norm`、`layer`(**没有 evidence/pubmed/paper_id/confidence 等属性**,证据信息挂在 `SRT2CanonicalAssertion` 同构的节点/或需 join Paper 节点,未深挖)。
|
||
- `SUPPORTED_BY` 关系:`support_id`、`assertion_id`、`layer`。
|
||
|
||
> 任务书预期的 `evidence/section/pubmed_id/paper_id/confidence/claim_scope/output_layer` 属性在**两个实例的关系上都未出现**;这些字段实际出现在 QA 服务返回的 `sources[].raw` 里(QA 服务在应用层拼装),图库关系本身不携带。
|
||
|
||
### 2.3 选型理由(当选:`neo4j-plant-srt-direct-v1-full`)
|
||
|
||
1. **权威性**:QA 7920 服务(产生可用的图谱证据)的进程环境明确指向 `bolt://127.0.0.1:18788`(= direct-v1-full)。BFF 直接复用该实例能保证与 QA 检索结果一致。
|
||
2. **schema 匹配**:QA 服务的 Cypher(`direct_flow_retriever.py`、`graph_path_chain.py` 等)全部使用 `SRT2Canonical*` 标签,只存在于 direct 实例。
|
||
3. **检索性能**:名字检索走 `name_norm` RANGE 索引,等值 0.10s / 前缀 0.09s;canonical_id 一跳扩展 0.16s。normalized 实例无 name_norm 索引(等值 6.81s),不适合交互式 BFF。
|
||
4. **数据规模**:实体 382 万 + 断言 824 万 + 边 1644 万,远大于 protected(空)。
|
||
5. **normalized 不满足** `entity_name_ftx` 要求(两库都没有该索引);`Entity` 标签虽存在且更大(631 万),但 QA 不用它,且其关系无证据属性。
|
||
|
||
**回退顺序**:① direct-v1-full(首选)→ ② normalized(`neo4j/<normalized-neo4j-password-in-.env>`,bolt 19788,schema 不同,需单独的 Cypher 适配层)→ ③ protected(空库,仅在需要读保护线数据时用,密码 `test1234`,bolt 17687)。
|
||
|
||
### 2.4 三条可用的 BFF Cypher(已对当选实例实测)
|
||
|
||
**(a) 实体名检索(精确 + 前缀,走 name_norm 索引)**
|
||
|
||
```cypher
|
||
MATCH (e:SRT2CanonicalEntity)
|
||
WHERE e.name_norm = $q_norm OR e.name_norm STARTS WITH $q_norm
|
||
RETURN e.canonical_id, e.name, e.entity_type, e.support_count
|
||
LIMIT 20
|
||
```
|
||
参数:`q_norm = toLower(用户输入)`。实测 0.09s。(模糊检索可加 `CONTAINS`,但注意 CONTAINS 不走索引;替代方案是先 `STARTS WITH` 取候选再应用层过滤。)
|
||
|
||
**(b) 获取单个实体属性**
|
||
|
||
```cypher
|
||
MATCH (e:SRT2CanonicalEntity {canonical_id: $canonical_id})
|
||
RETURN e {.*}
|
||
```
|
||
实测 0.10s(canonical_id 有唯一约束索引 `srt2_canonical_entity_id`)。名字定位:`MATCH (e:SRT2CanonicalEntity {name_norm: $name_norm}) RETURN e LIMIT 5`。
|
||
|
||
**(c) 有界邻域扩展(深度 N、节点/边上限,一跳实测 0.16s)**
|
||
|
||
```cypher
|
||
MATCH (s:SRT2CanonicalEntity {canonical_id: $seed_id})
|
||
OPTIONAL MATCH (s)-[r1:SRT2_CANONICAL_ASSERTS]-(n1:SRT2CanonicalEntity)
|
||
WITH s, r1, n1
|
||
ORDER BY coalesce(r1.paper_count,0) DESC, coalesce(r1.support_count,0) DESC
|
||
WITH s, collect(DISTINCT n1)[..$max_nodes] AS level1, collect(DISTINCT r1)[..$max_edges] AS edges1
|
||
OPTIONAL MATCH (n1)-[r2:SRT2_CANONICAL_ASSERTS]-(n2:SRT2CanonicalEntity)
|
||
WHERE n1 IN level1
|
||
WITH s, level1, edges1,
|
||
collect(DISTINCT n2)[..$max_nodes] AS level2,
|
||
collect(DISTINCT r2)[..$max_edges] AS edges2
|
||
RETURN s {.*} AS start,
|
||
[n IN (level1 + level2) | n {.*}] AS nodes,
|
||
[r IN (edges1 + edges2) | r {.*}] AS edges
|
||
```
|
||
要点:每跳分别 cap 并 `ORDER BY paper_count DESC` 优先取高质量边;`OPTIONAL MATCH` 保证孤立节点不丢;深度 >2 时按同模式追加。注意 `[...]` 截取语法在 cap 前的排序至关重要,否则超度节点(hub)会吃满预算。一跳带全属性实测 0.16s,两跳约 13s(可接受,但建议 BFF 先只做一跳 + 按需第二跳)。
|
||
|
||
---
|
||
|
||
## 3. 抽取接口真实结构(`http://127.0.0.1:8000`,fallback `7900`)
|
||
|
||
服务由 `/home/xzq/5090/PlantAI-rag/scripts/start_methodology_api_8000.sh` 启动:conda `gfpy312`,工作目录 `/home/xzq/5090/PlantAI-rag`,`uvicorn api.main:app --host 0.0.0.0 --port 8000`。启动脚本自带 health 检查和 PID 文件(`runtime/methodology_api/methodology_api_8000.pid`)。当前存活,**不要重启**。
|
||
|
||
### 3.1 `GET /api/v1/methodology/extract-jobs`(及 `?limit=N`)
|
||
|
||
响应形状:`{"jobs": [...], "count": N}`(`limit` 默认 50;`?limit=5` 会截断 jobs 数组,count 仍是截断后的条数)。item 字段(全部实测出现):
|
||
|
||
| 字段 | 类型 | 说明/示例 |
|
||
|---|---|---|
|
||
| `job_id` | str | 12 位 hex,如 `2943168e9c48` |
|
||
| `status` | str | 枚举:`queued` / `running` / `completed` / `failed`(磁盘上 49 个任务只有 completed 22 + failed 27) |
|
||
| `stage` | str | 与 status 同步:`queued` / `mineru` / `llm` / `completed` / `failed` |
|
||
| `substage` | str | completed 时为 `done`,failed 时为 null |
|
||
| `message` | str | 中文进度描述 |
|
||
| `updated_at` | str | `2026-08-07T09:42:17`(无时区) |
|
||
| `paper_id` / `family` | str | 如 `demo_paper` / `""` |
|
||
| `source_filename` / `source_path` | str | 上传文件名与绝对路径 |
|
||
| `output_dir` / `batch_dir` | str | 结果目录 |
|
||
| `stage_count` / `species_count` / `figure_table_caption_count` / `figure_table_stage_count` | int | 提取统计 |
|
||
| `config_url` | str | `/api/v1/methodology/extract-jobs/{id}/bbav5-config` |
|
||
| `methodology_plan_url` | str | `/api/v1/methodology/extract-jobs/{id}/plan` |
|
||
| `methodology_sandbox_requested` | bool | |
|
||
| `methodology_sandbox_status` / `_dir` / `_registry` / `_collection` | str | 沙箱相关 |
|
||
|
||
### 3.2 `GET /api/v1/methodology/extract-jobs/{job_id}`
|
||
|
||
单个 job 的扁平 JSON(无包裹):与列表 item 同字段 + 额外 `content_list`(mineru 结果路径)、`figure_table_files`(object,含 `figure_table_inventory`/`figure_table_inventory_csv`/`figure_table_audit`/`reproduction_plan_preview` 四个路径)、`figure_table_warning`、`figure_table_inventory_url`、`reproduction_plan_preview_url`、`log_path`(failed 时)。样例(`2943168e9c48`,已截断):
|
||
|
||
```json
|
||
{"updated_at":"2026-08-07T09:42:17","job_id":"2943168e9c48","status":"completed","stage":"completed","substage":"done","message":"MinerU+LLM 方法学提取完成","source_path":"/home/xzq/5090/PlantAI-rag/data/evaluation/methodology_upload_jobs/2943168e9c48/upload/wang2019.pdf","content_list":".../mineru/wang2019/txt/wang2019_content_list.json","output_dir":".../methodology_batch_demo_paper_2943168e9c48","paper_id":"demo_paper","family":"","stage_count":6,"species_count":1,"figure_table_caption_count":9,"figure_table_stage_count":12,"figure_table_warning":"","figure_table_files":{...},"config_url":"...","methodology_plan_url":"...","figure_table_inventory_url":"...","reproduction_plan_preview_url":"..."}
|
||
```
|
||
未完成时(非 completed)访问 `bbav5-config`/`plan` 会返回 **409** + `{"detail":"Extraction job is not completed: ..."}`;job 不存在返回 404。
|
||
|
||
### 3.3 `GET /api/v1/methodology/extract-jobs/{job_id}/plan`
|
||
|
||
顶层:`plan_id`、`paper_id`、`gene_family`、`source_batch_dir`、`stages[]`。每个 stage 含:
|
||
`observation_id`、`literature_stage`(如 `gene_family_identification`)、`literature_tools[]`(`tool_name/version/role/url/parameters`)、`method_components[]`(`component_type/tool/tools/parameters/evidence_sentence`)、`literature_parameters[]`(`component_type/component_tool/parameter_name/parameter_value/parameter_type/evidence_sentence`)、`inputs[]`、更多字段被截断。这是执行计划的完整结构,BFF 的 plan 视图可直接透传。
|
||
|
||
### 3.4 `processing-status` / `progress` / `summary` / `run-log`
|
||
|
||
| 接口 | 实测响应 | Content-Type |
|
||
|---|---|---|
|
||
| `GET .../processing-status` | `{"rows":[]}` | JSON |
|
||
| `GET .../progress` | `{"rows":[]}` | JSON(正常时 rows 为 progress.jsonl 的逐行 JSON 对象) |
|
||
| `GET .../summary` | `{"rows":[]}` | JSON(rows 为 summary.csv 的 dict 行) |
|
||
| `GET .../run-log` | `{"text":""}` | JSON(**不是文本流**;text 内是日志文件原文) |
|
||
|
||
**空的原因是** `BATCH_DIR_NAME` 默认 `methodology_batch_llm`(目录不存在)。8000 进程环境里没有 `METHODOLOGY_BATCH_DIR` 覆盖。若 BFF 需要这些接口有数据,须用 `METHODOLOGY_BATCH_DIR=methodology_batch_demo_paper_*` 之类实际存在的目录重启服务——**此动作需团队决策,本探测未执行**。
|
||
|
||
### 3.5 `GET /api/v1/methodology/sandbox/example-batches`
|
||
|
||
```json
|
||
{"success":true,"sandbox_root":"/home/xzq/5090/PlantAI-rag/data/evaluation/methodology_qa_sandbox","batches":[{"name":"methodology_batch_Ft_spl","path":"/home/xzq/5090/PlantAI-rag/methodology_batch_Ft_spl","has_plan":false,"has_preview":false},{"name":"methodology_batch_pecan_spl",...},{"name":"methodology_batch_sunflowers_spl",...}]}
|
||
```
|
||
|
||
### 3.6 `POST /api/v1/methodology/extract-upload`(未实际上传,来源:OpenAPI + 源码)
|
||
|
||
multipart/form-data,**必填字段仅 `file`**:
|
||
|
||
| 字段 | 类型 | 默认 | 说明 |
|
||
|---|---|---|---|
|
||
| `file` | UploadFile | (必填) | PDF 或 `*_content_list.json` |
|
||
| `paper_id` | str(form) | `uploaded_paper` | 只保留 `[0-9A-Za-z._-]`,否则替换为 `_` |
|
||
| `family` | str(form) | `""` | |
|
||
| `output_name` | str(form) | `""` | 输出目录名基名,最终为 `{output_name}_{job_id}` |
|
||
| `llm_model` | str(form) | `deepseek-v4-flash` | |
|
||
| `llm_request_timeout` | int(form) | `75` | 秒 |
|
||
| `sandbox` | bool(form) | `false` | |
|
||
| `sandbox_run_id` | str(form) | `""` | |
|
||
|
||
成功响应:`{"success": true, "job_id": "<12hex>", "status_url": "/api/v1/methodology/extract-jobs/<job_id>"}`。任务在 FastAPI BackgroundTasks 中异步执行;状态流转:`queued` →(MinerU)`running/stage=mineru` →(LLM 提取)`running/stage=llm` → `completed`(含 `config_url`/`methodology_plan_url`/统计字段/沙箱字段)或 `failed`(`message` 为异常文本,含 `log_path`)。失败样例原因:MinerU 路径不存在(`/home/xia-lab/miniconda3/envs/minerupy311/bin/mineru`)——历史 27 个 failed 任务多为这种环境问题。
|
||
|
||
### 3.7 7900 上的同构接口
|
||
|
||
7900(容器 `plantai-protected-rag-1`)暴露同样的 `/api/v1/methodology/*` 路由(51 条路径,`extract-upload`/`extract-jobs` 均存在),但 `extract-jobs` 返回 `{"jobs":[],"count":0}`(容器内数据目录独立)。另有 `/api/v1/kg/*`(stats/families/species/query/search)指向空 Neo4j,**全部为空结果**,BFF 不应依赖 7900 的 kg 路由。源码在容器内是编译过的 `.so`(`api/kg_routes.cpython-311-x86_64-linux-gnu.so`),无法读源码,以 OpenAPI + 实测为准。
|
||
|
||
---
|
||
|
||
## 4. QA 服务响应结构(`http://127.0.0.1:7920`)
|
||
|
||
服务:`uvicorn scripts.qa_v1_1_73_server:app`,app-dir `/home/xzq/5090/PlanAI-cooperate/RAG/rag-qa-v1_1_73`,conda `gfpy312`,版本 `1.1.73-assertion-anchored`。启动脚本:`docs/legacy_startup_scripts/start_qa_v1_1_73_*.sh`(注意 legacy 脚本里写的 NEO4J_URI 是 17687,**与运行中进程的 18788 不一致**,以进程环境为准)。LLM:`https://api.deepseek.com` + `deepseek-v4-flash`,**当前 402 Insufficient Balance**。
|
||
|
||
### 4.1 `POST /api/v1/qa-v1-1-73/search`(实测 2026-08-25,1.78MB 响应,329 sources)
|
||
|
||
**顶层键完整清单(31 个)**:
|
||
|
||
| 键 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `success` | bool | true |
|
||
| `version` | str | `"1.1.73"` |
|
||
| `query_id` | str | `"20260825_000715_49f801a9"` |
|
||
| `question` | str | 原问题 |
|
||
| `answer` | str | retrieval-only 时为空串 |
|
||
| `citation_validation` | dict | `{valid, cited_pmids[], unknown_pmids[]}` |
|
||
| `sources` | list[329] | 证据条目(见下) |
|
||
| `source_count` | int | 329 |
|
||
| `evidence_chain_top30` | list[30] | 与 sources 同构(top30 精选) |
|
||
| `provisional_answer` | str | 空 |
|
||
| `retrieval_hypothesis` | dict | `{question_type, direct_question_entities[], hypothesized_entities[], relation_intents[], concept_queries[], answer_slots[], atomic_claims[], negative_constraints[], parse_status}` |
|
||
| `query_plan` | dict | `{queries{}, alias_audit{}, agentic_plan{14}, retrieval_options{29}}` |
|
||
| `retrieval_audit` | dict | `{qdrant[], seed_extraction{}, neo4j[], dedup{}, options{}, neo4j_status:"enabled", bounded_graph_backend{12}, public_citation_filter{}}` |
|
||
| `graph_evidence_quota_audit` | dict | `{policy, top_k_for_llm, graph_min_requested, graph_candidates_available, non_graph_candidates_available, graph_selected, non_graph_selected, graph_quota_satisfied, note}` |
|
||
| `graph_knowledge_chains` | dict | `{mode:"neo4j_native_path", chain_policy, chains[305], chain_count, audit{35}, summary{note, used_for_answer_generation}}` |
|
||
| `native_graph_chains` | list[305] | 图链(见下) |
|
||
| `native_graph_chain_audit` | dict | 35 个审计键(enabled/chain_source/max_hops/beam_width/top_k_chains/seed_ids/…) |
|
||
| `assertion_anchored_graph_chains` | list | 本次为 `[]` |
|
||
| `assertion_anchored_graph_audit` | dict | `{enabled, status, error, fallback_required, hop_policy}` |
|
||
| `endpoint_path_audit` | dict | `{enabled:false, status:"not_attempted", fallback_to_native_seed_expansion:false}` |
|
||
| `native_seed_policy_audit` | dict | 20 键(policy/seed_top_k_after_bge/canonical_ids/names/…) |
|
||
| `agentic_controller_audit` | dict | `{enabled, status, strict_review_accepted, fallback_reason, attempt_count, replan_count, attempts[], final_plan{}}` |
|
||
| `agentic_review` | dict | `{decision, accepted_evidence_ids[], accepted_chain_ids[], problems[], final_handoff, strict_review_decision, review_fallback_used, fallback_reason}` |
|
||
| `question_decomposition` | dict | search 时为 `{}` |
|
||
| `runtime_recovery_audit` | list | 每次 LLM 失败一条:`{stage, mode, degraded:true, error}` |
|
||
| `degraded_execution` | bool | **true**(LLM 402) |
|
||
| `subquestion_evidence_groups` | list | `[]`(search 时) |
|
||
| `subquestion_retrieval_audit` | list | `[]` |
|
||
| `cluster_audit` | list[106] | `{cluster_id, cluster_key[], representative_assertion_id, representative_srt{source,relation,target}, member_count, member_assertion_ids[], member_paper_ids[], ...}` |
|
||
| `rerank_audit` | list[80] | `{rank, evidence_id, source, relation, target, rrf_score, bge_score, final_score}` |
|
||
| `timings` | dict | 秒,float:`{provisional_answer, structured_planner, question_decomposition, agentic_retrieval_plan, retrieval, cluster_bge_rerank_and_select, native_graph_chain_retrieval, final_answer, total}`(本次 total 91.9s) |
|
||
| `flow` | list[17] | 管道阶段名有序列表 |
|
||
|
||
**一条 `sources[]` 的全字段(26 个键,S1 实例)**:
|
||
|
||
| 键 | 类型 | 示例值 |
|
||
|---|---|---|
|
||
| `evidence_id` | str | `"S1"` |
|
||
| `kb` | str | `"V16/V15"` |
|
||
| `source` | str | `"SPL gene family"` |
|
||
| `relation` | str | `"characterized_in"` |
|
||
| `target` | str | `"Oryza sativa"` |
|
||
| `evidence` | str | markdown 段落(`## Phylogenetic analysis of the PeSPL genes ...`,可长) |
|
||
| `paper_id` | str | `"PMC5488377_12864_2017_Article_3882"` |
|
||
| `title` | str | 论文标题 |
|
||
| `pmid` | str | `"28655295"` |
|
||
| `pmcid` | str | `"PMC5488377"` |
|
||
| `doi` | str | `"10.1186/s12864-017-3882-4"` |
|
||
| `species` | str | 常为空串 |
|
||
| `section` | str | 常为空串 |
|
||
| `output_layer` | str | `"main_kg"` |
|
||
| `claim_scope` | str | 常为空串 |
|
||
| `relation_id` | str | `"cass_d12f62f9abffbd903b97"`(= assertion_id) |
|
||
| `retrieval_methods` | list[str] | `["qdrant_vector"]` |
|
||
| `retrieval_queries` | list[str] | 3 条查询串 |
|
||
| `vector_score` | float | 0.714 |
|
||
| `rrf_score` | float | 1.114 |
|
||
| `rerank_score` | float | 0.989 |
|
||
| `final_score` | float | 0.982 |
|
||
| `cluster_id` | str | `"clu_0f8da21642adc4f0"` |
|
||
| `cluster_member_count` | int | 3 |
|
||
| `cluster_member_assertion_ids` | list[str] | 3 个 cass_* |
|
||
| `cluster_member_paper_ids` | list[str] | 2 个 |
|
||
| `cluster_member_pmids` | list[str] | 1 个 |
|
||
| `raw` | dict | 28 键,完整断言原样:`kb_version, source_system, assertion_id, relation_id, source, source_type, source_canonical_id, relation, relation_norm, relation_category, target, target_type, target_canonical_id, evidence, best_evidence, paper_id, best_paper_id, support_count, paper_count, quality_score, best_score, embedding_text, cluster_id, cluster_key[], cluster_member_assertion_ids[], cluster_member_count, cluster_member_paper_ids[], cluster_member_pmids[]` |
|
||
|
||
**`native_graph_chains[]` item**:`{chain_id:"G1", chain_source:"neo4j_native_path", hop_count:3, path_score:0.861, start:"SPL gene", end:"18 SPL genes in rice", bridge_entities[], hops[], score_breakdown{22}}`。
|
||
**hop**:`{hop_index, from_id, from_name, to_id, to_name, source, relation, target, source_canonical_id, target_canonical_id, source_type, target_type, relation_category, assertion_id, paper_id, title, pmid, pmcid, doi, species, evidence, support_count, paper_count, best_score, edge_score, score_breakdown, passive_relation, structural_direction, semantic_direction}`。
|
||
|
||
### 4.2 `POST /api/v1/qa-v1-1-73/chat/stream` SSE 实测
|
||
|
||
帧格式:`event: <name>` + `data: <JSON>` 两行一组,空行分隔;期间有 `: keepalive` 注释帧(实测 2 次)。
|
||
|
||
**有序 stage 序列(data.stage,五阶段 UI 映射基准)**:
|
||
|
||
1. `understanding_started` — details `{}`
|
||
2. `entities_identified` — details `{entities:["SPL gene family"], question_type:"raw_question"}`
|
||
3. `related_search_started` — details `{}`
|
||
4. `concepts_found` — details `{concepts[], concept_count:250, connection_count:335, publication_count:109, candidate_count:328}`
|
||
5. `subquestion_retrieved` — details `{subquestion_id:"Q0", attempt:1, candidate_count:30, connection_count:305}`
|
||
6. `agent_review_started` — details `{attempt:1}`
|
||
7. `evidence_accepted` — details `{concepts[], concept_count, connection_count, publication_count, accepted_count:30}`
|
||
8. `answer_generation_started` — details `{}`
|
||
9. `completed` — details `{elapsed_seconds:38.357}`
|
||
|
||
**终端帧**:`event: complete` + `data: <完整 JSON>`(与 search 响应同构,约 2.37MB;顶层键同 search 但 `citation_validation` 12 键、`sources` 仅 4 条、`timings` 10 键、`question_decomposition` 13 键、`subquestion_evidence_groups` 1 项、`agentic_controller_audit` 12 键、`agentic_review` 7 键)。**LLM 402 影响**:`answer` 为 fallback 文案 `"The retrieval pipeline completed. The answer model did not return usable text; the most relevant retrieved evidence facts are: - SPL gene family has domain SBP box [PMID: 33234605] ..."`(事实列表而非自然语言答案),`degraded_execution=true`,`runtime_recovery_audit` 4 条 LLM 失败记录。全流程耗时约 37–38s(不带 keepalive 间隙)。
|
||
|
||
**health**:`/api/v1/qa-v1-1-73/health` → `{"status":"ok","service":"qa_v1_1_73","version":"1.1.73-assertion-anchored"}`。
|
||
**info**:返回服务名、管道描述、config(alias_path/taxonomy_path/reranker 模型路径/knowledge_chain_defaults 等)。
|
||
其他路由:`/chat`(非流式)、`/search`。
|
||
|
||
---
|
||
|
||
## 5. 环境与启动脚本
|
||
|
||
### 5.1 `/home/xzq/5090/PlantAI-rag/scripts/` 清单(15 个)
|
||
|
||
| 脚本 | 用途(据头部注释/内容) |
|
||
|---|---|
|
||
| `download_marker_models.sh` | 手动下载 marker-pdf 模型(解决自动下载中断) |
|
||
| `organize_project.sh` | gene-family-mas-v2 项目文件整理(建目录结构) |
|
||
| `process_all_pdfs.sh` | 批量处理 `gfpaper` 目录 PDF |
|
||
| `process_by_inode_shell.sh` | 用 inode 处理乱码文件名 PDF → rag_index_v3 |
|
||
| `process_failed_by_inode.sh` | 用 inode 重处理 failed_to_process 目录 → rag_index_v4 |
|
||
| `run_v15_3_4_q1_5papers_smoke_20260604.sh` | V15.3.4 Q1 5 篇论文冒烟测试(gfpy312) |
|
||
| `run_v15_3_4_q1_remaining_500_20260604.sh` | V15.3.4 Q1 剩余 500 篇批量(加载 .env.v15_deepseek) |
|
||
| `run_v16_rerun6_20260625.sh` | V16 batch10 重跑 6(/data/gene-family-mas-v2) |
|
||
| `start_dual_kb_qa_api_7902.sh` | 双 KB QA API 7902(/data/gene-family-mas-v2) |
|
||
| `start_dual_kb_qa_api_8000.sh` | **历史名**;实际启动 `combined_qa_lightrag_keyword_server` 于 **7905**(V15+PC Qdrant 检索) |
|
||
| `start_methodology_api_8000.sh` | **当前 8000 的启动脚本**(见 5.2) |
|
||
| `start_mineru_api_50215_20260605.sh` | MinerU API 50215 |
|
||
| `start_qa_v1_0_0_7908.sh` | QA v1.0.0 7908 |
|
||
| `start_taxonomy_bge_unified_7907.sh` | taxonomy+BGE 统一服务 7907 |
|
||
| `start-webui.sh` | WebUI(端口 8787,state 在 ~/.hermes/webui-mas-v2) |
|
||
|
||
### 5.2 三个上游服务
|
||
|
||
| 服务 | 端口 | 启动方式 | conda / 工作目录 | 重启安全性 |
|
||
|---|---|---|---|---|
|
||
| QA v1.1.73(graph QA) | 7920 | `python -m uvicorn scripts.qa_v1_1_73_server:app --app-dir /home/xzq/5090/PlanAI-cooperate/RAG/rag-qa-v1_1_73 --host 127.0.0.1 --port 7920`(PID 2586988,父进程 1 = 守护化;legacy 脚本在 `rag-qa-v1_1_73/docs/legacy_startup_scripts/`,其硬编码 URI 17687 已过时,**不能照抄**) | `gfpy312`;环境来自 `RAG/runtime/qa_v1_1_73.env` + 进程内联 env(`NEO4J_URI=bolt://127.0.0.1:18788`、`NEO4J_PASSWORD=<neo4j-password-in-.env>`、`V15_QDRANT_URL=http://127.0.0.1:26333`、collection `plant_srt_direct_v1_bge_m3_20260702`) | 正在服务流量,**未验证重启安全性**;重启前需确认无长任务依赖(LLM 目前 402 已降级,重启不影响数据) |
|
||
| Methodology API | 8000 | `/home/xzq/5090/PlantAI-rag/scripts/start_methodology_api_8000.sh`(脚本自带 health 检查 + 幂等启动,health 通过则直接退出) | `gfpy312`;工作目录 `/home/xzq/5090/PlantAI-rag`;日志 `runtime/methodology_api/methodology_api_8000.log` | 脚本幂等、支持 `METHODOLOGY_API_PORT`/`METHODOLOGY_BATCH_DIR` 覆盖;停止后重跑脚本即可。**当前别重启**(本探测依赖其持续在线) |
|
||
| Protected RAG | 7900 | Docker 容器 `plantai-protected-rag-1`(镜像 `plantai-rag-protected:1.0.0`,compose:`hsj-workspace/encryption-test/server/protected_docker_packager/docker-compose.yml`),同一 compose 栈含 web/workers/redis/qdrant/neo4j 等 8+ 容器 | 容器内 `python -m uvicorn api.app:app`(2 workers),`NEO4J_URI=bolt://neo4j:7687`(compose 内部) | 容器健康检查通过;其 kg 路由数据为空(protected Neo4j 空库),**BFF 不应依赖** |
|
||
|
||
### 5.3 其他环境事实
|
||
|
||
- 端口 8090、5180:`ss -tln` 无监听 → **空闲可用**。
|
||
- `node -v` = v18.19.1,`npm -v` = 9.2.0;`npm ping` PONG 573ms → Playwright chromium 下载可行(约 150MB,未实际执行)。
|
||
- Qdrant 端口映射:QA 用 `qdrant-qa-v1-1-73-full` 26333;normalized 用 `qdrant-plant-srt-pc2025-v3-20260817-normalized` 27333;protected 用 `plantai-protected-qdrant-1` 16333。
|
||
- 全部 docker 容器(13 个)状态 Up,无异常退出。
|
||
|
||
---
|
||
|
||
## 6. 遗留问题与风险
|
||
|
||
1. **QA LLM 余额不足(最重要风险)**:DeepSeek API 402 Insufficient Balance。所有 LLM 阶段(planner/agentic/review/answer)降级为 deterministic recovery。**chat/stream 目前无法产出自然语言答案**(只有证据列表 fallback),BFF 五阶段 UI 中"答案生成"阶段会看到降级行为。充值时注意:`QA_V1_LLM_BASE_URL=https://api.deepseek.com`,`QA_V1_LLM_MODEL=deepseek-v4-flash`、`QA_V1_FINAL_LLM_MODEL=deepseek-v4-flash`、`QA_V1_LLM_MODEL`(实际 env) = `deepseek-chat` 并存(进程 env 与 runtime env 文件略有差异,未确认哪行最终生效)。
|
||
2. **`entity_name_ftx` 全文索引不存在于任何实例**。若 BFF 必须全文检索,需要团队决策是否创建(会修改共享实例的 schema——本探测未创建任何东西)。
|
||
3. **normalized 实例名字检索慢**(name_norm 无索引,等值 6.81s):若团队将来切到 normalized(`Entity` 标签 631 万),需要先建索引。
|
||
4. **methodology `processing-status`/`progress`/`summary`/`run-log` 当前空数据**:原因是 `METHODOLOGY_BATCH_DIR` 指向不存在的 `methodology_batch_llm` 目录(默认值)。未确认哪个目录名才是"有数据"的正确批次目录(历史任务输出在 `data/evaluation/0505/methodology_batch_demo_paper_*`)。需要读有数据的目录必须重启 8000 并设 env——未执行。
|
||
5. **QA 7920 的正式启动脚本未找到**:只有 legacy 脚本且其中 NEO4J_URI(17687)与运行中进程(18788)矛盾。进程由谁、以何完整 env 启动,未确认。以 `/proc/2586988/environ` 实测为准。
|
||
6. **failed 任务(27 个)失败原因**:主要是 MinerU 二进制路径不存在(`/home/xia-lab/miniconda3/envs/minerupy311/bin/mineru`)。上传新 PDF 是否会再次失败取决于 MinerU 环境是否修复——**未测试实际上传**(按任务要求未执行)。
|
||
7. **7900 的 kg 路由源码不可读**(编译 .so),其 schema 以 OpenAPI + 实测为准;kg 数据为空的原因是 protected Neo4j 空库,后续若保护线灌库,kg 路由可能恢复。
|
||
8. **一次 search 约 92s**(88.8s 在 native_graph_chain_retrieval),stream 约 37s。BFF 需要长超时(>120s)和进度展示;未做并发压测。
|
||
9. **`SSH_CONNECTION` 显示会话来自 192.168.0.142 → 192.168.0.175**:远程机在 192.168.0.175(通过 Tailscale IP 100.109.52.26 可达)。BFF 若部署在远程机上,绑定 127.0.0.1 的端口只能本机访问——BFF 与本机服务同机部署即可;跨机需要另开隧道,未做。
|