跳到主内容
快讯直播
AI智模界
教程

模型来源合规审计:资产清点、证据链与替换演练

这篇能做出什么

先看结果。按这篇走完一遍,团队可以拿出三份可以直接给法务、采购、安全和管理层看的东西:

1. 一张模型资产台账:公司里到底有哪些地方在调用外部模型服务、用的是哪个供应商、走的是哪条通道、由谁付费、经手过哪些数据。这张表能覆盖“合同里有的”和“合同里没有的”两类,而后者通常是风险最大的部分。

2. 一个证据包目录:每一条台账记录后面都挂着一组可复核的材料,包括服务条款快照、数据驻留声明、子处理商(subprocessor)名单、配置截图或配置文件、调用日志样本。每份材料带时间戳和哈希,能证明你什么时候、以什么方式取到的。

3. 一份替换演练报告:证明当某个供应商因为政策、合规或商业原因被要求停用时,业务能在多长时间内切到备选模型,切换过程中哪些功能会退化,回滚路径是什么。

触发这件事的场景不止一种。美国若干联邦机构曾以安全审查为由停用某款中国厂商的模型服务,这类事件这几年在不同国家和行业反复出现:某个供应商突然被列入限制名单、某个 API 区域突然停止服务、某份服务条款悄悄改了数据使用条款。这些事件对企业来说,真正要回答的问题始终是同一个:如果明天必须换掉这个模型,你知不知道它被用在了哪里,能不能在两三天内切走。

这篇把这件事拆成六步,全程可以用免费工具和通用配置完成,不需要采购专门平台。

前置条件清单

动手之前,确认下面这些东西能拿到,缺哪项就先补哪项:

  • 代码仓库的只读权限(或至少能让平台方导出全部仓库的快照)。要用它做调用痕迹扫描。
  • 云账号的账单只读权限。用来发现“用个人信用卡在云市场或模型平台直购”的漏网资产。
  • 模型网关 / API 网关的访问日志。至少保留最近 30 天的请求日志,包含时间、来源服务、目标域名、状态码。
  • 各业务线的应用清单。哪怕是口头确认,也要有人能回答“你们组有没有调外部大模型”。
  • 一份合规口径(可以由法务或安全给一句话):哪些数据等级不允许出境、哪些数据等级不允许离开公司内网、哪些业务必须可审计。没有这个口径,后面所有判断都是拍脑袋。
  • 一个备选模型的可测试入口。可以是另一家公有云、可以是自建推理服务,只要能发请求就行。没有备选就没法演练,这一步不能省。
  • 一个共享目录(对象存储或 Git 仓库都可以),用于存放证据包。

工具方面,一台能联网的 Linux 或 macOS 机器、Python 3、curl、sha256sum、jq、git 就够了。

步骤一:先定口径,再动手

顺序很重要。先扫资产再定口径,会导致你扫出一堆东西却不知道怎么分类。先花半小时写清楚三件事:

第一,模型资产的判定粒度。 建议按“供应商 + 接口地址 + 模型标识 + 调用方服务”四元组来切分。同一个供应商的两个模型算两条资产,因为它们的可替换性和合规条款可能不同。

第二,证据分级。 用一套简单的 A/B/C 三级,避免每次开会都重新争论“这算不算证据”:

等级含义例子
A来自供应商官方渠道、可取回、可验证官网服务条款页面的快照 + 哈希、官方状态页历史、合同正本扫描件
B来自公司内部系统、可复现模型网关配置文件、API 调用日志导出、云账单明细
C口头说明、聊天记录、第三方转述销售口头承诺、同事转发的截图

台账里不同等级要分开标。审计报告里只把 A 级证据当作“可对外陈述的事实”,B 级用于内部核查,C 级只能当作线索。

第三,风险打分口径。 建议用四个维度各自 1–3 分,加总后排序:

  • 数据敏感度:1 = 公开数据,2 = 内部数据,3 = 个人信息或客户数据
  • 可替换性:1 = 已有多家备选且验证过,2 = 有备选但没验证,3 = 无备选
  • 供应商稳定性:1 = 有正式合同与 SLA,2 = 有账号无合同,3 = 个人账号直购
  • 证据完整度:1 = 有 A 级证据,2 = 只有 B 级,3 = 只有 C 级

总分 4–12 分。分数高的排前面处置,这就是你的审计结论落地的抓手。

