普通视图
Qwen3 系列全家桶,百度百舸一键部署
中国自动驾驶研发解决方案,第一!
千亿级打点PV的成本治理实践
名列前茅!百度文心大模型4.5及X1在中国信通院“方升”大模型基准测试中表现优异
飞桨新一代框架3.0正式发布:加速大模型时代的技术创新与产业应用
即刻体验!文心大模型X1现面向企业用户全面开放!
一篇论文,看见百度广告推荐系统在大模型时代的革新
前沿多模态模型开发与应用实战3:DeepSeek-VL2多模态理解大模型算法解析与功能抢先体验
秒哒首发即爆发!上线首日吸引2万用户,打造3万应用!
图灵数据洞察平台-TDF(Turing Data Finder)
两连发!文心大模型4.5及X1,上线千帆!
百度百舸万卡集群的训练稳定性系统设计和实践
01 AI 训练稳定性的演进历程
2012 年 ImageNet 竞赛中 AlexNet 的横空出世,开启了现代 AI 发展的新纪元。彼时我们不会想到,十年后支撑 AI 训练的 GPU 集群会从研究室里的几台服务器,发展成需要专门供电系统的万卡级计算矩阵。在这个算力爆发式增长的过程中,训练系统的稳定性管理正经历着从「简单运维」到「精密工程」的深刻变革。
1.1 标早期的小模型时代:手动运维的黄金年代
2022 年之前的 AI 训练,更像是手工作坊式的精雕细琢。大多数训练任务只需十几块 GPU,利用 PyTorch 或 TensorFlow 的数据并行功能就能轻松应对。记得那时算法工程师们有个共识:如果训练遇到问题,重启往往比排查更高效。
当时我们构建的监控系统就像汽车仪表盘,只能显示最基本的任务状态。当训练意外中断时,工程师们会像侦探一样翻查日志 —— 如果发现是 GPU 报错,就联系运维同事。运维人员则带着「NVIDIA三件套」(nvidia-smi、dcgm、nsys)到机房巡检,像老中医把脉般通过温度、功耗等指标判断硬件状态。这种工作模式虽简单,但应对数十卡规模的集群还算游刃有余。
1.2 大模型风暴:从量变到质变的冲击
ChatGPT 的登场如同打开潘多拉魔盒,将 AI 训练带入新的纪元。当我们开始部署千卡/万卡集群时,才发现原有的运维体系就像用小渔网捕鲸鱼 —— 完全无法匹配新需求。
让我们通过百度百舸经历过的一个真实案例来深入理解这个问题:
2024 年初,百度百舸帮助一家 AIGC 创业公司迅速将其训练规模从百卡扩展到千卡级别。然而在训练数天后的某个周末凌晨,训练进程意外发生了 hang 死。由于当时缺乏有效的故障感知和容错机制,直到第二天算法工程师发现任务超时退出时,已经耽误了数小时宝贵的训练时间。更糟糕的是,任务日志中除了简单的 timeout 报错外毫无线索,平台监控也显示所有训练节点状态正常。
着急恢复训练的算法工程师没有立即上报问题,而是选择直接重新提交任务。但不幸的是,新任务运行数小时后再次出现相同的超时退出。这时他们才不得不寻求技术支持,但值班工程师面对这种任务 hang 死的问题也缺乏诊断经验,只能通过二分法慢慢定位。最终发现是某个节点的静默故障(SDC)导致了训练进程假死。等问题得到解决时,距离首次故障已经过去将近 30 小时,这意味着损失了价值巨大的千卡算力资源。
02 百度百舸集群训练稳定性全景图
站在现在的时间点回望,AI 训练稳定性已从辅助功能演变为核心基础设施。就像现代建筑中的抗震结构,它虽不直接参与空间构成,却是万丈高楼得以屹立的关键。当行业向着数万卡集群迈进时,这套隐形护甲的质量,将直接决定 AI 进化的速度与边界。
在 2024 年百度百舸对训练过程的生命周期进行了更细致的拆分,提出了「无效训练时间」这一关键指标,并致力于将其最小化。具体来说:
任务无效训练时间 = 故障中断次数 × 任务故障恢复时长 + 任务常态写 Ckpt 总时长
其中,任务故障恢复时长 = 故障感知召回耗时(自动/人工定位)+ 任务调度耗时 + 任务初始化耗时 + 任务重算时长。
通过这个公式可以看出,要降低无效训练时间,需要「围绕基础设施稳定性」、「任务容错」两个维度来系统展开,重点解决三个方面的问题:
-
提高基础设施的交付质量。
-
提高任务故障容错的召回率、准确率和时效性。
-
优化 checkpoint 机制,减少保存时间和恢复时的重算时间。
经过容错架构的整体变革,百度百舸形成了从 「任务负载 — 框架 — 通信 — 基础架构」全链路的自动异常感知、诊断、恢复能力,可覆盖 90%+ 的训练异常场景,时效性最快可以实现秒级异常感知、分钟级定位,以及平均 3 分钟的故障自愈能力。
03 基础设施交付质量保障
基础设施的交付质量保障是稳定性的基础。
CPU 时代,机器的交付前可能仅会跑一些常规的 CPU 计算、网络的压力测试,并不会从业务视角去评估基础架构,机器交付后硬件异常的故障频率相对较少。有硬件故障时,通常走工单系统人工换机用户相对是可接受的。
而 GPU 时代,AI Infra 的交付则需要考虑 CPU、GPU、RDMA 网络、存储,甚至机房的功率、温度等各方面因素,遗漏任何一个环节都会成为后续稳定性的隐患。在交付给客户后,机器也可能会由于长时间的高负载运行频繁出现硬件故障,而 GPU 机器的高昂成本,使客户对节点故障感知、换机的时效性提出了非常高的要求。
因此百度百舸对 GPU 机器交付前及交付后的稳定性质量进行了系统性管理:
-
交付前,百度百舸会对机器进行 200 多项指标检测,然后进行 48 小时烤机,以及 NCCL-Test 的机内、机间的大环、同号卡通信性能基准测试,端到端的大模型训练、推理性能基准测试。
-
交付后,需要能够实时的感知节点故障及定期巡检,并具备分级处理的自愈能力,例如 Error 级别的故障实现自动排水、重启,Fault 级别故障实现自动换机。
04 任务容错的准召率保障
任务层面稳定性最核心的就是做好容错,能够让业务在无论遇到何种故障时都能快速恢复。
那么,首要的工作就是我们能够准确的识别出异常,然后对故障进行诊断定位,最后能够自动化的从异常中恢复。
因此,任务容错需要能够从端侧(即每个训练 worker)探测到进程与环境的各类异常,同时有个中心服务(Master)从任务全局的视角去诊断、定位异常,最终做出相应的决策来使任务能够快速从异常中恢复。
任务容错最重要的就是提升故障的召回率与准确率,即如何能够尽可能的准确识别、定位所有故障。我们将故障分类两类:显式故障和隐式故障。
-
显式的故障通常比较容易召回,我们将实践积累的各种进程异常状态及各类报错pattern形成专家知识库,再结合硬件感知服务(HAS Agent)的硬件全链路 10 秒级监控能力,可以实现显式故障的召回率达到 95%+。
-
隐式的异常则往往很难轻易的识别,例如训练进程 hang、慢节点就是典型的隐式故障,需要丰富的经验积累才能准确的识别出异常。
下面我们就以最典型的隐式故障场景 —— 训练进程 hang 死为例,来看下如何能够做好 hang 自动感知、诊断。
4.1 训练****hang 的自动感知
训练任务发⽣ hang 之后,绝⼤多数情况都会以 timeout 的⽅式报错并退出进程,最常⻅的就是在通信过程中如果发⽣ hang,NCCL 的 watchdog 会中断通信,并有报如下 timeout 报错,然后再由 pytorch 的 torchrun 进程感知并中断训练过程。
[E ProcessGroupNCCL.cpp:828] [Rank 1] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=15173, OpType=ALLREDUCE, Timeout(ms)=1800000) ran for 1802710 milliseconds before timing out.
[E ProcessGroupNCCL.cpp:828] [Rank 0] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=15173, OpType=ALLREDUCE, Timeout(ms)=1800000) ran for 1802713 milliseconds before timing out.
Pytorch 默认为 10 分钟 NCCL 通信超时,而 Megatron-LM 为 30 分钟。在万卡规模训练场景中,意味着一万张卡要至少浪费 30 分钟才能被发现。这个时效性是不可接受的。而且当 30 分钟超时后程序会立马退出,很难有机会进行下一步定位,需要一些时效性更高的感知机制,并且在程序退出前获取一些有效信息供后续诊断分析。
很多公司、实验室在面对 hang 的问题时,会在采用框架层插桩的方式来 trace 训练进程,这种方式通常是比较直接且准确的,但是有比较强的侵入性,而且可能还会有一些性能开销。对于云厂商来说,需要寻找对用户更透明、更无损的方式来感知、定位 hang 异常。
如何感知训练 hang,以百度百舸的产品设计思路为例,我们可以从以下几个方向去思考:
-
训练进程 hang 的最直观表现是什么?
人工判断一个任务是否 hang 了,最直接的方式就是看是否所有 worker 的任务日志一段时间内都不输出日志了,所以 hang 自动感知的第一种方法就是采集所有 worker 的日志,并判断所有 worker 日志中最后一行日志是否为 x 分钟前的(x 小于 Pytorch 的通信超时时间,例如 8 分钟),如果是则基本可以判定为 hang。
-
任务 hang 时进程有什么样的表现?
任务 hang 时,可能进程的调用栈都不在发生变化,进程的调用栈可以通过 py-spy/pystack 等工具进行探测,所以我们可以用此类工具对所有训练任务进行一个定时采样,当采集 n 个样本所有进程栈都没有变化时,可以判定一次 hang,这种方式通常可以将 hang 感知缩小至 3~5 分钟。
-
任务 hang 时监控指标有哪些变化?
训练进程中的 CUDA 算子计算、集合通信操作通常都是在毫秒,甚至微秒、纳秒内完成的,当任务在正常迭代过程中发生了 hang,我们常遇到的情况是所有 rank 的 RDMA 流量会降到 0,而 GPU 的利用率为 100%、SM 利用率则在很低的水位。如果持续几分钟都是这种状态时,意味着训练进程已经计算完成,在等着集合通信完成,这种情况下基本可以判定为 hang。
-
是否能在通信库中更快的感知通信 hang?
通常单次集合通信操作都是在 ms 级的,如果一次操作在 30 秒钟都没有完成,那就可以判定为通信 hang 死了。百度自研的 BCCL 集合通信库层可以对每一次集合通信操作都进行打点,来实现通信 hang 感知。
上述几种方法,我们可以分别实现一种探针,来抓取相应的特征到中心端 master 组件进行下一步诊断和容错决策。
百度集合通信库 BCCL是百度智能云推出的一款面向大模型训练场景优化的集合通信库。
BCCL 基于开源的 NCCL 进行了功能扩展和能力增强,针对大模型训练场景在可观测性、故障诊断、稳定性等方面进行优化,进一步提升集合通信库的可运维能力。相比 NCCL,BCCL 的关键特性如下:
* 可观测性:新增集合通信带宽实时统计能力;
* 故障诊断:新增集合通信 hang 时的故障诊断能力;
* 稳定性:增强网络稳定性和故障容错能力;
* 性能优化:提升大模型训练主流 GPU 芯片的集合通信性能。
4.2 训练 hang 的自动诊断
有了以上感知手段,我们需要进一步的诊断、定位,来确定是否真的发生了 hang,以及 hang 的具体位置。具体的来讲,master 收集到各类 agent 的数据后,会做一些综合分析:
-
是否真的发生了 hang?
感知阶段各种探针只能探测到 hang 的一种特征,并没有办法 100% 的确定是否真的 hang 住了,事实上不侵入用户进程是很难做到 100% 确定 hang 的。因此,为了提高 hang 的判定准确率,我们需要将各种特种综合起来判断,探针上报到 master 后,由一个 hang 诊断模块,按照一个时间窗口(例如 5 分钟),进行综合判断。如果在时间窗口内日志、监控、进程调用栈、通信库中有 2 条以上都处于不处于活跃状态时,我们判断任务真正发生了 hang。
-
hang 的具体发生的位置?
确定任务 hang 了之后,我们需要找到 hang 所在的节点来对它进行隔离。因此诊断模块需要在探针上报的数据中进一步找寻特征,来确定 hang 发生的位置:
-
BCCL Tracehang 诊断:在感知阶段,BCCL 可以在通信库层面对所有 rank 的通信进行打点。如果有节点一直未完成通信则是发生了 hang。但是此节点可能并非真正发生 hang 的源头,有可能是在等待其他节点完成通信。诊断模块可以根据 BCCL 打印的通信组信息,进行交叉判断,如果某个节点在多个通信组中都未完成通信,那这个节点就是 hang 的源头。
-
RDMA/GPU 指标诊断:上文中我们提到,通信阶段发生 hang 之后,所有 rank 的 RDMA 流量都会降到 0,而同时绝大部分 rank 的 GPU 利用率持续为 100%,只有某一两个 rank 的 GPU 利用率为 0,那这个 rank 很有可能是 hang 的源头。
-
进程调用栈诊断:进程调用栈也可以作为一个 hang 源头诊断的重要参考。当发生 hang 之后,绝大部分的 rank 都要么处于 barrier 等待状态,要么处于通信等待阶段。只有个别的 rank 卡在其他函数上,那么通过对比分析,可以将调用栈与其他 rank 不同的节点初步判定为 hang 的源头。
-
综合诊断:上面 3 种特征为我们提供了 hang 的诊断依据,将 3 者关联起来分析后,我们基本上可以比较准确的确定一个具体的 hang 的源头,再结合硬件故障感知的相关信息可以进一步明确根因。
4.3 基于 eBPF 的隐式故障感知与诊断
在复杂的大规模分布式训练场景中,传统用户态监控往往难以捕获系统内核层面的异常事件。
百度百舸基于 eBPF(Extended Berkeley Packet Filter)技术的隐式故障感知体系,能够在不侵入用户代码的前提下,对训练进程的系统调用、网络通信、CPU 调度等内核态行为以及训练框架关键函数运行时间建立立体观测能力。
eBPF 探针部署原理通过在内核关键路径注入轻量级探针,实现低开销的系统级行为捕获。针对训练场景特点,主要聚焦 4 类事件跟踪:
-
训练关键函数跟踪:微秒级跟踪训练过程中,前向计算、反向计算、集合通信操作等关键函数执行耗时,记录函数间调用关系。
-
进程调度阻塞跟踪:挂钩 sched_switch 事件,检测进程在 TASK_UNINTERRUPTIBLE 状态持续时间,当单次持续超过阈值(如 5 秒)时捕获调用栈。
-
CUDA 运行时 API 监控:通过 uprobe 在 libcuda.so 等关键库注入探针,记录 CUDA API 调用耗时分布。
-
RDMA Verbs 级通信监控:在 ibv_post_send/ibv_poll_cq 等核心通信接口设置观测点,统计通信时延分布。
结合上面 4 类事件,完成以下 2 类数据分析:
-
单体异常探测基线与实时数据对比。
-
群体一致性检测。采用卡间对比算法,当某一 rank 的以下指标偏离集群中位数超过阈值时判定异常,包括系统调用频率、进程就绪队列等待时长、NVLink/RDMA 带宽利用率等。
基于以上所述方法,百度百舸针对以下 2 类典型的隐式故障进行诊断:
-
训练 hang 根因定位。通过关联 eBPF 捕获的多维度数据进行如下操作:
-
当检测到某 rank 的 GPU Kernel 执行出现分钟级空跑(SM 利用率 > 70% 但无有效计算输出)。
-
同时伴随该节点 RDMA QP 状态停滞(ibv_poll_cq 无新完成事件)。
-
内核调度器显示进程处于 D 状态超过阈值。
-
性能抖动溯源。基于 eBPF 火焰图、时序图等进行分析:
-
抓取发生性能下降时段的 CPU on-cpu/off-cpu 堆栈。
-
对比正常时段数据,识别出异常的锁竞争(futex 调用占比上升)。
-
结合 NUMA 内存访问统计,定位跨 NUMA 内存访问导致的 TLB 颠簸问题。
此类技术已在百度百舸的万卡规模训练集群中验证,相比单纯依赖应用层监控的方案,将隐式故障的平均检测时间从分钟级缩短至秒级,诊断准确率提升 40% 以上。
通过与既有硬件故障感知服务、BCCL 通信库监测体系联动,百度百舸形成了覆盖从硬件到系统内核再到应用层的立体化诊断能力。
05 任务故障恢复的时效性保障
故障恢复的时效性也是容错能力的一个重要指标,反映的是任务从故障发生到再次重新进入训练迭代的时间,恢复效率越高则算力浪费越少。影响到任务恢复效率有 2 个重要因素,一是任务平均中断时间,二是训练重算时间。
5.1 多级重启策略减少故障中断时间
任务发生异常后,上文中我们提到需要经过故障自动感知、诊断和自愈等 3 个环节,那么减少中断时间的核心思想,就是尽可能的缩短这 3 个环节的时间,通过多维度的感知、诊断手段可以将故障发现、定位的时效性降低至分钟级甚至秒级。自愈则需要能够根据不同的诊断结果进行分级恢复和故障屏蔽的能力:
-
单点显式故障:重调度异常节点(replace),对节点进行集群级别屏蔽。
-
单点隐式故障:重调度异常节点,对节点进行任务级别屏蔽。
-
非单点故障:原地重启尝试恢复(restart),无法恢复时重新调度所有节点(resubmit)。
通过多级重启策略,尽可能避免单点故障引发全部节点的重新调度。在万卡级别的训练场景中,百度百舸将大部分训练异常场景恢复时间从过去的 30min 缩短至现在的 30s 内,成功率到 95%+。
5.2 触发式 checkpoint 减少训练重算时间
除了上述的多级任务重启策略外,另一个提高任务故障恢复效率的重要手段就是减少训练重算时间。在探讨具体技术方案之前,我们先来看看目前主流的 checkpoint 保存策略。
传统的 checkpoint 保存通常采用固定间隔策略,比如每隔 N 个 step 或每隔 T 小时保存一次,这种方式实现简单但缺乏灵活性,可能会产生大量冗余存储,同时在故障发生时可能会损失较多训练进度。
而触发式 checkpoint 则是一种更智能的方案,它根据特定条件或异常事件(如故障、显存不足、显式指令等)动态触发模型状态保存。其核心目标是通过灵活的控制保存时机,减少不必要的存储开销和训练中断时间,从而降低因频繁或冗余保存导致的重算时间浪费。
随着大模型训练规模的扩大,还有一种更激进的「零重复 checkpoint」技术,即在每个训练 step 都保存一次 checkpoint。这种方案的优势在于可以将重算时间降到最低,确保故障发生时能够从最近的 step 恢复,几乎不会损失训练进度。但其显著的缺点是存储开销巨大,即使采用增量式存储,仍然需要相当大的存储空间和 I/O 带宽。此外,频繁的 checkpoint 操作也可能影响训练性能。
相比之下,触发式 checkpoint 走的是一条平衡之路。我们来看下它实现的几个核心要点:
-
集成容错:训练进程集成容错的故障感知与定位机制,在进程退出前自动触发保存。这种主动感知机制能够在故障发生的第一时间保存训练状态,最大限度减少进度损失。
-
高速转储:异步 checkpoint 保存机制会将 checkpoint 暂存到共享内存中,再由外部程序转储至磁盘。当某个节点异常时,容错组件会拉起新节点,并在新节点训练进程启动前,利用 RDMA 技术实现 checkpoint 快速从故障节点转储至新节点,这大大减少了从远程存储拉取 checkpoint 的时间。
-
冗余备份:触发式 checkpoint 也并非完美无缺,例如在节点发生内核 crash 等严重故障时,可能无法触发自动保存。因此,需要通过定期的冗余备份机制进行兜底,确保 checkpoint 不会完全丢失。
实践表明,当触发式 checkpoint 与异步、增量式的 checkpoint 机制结合使用时,可以在保证数据安全性的同时,显著提高 checkpoint 保存效率,减少训练重算时间。
相比零重复 checkpoint 的重型方案,触发式 checkpoint 提供了一个更实用的折中方案,在合理的存储开销下实现较好的容错效果。当然,具体选择哪种方案,还需要根据实际的训练规模、硬件条件和可用资源来权衡。
随着分布式训练规模的持续增长,相信未来会出现更多创新的 checkpoint 方案,比如基于预测的主动保存策略、多级存储架构的智能调度等,这些都将为提高大规模训练的可靠性提供新的可能。
06 业务发展对稳定性的要求
AI 训练的稳定性管理已经演变为智能时代的精密工程。从最初靠人工重启解决问题的摸索阶段,到如今能自动感知异常、快速恢复的智能系统,每一次进步都映照着算力规模的跨越式发展。
让人不禁思考,在未来十万卡集群的算力洪流中,或许会出现更精妙的动态平衡方案:既能像鹰隼般敏锐捕捉故障征兆,又能如雁群迁移般智能调度资源,在秒级恢复与 PB 级存储成本之间找到新的平衡支点。
目前百度百舸支持厂内千卡和万卡集群有效训练时长已经可达 99.5%,为客户大模型的预训练保驾护航,比如国内第一个数学大模型——九章算术,国内第一个类 Sora 大模型 —— Vidu 等。
----------END----------
推荐阅读
LLM增强语义嵌入的模型算法综述
导读
语义嵌入是自然语言处理、信息检索、推荐系统等领域的核心技术,对于精准捕捉文本深层次语义信息至关重要。近年来,大语言模型(LLM)的兴起为语义嵌入技术开拓了新的方向。本文介绍了LLM在提升语义嵌入效果的最新模型与算法,聚焦在如何利用LLM生成合成数据以及如何作为模型骨干来优化语义嵌入。文章概述了当前研究的主要方向和先进成果,展示了LLM在学习语义嵌入方面的独特优势,并展望了其在搜索、推荐等下游任务的广阔应用前景。
01 背景介绍
1.1 语义嵌入
文本语义嵌入,作为将文本映射到语义空间的关键技术,通过将原本高维且稀疏的向量转化为低维稠密向量,实现了对单词、句子乃至整个文档深层次语义信息的精确捕捉。这一技术在信息检索、问答系统、文本相似度计算及推荐系统等自然语言处理(NLP)的诸多任务中展现出广泛的应用价值。
早期语义嵌入方法,诸如 Word2vec 和 GloVe,主要基于统计特性构建,然而,这些方法受限于其静态性,难以充分捕捉自然语言复杂多变的上下文信息。随后,BERT 及其衍生的一系列上下文敏感模型(如 RoBERTa、DistilBERT、ALBERT 等)应运而生,通过独特的模型增强与优化策略,不仅保留了双向编码的核心优势,还显著提升了语义嵌入对上下文信息的感知能力。此外,Sentence-BERT 模型的提出,通过引入连体网络(Siamese Network)和三重网络(Triplet Network)结构,实现了高效的句子级嵌入生成。近年来,随着对比学习框架的兴起,如 SimCSE 等方法利用标准 dropout 作为噪声源,无需额外监督数据即可生成高质量的句子向量,进一步推动了语义嵌入技术的革新与发展。
当前研究热点聚焦于通用文本嵌入技术的优化,通过引入多阶段训练范式和复杂的数据混合策略,如 E5[1]、BGE[2]、GTE[3] 等模型,在数据规模、质量及多样性方面取得了显著进展。随着大语言模型(LLM)的蓬勃发展,利用 LLM 生成语义嵌入成为新的研究方向。研究者们通过合成高质量训练数据以提升嵌入性能,或直接以 LLM 作为模型主干生成嵌入,显著增强了语义嵌入的鲁棒性和泛化能力,为 NLP 领域的未来发展探索出了新的道路。
1.2 大语言模型(LLM)
LLM 作为一种规模宏大的预训练语言模型,通常具有数亿乃至数十亿之多的参数,经由海量数据的训练,已具备理解和生成更为繁复且丰富文本内容的能力。随着模型规模的不断扩张与数据量的显著增加,LLM 已能极为娴熟地应对众多下游自然语言处理任务。凭借其强大的表达能力和出色的泛化性能,LLM 能够应对各类自然语言处理任务,并在诸多场景下展现出超越传统机器学习方法的卓越表现。“预训练+提示”作为 LLM 的第四范式,开创了一种引导生成输出以匹配多样化下游任务需求的新颖路径。在此范式下,模型的适应不再单纯依赖微调,而是通过引入“提示”这一文本或模板元素来引导生成过程,旨在促使模型在接收任务时能够有效唤醒预训练阶段所学到的知识,并据此精准地生成符合任务特定要求的输出。诸如 LLaMA-2[4]、LLaMA-3[5] 及 Mistral[6] 等开源 LLM 模型已取得了显著成效,它们不仅推动了 LLM 在语义嵌入领域的广泛应用,更掀起了利用 LLM 进行语义嵌入研究的热潮。
LLM 语义嵌入与传统语义嵌入之间的对比:
综上所述,使用 LLM 进行语义嵌入与传统语义嵌入(如使用BERT)在模型结构与训练方式、嵌入质量、应用场景等方面都存在显著差异。这些差异使得 LLM 语义嵌入在复杂的 NLP 任务中表现出更强的性能和适应性。下文将介绍一些当前主流的 LLM 语义嵌入方法。
02 算法解读
随着 LLM 的广泛应用,出现了一些利用 LLM 来生成语义嵌入的尝试。Jiang等人[7] 首次提出了基于提示(prompt)的句子嵌入方法,结合对比学习框架,通过设计如 “[X] means [MASK]” (其中,[X] 表示一个 placeholder,对应一个句子,[MASK] 则表示待预测的 token)的模板捕捉句子表征,并借助模板去噪避免语义偏向。随后,Zeng等人[8] 提出了 Prompt-derived Virtual semantic Prototypes(ConPVP)的对比学习方法,利用提示构建虚拟语义原型及否定原型,通过原型对比损失优化句子嵌入。Cheng等人[9] 则进一步提出了基于AI反馈(CLAIF)的句子嵌入对比学习方法,利用来自 LLM 的AI反馈来构建具有细粒度样本相似性分数的样本对,提升句子嵌入的监督对比学习的效果。
当前,利用 LLM 提升语义嵌入的研究热点聚焦于合成数据和模型骨干两大方向,如图 1 所示。下面将具体介绍各方向的一些代表模型。
△图1: LLM 提升语义嵌入的算法模型梳理
2.1 合成数据
利用 LLM 进行数据合成正日益受到业界的广泛关注,该方法能够显著提升模型在处理多任务及多语言环境下的能力多样性,从而训练出更为强健的语义嵌入模型,可广泛应用于各类下游任务中。具体而言,LLM 在生成高质量、多语言、多任务合成数据方面展现出巨大潜力。例如,通过将 LLM 作为数据注释工具,可以高效地标注伪监督数据以强化模型训练效果;利用如 GPT-4 等先进的 LLM,可以生成覆盖广泛语言范围及多种语义嵌入任务的合成数据,极大地丰富了训练数据的多样性;此外,合成数据还被用于从大模型中提取知识并融入检索系统中。接下来,本文将重点介绍在 MTEB 基准测试中表现突出的几个典型语义嵌入模型,包括 E5-mistral-7b-instruct[10] 混合真实与 LLM 合成数据进行微调、SFR-Embedding-Mistral[11] 采用改进的难负样本进行多任务微调的方法,以及 Gecko[12] 采用两步蒸馏法将LLM知识融入检索器的技术。
2.1.1 E5-mistral-7b-instruct
【主要贡献】
微软的研究团队提出的语义嵌入训练方法,无需复杂的流程设计或人工构建的数据集,只需要利用 LLM 来合成多样化的文本数据,就可以为93种语言的数十万文本嵌入任务生成高质量的语义嵌入,整个训练过程还不到1000步。
实验结果证明,当仅对合成数据进行微调时,Mistral-7B 在 BEIR 和 MTEB 基准上获得了非常有竞争力的性能;当同时加入合成和标注数据进行微调时,即可实现 SOTA 性能。
【算法概述】
- 数据合成:
为了生成不同的合成数据,提出了一种简单的分类法,将嵌入任务分为几个组,然后对每个组应用不同的提示模板。如图 2 所示,对于每个组,该算法设计了一个两步提示模板,首先提示 LLM 生成一系列的任务,然后为每个任务生成(用户查询、正样本、难负样本)三元组。“{...}”表示一个占位符,将在其中填入从预先定义的一组值中随机选取的值。
为了覆盖不同的应用场景,该算法为每个任务类型设计了多个提示模板,并将不同模板生成的数据进行组合。为了进一步提高合成数据的多样性,在每个提示模板中加入了几个占位符,在运行时随机采样,例如 {query_length} 是从集合 {少于5个单词,5-10个单词,至少10个单词} 中采样的。
△图2: E5-mistral-7b-instruct 数据合成两步提示模板
- 训练阶段:
给定一个预训练的 LLM,在查询和文档的末尾添加一个 [EOS] 标记。最后一层 [EOS] 向量被用作语义嵌入。为了帮助模型适应不同的任务,在生成新的查询时,可以使用统一的指令模板,给定相关的查询-文档对,先使用原始查询 来生成一个新的指令,其中 {task_definition} 是嵌入任务的一句话描述的占位符:
最后,选择预训练的开源 LLM Mistral-7B 模型,在对一组混合的合成和标记数据(包含 13 个公开数据集)进行采样后进行微调。
2.1.2 SFR-Embedding-Mistral
【主要贡献】
用改进的难负样本对 E5-mistral-7b-instruct 进行多任务微调,将性能提高了0.93%。主要结论有:
-
语义嵌入与聚类任务集成后检索性能显著提高,并通过多任务知识转移进一步增强检索性能。此外,通过采用多任务训练并使模型适应特定任务,可以增强泛化能力。
-
采用任务同构批处理,即同个batch里的所有样本来自于同个任务,这样可以保证对比学习的 in-batch negatives 更具挑战性。
-
之前的难负样本挖掘方法都是先通过检索将排序靠前的文档作为难负样本,这样有可能混入部分错误的负样本,影响模型训练结果。该方法发现使用排序在30-100之间的文档作为难负样本能提升模型性能,而使用排序在0-100之间的文档则容易引入错误的负样本,使用排序在50-100之间的文档则缺乏训练难度。
2.1.3 Gecko
【主要贡献】
Gecko 提出的主要思想:从 LLM 中提取知识到检索器中。使用两步蒸馏过程:首先使用 LLM 生成不同的任务-查询对数据。接下来通过为每个查询检索一组候选段落,并使用相同的 LLM 重新标记正样本和难负样本段落,进一步改进数据质量。
△图3: Gecko 整体流程概述
Gecko 选用 gtr-t5-xl (1.2B, encoder from T5-3B model) 模型骨架。通过将 LLM 生成的和经 LLM 排序的数据,与人工标注的数据相结合,Gecko 模型在 MTEB 基准上实现了较好性能。
【算法概述】
该方法利用知识蒸馏的思想,创建了一个两步骤的 LLM 驱动的嵌入模型。
- 多元查询生成
如图 4 所示,首先向 LLM 中输入一段网络文章节选,让其生成任务描述和任务的相关查询:
其中 是从web语料库中随机抽取的一个段落,而 是一个固定的提示符。对于每个示例来说,提示模板是相同的,并且由几个示例和说明组成。LLM 生成一个任务描述 t(描述了检索的类型,如问答或事实检查)。通过对这些任务描述进行抽样,可以指导 LLM 生成与任务一致的查询 𝑞。
- 正负样本挖掘
首先,给定生成的查询 𝑞,使用一个嵌入模型来检索最相关的段落。然后,使用 LLM 根据检索到的段落与查询的相关性对它们进行排序。排序方法采用的是查询似然(query likelihood)和相关性分类(relevance classification)这两个少样本提示的 LLM 排序函数。最后将两种不同提示结果的排名与标准的倒数秩融合(RRF)方法集成在一起,获得排名函数𝑅(𝑞,𝑝),并根据排名找到更多相关的正样本以及生成查询的难负样本。
△图4 :两步检索流程
2.2 模型骨干
另一类主流方法是将 LLM 作为语义嵌入的主干网络,原因在于它们无需遵循现有语义嵌入模型中普遍采用的对比预训练步骤,使得 LLM 在训练过程中能够更加灵活地处理文本数据。得益于全面的自回归预训练,LLM 能够充分捕捉到文本中的上下文信息和语义关系,具有出色的文本表征能力,并且仅需最少的微调即可转化为高效的通用文本嵌入模型。
同样,后续内容将着重介绍在 MTEB 基准测试中表现优异的几个语义嵌入模型。其中,NV-Embed-v2[13] 模型通过关注潜在向量并采用两阶段对比指令调优方法来提升性能;BGE-EN-ICL[14] 模型则利用LLM中的 in-context learning 能力来优化语义嵌入的生成;Echo-mistral[15] 模型采用双向注意机制,通过重复输入并提取第二次出现的嵌入来增强效果;LLM2Vec[16] 模型同样采用了双向注意力机制,还结合掩码下一个token预测以及无监督对比学习来提升嵌入效果;GRIT[17] 模型通过训练LLM和指令,实现了生成和嵌入任务的统一处理;GTE-Qwen1.5-7B-instruct[18] 模型则利用双向注意力机制、查询侧指令调优,并融合了弱监督与监督数据进行训练;最后,stella_en_1.5B_v5[19] 模型简化了提示的使用,为大多数通用任务提供了序列到段落(s2p)和序列到序列(s2s)两种便捷的提示方式。
2.2.1 NV-Embed-v2
【主要贡献】
一个通用文本嵌入模型,NV-Embed-v2 提出了几个新的设计,包括让 LLM 关注潜在向量以获得更好的池化嵌入输出,并展示了一种两阶段指令调优方法以提高检索和非检索任务的准确性。此外,NV-Embed-v2 采用了一种新的难负样本挖掘方法,该方法考虑了正样本的相关分数,以更好地去除假负样本。
基于预训练的 Mistral-7B 模型进行训练,该模型在大规模文本嵌入基准(MTEB基准)(截至2024年12月3日)中排名第一,在56个文本嵌入任务中得分为72.31。
【算法概述】
- 模型架构
提出了一种潜在注意层来获得一系列 token 的池嵌入。如图 5 所示,将解码器最后一个隐藏层表示为查询 Q,然后结合潜在数组 K = V(可训练的“字典”),用于获得更好的表示。该交叉注意的输出是:
最后通过一个正则 MLP 层和平均池化来获得整个序列的嵌入。
为了进一步增强表征学习,在 decoder-only 的 LLM 对比训练过程中去掉了因果注意掩码,从而缓解了单向注意力对模型表示能力的限制。
△图5: NV-Embed-v2 模型架构
- 模型训练
引入了一种两阶段的对比指令调优方法。第一阶段利用批量负样本和精选的难负样本,在多种检索数据集上利用指令进行对比训练。在第二阶段,该算法在检索和非检索数据集的组合上执行对比指令调优。由于同一批次内的负样本可能会误导非检索任务,该算法在第二阶段不采用 in-batch negatives 方案。这种设计不仅提高了分类、聚类和语义文本相似度任务的准确性,而且显著提高了检索性能。
2.2.2 BGE-EN-ICL
【主要贡献】
利用 LLM 中的in-context learning(ICL)能力来增强语义嵌入生成的过程。BGE-EN-ICL 模型使用少量示例来生成高质量的语义嵌入,直接将与任务相关的示例集成到查询端,从而在多种任务上取得了显著的改进。此外,还研究了如何有效地将 LLM 用作嵌入模型,包括各种注意力机制、池化方法等。
该模型采用 Mistral-7B 作为模型骨架,研究结果表明,保留原始框架往往能获得最佳结果。在 MTEB 基准测试上的实验结果目前排名第二。
【算法概述】
- 上下文学习增强嵌入模型
△图6: 基于ICL的模型体系结构
通过少样本对比训练实现 ICL 增强嵌入模型。考虑嵌入任务中的一个查询-段落对,首先构建一个示例模板如下:
“task definition”表示特定嵌入任务的描述(图 6)。对于一个相关的查询-段落对,修改后的查询构建如下:
- 表征方法
该方法认为在嵌入微调过程中引入双向注意力与模型的预训练设计不匹配,可能会破坏其上下文学习和生成属性。为了保留特定任务的嵌入表示与生成属性,与大多数现有的嵌入方法一样,该方法保留了单向注意力机制。具体来说,在输入修改后的查询和段落的末尾添加一个 [EOS] 标记,以通过因果注意力机制捕捉语义和上下文学习模式,然后将它们输入到 LLM 中,通过提取最后一层的 [EOS] 向量来获得嵌入。训练过程中采用标准的 InfoNCE 损失函数,同时利用 in-batch negatives 和 hard negatives。
- 基于上下文学习的指令微调
实验表明,如果在训练过程中一直提供示例,可能会降低模型的零样本推理能力。因此,该方法提出了一种动态训练过程。即在每个训练步骤中,查询会被提供数量可变(0 到 n)的少量样本,这种方法在 ICL 能力和零样本性能之间取得了平衡。
2.2.3 Echo-mistral
【主要贡献】
自回归模型中由于存在因果注意力掩码,会导致token嵌入无法包含出现在输入中较靠后的token的信息。为了解决这一限制,Echo-mistral 模型中设计了 “Echo embeddings”(如图 7 所示),即使用双向注意:重复两次输入并从第二次出现中提取嵌入。原则上,第二次出现的语境化嵌入可以关注第一次中呈现的整个句子。此外,需要在 LLM 的提示信息中包括如“重写”或“重述”等词,从而尽可能确保第二次真的“编码”了关于第一次的信息。实验表明,Echo嵌入可以编码靠后token的信息,从而最大限度地利用 LLM 进行嵌入。
在 MTEB 排行榜上,Echo嵌入比传统嵌入提高了9%以上,在微调后提高了0.7%左右。与之前没有利用合成微调数据的开源模型相比,Mistral-7B 模型的Echo嵌入也有较大提升。
△图7: Echo嵌入概念介绍
2.2.4 LLM2Vec
【主要贡献】
与 Echo-mistral 模型的思想类似,语义嵌入任务中解码器模型的因果注意力机制,限制了从整个输入序列中获取并创建双向上下文表示的能力。因此,为了改进 decoder-only 获得的语义嵌入,LLM2Vec 提出了一种简单的无监督方法,可以将任何 decoder-only LLM 转换为强大的文本编码器,如图 8 所示,只需三步即可:1)启用双向注意力机制(bidirectional attention);2)掩码下一个token预测(masked next token prediction);3)无监督对比学习(unsupervised contrastive learning)。
△图8:LLM2Vec的三个步骤
LLM2Vec 选择 Llama-3 和 Mistral-7B 作为模型骨架,实验结果和广泛的分析表明,能够以参数高效的方式将 LLM 有效地转变为通用文本编码器,而无需额外的调整或利用 GPT-4 合成的数据。
【算法概述】
- 双向注意力机制
用全1矩阵替换 decoder-only LLM 的因果注意掩码,转换为双向 LLM,每个token可以访问序列中的其他token。
- 掩码下一个token预测
通过掩码下一个token预测(MNTP)来调整模型,使其更好的利用双向注意力。MNTP 是一种训练目标,它将下一个token预测与掩码语言建模相结合。给定一个任意序列作为输入,首先掩蔽输入 token 的一部分,然后训练模型根据前后文来预测这些掩蔽的 token。
- 无监督对比学习
decoder-only LLM 没有经过明确训练来捕捉整个序列的上下文,该方法采用 SimCSE 的无监督对比学习弥补了这一缺陷。具体来说,给定一个输入句子,让句子两次通过模型,每次使用独立采样的dropout掩码,从而为同一个句子生成两种不同的表征。模型被训练为最大化这两种表征之间的相似性,同时最小化它们与批次中其他句子表征之间的相似性。最后对词表征进行池化操作,以获得句子表征。
2.2.5 GRIT
【主要贡献】
Generative Representational Instruction Tuning (GRIT) 模型**,**与 Echo-mistral 和 LLM2Vec 的思想类似,也强调了双向注意力对通用文本嵌入的重要性。然而,生成式表征指令调优(GRIT)方法的关键在于,通过训练 LLM 和指令来统一处理生成和嵌入任务。对于长文本,不再需要单独的检索和生成模型,该模型可以将检索增强生成(RAG)的速度提高60%以上。模型骨架选用 Mistral-7b 和 Mistral-8x7b。
【算法概述】
GRIT 将表征式指令调优和生成式指令调优统一到了一个模型中。采用一致的数据格式,使用表征和生成式指令数据对预训练的 LLM 进行微调,如图 9 所示。对于表征数据,使用 in-batch negatives 的对比目标来计算损失,同时采用双向注意力机制,随后进行平均池化对序列长度上的最终隐藏状态进行平均。为了计算生成式数据的损失,GRIT 使用语言建模目标,即模型需要预测下一个 token。最后,将目标函数与损失权重(表征式损失权重)和 (生成式损失权重)相加。
△图9: GRIT的架构和格式
2.2.6 GTE-Qwen1.5-7B-instruct
【主要贡献】
GTE-Qwen1.5-7B-instruct 基于 GTE 嵌入模型和 Qwen1.5-7B LLM 所构建,借鉴了 Qwen1.5-7B 模型强大的自然语言处理能力。通过先进的嵌入训练技术,该模型融入了多项关键改进:
-
整合了双向注意力机制,丰富了模型的上下文理解能力;
-
仅在查询侧应用了指令调优,以提高效率;
-
在涵盖不同领域和场景的大规模、多语言文本语料库上进行了全面训练。这种训练同时利用了弱监督和监督数据,确保了模型在多种语言和广泛的下游任务中的适用性。
此外,还推出了 GTE-base-en-v1.5 和 GTE-large-en-v1.5 两个最新的英文嵌入模型,在同模型尺寸类别的MTEB基准测试上取得了很好的成绩,并且支持长达8192的上下文长度。
2.2.7 stella_en_1.5B_v5
【主要贡献】
该模型是基于 GTE-large-en-v1.5 和 GTE-Qwen2-1.5B-instruct 进行训练的。简化了提示的使用,为大多数通用任务提供了两个提示,一个是用于序列到段落(s2p)任务,另一个是用于序列到序列(s2s)任务。
-
序列到段落(s2p)任务(例如检索任务)的提示:“Instruct: Given a web search query, retrieve relevant passages that answer the query.\n Query: {query}”
-
序列到序列(s2s)任务(例如语义文本相似性任务)的提示:“Instruct: Retrieve semantically similar text.\n Query: {query}”
该模型最终选用 MRL 框架进行训练,从而具备多个维度设置,包括512维、768维、1024维、2048维、4096维、6144维以及8192维等多个层次。在理论及实践层面,通常观察到的一个趋势是,随着维度的提升,模型的性能呈现出增强的态势。然而在多数应用场景中,1024维的配置已经展现出了极为可观的性能表现,其在 MTEB 测试中的得分与最高维度的8192维模型相比,差距仅有0.001分。这表明1024维模型在性能与计算资源之间的良好平衡,也为后续模型选择与优化提供了有价值的参考依据。
2.3 方法小结
在本节中,我们详细阐述了基于 LLM 的通用文本嵌入算法模型(特别是在 MTEB 测试中排名前10的模型)。多数算法研究表明,通过全面的自回归预训练策略,LLM 能够习得高质量的文本表征,仅需少量微调即可转型为高效的通用文本嵌入模型。具体而言,微软提出的 E5-mistral-7b-instruct 与谷歌 DeepMind 的 Gecko 模型展示了两种创新途径,即通过 LLM 生成合成数据以进一步优化通用文本嵌入性能。同时,Echo-mistral 与LLM2Vec 的研究则强调,专为 decoder-only LLM 设计双向注意力机制,无需依赖合成数据,同样能实现出色的通用文本嵌入效果。BGE-EN-ICL 利用 LLM 中的 ICL 能力来增强文本嵌入生成的过程。NV-Embed-v2 设计了关注潜在向量的池化嵌入输出,并提出一种两阶段指令调优方法以提高检索和非检索任务的准确性。值得注意的是,本节介绍的所有专注于文本语义嵌入的 LLM 模型均采用了指令调优方法。这主要归因于 LLM 卓越的指令遵循能力,从而可以构建能够灵活应对多样化任务的通用文本嵌入模型的优选。此外,Mistral-7B 模型在 LLM 增强文本嵌入技术中是最流行的基线模型。其中一个关键因素在于,即便未经任何特定训练,为 Mistral-7B 启用双向注意力机制也已展现出了显著成效。LLM2Vec的作者据此推测,Mistral 模型可能已预先经历了某种形式的双向注意力训练。
03 总结
本文开篇即对文本语义嵌入方法进行了系统性概述,剖析了当前主流算法模型的架构特征及其发展脉络与趋势。鉴于 LLM 的迅速崛起,文章进一步在多维视角下对比了 LLM 文本嵌入技术与传统语义嵌入方法之间的显著差异。传统的文本语义嵌入技术以其高效性、广泛应用性和强大的语义表示能力为众多任务提供了有力支持,在自然语言处理领域占据重要地位。然而,该技术也面临着数据依赖性、静态性以及计算资源消耗等瓶颈问题。相比之下,LLM 通过捕捉文本上下文信息、支持多语言处理及出色的生成能力,为提升文本嵌入质量带来了新视角。随后,核心内容聚焦于 LLM 在生成文本嵌入领域的最新研究进展。当前,研究界对通用文本嵌入模型给予了高度关注,该模型旨在构建一个统一且全面的框架,以灵活应对不同长度的输入文本、多样化的下游任务、广泛的领域覆盖以及多语言处理需求。为实现 LLM 在提升文本嵌入能力上的潜力,研究者们探索了两条主要路径:一是通过合成数据生成策略来增加训练数据多样性和灵活性;二是直接将 LLM 作为核心架构,来优化通用文本嵌入的性能。本文介绍了这两条路径下的代表性模型,这些前沿方法均在多文本嵌入基准测试(MTEB)排行榜上名列前茅,在训练数据的规模上实现了显著提升,同时在数据质量与多样性方面展现了创新性的突破。这些进展不仅为文本语义嵌入技术提供了新的研究视角,也为未来自然语言处理领域的发展奠定了坚实的基础。
尽管 LLM 能生成更精确的文本语义嵌入,但也面临计算资源消耗大、数据隐私与伦理挑战以及解释性不足等难题。尤为关键的是,LLM 高度依赖于提示的质量,然而为各种任务创建精确且全面的提示不仅繁琐且耗时,同时,将提示整合到文本嵌入中会增加输入长度,这对于大型数据集和模型而言,将带来额外的计算开销。随着技术的持续进步,未来应该会出现更高效的训练算法,这将显著加速 LLM 的训练过程,进而推动其在 NLP 领域的广泛应用。同时,文本嵌入与图像、音频等其他模态嵌入的融合将成为趋势,旨在实现多模态自然语言处理任务,拓宽模型的应用范围并提升其性能。此外,为应对日益增长的模型解释性需求,未来 LLM 将朝着更强可解释性方向发展,优化提示生成算法和质量评估,确保决策过程的合理性、准确性和伦理性。随着这些技术的不断成熟,LLM 语义嵌入生成技术将在智能客服、内容创作、教育等众多领域展现更为广阔的应用前景,开启自然语言处理的新篇章。
主要参考文献:
[1] Wang L, Yang N, Huang X, et al. Text embeddings by weakly-supervised contrastive pre-training[J]. arXiv preprint arXiv:2212.03533, 2022.
[2] Xiao S, Liu Z, Zhang P, et al. C-pack: Packed resources for general chinese embeddings[C]//Proceedings of the 47th International ACM SIGIR Conference on Research and Development in Information Retrieval. 2024: 641-649.
[3] Li Z, Zhang X, Zhang Y, et al. Towards general text embeddings with multi-stage contrastive learning[J]. arXiv preprint arXiv:2308.03281, 2023.
[4] Touvron H, Martin L, Stone K, et al. Llama 2: Open foundation and fine-tuned chat models[J]. arXiv preprint arXiv:2307.09288, 2023.
[5] Dubey A, Jauhri A, Pandey A, et al. The llama 3 herd of models[J]. arXiv preprint arXiv:2407.21783, 2024.
[6] Jiang A Q, Sablayrolles A, Mensch A, et al. Mistral 7B[J]. arXiv preprint arXiv:2310.06825, 2023.
[7] Jiang T, Jiao J, Huang S, et al. PromptBERT: Improving BERT Sentence Embeddings with Prompts[C]//Proceedings of the 2022 Conference on Empirical Methods in Natural Language Processing. Association for Computational Linguistics, 2022.
[8] Zeng J, Yin Y, Jiang Y, et al. Contrastive Learning with Prompt-derived Virtual Semantic Prototypes for Unsupervised Sentence Embedding[C]//Findings of the Association for Computational Linguistics: EMNLP 2022. 2022: 7042-7053.
[9] Cheng Q, Yang X, Sun T, et al. Improving Contrastive Learning of Sentence Embeddings from AI Feedback[C]//Findings of the Association for Computational Linguistics: ACL 2023. 2023: 11122-11138.
[10] Wang L, Yang N, Huang X, et al. Improving Text Embeddings with Large Language Models[J]. arXiv preprint arXiv:2401.00368, 2024.
[11] M. Rui, L. Ye, J. Shafiq Rayhan, X. Caiming, Z. Yingbo, and Y. Semih, “Sfr-embedding-mistral:enhance text retrieval with transfer learning.” Salesforce AI Research Blog, 2024.
[12] Lee J, Dai Z, Ren X, et al. Gecko: Versatile text embeddings distilled from large language models[J]. arXiv preprint arXiv:2403.20327, 2024.
[13] Lee C, Roy R, Xu M, et al. NV-Embed: Improved Techniques for Training LLMs as Generalist Embedding Models[J]. arXiv preprint arXiv:2405.17428, 2024.
[14] Li C, Qin M H, Xiao S, et al. Making text embedders few-shot learners[J]. arXiv preprint arXiv:2409.15700, 2024.
[15] Springer J M, Kotha S, Fried D, et al. Repetition improves language model embeddings[J]. arXiv preprint arXiv:2402.15449, 2024.
[16] BehnamGhader P, Adlakha V, Mosbach M, et al. Llm2vec: Large language models are secretly powerful text encoders[J]. arXiv preprint arXiv:2404.05961, 2024.
[17] Muennighoff N, Hongjin S U, Wang L, et al. Generative Representational Instruction Tuning[C]//ICLR 2024 Workshop: How Far Are We From AGI.
[18] Li Z, Zhang X, Zhang Y, et al. Towards general text embeddings with multi-stage contrastive learning[J]. arXiv preprint arXiv:2308.03281, 2023.
[19] Dun Zhang. stella_en_1.5B_v5. huggingface.co/dunzhang/st…, 2023.
----------END----------
推荐阅读
基于Flink的配置化实时反作弊系统
图引擎在智能体开发场景的应用实践
导读
随着AGI理论的不断突破,智能体已经成为LLM在企业落地的最重要的形式之一。一个完备的智能体必须能实现:感知、推理、计划、执行等一套完整的功能,从工程的角度来看workflow特别适合这种复杂任务的分析、拆解、重组、执行, 再结合CoT技术, 实现LLM和业务功能完美契合的智能体应用。本文尝试用成熟的图引擎技术驱动workflow探索更多样性的拓展agent能力的方法,以更好应对各类业务场景。
01 简介
1.1 什么是智能体
以大模型(LLM)为核心, 具备以下特性的智能化系统:
-
交互性: 通过文字,语音,图像等多种交互方式来理解用户的持续性需求 (感知);
-
适应性: 感知环境的变化持续进化,以更好地完成任务和适应复杂环境 (记忆);
-
自主性: 能够自主学习,主动思考和决策 (推理);
1.2 业务形态、流程
一个智能体生态平台,用户可以在上面体验功能各异的智能体app,同时也能让用户将自己的优秀想法以极低的成本(通过快速组装已有的插件、workflow、知识库、记忆) 快速实现成新的agent。
系统特色:
-
流程编排能力:支持可视化的数据流加工,通过编辑各个处理节点将原始input加工成output;
-
功能复用能力:众多的agent库、插件库都可直接复用到自己的智能体里, 可插拔、替换;
-
低代码能力:无需大量写代码,直接通过拖拽元素就能拼装出想要的功能。
1.3 业务场景的需求难点
1.3.1 能自由组装流程实现人机无缝衔接、数据解耦
-
能将人的需求表达和agent思考结果的进行完美串联融合,发挥各自优点;
-
除context外更多样性的数据传递方式,更好满足workflow、cot等流程编排的场景;
-
细粒度控制数据传递、适配方式,满足特定场景的灵活性和性能的平衡需求。
1.3.2 能更精细规划路径、简化流程设计
-
支持多种路径控制能力,满足多样性的静态化任务编排;
-
支持在workflow内部动态编排新的子flow, 满足动态化的场景。
1.3.3 能对流程进行统一的控制、干预
-
流程运行过程中当出现超时、异常等非预期情况需要框架能提供快速干预、退出机制;
-
摆脱对executor(执行器的依赖),更低成本支持大量功能异构的流程。
1.3.4 能进行简单的功能注入
-
支持在模型前后、工具调用前后等地方注入策略逻辑和观测代码,避免对大量节点进行浸入式改造;
-
支持流程编排时给节点初始化赋值,降低数据传递的成本;
-
支持任意节点信息的流式输出能力,满足长流程中阶段性结果的sse输出需求。
1.3.5 能支持缺少代码能力的使用场景
-
将用户生或者LLM产生的cot转化成具体流程配置;
-
将流程配置转换成可运行的代码。
1.4 为什么自研图引擎
1.4.1 常用智能体开发框架简介
-
LangChain框架:一个开发智能体的框架,定义了prompts, index, memory, agents, tools, outputParser等一系列功能抽象,通过chains将各个功能串联成应用。
-
开发模式:
-
Chains: 规划静态任务, 很多抽象都实现了chains的接口,规划好路径就能让各功能有序执行
-
AgentExecutor: 执行动态任务,某些场景无法预知执行路径,需要不同的输入走不同的分支,因此引入代理人(AgentExecutor), 通过多轮循环推理产生最终结果
-
总结:多轮学习和推理是自主ai系统的基本的能力, Chains不具备循环”能力, AgentExecutor多轮调度是一个不透明度黑盒。
-
LangGraph:基于LangChain基础上演化的框架,引入条件边,赋予用户对循环的控制能力。
-
开发模式:用透明化的有向状态图打破LangChain动态任务的循环黑盒 (AgentExecutor)
已有框架比较注重系统的自主性,对业务执行路径的编排能力较弱。
1.4.2 业务需求的挑战
-
强化的路径控制能力:既能满足llm的多轮循环特性, 又能结合cot模式的功能编排;
-
传统功能的结合能力:模型存在知识能力边界,业务需要结合之前传统功能来满足多样性、个性化的需求, 在数据的校验、传递、并发、同步,流程控制等这些贯穿整个业务随处可见的基建功能都需要支持。
这些都不是已有智能体开发框架本身所擅长的,从下层视角看需要提供一个更通用、更精细化控制能力的流程驱动框架增强以下特性来满足业务需求。
02 用seda图引擎驱动workflow的模式开发智能体
对于以上共性需求我们引入图引擎驱动workflow的开发模式:将任务拆解成独立的功能节点,不仅可以包含 LLM, prompts, memory, tools, 等智能体(ai)元素还融入了 分支、循环、条件、多路复用、数据传递等传统应用所擅长的路径编排、数据转发、超时控制、错误处理等方面的功能,为智能体应用提供一个更强大、稳定、便于解耦且可黏合性强的基座环境。
2.1 实现更灵活的流程拆分组装、数据解耦
2.1.1 流程拆分
元素:
算子: 若干个函数的集合,组成一个业务逻辑上可简单描述的功能模块;
边: 联接2个算子,具有方向性,代表执行顺序,起始节点作为上游算子,指向节点作为下游算子;
联接:
串联: 一个上游算子联接一个下游算子,上下游顺序执行;
并联: 一个上游算子联接多个下游算子,上下游顺序执行,下游算子之间并行执行;
join: 多个上游算子联接一个下游算子,上游之间并行执行,下游等待所有上游执行完后再执行,实现汇聚、归并。
flow:
将复杂业务功能分解成若干个易实现、解耦、可复用的算子,根据业务执行顺序用边将算子串联起来,形成工作流。
用户请求从起始算子流入,通过flow的算子进行加工,最终从结束算子输出,完成整个业务流程。同时支持 dag 和 dcg(有环图)。
2.1.2 分层组装
-
子图(sub-flow):把一个flow也当成一个算子(sub-flow),直接挂到另一flow上,当数据推动到这个算子的时候就会触发这个(sub-flow)的内部逻辑,实现flow级别的抽象和复用;
-
分层脉络地图:功能复杂导致算子数量过多时可以按不同粒度划分层级,把相同抽象粒度的算子放到同一个层级,不同层级的算子通过子图实现串联。通过点击进入子图内部浏览功能细节,通过收拢子图回到上层抽象,以此实现功能导航地图,既方便浏览又方便解耦拆分到多人协作开发。
2.1.3 数据解耦
context共享可以方便的在所有算子间传递数据,算子的插拔替换、顺序调整也无需考虑数据的匹配,但同时也带来了数据加工处理过程黑盒,以及为了尽量避免参数读、写范围放大而需要加强数据访问权限保护这2个问题。
为此我们提供了额外的方式,满足不同场景的需求。
- 链式推导 -- 更细粒度数据解耦
描述:上游output和下游input类型一致,就能串联并传递数据。
优势:output/intput是数据传播的契约约束,数据加工流程清晰。相同intput, output定义的算子之间能串联且插拔替换;相互之间不匹配的算子能通过定义中间类型的"桥接"算子来实现串联。
短板:需要用户手工串联算子,而且算子间容易产生串联类型不匹配以及并发问题也需要用户自己解决。
- 自动推导 -- 自动优化使用和运行效率
描述:算子数量越多人工编排效率越低,在链式推导的方式上引入Referential Transparency, Single Assignment等规则约束来实现调用链自动推导。
优势:可以帮助用户自动管理大量算子的联接关系, 省时省力的同时还能在保证数据并发安全性的同时实现最大程度的并行化。
短板:关注的焦点从过程转移到数据,用户需要对流程做设计、优化时需要从数据入手做逆向推导流程(数据是在流程中慢慢产生和迭代的),违背了用户的使用习惯。而且对现有系统来说这种对数据读写的严格拆分、解耦往往需要全部推翻重来。
2.1.4 拷贝与引用
除了以上的数据传递方式外在不同的需求场景下我们同时还需要思考是传递数据的副本拷贝还是传递数据引用(本身)的问题
-
context共享:出于性能考虑,基本都是采用传递引用的方式;
-
链式推导:可以手工指定,默认通过简单的判断下游算子的数量来自动决定:下游算子个数等于1:传引用,大于1: 第一个算子传引用,剩余算子传副本,尽可能在局部范围内降低用户心智负担;
-
自动推导:在Referential Transparency, Single Assignment双重数据访问规则保护下无需用户考虑并发安全性问题;
-
自定义:用户可以在联接2个算子之间的边(edge)上显示指定是副本拷贝还是传递数据引用(本身)来获取更大的灵活度。
2.1.5 类型适配
同一类功往往有多种实现,各自针对不同的使用场景有自己的优化,这些算子的input/output 往往基本结构一致,但又稍稍有一些小差异,为了更方便让这些算子能快速插拔,提高功能复用度,降低复用成本,我们提供了一系列自动适配机制。
- 类型自动放大:内置多种数据类型及其变体自动转换逻辑:
A <---> *A, interface{}
A -> []A, []*A, []interface{}
-
特型自动匹配:上游算子的output类型是被下游算子input类型内部组合的子类型,相互能串联,并完成自动赋值。
-
自定义适配器:一个单独的适配器完成2个功能类同,但是intput/output参数形式差异较大的算子之间串联,适配器的input是上游算子的output, 其output是下游算子的input。
-
为什么不直接用过度算子实现:避免大量转换算子干扰业务流程;
-
为什么不把适配逻辑放算子内:避免侵入式改造和过度引用导致耦合。
2.2 实现精细化的路径规划
2.2.1 多功能边
-
if: 条件边 (单分支);
-
switch: 多条件边 (多分支);
-
multiplex: 多路复用边 (同时监听多个资源、信号);
-
optional edges: 可选边 (按需放弃对非强依赖上游的等待);
-
while: 循环边 (条件和循环次数组合实现dcg);
2.2.2 动态规划
编译时构建一个基础的大致性的功能脉络(上层基础逻辑定义),具体实现逻辑由执行期根据代码运行情况及LLM返回结果动态规划做逻辑的实时增删、拼接、构建。
2.3 实现统一的驱动控制和干预
2.3.1 流程驱动
-
executor 执行器:
-
存算分离设计:执行器读取flow信息并驱动执行,提供路径控制、资源调配,flow仅存储数据;
-
一次解析多次执行:对flow进行一次解析后可以得到该flow的一个excutor, 后续相同的flow都可以通过该executor进行执行;
-
适用场景:系统里flow异构类型有限, 都需要大量重复的被执行, 能节省每次构建重复flow的开销。
-
flow自驱动:
-
无需解析,直接执行:flow被构建出来后,利用flow自驱动的功能直接运行, 无需构建执行器;
-
适用场景:系统里大量异构flow,或者会动态产生出新构型的flow,能节省复用度低的执行器构建的开销。
2.3.2 错误处理
- 退出流程
当算子返回值 <0 时表示发生错误,默认直接跳到最后一个算子执行(让系统能有一个给用户回包、打日志的机会) 后并退出当前流程,快速终止无效的执行逻辑,迅速释放资源。
- 逐层退出
当有多层(子图)时候,每一层有算子返回值 <0都会直接跳转到本层子图的最后一个算子执行,随即返回回上一层。用户可以按需给上层指定返回值,当给上层的返回值 >=0时候上游正常往后面算子执行,否则继续跳到本层的最后一个算子执行,以此类推直到整个flow结束。
2.3.3 超时控制
- 图超时
我们可以给整个flow指定一个执行的超时时间,触发后直接跳入到本层最后一个算子(让系统能有一个给用户回包、打日志的机会),这样快速终止无效的执行逻辑,迅速释放资源。
- 算子超时
一般没有特殊需求我们建议根据业务接口要求通过flow控制整体超时即可,由系统自行判断可以尽量避免一些超时设置不合理的问题,同时我们也保留单独指定算子超时的能力,算子发生超时但flow整体没有超时时会跳过超时算子继续往下执行;,尽可能保持必要的灵活性。
2.4 实现通用注入
2.4.1 事件监听
- 监听通用事件
提供以aop接口的形式统一支持算子 on_enter, on_leave, on_timeout, on_error等关键事件的钩子机制,以全局函数或者算子成员函数的形式进行改写,以便用户能统一加入自定义的日志记录、监控、通知、错误处理等应对机制。
- 监听自定义事件
除了上面的通用事件,我们还提供统一的机制,提供用户在算子内部任意地方加入自定义事件的能力,帮用户简便地完成应用层框架监听机制的建设需求。
2.4.2 附加属性
除了context共享,链式推导的传递机制外我们还提供了额外第三种"附加属性"的方式来给算子传递数据,方便用户在编辑算子时就能给算子指定一些固定属性值,算子运行时能快速被读取,降低初始化成本。
2.4.3 流式输出
放置一个内置的流式输出的算子到workflow里,通过向这个算子的channel里写入数据即可实现在任意算子里流式输出信息来满足sse需求,同时将流式输出算子和最后一个算子相连,即可实现优雅退出。
2.5 实现低代码
-
提供可视化编辑器,让用户拖拽设计流程并产生对应的配置文件;
-
后端提供算子仓库作为用户功能实现的基础素材;
-
图引擎的generate负责将配置翻译成流程代码, builder动态构建流程,driver负责驱动流程运行并返回结果。
2.6 seda相较其他图引擎实现的优势
2.6.1 图引擎实现方案一:多线程并发(thread-base-on-request)
本质:线程数和请求数N:M的模型,基于请求数量规划线程的设计, 由操作系统保证线程调度、资源分配的均衡。
优势:实现简单、数据局部性好,负载在系统处理能力阈值内性能及佳,适用于对耗时要求苛刻的场景。
短板:
-
流程黑盒:线程粒度太粗(请求粒度),不利于功能迭代、优化。
-
扩展性差:请求数受系统线程数制约, 负载超出系统处理能力阈值会使系统陷入“调度内耗” (上下文切换,锁竞争),处理能力指数级下降。
2.6.2 图引擎实现方案二:事件驱动并发(thread-base-on-resource)
本质:资源数和线程数N:M的模型, scheduler根据系统资源初始化若干线程,将请求拆解成由若干个non-blocking节点组成的有限状态机(FSM),节点执行后将状态回传给scheduler, 由其根据当时资源使用情况分配下一个节点的处理线程,直到整个有限状态机结束。
优势:
-
流程可视:通过有线状态机实现各个功能节点之间互相解耦;
-
扩展性佳:线程数不受请求数影响,能始终控制在系统资源可高效运行的阈值范围内;
-
吞吐量大:事件驱动极大程度避免了多线程之间的"资源内耗",能有效提升系统并发和吞图。
短板:
-
时延增大:一次请求处理过程跨多个线程执行增加了数据传递消耗的同时也降低了硬件缓存命中率导致请求延迟增大;
-
实现困难:中心化的scheduler调度器既要驱动业务状态流转又要管理资源调度往往会顾此失彼。
2.6.3 图引擎实现方案三:基于seda的图引擎驱动(thread-base-on-stage)
seda:staged event driven architecture
本质:将上面中心化的scheduler模块给拆分成多个子部件实现。
-
用多个事件队列将每个状态节点(stage), 组成一张数据流动网络 (Directed Graph);
-
每个stage都由事件队列(接收数据)、控制器(分配资源,驱动stage流转)、线程池(调节线程数)、事件处理器(业务处理handler)组成;
优势:
-
资源按流程stage拆分,粒度适当 (按request粒度过小,容易陷入内耗;按resource粒度过大,容易浪费);
-
去除中心化模块,通过对事件队列的流速控制使得每个stage可以单独进行负载调节。
短板:
相比运行状态良好情况下的单线程处理一个请求的设计, 时延上会有增大 。
03 通用图引擎在智能体场景的实际应用
3.1 功能场景应用
3.1.1 根据大模型COT结果动态生成子workflow
-
query:请预测下明年下周的天气情况
-
大模型将问题拆解成具备先后依赖关系的多个小步骤:
-
计算下一周对应的时间范围
-
查询本周天气情况
-
查询历史上前n年对应时间范围的的天气情况,
-
根据历史查询结合当前情况推测明年对应的时间范围的天气情况(结果保存到短期记忆)
-
如样本范围太小或结果单一则重复前面过程3-4,直到给出预测结果的具体概率分布
- 大模型根据当前执行到的具体步骤将工作内容动态分解到子图并执行。
3.1.2 复杂场景的功能拆分解耦和精细化路径控制能力
-
用"多路复用"同时监听多值,支持任意数量路径分发,将 "路由和子功能调用" 算子进行拆分解耦;
-
用"可选边"将多处可能会触发到的公共逻辑"润色模型"模块拆分成独立算子;
-
用过"融合边"将各种不同类型的边融合汇聚到一个算子, 便于整体控制流程结束逻辑;
-
通过以上多种精细化路径控制功能,减少大量胶水代码的同时方便对流程图做快速修改,让用户专注于业务逻辑自身。
3.1.3 通用注入和循环增强
-
由侵入式改造转变成通用事件注入来统一控制算子内部的共性行为;
-
个性化功能增强也可以通过非侵入式方式注入算子内部;
-
在之前纯代码逻辑控制循环结束条件的同时增加了框架保护机制,避免响应不及时和资源长时间侵占。
3.2 小结
通过图引擎驱动workflow的开发模式提供了一个强大的基座,用户可以快速在其上通过插拔替换、顺序调整、串联汇聚、编辑出任意自己想要的流程,其强大的解耦和精细化路径控制能力从根本上解决传统ai开发模式带来的黑盒问题和相关不确定性问题,同时还能获得极佳的运行时效率(天然并发);其自带的低代码、分层导航等特性减少了大量胶水代码,还有助于多人同时入场并行开发,降低开发、维护成本。
目前系统已经接入80w开发者,15w合作企业,超过10w个智能体。
————END————
推荐阅读
如何在百度百舸部署满血版DeepSeek-V3、DeepSeek-R1模型
直播间互动框架性能优化与稳定性实践
导读
直播间互动体验框架技术实践,揭秘性能与稳定性优化之道,快来探索吧!在百度直播间歌会红包等活动中,我们创新性地将红包互动与高质内容深度融合,通过技术架构升级与系统性优化,打造了"音乐+红包"(边听歌边抢红包)的沉浸式体验。本次实践显著提升了直播间的并发承载能力、实时互动响应速度和用户参与满意度,同时沉淀出可复用的技术方案,为后续大型直播活动奠定坚实基础。
01 百度直播间歌会红包运营活动介绍
为提升直播内容质量和用户粘性,需注入多元化内容,增强直播间多样性和观赏性。同时,通过活动裂变扩大影响力,吸引特定用户群体,保持用户新鲜感和期待感,为平台长期发展奠定基础。
为落实直播歌会目标要求,需加快直播间互动体验框架建设,探索新型混合模式和沉淀通用能力,着力适配重点业务场景,打造"音乐+红包"的互动体验,提升直播间品质:
一是通用基础。主要包括组件复用、大图压缩等减少产物体积,页面异常、性能、白屏监控,BFF服务编排扩缩、稳定性监控等。
二是访问保障。主要包括页面多域名容灾、开启强缓存;字体、图片、CSS、JS等静态文件单独CDN强缓存域名,开启多级缓存等。
三是红包性能。主要包括页面预静态化、数据预加载、文档预取、资源预取、视图预渲染、动效降级等。
四是开发体验。主要基于直播前端一站式,建强队伍,确保项目开发流程规范统一,搭建增质增效的研发环境等。
02 体积
2.1 页面划分
在大型产品需求中,通过合理的页面划分策略,实现高效开发与维护。面对产品需求中罗列的多样玩法功能和19种以上的红包状态,研发团队面临的首要挑战是如何将这些功能合理的拆解成多个页面承载。合理的页面划分不仅关乎用户体验的流畅性,更是减小产物体积、提升跨页面资源缓存利用率的关键。通过深入分析业务逻辑与用户行为路径,我们精心设计了页面边界,确保每个页面和组件都承载着唯一元素,同时避免了冗余代码的产生。此外,这一策略还极大地促进了开发团队的协作效率,明确的页面划分减少了代码冲突的可能性,使得团队成员可以高效并行集成,从而加速了开发迭代周期。在直播间端能力的规范化构建上,同样遵循了通用化这一原则。
在页面划分时,我们非常注重跨页面资源的最优利用,通过策略性地缓存HTML、CSS和JavaScript等资源,确保一旦用户在任意时刻首次触发了红包弹出事件,这些资源即可被全面缓存,使用户在后续的页面切换过程中无需再次加载这些核心资源。
通过一系列设计举措,划分多页应用(MPA)10+个、单页应用(SPA)20+个、红包组件状态(Component)19+个、规范化直播间端能力(Scheme)30+个,每一项都经过精心设计,共同作用于提升应用的整体性能,为用户带来更加轻盈、快速且协同良好的使用体验。
2.2 性能优化
在直播歌会抢红包运营活动中,Web页占据了80%的比重,对于每一个依赖较多网络资源的玩法页面,在直播间中实现即时加载和快速展现确实面临较大挑战,尤其是在高并发、低延迟的场景下。
△页面展现过程
为了有效应对这些挑战,通过深入分析页面展现过程中的各个环节,直播间互动框架提炼出七种通用的优化方案。旨在提升用户交互体验、增强系统的整体性能。并确保直播间玩法在高并发场景下依然能够流畅运行。这些优化方案覆盖了从页面加载、资源获取到实时交互的各个方面,形成了一个全方位的性能提升样板,具体方案如下:
2.3 页面预静态化(SSG)
在直播歌会抢红包的场景中,所有不变的内容(如活动规则、活动主页框架等)使用SSG能够显著提高页面通用静态内容的加载速度,同时通过集成CSR可以实现部分动态内容的及时更新。
△框架原生SSG Webpack插件
△图1:活动规则 △图2:攒百元半屏页 △图3:支线攒碎片
2.4 页面静态化(SSR)
在直播歌会抢红包的场景中,节目单页作为用户获取歌曲节目信息的第一入口,其快速加载至关重要。SSR提供快速的节目单页初始加载,后续通过客户端的JavaScript动态增强功能(如进度提醒、节目回放等)获得更丰富的交互体验。
2.5 增量静态渲染(ISR)
在直播歌会抢红包的场景中,对于实时性要求极高的红包抢夺场景,ISR的动态更新和实时交互特性为活动的各个环节提供了实时回显的用户体验:
-
首先,在全屏红包弹窗页(如初始红包、任务红包和裂变红包)中,ISR使得页面无需刷新即可实时更新用户的红包状态。当用户参与活动或完成任务时,ISR的快速响应确保用户能即时获得任务状态和奖励领取情况,增强了用户的参与感与互动性。
-
对于实时轮次切换功能,ISR保障用户迅速在游戏阶段间切换,提升了同页面不同状态的连续性。当活动结束时,系统能够快速通知用户并更新活动状态为下线,避免误导用户继续参与。
-
在内容分享与社交互动方面,ISR处理高效的页面加载与实时显示,如微信邀请和海报分享,保证用户能快速刷新助力进度。在邀请分享页,主态用户能立即看到受邀好友的参与情况和贡献,进一步增强社交互动体验。
2.6 数据预取(Prefetch Data)
在直播歌会抢红包的场景中,通过NA与H5之间的有效数据预取和缓存衔接,实现了端数据的复用,有效减少与服务器的交互频率,消除了数据加载的等待时间,确保了在直播环境中用户能够高效参与活动:
-
预取皮肤元素配置,进入直播间后,NA会预取皮肤元素配置,预加载与活动相关的皮肤素材,并将这些信息进行缓存,包括页面主题色和红包动画等。同时,前端JavaScript能够在页面弹出时,通过端能力或全局变量直接获取相关数据,用户不需要等待皮肤配置加载,界面视觉能够立即呈现,从而实现在操作上的流畅体验。
-
攒百元红包的进度更新,在活动进行中,用户需要实时查看攒百元红包的进度,通过数据预取的方式,能够迅速更新至用户界面。在启动WebView的同时,NA实现数据的并行获取。这意味着在用户点击挂件后,相关的数据请求会立即开始,前端JavaScript则能够在执行时通过端能力直接获取这些已经预取的数据,降低了数据延迟加载等待时间,增强了用户参与活动的效率。
2.7 文档预取(Prefetch HTML)
在互动性较强的直播歌会抢红包的场景中,用户不仅可以观看演出,还能参与抢红包活动。为提供最佳的用户体验,确保用户在首次点击不同功能时能够快速上屏相关内容,采用文档预取能力在后台主动下载歌会相关HTML内容,如攒百元半屏页、节目单页等。当用户最终点击某个链接时,直接从内存中读取HTML文档内容,无需网络请求,从而显著提高页面加载速度,确保用户在直播间里的互动预期。
通过数据结果来看,文档预取的效果非常显著。在优化了节目单页的性能后,Android用户的首屏加载时间从3秒级减少到500毫秒级,iOS用户的首屏加载时间从2.5秒级减少到500毫秒级。这样的性能提升显然改善了用户体验,使得用户能够快速获取所需信息,进而积极参与到活动中,营造出活跃的直播间氛围。
△Prefetch SSR/CSR HTML
2.8 资源预取(Prefetch Resource)
在直播歌会的场景中,用户参与抢红包是一个关键的互动环节。在此过程中,确保红包弹出的多层动画和红包图能够迅速、完整地展示对于增强用户体验至关重要。为此,资源预取在这一场景中得到了有效应用,在正式直播活动开始前期,后台服务主动下载、缓存、更新关键资源,包括红包的动画文件和高质量的红包皮图像。以确保当红包正式弹出时,最新的文件已被准备妥当,用户能够立即看到完整的红包图和流畅的动画效果,避免了图片逐块加载造成的卡顿和不完整展示。
通过数据结果来看,资源预取的效果非常显著。Android用户资源加载耗时提升幅度约46.7%,iOS用户资源加载耗时提升幅度达86.1%,大幅提升了整体互动体验,使用户在关键时刻享受到快速且流畅的操作体验。
为了确保资源预取的有效性,需要注意以下几点:
-
预取的资源应以用户行为的合理预测为基础,避免过度预取,从而造成带宽浪费。
-
采用分模块的离线包设计,将每个模块的资源单独管理。
-
在活动结束后,应及时下线不再需要的资源,释放带宽和用户手机空间。
2.9 视图预渲染(Prerender WebView)
在直播歌会的场景中,观众们期待快速响应的抢红包互动体验,此时视图预渲染能力发挥了重要作用。当用户进入直播间后,提前在后台加载并渲染抢红包页面内容,并注册页面可见性监听器。即使用户专注于观看直播,红包页面也已准备妥当。用户点击按钮,抢红包页面便迅速显示,无需等待加载和渲染时间,同时触发监听器实时更新数据。这样的即时反馈使得用户几乎可以瞬间查看抢红包的结果,极大提升了参与的积极性和体验感,进一步增强了直播的互动乐趣。
在预渲染过程中,仅对用户频繁访问的页面进行预渲染,避免资源浪费,确保当前视图性能不受影响。由于预渲染占用内存资源,因此需要控制WebView的数量,防止内存泄漏。在实施时应关注内存管理、时机选择、兼容性和安全性,以灵活适应具体应用场景。
03 稳定性
3.1 弹窗稳定性
保障直播间红包弹层的进退场稳定性,防止透明弹层卡住以致用户无法互动,是一项关键挑战。在直播间中,红包弹层通过覆盖全屏透明WebView实现,且与动画控制密切相关,用户在拆红包动画播放过程中无法进行任何交互,关闭按钮在动画结束后才会显示。这要求我们确保红包动画的持续时间和效果稳定,以便在合适的时机正确显示关闭按钮。为确保红包弹窗正常退出,尤其是在H5页面渲染异常或网络不稳定的情况下,用户也能得到一个状态友好的反馈。保障直播间抢红包互动的稳定性,我们设计了“一次握手”和“双重兜底”策略:
-
一次握手,即Web内容健康检查:
-
JavaScript通过WebContentLoaded端能力,表示H5成功接管用户交互,并通知Native端取消WebView的超时销毁策略,以确保全屏红包弹窗能够稳定展示。
-
如果H5接管未在规定时间内完成,Native端将销毁上层全屏透明的WebView。这一措施确保用户不会因弹窗问题而中断观看体验,从而能够持续与直播间进行交互。
-
双重兜底,即NA兜底页和H5兜底页:
-
NA兜底页,当HTML入口文件请求异常时,展示Native兜底页面,确保用户有可见的替代内容。
-
H5兜底页,在JS业务组件发生异常(例如接口请求异常、端能力调用失败、组件内部异常、重要资源缺失)时,展示H5兜底内容,为用户提供实质反馈。
△图1:NA兜底页 △图2:H5__兜底页 △图3:请求______兜底
3.2 动效降级
炫酷的动效的表现直接影响用户的体验,在直播歌会场景中,红包动效由复杂的元素组成,包括Lottie动画、AFX透明视频和CSS动画。炫酷的动效虽然可以增强视觉吸引力,但在低端手机上可能导致卡顿。为确保所有用户可以顺畅参与活动,我们实施了分级动效降级策略:
-
高性能设备(High):在高性能设备上,展示完整的动画和丰富的动态效果,享受到丰富的视觉效果。
-
低性能设备(Low):对于低端手机,复杂的动效将被简化为静态图像或低复杂度的CSS动画。例如,红包拆开时只展示基本的静态图形,替代激烈的动态效果,确保用户能够正常阅读红包金额,而不至于因动效卡顿而影响体验。
分级动效降级策略能够根据当前手机的实时性能情况,在用户点击拆红包时动态调整展示的动效级别,确保以最佳效果参与活。这种适应性有效地解决了不同设备用户在参与红包活动时可能遇到的性能问题,从而提升整体用户体验的品质。
3.3 组件响应
随着用户体验的不断优化,直播歌会抢红包活动中页面组件的运行环境日益复杂。特别是在复杂组件的开发中,组件开发者必须意识到各项适配工作的必要性,以确保用户体验与开发体验之间的平衡。为了有效满足用户需求并提升开发效率,我们需要综合考虑多个环境及其不同状态。至此,在一个组件的设计和实现过程中,需要针对以下五种状态进行响应和适配:
-
SSG环境(编译线环境):组件在编译过程中,通过Node.js将公共的信息(如活动规则)提前生成静态内容,以提供快速响应时间。
-
SSR环境(服务端环境):组件服务器集群上,通过Node.js根据用户请求动态生成相应的内容(如歌会节目单),减去客户端JavaScript加载执行时间,加快页面首屏展示速度。
-
ISR环境(客户端环境):组件在浏览器中,通过JavaScript进行动态渲染、响应用户点击、滑动等操作,通过异步接口获取最新数据(如红包金额、助力信息)并即时更新界面,保证用户体验的实时性和互动性。
-
页面可见(Visibility):组件在浏览器中,通过JavaScript控制组件的渲染时机,仅在内容需要展示时才进行渲染(如播放红包动画),减少不必要的DOM操作,提升性能并降低资源消耗。
-
动效级别(High / Low):组件在浏览器中,通过Native端能力获取用户设备的性能,动态调整组件中的动效,在高性能设备上展示更炫酷的动效,在低性能设备上则展示更简单的动效,确保流畅体验。
04 总结
-
沉淀直播框架能力:通过优化直播间视图容器组件,并形成标准化的组合能力样板,拉升直播间活动页面的性能水准,这些方案具备良好复用性,适用于未来各种直播活动。
-
系统稳定性保障:组件复用、性能监控和容错机制,减少重复开发和维护成本,进行压力测试与优化,提升系统可靠性和用户体验,确保高峰流量下的稳定性。
-
强化互动性体验:在直播歌会中建立综合能力框架,特别是在抢红包等互动性强的活动中,确保用户在享受歌会演出的同时体验流畅的互动,鼓励积极参与
————END————
推荐阅读
如何在百度百舸部署满血版DeepSeek-V3、DeepSeek-R1模型
首日调用客户破1.5万!DeepSeek-V3/R1上线背后的超低推理成本技术揭秘
百度网盘防雪崩架构实践
如何在百度百舸部署满血版DeepSeek-V3、DeepSeek-R1模型
百度百舸·AI异构计算平台已支持快速部署DeepSeek-V3、DeepSeek-R1及其蒸馏的Llama、Qwen等小规模dense模型。您可以登录百度百舸平台快速部署DeepSeek系列模型体验模型效果。
01 开通轻量计算实例
开通一台H20(ebc.lgn7t.c208m2048.8h20.4d)规格的计算实例并添加到百度百舸·AI异构计算平台。
02 部署vLLM
在百度百舸平台的左侧导航中选择「工具市场」页面,部署工具vLLM。
03 模型推理
vLLM部署成功,登录实例下载模型并启动vLLM服务,安装WebUl客户端。
发送请求开始对话。
04 各系列模型的推荐配置清单
在完成满血版DeepSeek模型的快速部署后,百度百舸·AI异构计算平台还能为这些在线服务提供全生命周期管理、自研框架推理加速、推理资源碎片整理等能力。在保障服务稳定性的同时,有效降低推理成本并提升推理性能。
访问百度百舸页面cloud.baidu.com/product/aih…
————END————
推荐阅读
首日调用客户破1.5万!DeepSeek-V3/R1上线背后的超低推理成本技术揭秘