简历项目

2025/08/20 技术文档

0.综述

简历项目共包括5部分:

  • 数据治理&性能调优
  • 离线数仓&ETL
  • 实时计算
  • 数据分析&AI
  • 数据平台

1.数据治理&性能调优

  • 技术栈: Scala + Shell + Hadoop + Hive + Spark SQL + Scheduler
  • 负责:
    • PUSH方向的数据治理:主要包括代码治理、任务治理,规范治理,资源治理和时效性治理。
  • 具体工作:
    • 代码治理: 原来PUSH离线任务多为MR任务,sql脚本杂乱无章,无版本概念,且多在无人维护的旧调度平台。将代码统一用spark3重写,提交到代码库进行管理,并迁移到新的调度平台。
      • 制定项目结构,做到代码分层和直接运行sql文件,参考:https://github.com/chenchi-cc/data-warehouse-etl-framework
      • 因成本问题去udw表(一种自研hive表),需要将非核心表迁移到HDFS读写。为提高易用性,将HDFS文件读写(parquet)统一抽象成公共方法,封装schema信息,支持多天查询,兼容通过新增的字段查询旧文件;
    • 任务治理: 针对PUSH任务数据分层不合理,自助化率低的现状,进行了重构的工作。
      • 报表逻辑转移至数仓,去除无用中间层逻辑,重复字段的清洗复用同一套代码;
      • 公共代码抽取,降低代码耦合度,复杂逻辑全部通过udf重写;
      • 充分利用spark3特性,进行参数性能调优,调整并行度,去除逻辑中不等join,全部通过等值join来替代;
      • 进行分而治之的思想,减少shuffle,将能广播的任务,配置广播;
      • 引入remote shuffle service,将shuffle数据写到HDFS,防止单台机器被打满,在大规模数据量和非标准队列条件下,保障任务的稳定性;
      • 针对小文件场景,前置方案设计自适应的分区数(考虑压缩,数据量 / HDFS 块大小),调参动态合并小文件,采用高效parquet格式;后置方案编写脚本,自动化定期合并;
    • 规范治理: 对设计、流程以及质量层面做了相应的规范性约束。
      • 设计规范:涵盖表命名,字段命名,数仓模型建设,代码层级规范等;
      • 流程规范:针对过往排期混乱、需求滞后偏多等问题,规范化了提需流程,需求插入流程,开发流程以及上线流程等;
      • 质量规范:核心任务全部配置DQC监控,前置在数仓产出前会进行量级校验,后置在报表指标层会对核心指标波动报警;任务失败和延迟都配置了对应的值班机制;
    • 资源治理: 物理机,计算队列,HDFS存储均会有不同程度的打满,配置了多层监控以及自动清理脚本,推动值班机制进行可靠性保障。
      • 针对计算队列多而杂的问题,将同地域合并,将队列划分为线上队列(核心+非核心),测试队列和回溯队列;
      • 针对HDFS存储资源不够现状,进行地域置换,跨地域迁移(distcp),尽量保证和计算队列同一地域;
      • 针对全量任务梳理,下线无用的任务,清理存储;
    • 时效性治理: 缩短数仓链路,解决不合理的数据依赖,推动上游签署SLA,切换更快产出的数据源,通过性能调优缩短任务本身的执行时间。
  • 难点:
    • 数据倾斜问题优化: 针对Group By场景以及Join场景(大表join大表,大表join小表)进行优化,提升任务的稳定性和时效性。
      • 第一步:脏数据的过滤,union数据类型的统一,压缩的调整(当对文件使用GZIP压缩等不支持文件分割操作的压缩方式,在日后有作业涉及读取压缩后的文件时,该压缩文件只会被一个任务所读取。如果该压缩文件很大,则处理该文件的Map需要花费的时间会远多于读取普通文件的Map时间)。
      • 第二步:想尽一切办法避免shuffle,消除Exchange。
        • 看小表能否被广播出去:spark.sql.autoBroadcastJoinThreshold默认10MB,调整成2G或更大;或者利用Join Hint强制广播。需要预估小表的大小(磁盘+内存)。限制是不能full outer join,也不能广播外表(例如左关联,广播左边的表)。
        • 小表不能广播:看能否过滤后被广播。常见的嵌套查询、子查询利用filter做谓词下推;多个JOIN的场景,就要用AQE(spark.sql.adaptive.enabled=true)的JOIN策略调整(DemoteBroadcastHashJoin),基于shuffle map的中间值。
        • 小表不能广播:Join Key 远大于 Payload。多个Join Key进行合并,两次hash取值连接,进行join。这样小表就能被广播出去了。
        • 小表不能广播:小表拆分列,一般按日期,多个和大表关联,每一个都转成广播。大表要避免重复扫描:cache住或者利用DPP机制。
        • 分桶join(Bucket join),本身也是一种shuffle free的方式,同时还能通过存储桶修剪(Bucket pruning)功能减少IO。需要注意的是,必须按同一个join key做分桶表,且分桶数量要大于等于shuffle分区数量,否则至少一侧还是会触发shuffle(Spark 3.1.1做了增强,不考虑分区数量,只要两者成倍数就能shuffle free)。
      • 第三步:必须shuffle的情况,分为Task粒度和Executor粒度。Task粒度开启AQE即可,重点说下Executor粒度,思想就是:加盐+两阶段shuffle
        • Group By场景:非去重类指标直接通过随机数加盐,去重类指标需要按照去重id哈希取模来加盐。同时如果只有几个大key可以单独进行处理。
        • Join场景:如果是一个表有很多大key,另一个表比较均匀,将数据倾斜表全部加盐,另外一个表数据增到到原来的N倍(随机数个数,笛卡尔积),然后将二者Join并去盐。同时如果只有几个大key可以单独进行处理。
    • 维度爆炸背景下uv计算实践: 优化大数据计算中多维度用户数统计的方法,通过数据打标的方式避免数据膨胀和冗余传输,同时通过编号化结果维度信息,采用更小的数据结构进行存储,提高性能并减少计算成本。
      • 具体参考:https://mp.weixin.qq.com/s/kHfc2783V5GV3dxWU95odQ
      • PUSH增量数据发送为160亿,到达为60亿,点击为3000万,其中发送数据一天增量约为16T,在做报表聚合时,需要从不同维度去看对应的用户数,由于用户数不同维度不可累加的特性,基本上所有维度的用户数都需要单独计算,维度少可以直接count distinct计算,但是维度多的话这种计算相当痛苦。
      • 常规方式按照 cuid+初始维度 去重后,使用 lateral view explode(array(维度名, ‘all’)) 将数据从一行膨胀成多行,然后直接 distinct 的数据计算方式。新的优化思路可以理解为在数据处理过程中采用一种“数据打标”策略,通过在数据去重的基础上生成用户粒度的中间数据,并在此基础上动态附加所需的结果维度信息。
      • 通过将不同维度(含all)的组合进行维度编码,然后将维度编码聚合到用户cuid粒度上,最后再拆解聚合后的维度编码去计算uv,理论上整个计算过程数据量是呈收敛聚合的,不会膨胀。例如001用户有两条数据,分别是产品线=1 & 付费类型=免费,和产品线=1 & 付费类型=付费,那么第一条数据就会编码为((1,all),(all,免费),(1,免费),(all,all)),我们不妨简化为(1,3,5,9),同理第二条数据为(1,4,6,9),这样聚合到用户粒度就是001用户的编码集为(1,3,4,5,6,9),反过来1,3,4,5,6,9每个维度组合都有用户001。
      • 具体计算可以先利用dense_rank生成编码集,维度集含有dim_A,…,dim_N的具体值以及对应的编号,将该数据集广播,去和原日志表join(key就是多个dim)获取cuid,如果dim过多超过阈值无法广播,可以把所有join key拼接在一起去进行哈希(防止碰撞可考虑二次哈希),然后利用hash key进行关联,cuid聚合编码集可利用array_distinct函数。
      • 执行时间可由原2小时缩短到30分钟内,且任务稳定性增加,随着维度的增加,性能优势逐渐明显。
  • 效果:
    • 核心数据产出时效由T+1日22点提升至T+1日12点;
    • 减少研发临时跑数1人力的工作量,需求完成率达到100%;
    • 减少70%以上的冗余代码,计算资源减少50%以上;
    • 任务的稳定性得到极大提升,核心任务SLA满足率100%。