步骤二:模型资产盘点

不要只查采购合同。合同只能覆盖走完采购流程的部分,而实际情况里,模型调用往往从工程团队的一次试验开始,用个人账号充了值,跑起来之后没人回头补流程。盘点要从五个互相独立的来源交叉验证:

1. 代码仓库扫描——找调用痕迹。

2. 云账单与 SaaS 账单——找付费痕迹。

3. 网关与出口日志——找实际流量痕迹。

4. 域名解析与出口 IP 观察——找“以为走了代理其实没走”的情况。

5. 各业务线自述——补充上面四个都覆盖不到的(比如某个业务在客户端里内嵌了带 key 的 SDK)。

扫描代码仓库

把各仓库拉到本地统一目录后,跑一个扫描脚本。它不追求精准,目标是“宁多勿漏”,后面再人工筛。

```python

scan_model_calls.py

用途:扫描代码库中的模型调用痕迹,输出候选清单供人工确认

用法:python scan_model_calls.py /path/to/repos model_calls.csv

import csv, os, re, sys

PATTERNS = [

("sdk", re.compile(r"\b(openai|anthropic|google\.generativeai|dashscope|zhipuai|volcengine|huggingface_hub|ollama)\b", re.I)),

("base_url", re.compile(r"base_url\s*[=:]\s*\"'", re.I)),

("endpoint", re.compile(r"https?://[a-z0-9.\-]+/(v1|api|chat/completions|embeddings)", re.I)),

("model", re.compile(r"[\"']?model[\"']?\s*[=:]\s*\"'[\"']", re.I)),

("api_key", re.compile(r"[A-Z0-9_]*(API_KEY|APIKEY|TOKEN|BASE_URL|ENDPOINT)[A-Z0-9_]*", re.I)),

]

SKIP_DIRS = {".git", "node_modules", "vendor", "dist", "build", "__pycache__", ".venv", "venv"}

EXTS = {".py", ".js", ".ts", ".tsx", ".go", ".java", ".kt", ".rb", ".php",

".yml", ".yaml", ".json", ".toml", ".ini", ".env", ".conf", ".properties"}

def iter_files(root):

for dirpath, dirnames, filenames in os.walk(root):

dirnames[:] = [d for d in dirnames if d not in SKIP_DIRS]

for fn in filenames:

if os.path.splitext(fn)[1].lower() in EXTS or fn.startswith(".env"):

yield os.path.join(dirpath, fn)

def main(root, out):

rows = []

for path in iter_files(root):

try:

text = open(path, encoding="utf-8", errors="ignore").read()

except OSError:

continue

for lineno, line in enumerate(text.splitlines(), 1):

for kind, pat in PATTERNS:

m = pat.search(line)

if m:

rows.append({

"file": os.path.relpath(path, root),

"line": lineno,

"kind": kind,

"match": (m.group(1) if m.groups() else m.group(0))[:160],

"snippet": line.strip()[:220],

})

break

with open(out, "w", newline="", encoding="utf-8") as f:

w = csv.DictWriter(f, fieldnames=["file", "line", "kind", "match", "snippet"])

w.writeheader()

w.writerows(rows)

print(f"命中 {len(rows)} 处,已写入 {out}")

if __name__ == "__main__":

main(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else "model_calls.csv")

```

跑完之后按 match 列去重,人工过一遍,把“文档里提到模型名”和“代码里真的在调”区分开。经验上,真正需要进台账的大概是命中量的十分之一。

看账单和日志

账单侧重点看三类关键词:模型 API、GPU 算力、AI 类 SaaS。云厂商的账单导出成 CSV 后用 grep 过滤即可:

```bash

账单 CSV 里筛出与模型/算力相关的条目

grep -Ei 'openai|anthropic|bedrock|vertex|azure.*openai|dashscope|model|llm|gpu|inference' billing_export.csv \

| awk -F',' '{print $0}' | sort -u > billing_ai_items.csv

```

日志侧重点是找出目标域名清单。有了完整的目标域名清单,你就知道流量到底去了哪些外部服务:

```bash

从网关访问日志中提取外部目标域名并统计调用量

假设日志为 JSON Lines,字段包含 ts / src_service / host / status

jq -r 'select(.host != null) | [.src_service, .host] | @tsv' gateway.log \

| sort | uniq -c | sort -rn | head -50 > egress_hosts.tsv

```

