OT-Trace 数据治理模板从 OT-Trace 数据中按 traceId 组装完整对话,经三级去重、语义聚类、多样性采样、AI 评估和标注,实现 Trace 级别的 Agent 数据全链路治理。
业务场景
AI Agent 在运行过程中产生海量对话数据,直接使用存在大量重复和噪声。本模板实现 Trace 级别的完整数据治理链路,覆盖从原始 Span 数据到高质量标注数据集的全流程。
主要治理能力:
数据组装:将离散 Span 按 traceId 聚合为完整对话宽表,每行代表一条完整 Trace。
三级去重:精确去重、近似去重、语义去重逐级清洗重复数据,大幅降低数据量。
多样性采样:语义聚类 + 分组采样,确保样本覆盖多种场景。
AI 评估:对采样数据进行多维度质量评分。
AI 标注:自动标注任务类型、复杂度、业务领域等标签。
Pipeline 流程
本模板的 Pipeline 由 4 个阶段、12 个节点组成,完整算子链为:where > extend > make-instance > extend > where > dedup-exact > dedup-fuzzy > dedup-semantic > semantic-cluster > sample > llm-call x 2。
Phase 1:数据组装
将 OT-Trace 中的离散 Span 组装为完整的 Trace 级宽表。
顺序 | 节点 | 说明 |
1 | 过滤出包含 | |
2 | 按 Span Kind(ENTRY、LLM、TOOL、AGENT)预处理字段,提取用户输入、模型信息、Token 用量、工具调用等结构化数据。 | |
3 | 按 | |
4 | 派生统计指标(总 Token 数、Span 数、LLM 调用次数、工具调用次数、耗时毫秒),并提取用户查询文本和完整对话全文。 | |
5 | 过滤出包含有效用户输入的 Trace,排除缺少用户查询的空记录。 |
Phase 2:三级去重
递进式去重:精确去重、近似去重、语义去重逐级清洗,大幅降低数据量。
顺序 | 节点 | 说明 |
6 | 基于SimHash完全匹配,去除 | |
7 | 基于SimHash海明距离,去除 | |
8 | 基于 Embedding 向量距离,去除语义含义相似的记录。默认阈值为 0.1。 |
Phase 3:多样性采样
对去重后的数据进行语义聚类和分组采样,确保产出数据覆盖多种场景。
顺序 | 节点 | 说明 |
9 | 复用语义去重阶段生成的 | |
10 | 按 |
Phase 4:AI处理
对采样后的代表性数据进行AI 质量评估和场景标注。
顺序 | 节点 | 说明 |
11 | llm-call(评估) | 使用Prompt模板 |
12 | llm-call(标注) | 使用 |
完整配置
本模板提供 JSON 配置格式。
以下为完整的 Pipeline JSON 配置,可直接通过 API 提交创建 Pipeline。
{
"name": "ot_trace_data_governance",
"description": "OT-Trace Trace 粒度:Agent 对话数据治理",
"source": {
"type": "logstore",
"logstore": {
"project": "<your-project>",
"logstore": "<your-logstore>",
"query": "*"
}
},
"pipeline": {
"nodes": [
{
"id": "kind_filter",
"type": "where",
"parameters": {
"filter": "\"attributes.gen_ai.span.kind\" IS NOT NULL AND \"attributes.gen_ai.span.kind\" != ''"
}
},
{
"id": "kind_preprocess",
"type": "extend",
"parameters": {
"entry_input": "CASE WHEN \"attributes.gen_ai.span.kind\" = 'ENTRY' THEN \"attributes.gen_ai.input.messages\" ELSE CAST(NULL AS VARCHAR) END",
"entry_output": "CASE WHEN \"attributes.gen_ai.span.kind\" = 'ENTRY' THEN \"attributes.gen_ai.output.messages\" ELSE CAST(NULL AS VARCHAR) END",
"llm_model": "CASE WHEN \"attributes.gen_ai.span.kind\" = 'LLM' THEN CASE WHEN \"attributes.gen_ai.request.model\" IS NOT NULL AND ... THEN \"attributes.gen_ai.request.model\" ELSE spanname END ELSE CAST(NULL AS VARCHAR) END",
"llm_input_messages": "...",
"llm_output_messages": "...",
"llm_input_tokens": "...",
"llm_output_tokens": "...",
"tool_name": "...",
"agent_name": "...",
"process_label": "..."
}
},
{
"id": "assemble",
"type": "make-instance",
"parameters": {
"by": "traceid",
"session_id": "first(\"attributes.gen_ai.session.id\")",
"user_input": "first(entry_input)",
"final_output": "last(entry_output)",
"model_list": "array_distinct(llm_model)",
"total_input_tokens": "sum(llm_input_tokens)",
"total_output_tokens": "sum(llm_output_tokens)",
"tool_name_list": "array_distinct(tool_name)",
"tool_call_chain": "join(tool_name, ' → ')",
"process_chain": "join(process_label, chr(10))",
"span_kind_list": "array(\"attributes.gen_ai.span.kind\")",
"start_time": "first(__time__)",
"end_time": "last(__time__)",
"trace_duration": "max(CAST(duration AS BIGINT))"
}
},
{
"id": "derive",
"type": "extend",
"parameters": {
"total_tokens": "total_input_tokens + total_output_tokens",
"span_count": "cardinality(span_kind_list)",
"llm_count": "cardinality(filter(span_kind_list, x -> x = 'LLM'))",
"tool_count": "cardinality(filter(span_kind_list, x -> x = 'TOOL'))",
"trace_duration_ms": "CAST(trace_duration AS DOUBLE) / 1000000.0",
"user_query": "CASE WHEN user_input IS NOT NULL ... END",
"full_text": "concat('## 用户输入', chr(10), ..., '## 执行过程', ..., '## 最终输出', ...)"
}
},
{
"id": "filter_valid",
"type": "where",
"parameters": {
"filter": "(user_input IS NOT NULL AND user_input != '') OR (first_llm_input IS NOT NULL AND first_llm_input != '')"
}
},
{
"id": "exact_dedup",
"type": "dedup-exact",
"parameters": { "field": "user_query" }
},
{
"id": "fuzzy_dedup",
"type": "dedup-fuzzy",
"parameters": { "field": "user_query", "threshold": "3" }
},
{
"id": "semantic_dedup",
"type": "dedup-semantic",
"parameters": { "field": "user_query", "threshold": "0.1" }
},
{
"id": "cluster",
"type": "semantic-cluster",
"parameters": { "field": "__dedup_emb", "n": 20 }
},
{
"id": "sample_per_cluster",
"type": "sample",
"parameters": { "n": 3, "by": "__cluster_id" }
},
{
"id": "evaluate",
"type": "llm-call",
"parameters": {
"prompt": "@eval/trace-eval-prompt.md",
"fields": "user_query,process_chain,full_text",
"format": "json",
"as": "eval"
}
},
{
"id": "annotate",
"type": "llm-call",
"parameters": {
"prompt": "@anno/trace-label-prompt.md",
"fields": "user_query,process_chain",
"format": "json",
"model": "qwen-plus",
"as": "anno"
}
}
]
},
"sink": {
"type": "dataset",
"dataset": {
"workspace": "<your-workspace>",
"dataset": "<your-dataset>"
}
},
"executePolicy": {
"mode": "run_once",
"run_once": { "fromTime": 0, "toTime": 0 }
}
}
配置中的source.logstore和sink.dataset需替换为实际资源。kind_preprocess节点的完整表达式较长,此处以省略号表示,请参见下方 SPL 格式获取完整表达式。
占位符说明:
<your-project>:SLS Project 名称。<your-logstore>:存储 OT-Trace 数据的 Logstore 名称。在目标 Project 中,选择日志存储查看 Logstore 列表。<your-workspace>:数据集所属的工作空间名称。在日志服务控制台左侧导航栏选择数据集,查看已有工作空间。<your-dataset>:Pipeline 输出目标数据集名称。可使用已有数据集或在创建 Pipeline 时新建。
创建并运行 Pipeline
完成 Pipeline 配置后,通过以下方式提交并运行。
通过控制台创建
登录AgentLoop控制台,在左侧导航栏数据集-数据处理中,选择应用模板,挑选OT-AI Trace 数据治理模板,单击创建任务。
参数说明
以下为各节点的关键参数,可根据实际业务需求调整,控制数据治理的力度和产出规模。
参数 | 默认值 | 调整说明 |
| 3 | SimHash 海明距离阈值。值越小去重越严格,值越大保留越多近似数据。详细说明请参见dedup-fuzzy。 |
| 0.1 | Embedding 向量距离阈值。值越小去重越严格,值越大保留越多语义相似数据。详细说明请参见dedup-semantic。 |
| 20 | 聚类数量。更多簇代表更细粒度的分类,但每簇内样本量可能减少。详细说明请参见semantic-cluster。 |
| 3 | 每簇采样数量。影响下游 AI 处理的数据量和成本。当前默认配置下最多产出 20 x 3 = 60 条数据。详细说明请参见sample。 |
| 模板引用 | 可自定义评估和标注的Prompt模板。评估节点使用 |
| 系统默认 / qwen-plus | 评估节点使用系统默认模型,标注节点使用 |
运行结果
Pipeline 运行完成后,产出的数据集中每条记录包含以下关键字段:
字段 | 来源 | 说明 |
| 组装 | Trace 唯一标识。 |
| 派生 | 提取的用户查询文本,优先取 ENTRY 输入,回退取首条 LLM 输入。 |
| 组装 | 完整执行链路,按时间顺序拼接每个Span的处理标签(如 |
| 组装 | 去重后的模型名称列表。 |
| 派生 | 输入和输出 Token 总数。 |
| 组装 | 工具调用链路。 |
| 派生 | Trace 总耗时(毫秒)。 |
| AI评估 | 多维度质量评估结果(JSON 格式)。 |
| AI标注 | 任务类型、复杂度、业务领域等标注结果(JSON 格式)。 |
注意事项
使用本模板前,请注意以下常见问题及处理方式。
场景 | 预期行为 | 排查与建议 |
源 Logstore 中无 OT-Trace 数据 | Pipeline 正常运行但输出数据集为空,不会报错。 | 确认目标应用已正确接入 OT 探针并产生 Trace 数据。在 Logstore 中执行 |
LLM 调用失败或超时 |
| 检查 LLM 服务的连通性和配额。如果超时频繁,可在 |
三级去重后数据量极少或为零 | 下游聚类和采样阶段输入数据不足,输出结果可能无法反映真实分布。 | 适当放宽去重阈值:增大 |
权限不足 | Pipeline 创建或运行时报 | 确认当前账号或 RAM 角色具备源 Logstore 的读取权限和目标 Dataset 的写入权限。 |
Token 配额超限 | Pipeline 运行失败并返回配额相关错误信息。 | 检查当前账号的 LLM 调用配额上限。如需处理更多数据,请提升配额上限或减少 |
定制建议
可在本模板基础上进行以下定制:
调整去重力度:修改
dedup-fuzzy.threshold和dedup-semantic.threshold参数值。提高阈值保留更多数据,降低阈值去重更严格。详见上方参数说明中的对应参数。调整采样规模:修改
semantic-cluster.n和sample.n参数。聚类数 x 每簇采样数 = 最终产出上限。详见上方参数说明中的对应参数。自定义Prompt模板:替换评估和标注的Prompt模板,适配特定评估维度或标注体系。
添加文本统计:在采样后、LLM 调用前插入doc-stats节点,统计文本长度、词频等信息。
扩展组装字段:在
kind_preprocess和assemble节点中添加更多字段提取和聚合规则,丰富Trace宽表数据。