2.离线数仓&ETL

  • 技术栈: Scala + Java + Shell + Hadoop + Hive + Spark SQL + Doris + ClickHouse + MySQL + SpringBoot(SSM)
  • 负责:
    • PUSH数仓基建: 主要采用的Kimball维度建模,实时和离线采用的Lambda架构,后续离线和实时共用一套ODS层数据。
    • 百家号大B端数仓基建: 主要采用的宽表建模(进一步降低冗余,减少存储,增强易用性),核心字段来自于实时数据(全量同步+增量同步),采用列式存储和高效压缩,降低了存储,事实表与维度表进一步打平。
  • 具体工作:
    • PUSH数仓按照明确数据域,构建业务总线矩阵,明确统计指标的步骤整体设计的,下游使用方主要是是报表层和算法策略数据。
      • 横向分层为ODS、DWD、DWS、ADS以及DIM层;纵向划分数据域,包括流量域、用户域和物料域;
      • 流量域是行为日志,含有发送、到达、点击、首调归因4种行为,为事务型事实表;用户域来源于日活用户日志和cuid-厂商token-系统channelid映射表,物料域来源于业务底表,均作为维度表使用(可理解为全量快照表),维度设计便于统计,采用星型模型;
      • 明确行为日志粒度为cuid(设备id)+appid(设备APP)+taskid(物料id),根据4种业务过程和维度信息构建业务总线矩阵;
      • 明确统计指标,划分原子、派生和衍生指标,其中派生指标为原子+统计周期+业务限定+统计粒度,衍生指标为复合指标逻辑(比率),进行指标的复用;
      • DWS汇总层继承了明细层的粒度,JOIN上了全量维度信息,在其上ADS层服务于报表会进一步上卷(多为Doris和CK表);
    • 百家号数仓数据按照宽表建模,简化了分层和数据域的概念,减少数据分层,底层多为文件,上层只分为作者和文章两大主题宽表(明细粒度),将多个业务域(百家号、动态、好看、feed)统一,解决了数据孤岛问题,宽表分多版本产出,会将宽表同步CK,方便使用方一站式自助分析。
      • 数据孤岛问题:原始数仓各个业务口径、业务覆盖差异,数据流通、业务沟通、数据开发成本很高,通过责权分明和技术统一,做了高效的融合,融合后的宽表含有1000+字段,口径更清晰,同时业务使用上更方便,效率更高;
      • 木桶效应问题:30+上游,到位时间不同会形成木桶效应,为了复杂逻辑进行解耦,引入了分版本输出方案(见难点1);
      • 存储冗余问题:简化多层数仓,降低冗余,总存储下降30%左右;
      • 回溯成本问题:开发通用型工具,迭代需要更新的字段,其他字段取原表数据,merge在一起后写入临时目录,最后再rename回原表目录;
  • 难点:
    • 百家号数仓分版本产出方案: 宽表通过设置多个版本,分阶段产出不同类型的数据,下游使用方通过对应的版本产出标识配置依赖(可以根据sql字段自动提取对应的版本)。
      • V1表是数仓的base表,作为整个数仓的核心数据,包含核心主键以及相关字段,最先产出,非V1版本的其他字段置NULL;
      • 其他版本V2-Vn,彼此间没有先后关系,谁先依赖就绪谁先运行,先把当前版本数据写到HDFS目录,然后通过主键merge回原表(非当前版本的字段取表中的原值);
      • 每个版本会有一个当前版本字段的配置文件,获取表元数据metadata的全量字段,两者diff就是非当前版本的字段,配置文件会接入数据平台服务,方便配置依赖关系;
      • 多个版本同时merge会出现数据异常,一方面限制版本的数量,另一方面会通过 表+分区 粒度进行事务隔离,具体如下:
        • 表+分区粒度在MySQL中存放版本锁标识,每次任务merge前先查看版本锁是否占用,没占用就加版本锁,然后执行merge,执行完、占用时间超时或者异常都会释放;
        • 如果当前版本锁已被占用,则进行等待,按照3分钟的频次轮询;
        • 极端情况,两个事务线程同时查看版本锁状态,MySQL InnoDB默认采用REPEATABLE READ隔离级别,通过MVCC乐观锁使得读写之间不阻塞,在第一次SELECT时生成并复用该ReadView,但是可能造成两个事务同时获取未加版本锁的状态。因此将采用MySQL中的排他锁,在SELECT的时候加上FOR UPDATE;
    • 百家号活动作者应用数据: 每个百家号作者在活动期间仅会引入一次,引入日期固定,需要计算每位作者自引入日期开始,当月、次1月……一直到次12月的留存、发文和分发情况,“月”按照滚动30日窗口计算,不满一整月按实际天数计算。
      • 留存和发文可根据快照表时间判定是否活跃和是否发文,分发需要关联文章行为事实数据,为增量数据,关联多少天分区根据实际而定;
      • 考虑到未来扩展性,当月,次1、次2采用一个新列period_type来表示,分别取值为0-12;
      • 每位作者的时间周期都不相同,实际是按照每位作者做一个窗口大小为30(不满30按照实际天数)的滚动窗口;
      • 经分析每位作者只有在最近30天的数据有变化,其余周期数据固定不变,为避免重复计算,需做成与前一日增量聚合的效果;
      • 因每位作者时间周期不同,在最近30天的时间范围也不同,因此关联是不等join,优化为提前算最近1-30日的数据,采用等值join进行关联;
  • 效果:
    • PUSH数仓: 支持下游工程团队分析和算法团队模型训练,促进了PUSH dau的增长。
    • 百家号数仓: 需求平均交付时长由4.7d下降为2.8d,数仓存储平均节省了2.6PB,易用性得到极大的提升。
    • 整体达到高效率,高性能,高质量,低成本的数仓建设目标。