这一步经常有惊喜:某个“只用了 A 供应商”的服务,日志里同时出现了三个不同厂商的域名。

步骤三:建立供应商清单与证据链

台账字段设计

用 CSV 起步就够了,字段建议如下(model_id 用你内部编号,不要用供应商的模型名字当主键,因为供应商改名是常事):

```csv

asset_id,upstream_vendor,access_channel,model_identifier,owner_team,env,data_classes,residency_claim,residency_verified,contract_type,evidence_level,evidence_path,review_date,fallback_asset,risk_score,notes

M-001,<供应商A>,公有云 API,<模型标识>,客服技术组,生产,PII-低,声明为境内部署,待核,按量付费,B,evidence/M-001/,2025-01-01,M-002,7,

M-002,<供应商B>,自建推理,<模型标识>,客服技术组,预发,内部数据,完全内网,已核,自持硬件,A,evidence/M-002/,2025-01-01,,4,备选候选

```

两个字段值得单独说:residency_claim 记录供应商声称的数据驻留地,residency_verified 记录你们核实过没有。这两个永远不要合并成一个字段——审计里最有价值的发现,就是“声称”和“核实”之间的差距。

证据包目录规范和取证脚本

每条资产的证据放在一个独立目录,命名固定,内容不超过六类:

```bash

evidence_collect.sh —— 为一条件资产采集一份带时间戳的证据快照

用法:bash evidence_collect.sh evidence/M-001 https://<供应商域名>/legal/terms

set -euo pipefail

EVID="$1"

TERMS_URL="$2"

mkdir -p "$EVID"

1) 抓取条款页面(注意:动态渲染页面可能抓不全,必要时改为浏览器打印 PDF)

curl -sSL --max-time 30 -A "compliance-audit-bot" "$TERMS_URL" -o "$EVID/terms.html" || true

2) 抓取子处理商页面(很多供应商把名单单列一页)

curl -sSL --max-time 30 -A "compliance-audit-bot" "${TERMS_URL%/legal/terms}/legal/subprocessors" \

-o "$EVID/subprocessors.html" || true

3) 记录取证时间、取证人和来源地址

{

echo "collected_at_utc: $(date -u +%Y-%m-%dT%H:%M:%SZ)"

echo "collected_by: $(whoami)"

echo "source_url: $TERMS_URL"

echo "method: curl + browser-pdf"

} > "$EVID/collection_log.txt"

4) 生成哈希清单,证明文件此后未被修改

sha256sum "$EVID"/* > "$EVID/SHA256SUMS"

cat "$EVID/SHA256SUMS"

```

几个实操细节:

  • 条款页面多数是动态渲染的,curl 抓下来的 HTML 可能是空壳。这种情况用浏览器“打印为 PDF”,然后照样算哈希,并在 collection_log.txt 里注明取证方式是人工打印。
  • 每季度重跑一次这个脚本,把新快照存成 terms-YYYYQ1.html 这样的名字,用 diff 对比条款变更。供应商改数据使用条款时,你往往是最后知道的。
  • 证据目录本身要纳入版本管理或用对象存储的版本控制,别让它躺在某个人电脑里。

台账完整性校验

台账写完先跑一遍校验,把明显的问题拦在外面:

```python

validate_ledger.py

用途:检查台账必填字段、枚举值、以及证据目录是否存在

import csv, os, sys

REQUIRED = ["asset_id", "upstream_vendor", "access_channel", "model_identifier",

"owner_team", "env", "data_classes", "evidence_level", "evidence_path"]

ALLOWED_ENV = {"生产", "预发", "测试", "个人"}

ALLOWED_EVID = {"A", "B", "C"}

def main(path, base):

problems, seen = [], set()

with open(path, encoding="utf-8") as f:

for i, row in enumerate(csv.DictReader(f), start=2):

for k in REQUIRED:

if not (row.get(k) or "").strip():

problems.append(f"第{i}行缺少字段 {k}")

aid = row.get("asset_id", "")

if aid in seen:

problems.append(f"第{i}行 asset_id 重复:{aid}")

seen.add(aid)

if row.get("env") not in ALLOWED_ENV:

problems.append(f"第{i}行 env 取值不在允许范围:{row.get('env')}")

if row.get("evidence_level") not in ALLOWED_EVID:

problems.append(f"第{i}行 evidence_level 取值非法:{row.get('evidence_level')}")

p = row.get("evidence_path", "")

if p and not os.path.isdir(os.path.join(base, p)):

problems.append(f"第{i}行证据目录不存在:{p}")

print("\n".join(problems) if problems else "校验通过")

return 1 if problems else 0

if __name__ == "__main__":

sys.exit(main(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else "."))

```

