feat(server): add workbench API, DSH planner worker and RAG pipeline
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""任务启动点数预检 + 运行中熔断(用户反馈:没点数了还在跑)。
|
||||
|
||||
预检(readiness 阶段):按成本预估与当前余额比较,余额必须覆盖预估 + 20% 缓冲。
|
||||
熔断(runner 每段结束后):点数/余额类错误说明继续跑只会白跑,立刻停止整个任务。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlmodel import Session
|
||||
|
||||
from .billing import point_state
|
||||
|
||||
# 启动缓冲:预估之外还要留 20%,防止输出超长导致中途断粮
|
||||
BALANCE_BUFFER_RATIO = 0.2
|
||||
|
||||
|
||||
def points_preflight(session: Session, campaign, estimated_points: int) -> dict:
|
||||
"""启动前点数校验。返回 {ok, blocker, info}。
|
||||
|
||||
ok=False 时 blocker 是可直接展示的中文原因。
|
||||
"""
|
||||
owner_id = int(campaign.owner_user_id or 0)
|
||||
org_id = int(campaign.organization_id or 1)
|
||||
if not owner_id:
|
||||
return {"ok": True, "blocker": "", "info": None}
|
||||
state = point_state(session, owner_id, org_id)
|
||||
balance = int(state.get("points") or 0)
|
||||
need = int(estimated_points or 0)
|
||||
required = int(need * (1 + BALANCE_BUFFER_RATIO))
|
||||
info = {"balance": balance, "estimated_points": need,
|
||||
"required_points": required, "buffer_ratio": BALANCE_BUFFER_RATIO}
|
||||
if balance < required:
|
||||
gap = required - balance
|
||||
return {
|
||||
"ok": False,
|
||||
"blocker": (f"点数不足:本次预估需要约 {need:,} 点数(含 20% 缓冲共 {required:,}),"
|
||||
f"当前余额 {balance:,},还差 {gap:,}。请联系管理员在「用量与账单」增加点数后重试"),
|
||||
"info": info,
|
||||
}
|
||||
return {"ok": True, "blocker": "", "info": info}
|
||||
|
||||
|
||||
# 段级失败里属于「继续跑没有意义」的错误类型:钱的问题不会自愈。
|
||||
CIRCUIT_BREAK_FAILURE_TYPES = {"billing", "balance", "auth"}
|
||||
|
||||
|
||||
def should_break_run(failure: dict | None) -> tuple[bool, str]:
|
||||
"""根据 execute_segment 返回的 failure 判断是否熔断整个任务。
|
||||
|
||||
返回 (是否熔断, 原因)。
|
||||
"""
|
||||
if not failure:
|
||||
return False, ""
|
||||
ftype = str(failure.get("type") or "")
|
||||
detail = str(failure.get("detail") or "")
|
||||
if ftype in CIRCUIT_BREAK_FAILURE_TYPES:
|
||||
return True, detail[:160] or "模型服务拒绝(余额/鉴权问题)"
|
||||
low = detail.lower()
|
||||
if ("点数余额不足" in detail or "余额不足" in detail
|
||||
or "insufficient" in low and ("balance" in low or "quota" in low)
|
||||
or "invalid api key" in low):
|
||||
return True, detail[:160]
|
||||
return False, ""
|
||||
|
||||
|
||||
__all__ = ["points_preflight", "should_break_run", "BALANCE_BUFFER_RATIO",
|
||||
"CIRCUIT_BREAK_FAILURE_TYPES"]
|
||||
Reference in New Issue
Block a user