3.实时计算

  • 技术栈: Scala + Java + Shell + Structured Streaming + Flink + TM(百度自研流式框架)+ Kafka + BigPipe(百度自研消息队列) + Hadoop + Redis + Doris + MySQL + HBase + Google Guava
  • 负责:
    • PUSH实时架构设计和维护: PUSH实时流共有100+条流,涵盖矩阵、中台、折损、地理位置等业务线;业务同离线类似,核心数据还是来自发送、到达、点击以及首调数据;技术栈因历史原因,全部由Structured Streaming编写,后期部分迁移到了TM和Flink;数据流下游包含Doris,HDFS,Redis,Kafka/BigPipe,MySQL等,除了实时报表分析监控外,还涉及线上的服务的调用和算法团队的模型训练。
    • PUSH实时监控工具: 包含任务延迟监控,任务异常监控,实时流量监控和实时报表监控。
  • 具体工作:
    • PUSH实时架构主要采用Structured Streaming,在物理机打包,利用shell脚本进行集群提交,通过Yarn管理调度,迭代运维整个流式任务。
      • Structured Streaming任务没有设置WaterMark,针对写Doris、Redis这种可update的场景,采用event_time聚合,update数据即可;针对HDFS这种只能append的场景,采用系统时间作为分区时间(5min粒度),因下游只有策略团队使用,需要保证时效性,能接受数据的延迟;
      • 在Flink任务中针对乱序数据处理思路一般为:加WaterMark延迟触发计算时间,设置allowedLateness延迟关闭窗口时间,侧输出流来进行兜底;
      • 针对写HDFS的任务,会写入一个_spark_metadata目录,每10个文件聚合成一个compact,随着增大会导致任务越来越慢,做了例行化检测清理;
      • 通过参数调优、控制拉取数据量、调整读取写入计算并行度、调整trigger时间、Kafka/BigPipe扩容、背压机制来应对高流量带来的挑战,其中调整shuffle并行度需要同步修改checkpoint目录下offsets内的最新文件,否则任务重启还会从checkpoint恢复配置,修改不生效;
      • 通过checkpoint来保证容错性,由于Structured Streaming 本身并不支持像 Flink 那样的内置两阶段提交机制,因此原则上只支持At least once,除非下游是幂等性,针对PUSH业务来说,允许数据有一定的精度误差;
    • PUSH监控分为不同层面:
      • 延迟监控:通过开发监控工具嵌入代码(获取数据源后调用),获取当前数据中的水印(max_eventtime),与当前系统时间对比,超过阈值,则会触发报警,消息发送到报警群,为了降低告警频次,会进行抽样;
      • 异常监控:通过例行shell脚本,爬取yarn界面的任务列表,针对失败任务和单Job超时任务重启,重复运行任务远程杀死;
      • 流量监控:通过Python小时级爬取BigPipe的发布流量和订阅流量,监控是否触发发布流控和订阅流控,并将当天0点截止到当前小时的流量聚合,分别与昨日同时段以及一周前同时段对比计算日环比和周同比,触发阈值报警,小时聚合流量数据存储在Redis;
      • 报表监控:针对核心指标配置日环比和周同比的波动阈值,触发会在值班群报警;
  • 难点:
    • 流批关联: 流批关联的场景分为两类,一类是时效性要求低通过天级别离线灌Redis库,实时流通过Redis查询对应数据,比如月活基准灌库来判断是否月活用户,cuid_mapping灌库来通过token、channel反查cuid,一般能命中95%左右;另一类是时效性要求高,比如物料拼接场景,重点说明:
      • 物料拼接一条流是行为数据流(发送、到达、点击行为),批数据是通过python不间断拉取业务MySQL表(源表很大),取需要的字段灌入我们自运维的一个MySQL表(dim_task),然后每次实时流启动会加载近90天的物料信息到内存中,后续每次查询也会不断增量更新;
      • 首次加载到内存比较慢,所有的机器都要查询dim_task近90天数据,数据在内存中以Google Guava存储,相对于HashMap,可以设置过期策略(只保留近90天),容量限制(防止数据过大),自动加载以及线程安全;
      • 拼接物料就是每个微批数据,从内存Guava Cache中按照taskid获取物料信息的过程;
      • Guava Cache数据会增量更新,以2秒为间隔循环拉取,每次会记录前一次拉取的MySQL数据主键id(Volatile保存),在最新的位置进行拉取;
      • 时间不同步问题,Guava Cache加载数据过慢,会通过行为数据流最新的一次事件时间判断是否要等待,比较最新事件时间和上一次拉取MySQL数据封装Guava Cache的时间差,大于阈值13秒则会等待;
    • 双流关联: 双流关联会涉及多条行为数据流之间的关联比较,比如商业化点击的判断和首调数据判断,基本思想都是其中要比较的流写入Redis,另外一条流从Redis取出对应的数据,因为有时间不一致的问题,所以均会有一个调起时间的判断,这里以首调数据重点说明:
      • 计算逻辑是对于同一组cuid+appid计算first_open_timestamp = MIN(运营调起当日最早时间戳, 主动调起当日最早时间戳, PUSH调起当日最早时间戳),如果first_open_timestamp = push调起当日最早时间戳,则当日push调起+1;
      • 运营调起、主动调起和PUSH调起是3条不同的流,除PUSH调起外另外两条流会写入Redis(key为cuid_appid,value为时间戳),PUSH调起流会查询当前自身的时间戳和另外两个时间戳的大小,并同时判断是否已经算入当天首调了(如果已经算过首调也会在Redis保存),只有满足比其他两个时间戳小并且当日还没算入首调,才会把该cuid_appid归为首调数据;
      • 如果运营调起、主动调起数据流延迟,也会记录每条流最新的事件时间,一旦超过阈值30秒,PUSH调起流则会循环等待,同时报警让值班同学介入处理;
  • 效果:
    • 保障了PUSH实时数据的稳定性,为PUSH业务工程侧监控、PUSH策略在线模型特征、特征工程服务等均提供了数据支撑。

