袁聪的第二次提交,项目已完整

This commit is contained in:
2026-09-11 16:57:47 +08:00
parent 5907fcd6d2
commit fd9598efdf
190 changed files with 31513 additions and 680 deletions
+75 -1
View File
@@ -381,10 +381,12 @@ def _compile_sql(plan: QueryPlan, auth: AuthContext) -> tuple[str, dict[str, Any
"持仓数量": "h.total_quantity AS total_quantity",
"持仓市值": "h.market_value AS market_value",
"浮动盈亏": "h.profit_loss AS profit_loss",
"可用份额": "h.available_quantity AS available_quantity",
"可用现金": "a.available_cash AS available_cash",
"现金余额": "a.cash_balance AS cash_balance",
"历史资金变化": "SUM(l.amount) AS cash_change",
"收盘价": "m.close_price AS close_price",
"基金总份额": "m.total_fund_shares AS total_fund_shares",
"基金净值": "n.nav AS nav",
"成交价格": "t.executed_price AS executed_price",
"客户数": "COUNT(DISTINCT cp.customer_id) AS customer_count",
@@ -491,6 +493,74 @@ def _mock_plan(request: QueryRequest, domains: list[str]) -> dict[str, Any]:
"confirmation_question": "请明确要查询的业务对象、指标和时间范围。"}
def _offsite_mock_plan(request: QueryRequest, domains: list[str]) -> dict[str, Any] | None:
"""为场外核对补充确定性查询计划,仍复用统一 SQL 安全校验。"""
question = request.question
if "基金代码" not in question:
return None
fund_match = re.search(r"基金代码(?:为|是)?\s*([A-Za-z0-9_-]+)", question)
if fund_match is None:
return None
filters: list[dict[str, Any]] = [{
"field": "fin_product.product_code",
"operator": "=",
"value": fund_match.group(1),
}]
account_match = re.search(r"账户标识(?:为|是)?\s*([^,,。;;\s]+)", question)
account_filter = {
"field": "fin_holding.trade_account",
"operator": "=",
"value": account_match.group(1),
} if account_match is not None else None
common = {
"domains": ["market_nav", "trading_account"],
"filters": filters,
"confidence": 0.99,
"needs_confirmation": False,
"limit": 1,
}
if "最新总份额" in question and "申请前持有份额" in question:
holding_filters = filters + ([account_filter] if account_filter else [])
return {
**common,
"intent": "offsite_subscription_holding_check",
"tables": ["fin_market_price", "fin_nav_history", "fin_holding", "fin_product"],
"metrics": ["基金总份额", "基金净值", "持仓数量"],
"filters": holding_filters,
}
if "最新总份额" in question and "最新净值" in question:
return {
**common,
"intent": "offsite_fund_limit_check",
"tables": ["fin_market_price", "fin_nav_history", "fin_product"],
"metrics": ["基金总份额", "基金净值"],
}
if "当前最新可用份额" in question or "可用份额" in question:
holding_filters = filters + ([account_filter] if account_filter else [])
return {
**common,
"intent": "offsite_redemption_available_check",
"tables": ["fin_holding", "fin_product"],
"metrics": ["可用份额"],
"filters": holding_filters,
}
if "最新净值" in question:
return {
**common,
"intent": "offsite_latest_nav",
"tables": ["fin_nav_history", "fin_product"],
"metrics": ["基金净值"],
}
if "最新总份额" in question:
return {
**common,
"intent": "offsite_latest_total_shares",
"tables": ["fin_market_price", "fin_product"],
"metrics": ["基金总份额"],
}
return None
def _audit_payload(request: QueryRequest, plan: QueryPlan, sql: str | None, params: dict[str, Any],
validation: dict[str, Any], execution: dict[str, Any]) -> dict[str, Any]:
return {
@@ -536,7 +606,11 @@ def query(request: QueryRequest, *, db_engine: Any = None,
request.request_id = request.request_id or str(uuid.uuid4())
domains = _route_keywords(request.question)
try:
raw = _llm_plan(request, domains) if use_llm and LLM_KEY else _mock_plan(request, domains)
raw = (
_llm_plan(request, domains)
if use_llm and LLM_KEY
else _offsite_mock_plan(request, domains) or _mock_plan(request, domains)
)
plan = _normalize_plan(raw, request, domains)
if request.confirmation and plan.needs_confirmation:
plan.needs_confirmation = False