Files
PlantAI-rag/src/rag/qa_v1_1_73/config.py
T
potaser 4fef3a65ac 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/
2026-08-29 12:39:25 +08:00

103 lines
3.6 KiB
Python

from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
@dataclass(frozen=True)
class QAConfig:
project_root: Path
gfanalysis_root: Path
alias_path: Path
taxonomy_path: Path
reranker_model: Path
initial_recall_per_query: int
max_query_variants: int
max_evidence: int
min_evidence: int
max_rounds: int
graph_hops: int
include_candidate: bool
enable_provisional_draft: bool
enable_second_round: bool
enable_bge_rerank: bool
graph_schema: str
enable_agentic_controller: bool = True
agentic_max_replans: int = 2
enable_question_decomposition: bool = True
subquestion_workers: int = 3
vector_query_workers: int = 2
@classmethod
def from_env(cls) -> "QAConfig":
root = Path(os.environ.get("GENE_FAMILY_ROOT", "/data/gene-family-mas-v2"))
graph_schema = os.environ.get(
"QA_V1_GRAPH_SCHEMA", "canonical"
).strip().lower()
if graph_schema != "canonical":
raise RuntimeError(
"QA V1.1.73 production only permits the canonical graph schema"
)
return cls(
project_root=root,
gfanalysis_root=Path(
os.environ.get("GFANALYSIS_ROOT", "/data/wutx/00test/gfAnalysis")
),
alias_path=Path(
os.environ.get(
"QA_V1_ALIAS_CONFIG",
root / "configs" / "rag" / "entity_alias.yaml",
)
),
taxonomy_path=Path(
os.environ.get(
"QA_V1_TAXONOMY_CONFIG",
root / "configs" / "rag" / "relation_taxonomy.yaml",
)
),
reranker_model=Path(
os.environ.get(
"QA_V1_BGE_RERANKER_MODEL",
root / "bge-reranker-base",
)
),
initial_recall_per_query=int(
os.environ.get("QA_V1_INITIAL_RECALL_PER_QUERY", "50")
),
max_query_variants=int(
os.environ.get("QA_V1_MAX_QUERY_VARIANTS", "6")
),
max_evidence=int(os.environ.get("QA_V1_MAX_EVIDENCE", "40")),
min_evidence=int(os.environ.get("QA_V1_MIN_EVIDENCE", "8")),
max_rounds=max(1, min(int(os.environ.get("QA_V1_MAX_ROUNDS", "2")), 2)),
graph_hops=max(1, min(int(os.environ.get("QA_V1_GRAPH_HOPS", "2")), 2)),
include_candidate=os.environ.get("QA_V1_INCLUDE_CANDIDATE", "0") == "1",
enable_provisional_draft=os.environ.get(
"QA_V1_ENABLE_PROVISIONAL_DRAFT", "1"
)
== "1",
enable_second_round=os.environ.get("QA_V1_ENABLE_SECOND_ROUND", "1")
== "1",
enable_bge_rerank=os.environ.get("QA_V1_ENABLE_BGE_RERANK", "1")
== "1",
graph_schema=graph_schema,
enable_agentic_controller=os.environ.get(
"QA_V1_ENABLE_AGENTIC_CONTROLLER", "1"
)
== "1",
agentic_max_replans=max(
0, min(int(os.environ.get("QA_V1_AGENTIC_MAX_REPLANS", "2")), 2)
),
enable_question_decomposition=os.environ.get(
"QA_ENABLE_QUESTION_DECOMPOSITION", "1"
)
== "1",
subquestion_workers=max(
1, min(int(os.environ.get("QA_V1_SUBQUESTION_WORKERS", "3")), 3)
),
vector_query_workers=max(
1, min(int(os.environ.get("QA_V1_VECTOR_QUERY_WORKERS", "2")), 2)
),
)