1. 为什么新闻推荐非得“开口说话”做推荐系统的人可能都有过这种体验你明明给用户推了一篇“看起来符合兴趣”的文章用户却压根不买账后台数据显示点击率很低反馈也很冷淡。问题出在哪儿黑盒推荐系统的通病——模型算出了“用户可能喜欢”但说不清“为什么喜欢”。新闻推荐尤其特殊。新闻讲究时效、讲究冲突、讲究贴近读者当下的关注点用户点开一篇文章往往有一个很具体的心理动机可能因为标题提到他关心的公司可能因为文章里那段话戳中了他的某个立场也可能单纯因为他刚刚看完同主题的短视频。传统的协同过滤、CTR预估模型把用户历史行为压成一个向量再做匹配给出一个分数排序。这个分数的确能排序但没法回答“为什么”。于是行业里这些年一直有人在尝试做“可解释推荐”。早年的做法很朴素统计你浏览过的文章里“体育”类最多那我推体育文章解释词就是“因为你常看体育资讯”或者用item间的相似度解释成“因为你喜欢过类似内容”。这类解释能用但粗糙而且经常闹笑话——因为你看过的某篇爆款里有“美食”标签系统就把它当成你爱吃辣推了一堆辣椒专栏解释还理直气壮。那段时间我自己的体感是可解释性在推荐场景里一直是“锦上添花”的东西属于“有了更好、没有也不致命”。但这两年情况变了。一方面新闻产品的用户粘性越来越依赖信任感——用户需要知道平台推给他的理由才会愿意持续留下来而不是把新闻App当成一个不知道背后逻辑的“黑箱分发机器”另一方面大语言模型的出现第一次让“生成自然语言解释”变成了成本极低、效果极好的事情。这篇文章我想用一个实际项目的思路聊聊怎么用LLM把新闻推荐做成“会说话的推荐器”——不光是给出排好序的候选列表而是给每一条推荐都配上用户能看懂、愿意信、甚至能引发点击欲的自然语言解释。2. 思路拆解可解释新闻推荐的本质问题在动工之前得先把“可解释”这事儿拆开。业内对推荐解释的研究长期以来围绕三个层面的问题转解释给谁看、解释到什么粒度、解释由谁生成。第一个问题“解释给谁看”看起来废话——当然是给用户看。但在真实的新闻产品里解释的用户可能是三类人最终读者、内容运营编辑、以及推荐算法团队自己。读者要的解释是“人情味”的能说服他点进来运营编辑要的解释是“复盘式”的能看出来推荐逻辑有没有跑偏算法团队要的解释是“诊断式”的能帮助定位模型行为异常。我见过不少团队一开始想做一个解释模块结果做出来之后只有算法组自己看用户端完全不展示——这是目标没定清楚就开工的典型症状。第二个问题“解释到什么粒度”其实更关键。粗粒度解释是“因为你关注了科技频道”细粒度解释是“因为你最近阅读的3篇文章都与芯片行业相关而这篇是同一个话题的深度追踪”。细粒度的解释用户感知更好但技术难度也更高——需要从用户近期行为里抽取出真正触发推荐的那个“兴趣点”。第三个问题“解释由谁生成”在LLM出现前主流是模板式生成比如填空“推荐理由你可能喜欢{兴趣标签}相关的{内容类型}”。用LLM之后变成了开放式的自然语言生成但引入了一个新的麻烦生成的解释可能胡编乱造即“幻觉”。回到这个项目我把核心矛盾定义成一句话想要可解释但不能因为解释伤了用户信任。解释如果和真实的推荐原因对不上用户反而觉得你在骗他。基于这个定义方案选型上我遵循几个原则解释必须能被溯源。哪怕语言是自然生成的背后的推荐依据必须来自可以查证的用户行为信号。解释不是独立生成的任务。解释要拿推荐结果和用户行为配合着生成不能把推荐和解释拆成两条线。解释要在成本和效果之间取平衡。并非所有推荐都需要解释解释的展示位置、展示时机、生成成本都要规划。这三点决定了后面整个架构的走向。3. 整体架构设计召回、排序、解释三层联动很多LLM推荐项目的第一反应是把全文内容一股脑丢给大模型让模型又做召回又做排序还顺带写解释。这样做的技术验证很快但落地很痛苦一方面是成本太高用户每一次刷新页面都要喂给模型上百万token的新闻内容另一方面是延迟完全不可控用户等不起十几秒才看到结果。这个项目采用了一个更稳的三层架构——召回、排序、解释各司其职LLM只负责做它最擅长的事理解和生成语言。召回层照旧用轻量级方案。这一层基于用户画像、行为序列、热门榜单、话题聚类从海量新闻里粗筛出几百篇候选。这个阶段完全不碰大模型用向量检索加规则加权就能搞定。召回的目的不是精准而是别漏掉可能感兴趣的内容把规模从一个资讯库收敛到一次排序能处理的数量级。排序层承接候选集用行为模型打个分。这里延续原来的CTR预估模型把用户历史行为、新闻特征、场景特征作为输入输出一个排序分数。我见过有些团队想在排序层直接引入LLM做语义排序但实践下来成本和延迟的代价太高而且排序效果未必比专精的行为模型好。LLM的强项是语言理解和生成不是大规模数值排序没必要拿导弹打蚊子。解释层才是LLM的主场。排序层输出带分数的候选列表之后解释模块取候选新闻的正文摘要、标题、关键实体再取用户近期的行为记录一起丢给LLM让它生成自然语言解释。这里有个关键细节传给LLM的用户行为记录不是原始日志而是经过一层“兴趣抽取”加工后的结构化信号例如“用户近7天点击了18篇科技类内容其中9篇与芯片话题相关”。这样做既能让LLM基于事实生成解释又能避免把原始行为序列全量塞给模型的成本和隐私风险。这三层联动的结果是用户看到的解释建立在可验证的兴趣信号之上而且新闻本身是由传统推荐模型精挑细选出来的——LLM只是给结果“配解说词”。这种分工方式落地的时候改动最小出问题的面也最小。4. 核心实现一兴趣信号抽取与压缩LLM生成解释要靠谱首先得喂给它靠谱的“料”。我在这块踩过不少坑最初直接拿原始行为序列试过效果很差——模型看着一大串URL链接和数据ID完全不知道用户到底喜欢什么。后来改成把行为数据加工成人话才稳定下来。这一层我叫它“兴趣信号抽取”。流程是从推荐系统里拿用户近N天的点击行为做几件事——统计点击量的频道分布做一次关键实体的聚类把点击文章里的高频人名、机构名、主题词挑出来再算一下点击时间的集中度识别用户是“持续关注型”还是“一次性刷到型”。加工出来的信号是一个结构化的兴趣摘要例如用户近7天点击34篇新闻分布为 - 科技类 16篇芯片话题 9篇AI应用话题 5篇其他 2篇 - 财经类 9篇股市相关 6篇产业公司动态 3篇 - 社会类 5篇 - 体育类 4篇 高频关注点芯片、智能汽车、人工智能行业动态 近期活跃时段工作日早晚通勤时间这段话包含的信息量不大但它是幻觉的克星——LLM生成解释时所有素材都从这里来。你给它一个具体可考的信号它生成的解释至少不会离用户真实兴趣太远。兴趣抽取的任务不重我用现成的实体识别工具加一个轻量聚类就能完成。比较关键的设计决策是这段摘要的结构设计必须服务于解释生成的“可引用性”。所谓可引用性就是LLM在解释里提到的每个理由都能对应到摘要里的某一行信息。这个约束在后面的prompt里有明确要求。5. 核心实现二面向推荐的解释生成Prompt设计Prompt是解释质量的分水岭。同一套兴趣信号不同写法的prompt生成结果一个天上一个地下。这个项目我迭代了好几版prompt最终稳定下来的结构包含四部分任务定义、输入材料、生成约束、输出格式。任务定义部分要写得足够窄。不能只说“请你为用户生成推荐理由”而是明确到“你是一个新闻推荐的解释器你的任务是基于用户的兴趣信号和新闻内容解释系统为什么将这篇新闻推荐给该用户”。我看过太多生成解释太泛泛的案例根子就是把一个要命的“为什么”让模型自己揣摩。输入材料部分同时给兴趣信号和新闻内容。新闻内容也不是全文取前200字的摘要加上核心实体列表就够了。正文全文没必要喂一来浪费token二来新闻的导语段落已经涵盖了最核心的信息点。生成约束部分是最重要的。我固定了三条硬性约束解释中出现的观点必须有出处要么出自兴趣信号中的统计要么出自新闻摘要中的事实。不允许凭空创造。解释要简短控制在三句话以内。新闻信息流的场景用户扫一眼就过解释写五句话反而是干扰。语气要自然不要使用“根据您的喜好推荐”这种AI味十足的模板用语。要像编辑在推荐给朋友文章时的语气。输出格式用JSON封装让后续的工程链路好接{ explanation: 你对芯片行业动态的关注比较持续这篇报道提到的芯片厂商正是你最近阅读中多次出现的当事人。, reason_tags: [芯片, 科技], evidence_detail: [近7天点击芯片类文章9篇, 新闻中出现实体某芯片厂商] }这里的evidence_detail字段是为了后续做“解释可点开”的交互——用户点一下解释能看到支持这个解释的行为依据是什么进一步增加可信度。这部分最初没有设计是给用户做可用性测试后加上的效果很好。这个prompt结构后来我复用到了其他项目里发现只要任务定义清晰、来源约束到位、输出结构可解析LLM生成的质量整体是稳的。6. 核心实现三LLM生成效果的质量控制解释生成的第一个可用版本其实很差差在“不接地气”。模型生成的是“根据您的阅读偏好这篇包含您感兴趣的芯片话题的新闻可能对您有价值”这种四平八稳的句子。语法没有错信息也没错但用户看了毫无感觉。这也让我意识到可解释推荐的解释不仅要“对”还要“动人”。要动人得在质量控制上做文章。我的处理方式是把生成解释分成两路选优。一路走“事实优先”的生成器约束严格按前面说过的prompt生成保证不出错、可溯源。另一路走“情绪优先”的生成器约束放松让它更有发挥空间例如把新闻里最具冲突感的句子提炼出来跟用户兴趣产生勾连。两路都生成之后用一个简单规则把它们拼起来或者择优。举个例子。事实优先的解释是你近期较多阅读芯片产业报道这篇新闻的核心人物正是你关注过的某半导体公司。情绪优先的解释是你关注的某半导体公司最近有了大动作这篇报道把来龙去脉讲清楚了。拼起来效果就很好你关注的那家半导体公司最近有了新动作这篇报道正好跟你平时看的芯片产业动态连上了帮你把来龙去脉讲清楚。质量控制另一个重要的点是自动评测。我当时建了一个小型的解释质量标注集请团队里几名编辑同学给生成的解释打分维度是准确度解释依据是否与兴趣信号一致、相关性解释与新闻内容是否匹配、感染力用户看了会不会想点。跑了几轮下来发现prompt约束里的“禁止幻觉”直接影响准确度而感染力最有效的变量是“是否使用具体实体”——解释里提到某公司的具体名字比只说“相关企业”点击意愿强很多。这种自动评测流程要在项目早期就建立起来。没有评测集后面每一次调整prompt都只能凭感觉很难持续优化。7. 实操过程一个新闻App的改造实录这套方案是在一个模拟的新闻资讯App上做的改造目标场景是“频道信息流 相关推荐”两个位置。改造过程大致分四步走。第一步是在现有推荐系统上接兴趣信号抽取模块。这一步比较关键因为它要读日志、写特征但又不能影响线上的主流程。我把抽取模块做成了离线任务每五到十分钟跑一批把抽取结果写入缓存服务。线上推荐请求时直接从缓存读兴趣信号响应不会感知到这一层处理的存在。第二步是接解释生成的服务。这一步踩了延迟的坑——最初直接同步调用LLM接口单次生成稳定消耗一到两秒用户请求整体变慢。后来改成异步预生成当推荐结果确定后后台先把解释生成好缓存在Redis里前端展示时直接读缓存基本没有增量延迟。只有当缓存未命中时才触发同步生成做一个兜底。第三步是AB实验测试。对照组用原版推荐不展示解释实验组展示解释。只改一个变量别同时动推荐策略和解释逻辑否则出了问题根本没法归因。跑了大约两周数据之后实验组的点击率显著提升但细看发现提升主要集中在“用户画像丰富”的群体——也就是那些有较多历史点击行为的人。冷启动或行为稀疏的用户解释的提升不明显甚至有时候会下降。第四步是处理冷启动和低质解释的兜底。行为稀疏用户缺乏兴趣信号LLM生成解释时可用素材太少效果自然差。后来我加了一条策略对兴趣信号置信度低的用户不展示解释或者退化为频道级粗粒度解释——“因为你关注了科技频道”。绝不硬生成这是我在这个坑里反复摔出来的教训。8. 常见问题与排查技巧实录8.1 解释与推荐结果逻辑矛盾最常遇到的问题是解释看起来合理但跟推荐的新闻对不上。例如解释里写了“因为你最近关注某公司的财报”推的新闻却压根不是财经类。排查后发现问题出在兴趣信号抽取的滞后性——用户最近点击的新闻已经换了话题但兴趣信号缓存还是旧数据。解决办法是给兴趣信号加时间衰减权重近一天的点击行为权重高三天前的行为权重衰减掉一半。另外生成解释时加入一个校验环节比较新闻的实体/话题标签和兴趣信号里的高频实体/话题如果交集为空就直接降级为不展示解释或用默认解释别硬解释强推。8.2 LLM生成的解释语气过于官方LLM默认输出风格是比较正式的指示词换成“像个懂行的编辑在推荐给朋友”效果会好很多。我在生成约束里加了一条明确禁止使用“根据您的阅读偏好”“为了让您更好地了解”这类套话。如果想要更稳定的风格可以在prompt里给一个样例解释作为few-shot示例。一次给两到三个正反样例效果比在约束里反复强调有用得多。8.3 成本爆炸LLM解释生成的成本一开始容易被低估。如果每天有几百万次信息流刷新每次都同步生成一次解释token开销是相当可观的。实际应对策略有三个缓存优先同一篇新闻面向同一类兴趣信号生成的解释可以缓存起来复用不必每个用户单独生成异步批量生成集中在低峰期把热门新闻的解释池提前填满控制输入输出token新闻摘要截断到200字、兴趣信号控制在几行内、输出控制在三句话内这比任何模型优化都省。8.4 解释影响推荐的自然感有个很有意思的问题解释生成得太好用户把注意力放在解释上反而忽略了新闻内容。AB实验数据发现某些解释里如果提到了具体的数字“你最近看了9篇”“近一周点击了16次”用户会觉得被“监视”了点击意愿不仅没提升反而下降。这个教训让我调整了解释的生成策略数字细节只作为模型生成依据不允许明晃晃写进解释里。用户能接受“你最近比较关注芯片话题”但接受不了“你这周点了16篇芯片新闻”。这里面有个微妙的隐私感知边界要靠实际测试摸出来。8.5 语言风格与新闻调性不匹配严肃新闻、娱乐新闻和体育新闻它们的信息语境差异很大。用同一套解释prompt跑出来的东西放在娱乐新闻下可能显得太理性放在深度报道下又不够有分量。我最终的解法是准备两到三套风格模板按新闻频道做切换。严肃报道的解释重背景关联娱乐新闻的解释重情绪共鸣体育新闻的解释侧重赛程和观众体验。这个区分需要花一点成本维护但对用户体验的提升是实实在在的。9. 落地效果复盘价值在哪里、边界在哪里改造之后我整理过一轮数据。点击率提升可以归功于解释的出现但它不是唯一的价值点。更大的变化在用户侧——信息流里的“推荐理由”展位一出现用户对推荐内容的信任感明显更强。从测试用户的回访来看不少人提到“至少我知道为什么给我推这个了”这种信任感用旧系统是给不了的。解释对产品侧的另一个隐性价值是运营可解释。内容运营编辑可以查看解释生成日志判断推荐策略是否跑偏。曾经有一次模型改版后运动类的推荐量异常上升运营就是从解释日志里发现“运动”标签的权重被意外拉高及时止损。这算是意外收获。边界也很明显。解释不是解决推荐效果问题的银弹它只是让推荐结果更容易被理解和接受的润滑剂。如果你的推荐本身质量差解释写得再好也救不回来甚至会放大用户的负面感知。我曾经测试过在低质推荐上强行加解释结果用户反馈的是“平台在找借口骗我点击”。所以解释模块一定要放在推荐质量已经过关的前提下再做。冷启动用户是另一个边界。行为数据不足时解释效果有限不宜强求。宁可让这部分用户看到没有解释的干净信息流也不要为了追求功能覆盖率而牺牲体验。10. 如果你要复刻这个方案我的一些建议动手之前先确认你的推荐系统质量是否稳定。可解释是放大器不是修复器推荐本身太差就别急着上解释。上线顺序从离线开始。先做兴趣信号抽取的离线任务再做解释生成的离线批量生成观察解释质量的评估结果最后再接入线上异步缓存链路。每一阶段都单独验证过再进下一层排查问题会方便很多。评测至关重要。整理一个小的标注集至少包含300条样本覆盖不同兴趣类型、不同新闻类别的解释质量标注。每次改prompt或改抽取逻辑都拿这个标注集跑一遍打分。算上人力成本前期投入不大但能帮你建立可复现的优化基准线。写prompt时把“可溯源”放在第一优先级。每一句解释都要能对应到证据这个约束要写死在任务定义里。最后多看解释的失败样本。我复盘过大量生成效果差的case发现大部分失败不是什么技术难题而是用户兴趣信号表达得太粗糙。一个具体的、结构化的、可读性强的兴趣摘要胜过再多花哨的prompt技巧。新闻推荐的可解释化本质是让推荐系统从“算得准”进化的“说得清”。LLM把这个进化的成本降到了可以接受的程度剩下的就是各个团队从自己的产品场景出发找到那条真正适合的路。