1. 系统总览
| 维度 | 设计 |
|---|---|
| 形态 | 单服务 FastAPI 应用,同时托管 API 与前端构建产物;案件为异步后台任务 |
| 模型 | GLM-5.3(文本涵摄/抗辩/评审/路由)+ GLM-4V(图像剥离与叙述,advisory) |
| 模态 | 文本(ROUGE/LCS 系指标 + S1/S2/S3 LLM 取证)与图像(L1/L2/L3/LE/LV 级联) |
| 判定 | R1–R8 确定性规则代码三择一输出:侵权 / 非侵权 / 存疑(强制人工升级) |
| 存储 | 案件 JSON 文件(增量落盘)+ SHA-256 哈希链审计日志 + Redis Stream token 指标(JSONL 兜底) |
| 交互 | 前端 2.5s 轮询 + 对话干预通道(暂停/继续/终止/检查点、补证、人工钉定、问答、红队) |
核心设计哲学(贯穿全部代码):
- AI 不自证——引证核验(A10)、要件树装载(A1)、判定规则(R1–R8)、相似度指标、引证三闸门全部为确定性代码,不经生成模型。
- VLM 仅叙述——图像实质性相似判定由确定性度量(ΔE00/OT/RANSAC/NCC)完成,VLM 只把数字翻译成律师语言并标注 advisory(依据:VLM 判定能力 BLINK 51.3% vs 人类 95.7%)。
- fail-closed——评审降级=不通过;抗辩检验缺失=存疑(null);同源片段无法归因=E5 存疑强制人工。
- 磁盘为权威——控制标志/对话/证据/钉定以磁盘为准,工作流落盘前做"外带字段合并",杜绝并发覆盖竞态。
- 人机协同责任边界——人工钉定(pins)优先于模型映射(置信度 1.0),重跑仍保持生效。
2. 代码结构
cias/
├─ backend/app/
│ ├─ main.py # FastAPI 路由、用户中间件、检查点恢复、演示种子、静态托管(1,158 行)
│ ├─ engine.py # A0 编排官:Plan-and-Execute 主干 + R1-R8 + 权属闸口 + 步骤闸门(383 行)
│ ├─ agents.py # A1-A12 + A11.5 智能体(LLM 涵摄/抗辩/评审/红队/摘要)(472 行)
│ ├─ image_pipeline.py# 图像级联 v2:L1/L2/L3/LE/LV + 确定性分级 + 举证图(511 行)
│ ├─ colorgeom.py # 确定性色彩/几何引擎:LAB/CIEDE2000/Sinkhorn-OT/RANSAC/NCC(341 行)
│ ├─ similarity.py # 文本指标:ROUGE-L/LCStr/Jaccard/编辑距离/分布统计(纯 Python)(150 行)
│ ├─ forensics.py # S1 内容回忆 / S2 说服越狱 / S3 知识记忆取证(106 行)
│ ├─ knowledge.py # 双法域要件模板 + BM25 式 RAG + 引证三闸门(107 行)
│ ├─ chat_ops.py # 对话通道 v2:LLM 意图路由 + explain/attack/answer(178 行)
│ ├─ llm.py / vlm.py # GLM 客户端:重试/JSON 增强/升额/调用日志(176+162 行)
│ ├─ store.py # 案件 JSON 存储 + 哈希链审计(97 行)
│ ├─ metrics.py # Redis Stream token 指标 + JSONL 兜底 + 用户/事务/阶段上下文(175 行)
│ ├─ report.py # A12 七段式意见书渲染(claim→source 映射)(175 行)
│ └─ knowledge/*.json # 要件模板(CN/US)/判例库/法条库/图像剥离判例库/说服策略库
└─ frontend/src/ # Vue3:案件列表/创建/详情(要件矩阵/级联/评审/意见书/对话流)+ 工具页
3. 总体架构图
graph TB
subgraph L1["前端层 Vue3 + Vite(App.vue / api.js / i18n)"]
UI1[案件列表/创建/重跑] --- UI2[案件详情: 要件矩阵·级联取证·评审团·红队·意见书]
UI3[对话干预通道: ⏸▶⛔ 检查点·补证·钉定·问答·红队] --- UI4[工具页·智能体名册]
end
L1 -->|"HTTP /api/*(X-User-Id 头,2.5s 轮询)"| L2
subgraph L2["API 层 main.py(FastAPI)"]
MW["user_context_middleware → metrics 上下文"]
API1["案件 CRUD · run/resume/checkpoint"] --- API2["control/evidence/pin/chat"]
API3["uploads / files · tools · metrics · demo/seed"]
end
L2 --> L3
subgraph L3["编排层 engine.py(A0 主编排官)"]
E1["权属闸口 ownership_gate(阻断式三态)"]
E2["_step 检查点步骤(done_steps 跳过)"]
E3["_gate 步骤闸门(轮询磁盘: 暂停/终止/检查点)"]
E4["apply_rules R1-R8(确定性三择一)"]
E5["_persist 外带字段合并(磁盘优先防竞态)"]
end
L3 --> L4
subgraph L4["智能体层 agents.py / chat_ops.py"]
AG1["A2 受理抽取 → A1 要件树/映射"] --- AG2["A3 权属链 · A4 保护范围 · A5 接触"]
AG3["A8 双轨论证 · A9 抗辩 · A11.5 红队"] --- AG4["A11 评审团(rubric) · A12 摘要"]
AG5["chat 意图路由(快路径 + LLM 慢路径)"]
end
L4 --> L5
subgraph L5["工具与取证层(全部确定性)"]
T1["similarity.py 文本指标"] --- T2["image_pipeline + colorgeom 图像级联"]
T3["forensics S1/S2/S3"] --- T4["knowledge.py RAG + 引证三闸门"]
end
L5 --> L6
subgraph L6["模型与基础设施层"]
M1["llm.py GLM-5.3(重试/JSON增强/调用日志)"] --- M2["vlm.py GLM-4V(多策略JSON解析/升额)"]
M3["store.py JSON案件 + SHA-256哈希链审计"] --- M4["metrics.py Redis Stream + JSONL"]
M5["knowledge/*.json 要件/判例/法条/策略库"]
end
分层依赖关系:上层只经显式接口调用下层;智能体约定为 "LLM/VLM 仅产出分析意见与置信度,确定性判断一律由代码执行"(agents.py 模块头注释)。
4. 主工作流(A0 Plan-and-Execute)
flowchart TD
S0([POST /api/cases/id/run<br/>asyncio.create_task 后台运行]) --> G{权属闸口<br/>ownership_gate}
G -->|fail: 无任何权属证据| BLK["阻断式终止:要件标注 INSUFFICIENT/REFUTED<br/>仅输出补证建议短文(rule=GATE, blocked)"]
BLK --> DONE([DONE])
G -->|pass / doubt| A2["A2 受理抽取(LLM→结构化案件卡片)"]
A2 --> A1B["A1 要件树装载(确定性:CN/US JSON 模板<br/>E1-E6 要件 + D1-D6 抗辩)"]
subgraph PAR["并行事实调查(asyncio 并发)"]
A6["A6 相似度矩阵<br/>文本: similarity.compare + S1取证<br/>图像: compare_images 四级级联"]
A4["A4 保护范围<br/>思想/表达二分·图像14类元素剥离"]
A3["A3 权属链校验"]
end
A1B --> PAR
PAR --> A5["A5 接触分析(发表在先+高相似 ⇒ 推定)"]
A5 --> A1M["A1 要件—证据映射<br/>LLM 逐要件涵摄(≤3轮补齐)<br/>+ 人工钉定优先 + 图像同源归因闸"]
A1M --> A7["A7 判例检索(确定性 BM25 式 RAG, Top-3)<br/>+ 法条检索"]
A7 --> A89["A8 实质性相似双轨论证(外测+内测)<br/>∥ A9 抗辩强制清单(三态防漏检)"]
A89 --> R{"apply_rules<br/>R1-R8 确定性规则"}
R -->|R1 要件齐备+抗辩不成立| C1[侵权]
R -->|R2 要件否定 / R3 抗辩成立 / R5 复制否定| C2[非侵权]
R -->|R4 关键要件存疑 / 状态不完整| C3[存疑 + 强制人工升级]
C1 --> RV["A11 三视角评审团(律师/技术/市场损害<br/>rubric 二元评分, fail-closed)"]
C2 --> RV
C3 --> RV
RV --> RT["A11.5 红队模拟(被告律师视角攻击结论)"]
RT --> A10["A10 引证三重校验<br/>存在性→逐字对照→时效(确定性)"]
A10 --> A12["A12 执行摘要(LLM)+ report.py 模板渲染七段意见书"]
A12 --> DONE
DONE --> AUD(["A13 审计:哈希链 + token/模型版本留痕"])
style BLK fill:#fdd
style C1 fill:#fdd
style C2 fill:#dfd
style C3 fill:#ffd
编排关键机制(engine.py):
- 步骤闸门
_gate:每个智能体任务启动前轮询磁盘上的control标志——paused则挂起(每 1.2s 轮询)、abort抛WorkflowAborted、checkpoint抛CheckpointReached。控制以磁盘为权威,暂停期间工作流不落盘也能感知恢复/终止。 - 检查点
_step:每步完成即写done_steps并落盘;/resume对 CHECKPOINTED/INTERRUPTED/ABORTED/PAUSED 跳过已完成步骤续跑;服务重启时 startup 钩子把悬挂案件标为 INTERRUPTED(而非从头重跑)。 - 并行分派:A6/A4/A3 用
_step返回的协程并发执行;A8 与 A9 同理。 - 单点降级:LLM 失败重试 3 轮(429 退避、空内容自动升额 max_tokens×2 至 16384、400 自动摘除 thinking 字段),要件映射 3 轮补齐仍缺则抛错(不允许占位符混过判定)。
5. 判定规则引擎(apply_rules:GATE + R1–R5)
规则的求值顺序(先到先得,输出三择一 + 路径 + 置信度 + 要件/抗辩状态快照;设计文档中的 R6–R8 升级/复核语义由 escalation_required 标志与 A11 评审强制人工机制承担):
| 顺序 | 条件 | 结论 | 规则/路径 |
|---|---|---|---|
| 0 | 权属闸口 fail(在规则前阻断) | 存疑(blocked) | GATE |
| 1 | 无存疑无否定 ∧ E4 接触≠成立 ∧ 相似低于阈值 | 非侵权 | R5 复制否定(独立创作/巧合) |
| 2 | 存在 REFUTED 要件 | 非侵权 | R2 要件否定型 |
| 3 | 存在 INSUFFICIENT 要件 | 存疑 + 人工升级 | R4 疑点利益归被告 |
| 4 | 存在成立抗辩 | 非侵权 | R3 抗辩阻却 |
| 5 | 全部要件 SUPPORTED | 侵权(抗辩有存疑 ⇒ 加人工升级) | R1 要件齐备 |
| 6 | 兜底 | 存疑 | R4 状态不完整 |
要件树(CN 模板):E1 作品适格 / E2 权属 / E3 受控行为 / E4 接触 / E5 实质性相似 / E6 损害与因果(optional,不参与齐备性检查);抗辩 D1 客体不受保护 / D2 独立创作 / D3 合理使用 / D4 时效程序 / D5 权利瑕疵 / D6 AI 输出独立。抗辩输出三态 true/false/null(null=存疑,绝不默认不成立——防漏检)。
6. 图像四级级联管线(image_pipeline v2)
flowchart LR
IMG["两图上传(sha256 命名)"] --> L1
subgraph CASCADE["compare_images(确定性判定 + VLM 仅叙述)"]
L1["L1 pHash 快筛<br/>DCT-8x8 汉明≤8 ⇒ 近重复"]
L2["L2 分块局部匹配<br/>4×4 网格 ±1 邻域<br/>信息块匹配率≥0.45"]
L3["L3 统计特征<br/>色彩/边缘/构图加权余弦<br/>摄影0.85·美术0.80·图形0.82"]
LE["LE ★元素级确定性分析<br/>LAB k-means 色域区域化 → Sinkhorn-OT 对齐<br/>→ 逐对 ΔE00/质心偏移/IoU/占比<br/>→ 五类结论 + 显著小块 NCC 探针<br/>+ RANSAC 平移单应 + 举证图"]
LV["LV VLM 仅叙述(advisory)<br/>把结构化数字翻译为律师语言<br/>不得自创数字/结论"]
L1 --> L2 --> L3 --> LE --> LV
end
LV --> XV{"确定性分级<br/>(VLM 不参与)"}
XV --> G1["strong_duplicate(L1∧2层佐证)"]
XV --> G2["transformed_copy(同源片段+表达取用)"]
XV --> G3["shared_fragment(待归因 → 人工)"]
XV --> G4["element_copy / stat_similar"]
XV --> G5["weak_or_none"]
LE 五类元素级结论(可直接翻译为判决书语言):
| 类别 | 判据 | 含义 |
|---|---|---|
| 复制 | 几何同(IoU≥0.40 或 偏移≤8%) ∧ 色同(ΔE00≤3.5) | 受保护表达层面的取用 |
| 改色 | 几何同 ∧ ΔE00>5 | 换色保留构图 |
| 改位 | 色同 ∧ 偏移>10% | 元素移动 |
| 替换 | IoU<0.15 ∧ 偏移>18% | 元素更换 |
| 近似改写 | 其余 | 部分类似 |
expression_copies = 复制+改色+改位 计数,是 E5 要件支持的核心证据。显著一致片段探针(A 图高方差 64px 模板在 B 图 NCC 滑窗搜索,≥3 处命中 ⇒ shared_fragment_signal)对应"共同错误"这一抄袭最强证据形态——独立创作几乎不可能复制同一错误。图像案件与文本案件共用同一要件树、规则引擎、评审与文书出口。
7. 文本模态与 LLM 取证
- 确定性指标(similarity.py):ROUGE-L(F/P/R)、LCS 比率、最长公共连续子串 LCStr(>50 强逐字)、Jaccard、归一化编辑距离;改写信号 = 高 Jaccard(≥0.35) + 低 LCS 比率(<0.45) + 差值>0.1(洗稿型);证据分级 strong_verbatim → verbatim_likely → paraphrase_likely → weak_or_none。
- S1 内容回忆取证(forensics.py,AI 场景):对被测模型同 prefix 独立采样 N 次(T=1.0,信号量并发 4),统计 mean/P50/P90/P95/max/逐字率——捕获"闪烁式泄漏"(单次采样会漏)。
- S2 说服越狱(授权场景手动调用):说服策略变异请求 → LLM 意图守恒判定 → 逐策略采样分布对比基线,Δ>0.3 判"分布显著偏移"。
- S3 知识记忆探测:开放式 QA + ROUGE 语义比对(评判与被测同源,结果标注仅参考)。
8. 知识库与引证校验
knowledge/*.json:CN/US 要件模板(含 burden 与 sub_question)、8 条判例(issue/holding/difference_hint)、7 条法条、图像剥离判例库(filter_precedents/element_checklist/delta_e_language/provenance_gate)、6 类说服策略。- 检索:法域过滤 + 关键词重叠打分(demo 级 BM25 近似),确定性、零 token。
- 引证三闸门(A10,AI 不自证):闸门1 存在性(题名关键词覆盖率≥60%)→ 闸门2 逐字对照(引文须为库内原文子串)→ 闸门3 时效;未过 ⇒ 从稿中移除并在意见书标注。
9. 对话干预通道(人机协同)
sequenceDiagram
participant U as 用户(前端/对话)
participant API as /api/cases/id/chat
participant R as chat_ops 意图路由
participant W as 工作流(A0)
U->>API: 消息(如"暂停"/"把E5钉定为证据不足"/"为什么D2不成立")
API->>API: 快路径:短指令/前缀匹配(零 LLM 开销)
API->>R: 慢路径:LLM 意图路由(11 类意图)
R-->>API: intent + target + status + evidence
alt 流程控制类
API->>W: 写 control 标志(磁盘权威)→ 步骤边界闸门生效
else 补证 / 钉定 / 解除钉定
API->>API: 证据池 EV-Uxx 登记 / pins 写入(钉定前快照可回滚)
else 重跑 / 检查点 / 恢复
API->>W: run / checkpoint / resume(跳过 done_steps)
else explain(依据追问)
API->>R: 引 llm_trace 真实推理轨迹解释"为什么"
else attack(即时红队)
API->>R: 被告律师视角攻击指定目标
else answer(默认)
API->>R: 案件全量快照 + 对话历史 深度问答
end
API-->>U: 回复落盘 chat 数组(前端 feed 与 timeline 按时间合成渲染)
意图集:answer / pause / resume / abort / checkpoint / add_evidence / pin / unpin / rerun / explain / attack。工作流 _persist 时对 chat/evidence_pool/pins/control/pin_backup 以磁盘为准合并,防止长任务覆盖对话通道的并发写入。
10. 数据模型与案件状态机
案件 JSON(backend/data/cases/CASE-*.json)核心字段:status / control(paused·abort·checkpoint) / done_steps / timeline / tasks / llm_trace / facts / elements(E1-E6+D1-D6 状态机节点) / similarity(metrics·signals·cascade·cross_validation·forensics) / protectable / chain_of_title / access / precedents / statutes / conclusion / review / redteam / citations / summary_llm / opinion_md / evidence_pool / pins / pin_backup / chat / gate / user_id。
stateDiagram-v2
[*] --> CREATED: POST /api/cases
CREATED --> RUNNING: /run(后台任务)
RUNNING --> PAUSED: ⏸ 暂停(步骤边界挂起)
PAUSED --> RUNNING: ▶ 继续(内存挂起直接恢复)
RUNNING --> CHECKPOINTED: 停止到检查点(done_steps 持久化)
RUNNING --> ABORTED: ⛔ 终止(安全退出,可重跑)
RUNNING --> FAILED: 异常(降级捕获后落盘)
RUNNING --> INTERRUPTED: 服务重启(startup 扫描悬挂案件)
CHECKPOINTED --> RUNNING: /resume 跳过已完成步骤
INTERRUPTED --> RUNNING: /resume 从检查点续跑
ABORTED --> RUNNING: /resume(有检查点)或 /run 重跑
PAUSED --> RUNNING: /resume(跨重启时从检查点续跑)
RUNNING --> DONE: 意见书落盘 + A13 审计
DONE --> RUNNING: 重跑(钉定/新证据纳入)
11. 可观测性、审计与安全
- Token 指标:每次 LLM/VLM 调用发布到 Redis Stream
wf:llm_tokens(XADD,MAXLEN 100k),字段含 user_id/matter_id/stage/name/model/tokens_in/out/total;上下文由 HTTP 中间件与引擎注入(contextvars)。Redis 不可用 60s 熔断 + 本地 JSONL 始终留档。 - 审计哈希链:audit.log 逐条
hash = SHA256(entry + prev_hash)链式衔接,追加只写,满足可复现取证。 - LLM 调用轨迹:内存环形日志(200 条)记录 prompt/reasoning/content 摘要与 token/时延,按智能体切片存入
llm_trace,供前端"思考过程"与 explain 意图引用。 - 鲁棒性:JSON 解析失败自动重试并追加纠正消息;VLM 多策略 JSON 修复(代码围栏提取→子串截取→中文引号替换→尾逗号修复);空内容自动升额 max_tokens(恒思考模式)