feat(qa): 断言锚定检索 + robustness 加固

- assertion_anchored_graph_retriever 断言锚定候选与 top30 合并
- pipeline/agentic_controller/llm_client 重试与 Q0 软回退
- question_decomposition JSON repair、citation_contract grouped 归一化
- api endpoint_path 全参数、retrieval 禁用 PC/SQLite、canonical-only 校验
- bounded_canonical/direct_flow 白名单、subquestion_orchestrator required_review
- scripts/qa_v1_1_73_server.py 新服务入口(backend_guard + gate_policy)
- 旧 start_qa_v1_1_73_*.sh 移入 docs/legacy_startup_scripts/
This commit is contained in:
potaser
2026-08-29 12:39:25 +08:00
parent fdf24c8ab0
commit 4fef3a65ac
24 changed files with 6145 additions and 510 deletions
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
from __future__ import annotations
import os
import sys
from pathlib import Path
from fastapi import FastAPI
PROJECT_ROOT = Path(os.environ.get("GENE_FAMILY_ROOT", "/data/gene-family-mas-v2"))
GFANALYSIS_ROOT = Path(os.environ.get("GFANALYSIS_ROOT", "/data/wutx/00test/gfAnalysis"))
for root in (PROJECT_ROOT, GFANALYSIS_ROOT):
value = str(root)
if value not in sys.path:
sys.path.insert(0, value)
from src.rag.qa_v1_1_73.api import router
from src.rag.qa_v1_1_73.backend_guard import validate_backends
from src.rag.qa_v1_1_73.soft_gate_policy import gate_policy
app = FastAPI(
title="Plant Biology QA V1.1.73",
version="1.1.73",
description=(
"QA V1.1.73: graph-balanced top30 plus cascaded two-hop native Neo4j path chains. The top30 context keeps "
"at least 15 graph-derived evidence items when available, and sends "
"native graph chains as a separate output. Chat composes a validated final LLM answer; "
"retrieval-only search returns evidence without an answer."
),
)
app.include_router(router)
@app.on_event("startup")
def validate_production_backends() -> None:
app.state.kb_backend_identity = validate_backends()
@app.get("/health")
def health():
return {
"status": "ok",
"service": "qa_v1_1_73",
"version": "1.1.73-assertion-anchored",
"gate_policy": gate_policy(),
"backend": getattr(app.state, "kb_backend_identity", None),
}
-56
View File
@@ -1,56 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT=/home/xzq/5090/PlanAI-cooperate/RAG/rag-qa-v1_1_73
PRIVATE_ENV=/home/xzq/5090/PlantAI-rag/.env
RUNTIME_ENV=/home/xzq/5090/PlanAI-cooperate/RAG/runtime/qa_v1_1_73.env
cd /home/xzq/5090/PlanAI-cooperate/RAG/rag-qa-v1_1_73
if [[ -f "$PRIVATE_ENV" ]]; then
set -a
source "$PRIVATE_ENV"
set +a
fi
if [[ -f "$RUNTIME_ENV" ]]; then
set -a
source "$RUNTIME_ENV"
set +a
fi
export GENE_FAMILY_ROOT="$ROOT"
export GFANALYSIS_ROOT="${GFANALYSIS_ROOT:-/data/wutx/00test/gfAnalysis}"
# These addresses are intentionally fixed so a private .env cannot silently
# reconnect this isolated QA runtime to the pre-existing remote databases.
export NEO4J_URI=bolt://127.0.0.1:17687
export V15_QDRANT_URL=http://127.0.0.1:16333
export PC_QDRANT_URL=http://127.0.0.1:16333
export PC_NEO4J_HTTP_URL=http://127.0.0.1:17474/db/neo4j/tx/commit
export V15_QDRANT_COLLECTION=plant_srt_direct_v1_bge_m3_20260702
export PC_QDRANT_COLLECTION=pc_srt_bge_full_20260620
export QA_V1_GRAPH_SCHEMA=legacy
export QA_ENABLE_QUESTION_DECOMPOSITION=1
export QA_PAPER_METADATA_REGISTRY="${QA_PAPER_METADATA_REGISTRY:-$ROOT/data/knowledge_base/paper_metadata_registry_v1_20260717/paper_metadata_registry_full.jsonl}"
export QA_V1_BGE_RERANKER_MODEL="${QA_V1_BGE_RERANKER_MODEL:-/home/xzq/5090/PlantAI-rag/bge-reranker-base}"
export QA_V1_BGE_DEVICE="${QA_V1_BGE_DEVICE:-cuda}"
export QA_V1_LLM_TIMEOUT="${QA_V1_LLM_TIMEOUT:-180}"
export QA_V1_SUBQUESTION_WORKERS="${QA_V1_SUBQUESTION_WORKERS:-3}"
export QA_V1_VECTOR_QUERY_WORKERS="${QA_V1_VECTOR_QUERY_WORKERS:-2}"
export QA_V1_ENABLE_PROVISIONAL_DRAFT="${QA_V1_ENABLE_PROVISIONAL_DRAFT:-0}"
export QA_V1_MAX_ROUNDS="${QA_V1_MAX_ROUNDS:-1}"
export QA_V1_ENABLE_AGENTIC_CONTROLLER="${QA_V1_ENABLE_AGENTIC_CONTROLLER:-1}"
export QA_V1_AGENTIC_MAX_REPLANS="${QA_V1_AGENTIC_MAX_REPLANS:-2}"
export PC_NEO4J_USER="${PC_NEO4J_USER:-${NEO4J_USER:-neo4j}}"
export PC_NEO4J_PASSWORD="${PC_NEO4J_PASSWORD:-${NEO4J_PASSWORD:-password}}"
export LD_LIBRARY_PATH="/home/xzq/miniconda3/envs/gfpy312/lib:${LD_LIBRARY_PATH:-}"
export PYTHONPATH="$ROOT:$GFANALYSIS_ROOT"
exec /home/xzq/miniconda3/envs/gfpy312/bin/python -m uvicorn \
scripts.qa_v1_1_73_server:app \
--host 127.0.0.1 \
--port 7925
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
cd /data/gene-family-mas-v2
if [[ -f .env ]]; then
set -a
source .env
set +a
fi
source /data/miniconda3/etc/profile.d/conda.sh
conda activate gfpy312
export GENE_FAMILY_ROOT=/data/gene-family-mas-v2
export GFANALYSIS_ROOT=/data/wutx/00test/gfAnalysis
export V15_QDRANT_URL="${V15_QDRANT_URL:-http://127.0.0.1:6333}"
export V15_QDRANT_COLLECTION="${V15_QDRANT_COLLECTION:-plant_srt_direct_v1_bge_m3_20260702}"
export QA_PAPER_METADATA_REGISTRY="${QA_PAPER_METADATA_REGISTRY:-/data/gene-family-mas-v2/data/knowledge_base/paper_metadata_registry_v1_20260717/paper_metadata_registry_full.jsonl}"
export NEO4J_URI="${NEO4J_URI:-bolt://127.0.0.1:18788}"
export NEO4J_USER="${NEO4J_USER:-neo4j}"
export NEO4J_PASSWORD="${NEO4J_PASSWORD:-plant_srt_direct_password}"
# Required on this host for transformers/scipy/BGE imports; otherwise Python may
# pick /lib/x86_64-linux-gnu/libstdc++.so.6 and fail on CXXABI_1.3.15.
export LD_LIBRARY_PATH="${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH:-}"
exec /data/miniconda3/envs/gfpy312/bin/python -m uvicorn \
scripts.qa_v1_1_73_server:app \
--host 0.0.0.0 \
--port 7924