- 人工智能
- 大模型
- AI 安全治理
- 模型安全
- 内容安全
- 提示词注入防护
- RAG
【免费下载链接】Guardrails
NeMo Guardrails is an open-source toolkit for easily adding programmable guardrails to LLM-based conversational systems.
本文以 NeMo Guardrails 的追踪(Tracing)能力为主线,讲解如何启用并接入 Guardrails 交互追踪,从而监控哪些护栏被激活、观察 LLM 调用与响应、定位性能瓶颈并还原完整对话流程。读完本文,你将掌握config.yml中tracing配置项的完整写法、FileSystem 与 OpenTelemetry 两类适配器的接入方式、自定义适配器的实现方法,以及从旧版配置平滑迁移到 OpenTelemetry 最佳实践的路径。
一、什么是 Tracing:看穿 Guardrails 内部的一次交互
追踪(Tracing)解决的是"黑盒"问题:当一个用户请求进入 Guardrails,中间经历了输入护栏检查、LLM 调用、输出护栏校验、流式生成等多个环节,最终返回响应。追踪能力让你看清这条链路上发生了什么:
- 追踪哪些护栏(rail)被激活:每一次交互实际命中了哪些输入/输出护栏、哪些 flow;
- 监控 LLM 调用与响应:记录调用耗时、模型名、输入输出内容(可选);
- 调试性能问题:通过 span 的起止时间还原各环节耗时,定位慢在护栏还是慢在 LLM;
- 分析对话流:还原从用户消息到 bot 回复的完整事件序列。
从源码结构看,追踪的核心链路位于 nemoguardrails/tracing/ 目录:Tracer类负责把一次交互(InteractionOutput)与生成日志(GenerationLog)转换为InteractionLog,再交给配置好的适配器导出;span 的抽取逻辑由 span_extractors.py 中的SpanExtractorV1/SpanExtractorV2实现,它们根据activated_rails的时间信息构建出 interaction、rail、LLM 调用等 span 树。也就是说,一次交互的"内部快照"最终以InteractionLog为载体,包含activated_rails、完整事件列表events和trace(span 集合),定义见 interaction_types.py。
二、快速开始:30 秒跑通一个带追踪的示例
1. 安装追踪依赖
# 安装追踪支持(含 SDK 依赖,示例所需) pip install nemoguardrails[tracing] opentelemetry-sdk2. 运行仓库自带的完整示例
仓库在 examples/configs/tracing/ 目录下提供了一个开箱即用的可运行示例:
cd examples/configs/tracing/ python working_example.py运行后,追踪结果会立即打印到控制台,无需任何外部基础设施。该示例(working_example.py)的完整流程是:
setup_opentelemetry():在应用侧配置 OpenTelemetry SDK——创建一个带service.name(nemo-guardrails-example)、service.version、deployment.environment的Resource,注册TracerProvider,并挂上ConsoleSpanExporter与BatchSpanProcessor;create_guardrails_config():用RailsConfig.from_content定义一个"问候"对话 flow,同时通过config={"tracing": {"enabled": True, "adapters": [{"name": "OpenTelemetry"}]}}开启追踪;- 调用
rails.generate(...)触发一次真实交互,生成并导出 spans; - 最后调用
trace.get_tracer_provider().force_flush(1000)强制冲刷剩余的 span。
这里有一个关键顺序:OpenTelemetry 的 SDK 配置必须发生在 NeMo Guardrails 使用之前,因为 Guardrails 只消费已配置好的全局TracerProvider,自身不做任何 SDK 初始化。
3. 最小配置:在 config.yml 中开启追踪
在config.yml中启用追踪的最小配置:
tracing: enabled: true adapters: - name: FileSystem若要改用 OpenTelemetry(需要额外在应用代码中做 SDK 配置):
tracing: enabled: true adapters: - name: OpenTelemetry仓库中现成的示例配置位于 examples/configs/tracing/config.yml,它在启用 FileSystem 适配器的同时还指定了输出路径:
models: - type: main engine: openai model: gpt-3.5-turbo-instruct tracing: enabled: true adapters: - name: FileSystem filepath: "./traces/traces.jsonl"三、TracingConfig 配置项全解
从源码 nemoguardrails/rails/llm/config.py 可以看到,tracing配置由TracingConfig模型承载,包含以下字段:
| 配置字段 | 默认值 | 说明 |
|---|---|---|
enabled | false | 总开关,是否启用追踪。 |
adapters | 默认一个LogAdapterConfig | 追踪适配器列表。若未指定,使用默认适配器。 |
span_format | opentelemetry | span 格式:legacy(简单指标格式)或opentelemetry(OpenTelemetry 语义约定)。 |
enable_content_capture | false | 是否在追踪/遥测事件中捕获 prompt 与响应(user/assistant/tool 消息内容)。默认关闭以保护隐私、对齐 OpenTelemetry GenAI 语义约定;开启可能把 PII 与敏感数据送入遥测后端,需谨慎。 |
关于enable_content_capture的行为差异,源码注释有明确说明:
- IORails 引擎:环境变量
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT优先级最高(true/1强制开启,false/0强制关闭,其他值回退到本字段);OTEL_SEMCONV_STABILITY_OPT_IN决定输出格式(包含gen_ai_latest_experimental时输出为 JSON 编码的 span 属性,否则输出为逐消息的 span 事件)。 - LLMRails 引擎:不读取上述环境变量,仅由本字段控制,且内容始终通过已废弃的
gen_ai.content.prompt/gen_ai.content.completionspan 事件输出。
四、内置追踪适配器详解
1. FileSystem 适配器(最易上手)
将追踪记录写入本地 JSON 文件(JSONL 格式,每行一条交互记录),适合开发调试:
tracing: enabled: true adapters: - name: FileSystem filepath: "./logs/traces.jsonl"适用场景:开发、调试、简单的日志记录需求。
从源码 filesystem.py 看,该适配器有两个值得注意的实现细节:
- 默认路径:不传
filepath时,默认写入./.traces/trace.jsonl;传入时会被os.path.abspath转为绝对路径,并自动makedirs创建父目录; - 输出结构:每条记录是一个 JSON 对象,包含
schema_version、trace_id(即交互 id)和spans数组,以追加模式("a")写入文件——同一文件会累积多条交互记录,可直接用jq等工具分析。
2. OpenTelemetry 适配器
tracing: enabled: true adapters: - name: OpenTelemetry适用场景:生产环境、对接监控系统、分布式应用。
从源码 opentelemetry.py 看,OpenTelemetryAdapter严格遵循"库只用 API"的最佳实践:
- 只依赖
opentelemetryAPI(trace.get_tracer等),不修改任何全局状态,也不自行创建TracerProvider; - 构造时会检查
trace.get_tracer_provider():如果为None或NoOpTracerProvider,会发出警告提示应用尚未配置 OpenTelemetry; - span 导出时会把
InteractionLog中相对起始时间的 span 时间戳换算为绝对纳秒时间(base_time_ns取自第一个激活 rail 的started_at,回退到time.time_ns()),并按span.kind属性把字符串映射为 OpenTelemetry 的SpanKind(server/client/internal); - 事件(event)的 body 若为字典,会被合并进 OTel 事件的 attributes 中(因为 OTel 事件只有 attributes 没有独立 body)。
3. 自定义适配器
当内置适配器无法满足需求时,可以继承InteractionLogAdapter实现自己的适配器:
from nemoguardrails.tracing.adapters.base import InteractionLogAdapter class MyCustomAdapter(InteractionLogAdapter): name = "MyCustomAdapter" def transform(self, interaction_log): # 你的自定义逻辑,将 InteractionLog 转换为目标后端格式 pass从源码 base.py 看,InteractionLogAdapter是一个抽象基类,要求实现两个方法:同步的transform(interaction_log)与异步的transform_async(interaction_log)(后者在Tracer.export_async中通过asyncio.gather并发执行);同时提供close()、__aenter__/__aexit__供异步上下文管理使用。此外,registry.py 提供了register_log_adapter(model, name)用于注册自定义适配器,注册时会校验类必须是InteractionLogAdapter的子类。
配置层如何把适配器实例化?看 tracer.py 中的create_log_adapters:当config.enabled为真时,遍历config.adapters,从LogAdapterRegistry按name取出适配器类,把其余配置项(如filepath)作为构造参数实例化。
五、OpenTelemetry 生态兼容性
NeMo Guardrails 与整个 OpenTelemetry 生态兼容。下面的示例只是常见配置,实际上任何 OpenTelemetry 兼容组件都可以使用:
- Exporters:Jaeger、Zipkin、Prometheus、New Relic、Datadog、AWS X-Ray、Google Cloud Trace 等众多导出器;
- Collectors:OpenTelemetry Collector、Jaeger Collector 及自定义 Collector;
- Backends:任何能接收 OpenTelemetry traces 的系统。
完整的导出器清单可查阅 OpenTelemetry 官方生态注册表(Registry)。
六、OpenTelemetry 接入架构与安装
1. 理解职责分离的架构
这是整个接入方案的核心前提:
- NeMo Guardrails:只使用 OpenTelemetryAPI,不负责任何 SDK 初始化与导出器配置;
- 你的应用:负责配置 OpenTelemetrySDK与导出器。
因此,必须在应用代码中完成 OpenTelemetry 的配置,Guardrails 才能把 span 送出去。这种设计避免了库与应用的配置冲突,也让你自由决定 trace 的去向。
2. 按场景安装依赖
仅需追踪支持(只用 API):
# NeMo Guardrails 追踪功能的最低要求 pip install nemoguardrails[tracing]这只安装 OpenTelemetry API,如果你的应用已经自行配置了 OpenTelemetry,这一条就够用。
运行示例与开发:
# 额外包含 OpenTelemetry SDK,用于配置导出器 pip install nemoguardrails[tracing] opentelemetry-sdk生产部署:
# 安装追踪支持 pip install nemoguardrails[tracing] # 安装 SDK 与所需的导出器 # OTLP: pip install opentelemetry-sdk opentelemetry-exporter-otlp # 或 Jaeger: pip install opentelemetry-sdk opentelemetry-exporter-jaeger # 或 Zipkin: pip install opentelemetry-sdk opentelemetry-exporter-zipkin3. 常见配置示例
Console 输出(开发/测试):把 trace 打印到终端,适合开发阶段验证:
from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.sdk.resources import Resource # 配置 OpenTelemetry(必须在使用 NeMo Guardrails 之前完成) resource = Resource.create({ "service.name": "my-guardrails-app", "service.version": "1.0.0", }, schema_url="https://opentelemetry.io/schemas/1.26.0") tracer_provider = TracerProvider(resource=resource) trace.set_tracer_provider(tracer_provider) # 使用控制台导出器(打印到终端) console_exporter = ConsoleSpanExporter() span_processor = BatchSpanProcessor(console_exporter) tracer_provider.add_span_processor(span_processor) # 再配置 NeMo Guardrails from nemoguardrails import LLMRails, RailsConfig config = RailsConfig.from_content( config={ "models": [{"type": "main", "engine": "openai", "model": "gpt-3.5-turbo-instruct"}], "tracing": { "enabled": True, "adapters": [{"name": "OpenTelemetry"}] } } ) rails = LLMRails(config) response = rails.generate(messages=[{"role": "user", "content": "Hello!"}])OTLP 导出器(生产就绪):对接各类可观测性平台:
# 安装 OTLP 导出器 pip install opentelemetry-exporter-otlpfrom opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import Resource # 配置 OpenTelemetry resource = Resource.create({ "service.name": "my-guardrails-app", "service.version": "1.0.0", }, schema_url="https://opentelemetry.io/schemas/1.26.0") tracer_provider = TracerProvider(resource=resource) trace.set_tracer_provider(tracer_provider) # 配置 OTLP 导出器 otlp_exporter = OTLPSpanExporter( endpoint="http://localhost:4317", # 你的 OTLP Collector 端点 insecure=True ) span_processor = BatchSpanProcessor(otlp_exporter) tracer_provider.add_span_processor(span_processor) # 与 NeMo Guardrails 配合使用时,与 Console 示例完全相同注意:这些示例是常见配置,OpenTelemetry 支持远更多的导出器与后端。安装对应的导出器包并在应用代码中配置后,即可接入任何 OpenTelemetry 兼容的可观测性平台。
七、更多集成示例
1. Zipkin 集成
# 1. 启动 Zipkin 服务 docker run -d -p 9411:9411 openzipkin/zipkin # 2. 安装 Zipkin 导出器 pip install opentelemetry-exporter-zipkin# 3. 在应用中配置 from opentelemetry.exporter.zipkin.proto.http import ZipkinExporter zipkin_exporter = ZipkinExporter( endpoint="http://localhost:9411/api/v2/spans", ) span_processor = BatchSpanProcessor(zipkin_exporter) tracer_provider.add_span_processor(span_processor)2. OpenTelemetry Collector
创建一个 Collector 配置文件:
# otel-config.yaml receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: logging: loglevel: debug service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [logging]运行 Collector:
docker run -p 4317:4317 -p 4318:4318 \ -v $(pwd)/otel-config.yaml:/etc/otel-collector-config.yaml \ otel/opentelemetry-collector:latest \ --config=/etc/otel-collector-config.yaml八、从旧版本配置迁移
1. 旧的 OpenTelemetry 配置不再受支持
❌ 不再支持(旧写法):
tracing: enabled: true adapters: - name: OpenTelemetry service_name: "my-service" exporter: "console" resource_attributes: env: "production"✅ 受支持(新写法):在应用代码中配置 OpenTelemetry,tracing配置只负责"开启 + 指定适配器":
# 在应用代码中配置 OpenTelemetry from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter tracer_provider = TracerProvider() trace.set_tracer_provider(tracer_provider) console_exporter = ConsoleSpanExporter() span_processor = BatchSpanProcessor(console_exporter) tracer_provider.add_span_processor(span_processor) config = RailsConfig.from_content( config={ "tracing": { "enabled": True, "adapters": [{"name": "OpenTelemetry"}] } } )2. 已弃用的register_otel_exporter函数
register_otel_exporter函数已弃用,将在 0.16.0 版本移除:
# DEPRECATED - 将在 0.16.0 移除 from nemoguardrails.tracing.adapters.opentelemetry import register_otel_exporter from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter register_otel_exporter("my-otlp", OTLPSpanExporter)应改为直接在应用代码中配置导出器:
from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter tracer_provider = TracerProvider() trace.set_tracer_provider(tracer_provider) otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4318") span_processor = BatchSpanProcessor(otlp_exporter) tracer_provider.add_span_processor(span_processor)3. 为什么这样变更?
这一变更遵循 OpenTelemetry 官方对库与应用的职责划分最佳实践:
- 库只使用 API:避免配置冲突,Guardrails 不触碰 SDK 的任何全局状态;
- 应用掌控可观测性:由你决定 trace 发往哪里、用什么导出器、带什么资源属性;
- 更好的兼容性:可与任何 OpenTelemetry 配置协同工作,不受内置导出器限制。
从源码 opentelemetry.py 的类注释同样能印证这一点:"该适配器只使用 OpenTelemetry API 并依赖应用配置 SDK,不修改全局状态,也不创建自己的 tracer provider。"
九、故障排查
常见问题
没有出现任何 trace:
- 确认 OpenTelemetry 是在应用代码中配置的(仅配置 NeMo Guardrails 的
tracing是不够的); - 先用
ConsoleSpanExporter验证导出器本身工作正常; - 检查
config.yml中tracing.enabled是否为true。
OTLP 连接错误:
WARNING: Transient error StatusCode.UNAVAILABLE encountered while exporting traces to localhost:4317- 确认 Collector/端点服务正在运行;
- 测试阶段可以不依赖外部服务,直接改用
ConsoleSpanExporter。
导入错误:
ImportError: No module named 'opentelemetry'- 安装追踪依赖:
pip install nemoguardrails[tracing]; - 使用导出器还需:
pip install opentelemetry-exporter-otlp等对应包。
trace 中的服务名错误:
- 在应用代码中通过
Resource配置SERVICE_NAME(即service.name资源属性); - 旧的
service_name参数已不再生效。
十、深入源码:一次交互的追踪数据流
结合仓库源码,可以把追踪的数据流完整串联起来(对应文件均在 nemoguardrails/tracing/):
- 配置解析:
RailsConfig中的tracing字段被解析为TracingConfig(config.py); - 适配器实例化:
create_log_adapters遍历适配器配置,经LogAdapterRegistry查表并实例化(tracer.py); - 交互日志生成:
Tracer.generate_interaction_log调用extract_interaction_log,把GenerationLog中的内部事件交给SpanExtractorV1/V2抽取 span,得到InteractionLog(interaction_types.py); - 导出:
Tracer.export/export_async依次调用每个适配器的transform/transform_async,完成落盘、OTel span 创建或自定义处理。
其中 span 的语义属性抽取由 span_formatting.py 的extract_span_attributes、format_span_for_filesystem等函数完成,时间基准取自第一个激活 rail 的started_at,其余 span 的时间均为相对偏移,再由 OpenTelemetry 适配器换算为绝对纳秒时间戳。
十一、结语
NeMo Guardrails 的追踪体系遵循"库只用 API、应用控制导出"的 OpenTelemetry 最佳实践,配合 FileSystem 适配器可以零依赖地在开发阶段快速看到完整的交互内部视图;接入生产环境时,只需在应用侧配置好 OTLP/Jaeger/Zipkin 等导出器,即可让 Guardrails 交互数据融入你已有的可观测性体系。建议从仓库自带的 working_example.py 与 config.yml 起步,先用 Console 输出验证链路,再逐步替换为生产级导出器。
- 人工智能
- 大模型
- AI 安全治理
- 模型安全
- 内容安全
- 提示词注入防护
- RAG
【免费下载链接】Guardrails
NeMo Guardrails is an open-source toolkit for easily adding programmable guardrails to LLM-based conversational systems.
相关推荐
Megatron-LM 可观测性实战指南:基于 OpenTelemetry 与 nemo-lens 的 Traces、Metrics 与 Pipeline 并行追踪
Megatron LM 可观测性实战指南:基于 OpenTelemetry 与 nemo lens 的 Traces、Metrics 与 Pipeline 并行
人工智能大模型预训练分布式训练深度学习强化学习NocoBase 无代码平台开发环境从零跑通:5 分钟起本地服务,避开 3 个高频坑
NocoBase 无代码平台开发环境从零跑通:5 分钟起本地服务,避开 3 个高频坑 第一次在本地跑 yarn dev 时,终端抛出一句 EADDRINUSE,
低代码后端前端人工智能AI 应用工作流自动化OGX 可观测性实战:基于 OpenTelemetry 的指标、链路追踪与仪表盘体系
OGX 可观测性实战:基于 OpenTelemetry 的指标、链路追踪与仪表盘体系 导读:本文以 OGX(Open GenAI Stack)内置的 OpenT
AI应用API网关后端模型推理服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考