基于激活稀疏性的长上下文大模型推理优化:LongAct原理与实战

基于激活稀疏性的长上下文大模型推理优化:LongAct原理与实战

1. 项目概述:当长上下文成为标配,我们如何为推理“瘦身”?

最近半年,大模型圈子里最热闹的话题之一,莫过于各家厂商在上下文长度上的“军备竞赛”。从最初的4K、8K,到现在的128K、200K,甚至宣称百万级别的上下文窗口,仿佛一夜之间,处理超长文档、进行复杂多轮对话成了标配能力。作为一名长期在一线折腾模型部署和优化的从业者,我最初也和很多人一样兴奋,但真正把动辄几十万token的模型塞进生产环境后,问题就来了:推理成本高得吓人,响应速度慢得让人心焦。

这背后是一个简单的算术题:标准的Transformer注意力机制,其计算复杂度与序列长度的平方成正比。这意味着,处理一个10万token的序列,其注意力计算开销可能是处理1千token序列的一万倍。这带来的不仅是巨额的GPU显存占用,更是实实在在的云服务账单和用户等待时间。正是在这种“长上下文狂欢”与“推理成本焦虑”的夹缝中,我注意到了LongAct这个方向。它不是一个具体的产品,而是一种基于激活稀疏性的优化思想,旨在为长上下文推理“瘦身”,让大象也能轻盈起舞。

简单来说,LongAct的核心思路是:在处理超长序列时,模型并非需要对所有历史token都保持“高度警觉”。就像我们人类阅读一篇长报告,只会对当前段落和关键结论投入主要精力,而不会时刻在脑海里复述每一个标点符号。LongAct试图让模型也学会这种“选择性关注”,在推理的每一步,只对一小部分最相关的历史激活(即神经网络中间层的输出值)进行精细计算,而对其他大部分激活则采用一种近似或缓存的方式处理,从而大幅降低计算量。

这尤其适合那些需要频繁与超长上下文进行交互的场景,比如法律文档分析、代码库问答、长篇小说续写、以及跨越多轮次(数十甚至上百轮)的深度对话助手。如果你正在为如何经济、高效地部署支持长上下文的模型而头疼,或者单纯好奇前沿的推理优化技术,那么这次关于LongAct的深度拆解,或许能给你带来一些新的思路和可落地的参考。

2. 核心原理:为什么是“激活稀疏性”?

要理解LongAct,我们得先回到问题的根源——Transformer的自注意力机制。在标准的自注意力中,当前要生成的token(Query),需要与序列中所有先前的token(Key)计算一个注意力分数,然后根据这个分数对所有先前的token对应的信息(Value)进行加权求和。这个“所有”二字,就是计算和内存开销的罪魁祸首。

近年来,学术界和工业界提出了许多近似注意力方法,如局部窗口注意力线性注意力基于哈希的注意力等,它们大多在注意力矩阵的稀疏化或低秩近似上做文章。而LongAct代表的思路,则另辟蹊径,将优化的焦点从“注意力模式”转移到了“激活张量”本身。

2.1 激活张量:被忽视的性能瓶颈

在Transformer的每一层,输入经过自注意力层和前馈网络层后,都会产生一个中间输出,这就是激活(Activation)。在推理时,为了支持生成下一个token,我们通常需要缓存这些历史token的Key和Value(即KV Cache),以避免重复计算。随着序列变长,KV Cache的显存占用线性增长,这已经是众所周知的瓶颈。

但容易被忽视的是,前馈网络(FFN)层的输出激活同样需要被存储或处理,尤其是在一些需要利用中间层特征进行复杂推理的架构中。更重要的是,在计算当前token时,即使注意力机制本身通过某种方式变得稀疏(例如只关注最近的128个token),但为了计算这128个token的Value,我们仍然需要读取它们对应的、经过所有网络层变换后的完整激活值。这个过程涉及大量的内存访问(Memory Access),在现代GPU上,内存带宽常常是比计算单元更稀缺的资源,从而成为延迟的隐形杀手。

LongAct的思想是:我们能否让这些激活值也变得“稀疏”?即,对于大部分历史token,我们只保留一个“粗糙”的、信息压缩后的表征;只有当某些token被判定为与当前计算高度相关时,才去动态地恢复或计算其“精细”的完整激活。这就引入了激活稀疏性的概念。

