有人问我,数字公关是不是就是“用AI写新闻稿”?我说你要是这么理解,那这个活三个月就能干完,根本不需要中台。真正难的不是让模型写出一篇稿子,而是让舆情监测、内容生产、媒介分发、效果归因这几个环节在一套系统里持续跑通,并且每个环节产出的数据都能反过来优化下一个环节。我们团队花了一年多时间,从零搭了一套数字公关AI中台。这篇文章把架构的来龙去脉、关键技术决策、核心模块实现和实际踩坑一次性讲清楚,希望能给正在做同类系统的朋友一些参考。
1. 项目背景与核心需求拆解
1.1 数字公关AI中台到底要解决什么问题
数字公关行业跟其他行业不太一样,表面上拼的是文案能力和媒体资源,实际上拼的是信息处理速度。舆情哪一刻冒头、什么话题在社交平台开始发酵、哪些媒体会跟进、稿子发出去之后到底带来多少声量,这些问题以前全靠人肉盯着,几个群里来回转发截图,等发现的时候热点已经过去了。所以我们明确了一个目标:把公关作业链条上的数据采集、事件分析、内容创作、渠道分发、效果归因全部串成一套可编排的服务,让每个环节都能被监控、被度量、被优化。这个目标定下来之后,“AI中台”就不是一个时髦词,而是业务刚需。
老规矩,先拆痛点。第一个痛点是舆情监控滞后。公开信息分散在新闻门户、社交平台、行业垂直站点,人工巡检的覆盖率和时效性都上不去。第二个痛点是内容生产缺少弹药。写稿子的人需要背景资料、历史报道、相关专家和媒体偏好,这些知识散落在每个人的电脑里,换个人就找不到了。第三个痛点是效果黑盒。稿子发出去之后,往往只能看阅读数,根本不知道是哪家媒体带来的流量、哪类受众在讨论、正面负面情感怎么变化。第四个痛点是复盘靠Excel,做完一个项目要花两三天整理数据,整理完也没法形成下一次行动的策略。
这四个痛点对应到中台建设上,就是四个核心能力:实时数据接入能力、知识沉淀与语义检索能力、内容生成与质量管控能力、多触点归因分析能力。能力建设不能各做各的,因为它们之间天然有依赖。舆情事件分析结果要喂给内容生成做素材,内容分发数据要回传效果归因,归因结论再反哺下一步的舆情监控关键词。所以我们的第一版架构不是从某个模块开始写,而是先把这条数据闭环画出来,再谈技术选型。
1.2 边界划分:为什么不能一上来就拆微服务
我刚接手这个项目时,团队里已经有一些零散的脚本和后台,有的负责抓新闻,有的负责生成周报,有的负责管理媒体联系人。如果按功能直接拆微服务,很快会得到一堆互相调用的“分布式单体”,接口盘根错节,数据口径各说各话。所以我们先做了一件事:用领域驱动设计的思路划分边界,而不是按功能点划分。
最终划分成四个域。第一个是数据接入域,负责所有公开渠道的采集、去重和标准化,对外只提供“事件流”和“实体更新”这两个出口。第二个是分析智能域,负责情感分析、事件聚类、实体识别、传播路径计算,它消费数据接入域的事件流,再产出事件标签、热度趋势和传播关系。第三个是内容生产域,负责素材检索、大纲生成、正文生成、事实核查和人工审核流程,它依赖分析智能域的标签数据和自己的知识库。第四个是投放分析域,负责渠道数据回收、归因计算和报告生成,它接收内容生成域发布的内容标识,再回流效果数据。
这四个域之间有一条明确的依赖规则:下游只能消费上游的产物,不能反向读取上游的原始库。比如内容生产域想做传播效果分析,它不能直接连投放分析域的数据库,必须通过投放分析域提供的查询接口。这样做的原因很直接:每个域的存储模型是为自己服务的,别人直接连库,等域内部改了表结构,下游就崩了。中台的本质是把业务能力封装成接口,而不是把数据库分享给所有人。这个边界原则在后来的迭代中帮了大忙,至少我们没出现过“为了一个字段跨库join”这种烂账。
2. 总体架构设计与技术选型
2.1 六层架构与数据流转
确定好业务边界后,技术架构自然分成六层。最底层是接入层,承载着所有公网数据源的采集任务,包括定时抓取、订阅推送、开放API轮询,以及一些实时流接入。接入层不做任何数据分析,只负责把源数据变成统一的JSON结构扔进消息队列。第二层是标准化层,负责数据清洗、去重、语言识别、URL归一化,把同一件事在不同渠道的报道关联起来,产出“事件ID”。第三层是分析层,消费标准化事件,跑实体识别、情感分类、事件聚类和热度计算,结果写入分析存储和向量库。第四层是服务层,把下游能力统一封装成REST API,包括事件检索、素材检索、内容生成、任务创建和报告查询。第五层是应用层,包括运营工作台、内容编辑器、实时看板和后台管理。第六层是治理层,不直接参与业务,但贯穿所有层,包含权限认证、审计日志、限流熔断和可观测性组件。
数据流转的真实路径是这样的:一条新闻从某个媒体网站被抓下来后,先进Kafka的raw-events主题,标准化服务消费它并产生normalized-events,分析服务再消费normalized-events输出事件标签和实体关系。内容生成服务需要素材时,不直接消费消息,而是调用分析域的API拿事件ID列表,再从知识库和向量库检索相关资料。生成的内容完成人工审核后,会发布事件到content-published主题,投放分析域的归因服务消费这个消息,开始跟踪传播链路。每一步都通过事件驱动解耦,避免上游接口慢导致下游阻塞。这个设计不是一开始就拍脑袋定的,是经历过一次“同步调用链爆炸”之后重构出来的,后面我会讲那个案例。
2.2 存储选型:每种数据都有自己的家
在这个中台里,数据形态差异非常大,用一种存储打天下会非常痛苦。我的选型原则很简单:按照读写模式和一致性要求,给每种数据找最合适的家。
事件流水和内容快照用关系型数据库做主库,因为要支持条件查询、事务更新和审计,比如“查某客户近一周所有正面事件的原始链接”,这种查询单靠文本检索效率很低。实体关系网络用图数据库,用来分析媒体关系、KOL传播路径、事件之间的演进关系。语义检索用向量库,支撑“找跟当前事件最相似的历史案例”这类模糊匹配。任务状态和工单用带版本号的文档存储,因为流程编排需要频繁更新状态且保留历史。指标结果和报表用列式存储,承担大范围扫描和聚合计算。
风险在于多存储必然带来一致性问题。我们没有采用分布式事务,而是用了“主库产生事实,其他存储异步同步”的模式。业务上真正需要强一致的只有内容审核与发布这一步,其他场景允许秒级延迟。比如事件数据写入主库后,通过消息异步同步到向量库和图库,如果同步失败就重试,重试还失败就进死信队列,由巡检任务兜底重建。这个取舍要讲清楚:中台内部的数据一致性,应该聚焦在业务关键时刻,而不是全链路强一致,否则性能和复杂度都会被拖垮。实际运行下来,这套异步同步方案完全够用,因为公关业务对数据的新鲜度容忍度在分钟级,而不是交易系统那种毫秒级。
2.3 模型选型与推理网关设计
AI中台最核心的选型是模型。我们的经验是:大小模型各干各的。舆情分类、情感识别、实体抽取这些高频且要求低延迟的场景,使用领域微调的小模型,成本低、延迟稳定、效果可解释。内容生成、摘要改写、传播文案润色这些需要语言理解和创作能力的场景,使用通用大模型。为什么不全部用大模型?我算过一笔账,如果所有文本都用大模型跑一遍,每天几百万条舆情内容的推理成本会直接划不来,而且大模型推理延迟不稳定,舆情突发时容易积压。更关键的是,小模型出错了可以明确知道是哪一层的问题,大模型出错了解释成本太高。
为了屏蔽底层模型的差异,我们做了一个推理网关。网关统一封装输入输出格式,定义任务类型、模型ID、超时时间和降级策略。业务方调用时只传任务参数,不关心背后是哪个模型。网关内部负责路由、并发控制、结果缓存、失败重试和token计量。这样带来的一个直接好处是模型可以灰度替换。比如内容生成模型从A版本切到B版本时,只需调整路由权重,先在10%的流量上观察结果质量,没问题再逐步放大,不会影响业务方代码。
这里有个容易忽略的细节:大模型的输出格式必须做严格校验。我们要求所有生成任务返回结构化JSON,网关在返回给业务方之前先做schema校验,字段缺失或格式错误就自动重试一次,重试仍失败就走兜底模板。宁可给用户一个通用的框架稿件,也不能给一个带着错误字段的半成品。这个校验环节在早期没有,上线后吃了不少亏,后来才补上。
2.4 容器化部署与弹性拓扑
整套中台跑在Kubernetes集群上,按业务域划分命名空间,dev、staging、prod三套环境各自独立。服务通过Helm管理发布,镜像打上Git commit的短哈希作为版本号,回滚时可以精确定位到代码版本。核心业务的Pod都配置了资源请求和限制,避免一个服务把节点内存吃满,导致同节点的其他服务一起被拖死。
弹性伸缩方面,我们针对不同服务用了不同策略。舆情接入和标准化服务是CPU密集任务,使用基于CPU利用率的HPA,配合PodDisruptionBudget防止缩容时打断任务。内容生成服务是IO和GPU密集任务,使用基于自定义指标(队列深度、推理网关的排队长度)的HPA,并且设置了最小副本数,因为模型推理服务冷启动很慢,不能等积压了才扩容。还有一个实操细节:模型推理的GPU节点不要和业务Pod混部,否则GPU利用率波动会干扰CPU服务的稳定性。这些看起来很基础的部署拓扑,在整个中台稳定性上起了决定性作用。
下面给一个我们内部上下文中“舆情标准化服务”的部署片段,注意不是完整配置,只是为了说明关键字段:
apiVersion: apps/v1 kind: Deployment metadata: name: event-normalizer namespace:>你是某企业的公关撰稿助手。 请根据以下素材和写作要求,完成"{{section_title}}"这一节。 要求: 1. 语言客观,不使用夸大词汇。 2. 引用素材中的数字时,必须原样保留单位和精确值。 3. 每段不超过4句话,总字数控制在500字以内。 4. 不得编造任何素材中未出现的事实。 素材包: {{context}} 写作要求: {{section_requirement}}这个模板看着简单,但里面有三个关键点:限定引用数字必须原样保留,是为了方便事实核查;限定段落长度,是为了控制生成模型的注意力范围;强制声明不得编造事实,是为了尽量减少幻觉。当然提示词只是第一道防线,后面还有独立的校验服务做第二道防线,双保险才算真正可靠。
3.3 传播链路追踪与归因分析
传播效果这个模块,我们走过弯路。最初以为只要接入媒体平台的后台数据就够了,后来发现公关场景更多是公开网络传播,平台后台数据覆盖不全,而且不同平台指标口径不一样。所以我们换成“内容指纹+公开站内数据”的组合方案。
每篇稿件发布前会生成一个内容指纹,它基于正文的simhash和发布媒体ID联合计算。归因服务定期抓取公开渠道上包含相同指纹的内容,通过发布时间差和转载关系构建传播树。有了传播树,就可以计算几个核心指标:首发媒体、二级转载率、传播深度、声量峰值时间、情感分布变化。举例来说,某篇稿件首发在一家行业媒体,两小时内被五家门户转载,其中一家门户的转载带来了后续的社交讨论峰值。传播树能清楚地把这条路径还原出来,而不是只给一个总阅读数。
归因模型方面,我们没有直接用“最后一次触点归因”,因为公关内容的价值往往在首发和早期转载,而不是最后的某一个点击。最终用的是时间衰减加权:离首发时间越近的传播节点,在归因中的权重越高。这个模型不算复杂,但它和业务目标匹配得很好。做归因分析最怕的不是模型不精确,而是埋点数据缺失,所以我们还设计了对账任务,定期把媒体端报告的数据和爬取数据做差异比对,差异超过阈值就告警。
3.4 知识库与检索增强生成的实际落地
内容生成引擎刚上线时,质量和下限都不错,但有一个问题:对历史案例和媒体关系的引用不够准确。生成出来的稿子虽然通顺,却缺少针对性和家族记忆。为了解决这个问题,我们上线了知识库,并在生成链路里接入了RAG。
知识库的内容来源有四类:历史新闻稿和传播报告、媒体背景与记者偏好、品牌定位语料、行业研究报告。文档进入知识库前会做清洗和分块,每块最多800字,保留标题、发布时间、来源、业务线等元数据。分块大小是我们调出来的,太小了上下文信息不足,太大了向量检索的精度会下降。检索时会先做查询改写,把“最近的新能源车安全事故”改写成带实体和时间范围的关键词,然后同时走BM25和向量检索,两类结果合并后用重排模型取TopK。重排这个步骤刚开始没做,导致检索结果经常有相关性不错但信息陈旧的内容,加上重排之后明显改善。
为什么坚持用RAG而不是微调?因为公关知识更新太快,微调模型没办法跟着每天的新闻实时变,而且微调的成本和风险评估都很高。RAG能把知识更新变成知识库里的文档增删改,模型本身的参数不动,出问题可以快速定位是知识库的问题还是生成模型的问题。这个决策让我们的内容查证效率提高了很多,也给业务方建立了一个很直观的心智:稿子里的每个关键结论,都能点开“引用来源”看到出处。对公关这个极其讲究“每一句话都要有依据”的行业来说,这一点甚至比生成质量更重要。
4. 工程化落地与避坑实录
4.1 绞杀者迁移:不要幻想一次性重写
项目启动时,公司已经有一套勉强在跑的老系统,如果停掉老系统一次性切换到新中台,风险非常大。我一开始也差点走上“大爆炸”的重写路线,后来被一次联调事故劝退了。那次联调只是切换了一个很小的订阅服务,都因为数据口径不一致折腾了三天。从那以后,我们改用绞杀者模式:按数据流顺序,从接入层开始,一个环节一个环节替换。
具体节奏是这样的。第一轮先替换舆情采集和标准化,老系统继续写自己的库,同时把标准化结果同步到新中台的Kafka,相当于老系统变成新中台的一个数据消费者。第二轮替换分析模块,让新中台的事件分析结果直接写入老系统的舆情库,老系统界面不用变。第三轮替换内容生成和归因,此时老系统只剩一个前端壳子,数据全部来自新中台。每替换一轮,都留出两周时间让业务方对比新旧数据,确认没有差异后再切流量。
这个过程中最关键的是数据对齐。我们每一轮切换都会跑一个数据比对任务,拿新旧两边的核心指标做差异比对,比如事件总数、实体覆盖率、情感判定一致率。差异率超过1%就要回滚或修复,不能带着问题继续往下走。绞杀者模式听起来慢,实际上是最快的方式,因为每一步都可回退、可验证。如果一开始就追求一步到位,大概率会陷入“改了三个月还没法上线”的泥潭。
4.2 突发流量下的弹性与成本控制
数字公关有一个很特殊的流量特征:平时很平稳,一旦出现重大社会事件或品牌危机,舆情数据量会在短时间内暴涨几十倍。我们经历过一次大流量冲击,当时Kafka消费者组全部积压,NLP服务CPU打满,消息一直延迟到40分钟才处理完。对公关来说,40分钟足够让一个话题从萌芽变成爆发。
复盘之后做了三件事。第一,给采集服务设置优先级队列,重大事件的采集任务可以抢占普通任务的资源,保证关键数据优先入库。第二,给分析服务设置消费上限,宁可丢弃一部分非关键事件的低置信度分析,也要保证核心事件的时效性。第三,为推理网关预留弹性缓冲,在高峰期自动把低优先级的生成任务降级为排队等待,同时把一部分同步调用改成异步回调。这三件事的组合,让我们在后续多次流量冲击中保持了分钟级延迟。
成本控制和高可用是硬币的两面。大模型推理很贵,所以我们做了三层削减:结果缓存、批次化、前置过滤。内容生成的相似请求直接走缓存,比如同一个事件的多条稿件共用素材摘要,摘要只生成一次。舆情分析则先用小模型初筛,只有低置信度或者被规则命中的文本才送大模型做二次判定。这样算下来,大模型推理调用量降了大概70%,而整体效果几乎没有下降。省钱省下来的预算,反而可以投入到GPU节点冗余上,形成正向循环。
4.3 可观测性:没有统一Trace就没法排查
中台服务一多,最怕的是出了问题时不知道问题在哪一层。我们的可观测性建设分成三块:指标、日志和链路追踪。指标用Prometheus采集,Grafana做看板,核心看板包括采集任务失败率、Kafka消费者Lag、消息处理耗时、API P99、模型调用token消耗。日志集中到统一平台,保留30天,按服务名和traceId建立索引。链路追踪用OpenTelemetry,从接入层的HTTP抓取开始,到标准化、分析、生成、归因,全链路共享同一个traceId。
为什么链路追踪特别重要?因为一个从舆情到内容的完整业务流程会跨五六个服务,任何一个环节慢都会导致用户感觉“卡了”。有一次业务反馈“报告生成特别慢”,单看每个服务指标都正常,最后通过链路追踪发现是知识库检索的一个N+1查询问题:稿件生成时要检索10个素材,每个素材都要查一次向量库,串行下来耗时翻了好几倍。改成批量检索后,耗时从12秒降到2秒。这种问题如果没有关联traceId,只能靠各服务日志时间硬拼,效率极低。
另外提醒一句,日志一定要做脱敏。我们的日志中会有媒体名称、链接、摘要片段,这些信息在存储和查询时都要做权限控制。运营人员在排查问题时,只能看到脱敏后的数据,避免内部素材信息被无关人员拉取。这个不是技术问题,但必须从建设初期就定好规则,否则后期清理成本很高。
4.4 多租户隔离与权限审计
数字公关中台通常要服务多个客户品牌,每个客户的数据必须严格隔离。我们在架构上做了三层隔离。第一层是服务层隔离:每个客户可以配置自己的模型调用配额和优先级,重要客户的生成任务可以插队。第二层是数据层隔离:所有业务表都带tenant_id,查询强制拼接租户条件,向量库检索也带租户过滤条件,防止通过语义相似度检索串数据。第三层是界面层隔离:运营工作台只能看到当前租户的数据和配置。这里有个容易被忽视的点:不要迷信“独立数据库实例”能解决一切,那只是隔离维度之一,真正容易出错的是代码里漏加租户条件,所以我们在ORM框架层做了一个强制拦截,统一注入租户条件,约定所有查询必须走框架封装的方法,不允许裸写SQL。
权限审计方面,我们实现了RBAC权限模型,角色包括管理员、运营、分析师、审核员。关键操作都有审计日志。内容发布前必须经过审核员操作,发布动作会记录操作人、操作时间、稿件版本、目标媒体。审计日志保留一年。为什么会强调这个?因为公关内容一旦发出,涉及对外口径和责任认定,如果出了问题只有稿子没有操作记录,复盘和追责都无从谈起。中台不只是一个提效工具,也是一个合规基础平台,这一点越早想清楚越好。
5. 常见问题与排查技巧实录
5.1 “全网声量突然下降”先查采集,再查分析
使用中台之后,业务方最先依赖的是实时看板。某天早上业务方突然说“声量跌了40%”,我们第一反应不是算法问题,而是数据入口问题。排查顺序固定为:先看采集任务失败率,再看Kafka消费者Lag,再看NLP服务错误率,最后才看业务指标计算逻辑。那次的问题出在某个信息源悄悄改了页面结构,采集解析器返回全是空字段,解析失败率飙升,但采集服务因为“请求成功”还显示正常。我们用“解析成功率”指标才捕捉到异常。所以说,监控采集任务时不能只看HTTP状态码,一定要看解析成功率、字段完整率这类业务性指标。
还有一个容易踩的坑是Kafka消息积压。消费者Lag涨了不代表一定有问题,也可能是瞬间流量上涨,先看持续时间和积压区间。我们之前就遇到过,某个信息源突然推送了大量历史报道,Lag瞬间拉高,但只持续了几分钟就被消费完了,业务指标没受影响。所以我们在Lag看板上加了阈值告警,超过5分钟未恢复才触发电话告警,避免误报疲劳。另外还要关注Lag的分区分布,如果只有一个分区积压严重,其他分区正常,大概率是事件聚类的热点key问题,不是整体处理能力不足。这条规则后来帮我们在业务方感知之前处理过好几波隐患。
5.2 大模型输出不稳定,靠“低温度+强校验+兜底”三板斧
有朋友问,大模型生成的内容怎么确保稳定,特别是给客户看的东西。我们不是靠运气,而是靠三板斧。第一是低温度。写作任务统一设置temperature在0.2左右,最高不超过0.4,减少随机性,保证同一个输入重复生成的结果基本一致。第二是强校验。模型输出必须通过JSON schema校验,校验失败的自动重试一次,如果还不行就把这个case记录下来,用于后续调优提示词或模型参数。第三是兜底模板。当模型服务不可用或连续校验失败,生成引擎会返回一个由规则模板拼装的稿件框架,附带提示“需人工补充”,至少不会让用户面对一个空页面。
这里要强调,不要把模型放在流程的最前端直接面向用户,而是放在生产链路的中间环节。用户拿到的永远是经过校验、审核、模板兜底之后的结果。即便模型在某些case上表现不稳定,我们也保证出口的稳定性。这是中台和纯AI玩具之间最大的区别。
5.3 任务编排重复执行与幂等控制
内容生成、报告生成这类任务都会经过编排引擎,而编排引擎基于消息队列,消息投递是at-least-once语义,同一个任务可能被消费两次。最开始我们没有做幂等,结果出现过一个报告被生成了两次。排查下来发现是消费者在提交偏移量之前发生了重平衡,任务被重复拉取。
解法很简单:给每个任务定义全局唯一的taskId,在数据库里建任务状态表,状态流转必须通过条件更新实现。任务进入处理节点前,先尝试把状态从PENDING更新为RUNNING,如果更新影响行数为0,说明另一个实例已经在处理,当前实例直接丢弃。节点执行完成后,再更新为SUCCESS或FAILED。任务重试时,只对失败节点做补偿,而不是整个流程重跑。比如报告生成依赖素材检索、摘要生成、图表生成三个子步骤,素材检索成功了,摘要生成失败,重试时只需要重新执行摘要生成,不能把素材检索再跑一遍。这个规则写进编排引擎后,重复执行的问题基本绝迹。
还有一些必须人工介入的场景。比如一个任务连续重试三次都失败,就会进死信队列,运营工作台出现一条待处理工单。工单上能看到任务Id、失败节点、错误日志和当时的入参,人工修复后可以重新放入队列。这条人工闭环虽然不常用,但它是整个任务编排可靠性的最后一道保险。
最后再分享一点我个人的体会。技术架构做得再漂亮,如果业务侧的数据没有闭环回来,中台很快就会变成一堆无人维护的接口。我们之所以能在一年多里持续迭代,靠的不是某个模型多厉害,而是每一次舆情事件、每一篇稿子、每一个传播数据最终都在反哺知识库和分析模型。所以如果你也要做类似的中台,我建议先从最小可用闭环开始:舆情进来,内容出去,效果回来,哪怕很粗糙。先把这条链路跑通,再慢慢补细节,比一开始就追求大而全要靠谱得多。