fix(priv): R1 缺陷修复——信封包 ok 键 + 空 question 422 + 自谦答语确定性改判 hit:false

- private_docs.py: 命中/未命中两态响应包 ok:true(错误信封 ok:false 不变)
- schemas.py: PrivateQARequest.question 加 min_length=1
- privateqa.py: LLM 自谦答语(资料中未找到相关信息+等价变体)确定性改判
  {hit:false,mode:empty},不调默认阈值(底噪 0.3-0.37 与真实命中 0.42-0.73
  有重叠)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 23:07:19 +08:00
co-authored by Claude Fable 5
parent 19e928ba93
commit 04c08e8339
3 changed files with 31 additions and 3 deletions
+5 -2
View File
@@ -43,13 +43,16 @@ def _envelope(
@router.post("/private")
async def private_qa(req: PrivateQARequest) -> dict[str, Any]:
"""私有资料问答:命中/未命中 200;上游故障转错误信封。"""
"""私有资料问答:命中/未命中 200(均带 ok:true 信封,BUG-PRIV-R1-01);
上游故障转错误信封(ok:false)。"""
try:
return await ask_private(
result = await ask_private(
req.question,
top_k=req.top_k,
min_score=req.min_score,
)
# BUG-PRIV-R1-01(TL 裁决):命中与未命中两态响应均包 ok:true
return {"ok": True, **result}
except DocgenUnavailable as exc:
logger.warning("privateqa: vstore 不可达:%s", exc)
return _envelope("UPSTREAM_DOWN", message="私有资料检索服务不可用,请稍后重试")
+1 -1
View File
@@ -236,7 +236,7 @@ class PrivateDocBlock(BaseModel):
class PrivateQARequest(BaseModel):
"""POST /api/qa/private 请求体(FR-PRIV-004)。"""
question: str
question: str = Field(..., min_length=1) # BUG-PRIV-R1-02:空串 422(VALIDATION 信封)
session_id: str | None = None
top_k: int = 8
min_score: float = 0.30
+25
View File
@@ -35,6 +35,26 @@ SYSTEM_PROMPT = (
"300 字内简体中文 markdown。"
)
# BUG-PRIV-R1-03(TL 裁决):system prompt 固定的自谦答语。LLM 返回匹配
# 任一即改判未命中(底噪越线时不展示低质块;不调默认阈值)。
SELF_DEPRECATING_ANSWERS = (
"资料中未找到相关信息",
"资料中没有相关信息",
"资料中未找到相关的内容",
"资料中没有相关的内容",
"资料中找不到相关信息",
"未找到相关信息",
"没有找到相关信息",
)
def _is_self_deprecating(text: str) -> bool:
"""确定性自谦答语判断(子串匹配)。"""
src = (text or "").strip()
if not src:
return True # 空答案视同未命中
return any(phrase in src for phrase in SELF_DEPRECATING_ANSWERS)
def _safe_float(value: Any) -> bool:
try:
@@ -116,6 +136,11 @@ async def ask_private(
max_tokens=PRIVATE_QA_MAX_TOKENS,
timeout=PRIVATE_QA_LLM_TIMEOUT,
)
# BUG-PRIV-R1-03(TL 裁决):LLM 自谦答语 → 改判未命中。
# vstore 检索先行行为不变(search-chunks 仍返回 items 供内部判断),
# 只是最终响应改判,前端零痕迹。
if _is_self_deprecating(answer):
return {"hit": False, "mode": "empty", "answer": "", "items": []}
elapsed_ms = int((time.perf_counter() - started) * 1000)
return {
"hit": True,