2.2 实现激活稀疏性的两种路径

在实践中,实现激活稀疏性主要有两种技术路径,它们各有优劣,适用于不同的场景。

路径一:分层级的激活存储与计算这是最直观的思路。我们可以为每个历史token维护两种状态的激活:

  1. 稠密激活:完整的、高精度的网络层输出。我们只为极少数被预测为未来会高频用到的“关键token”保留此状态。
  2. 稀疏激活:经过压缩的、低精度的表征。例如,对原始激活进行量化(如从FP16降到INT8)、进行主成分分析(PCA)降维、或者使用一个轻量级网络学习一个摘要向量。绝大部分历史token仅存储这种稀疏激活。

在推理时,当需要用到某个历史token的信息时,系统首先检查其存储的是稠密还是稀疏激活。如果是稀疏激活,并且当前计算需要其精细信息,则触发一个“反压缩”或“小范围重计算”的过程。这个过程的计算开销,远低于从头开始计算该token经过所有网络层的结果。

路径二:基于预测的动态激活计算这种方法更为激进,它不存储完整的激活历史,而是“用时间换空间”。其核心是一个轻量级的预测器(Predictor),它根据当前的上下文和生成状态,实时预测接下来最可能需要用到哪些历史token的精细激活。

例如,在生成长文档的摘要时,当模型写到“综上所述”时,预测器可以判断接下来需要引用开头的“研究目标”和中间的“核心数据”部分。于是,系统可以提前或按需地只重新计算这几个关键片段所对应的网络层激活,而其他部分的激活则保持在一个基线水平或直接被忽略。

注意:路径二对预测器的准确性要求极高。如果预测失误,频繁的错误重计算会导致性能反而下降。因此,初期实践更倾向于采用路径一,即“存储压缩态+按需解压”的稳健策略。

2.3 LongAct与现有技术的协同关系

理解LongAct,不能把它看作一个孤立的银弹。它通常与现有的其他优化技术协同工作,形成组合拳:

  • 与KV Cache量化结合:LongAct优化的是FFN等层的激活,而KV Cache的量化(如KV Cache INT8)优化的是注意力层的状态。两者可以同时应用,分别从不同维度降低内存压力。
  • 与注意力稀疏化结合:例如,模型可能使用局部窗口注意力来限制注意力范围,同时使用LongAct来管理窗口内那些被关注到的token的激活精度,实现“稀疏注意力+稀疏激活”的双重节省。
  • 与模型剪枝/蒸馏结合:LongAct是一种动态的、推理期的优化。而模型剪枝或蒸馏是静态的、训练期的优化,旨在得到一个更小的模型。一个经过剪枝的轻量模型,再配合LongAct技术,往往能获得最佳的端到端推理效率。

3. 实战设计:构建一个LongAct推理系统的关键组件

理论很美好,但落地需要设计。一个具备LongAct能力的推理系统,其架构会比标准推理引擎复杂。下面,我将以一个假设的、支持长上下文对话的LLM服务为例,拆解其核心组件设计。

3.1 系统架构总览

整个系统可以看作在标准Transformer推理引擎之上,增加了一个“激活管理层”。这个管理层负责激活的压缩、存储、检索和按需精化。

[用户输入] -> [Tokenizer] -> [嵌入层] | v [当前序列] -> [Transformer Block 1] -> [激活管理器] -> [压缩/存储历史激活] | | v v [Transformer Block N] -> [生成下一个token] | v [输出Logits] -> [采样] -> [生成token]

关键点在于,每个Transformer Block的输出,在送入下一层的同时,也会被送到激活管理器。管理器决定是将其完整存储(作为稠密激活),还是压缩后存储(作为稀疏激活),亦或是根据策略直接丢弃。

3.2 核心组件一:激活压缩器

这是实现稀疏性的基础。压缩算法需要在“保真度”和“压缩率”之间取得平衡。

  • 量化:最简单有效的方法。将FP16的激活值量化为INT8甚至INT4。对于FFN层的激活,由于其分布相对稳定,量化通常效果良好且带来的精度损失可控。我们可以使用训练后量化(PTQ)或更精细的量化感知训练(QAT)来获得校准参数。
  • 结构化剪枝/低秩近似:我们可以认为,不是所有神经元通道都对后续计算同等重要。通过分析激活的统计特性,可以识别并剪枝掉那些输出值常年接近零的通道,或者用一组低秩矩阵来近似原始的激活矩阵。
  • 学习式摘要:训练一个极小的神经网络(如一个两层的MLP),将原始高维激活映射到一个固定长度的低维向量。这个向量需要蕴含足够的信息,以便在需要时能通过另一个小网络(解压器)进行一定程度的重建。

