大模型落地营销广告:货拉拉三层架构与工程实战
去年我们团队接到一个任务把大模型真正用进货拉拉的营销广告链路里。当时内部讨论时两种声音特别典型一种是觉得大模型无所不能干脆把整个广告系统推翻重来另一种觉得大模型就是玩具上线后只会拖慢线上耗时、抬高成本。实际做完一轮之后我最大的感触是真正有价值的不是“用了大模型”这个标签而是把生成、理解、审核这三类能力拆开分别放到广告链路中最合适的位置上。这篇文章就记录这次从数据、微调、部署到线上业务的落地过程分享一些可复用的经验也把踩过的坑原原本本写出来。如果你在电商、本地生活、出行或者货运平台做营销广告算法或者正准备把大模型接入业务系统这篇文章应该能帮你少走很多弯路。1. 业务痛点与整体架构选型1.1 货拉拉广告场景的难点在哪里货拉拉的营销广告跟传统电商广告相比有比较明显的自身特点。C端用户使用场景集中在搬家、拉货、同城运输决策周期短、地域属性强B端司机侧则需要持续招募、活跃留存同时要保证司机收入和平台单量之间的平衡。整个平台的广告位分布在首页信息流、搜索广告、开屏、Push、短信营销等多个入口投放目标既有用户拉新、也有老用户促活、还有司机端招募转化。传统广告系统在文本理解上的瓶颈是很明显的。CTR/CVR模型主要依赖ID类特征、统计类特征和基础的文本匹配特征但广告标题、描述、利益点、适用场景这些长文本语义信息很难被充分利用。新司机、新用户、新广告主都是稀疏样本冷启动问题严重文案素材同质化严重写来写去都是“专业搬家、收费透明、快速上门”运营同学手工改写效率也不高。更深层的问题是广告创意和用户意图之间的匹配不能只看关键词重合度还需要理解“我今天要搬钢琴”和“提供钢琴搬运保护”这种细颗粒度的语义关联。大模型正好在这些痛点上有发挥空间。最直接的是生成能力可以用大模型批量生成几十组广告标题、利益点、场景描述缓解素材供给不足。其次是语义理解用大模型把广告和用户请求映射到语义空间改善稀疏场景下的召回。还有就是控制能力广告上线前需要做素材审核、敏感词过滤、夸大宣传检测过去靠词表规则误杀和漏杀并存大模型可以做得更准。1.2 为什么没有选择“全量重构方案”内部也有同事提出过一个看起来更“彻底”的思路既然大模型能力这么强干脆用它把召回、粗排、精排全部替换掉。这个方案我一开始就反对不是说大模型能力不行而是工程代价和风险完全不可控。广告系统对延迟极其敏感信息流和搜索场景要求整个请求链路在百毫秒级别返回如果每个环节都插入一次几十毫秒甚至上百毫秒的大模型推理线上根本扛不住。另外大模型本质上是概率模型直接做精排打分会有置信度和可解释性问题。业务方问一句“为什么这个人看到了这条广告”我们需要能回答出具体的特征贡献。而精排模型中的LR、DNN这类模型配合SHAP或特征归因至少能给出一个让人信服的解释。大模型生成的内容则需要叠加校验环节比如金额计算是否正确、优惠是否真实可达、是否违反广告法。所以最终我们走了“共生”路线原来成熟的召回和精排体系保留大模型负责给系统提供更好的文本语义、更丰富的创意素材、更准的审核判断。1.3 最终架构生成层、理解层、控制层整个应用架构我习惯分成三层这样团队里做工程、做算法、做数据的人都有一个共同语言。生成层负责广告创意生产、标题改写、利益点扩写、Push文案生成输入是广告主素材和业务画像输出是多种风格的候选文案。理解层负责语义向量召回、广告文本向量化、用户搜索意图识别、人群标签自动扩展。它的产出不只是向量还包括结构化的意图标签和关键词权重。控制层负责广告内容合规审核、虚假宣传检测、折扣准确性校验、敏感行业拦截。所有生成层和理解层的产出都要经过控制层确认后才能进入线上。这个三层架构的好处是边界清晰。生成层坏了最多是素材供给变慢不影响广告主流程理解层出问题召回效果波动但精排还能兜底控制层是唯一要求高召回率的部分宁可误杀也不能漏过违规内容。三层之间互不阻塞我们可以独立迭代、独立灰度、独立回滚。技术底座上我们没有选择接外部API因为广告数据涉及投放策略和用户画像数据合规上走私有化部署是更稳妥的选择。也对比了几种开源底座方案最后选了7B级别的中英双语底座一台A10或者4090级别的单卡就能跑推理训练阶段用4卡就可以完成微调。这套选型保证了后续不管是灰度验证还是正式上线都不用为算力发愁。2. 数据链路与样本工程决定效果的上限2.1 营销广告数据池里有什么可以利用的很多团队做大模型应用时最容易犯的错误是一上来就问“用什么基座模型”却忽视训练数据。实际上模型效果的上限由数据决定模型结构决定了能逼近这个上限多少。货拉拉广告系统沉淀下来的数据其实非常丰富关键是看怎么组织。第一类是广告主侧的素材数据包括历史投放过的标题、描述、图片文案、落地页利益点以及每个素材的曝光、点击、转化数据。这些数据可以直接用于监督微调让模型理解什么风格在什么场景下更容易获得正向反馈。第二类是用户行为序列也就是用户在广告位的曝光、点击、停留、咨询、下单行为这些数据可以构造偏序样本判断哪些广告文案更符合用户需求。第三类是审核数据包含历史上被拒绝的违规素材、被投诉的广告、人工审核的标注结果这些数据是控制层模型训练的核心原料。有一点要特别提醒不要天真地以为CTR高的素材就一定是好素材。点击行为受广告位展示位置、人群定向、投放时段等多重因素影响如果直接用点击率给样本打标模型学到的可能是“不同位置带来的偏差”。我们的做法是把素材归一到同一广告位、同一人群桶、同一时段下再做相对比较最终用转化率、获客成本这些业务指标来打辅助标签。2.2 三种训练样本的构造方式这次项目里我们同时训练了三个能力创意生成、语义召回、内容审核。每个能力对应的样本结构完全不同共享基座模型但使用不同的Adapter这样可以避免一个模型把所有能力揉在一起导致互相干扰。创意生成任务的样本是一个典型的监督式文本生成样本格式大概是这样的{ instruction: 为搬家服务写一条APP内信息流广告文案突出专业和价格透明不超过25个字。, context: 用户近期搜索过钢琴搬运近7天有搬家意向。, output: 专业钢琴搬运全程保险费用明细提前说清 }这里的关键点不只是让模型学会写得通顺还要学会利用上下文中的用户意图。我们会把用户搜索词、浏览行为摘要作为前缀写进prompt让模型生成时具备场景感知能力。样本数量最终控制在20万条左右覆盖搬家、拉货、同城货运、企业服务、汽车增值服务等主要业务线。语义召回任务我们做的是双塔式的对比学习样本但这里没有用传统双塔而是用大模型底座做文本编码产出语义向量再配合Faiss做向量检索。训练样本来自搜索日志和广告投放日志中的“查询词-广告标题”对正样本是有点击或转化的对负样本是从曝光未点击和随机采样中构造的。对错误负样本要特别小心比如“搬家费用”和“宠物托运”看起来完全不相关但如果用户同时看了两个广告就不能简单认为是纯负样本我们会根据行为强度动态调整负样本的难易程度。审核任务的样本则相对直接输入是一条待审核广告文本输出是一个多标签集合包括“是否违规”“违规类型”“风险等级”“建议动作”。历史审核记录天然存在标注偏置早期标注标准比较松后来标准收紧所以训练前要统一标准做一次重标注否则模型会学习到旧标准下的错误判断。2.3 数据清洗的血泪经验第一轮微调我们翻过一个大跟头。直接用历史素材训练生成模型发现生成结果几乎全都在“抄”高频模板多样性非常差。排查后发现问题出在文本重复上——历史素材里有大量同一个模板只改了城市名的文案比如“北京专业搬家”“上海专业搬家”看起来是不同样本但模型学到的是复读机。解决办法是加了一层MinHash近重复去重相似度超过阈值的只保留一条同时保证每个业务线、每种利益点类型都有足够的覆盖。另一个坑是数据穿越。训练语料里混入了投放周期比较长的素材导致验证集里也包含同一条文案离线指标虚高。我们后来严格按时间切分训练集取前60天数据验证集取最近14天数据再用规则检查训练集和验证集的公开标识比如素材ID是否有重叠有重叠就剔除。这看起来是基础操作但真到了做样本工程的时候很多人为了贪图样本量会睁一只眼闭一只眼最后上线效果还原不了离线结果反而更耽误事。还有一个容易被忽略的问题是标签噪声。广告点击数据里存在大量误点击和恶意点击直接拿这些样本喂给模型会让生成模型学到“标题党”倾向。我们设计了一套规则点击后停留小于2秒的样本降权短时间内连续多次点击同一广告但无后续行为的用户样本直接过滤。迭代过程中还做人工抽检每批次抽500条样本由运营团队给新旧版本打分抽检一致率低于85%的样本批次不进入训练。3. 模型选型与微调细节花小钱办大事3.1 基座模型怎么选7B是甜点还是妥协模型选型上我们经历了比较长的技术调研。一开始团队里有人提出直接用千亿级API效果好但数据合规和成本都不太接受也有人提议私有化部署一个数百亿参数的大模型结果评估下来光是GPU服务器成本就够养好几个算法工程师了。最终锁定在7B到14B这个区间的开源底座实际跑完业务侧的效果之后确定用7B中英双语底座作为主力。为什么7B够用因为我们的广告文案本身长度有限单条素材通常在20到80个字之间输入的用户画像信息也不复杂模型的推理任务负载并不重。7B模型的语义理解能力和文本生成质量在广告这种“短文本、强结构化”的领域中跟14B甚至更大模型的差距并没有想象中那么大。我们把同一套验证集跑完对比在ROUGE-L、语义相似度和人工好评率三个指标上7B只比14B低不到3个百分点但推理时延降低了一半多显存占用也从接近40GB降到不到20GB。对广告系统来说延迟就是钱这个妥协是值得的。当然7B也有明显的短板主要体现在复杂指令跟随和长文本推理上。比如让它根据用户历史行为序列做深度归因或者生成包含多条件优惠计算的文案它偶尔会丢条件或算错金额。这种情况我们不硬扛而是把任务拆解条件校验交给规则系统优惠金额计算用模板填充大模型只负责生成“人话”部分。3.2 微调方式对比为什么选LoRA而不是全量微调基座模型确定后微调方式是我们讨论最久的技术细节。三种主流方案我们都做了小规模实验全量微调、LoRA、QLoRA。全量微调的效果上限最高但训练成本惊人。7B模型全量微调在A100-80G上即使用了ZeRO优化也需要至少4卡才能跑得比较舒服一个epoch就要两三个小时而且每次实验调参都要重来迭代效率太低。QLoRA的显存占用确实最低4-bit量化后甚至可以在单张4090上跑但训练速度偏慢且量化带来的信息损失在广告审核这类精细任务上偶发误判。最后我们选择的是LoRA加16-bit混合精度训练用4张A10训练效果和成本达到了一个比较舒服的平衡。微调参数上我们的经验是rank不要一味追求大。早期试过rank64训练收敛慢且推理时有额外显存开销稳定下来用的是rank32、alpha64、dropout0.05这个配置在生成质量和训练速度之间比较均衡。学习率用2e-4warmup ratio设为0.1batch size按每个GPU 16条样本、梯度累积8步来设置相当于每轮更新用512条样本的梯度。训练轮数我们控制在2到3轮超过3轮会开始出现明显的过拟合验证集困惑度上升生成内容变得死板。# 训练命令示例细节略去平台相关配置 accelerate launch --mixed_precision bf16 \ --num_processes 4 \ finetune.py \ --base_model /data/models/qwen-7b-chat \ --adapter_name lora_ads_v1 \ --rank 32 \ --alpha 64 \ --learning_rate 2e-4 \ --num_epochs 2 \ --batch_size 16 \ --gradient_accumulation_steps 83.3 离线评测与上线前的三道关卡离线评测如果只用一个指标大概率会被带偏。我们设置了三个维度的指标只有三个维度都达标才允许进入线上灰度。第一是生成质量指标。计算生成文案和历史高转化素材之间的ROUGE-L、BLEU同时对文本多样性做统计比如重复n-gram占比、同一业务线下生成结果的成对相似度。我们希望ROUGE-L不要太高太高说明模型在背模板也不要太低太低说明模型跑偏了。第二是语义一致性指标。把生成文案和原始需求放到底座模型的向量空间里算余弦相似度低于阈值的结果直接丢弃。这能过滤掉“答非所问”的生成结果。比如业务方要的是“同城货运”模型生成“长途搬家”即使语句通顺也不会被采用。第三是安全合规指标。我们专门构造了一个包含1200条挑战样本的评测集覆盖夸大宣传、敏感行业、竞品词、价格歧义等类型。大模型生成的每一条内容都要经过控制层审核审核不通过的直接拦截。这里对召回率的要求是至少99%哪怕误杀率高一点都接受因为违规带来的平台风险远比多花一点审核成本严重。三道关卡全部通过后我们才做小流量AB实验。AB实验观测的不是单一的CTR而是综合了点击率、转化率、获客单价、投诉率四个指标。第一轮实验跑出来点击率提升了8%左右获客成本下降了6%左右但投诉率没有明显变化说明文案质量过关。这里多说一句做AB时一定要同时设置一个“人工撰写优质文案”的对照组不然老板会质疑“是不是因为新人写的文案太差才显得大模型好”。4. 线上推理部署与广告链路接入稳定压倒一切4.1 部署方式与首版性能数据线上部署我们用了vLLM作为推理框架它支持PagedAttention和Continuous Batching在高并发场景下能把GPU利用率拉得很满。模型权重做了16-bit和8-bit两种版本首版先用16-bit保证效果后续需要压成本再切8-bit。一个比较稳定的组合是单张A10跑7B模型16-bit最大输入长度512、输出长度128并发请求数设置成8首版线上压测的单个请求P95时延在180毫秒左右QPS能做到40上下。这个时延对内容生成类场景完全够用但绝对不能放在用户请求的同步主链路上。我们做了一个异步任务队列上游把需要生成文案的素材包推送到MQ消费者从MQ拉取任务后批量调用推理服务生成结果回写KV存储再由广告检索服务读取。首版上线后队列积压最严重的一次是凌晨大促活动几十万条素材同时涌入我们通过把消费者实例从3个扩容到10个在15分钟内就把积压清掉了。部署时还有一个容易忽略的点模型热加载。如果每次发版都手动重启推理服务整个链路会中断几分钟。我们最终把模型文件放在共享存储上启动时从共享存储加载权重发版通过更新Adapter文件实现秒级切换。配合灰度发布流量按1%、5%、20%逐步放开随时可以一键回滚到上一版。4.2 在广告召回、精排、创意环节的落点大模型在召回环节的价值主要体现在语义召回。传统的关键词召回只能匹配字面重合比如用户搜“搬钢琴”关键词系统只能召回标题里带“搬钢琴”的广告而“钢琴搬运”“钢琴托运”“贵重物品运输”这些语义相关的广告全部漏掉。我们利用大模型把用户查询词和广告标题统一编码成128维向量再叠加一层基于Faiss的ANN检索。实践下来的一个关键教训是向量召回不能单独用要和传统召回融合。我们在精排阶段把两种召回的得分都带上用特征交叉让精排自己学习偏重哪一种上线后召回率提升了12%但广告主覆盖率没有下降说明融合确实有效。精排环节我们比较克制没有直接把大模型作为打分器放进去。只在精排特征里增加了一个“大模型生成文本质量分”这个分数是控制层审核后得到的综合质量得分包含语义相关性、合规置信度、风格一致性等信息。精排模型拿到这个分数后会更好地过滤掉低质素材同时不影响原有特征体系。创意环节是大模型介入最深的地方。运营和广告主上传一条原始素材后系统自动基于用户画像生成多个版本的标题和利益点描述。比如一条原始的“专业搬家”素材大模型可以生成“钢琴也能安全搬运”“本周下单立减30元”“搬家师傅提前电话沟通”等多个变体然后自动做小流量测试用真实点击和转化数据反馈给生成服务形成“生成-投放-反馈-再生成”的闭环。这个闭环跑起来之后我们不再依赖人工从一堆文案里挑选而是把筛选交给数据。4.3 广告内容合规与风险控制广告行业的合规要求非常严格虚假宣传、违规承诺、敏感词、竞品贬低都是红线。传统词表规则最大的问题是无法处理语义变体比如“不花一分钱就能搬家”这种表达词表里未必有“不花一分钱”这个关键词但语义上明显属于诱导夸大。我们的控制层用大模型做文本分类输入是完整的待审核文案输出是违规类型和风险概率。模型覆盖的违规类型包括虚假折扣、绝对化用语、医疗功效承诺、金融误导、竞品攀比、性暗示擦边等。对于生成任务我们在prompt里强行加了一条“禁止输出与事实不符的促销信息禁止输出模糊价格”同时在解码阶段做了logit级别的约束如果生成文本中包含未出现在白名单里的价格数字或优惠折扣直接熔断重试。这一招非常管用上线后由模型幻觉导致的虚假折扣问题下降了90%以上。还有一个容易被忽略的细节模型要识别平台特有的业务黑话。有些词汇在普通场景没有风险但在货拉拉业务下就是违规词比如“司机绕路”“私下交易”“场外结算”。我们会在训练数据里专门补充这类业务正负样本并且维护一份动态的业务敏感词表大模型分类结果和敏感词表结果做加权融合两者都判断为风险时才放行否则进入人工审核列表。整体来说控制层的存在让业务方对大模型生成内容有了基本信任否则他们根本不敢把模型产出推到用户面前。5. 踩坑记录与问题排查这些坑常规文档里不会写5.1 模型幻觉差点把优惠金额算错第一次灰度时出现了一条“新用户立减100元”的文案但运营后台配置的真实优惠是“新用户立减30元”。原因是模型在读历史素材时学到了一个旧版本的优惠信息把它当成了通用的业务规则。这个问题光靠微调很难解决因为大模型本质上是在做概率预测它不知道促销活动具有时效性。我们最终的解决方案分三路提示词里把当前有效优惠信息单独放在“系统固话区”并用特殊分隔符和正文隔开生成结果里所有数字金额、折扣、满减必须预先经过模板化处理大模型只选择活动模板ID不直接生成数值最后校验模块检查所有数字是否与配置中心的活动参数一致不一致直接拦截。三路都加完之后类似问题基本清零。5.2 生成内容多样性不足第一版模型刚上线时运营反馈“十条文案起码六条惊人相似”我们检查发现其实是解码参数太保守了。为了求稳我们把temperature设成了0.1top_p设成了0.8结果生成的候选池里最频繁的几条模板占据了绝大多数。后来调整成temperature0.8、top_p0.9同时加了一个重复惩罚参数把生成结果的多样性明显拉开。但过高的temperature也会导致语法错误和语义漂移所以现在的做法是先生成20个候选然后过一个多样性筛选器保证最终进入AB池的10条文案两两之间相似度不超过0.75同时语义一致性得分都高于阈值。5.3 数据穿越让离线指标虚高差点误判模型能力在2.3里我提过数据穿越的问题这里再补充一个具体教训。有一版模型离线评估指标特别好ROUGE-L和语义一致性都大幅超过前一版但上线后效果没有明显提升。定位后发现是训练数据里包含了来自未来时间段的素材。具体场景是我们当时只按素材ID做了去重没有严格按时间切分导致测试集里混入了已经在线上投放过的历史素材模型等于“开卷考试”。后来我们加了时间过滤同时用规则检查训练集和验证集的文本重叠度把这个bug彻底堵住。做数据工程的人都知道这件事但真正动手时特别容易因为图省事而跳过我在这里强调第二次是因为它真的值得强调。5.4 线上推理延迟波动和GPU显存溢出首版部署时我们用的是单路同步推理压测时P95延迟非常好看但一上生产环境就原形毕露早晚高峰期用户请求并发上来后P95时延从180毫秒飙到接近1秒偶尔还会报CUDA Out of Memory。排查后发现是实例上混跑了好几个模型副本互相争抢GPU显存加上vLLM的KV Cache策略没有配置好长尾请求把缓存占满了。解决办法是分配独立的GPU实例给生成式服务并显式设置KV Cache的显存上限比例比如gpu_memory_utilization0.85同时配合请求排队和队列超时熔断。这一轮调整之后高峰期的P95时延稳定在350毫秒左右抖动幅度明显收敛。6. 项目复盘与我的个人体会6.1 复盘中值得肯定的三件事第一件事是坚持了“小步快跑、分模块上线”的节奏。我们没有搞一个“大模型全流程改造”的大版本而是把生成层先灰度验证稳定后再推理解层最后才上控制层这样每一层出问题时影响半径都很小。第二件事是把数据工程和大模型训练放在了同等重要的位置前期花了将近三周时间做样本清洗和标注标准统一虽然看起来拖慢了启动进度但后面模型迭代的效率成倍提升。第三件事是建立了比较完整的离线评测和上线回归体系特别是安全审核挑战集让业务方对生成内容建立了信任。如果要说做得不够好的地方我觉得是对大模型输出结果的解释性工具准备得偏少。业务方经常会问“为什么这个文案能过审、那个文案不能”我们只能事后分析日志。如果一开始就把日志埋点和归因模块做进控制层后续沟通成本会低很多。6.2 后续我还会做什么下一步我们在看两个方向。一个是多模态素材生成不只是文本而是把图片、文案、落地页结构化信息打通用统一的大模型底座去生成整张广告卡片这需要把视觉编码器接入现有的生成流程对推理成本和延迟提出更高要求。另一个是Agent化运营让大模型不只是“生成一条文案”而是能根据投放数据自动调整人群包和出价策略做成一个能对业务指标负责的智能体。这两个方向我们目前都在做技术验证但核心原则不变任何模型的产出都必须经过控制层校验任何推广效果都必须用AB实验说话。从个人经验角度说这次项目最深的体会是大模型不是银弹它更像是给广告系统装上了一个更强的“言语中枢”。真正决定项目成败的不是你用了多大的模型而是你把它放在什么样的工程链路里让它在什么时候该出场、什么时候该闭嘴。这个分寸感才是应用团队最需要修炼的内功。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →