From 2db83a69e8b7fe668dfa0c2bb9875a72aca2e93d Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Mon, 5 Oct 2026 18:58:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A1=E6=89=B9=E8=B4=A8=E8=AF=A2=EF=BC=9A?= =?UTF-8?q?=E5=8F=AA=E6=9C=89=E7=A9=BA=E4=B8=B2=E7=AE=97=E6=B2=A1=E6=8C=87?= =?UTF-8?q?=E6=98=8E=E5=8F=A5=E5=AD=90=E3=80=81=E5=AE=A1=E6=89=B9=E5=8D=A1?= =?UTF-8?q?=EF=BC=8C0=E3=80=81false=20=E8=BF=99=E7=B1=BB=E7=85=A7=E6=A0=B7?= =?UTF-8?q?=E6=8A=A5=E6=A0=BC=E5=BC=8F=E4=B8=8D=E5=AF=B9=EF=BC=9B=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E7=9B=B8=E5=90=8C=E7=9A=84=E4=B8=A4=E6=AC=A1=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=85=B1=E7=94=A8=E4=B8=80=E4=BB=BD=E5=BF=AB=E7=85=A7?= =?UTF-8?q?=EF=BC=8C=E5=BC=95=E7=94=A8=E5=88=97=E8=A1=A8=E9=87=8C=E5=8F=AA?= =?UTF-8?q?=E8=AE=B0=E4=B8=80=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/engine/inquiry.py | 18 ++++++++++++------ backend/tests/test_inquiry_api.py | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/app/engine/inquiry.py b/backend/app/engine/inquiry.py index 7c30c674..07b46f78 100644 --- a/backend/app/engine/inquiry.py +++ b/backend/app/engine/inquiry.py @@ -214,9 +214,8 @@ def parse_ask(body: Any) -> Ask: report = body.get("report") if not isinstance(report, str) or not report.strip(): raise _invalid("请指明质询的是哪份报告(报告撰写节点的 ID)", "report") - # 不指明句子、不是在审批卡上问的,写 null 和写空串是一个意思 - unit = body.get("unit") or None - if unit is not None and (not isinstance(unit, str) or not unit.strip()): + unit = _blank_as_none(body.get("unit")) + if unit is not None and not isinstance(unit, str): raise _invalid("句子编号需要是文字,例如「u12」;不指明句子时留空", "unit") quote = body.get("quote") if quote is not None and not isinstance(quote, str): @@ -230,13 +229,18 @@ def parse_ask(body: Any) -> Ask: question = question.strip() if len(question) > QUESTION_MAX: raise _invalid(f"问题最长 {QUESTION_MAX} 字,当前为 {len(question)} 字", "question") - approval_id = body.get("approval_id") or None - if approval_id is not None and (not isinstance(approval_id, str) or not approval_id.strip()): + approval_id = _blank_as_none(body.get("approval_id")) + if approval_id is not None and not isinstance(approval_id, str): raise _invalid("审批卡的 ID 需要是文字;不是在审批卡上提问时留空", "approval_id") return Ask(report=report.strip(), unit=unit.strip() if unit else None, quote=quote, question=question, approval_id=approval_id.strip() if approval_id else None) +def _blank_as_none(value: Any) -> Any: + """不指明句子、不是在审批卡上问的:写 null 和写空串是一个意思。别的类型原样交回,由调用方报格式不对。""" + return None if isinstance(value, str) and not value.strip() else value + + # -------------------------------------------------------------------------- # 开放条件 # -------------------------------------------------------------------------- @@ -669,7 +673,9 @@ async def _answer(op: _Opening, ask: Ask, target: _Target | None, settings: dict return { "answer_text": text, "answer_doc": doc_id, "ok": ok, "limit": _limit(outcome), "error": None if ok else (outcome.error or failed or NO_ANSWER), - "inquiry_artifacts": [q["artifact"] for q in queries if q.get("artifact")], "queries": queries, + # 结果一模一样的两次查询是同一份快照(工件按内容寻址):引用列表里只记一次 + "inquiry_artifacts": list(dict.fromkeys(q["artifact"] for q in queries if q.get("artifact"))), + "queries": queries, "model": outcome.model, "usage": {k: outcome.usage.get(k, 0) for k in USAGE_KEYS}, } diff --git a/backend/tests/test_inquiry_api.py b/backend/tests/test_inquiry_api.py index 811dda00..d0b2971b 100644 --- a/backend/tests/test_inquiry_api.py +++ b/backend/tests/test_inquiry_api.py @@ -526,7 +526,9 @@ async def test_the_run_must_be_waiting_on_that_approval(monkeypatch, shop, clien ({"report": "write", "unit": None, "question": QUESTION, "quote": "引" * 501}, "quote"), ({"report": "write", "unit": None, "question": QUESTION, "quote": 5}, "quote"), ({"report": "write", "unit": 12, "question": QUESTION}, "unit"), + ({"report": "write", "unit": 0, "question": QUESTION}, "unit"), ({"report": "write", "unit": None, "question": QUESTION, "approval_id": 7}, "approval_id"), + ({"report": "write", "unit": None, "question": QUESTION, "approval_id": False}, "approval_id"), ]) async def test_bad_requests_name_the_field(monkeypatch, shop, client, body, field_name): Models(monkeypatch, shop)