实操心得:在项目初期,建议从分层感知量化开始。即对不同网络层的激活采用不同的量化位宽。经验表明,靠近输入和输出的层对量化更敏感,应使用较高精度(如FP16或INT8),而中间层可以尝试更激进的INT4量化。使用像torch.quantizationTensorRT这样的工具可以快速进行实验。

3.3 核心组件二:相关性预测器

这个组件决定“哪些token的激活值得保留为稠密格式”。一个简单的基线策略是最近优先(Keep Recent),即总是保留最近N个token的稠密激活。这在对话场景中很有效,因为用户的最新问题通常与最近的对话历史最相关。

更高级的预测器可以基于内容:

  • 基于嵌入的相似度:计算当前查询token的嵌入向量与所有历史token嵌入的余弦相似度,选取Top-K个最相似的。
  • 轻量级注意力网络:训练一个只有1-2层、头数很少的微型Transformer,它接收当前上下文,输出一个对历史token重要性的打分。
  • 基于规则的启发式方法:在某些垂直领域(如代码),可以结合规则,例如当遇到“函数名”时,优先保留该函数定义处的上下文;当遇到“错误码”时,优先保留相关日志输出段的上下文。

注意事项:预测器本身必须非常轻量,它的计算开销必须远低于它所能节省的激活重计算开销。否则就本末倒置了。通常,这个预测器可以是一个在原始大模型上微调出来的、参数量小于1%的小模型。

3.4 核心组件三:激活缓存与检索系统

这相当于系统的“内存管理单元”。它需要高效地管理两种状态的激活:

  1. 稠密缓存:一个固定容量的FIFO或LRU缓存,存储预测器认为最重要的那些token的完整激活。当缓存满时,需要将某些稠密激活降级为稀疏激活(即进行压缩)。
  2. 稀疏存储:一个更大的、可能存储在更慢内存(如CPU RAM)中的存储区,存放所有其他token的压缩后激活。当预测器判断某个稀疏存储的token变得重要时,需要能快速将其检索出来,并送入“解压/精化”流水线。

这里的一个工程难点是数据一致性。当一个token的激活从稠密被降级为稀疏时,其压缩过程必须是可逆的(对于有损压缩)或精确的(对于无损压缩),以确保未来需要时,重建的激活不会引入导致生成混乱的误差。

4. 实现步骤:从零搭建LongAct推理引擎的简化原型

为了让大家有更直观的感受,我将勾勒一个使用PyTorch实现LongAct核心逻辑的简化原型。请注意,这是一个用于阐述概念的教育性代码,离生产级应用还有很大距离。

4.1 步骤一:定义激活压缩与解压类

我们首先实现一个最简单的量化压缩器。

