feat(bidding): 章节配图形态硬门禁——write_chapter拒绝mermaid/plantuml/ASCII伪图写入(2026-09-15用户要求:标书的图必须invoke_model t2i/i2i真图);review_chapter评审兜底同款检测(存量正文/绕行写入),伪图必退+意见自动附带;检测器复用pipeline_service.diagram_gate确定性判定,豁免钥匙=文中如实标注「配图缺失」;ImportError逃逸阀(宿主未装service放行)

This commit is contained in:
yumoqing 2026-09-15 14:55:45 +08:00
parent d0e2ab89a8
commit 73b7154718
2 changed files with 24 additions and 0 deletions

View File

@ -60,6 +60,20 @@ async def review_chapter(chapter_id, score, max_score="", comments="", detail=""
"请按评分规则子维度补全到操作层。" % (
wc, min_w, "商务" if (c.get("section") or "") == "business" else "技术"))
comments = (short_note + "\n" + (comments or "")).strip()
# ── 配图形态门禁(2026-09-15):mermaid/ASCII 伪图必退(write_chapter 已拦,
# 此处兜底存量正文/绕行写入),意见自动附带 ──
try:
from pipeline_service.diagram_gate import find_fake_diagrams
_dg = find_fake_diagrams(c.get("content") or "")
except ImportError:
_dg = []
if _dg:
passed = False
dg_note = ("【配图不合规】正文含伪图(%s)。图必须用 invoke_model 调 t2i/i2i 模型"
"生成真实图片,产物 URL 以 ![图N 标题](URL) 独占一行嵌入;"
"删除 mermaid/ASCII 字符画后重写提交。" % ";".join(sorted(set(_dg))))
comments = (dg_note + "\n" + (comments or "")).strip()
if not passed and not (comments or "").strip():
return False, ("评审不通过必须给出改进意见(comments),"
"写清缺哪些评分维度、应补什么内容、对照哪条得分规则")

View File

@ -86,6 +86,16 @@ async def write_chapter(chapter_id, content, summary="", who=None, agent_id=None
return False, ("章节正文过短(%d 字符 < %d),拒绝写入。请按招标文件要求与评分规则"
"写到操作层面(量化指标/流程步骤/责任人/表单),不要写空话。"
% (len(txt.strip()), MIN_CONTENT_LEN))
# ── 配图形态硬门禁(2026-09-15 用户要求:标书章节的图必须 t2i/i2i 真图)──
# 确定性判定(复用 pipeline_service.diagram_gate),mermaid/ASCII 伪图拒绝写入;
# 平台无图像模型时正文如实标注「配图缺失」即豁免。
try:
from pipeline_service.diagram_gate import find_fake_diagrams, gate_message
_dg = find_fake_diagrams(txt)
if _dg:
return False, gate_message(_dg, scene="标书章节")
except ImportError:
pass # 宿主未装 pipeline-service 时放行(逃逸阀,与产线零接触分层一致)
db, dbname = get_db()
async with db.sqlorContext(dbname) as sor:
recs = await sor.sqlExe(