步骤四:核查数据驻留

数据驻留核查要回答的是:请求发出去之后,数据实际经过了哪些地方、停在了哪里。 这件事不能只看合同,至少要做三层验证。

第一层:配置层

在部署环境里把实际生效的接口地址捞出来。最容易出问题的是这一层——代码里写的是供应商官网地址,但环境变量里被改成了某个第三方代理;或者代码里写的是境内地址,容器里却配了全局代理。

```bash

在部署机或容器内执行,确认实际生效的接口地址与代理设置

env | grep -Ei 'base_url|endpoint|proxy|openai|anthropic|api_host' | sort

如果是容器部署,从容器内部确认

docker exec -it <容器名> env | grep -Ei 'base_url|proxy|api'

确认容器/主机的 DNS 与出站代理

cat /etc/resolv.conf

cat /etc/hosts

```

任何在 base_url 里出现的非供应商官方域名,都要单独立项查清楚是谁在中间转发——转发的这一跳同样构成数据出境或数据交付。

第二层:网络层

看请求最终解析到哪、从哪个出口出去。注意这一层能看到的是入口节点,不一定等于存储位置,所以要结合第三层一起看。

```bash

观察模型接口域名的解析结果(在部署环境内执行)

for host in api.<供应商A域名> api.<供应商B域名>; do

echo "== $host"

getent hosts "$host" || nslookup "$host" 2>/dev/null

done

看出口 IP 的归属组织与国家(仅作线索,不能单独作为驻留结论)

for ip in $(getent hosts api.<供应商A域名> | awk '{print $1}' | head -3); do

echo "== $ip"

whois "$ip" | grep -Ei 'orgname|org-name|country|netname|descr' | head -10

done

```

如果解析结果落在某个 CDN 的任播地址上,whois 显示的国家基本没有参考价值。这种情况要退回第一层和第三层:查供应商文档里写的区域端点(region endpoint),如果有,就切换到明确的区域端点,再验证一次。

第三层:文档与合同层

对照供应商当前公开的文档核对三件事,并都存进证据包:

  • 有没有区域端点,以及你的调用有没有真的走区域端点。
  • 数据留存策略:请求内容留多久、是否用于训练、如何申请关闭。
  • 子处理商名单:模型服务商自己也可能调用第三方做审核、缓存、日志,这些转委托方同样在审计范围内。

这一步的结论写进台账的 residency_verified 字段,可选值就用“已核”“待核”“不符”三个,别搞太细。

步骤五:可替换性演练

这一步是整个审计里唯一能给出可量化答案的环节。目标不是找一个更强的模型,而是回答:“如果 M-001 明天不可用,切到 M-002 需要多久,哪些功能会掉。”

前置改造:把模型名从业务代码里拆出来

很多团队卡在这一步,因为模型标识硬编码在几十个地方。最常见的做法是加一层模型网关,业务代码只认一个内部别名,别名到真实供应商的映射放在网关配置里。

```yaml

gateway.yaml —— 统一模型出口,业务只认内部别名

字段名与能力以所用网关项目的官方文档当前版本为准

model_list:

  • model_name: chat-default # 业务代码里只出现这个名字

litellm_params:

model: openai/<供应商A的模型标识>

api_base: https://api.<供应商A域名>/v1

api_key: os.environ/PROVIDER_A_KEY

  • model_name: chat-default # 同名候选,用于分流与兜底

litellm_params:

model: openai/<供应商B的模型标识>

api_base: https://api.<供应商B域名>/v1

api_key: os.environ/PROVIDER_B_KEY

router_settings:

num_retries: 1

timeout: 30

allowed_fails: 3

cooldown_time: 60

```

如果没有网关,退一步的做法是统一环境变量名:所有服务只读 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL 三个变量,切换时改配置中心,而不是改代码。这个改造投入小,收益明确。

演练一:影子流量比对

把一批真实请求(脱敏后)同时打到 A、B 两端,记录可比指标。注意这里不追求“谁更好”,而是看可切换性:B 端能不能接住 A 端的输入形态。