import torch import torch.nn as nn class QuantizationActivationManager: """ 一个简单的量化激活管理器。 将激活量化为INT8存储,并在需要时反量化回FP16。 """ def __init__(self, dense_cache_size=512): self.dense_cache_size = dense_cache_size # 稠密缓存容量 self.dense_cache = {} # 格式:{token_position: full_activation} self.sparse_store = {} # 格式:{token_position: quantized_activation} # 简单的每层量化参数(生产环境需校准) self.scale = None self.zero_point = None def _quantize_tensor(self, tensor: torch.Tensor): """将FP16张量量化为INT8""" if self.scale is None: # 动态计算量化参数(简化版,实际应基于校准集) self.scale = (tensor.max() - tensor.min()) / 255.0 self.zero_point = torch.round(-tensor.min() / self.scale).to(torch.int8) q_tensor = torch.round(tensor / self.scale + self.zero_point).clamp(-128, 127).to(torch.int8) return q_tensor, self.scale, self.zero_point def _dequantize_tensor(self, q_tensor: torch.Tensor, scale: float, zero_point: int): """将INT8张量反量化为FP16""" return (q_tensor.float() - zero_point) * scale def store_activation(self, position: int, activation: torch.Tensor, is_important: bool): """ 存储一个位置的激活。 is_important: 预测器判断该位置是否重要。 """ if is_important or len(self.dense_cache) < self.dense_cache_size: # 存入稠密缓存 self.dense_cache[position] = activation.clone() # 如果缓存满了,把最旧的不重要的踢出去并压缩 if len(self.dense_cache) > self.dense_cache_size: self._evict_from_dense_cache() else: # 压缩后存入稀疏存储 q_act, scale, zp = self._quantize_tensor(activation) self.sparse_store[position] = { 'quantized': q_act, 'scale': scale, 'zero_point': zp } def _evict_from_dense_cache(self): """从稠密缓存中驱逐一个条目(这里用FIFO策略)""" if self.dense_cache: oldest_pos = next(iter(self.dense_cache)) act_to_evict = self.dense_cache.pop(oldest_pos) # 驱逐时将其压缩存入稀疏存储 q_act, scale, zp = self._quantize_tensor(act_to_evict) self.sparse_store[oldest_pos] = { 'quantized': q_act, 'scale': scale, 'zero_point': zp } def retrieve_activation(self, position: int) -> torch.Tensor: """检索某个位置的激活,自动处理稠密/稀疏""" if position in self.dense_cache: return self.dense_cache[position] elif position in self.sparse_store: data = self.sparse_store[position] return self._dequantize_tensor(data['quantized'], data['scale'], data['zero_point']) else: raise KeyError(f"Activation for position {position} not found.") def update_importance(self, position: int, new_importance: bool): """更新某个位置的重要性,可能触发其在稠密和稀疏间移动""" # 简化逻辑:如果变得重要且当前在稀疏存储,则解压并移入稠密缓存(需驱逐一个) if new_importance and position in self.sparse_store: restored_act = self.retrieve_activation(position) # 这会触发解压 # 先移除稀疏存储中的记录 del self.sparse_store[position] # 存入稠密缓存,可能触发驱逐 self.store_activation(position, restored_act, is_important=True)

4.2 步骤二:集成到Transformer推理循环中

接下来,我们需要修改标准的自回归生成循环。假设我们有一个model对象,我们将在其每一层后插入激活管理器。

class LongActWrapper(nn.Module): """将原始模型包装起来,增加LongAct功能""" def __init__(self, base_model, activation_manager, importance_predictor): super().__init__() self.base_model = base_model self.activation_manager = activation_manager self.importance_predictor = importance_predictor # 假设我们只管理最后N层FFN后的激活(通常这些层激活信息量更大) self.layers_to_manage = [-3, -2, -1] # 管理最后三层 def forward(self, input_ids, past_activations=None, use_cache=True): """ 改进的forward函数。 past_activations: 可存储之前调用返回的激活管理器状态。 """ outputs = self.base_model(input_ids, use_cache=use_cache) hidden_states = outputs.last_hidden_state # 模拟逐层计算并管理激活 current_position = input_ids.shape[1] - 1 # 假设我们关心最新token的激活存储 for i, layer in enumerate(self.base_model.model.layers): # ... 这里是layer的前向传播,得到该层的输出hidden_states ... # 假设layer_output是当前层的输出激活 layer_output = layer(hidden_states) # 简化表示 if i in self.layers_to_manage: # 使用预测器判断当前层、当前位置的激活是否重要 # 这里简化:预测器接收当前hidden_states和位置,返回布尔值 is_important = self.importance_predictor(layer_output, current_position) # 存储激活 self.activation_manager.store_activation( position=current_position, activation=layer_output.detach(), # 注意detach is_important=is_important ) hidden_states = layer_output # 在生成下一个token时,如果需要用到历史激活,可以通过activation_manager.retrieve_activation获取 # 这里需要根据模型具体的注意力机制修改,例如在计算注意力时,Value不是直接用hidden_states, # 而是可能需要用存储的、经过特定层变换后的激活。这是一个复杂点。 return outputs

4.3 步骤三:实现一个简单的预测器

我们实现一个基于最近距离和简单关键词的预测器。

