L5.3 LLMOps 特有
三维坐标
layer: L5(MLOps/LLMOps)|level: Senior|pillar: 训推框架上一篇我们把通用 MLOps 流水线搭起来了。但 LLM 带来了传统机器学习从未有过的新问题:模型权重不再是唯一可变量,Prompt 也是「代码」;输入输出都是自然语言,攻击面从结构化特征扩展到了无限语义空间。本文聚焦 LLMOps 真正「特有」的三块:Prompt 工程化、模型网关审计、护栏管线,并亲手拦下一次越权请求。
学习目标
- 前置知识:读过 L5.1(实验追踪与模型注册:MLflow Tracking / Model Registry)与 L5.2(CI/CD 流水线与安全发布:金丝雀/影子/蓝绿),知道「数据→特征→权重→服务」这条传统 MLOps 链路;了解 L6 的 RAG·Agent 基本形态(检索增强、工具调用),因为 LLMOps 的攻击面与可复现性问题大多由它们放大。无需安全/合规背景,标准库 Python 即可。
- 学完产出:① 能画出护栏的「输入→LLM→输出」双向夹层,并解释为什么它是网关层的横切关注点而非模型内部逻辑;② 能讲清「Prompt 即代码」的完整生命周期(模板→版本→评估→灰度→回滚),并说出为何线上要引用版本指针而非硬编码字符串;③ 能列举模型网关的四项核心职责(审计日志、脱敏、限速配额、多模型路由),并解释「脱敏必须发生在落库之前」的合规根因;④ 能区分 fail-closed 与 fail-open 的代价,按业务风险分级选择策略;⑤ 亲手给一个 mock LLM 网关接入双向护栏,构造注入/越权/PII 泄露三类请求并验证拦截与脱敏。
- 阅读姿势:盯住一条主线——「LLMOps 的所有特有动作,都是为了驯服『自然语言这个开放、不可穷举的可变量』」。Prompt 是可变量(要版本化),用户输入是可变量(要输入护栏),模型输出是可变量(要输出护栏),而把这三者钉在同一个可追溯锚点上的,正是模型网关。
背景与现状
传统 MLOps 管的是 数据 → 特征 → 模型权重 → 服务 这条相对「数值化、可度量」的链路。而 LLMOps(大语言模型运维) 的特有矛盾在于:系统的行为不仅由权重决定,更由 Prompt、上下文、外部工具与用户输入共同决定,而这些都是开放的自然语言——既无法穷举、也无法用一个 AUC 指标兜底。
这带来三个传统 MLOps 没有的「特有」工程命题:
- Prompt 即代码(Prompt-as-Code):一句系统提示词的改动,效果等价于一次模型微调。它必须像代码一样被模板化、版本化、A/B 测试、灰度与回滚,而不是散落在业务代码的字符串里。
- 模型网关即关口(Gateway-as-Gatekeeper):所有请求/响应都流经一个统一网关,承担审计日志、敏感信息脱敏、限速配额、多模型路由的职责——它是合规与成本治理的唯一锚点。
- 护栏即安全边界(Guardrails-as-Boundary):LLM 会被 prompt injection(提示注入)、越狱(jailbreak) 攻破,也会吐出 PII(个人身份信息)、有害内容与幻觉。必须在输入侧与输出侧架设双向护栏。
业界信号:
guardrails-ai/guardrails、NVIDIA/NeMo-Guardrails、protectai/rebuff(注入检测)、microsoft/presidio(PII 脱敏)等项目在 2023–2024 快速崛起;各大云厂商把「LLM Gateway / AI Firewall」做成独立产品。这说明——安全与治理已从「锦上添花」变成 LLM 上线的准入门槛。
原理与架构
LLMOps 的三块特有能力,本质都围绕一个核心对象:穿过网关的「请求-响应对」。我们沿着这条数据流,看它如何被版本化、被审计、被护栏拦截。
2.1 护栏的双向管线:输入护栏 → LLM → 输出护栏
护栏的核心架构是一个双向夹层:请求进 LLM 之前必须过「输入护栏」,响应出 LLM 之后必须过「输出护栏」,任一关被判定为风险则短路(fail-closed),绝不把风 险内容透传给用户。
读这张图的关键:护栏不是「LLM 内部的事」,而是网关层的横切关注点。输入护栏拦的是「用户想让模型做坏事」(注入/越狱),输出护栏拦的是「模型已经做了坏事或泄露了信息」(PII/有害/幻觉)。两道关共享同一套审计日志(带脱敏),构成可追溯的内容安全管线。
核心在于:护栏必须 fail-closed(默认拒绝)。任何一个护栏检测器自身报错或超时,正确做法是拦截并降级,而不是「检测器挂了就放行」——后者等于把安全门焊死在「常开」状态。
2.2 Prompt 工程化与版本化流
Prompt 一旦被当作代码,就要进入「模板 → 版本 → 评估 → 灰度 → 回滚」的生命周期。
核心要点:
- 模板化:把可变部分抽成变量(如
{{user_query}}、{{retrieved_context}}),Prompt 主体与业务数据分离。 - 版本化:每个 Prompt 用语义化版本号(
v1.3.0)入注册表,绑定 commit / 作者 / 评测分数,线上服务引用版本指针而非硬编码字符串。 - A/B 与灰度:新旧 Prompt 按流量比例分流,用线上指标(采纳率、人工评分、有害率)对比。
- 回滚:发现劣化时,把「线上指针」切回旧版本即可秒级回滚——这正是「Prompt 即代码」最大的 工程红利。
2.3 模型网关审计与安全
| 网关职责 | 解决的特有问题 | 典型实现要点 |
|---|---|---|
| 请求/响应日志 | 事后追溯、复现、合规审计 | 结构化落库 trace_id / 模型版本 / Prompt 版本 / token 数 |
| 脱敏(Redaction) | 日志里别把用户 PII 也存下来 | 落库前对手机号/邮箱/身份证做正则替换 |
| 限速与配额 | 防滥用、控成本(FinOps) | 按 API Key / 用户维度令牌桶限速 |
| 多模型路由 | 按成本/能力把请求分发到不同模型 | 简单问题走小模型,复杂走大模型 |
这里的关键在于:审计日志本身就是新的敏感数据源。把原始 Prompt 不脱敏地堆进日志系统,等于在合规审计的同时制造了一个更大的数据泄露面——脱敏必须发生在落库之前。
动手实践:极简代码实操
实验目标:给一个 LLM 网关接入输入护栏 + 输出护栏,然后构造越权 / 注入请求验证拦截。全程纯 CPU 可跑——用 mock LLM 替代真实模型,护栏用 Python 实现:输入侧做注入/敏感词检测,输出侧做正则 + 关键词 + PII 过滤。
3.1 环境准备
# 推荐 Python 3.11;零第三方依赖,标准库即可
python3 -m venv .venv && source .venv/bin/activate
# 本实验仅用标准库 re / dataclasses / logging,无需 pip install
python3 --version