```python

shadow_compare.py

用途:同一批请求同时打 A/B 两个端点,记录成功率、延迟、输出长度等可比指标

用法:A_URL=... A_KEY=... A_MODEL=... B_URL=... B_KEY=... B_MODEL=... \

python shadow_compare.py prompts.txt shadow_result.jsonl

import json, os, statistics, time, urllib.request

A = {"name": "A", "url": os.environ["A_URL"], "key": os.environ["A_KEY"], "model": os.environ["A_MODEL"]}

B = {"name": "B", "url": os.environ["B_URL"], "key": os.environ["B_KEY"], "model": os.environ["B_MODEL"]}

def call(ep, prompt, timeout=60):

body = json.dumps({

"model": ep["model"],

"messages": [{"role": "user", "content": prompt}],

"temperature": 0,

}).encode("utf-8")

req = urllib.request.Request(

ep["url"].rstrip("/") + "/chat/completions",

data=body,

headers={"Content-Type": "application/json",

"Authorization": f"Bearer {ep['key']}"},

)

t0 = time.perf_counter()

try:

with urllib.request.urlopen(req, timeout=timeout) as r:

data = json.loads(r.read().decode("utf-8"))

text = data["choices"][0]["message"].get("content") or ""

return {"ok": True, "ms": int((time.perf_counter() - t0) * 1000), "text": text}

except Exception as e: # 超时、限流、鉴权失败都走这里

return {"ok": False, "ms": int((time.perf_counter() - t0) * 1000), "err": repr(e), "text": ""}

def main(prompts_path, out_path):

prompts = [l.strip() for l in open(prompts_path, encoding="utf-8") if l.strip()]

rows = []

for p in prompts:

ra, rb = call(A, p), call(B, p)

rows.append({

"prompt": p,

"a_ok": ra["ok"], "a_ms": ra["ms"], "a_len": len(ra["text"]), "a_text": ra["text"][:2000],

"b_ok": rb["ok"], "b_ms": rb["ms"], "b_len": len(rb["text"]), "b_text": rb["text"][:2000],

})

with open(out_path, "w", encoding="utf-8") as f:

for r in rows:

f.write(json.dumps(r, ensure_ascii=False) + "\n")

both = [r for r in rows if r["a_ok"] and r["b_ok"]]

print(f"总样本 {len(rows)},双端成功 {len(both)}")

if both:

print("A 成功率 %.1f%%,中位延迟 %d ms" % (100 * sum(r['a_ok'] for r in rows) / len(rows),

statistics.median(r["a_ms"] for r in both)))

print("B 成功率 %.1f%%,中位延迟 %d ms" % (100 * sum(r['b_ok'] for r in rows) / len(rows),

statistics.median(r["b_ms"] for r in both)))

if __name__ == "__main__":

import sys

main(sys.argv[1], sys.argv[2])

```

prompts.txt 不要只放短问答。至少覆盖五类输入形态,否则演练结论会过于乐观:

1. 短问答(10 字级)

2. 长上下文(接近你线上最长的那一档)

3. 结构化输出(要求返回 JSON 的场景)

4. 工具调用 / 函数调用(如果业务在用)

5. 流式输出(如果业务在用)

演练二:真切换,掐表

影子流量只能证明“B 能返回结果”,不能证明“切过去业务不炸”。所以要安排一次真正的切换,选出一条风险最低的生产链路(比如内部知识库问答,不是对客核心流程),在低峰期执行:

```bash

切换演练的最小操作集(以环境变量注入为例)

1) 记录切换开始时间

date -u +"%Y-%m-%dT%H:%M:%SZ" | tee switch_timeline.log

2) 改配置中心的模型别名指向(或用网关的路由权重)

例如把 chat-default 的权重从 A:100% 改为 B:100%

3) 等待配置生效后,打一笔探针请求

curl -sS -X POST "$LLM_BASE_URL/chat/completions" \

-H "Authorization: Bearer $LLM_API_KEY" \

-H "Content-Type: application/json" \

-d '{"model":"'"$LLM_MODEL"'","messages":[{"role":"user","content":"ping"}],"max_tokens":16}' \

jq -r '.choices[0].message.content'

4) 记录切换完成时间,并观察 30 分钟内错误率与 P95 延迟

date -u +"%Y-%m-%dT%H:%M:%SZ" | tee -a switch_timeline.log

5) 回滚

把权重改回 A:100%,重复探针,确认业务恢复

```

