本文面向需要将原始AI回答转化为可分析结构化数据的技术人员和数据工程师。在多平台采样完成后你手里会有成百上千条非结构化的AI回答文本——有的有效有的是拒答有的提到了品牌有的没有有的用全称有的用别名。如果不经过系统化的清洗直接统计出的提及率和推荐率基本没有可信度。本文将从原始回答表设计、无效样本过滤、品牌实体识别、别名合并、推荐倾向判断和指标聚合六个环节拆解一条从“原始回答”到“可分析指标”的完整数据流水线。目录为什么样本清洗决定了指标的可信度清洗系统的整体架构原始回答表设计存储什么、怎么存无效样本过滤三级过滤机制品牌实体识别主词表映射与模糊匹配别名合并从多形态指代到统一标识推荐倾向判断规则层与语义层指标聚合从单条样本到统计结果清洗流水线的调度与可追溯性方法边界与注意事项总结一、为什么样本清洗决定了指标的可信度假设你采集了1000条AI回答不做任何清洗直接统计其中50条是AI的拒答“抱歉我无法回答这个问题”其中30条答非所问问运动鞋回答旅行攻略品牌“A”在回答中有时被叫“A牌”有时被叫“A官方名称”有时被拼错成“A牌牌”如果不做无效过滤拒答和离题回答会扩大分母拉低提及率。如果不做别名合并品牌“A”会被当成三个不同品牌统计每个的提及率都只有真实值的三分之一。样本清洗要做的事情很简单把不能用的样本剔除把能用的样本中的品牌信息准确提取出来。这一步如果出错后续所有指标、诊断、对比都是建立在错误数据上的。二、清洗系统的整体架构原始回答表raw_samples │ 存储采样原始数据不做任何修改 ↓ 第一级过滤无效样本标记 │ 识别拒答、空响应、格式错误 │ 输出is_valid标记 invalid_reason ↓ 第二级过滤内容质量过滤 │ 识别答非所问、信息不足、幻觉回答 │ 输出relevance_score quality_flag ↓ 品牌实体识别 │ 基于主词表匹配品牌名 │ 输出brands_identified列表 ↓ 别名合并 │ 将识别到的别名统一映射为标准品牌名 │ 输出brands_normalized列表 ↓ 推荐倾向判断 │ 对每个被识别的品牌判定推荐/中性/不推荐 │ 输出recommendation_flags ↓ 指标聚合 │ 按场景、品牌、平台维度汇总 │ 输出mention_rate, recommendation_rate ↓ 清洗后样本表cleaned_samples 聚合指标表aggregated_metrics三、原始回答表设计存储什么、怎么存3.1 核心原则原始数据不可变原始回答表是清洗系统的起点它的核心设计原则是只做追加写入不做修改不做删除。所有清洗结果写在附加字段中原始回答文本始终保留。这样做的目的是保证数据可追溯——如果三个月后发现清洗规则有问题可以基于原始回答重新清洗而不需要重新采样。3.2 表结构设计-- 原始回答表CREATETABLEraw_samples(-- 主键sample_idVARCHAR(64)PRIMARYKEY,-- 采样上下文关联问题库和采样计划plan_idVARCHAR(32)NOTNULL,question_idVARCHAR(32)NOTNULL,question_text_snapshotTEXTNOTNULL,-- 采样时的问题文本快照scene_tagVARCHAR(64),-- 场景标签intent_typeVARCHAR(32),-- 意图分类-- 平台信息platformVARCHAR(32)NOTNULL,request_timeDATETIMENOTNULL,response_timeDATETIME,-- 原始回答核心字段不可修改raw_responseTEXTNOTNULL,response_lengthINT,-- 有效性标记清洗后填充is_validBOOLEANDEFAULTNULL,-- NULL未处理TRUE有效FALSE无效invalid_reasonVARCHAR(64),-- 无效原因代码filter_levelVARCHAR(16),-- 被哪一级过滤标记的-- 品牌识别结果清洗后填充brands_raw JSONDEFAULTNULL,-- 原始识别结果含别名brands_normalized JSONDEFAULTNULL,-- 别名合并后的标准品牌名列表recommendation_flags JSONDEFAULTNULL,-- 推荐判定结果-- 元信息created_atDATETIMEDEFAULTCURRENT_TIMESTAMP,processed_atDATETIME,-- 清洗处理完成时间process_versionVARCHAR(16)-- 清洗规则版本号);3.3 为什么用JSON存储识别结果品牌识别结果是一个“一个样本中可能出现多个品牌”的一对多关系。用JSON字段存储可以避免为品牌识别结果单独建关联表带来的JOIN复杂度同时保持表结构的简洁。// brands_raw 字段示例[品牌A,A牌,品牌B]// brands_normalized 字段示例[品牌A,品牌B]// recommendation_flags 字段示例{品牌A:推荐,品牌B:中性}四、无效样本过滤三级过滤机制4.1 为什么要分级过滤不同类型的无效样本识别难度和处理成本差异很大。拒答可以通过关键词快速匹配毫秒级答非所问需要语义相似度计算百毫秒级幻觉识别甚至需要人工复核分钟级。三级过滤的设计原则是用最低成本过滤最容易识别的无效样本只让真正存疑的样本进入高成本处理环节。4.2 第一级技术无效过滤过滤因网络错误、API异常、响应超时等产生的无效样本deffilter_technical_invalid(sample): 过滤技术层面的无效样本 返回: (is_valid, reason) # 空响应ifnotsample[raw_response]orlen(sample[raw_response].strip())0:returnFalse,EMPTY_RESPONSE# API错误error_signals[rate_limit_exceeded,server_error,timeout,unauthorized]forsignalinerror_signals:ifsignalinsample[raw_response].lower():returnFalse,fAPI_ERROR_{signal.upper()}# 响应截断以不完整句子结束ifsample[raw_response].strip().endswith(...):iflen(sample[raw_response])50:returnFalse,TRUNCATED_RESPONSEreturnTrue,None4.3 第二级内容无效过滤过滤AI拒绝回答、信息严重不足、明显答非所问的样本deffilter_content_invalid(sample): 过滤内容层面的无效样本 返回: (is_valid, reason) textsample[raw_response]# 拒答模式匹配refuse_patterns[抱歉我无法,作为AI我不能,我无法回答这个问题,请提供更多信息,我没有相关信息,这个问题超出了我的能力范围]forpatterninrefuse_patterns:ifpatternintextandlen(text)150:returnFalse,REFUSAL# 信息严重不足iflen(text)20:returnFalse,TOO_SHORT# 纯链接或纯代码对品牌监测场景无意义strippedtext.strip()ifstripped.startswith(http)andlen(stripped)100:returnFalse,URL_ONLYreturnTrue,None4.4 第三级语义质量过滤过滤答非所问和疑似幻觉的样本这一步需要更多计算资源deffilter_semantic_quality(sample): 过滤语义质量不达标的样本 返回: (is_valid, reason, quality_score) textsample[raw_response]questionsample.get(question_text_snapshot,)# 答非所问检测问题与回答的语义相似度ifquestion:relevancecalc_semantic_similarity(question,text)ifrelevance0.25:returnFalse,OFF_TOPIC,relevance# 幻觉标记不直接过滤但降低权重# 实际实现中会与品牌事实库比对# 此处简化为如果回答中实体密度异常低标记为待复核returnTrue,None,None4.5 过滤结果汇总defapply_all_filters(sample): 依次应用三级过滤更新样本的有效性标记 # 第一级is_valid,reasonfilter_technical_invalid(sample)ifnotis_valid:sample[is_valid]Falsesample[invalid_reason]reason sample[filter_level]L1_TECHNICALreturnsample# 第二级is_valid,reasonfilter_content_invalid(sample)ifnotis_valid:sample[is_valid]Falsesample[invalid_reason]reason sample[filter_level]L2_CONTENTreturnsample# 第三级is_valid,reason,scorefilter_semantic_quality(sample)ifnotis_valid:sample[is_valid]Falsesample[invalid_reason]reason sample[filter_level]L3_SEMANTICreturnsample sample[is_valid]Truesample[invalid_reason]Nonesample[filter_level]Nonereturnsample五、品牌实体识别主词表映射与模糊匹配5.1 主词表精确匹配品牌实体识别的基础方法在前序文章中已有详述这里聚焦在清洗流水线中的集成方式defidentify_brands_in_sample(sample,brand_alias_map): 在单条样本中识别品牌实体 参数: sample: 已通过有效性过滤的样本 brand_alias_map: {标准品牌名: [别名列表]} 返回: 更新后的样本填充brands_raw字段 ifnotsample[is_valid]:sample[brands_raw][]sample[brands_normalized][]sample[recommendation_flags]{}returnsample textsample[raw_response]raw_brands[]normalized_brands[]matched_details{}forstandard_name,aliasesinbrand_alias_map.items():foraliasinaliases:postext.find(alias)ifpos!-1:# 记录原始匹配raw_brands.append(alias)# 归一化为标准名ifstandard_namenotinnormalized_brands:normalized_brands.append(standard_name)# 记录匹配详情matched_details[standard_name]{matched_alias:alias,first_position:pos,alias_type:classify_alias_type(alias,standard_name)}break# 同一品牌只记录一次sample[brands_raw]raw_brands sample[brands_normalized]normalized_brands sample[brands_match_details]matched_detailsreturnsample5.2 模糊匹配兜底对于主词表精确匹配未能覆盖的情况如错别字、谐音变体用编辑距离做兜底deffuzzy_match_unrecognized(text,brand_alias_map,threshold2): 对未被精确匹配的疑似品牌片段进行模糊匹配 返回: 候选匹配列表需人工确认 # 提取文本中可能是品牌名的未识别片段# 简化逻辑寻找未被匹配的专有名词片段unrecognized_spansextract_unmatched_proper_nouns(text,brand_alias_map)candidates[]all_known_nameslist(brand_alias_map.keys())forspaninunrecognized_spans:forknown_nameinall_known_names:distancelevenshtein_distance(span,known_name)ifdistancethreshold:candidates.append({unrecognized_span:span,candidate_brand:known_name,edit_distance:distance,confidence:1.0-(distance/max(len(span),len(known_name)))})returnsorted(candidates,keylambdax:x[confidence],reverseTrue)六、别名合并从多形态指代到统一标识6.1 合并策略品牌实体识别阶段已经将别名映射到了标准名brands_normalized字段。但在清洗流水线中还需要处理一个特殊场景同一品牌在同一回答中被多次提及且使用了不同的别名。例如AI回答中第一句用了“品牌A”第三句用了“A牌”。精确匹配阶段两个都会被识别并归一化为“品牌A”但计数时需要确保只计一次提及。defensure_single_count_per_brand(sample): 确保每个品牌在同一回答中最多被计数一次 该逻辑在品牌识别阶段已通过break实现 此函数用于后置校验和异常标记 normalizedsample.get(brands_normalized,[])# 检测是否有重复iflen(normalized)!len(set(normalized)):sample[anomaly_tags]sample.get(anomaly_tags,[])sample[anomaly_tags].append({type:DUPLICATE_BRAND_NORMALIZATION,detail:归一化后仍存在重复品牌名需检查别名映射表})# 去重sample[brands_normalized]list(set(normalized))returnsample6.2 别名映射表的版本管理别名映射表是动态更新的新别名不断被发现和纳入每次更新都需要记录版本以便历史数据可以追溯“当时用的是哪版映射表”alias_map_version_log{version:v2.3.1,updated_at:2026-07-08,changes:[{brand:品牌A,action:add_alias,new_alias:A牌牌,source:AI回答样本中发现样本ID: NS20260708_045,discovered_count:3# 该别名在3条样本中出现}],previous_version:v2.3.0}七、推荐倾向判断规则层与语义层7.1 在清洗流水线中的位置推荐倾向判断发生在品牌实体识别和别名合并完成之后。对每个被识别到的品牌系统需要判定AI的态度是推荐、中性还是不推荐。7.2 判定逻辑defjudge_recommendation_for_brands(sample): 对样本中识别到的所有品牌进行推荐倾向判定 填充 sample[recommendation_flags] ifnotsample[is_valid]:sample[recommendation_flags]{}returnsample textsample[raw_response]brandssample.get(brands_normalized,[])flags{}forbrandinbrands:# 提取品牌所在上下文contextextract_context_window(text,brand,window_size2)# 规则层判定intentrule_based_judgment(context)# 如果规则层无法确定进入语义层ifintentuncertain:intentsemantic_judgment(context)flags[brand]intent sample[recommendation_flags]flagsreturnsampledefrule_based_judgment(context):基于规则的推荐意图快速判定# 不推荐信号强strong_negative[不推荐,避坑,踩雷,后悔,品控差,投诉多]forsignalinstrong_negative:ifsignalincontext:return不推荐# 推荐信号强strong_positive[首选,强烈推荐,最推荐,闭眼入,不二之选]forsignalinstrong_positive:ifsignalincontext:return推荐# 中性列举信号neutral_signals[包括,还有,此外,另外还有,市面上有]has_neutralany(sincontextforsinneutral_signals)has_positiveany(sincontextforsin[推荐,值得,不错,可以考虑])ifhas_neutralandnothas_positive:return中性ifhas_positiveandnotis_negation_context(context):return推荐returnuncertain八、指标聚合从单条样本到统计结果8.1 聚合逻辑当所有样本完成清洗、品牌识别和推荐判定后最后一步是按维度聚合计算提及率和推荐率defaggregate_metrics(cleaned_samples,dimensions): 按指定维度聚合指标 参数: cleaned_samples: 已完成清洗的样本列表 dimensions: 聚合维度列表如 [scene, brand, platform] 返回: 聚合后的指标表 # 只统计有效样本valid_samples[sforsincleaned_samplesifs[is_valid]]total_validlen(valid_samples)# 按维度分组groupsgroup_by_dimensions(valid_samples,dimensions)results[]forgroup_key,group_samplesingroups.items():group_totallen(group_samples)# 统计每个品牌在该分组中的表现brand_stats{}forsampleingroup_samples:forbrandinsample.get(brands_normalized,[]):ifbrandnotinbrand_stats:brand_stats[brand]{mentioned:0,recommended:0}brand_stats[brand][mentioned]1ifsample.get(recommendation_flags,{}).get(brand)推荐:brand_stats[brand][recommended]1# 计算比率forbrand,statsinbrand_stats.items():results.append({dimensions:group_key,brand:brand,mention_rate:round(stats[mentioned]/group_total*100,2),recommendation_rate:round(stats[recommended]/stats[mentioned]*100,2)ifstats[mentioned]0else0,sample_count:group_total})returnresults8.2 聚合结果表结构-- 聚合指标表CREATETABLEaggregated_metrics(metric_idVARCHAR(64)PRIMARYKEY,plan_idVARCHAR(32)NOTNULL,dimension_keyVARCHAR(128)NOTNULL,-- 维度组合的哈希或序列化sceneVARCHAR(64),brandVARCHAR(64),platformVARCHAR(32),intent_typeVARCHAR(32),total_valid_samplesINT,mention_countINT,recommendation_countINT,mention_rateDECIMAL(5,2),recommendation_rateDECIMAL(5,2),calculated_atDATETIMEDEFAULTCURRENT_TIMESTAMP,process_versionVARCHAR(16));九、清洗流水线的调度与可追溯性9.1 流水线执行顺序清洗流水线中的每个步骤有明确的依赖关系必须按顺序执行原始样本 → L1过滤 → L2过滤 → L3过滤 → 品牌识别 → 别名合并 → 推荐判定 → 指标聚合每一步的输出是下一步的输入任何一步的规则更新都需要重新执行该步及之后的所有步骤。9.2 可追溯性设计清洗系统的每一次执行都应记录执行信息确保指标结果可追溯到具体的清洗规则版本pipeline_execution_log{execution_id:EXEC20260708_001,plan_id:SP20260707_001,executed_at:2026-07-08 10:00:00,input_sample_count:500,output_valid_count:460,rule_versions:{filter_rules:v1.2.0,brand_alias_map:v2.3.1,recommendation_rules:v1.1.0,aggregation_logic:v1.0.0},step_results:{L1_filter:{input:500,passed:495,filtered:5},L2_filter:{input:495,passed:470,filtered:25},L3_filter:{input:470,passed:460,filtered:10},brand_identification:{samples_processed:460,brands_found:380},recommendation_judgment:{brands_evaluated:380,recommended:120}}}十、方法边界与注意事项10.1 清洗规则需要持续迭代品牌别名会新增AI的拒答话术会变化新的无效回答模式会出现。清洗规则不是一劳永逸的建议每月抽查一次过滤结果将新发现的无效模式纳入规则库。10.2 过度过滤与过滤不足的平衡过滤阈值设置过严会导致有效样本被误杀、样本量不足阈值过宽会导致无效样本混入、指标被污染。建议定期对过滤结果进行人工抽检每批次抽检5%-10%的过滤决策统计误杀率和漏网率据此调整阈值。10.3 原始数据是最后的兜底无论清洗规则如何迭代原始回答表永远不删除、不修改。当发现指标异常波动时第一步永远是回到原始回答表查看原始数据——是品牌表现真的变了还是清洗规则出了问题。十一、总结本文拆解了AI回答样本清洗系统的设计思路核心包括六个环节原始回答表设计原始数据只追加不修改所有清洗结果写入附加字段保证全链路可追溯无效样本三级过滤L1过滤技术无效空响应、API错误L2过滤内容无效拒答、信息不足L3过滤语义质量答非所问、幻觉标记品牌实体识别主词表精确匹配为主编辑距离模糊匹配兜底识别结果同时记录原始别名和归一化标准名别名合并确保每个品牌在同一回答中最多计数一次别名映射表版本化管理推荐倾向判断规则层快速处理高置信度情况语义层处理边界样本指标聚合按场景、品牌、平台等维度汇总输出结构化的提及率和推荐率这套清洗系统是品牌AI可见度监测体系的数据处理中枢。它的设计原则可以总结为三句话原始数据永不丢失过滤决策逐级降本清洗规则有版本可查。只有建立在可追溯、可复核的数据基础上后续的诊断、对比、一致性分析才有意义。