- 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/
103 lines
3.6 KiB
Python
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)
|
|
),
|
|
)
|