演练报告里必须写清楚这几个数字:

指标记录方式
切换操作耗时switch_timeline.log 首尾时间差
业务中断时长从切走到探针成功的时间
错误率变化切换前后各 30 分钟网关错误码统计
P95 延迟变化同上,按来源服务分
功能退化清单哪些能力变差(结构化输出稳定性、长上下文、工具调用成功率)
回滚耗时从决定回滚到探针成功的时间

验收标准建议提前定好并写进报告,例如“切换操作 ≤ 30 分钟、业务中断 ≤ 5 分钟、核心链路错误率上升不超过 1 个百分点”。数字由团队自己按业务定,但一定要提前定,不能事后补。

常见坑与排错

现象常见原因处理办法
台账条数明显偏少只查了采购合同,漏掉工程团队个人账号直购用云账单 + 网关日志交叉验证;把“个人账号”作为一个独立的 env 取值显式列出
台账条数明显偏多、大部分是重复按模型名字而非四元组切分回到步骤一的粒度定义,合并同类项
驻留核查结论是“境内”,但心里没底只看了配置,没看实际出口和供应商文档三层都要做;解析落在 CDN 任播时不要下结论,改用区域端点重新验证
以为走了内网代理,实际没走容器里有全局代理变量但被 SDK 忽略,或 SDK 读了另一个变量名在容器内 `envgrep -i proxy 交叉确认;用网关日志的 host` 字段作为最终事实
条款快照打开是空白页面动态渲染,curl 抓的是空壳改用浏览器打印 PDF,并在取证日志里注明方式
演练时 B 端大量超时B 端限流配额低于 A 端,或长上下文能力不足演练前先确认 B 端的配额与上下文上限;分批压测而不是一次性打满
切换后功能“看起来正常”但输出质量下降只比了成功率,没比输出结构把结构化输出解析成功率、工具调用成功率纳入演练指标
回滚失败配置只改了一处,其他地方硬编码了模型名演练前先做硬编码清理;回滚脚本和切换脚本一起写、一起测
证据包过两个月就打不开只存了截图,没存原文和哈希原文 + 哈希 + 取证日志三件套;重要页面同时存 PDF
供应商改了子处理商名单没人发现没有定期复采机制每季度重跑取证脚本,用 diff 对比历史快照
审计做完就没人管了没有责任人也没有复审日期台账里 review_date 字段必填,到期进日历提醒

再补一个容易被忽略的坑:供应商转售。有些“小平台”其实是转售大厂能力,条款里写的数据驻留地是大厂的,但实际多经过了一跳第三方。判断方法是看接口域名和响应头里的服务标识,以及条款里是否出现“our third-party providers”这类表述。凡是出现转售链路的资产,risk_score 至少加 2 分。

下一步建议

审计做完不是终点,把下面几件事变成常态,下一次审计的成本会下降一个量级:

1. 把台账接到 CI 上。 在流水线里加一个检查:新增代码里出现新的模型域名或新的 base_url,就要求提交人在 PR 里补一条台账记录。这比事后盘点省力得多。

2. 把网关当成默认入口。 所有模型调用统一走网关,业务只认内部别名。这一步做完,“可替换”从项目管理问题变成配置问题。

3. 把演练排进日历。 建议每个季度挑一条链路做一次切换演练,一年覆盖完主要链路。演练报告归档,作为下次审计的 A 级证据。

4. 建立条款变更监控。 对清单里所有供应商的条款页和子处理商页做定期抓取加 diff,有变更就发通知。这类变更往往不打招呼。

5. 明确退出条款。 在新签或续签合同里加进去:数据删除的时限与证明方式、过渡期支持时长、模型下线前的提前通知期。这些条款在切换那一刻的价值,远高于签合同时省下的那点折扣。

6. 准备一份对外可用的说明。 一页纸,写清楚公司用了哪些模型、分别处理什么数据、驻留在哪里、备选方案是什么。客户和监管问起来,直接给这一页,比临时攒材料从容得多。

最后提醒一句:所有涉及具体供应商条款、区域端点、配额和能力的判断,都要以官方文档当前版本为准,本教程里的配置字段和命令只作结构参考。审计的价值不在于一次做得多完美,而在于结论可复核、缺口可追踪、切换可执行——这三条做到了,模型来源这件事就从“说不清”变成了“说得清”。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。