class SimpleImportancePredictor: """一个简单的基于规则的重要性预测器""" def __init__(self, keep_recent=100, important_keywords=None): self.keep_recent = keep_recent self.important_keywords = set(important_keywords) if important_keywords else set(['总结', '因为', '所以', '定义', '函数', 'import', 'def']) def predict(self, current_token_id, tokenizer, recent_positions): """ 简化预测:1. 最近的token重要;2. 包含关键词的token重要。 current_token_id: 当前正在处理的token的id。 tokenizer: 用于id到文本的转换。 recent_positions: 最近生成的token位置列表。 """ is_important = False current_text = tokenizer.decode([current_token_id], skip_special_tokens=True) # 规则1:属于最近N个token if any(abs(pos - recent_positions[-1]) < self.keep_recent for pos in recent_positions): is_important = True # 规则2:包含重要关键词 for keyword in self.important_keywords: if keyword in current_text: is_important = True break return is_important

核心环节解析:以上原型清晰地展示了LongAct系统的工作流:在模型前向传播的特定层后,拦截激活值;调用预测器判断其未来价值;根据判断结果,选择将其以高精度(稠密)或低精度(稀疏/量化)格式存储。在后续需要用到历史信息(如注意力计算)时,从管理器中检索,如果是稀疏格式则先解压。这个流程将存储和计算的压力,从“所有token的所有激活”转移到了“预测器的计算+部分token的精化计算”上。

5. 性能评估与调优:如何衡量LongAct的收益与代价

引入LongAct这样的复杂优化,必须有一套严谨的评估体系,确保其带来的收益(降低延迟、减少内存)大于其开销(预测器计算、压缩解压开销、可能的精度损失)。

5.1 核心评估指标

  1. 内存占用峰值(Peak Memory Usage):这是最直接的收益指标。使用torch.cuda.max_memory_allocated()在长序列推理任务前后进行测量,对比启用LongAct前后的差值。理想情况下,应能看到显着的下降,尤其是在序列长度超过10K token之后。
  2. 推理延迟(Latency):测量生成每个token的平均时间或整个序列的总时间。需要区分不同阶段:
    • 首token延迟:处理整个提示词(Prompt)并生成第一个token的时间。LongAct可能会因为初始的激活压缩存储而略微增加开销。
    • 生成阶段延迟:自回归生成每个后续token的平均时间。这是LongAct主要的优化目标,应观察到下降。
  3. 吞吐量(Throughput):在批量处理(Batch Inference)场景下,单位时间内能处理的token总数。LongAct通过降低单序列内存占用,使得同一张GPU卡上能并行处理更多的序列,从而提升吞吐。
  4. 任务精度(Task Accuracy):任何优化都不能以牺牲精度为代价。需要在目标下游任务上评估:
    • 困惑度(Perplexity):在长文本语言建模任务上,计算启用LongAct后模型的困惑度变化。
    • 特定任务指标:如长文档问答的F1分数、代码补全的精确匹配率等。需要设计包含长上下文依赖的测试集。

5.2 平衡艺术:稀疏度与精度的权衡

LongAct的核心参数是稀疏度,即有多大比例的激活被存储为稀疏格式。这通常由稠密缓存的大小和预测器的激进程度控制。

  • 高稀疏度(如95%):内存节省极大,但预测器失误或压缩损失导致信息丢失的风险增高,可能引发生成质量下降,表现为事实错误、逻辑矛盾或语言流畅度降低。
  • 低稀疏度(如50%):生成质量有保障,接近原始模型,但内存和计算节省有限。

调优建议:从一个保守的稀疏度(例如,只对序列中超过2048 token的部分应用LongAct,并保持较高的稠密缓存比例)开始。在验证集上监控精度指标,然后逐步提高稀疏度(扩大应用范围、减小稠密缓存),直到观察到精度出现不可接受的下降,然后回退一步。这个过程被称为稀疏度-精度曲线的绘制,是调优的关键。

5.3 实际测试中的常见模式

在我的实测中,观察到一些典型现象:

  • 收益非线性增长:当序列长度较短(<4K)时,LongAct的开销(管理器逻辑、预测器计算)可能抵消甚至超过其收益,导致延迟反而增加。LongAct的甜点通常在序列长度大于8K-10K之后
  • 任务依赖性:对于强依赖精确历史信息的任务(如精确引用、数学推导),LongAct需要更保守的配置(更大的稠密缓存、更精确的预测器)。对于创意写作、开放式对话等容错性较高的任务,则可以更激进。
  • 层间差异:不同Transformer层对激活压缩的敏感度不同。通常,中间层的激活更适合压缩,而靠近输出(特别是最后一层)的激活对生成质量影响更大,应谨慎处理或保持稠密。

