130 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""存量回洗(一次性,抽检 2026-07-15 后):
① 追加字段前缀堆叠/[本窗]残留清洗 + 同文去重34+9 张卡)
② 关系卡顶层演变轨迹迁移进 字段.演变轨迹(双份分裂修复)
③ 出场章全量重建:卡名+别名 机械预扫全书正文(零 AI比增量准
④ 脏别名清理:备忘录行/括号注释/错认两行(橡树妖/雷行天下)
⑤ 占位值清理:字段值含「续写不可见」的删字段
"""
import json
import re
import sys
import psycopg
DSN = ("postgresql://root:f6710e2d0294eb1c10e26a805a64bc54@100.64.0.8:5433/muse-example"
"?keepalives=1")
TENANT = 1
PREFIX_RE = re.compile(r"^(?:\[[窗本][^\]]{0,6}\]\s*)+") # 含 [窗本窗] 等模型自造变体
WIN_NUMS = re.compile(r"\[窗(\d+)\]")
# 7 型合同合法 key越合同 key 清洗用,运行时从库加载)
VALID_KEYS = {}
def load_valid_keys(conn):
for (sk, snap) in conn.execute(
"""SELECT s.schema_key, v.field_contract_snapshot FROM muse_meta_schema s
JOIN muse_meta_schema_version v ON v.id=s.active_version_id
WHERE s.tenant_id=1 AND s.schema_key IN
('character','location','item','faction','power_system','event','character_relation')"""):
VALID_KEYS[sk] = {f["key"] for f in snap.get("特有字段", [])} | {"一句话摘要", "演变轨迹"}
def clean_list(items):
"""剥堆叠前缀+同文去重;窗号取原条目最内层(最后一个),无窗号保持裸条目。"""
out, seen = [], set()
for it in items:
s = str(it)
core = PREFIX_RE.sub("", s).strip()
if not core or core in seen:
continue
seen.add(core)
nums = WIN_NUMS.findall(s[:len(s) - len(core)])
out.append(f"[窗{nums[-1]}] {core}" if nums else core)
return out
def rebuild_presence(chapters, names):
"""全书逐章扫描名字集合 → 出场章号列表。"""
hits = set()
for order_no, text in chapters:
if any(nm in text for nm in names):
hits.add(order_no)
return sorted(hits)
def main():
stats = {"前缀清洗卡": 0, "关系迁移卡": 0, "出场章重建卡": 0, "删别名行": 0, "删占位字段": 0}
with psycopg.connect(DSN) as conn:
load_valid_keys(conn)
for work_id in (4, 8):
chapters = conn.execute(
"""SELECT c.order_no, b.content_text FROM muse_content_chapter c
JOIN muse_content_block b ON b.chapter_id=c.id AND b.deleted=FALSE
WHERE c.tenant_id=%s AND c.work_id=%s AND c.deleted=FALSE
ORDER BY c.order_no""", (TENANT, work_id)).fetchall()
cards = conn.execute(
"""SELECT id, draft_payload FROM muse_knowledge_draft
WHERE tenant_id=%s AND work_id=%s AND source_type='upgrade_book'
AND deleted=FALSE""", (TENANT, work_id)).fetchall()
for did, p in cards:
changed = False
fields = p.get("字段") or {}
# ② 关系卡顶层演变迁移
if p.get("type") == "character_relation" and "演变轨迹" in p:
legacy = p.pop("演变轨迹")
base = fields.get("演变轨迹") or []
fields["演变轨迹"] = (base if isinstance(base, list) else [base]) + \
(legacy if isinstance(legacy, list) else [legacy])
p["字段"] = fields
changed = True
stats["关系迁移卡"] += 1
# ①⑤ 数组前缀清洗 + 占位字段删除 + 越合同畸形 key 清洗窗29黄蜂针实测
vk = VALID_KEYS.get(p.get("type"))
for k in list(fields.keys()):
if vk is not None and k not in vk:
del fields[k]
changed = True
stats["删越合同key"] = stats.get("删越合同key", 0) + 1
continue
v = fields[k]
if isinstance(v, str) and "续写不可见" in v:
del fields[k]
changed = True
stats["删占位字段"] += 1
elif isinstance(v, list):
nv = clean_list(v)
if nv != v:
fields[k] = nv
changed = True
stats["前缀清洗卡"] += 1
# ③ 出场章全量重建(实体卡;关系卡无出场章语义)
if p.get("type") != "character_relation":
names = {p.get("名称", "")} | set(p.get("别名") or [])
names = {n for n in names if n and len(n) >= 2} # 单字名误命中太多,跳过
if names:
nv = rebuild_presence(chapters, names)
if nv and nv != p.get("出场章"):
p["出场章"] = nv
changed = True
stats["出场章重建卡"] += 1
if changed:
conn.execute(
"UPDATE muse_knowledge_draft SET draft_payload=%s, updater='rewash' WHERE id=%s",
(json.dumps(p, ensure_ascii=False), did))
# ④ 脏别名:备忘录/括号/超长 + 抽检定点两行错认
r = conn.execute(
"""UPDATE example_upgrade_alias SET deleted=TRUE, updater='rewash'
WHERE tenant_id=%s AND deleted=FALSE AND (
alias ~ '[())。,:]' OR length(alias) > 12
OR canonical_name ~ '[())。,:]'
OR alias IN ('橡树妖','雷行天下'))""", (TENANT,))
stats["删别名行"] = r.rowcount
conn.commit()
print(json.dumps(stats, ensure_ascii=False))
if __name__ == "__main__":
sys.exit(main())