- 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>
31 KiB
发现报告 — PlantAI RAG BFF 上游探测
探测日期:2026-08-24 至 2026-08-25(远程机
100.109.52.26,SSH 用户 xzq) 本文件为团队事实基线。所有结构均来自真实探测响应或源码/OpenAPI,不是猜测。 未能确认的事项集中在第 6 节,明确标注,勿当作事实使用。
1. 摘要与关键结论
- Neo4j 选型:
neo4j-plant-srt-direct-v1-full(boltbolt://127.0.0.1:18788,HTTPhttp://127.0.0.1:18575,dbneo4j,用户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_normRANGE 索引(srt2_canonical_entity_name_norm),实测 0.09–0.10s。全文检索需求用STARTS WITH/CONTAINS+ name_norm 索引即可。
- 这是 QA 服务 7920 实际使用的实例(进程
- 抽取接口 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":""}(不是纯文本)。 - 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 的证据输出。 - 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 次)。 - 端口 8090、5180 空闲。node v18.19.1 / npm 9.2.0,
npm ping通(573ms),Playwright chromium 下载可行(约 150MB,未实际下载)。 - 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)
- 权威性:QA 7920 服务(产生可用的图谱证据)的进程环境明确指向
bolt://127.0.0.1:18788(= direct-v1-full)。BFF 直接复用该实例能保证与 QA 检索结果一致。 - schema 匹配:QA 服务的 Cypher(
direct_flow_retriever.py、graph_path_chain.py等)全部使用SRT2Canonical*标签,只存在于 direct 实例。 - 检索性能:名字检索走
name_normRANGE 索引,等值 0.10s / 前缀 0.09s;canonical_id 一跳扩展 0.16s。normalized 实例无 name_norm 索引(等值 6.81s),不适合交互式 BFF。 - 数据规模:实体 382 万 + 断言 824 万 + 边 1644 万,远大于 protected(空)。
- 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 索引)
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) 获取单个实体属性
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)
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,已截断):
{"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
{"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 映射基准):
understanding_started— details{}entities_identified— details{entities:["SPL gene family"], question_type:"raw_question"}related_search_started— details{}concepts_found— details{concepts[], concept_count:250, connection_count:335, publication_count:109, candidate_count:328}subquestion_retrieved— details{subquestion_id:"Q0", attempt:1, candidate_count:30, connection_count:305}agent_review_started— details{attempt:1}evidence_accepted— details{concepts[], concept_count, connection_count, publication_count, accepted_count:30}answer_generation_started— details{}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 pingPONG 573ms → Playwright chromium 下载可行(约 150MB,未实际执行)。- Qdrant 端口映射:QA 用
qdrant-qa-v1-1-73-full26333;normalized 用qdrant-plant-srt-pc2025-v3-20260817-normalized27333;protected 用plantai-protected-qdrant-116333。 - 全部 docker 容器(13 个)状态 Up,无异常退出。
6. 遗留问题与风险
- 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 文件略有差异,未确认哪行最终生效)。 entity_name_ftx全文索引不存在于任何实例。若 BFF 必须全文检索,需要团队决策是否创建(会修改共享实例的 schema——本探测未创建任何东西)。- normalized 实例名字检索慢(name_norm 无索引,等值 6.81s):若团队将来切到 normalized(
Entity标签 631 万),需要先建索引。 - methodology
processing-status/progress/summary/run-log当前空数据:原因是METHODOLOGY_BATCH_DIR指向不存在的methodology_batch_llm目录(默认值)。未确认哪个目录名才是"有数据"的正确批次目录(历史任务输出在data/evaluation/0505/methodology_batch_demo_paper_*)。需要读有数据的目录必须重启 8000 并设 env——未执行。 - QA 7920 的正式启动脚本未找到:只有 legacy 脚本且其中 NEO4J_URI(17687)与运行中进程(18788)矛盾。进程由谁、以何完整 env 启动,未确认。以
/proc/2586988/environ实测为准。 - failed 任务(27 个)失败原因:主要是 MinerU 二进制路径不存在(
/home/xia-lab/miniconda3/envs/minerupy311/bin/mineru)。上传新 PDF 是否会再次失败取决于 MinerU 环境是否修复——未测试实际上传(按任务要求未执行)。 - 7900 的 kg 路由源码不可读(编译 .so),其 schema 以 OpenAPI + 实测为准;kg 数据为空的原因是 protected Neo4j 空库,后续若保护线灌库,kg 路由可能恢复。
- 一次 search 约 92s(88.8s 在 native_graph_chain_retrieval),stream 约 37s。BFF 需要长超时(>120s)和进度展示;未做并发压测。
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 与本机服务同机部署即可;跨机需要另开隧道,未做。