4.数据分析&AI

  • 技术栈: Scala + Java + Spark SQL + ClickHouse + SpringBoot + SpringAI + LLM + RAG + Python + Sklearn + Xgboost
  • 负责:
    • 归因分析框架: 通过自定义需要分析的层级、维度和指标等,自动化生成SQL,并生成对应的归因分析数据集。为了进一步简化排查目标,引入deepseek大模型,可以针对数据集快速总结,给出对当前指标产生影响最大的维度以及后续的运营建议。
    • 流失预警模型: 通过盘点作者生命周期不同阶段的召回难度,建立流失预警模型,对前置作者进行干预,防止作者流失并对已流失作者及时召回。
  • 具体工作:
    • 归因分析框架: 采用预聚合的思想,把不同维度按照配置信息进行交叉组合,产出每种交叉维度对当前指标带来的影响贡献度(本期值,上期值,偏移量,波动率,偏移量占比等),从而定位出对当前指标产生影响最大的维度信息。
      • 项目框架参考:https://github.com/chenchi-cc/data-attribution-analysis-framework
      • 由于不同归因分析需求整体类似,只存在数据源、过滤条件、分析维度和分析指标4点不同,因此引入了配置化思想,通过在配置文件中配置关键信息,自动化生成sql语句。这里的过滤条件和分析维度不相同,过滤条件的组合是全组合,共有2^n种组合;过滤条件的组合是树状结构,只有在父节点不为ALL时,子节点才有取值;
      • 读取配置文件以后,分层分析采用一种二进制的思想,利用sql中自带的GROUPING__ID进行改造并结合GROUPING_SETS,所有维度按照优先级排列,用到该维度则设为1,否则为0,这样会生成一个包含0和1的二进制数据,该二进制值则是当前聚合维度的体现;
      • 分层深度支持到3层,不同层级配置的维度可能重复,即dim_A即可以在第一层级,也可以在第二层级,此时dim_A和dim_A是不能交叉的,需要进行去重。同样相同维度组合,虽然维度所属层级不同,但是只需要计算一次;
      • sql生成后,交给SparkSQL引擎进行数据计算,产出hive表,同步到CK做成数据集,支持数据集对接内部工具进行“拖拉拽”分析;
      • 通过SpringAI服务接口调用deepseek大模型,为防止知识局限性和幻觉现象,引入RAG检索增强生成,把业务知识库作为检索源,System Prompt构建上下文,利用大模型读取数据集并返回数据集整体的分析结果(影响指标波动的核心因素),并给出相对应的后续运营策略;
    • 流失预警模型: 按照数据集确定,标签定义,特征选取,模型对比进行分析。
      • 数据集确定:取作者12周每周发文量和每周内容分发量数据,将历史数据按时间切分流失风险判断集(前8周)与流失验证集(后4周),计算模型对验证集作者流失的预测准确率‌;
      • 标签定义:作者条件限定圈选,定义连续4周发文量总和≤阈值(lost_limit,默认为1)视为流失;
      • 特征选取:经过模型多次试跑,最终选择了如下5个特征进入分类模型:slope_last_4(发文量在过去4周的变化斜率),last_drop_ratio(发文量从倒数第二周到最后一周的下降比例),c_slope_last_4(分发量在过去4周的变化斜率),w8(最后一周的发文量),post_entropy(发文量分布的熵值,衡量不确定性);
      • 模型对比:决策树、随机森林和XGBoost梯度提升决策树3种模型对比,经过初步数据探测,作者流失前并未有普遍的发文下降的趋势表现,即发文量下降‌与‌是否流失‌之间的线性相关性不明显,考虑到中等数据量、可解释性高以及不容易过拟合,因此采用决策树模型;
      • 根据作者后四周发文量数据为作者打上是否流失的标签,划分80%训练集和20%测试集;利用测试集测试模型,输出混淆矩阵和关键指标(准确率、召回率、F1-score),最终表现为可在保持80%准确率的同时将召回率提升至50%,最后模型保存,进行例行化;
  • 难点:
    • 归因分析预聚合产生的性能瓶颈: 这里可以采用HLL以及bitmap进行优化。
      • 针对可模糊去重的场景,采取hyperloglog的思想,直接采用approx_count_distinct函数;
      • 针对精确去重场景,采用自定义bitmap UDF函数来替代 count(distinct uid),同时UDF提供在 hive、spark 中bitmap的灵活运算,比如:交集、并集、差集运算,计算后bitmap 也可以直接写入 hive 表中,同时bitmap还对数据进行了压缩 ,减少了存储成本;
    • 归因分析需要解决”归一“和”回补“的问题:
      • 比如按照dim_A、dim_B聚合和按照dim_B、dim_A聚合效果是一样的,只需要计算一遍,那就需要给不同维度定义一个优先级,来确保各自的占位情况,返回数据根据字段优先级归一化,比如dim_A优先级更高,那么dim_A就放在第一层级,dim_B就放在第二层级;
      • 那么如果确实有dim_B处在第一层级分析的情况,还需要把这部分缺失的数据回补,需要计算全排列组合然后排除掉当前情况,将剩余组合UNION回来,2个维度不明显,这在3个维度时最多会有6种交叉,需要补回5种情况。之所以回补是因为dim_A做第二层级和dim_B做第二层级,它们所对应的当前选中的父层级是不同的,因此得到的贡献度也是不同的;
  • 效果:
    • 归因分析框架: 运营单次进行指标异常归因的耗时,由线下分析4h减少到1h,借助大模型能力,能快速定位出影响指标波动的关键因素。
    • 流失预警模型: 流失作者召回率7%,活动半年覆盖约7.3w作者,共计挽回作者6k人。

Search

    Table of Contents