6. 避坑指南与进阶思考

在实际探索LongAct相关技术时,我踩过不少坑,也积累了一些超越基础实现的思考。

6.1 常见问题与排查

问题现象可能原因排查与解决思路
生成文本出现 nonsense 或重复1. 激活压缩损失过大(如量化位宽太低)。
2. 预测器错误地将重要token的激活驱逐或压缩了。
3. 解压过程引入误差累积。
1.检查量化误差:对比原始激活与量化再反量化后的激活,计算MSE。逐步提高量化位宽(如从INT4到INT8)。
2.分析预测器日志:在生成异常文本的位置,检查当时哪些token的激活被标记为“不重要”。手动验证这些token是否真的无关。
3.启用逐层调试:暂时关闭某些层的激活管理,观察问题是否消失,以定位敏感层。
内存下降不明显,甚至增加1. 激活管理器自身的状态(如索引、元数据)开销过大。
2. 稠密缓存比例设置过高。
3. 预测器过于复杂,计算开销大。
1.剖析内存:使用memory_profiler等工具,分析内存具体被哪些数据结构占用。优化管理器的数据结构,如使用更紧凑的数组而非字典。
2.调整缓存策略:尝试LRU(最近最少使用)替代FIFO,并调小缓存大小。
3.简化预测器:用基于规则的轻量预测器替代神经网络预测器,或降低其频率(如每10个token预测一次)。
推理速度变慢1. 预测器+压缩解压的耗时 > 节省的注意力计算耗时。
2. 检索稀疏激活的I/O开销大(如频繁访问CPU内存)。
3. 实现中存在不必要的同步或拷贝。
1.性能剖析:使用PyTorch Profiler,精确测量每个组件(标准注意力、预测器、压缩、检索)的耗时。确认瓶颈点。
2.优化数据布局:确保稠密缓存常驻GPU显存,稀疏存储的检索尽量批量进行,减少PCIe传输。
3.检查实现:避免在GPU和CPU间频繁切换,使用torch.cuda.stream异步操作。

6.2 从推理优化到训练协同

目前讨论的LongAct主要是一种推理期优化。但更极致的思路是,在模型训练阶段就引导其产生“易于稀疏化”的激活模式。这被称为稀疏感知训练可稀疏化训练

基本想法是在训练损失函数中加入一项正则化项,鼓励模型的激活具有以下特性之一:

  • 可压缩性:激活值的分布更集中,更容易被低精度量化而损失小。
  • 可预测性:激活值的变化更平滑,使得基于过去token预测未来重要性的任务更容易。
  • 层级重要性:不同层、不同头对上下文长度的依赖度产生分化,有些层专门处理局部依赖,有些层专门处理长期依赖,从而可以针对性地对“长期依赖层”应用更强的LongAct。

这项工作处于研究前沿,但无疑是降低长上下文模型全生命周期成本的重要方向。

6.3 工程化落地的挑战

将实验室原型转化为稳定、高效的生产系统,还有很长的路:

  • 与现有推理引擎集成:如何将LongAct模块无缝集成到vLLM、TGI、TensorRT-LLM等主流推理引擎中?这需要深入理解这些引擎的KV Cache管理和计算图优化机制。
  • 动态自适应:一个固定的稀疏度策略可能无法适应多样化的用户请求。理想的系统应该能根据当前请求的序列长度、内容类型(代码/文本/对话)甚至服务端的实时负载,动态调整LongAct的策略参数。
  • 硬件友好性:压缩、解压、预测这些操作,能否通过GPU内核(CUDA Kernel)进行极致优化?能否利用新一代硬件(如带有张量核心和高速缓存的H100、H200)的特性?

LongAct所代表的基于激活稀疏性的长上下文优化,是一条充满潜力的路径。它不像单纯扩大显存那样简单粗暴,而是试图从算法和系统层面赋予大模型处理超长序列的“智慧”。对于每一位身处降本增效压力下的工程师来说,深入理解并尝试这类技术,不仅是解决当前成本难题的钥匙,更是通往下一代高效大模型架构的必经之路。从我个人的实践来看,从一个小而美的原型开始,针对一个具体的、序列超长的业务场景进行验证和迭代,是探索这项技术最踏实的方式。