本文以 agentic-rl-example 项目为例,介绍如何为强化学习训练配置可观测能力:添加 OpenTelemetry 依赖、接入 Tracing、在控制台查看轨迹与指标。
概述
强化学习训练基于 OpenTelemetry 实现了深度链路追踪(Tracing)。您只需在函数代码中添加少量装饰器和包装调用,训练过程中的每一次 LLM 调用、每一次工具调用、每一个评分细节都会自动记录,并导出到 ARMS(应用实时监控服务),在百炼控制台可视化展示。
可观测性能帮助您回答:
-
模型在训练中实际做了什么?—— 查看轨迹详情,回放完整对话过程
-
得分为什么高或低?—— 查看 Reward 分析的每个评分维度
-
Agent 如何调用工具?调用是否正常?—— 查看工具调用分析和 Tracing Span 详情
-
自定义指标如何变化?—— 在指标 Tab 中追踪 reward_metrics 和 rollout_metrics 的曲线
数据流:您的函数代码(@observe_processor / trace_client / trace_tool)→ OpenTelemetry SDK → ARMS → 百炼控制台(轨迹 Tab、指标 Tab)
本文范围:以 agentic-rl-example 项目(CalcX 计算器场景)为主线,演示从零配置到控制台查看效果的完整流程。训练提交和超参数配置的完整说明请参见强化学习训练配置。
接入 Tracing
以下以 agentic-rl-example 的 CalcXRolloutProcessor 为例,3 步完成 Tracing 接入。
Step 1:添加依赖
在项目根目录的 requirements.txt 中添加以下 OpenTelemetry 相关依赖:
opentelemetry-api==1.41.1
opentelemetry-sdk==1.41.1
opentelemetry-exporter-otlp-proto-http==1.41.1
opentelemetry-processor-baggage==0.62b1
loongsuite-util-genai==0.4.0
dashscope、fastapi、uvicorn、pyyaml 已预装在运行环境中,无需列入 requirements.txt。
Step 2:添加观测代码
代码改动集中在 5 个装饰器/函数。它们会自动嵌套,形成完整的调用链:
[ENTRY: ROLLOUT] @observe_processor ← Rollout 处理器入口
├── [LLM] trace_client / @observe_llm ← LLM 调用
│ └── (OpenAI / LangChain / DashScope API)
├── [TOOL] trace_tool / @observe_tool ← 工具调用
│ ├── tool: calculator (MCP)
│ └── tool: response_scorer (自定义)
└── [custom] rollout_metrics ← Rollout 自定义指标
[ENTRY: REWARD] @observe_processor ← Reward 处理器入口
├── [LLM] trace_client / @observe_llm ← LLM 调用(评分用)
├── [TOOL] trace_tool / @observe_tool ← 工具调用
└── [custom] reward_metrics ← Reward 自定义指标
@observe_processor — 追踪处理器入口
加在 process() 方法上,创建顶层 ENTRY Span。SDK 根据父类自动识别类型:继承 AbstractRolloutProcessor → ROLLOUT 类型,继承 AbstractRewardProcessor → REWARD 类型。自动记录每次调用的输入、输出、耗时、成功/失败状态。
Rollout 侧(functions/rollout/rollout.py):
from dashscope.finetune.reinforcement.component.observability import (
observe_processor
)
class CalcXRolloutProcessor(AbstractRolloutProcessor):
@observe_processor # Span 类型 = ROLLOUT
async def process(self, input: RolloutInput) -> RolloutOutput:
await self._async_setup()
return await self._async_process(input)
Reward 侧(functions/reward/reward.py):
class DemoRewardProcessor(AbstractRewardProcessor):
@observe_processor # Span 类型 = REWARD
async def process(self, input: RewardInput) -> RewardOutput:
score = await evaluate(content, input.ground_truth)
return RewardOutput(
reward=Reward(
reward_score=score,
reward_metrics={"test1": 0.5, "test2": 0.3}
),
status=TaskStatus.SUCCESS,
)
trace_client() — 追踪 LLM 客户端
在初始化方法中调用,包装 LLM 客户端实例。之后该客户端的所有 LLM 请求都会自动产生 LLM Span,记录模型名、请求内容、Token 用量、延迟等。
支持的客户端类型(鸭子类型自动检测):
-
OpenAI 客户端(
AsyncOpenAI/OpenAI) -
OpenAI completions 资源(
.chat.completions) -
LangChain ChatOpenAI 等类(通过
.client/.async_client) -
DashScope Generation 类(传入类本身,非实例)
示例(functions/rollout/rollout.py):
from langchain_openai import ChatOpenAI
from dashscope.finetune.reinforcement.component.observability import (
trace_client
)
class CalcXRolloutProcessor(AbstractRolloutProcessor):
def _build_llm(self, input: RolloutInput) -> ChatOpenAI:
llm = ChatOpenAI(
model=input.model_resource.model_name,
openai_api_key=api_key,
openai_api_base=input.model_resource.base_url,
...
)
trace_client(llm) # 包装后自动追踪所有 LLM 调用
return llm
trace_tool() — 追踪工具调用
在获取工具实例后调用,包装工具对象。之后每次工具调用都会产生 TOOL Span,记录工具名、参数、返回值、延迟。
支持的输入格式:
-
单个 LangChain BaseTool
-
列表 / 元组 / 字典(自动遍历)
-
LangGraph ToolNode(自动展开
.tools_by_name) -
MCP 工具(自动检测,provider 设为 "mcp")
示例(functions/rollout/rollout.py):
from dashscope.finetune.reinforcement.component.observability import (
trace_tool
)
class CalcXRolloutProcessor(AbstractRolloutProcessor):
async def _init_resources_async(self):
client = MultiServerMCPClient({
"calculator": {"url": "http://localhost:10086/sse"}
})
tools = await client.get_tools()
trace_tool(tools) # 必须在 get_tools() 之后调用
MCP 特别注意:MCP Server 和 Client 运行在不同进程中。Server 端的 @observe_tool 对 Client 端无效。必须在 Client 端调用 get_tools() 之后,对返回的工具列表执行 trace_tool(tools)。
@observe_llm — 自定义 LLM 函数
当 trace_client() 无法自动检测您的 LLM 客户端时,用此装饰器手动标记 LLM 调用函数。
签名要求:函数必须包含 * 后的关键字参数 model 和 messages。
from dashscope.finetune.reinforcement.component.observability import (
observe_llm
)
@observe_llm # 标记为 LLM Span
async def call_custom_llm(*, model: str, messages: list, **kwargs):
# 自定义 LLM 调用逻辑
...
@observe_tool — 自定义工具函数
当 trace_tool() 无法自动检测您的工具时(如普通 Python 函数充当工具),用此装饰器手动标记。可通过 name 参数自定义 Span 名称。
from dashscope.finetune.reinforcement.component.observability import (
observe_tool
)
@observe_tool(name="response_scorer") # 标记为 TOOL Span
def score_response(*, messages: list) -> float:
# 自定义评分逻辑
...
Step 3:提交任务
提交任务时,Runtime 的 env 字段留空即可——链路追踪默认开启:
from dashscope.finetune.agentic_rl import AgenticRL
from dashscope.finetune.reinforcement import (
RolloutFunctionComponent, RewardFunctionComponent,
FunctionComponentModel, FunctionComponentRuntime
)
client = AgenticRL()
rollout_runtime = FunctionComponentRuntime(
cpu=2, memory_size=4096, disk_size=512,
concurrency=30, capacity=30,
min_capacity=30, max_capacity=60,
env={} # 留空 = 默认开启 Tracing
)
reward_runtime = FunctionComponentRuntime(
cpu=2, memory_size=4096, disk_size=512,
concurrency=30, capacity=30,
min_capacity=30, max_capacity=60,
env={}
)
result = await client.run(
model="qwen3.5-9b",
functions=[
RolloutFunctionComponent(
name="rollout-1",
fcmodel=FunctionComponentModel(
classpath="functions.rollout.rollout.CalcXRolloutProcessor"),
runtime=rollout_runtime,
),
RewardFunctionComponent(
name="reward-1",
weight=1.0,
fcmodel=FunctionComponentModel(
classpath="functions.reward.reward.DemoRewardProcessor"),
runtime=reward_runtime,
),
],
...
)
如需关闭 Tracing(节省成本),在 env 中设置 {"ENABLE_TRAJECTORY": "false"} 即可。关闭后 Actor/Critic/Perf 等系统指标不受影响,仅链路追踪数据停止采集。
自定义指标
在代码中通过以下入口定义的 key-value 指标,会自动出现在控制台指标 Tab 的 trace/ 分组和Reward 分析页面:
|
入口 |
代码位置 |
控制台路径 |
|
reward_metrics |
|
|
|
rollout_metrics |
|
|
|
子维度评分 |
|
合并到对应 Reward 函数的 |
多 Reward 函数场景:通过 RewardFunctionComponent(name="reward-1") 为每个 Reward 函数设置唯一名称,在指标路径中区分(trace/reward_metrics/reward-1/...)。还可以通过 reward_metric_weight 细分子指标在综合评分中的权重。
控制台查看效果
训练开始后,在百炼控制台进入模型调优页面,点击任务名称进入详情,即可看到观测数据。以下说明"您在代码中做了什么 → 在控制台看到什么"的对应关系。
轨迹详情 — 对应 @observe_processor
在轨迹 Tab 的轨迹详情子页面,可以看到每次 Rollout 的完整交互过程:
-
轨迹列表:展示所有采样轨迹,支持按 Sample ID / 轨迹 ID / Epoch / Step 筛选
-
对话过程:完整的多轮交互(user → assistant → tool_call → tool_result → assistant),直观看到模型的推理链
-
Reward 分数:每个 Step 显示对应的 Reward 分数和状态(SUCCESS/FAILED)
工具调用分析 — 对应 trace_tool / @observe_tool
在轨迹 Tab 的工具调用分析子页面,可以查看:
-
工具调用记录:工具名称、调用参数、返回结果和耗时
-
Tracing 子 Tab:每条轨迹的 Span 树,可展开查看每次工具调用和 LLM 请求的完整详情
典型用途:排查 Agent 的工具调用失败——哪个工具报错?参数传递是否正确?耗时是否过长?
Reward 分析 — 对应 reward_metrics
在轨迹 Tab 的Reward 分析子页面,从三个维度评估训练效果:
-
Step 维度:选择训练 Step,查看该 Step 下所有样本的 Reward 聚合(平均分、成功率、趋势图),判断整体训练趋势
-
Sample 维度:选择 Sample ID,查看同一样本在不同轨迹中的 Reward 对比,发现问题样本
-
Trajectory 维度:查看单条轨迹的每个评分维度原始分,用于归因分析
指标 Tab — 对应 rollout_metrics / reward_metrics
在指标 Tab 的 trace/ 分组,可以看到您在代码中定义的所有自定义指标的聚合曲线(avg / sum)。
除了 trace/ 分组(40 个指标,含用户自定义),以下系统分组也与 Agent 行为分析密切相关:
-
actor/(8 个):策略网络指标 — loss、entropy、KL 散度、grad_norm
-
critic/(12 个):价值网络指标 — rewards、advantages、score 的 max/mean/min
-
trajectory/(16 个):轨迹统计 — 回复长度、截断率、对话轮次
-
perf/(5 个):性能指标 — MFU、throughput、time_per_step、total_num_tokens
完整的 13 组 / 123 个训练指标说明请参见强化学习训练配置中的指标参考章节。
时间线 Tab
在时间线 Tab 查看训练各阶段(Rollout 生成、Reward 计算、模型更新、Checkpoint 保存)的起止时间和持续时长,帮助判断是否存在性能瓶颈。
常见问题
Trace 数据在哪里查看?
在百炼控制台完成 ARMS 授权后:
-
轨迹 Tab → 轨迹详情 / Reward 分析 / 工具调用分析
-
指标 Tab → trace/ 分组
Trace 看不到怎么办?
按以下顺序排查:
-
确认 Runtime
env中没有设置ENABLE_TRAJECTORY=false(默认开启,无需显式设置) -
确认已在百炼控制台授权 ARMS 服务
-
检查
requirements.txt是否包含 OpenTelemetry 相关依赖 -
检查
process()方法是否添加了@observe_processor装饰器
开启 Tracing 对性能有影响吗?
Tracing 会增加少量存储和延迟开销。建议在开发调试阶段开启,正式大规模训练时如只需看训练指标(Actor/Critic/Perf 等)而无需轨迹详情,可以关闭:在 Runtime env 中设置 {"ENABLE_TRAJECTORY": "false"}。关闭后系统指标不受影响。
如何在指标中区分不同的 Reward 函数?
通过 RewardFunctionComponent(name="reward-1") 为每个 Reward 函数设置唯一名称。该名称会出现在指标路径中(trace/reward_metrics/reward-1/...),控制台会自动按名称分组展示。
如何关闭 Tracing 以节省成本?
在 Runtime 的 env 中设置 {"ENABLE_TRAJECTORY": "false"}。可以通过 FunctionComponentRuntime(env={"ENABLE_TRAJECTORY": "false"}) 或 YAML 中设置 env: {ENABLE_TRAJECTORY: false}。