原始AI回答与可用分析指标之间,其实隔着一道不浅的鸿沟。采集回来的文本看似丰富,但真正要拿它算提及率、推荐率,还得经过好几道工序。

原始回答说白了就是非结构化文本——品牌名称可能全称、简称、英文名甚至错别字混着来;同一个实体在不同回答里形态各异;“提及”和“推荐”的边界需要清楚界定;解释充分不充分也得有量化标准。要是直接从原始文本里计数,结果里全是噪声:品牌别名没合并,同一实体被拆成好几个ID统计;无效回答没过滤,分母被污染;推荐口径不统一,不同批次的结果根本没法比。这些数据层面的问题,最后都会反映在指标的可信度上。
下面从数据工程角度,梳理一套从原始AI回答到可分析指标的完整处理流程,重点覆盖无效样本过滤、品牌别名合并、提及与推荐识别、解释文本抽取、指标口径统一与聚合五个环节,并以阿里云DataWorks + MaxCompute为例给出可复用的实现方案。
二、整体架构
整个处理流程分为六个阶段:
| 阶段 | 核心任务 | 依托组件 | 输出 |
|---|---|---|---|
| ① 采集 | 多平台API调用,原始回答入库 | DataWorks调度 + 采集节点 | 原始回答表 |
| ② 清洗 | 剔除拒答、过短、异常回答 | MaxCompute UDF | 有效样本表 |
| ③ 别名归一化 | 识别并合并品牌别名 | MaxCompute SQL + 维表 | 标准化样本表 |
| ④ 标签生成 | 标注提及、推荐等级、解释充分度 | MaxCompute SQL + 规则 | 带标签样本表 |
| ⑤ 口径统一 | 按统一标准计算指标 | MaxCompute聚合查询 | 指标中间表 |
| ⑥ 指标聚合 | 按品牌、场景、平台输出 | MaxCompute聚合查询 | 指标结果表 |
每个阶段通过DataWorks的审计日志记录处理状态,确保从最终指标可以追溯到原始回答。
三、无效样本过滤
3.1 需要剔除的样本类型
原始回答里,相当一部分没法直接用:
| 类型 | 特征 | 清洗方式 |
|---|---|---|
| 明确拒答 | 含“无法回答”“不能提供”等信号 | 关键词正则匹配 |
| 内容过短 | 少于20个字符 | 长度阈值过滤 |
| 语义偏离 | 回答与问题明显无关 | 相似度阈值(可选) |
| 格式异常 | 乱码、截断、重复内容 | 规则 + 长度校验 |
3.2 清洗实现
在MaxCompute中创建清洗UDF:
-- 注册UDF
CREATE FUNCTION is_valid_answer AS 'com.example.udf.AnswerValidator';
-- 在ETL任务中调用
INSERT OVERWRITE TABLE valid_samples PARTITION (dt='${bizdate}')
SELECT
id, platform, question_id, answer
FROM raw_answers
WHERE is_valid_answer(answer) = TRUE;
UDF核心逻辑:
public class AnswerValidator extends UDF {
public Boolean evaluate(String answer) {
if (answer == null || answer.trim().length() < 20) {
return false;
}
// 拒答信号匹配
String[] rejects = {"无法回答", "不能提供", "无法提供", "cannot answer"};
for (String kw : rejects) {
if (answer.toLowerCase().contains(kw.toLowerCase())) {
return false;
}
}
return true;
}
}
维护要点:拒答关键词列表需要持续维护。不同AI平台的拒答表达方式差异比较大,建议定期review被过滤的样本,补充新的拒答模式。
四、品牌别名合并
4.1 别名问题对指标的直接影响
别名不合并,同一实体的提及次数会被拆分到多个名称下,导致提及率被系统性低估,排序结果失真。
常见别名类型:
- 全称/简称:“绿雪智能科技有限公司” vs “绿雪智能”
- 中/英文:“阿里巴巴” vs “Alibaba”
- 产品名/公司名:“通义千问” vs “阿里云”
- 错别字/变体:不同来源使用的变体形式
4.2 别名映射表与归一化ETL
CREATE TABLE entity_alias_mapping (
canonical_id STRING COMMENT '标准实体ID',
canonical_name STRING COMMENT '标准名称',
alias_name STRING COMMENT '别名',
alias_type STRING COMMENT '简称/英文/产品名/错别字',
status STRING COMMENT 'active/pending/rejected'
);
归一化ETL:
SELECT
COALESCE(m.canonical_id, 'UNKNOWN') AS entity_id,
COALESCE(m.canonical_name, extracted.entity_raw) AS entity_name,
extracted.sample_id,
extracted.platform
FROM entity_extraction_results extracted
LEFT JOIN entity_alias_mapping m
ON extracted.entity_raw = m.alias_name AND m.status = 'active';
性能优化:当别名映射表规模较大时,建议使用 /*+ MAPJOIN(m) */ 提示优化关联性能。
五、提及与推荐识别
5.1 明确“提及”的边界
同一问题中,同一品牌最多计一次提及。判断时需要排除:
- 无关列表中的偶然出现
- 同名但不同实体的混淆情况
- 回答中仅作为引用来源出现而非主体讨论
5.2 明确“推荐”的等级
推荐不是一个二值状态,需要区分强度:
| 推荐等级 | 判断依据 | 示例表述 |
|---|---|---|
| 强推荐 | 明确首选、最佳、第一 | “首选推荐A品牌” |
| 一般推荐 | 列入推荐列表 | “可以考虑A品牌” |
| 弱推荐 | 作为备选或补充提及 | “另外也可以了解A品牌” |
SELECT
sample_id,
entity_id,
entity_name,
CASE
WHEN answer REGEXP '首选|最佳|最推荐|强烈推荐' THEN 'strong'
WHEN answer REGEXP '值得推荐|可以考虑|不错的' THEN 'normal'
WHEN answer REGEXP '也可以|备选|作为补充' THEN 'weak'
ELSE 'none'
END AS recommend_level
FROM samples_with_entities;
5.3 解释充分度判断
解释能力的量化需要识别品牌是否获得了充分描述:
SELECT
sample_id,
entity_id,
entity_name,
explanation_text,
LENGTH(explanation_text) AS explanation_length,
CASE
WHEN LENGTH(explanation_text) >= 20 THEN '充分'
WHEN LENGTH(explanation_text) >= 5 THEN '一般'
ELSE '不足'
END AS explanation_sufficiency
FROM extracted_explanations;
六、指标口径统一
6.1 为什么需要统一口径
指标口径不统一是数据分析中常见的隐蔽问题。同一个“提及率”,可能因为分母定义不同(全量采集 vs 有效样本)、去重规则不同(按品牌去重 vs 按样本去重)、平台覆盖不同而产生差异。口径统一的目标是:同一指标在同一份数据中只有一种计算方式,且该方式被清晰记录。
6.2 核心指标及口径定义
| 指标 | 计算公式 | 口径约束 |
|---|---|---|
| 提及率 | 提及样本数 / 有效样本总数 × 100% | 同一问题中同一实体最多计一次;仅统计有效样本 |
| 推荐率 | 推荐样本数 / 有效样本总数 × 100% | 含强推荐和一般推荐,弱推荐可选计入 |
| 强推荐率 | 强推荐样本数 / 有效样本总数 × 100% | 仅统计“首选”“最佳”等明确信号 |
| 解释充分度 | 充分解释样本数 / 提及样本数 × 100% | 解释文本长度≥20字符判定为充分 |
6.3 指标计算实现
WITH metrics_base AS (
SELECT
entity_id,
entity_name,
COUNT(DISTINCT sample_id) AS total_samples,
COUNT(DISTINCT CASE WHEN is_mentioned = 1 THEN sample_id END) AS mention_samples,
COUNT(DISTINCT CASE WHEN recommend_level IN ('strong', 'normal')
THEN sample_id END) AS recommend_samples,
COUNT(DISTINCT CASE WHEN recommend_level = 'strong'
THEN sample_id END) AS strong_recommend_samples,
COUNT(DISTINCT CASE WHEN is_mentioned = 1 AND explanation_sufficiency = '充分'
THEN sample_id END) AS sufficient_explain_samples
FROM labeled_samples
WHERE is_valid = 1
GROUP BY entity_id, entity_name
)
SELECT
entity_id,
entity_name,
ROUND(mention_samples * 100.0 / total_samples, 2) AS mention_rate,
ROUND(recommend_samples * 100.0 / total_samples, 2) AS recommend_rate,
ROUND(strong_recommend_samples * 100.0 / total_samples, 2) AS strong_recommend_rate,
ROUND(sufficient_explain_samples * 100.0 / NULLIF(mention_samples, 0), 2) AS explain_sufficiency_rate
FROM metrics_base;
七、数据质量保障
7.1 全链路可追溯
在DataWorks中,每个任务节点的执行日志自动记录。业务层面建议增加审计明细表:
CREATE TABLE pipeline_audit (
sample_id STRING,
stage STRING COMMENT '采集/清洗/归一化/标签生成/聚合',
entity_id STRING,
status STRING,
detail STRING,
created_at DATETIME
) PARTITIONED BY (dt STRING);
7.2 口径变更管理
当指标口径需要调整时(如推荐阈值变化、别名映射更新),建议:
- 在DataWorks中创建新的任务版本,保留旧任务作为备份
- 使用分区级补数据功能,只重新计算受影响的历史分区
- 在指标结果表中增加version字段,标识不同的口径版本
ALTER TABLE metrics_result ADD COLUMN version STRING COMMENT '口径版本号';
7.3 质量检查点
| 检查项 | 检查方式 | 告警条件 |
|---|---|---|
| 清洗率 | 统计无效样本占比 | 超过30%触发告警 |
| 别名覆盖率 | 抽样检查未归一化的实体 | UNKNOWN占比超过5%触发告警 |
| 指标波动 | 对比上一周期指标值 | 变化超过±20%触发告警 |
八、实践总结
从原始AI回答到可分析指标,数据工程的实质是将在采集阶段丢失的结构化信息,通过清洗、归一化、标签化和口径统一重新建立起来。
整个流程中有几个关键点值得特别注意:
无效样本过滤是基础保障。没有经过清洗的数据直接计算指标,结果必然被污染。拒答关键词列表需要持续维护,定期review被过滤的样本,补充新的拒答模式。随着AI平台和模型版本更新,拒答表达方式会不断变化,清洗规则也需要相应更新。
别名合并决定了指标的准确性。别名合并不当,同一个实体被拆分成多个ID统计,提及率会被系统性低估。建议建立别名映射表的版本管理机制,每次更新时记录变更原因,便于追溯。
指标口径决定了结果的可比性。在不同的分析场景下,提及率、推荐率的分母定义、去重规则、平台覆盖范围都需要统一。口径变更时,应通过DataWorks的任务版本管理和分区补数据功能,保证历史数据的一致性。
在阿里云技术栈上,DataWorks的任务编排能力支撑了从采集到聚合的完整链路,MaxCompute的计算能力保障了大规模样本的处理效率,数据质量规则在关键节点自动校验数据完整性。这套架构的核心优势在于任务可编排、口径可追溯、结果可复核——当某个指标出现异常时,可以从聚合结果一路追溯到原始回答,定位问题所在。
