feat(inference): chat_structured 接入 jsonschema 真校验(T1 架构审查整改)
- pyproject.toml 新增 jsonschema>=4.23 依赖 - engine.py: json.loads 后 jsonschema.validate,校验失败按解析失败重试(带错误信息) - 新增 3 用例:违规重试成功/耗尽 parse_error 含详情/合法一次通过 - 全量 163 passed / 100.00% 覆盖(936 stmts/238 br),fail_under=99 达标
This commit is contained in:
@@ -318,6 +318,49 @@ def test_chat_structured_empty_schema_no_hint():
|
||||
assert r.status == "ok" and r.data == {"v": True}
|
||||
|
||||
|
||||
# ---------- T1: chat_structured 真 schema 校验(jsonschema) ----------
|
||||
|
||||
def test_chat_structured_schema_violation_retries():
|
||||
"""返回不合 schema 的 JSON 时带错误信息重试;第二次合法 → ok。"""
|
||||
client = FakeLLMClient([("ok", '{"a": "not_a_number"}'), ("ok", '{"a": 2}')])
|
||||
eng = make_engine(client)
|
||||
r = eng.chat_structured(
|
||||
session_id="s1", prompt=Prompt(name="p", version="v1", template="提取"),
|
||||
variables={},
|
||||
schema={"type": "object", "properties": {"a": {"type": "number"}}, "required": ["a"]},
|
||||
)
|
||||
assert r.status == "ok" and r.data == {"a": 2} and r.parse_attempts == 2
|
||||
# 第二次调用带上次校验错误信息(重试提示)
|
||||
assert "校验失败" in client.calls[1]["messages"][0]
|
||||
|
||||
|
||||
def test_chat_structured_schema_violation_parse_error():
|
||||
"""全部返回不合 schema 的 JSON → parse_error,error 含校验详情。"""
|
||||
client = FakeLLMClient([("ok", '{"a": "bad"}'), ("ok", '{"a": "bad"}')])
|
||||
eng = make_engine(client)
|
||||
r = eng.chat_structured(
|
||||
session_id="s1", prompt=Prompt(name="p", version="v1", template="提取"),
|
||||
variables={},
|
||||
schema={"type": "object", "properties": {"a": {"type": "number"}}, "required": ["a"]},
|
||||
retry_count=1,
|
||||
)
|
||||
assert r.status == "parse_error"
|
||||
assert "校验失败" in (r.error or "")
|
||||
assert r.parse_attempts == 2
|
||||
|
||||
|
||||
def test_chat_structured_schema_valid_passes_without_retry():
|
||||
"""返回合法 JSON 时一次通过,不触发重试。"""
|
||||
client = FakeLLMClient([("ok", '{"a": 1}')])
|
||||
eng = make_engine(client)
|
||||
r = eng.chat_structured(
|
||||
session_id="s1", prompt=Prompt(name="p", version="v1", template="提取"),
|
||||
variables={},
|
||||
schema={"type": "object", "properties": {"a": {"type": "number"}}, "required": ["a"]},
|
||||
)
|
||||
assert r.status == "ok" and r.data == {"a": 1} and r.parse_attempts == 1
|
||||
|
||||
|
||||
def test_chat_truncation_callback_returns_none_keeps_variables():
|
||||
"""truncate_cb 返回 None 时回退原 variables(覆盖 new_vars is None 分支)。"""
|
||||
def truncate_cb(prompt_text, variables):
|
||||
|
||||
Reference in New Issue
Block a user