☰
NeMo Guardrails 可观测性实战:基于 OpenTelemetry 与 FileSystem 适配器的交互追踪指南
2026/9/29 2:49:28 网站建设 项目流程
  • 人工智能
  • 大模型
  • AI 安全治理
  • 模型安全
  • 内容安全
  • 提示词注入防护
  • RAG

【免费下载链接】Guardrails

NeMo Guardrails is an open-source toolkit for easily adding programmable guardrails to LLM-based conversational systems.

项目地址:https://gitcode.com/gh_mirrors/ne/Guardrails
点击查看免费下载

本文以 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-sdk

2. 运行仓库自带的完整示例

仓库在 examples/configs/tracing/ 目录下提供了一个开箱即用的可运行示例:

cd examples/configs/tracing/ python working_example.py

运行后,追踪结果会立即打印到控制台,无需任何外部基础设施。该示例(working_example.py)的完整流程是:

  1. setup_opentelemetry():在应用侧配置 OpenTelemetry SDK——创建一个带service.name(nemo-guardrails-example)、service.version、deployment.environment的Resource,注册TracerProvider,并挂上ConsoleSpanExporter与BatchSpanProcessor;
  2. create_guardrails_config():用RailsConfig.from_content定义一个"问候"对话 flow,同时通过config={"tracing": {"enabled": True, "adapters": [{"name": "OpenTelemetry"}]}}开启追踪;
  3. 调用rails.generate(...)触发一次真实交互,生成并导出 spans;
  4. 最后调用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模型承载,包含以下字段:

配置字段默认值说明
enabledfalse总开关,是否启用追踪。
adapters默认一个LogAdapterConfig追踪适配器列表。若未指定,使用默认适配器。
span_formatopentelemetryspan 格式:legacy(简单指标格式)或opentelemetry(OpenTelemetry 语义约定)。
enable_content_capturefalse是否在追踪/遥测事件中捕获 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-zipkin

3. 常见配置示例

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-otlp
from 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 官方对库与应用的职责划分最佳实践:

  1. 库只使用 API:避免配置冲突,Guardrails 不触碰 SDK 的任何全局状态;
  2. 应用掌控可观测性:由你决定 trace 发往哪里、用什么导出器、带什么资源属性;
  3. 更好的兼容性:可与任何 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/):

  1. 配置解析:RailsConfig中的tracing字段被解析为TracingConfig(config.py);
  2. 适配器实例化:create_log_adapters遍历适配器配置,经LogAdapterRegistry查表并实例化(tracer.py);
  3. 交互日志生成:Tracer.generate_interaction_log调用extract_interaction_log,把GenerationLog中的内部事件交给SpanExtractorV1/V2抽取 span,得到InteractionLog(interaction_types.py);
  4. 导出: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.

项目地址:https://gitcode.com/gh_mirrors/ne/Guardrails
点击查看免费下载

相关推荐

上一篇:devtools R包终极安装配置指南:快速上手完整教程
下一篇:Apache Spark MLlib 分类与回归算法完全指南:从逻辑回归到树集成

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询