这两年 AI 应用开发最热闹的方向,除了写代码、画图、做客服,还有一个被很多开发者忽略的品类:合规自动化。Veritas 就是这类产品中的一个代表。它的定位非常直接:用 AI 为全球初创公司持续追踪合规状态,把“我们公司现在有没有违反法规风险”这件事,从律师的收费咨询变成一套可运行、可追踪、可预警的工程系统。
合规这件事,对大型企业来说是法务部门的日常,对初创公司来说却往往是突然砸到头上的。你刚把产品上线准备进入欧盟市场,发现必须处理 GDPR;你接了美国大客户的合同,对方要求你提供 SOC 2 报告;你做了订阅制 SaaS,还得管好退款政策、税务申报和用户数据导出请求。传统做法是请律师或者用 Excel 表格跟踪,但律师贵,表格容易过期,法规又在不断更新,结果就是“看起来在管,实际靠运气”。
在拆解这类产品之前,先给一个明确判断:AI 在合规场景里的真正价值,不是替代法务人员去回答“是否违法”,而是把合规信息的采集、匹配、追踪和预警,从一次性人工操作变成可持续运行的工程流程。谁先把这件事做扎实,谁就能在全球客户和投资人面前获得明显的信任优势。
本文不打算列出 Veritas 的功能清单,因为项目材料有限,我不能替代官方文档。我更想从技术实现角度,拆解一个 AI 合规追踪工具应该具备哪些核心模块、为什么需要 AI、以及如何用 Python 搭建一个最小可运行的原型。如果你正在做全球化 SaaS、准备做 AI Agent 开发,或者单纯对“大模型 + 规则引擎”的落地组合感兴趣,这篇文章会给你一套可复用的思路。
1. 这篇文章真正要解决的问题
先说读者痛点。很多初创公司的合规工作,处于三种状态的叠加:
- 不知道要合规什么。不同国家、不同行业、不同客户类型,要求的合规项目完全不一样。刚进入一个新市场时,团队通常依赖搜索和同事口口相传,很容易漏掉关键条款。
- 无法持续追踪状态。即使知道要做 SOC 2、要更新隐私政策,合规任务也是分布在多个人的脑子里。谁负责、做到哪一步、什么时候截止,没有一个系统记录,换个人就断档。
- 法规一变,旧结论全部失效。法规不是静态的。GDPR 的执法解释在变,各州隐私法在陆续生效,云服务商的安全认证标准也在更新。今天查过没问题,不代表三个月后没问题。
Veritas 这类 AI 合规追踪器,本质上就是要解决这三件事:把合规要求结构化,把合规状态实时化,把风险变化及时预警化。
读这篇文章的读者,分为三类:
- 在做全球化 SaaS 产品或出海业务的开发者,需要建立自己的合规追踪体系。
- 从事 AI Agent、AI 大模型应用开发的工程师,想学习“大模型 + 规则引擎 + 向量检索”的组合范式。
- 产品经理或技术负责人,正在评估“自建合规系统”还是“采购商业工具”,需要理解技术边界和成本。
这篇文章的价值在于:你不需要先买一套商业系统,而是可以从一个最小原型开始,理解合规追踪的底层逻辑。等真正理解了核心机制,再决定是自建还是采购,会更稳妥。
2. 合规追踪的核心概念与 AI 的能力边界
2.1 合规追踪到底在追踪什么
合规追踪不是简单的“清单勾选”。在一个典型场景里,系统要追踪四层内容:
- 法规层:GDPR、CCPA、SOC 2、ISO 27001、各国数据保护法、行业监管要求。
- 公司事实层:公司注册地、业务开展地区、数据存储位置、员工数量、营收规模、客户合同类型。
- 义务层:由法规和公司事实共同推导出的具体义务,比如“处理欧盟用户数据的企业,必须提供数据导出接口”。
- 执行层:对应义务产生的任务、负责人、截止日期和证据文件。
传统合规系统只做“执行层”的任务管理,也就是把义务列表放到看板里跟踪。但真正的难点在“义务层”:它需要根据不断变化的法规和公司事实,动态推导出当前应该满足哪些要求。这正是 AI 可以发挥价值的地方。
2.2 AI 在合规链路中的三个可用位置
把整个流程拆开,AI 至少可以在三个位置介入:
第一,法规文本的理解与抽取。法律条文天然冗长、复杂,人工阅读成本高。大模型可以将一段法规文本提取为结构化要求,包括适用对象、必须完成的动作、时间期限等。
第二,公司事实与法规的匹配。判断“这家公司是否适用某条法规”,过去依赖人工判断,现在可以通过大模型加检索增强的方式,先从法规库中召回候选条款,再逐条判断相关性。
第三,风险评分与预警文案生成。当合规任务逾期、证据缺失、法规更新时,AI 可以自动生成风险摘要和修复建议,减少法务或运营人员的重复劳动。
但也要清醒认识 AI 的边界。合规是强风险场景,大模型存在幻觉风险。你不能让模型完全自主判断“某公司是否违法”,这既不可靠,也不符合负责任 AI 的原则。更合理的设计是:AI 负责生成候选和解释,规则引擎负责确定性检查,人工负责最终复核。
2.3 传统方案与 AI 方案的对比
| 维度 | 人工 + Excel | 传统规则系统 | AI 驱动系统 |
|---|---|---|---|
| 法规解读 | 依赖律师或法务,成本高 | 需要人工把法规写成规则 | LLM 辅助抽取,效率高 |
| 规则维护 | 经常过期 | 规则需要人工更新 | 法规库重新导入后可自动生成候选规则 |
| 匹配判断 | 取决于个人经验 | 只能处理结构化字段 | 能理解非结构化文本 |
| 可解释性 | 依赖人的说明 | 高,规则透明 | 中,需要附上原文和提示词上下文 |
| 风险 | 遗漏风险高 | 漏规则就漏检 | 幻觉风险需要人工复核 |
| 成本 | 随业务规模线性增长 | 初始建设成本高 | 初始建设成本适中,持续使用成本取决于调用量 |
从这张表可以看出,AI 驱动系统并不完美,但在“法规理解”和“事实匹配”这两个环节,它确实把成本降低了一个量级。这也是这类产品存在的核心理由。
3. 整体架构设计:一个 AI 合规追踪器的分层方案
在设计一个类似 Veritas 的 AI 合规追踪系统时,我建议采用分层架构。这里写的是思路,不绑定任何特定平台。
数据接入层 -> 合规知识库 -> AI 理解层 -> 规则引擎层 -> 追踪与预警层 -> 审计与呈现层- 数据接入层:负责采集公司事实数据。包括公司注册信息、产品页面 URL、隐私政策文档、员工规模、业务地区、客户合同等。来源可以是人工填写、API 接入或定期爬取。
- 合规知识库:保存各法域法规原文、摘要、版本号、生效日期、适用条件。这是整个系统的“法律底座”,需要版本化管理。
- AI 理解层:使用大模型做法规条款抽取、公司事实匹配、风险解释。所有模型输出都需要保留原始上下文,方便追溯。
- 规则引擎层:处理确定性的检查项,比如“隐私政策 URL 是否存在”“备份策略是否为空”“证书是否到期”。它的特点是确定、快速、可解释,是系统的安全底线。
- 追踪与预警层:把 AI 生成的合规任务、规则引擎的检查结果汇总,生成待办、设置截止日期、触发邮件或 webhook 通知。
- 审计与呈现层:记录每次 AI 判断的输入输出,形成审计日志;用仪表盘展示各法域合规状态和风险评分。
这样设计的好处是:AI 层负责处理不确定性,规则层负责确定性,审计层负责可信度。每一层都可以独立测试和替换。
4. 环境准备与基础配置
这一节开始进入实操。下面是一个本地即可运行的 Python 原型,脚本不依赖重型的微服务架构,适合作为学习起点。
4.1 运行环境
- 操作系统:Windows / macOS / Linux 均可
- Python 版本:3.10 或以上
- 包管理工具:pip 或 uv
4.2 依赖安装
pip install openai chromadb说明:
openai用于调用大模型接口,也可以换成其他兼容 OpenAI 协议的 SDK。下文代码中只需要关注chat.completions.create的调用方式。chromadb用于本地向量检索。它是一个轻量级向量数据库,适合原型阶段。生产环境再根据数据规模考虑更多选择。
4.3 项目目录结构
为了让代码清晰,我们建立如下目录结构:
compliance-tracker/ ├── compliance_engine.py ├── llm_extractor.py ├── vector_store.py ├── risk_score.py └── main.py接下来逐个文件实现。
5. 核心模块实现:一个可运行的 AI 合规追踪原型
5.1 合规规则引擎
规则引擎是整个系统的“确定性骨架”。它的职责非常简单:输入一个公司事实快照,输出每个合规检查项的通过状态。
# compliance_engine.py from dataclasses import dataclass from datetime import datetime, date from typing import Any @dataclass class ComplianceRule: rule_id: str name: str jurisdiction: str check_type: str target: str severity: str = "medium" class ComplianceEngine: def __init__(self, rules: list[ComplianceRule]): self.rules = rules def evaluate(self, snapshot: dict[str, Any]) -> list[dict[str, Any]]: results = [] for rule in self.rules: passed, detail = self._check(rule, snapshot) results.append({ "rule_id": rule.rule_id, "name": rule.name, "jurisdiction": rule.jurisdiction, "severity": rule.severity, "passed": passed, "detail": detail, "checked_at": datetime.utcnow().isoformat(), }) return results def _check(self, rule: ComplianceRule, snapshot: dict[str, Any]) -> tuple[bool, str]: if rule.check_type == "field_exist": value = snapshot.get(rule.target) if value is None or value == "": return False, f"字段 {rule.target} 缺失" return True, f"字段 {rule.target} 存在" if rule.check_type == "date_before": deadline = snapshot.get(rule.target) if deadline is None: return False, f"字段 {rule.target} 缺失,无法判断日期" try: deadline_date = datetime.fromisoformat(deadline).date() except ValueError: return False, f"字段 {rule.target} 不是合法日期" return deadline_date >= date.today(), f"截止日期为 {deadline_date.isoformat()}" return False, f"未知检查类型 {rule.check_type}"这段代码的核心是_check方法,它把规则检查拆成两种常见类型:
field_exist:检查公司快照里某个字段是否存在,比如隐私政策 URL、DPA 文档链接。date_before:检查某个截止日期是否已经过期,比如安全认证复审日期、年度审计日期。
这种设计的好处是规则可以被持久化存储,比如存到数据库或 YAML 文件,运行时加载成ComplianceRule对象。接下来在主程序中定义几条演示规则并调用。
# main.py 片段 from compliance_engine import ComplianceEngine, ComplianceRule rules = [ ComplianceRule( rule_id="gdpr_01", name="隐私政策页面存在", jurisdiction="EU", check_type="field_exist", target="privacy_policy_url", severity="high", ), ComplianceRule( rule_id="gdpr_02", name="数据保留期限声明存在", jurisdiction="EU", check_type="field_exist", target="data_retention_policy", severity="medium", ), ComplianceRule( rule_id="soc2_01", name="安全认证复审日期在有效期内", jurisdiction="US", check_type="date_before", target="security_review_date", severity="high", ), ] engine = ComplianceEngine(rules) company_snapshot = { "privacy_policy_url": "https://example.com/privacy", "data_retention_policy": "", "security_review_date": "2025-11-30", } results = engine.evaluate(company_snapshot) for item in results: print(item)运行这个片段,你会看到:
{"rule_id": "gdpr_01", "name": "隐私政策页面存在", "jurisdiction": "EU", "severity": "high", "passed": true, "detail": "字段 privacy_policy_url 存在", "checked_at": "2025-01-15T10:00:00.000Z"} {"rule_id": "gdpr_02", "name": "数据保留期限声明存在", "jurisdiction": "EU", "severity": "medium", "passed": false, "detail": "字段 data_retention_policy 缺失", "checked_at": "2025-01-15T10:00:00.000Z"} {"rule_id": "soc2_01", "name": "安全认证复审日期在有效期内", "jurisdiction": "US", "severity": "high", "passed": true, "detail": "截止日期为 2025-11-30", "checked_at": "2025-01-15T10:00:00.000Z"}规则引擎很直白,却已经能支撑非常多的合规检查场景。真正需要 AI 的是更上层的“法规条款如何变成规则”和“自由文本如何匹配事实”。
5.2 大模型抽取法规要求
法规条文通常是几页到几十页的文本。人工阅读并提取“企业必须做什么”非常耗时,用大模型生成结构化提取结果,是合规 AI 里典型的高性价比场景。
# llm_extractor.py import json from openai import OpenAI client = OpenAI() MODEL_NAME = "gpt-4o-mini" def extract_requirements(legal_text: str) -> list[dict]: prompt = f""" 你是一名专业的合规分析助手。请阅读以下法规或合同文本,抽取所有对企业提出的合规要求。 要求: 1. 只输出 JSON 数组,每个元素包含以下字段: - title: 要求标题 - description: 要求的具体描述 - action_needed: 企业需要完成的动作 - deadline_hint: 截止时间或期限线索,没有就写 null - applicable: 适用企业类型 2. 不要输出任何解释性文字。 文本: {legal_text} """ response = client.chat.completions.create( model=MODEL_NAME, messages=[{"role": "user", "content": prompt}], temperature=0.1, response_format={"type": "json_object"}, ) content = response.choices[0].message.content try: data = json.loads(content) if isinstance(data, dict) and "requirements" in data: return data["requirements"] if isinstance(data, list): return data return [] except json.JSONDecodeError as e: raise ValueError(f"模型输出不是合法 JSON: {e}\n{content}")这段代码有四个关键点:
- temperature 设为 0.1:合规场景需要低随机性,尽量让输出稳定。
- prompt 里限定输出结构:明确要求 JSON 字段,避免模型自由发挥。
- response_format 开启 JSON 模式:不是所有接口都支持,但支持时能显著降低解析失败率。
- 解析失败要报错:在生产环境里,可以把失败内容记录到日志,进入人工复核队列,而不是静默忽略。
用一段简单的 GDPR 文本测试时,模型可能输出类似下面的结构:
[ { "title": "用户数据访问权支持", "description": "企业必须支持用户随时访问其个人数据副本。", "action_needed": "开发数据导出接口,并在帮助中心说明申请方式。", "deadline_hint": null, "applicable": "面向欧盟用户提供服务的所有企业" } ]注意,模型输出的是候选要求,不是直接写进系统的最终规则。正确的做法是把候选输出作为草稿,经过合规负责人确认后再落库。这个“人机协同”的设计是整个系统风险控制的关键。
5.3 向量检索与风险评分
法规库会随着业务扩张越积越多。当新增一个新市场时,我们需要找出与该市场最相关的法规条款,再交给大模型判断适用性。这一步可以用向量检索实现。
# vector_store.py import chromadb client = chromadb.PersistentClient(path="./compliance_db") collection = client.get_or_create_collection(name="regulations") def add_regulation(doc_id: str, text: str, metadata: dict | None = None): collection.upsert( ids=[doc_id], documents=[text], metadatas=[metadata or {}], ) def search_regulations(query: str, top_k: int = 5) -> list[dict]: result = collection.query(query_texts=[query], n_results=top_k) docs = [] for i, doc in enumerate(result["documents"][0]): docs.append({ "id": result["ids"][0][i], "text": doc, "distance": result["distances"][0][i] if result.get("distances") else None, "metadata": result["metadatas"][0][i] if result.get("metadatas") else {}, }) return docs用法很简单:先把法规原文通过add_regulation写入本地数据库,查询时用search_regulations("We plan to support EU users and need GDPR check"),就能得到与这个问题最相关的条款。
向量检索的价值在于解决“不知道要看哪条法规”的问题。传统搜索依赖精确关键词,而法规表达灵活,同一件事在不同法域有完全不同表述。向量检索可以召回语义相近的条款,再由后续的 AI 层精细化判断。
为了让风险状态更直观,还需要把规则引擎的结果汇总成风险评分。
# risk_score.py def compute_risk_score(results: list[dict]) -> dict: severity_weight = {"low": 1, "medium": 3, "high": 5} total_weight = 0.0 failed_weight = 0.0 for item in results: weight = severity_weight.get(item.get("severity"), 1) total_weight += weight if not item.get("passed"): failed_weight += weight score = round(failed_weight / total_weight * 100, 2) if total_weight else 0.0 return { "failed_items": sum(1 for item in results if not item.get("passed")), "total_items": len(results), "risk_score": score, }风险评分的设计原则是:高风险项权重更高。这比简单计算“通过率”更符合合规场景的真实逻辑——一个高危违规事件的后果,可能抵得上十个低危事项。
6. 运行结果与效果验证
6.1 运行主程序
把上面几个模块串起来,我们可以跑一个简单示例。假设公司快照如下:
- 隐私政策 URL 存在
- 数据保留策略缺失
- 安全认证复审日期未过期
- 准备进入欧盟市场,需要检索相关法规
# main.py from compliance_engine import ComplianceEngine, ComplianceRule from risk_score import compute_risk_score from vector_store import search_regulations rules = [ ComplianceRule("gdpr_01", "隐私政策页面存在", "EU", "field_exist", "privacy_policy_url", "high"), ComplianceRule("gdpr_02", "数据保留期限声明存在", "EU", "field_exist", "data_retention_policy", "medium"), ComplianceRule("soc2_01", "安全认证复审日期在有效期内", "US", "date_before", "security_review_date", "high"), ] company_snapshot = { "privacy_policy_url": "https://example.com/privacy", "data_retention_policy": "", "security_review_date": "2025-11-30", } results = ComplianceEngine(rules).evaluate(company_snapshot) print("检查结果:") for item in results: print(f"[{'通过' if item['passed'] else '未通过'}] {item['name']} ({item['jurisdiction']}) - {item['detail']}") print("\n风险评分:") print(compute_risk_score(results)) print("\n法规检索结果:") hits = search_regulations("GDPR requirements for a startup handling EU user data") for hit in hits: print(f"- {hit['id']}: {hit['text'][:80]}")6.2 如何判断成功
一个合规追踪系统是否跑通,不建议只看代码运行不报错,可以从以下三个层面验证:
- 确定性检查准确:规则引擎对字段缺失、日期过期的判断必须完全准确,这是系统的安全底线。
- 模型输出可解析:大模型抽取结果的 JSON 解析成功率要尽量接近 100%,失败时必须有清晰的错误日志进入人工复核。
- 检索结果相关:用问题查询法规库时,Top 5 结果应该包含与问题语义相关的条款,而不是不相关文本。
如果运行失败,第一步要看的不是主程序逻辑,而是模型返回的原始内容。打印content,确认是 JSON 结构问题、字段值问题,还是接口调用超时。这类问题在合规系统中非常常见,尤其是当法规文本很长、包含大量引号或换行时,JSON 解析最容易出错。
7. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 模型返回内容不是合法 JSON | 模型输出被截断,或 prompt 未严格限制输出格式 | 打印原始 content,查看是截断还是格式错误 | 缩短输入文本;如果接口支持,启用 response_format;增加重试逻辑 |
| 同样的法规文本,两次抽取结果不一致 | 温度参数过高,或模型版本波动 | 检查请求中的 temperature 参数 | 将 temperature 降到 0.1 以下,并固定模型版本 |
| 检索结果与问题不相关 | 法规文本没有正确写入向量库 | 检查 add_regulation 时的文本与 metadata | 确认写入的文本质量,去掉页眉页脚等噪音 |
| 规则引擎未检查出缺失字段 | 公司快照中字段命名不一致 | 打印传入引擎的 snapshot 实际 | 建立字段映射表,统一字段命名 |
| 高风险项没有在评分中体现 | 权重配置错误 | 检查 risk_score.py 中 severity 映射 | 确保 severity 字段传入规则引擎 |
| 模型幻觉导致错误建议 | 大模型本身的不确定性 | 保留模型输出的原始上下文和提示词 | 设置“高风险判断必须人工复核”流程,不让 AI 直接执行动作 |
| 数据隐私风险 | 公司敏感数据发送到外部模型接口 | 检查请求体是否包含真实客户信息 | 先脱敏再调用模型,必要时候使用私有化部署模型 |
对于最后一项,需要特别强调:合规系统处理的数据本身就是要保护的数据。如果公司处于欧洲市场,把真实用户个人数据直接发送给外部大模型,可能反过来违反数据保护法规。更稳妥的做法是先用规则引擎和本地脚本完成大部分确定性检查,只把脱敏后的政策摘要发送给大模型。
8. 最佳实践与工程建议
8.1 规则引擎优先,AI 兜底
合规场景的正确姿势是用规则引擎处理确定性判断,用 AI 处理非结构化理解。不要把规则写进 prompt 让大模型判断“日期是否过期”,这类逻辑用代码更可靠。规则引擎的另一个优点是便于测试,你可以在 CI 里跑全量规则回归。
8.2 保留审计日志和原始上下文
AI 判断必须可追溯。每次调用大模型时,建议记录:
- 输入文本的前后文
- 使用的 prompt 版本
- 模型名称和参数
- 输出结果
- 最终是否经过人工确认
这样即使后来发现判断错误,也能回查是哪一步出了问题。
8.3 建立法规库版本化机制
法规会更新,合规结论会失效。你不能只存“当前生效法规”,还要记录“该法规从哪个时间点开始生效”“版本之间有什么变化”。最直接的做法是给每条法规加effective_date和version字段。每次重新计算某公司合规状态时,只使用当时生效的法规版本。
8.4 设计人工复核队列
AI 生成的合规任务,不一定要全部自动创建。更稳妥的做法是:系统生成“候选合规项”,合规负责人确认后变为“正式合规项”。人工复核队列要展示四个信息:法规原文、AI 摘要、公司事实、判断置信度。置信度低的项优先人工处理。
8.5 最小闭环起步
不要一上来就把所有法域和所有法规都接入。建议先选一个法域、一个典型法规、10 条规则,跑通“数据采集 -> 规则检查 -> 风险评分 -> 预警通知”的最小闭环。验证准确率和误报率后,再逐步扩展。这样能避免系统变成一个难以维护的“规则废墟”。
8.6 接口调用要降级容错
大模型接口不是 100% 可用的。合规系统每天可能依赖多次模型调用,必须做超时、重试、熔断。更关键的是:当模型接口不可用时,系统应该退回到纯规则引擎模式,而不是什么都不做。这样至少保证确定性检查不中断。
9. 总结与后续学习方向
在全球业务复杂度持续增加的背景下,AI 驱动的合规追踪会从“加分项”变成“必备项”。但对于开发者来说,核心不是追赶概念的潮流,而是掌握一套可落地的技术框架:用规则引擎守住确定性,用大模型处理非结构化理解,用向量检索解决法规召回,用审计日志保证可信度。这四件事相互配合,才是合规 AI 系统的真正地基。
如果你准备继续实践,可以从三个方向深入:
- 把它接到真实业务数据:比如用接一个自动化采集隐私政策页面的服务,让规则引擎定期重新评估。
- 完善预警机制:把合规检查结果接到邮件、Slack 或企业微信 webhook,让风险可以在第一时间触达负责人。
- 研究法规库的版本更新:这是合规系统最容易被忽视、却最能体现工程能力的地方。
合规追踪不是一个“一口气做完”的项目,而是一个需要持续迭代的系统。建议收藏这篇文章,从最小闭环开始,先把第一批规则和第一版风险评分跑起来,再根据实际业务的合规反馈逐步完善。准确率和误报率不是靠理论推出来的,而是通过真实数据不断校准出来的。