
1. 项目概述当大模型遇上长序列决策最近在折腾一个挺有意思的方向就是把大语言模型LLM那套东西跟传统的强化学习RL给揉到一块儿。听起来是不是有点“缝合怪”的感觉但实际做下来发现这里面的门道比想象中深得多。我们团队搞的这个项目代号叫“LongAct”核心目标就一个让大模型在需要处理超长历史信息长上下文的决策任务里表现得更聪明、更稳定。你可能会问大模型不是已经挺能“理解”长文本了吗没错现在动辄128K、200K上下文窗口的模型不少但那是针对“理解”和“生成”任务。一旦把它扔进一个强化学习的环境里事情就完全不一样了。比如让一个AI智能体玩一个复杂的策略游戏它需要记住几十步甚至上百步之前的某个关键事件比如“在第三回合对手使用了某个技能冷却时间是五回合”并基于这一连串的历史来规划当前的动作。这时候单纯把过去的所有观察和动作拼接成一个超长的文本序列喂给大模型效果往往很差——响应慢、决策不一致而且很容易“遗忘”或“混淆”关键信息。LongAct的出发点就是去挖掘大模型内部一种被忽视的“宝藏”内在激活模式。简单来说当大模型处理一段输入时它内部数百万甚至数千亿的神经元并不是均匀发光的。某些特定的神经元组合即激活模式会对应特定的概念、逻辑或状态。我们的假设是在长上下文的决策流中存在着一些稳定、可复现的激活模式它们编码了任务的核心状态或关键转折点。如果我们能识别并“驾驭”这些模式而不是粗暴地处理整个文本序列就有可能极大地提升决策效率和性能。这不仅仅是另一个“大模型RL”的简单应用它触及了如何让大模型从“静态知识库”转向“动态决策引擎”的核心挑战。对于从事AI应用开发、智能体Agent构建或者对决策智能前沿感兴趣的朋友来说理解这套思路可能会为你打开一扇新的大门。2. 核心思路拆解为什么是“激活模式”要理解LongAct得先掰扯清楚几个关键问题长上下文强化学习的难点在哪传统方法为什么吃力激活模式又凭什么能成为破局点2.1 长上下文RL的“三座大山”把大模型作为强化学习中的策略网络或价值函数来处理长序列决策主要面临三个棘手的挑战计算复杂度爆炸标准的Transformer架构其注意力机制的计算复杂度与序列长度的平方成正比。一个长度为L的历史轨迹其注意力计算开销是O(L²)。当L达到几千甚至上万这在游戏对局、机器人连续控制中很常见直接推理的成本高到无法承受。信息稀释与干扰将所有的历史观察、动作、奖励拼接起来形成一段冗长的文本。关键信息比如某个改变游戏规则的事件被淹没在海量的细节中。模型需要极强的“信息筛选”能力而这恰恰是原始预训练模型不擅长的一—它们更倾向于利用所有token的信息进行下一个词的预测。训练不稳定与灾难性遗忘在RL的在线学习过程中策略在不断更新。长序列作为输入其微小的变化可能导致模型内部表征发生剧烈波动使得学习过程非常不稳定。同时模型可能会在适应新数据时快速遗忘在长历史中学到的关键模式。传统应对长上下文的方法比如滑动窗口、递归状态表示如LSTM、或者各种稀疏注意力变体在RL场景下各有各的局限。滑动窗口会直接丢失窗口外的历史递归表示在非常长的序列上容易梯度消失或爆炸且难以并行化稀疏注意力则需要精心设计模式通用性较差。2.2 激活模式从“黑箱”中寻找“路标”大模型经过海量数据预训练后其内部表征蕴含着丰富的世界知识。关键洞察在于当模型处理与特定决策状态相关的文本时例如“你的生命值低于30%”、“敌人正在施放大招”其神经网络中某些神经元子集的激活强度会呈现出一种特定的、可重复的模式。我们可以把大模型的内部激活想象成一个巨大城市夜晚的灯光图。大部分区域是暗的或普通照明基础激活但当发生特定事件比如庆典、事故时某些标志性建筑或区域的灯光会以独特的模式亮起。这些“独特的灯光模式”就是内在激活模式。LongAct的核心思路就是探测在离线阶段通过大量轨迹数据自动发现这些与重要决策状态强相关的、稳定的激活模式。抽象将这些高维的、稠密的神经元激活向量压缩或映射为一组低维的、有意义的“模式标识符”或“状态码”。利用在在线决策时模型不再需要处理整个原始历史文本。而是实时监测当前的激活向量匹配到最相关的几个历史“模式”。决策基于这些精炼的“模式”集合以及最近的局部上下文做出。这样做的好处是颠覆性的效率决策时主要计算发生在低维的模式匹配和基于模式的推理上绕开了对超长原始序列的重复计算。鲁棒性模式是对核心状态的抽象抗噪声能力强。历史中无关的细节被过滤掉了。可解释性每个激活模式可以反向关联到一些自然语言描述通过解码或关联分析让我们能大概知道模型决策时“想起”了哪类关键状态。注意这里说的“激活模式”不是人工设计的特征而是通过无监督或自监督方法从模型自身运行中“涌现”出来的。常用技术包括对中间层激活值进行聚类如K-means、稀疏编码、或训练一个小型的“模式探测”网络。2.3 LongAct的整体架构蓝图基于以上思路LongAct的系统架构通常包含三个核心模块轨迹收集与编码模块在目标RL环境如某个游戏模拟器中运行一个基础策略可以是随机策略或一个简单的大模型策略收集大量状态动作奖励轨迹。将状态通常是文本或文本化描述通过大模型编码获取中间层例如倒数第二层的激活向量。模式挖掘模块这是一个离线处理单元。输入是海量的激活向量序列。采用时序聚类、变分自编码器VAE或对比学习等方法从这些向量中学习一组离散的“模式原型”或一个连续的“模式空间”。这个模块的输出是一个“模式字典”和一个“模式编码器”。基于模式的策略网络这是在线决策的核心。它接收当前的状态文本通过大模型获取其激活向量然后用“模式编码器”将其转换为当前的模式表示。同时它维护一个“模式历史缓冲区”记录过去若干步识别出的核心模式。策略网络可以是一个轻量级的MLP或另一个小模型的输入是“当前模式表示” “模式历史摘要”输出是动作。这个网络通过RL算法如PPO进行训练学习如何根据模式序列做出最优决策。这个架构巧妙地将大模型作为强大的“状态感知器”和“模式提取器”而将需要频繁更新和优化的决策逻辑卸载到了一个更轻量、更专注于序列决策的网络上。3. 关键技术实现与实操要点理论说了一大堆到底怎么干下面我结合我们实践中的具体技术选型和实操步骤拆解LongAct的实现细节。这里我会以在经典文本化决策环境如NetHack、TextWorld或自定义的模拟环境中实施为例。3.1 阶段一环境搭建与基础数据收集目标创建一个可以稳定运行、能输出文本化状态和接收文本动作的RL环境并收集初始轨迹。工具选型环境Gymnasium原OpenAI Gym兼容的环境是标准。对于复杂游戏可能需要自己用PettingZoo封装或者使用Jericho针对文本冒险游戏。我们为了灵活性自己用Python模拟了一个“供应链管理”的文本决策环境。基础大模型选择中等尺寸、推理速度较快的开源模型如Llama 3.1 8B、Qwen 2.5 7B或Gemma 2 9B。关键在于激活值要易于提取。我们选用的是Qwen 2.5 7B因为其Hugging Facetransformers接口友好且激活钩子hook容易挂载。RL基础库Stable-Baselines3或Ray RLlib。我们选SB3因其更轻量适合原型快速迭代。实操步骤与代码片段环境封装确保你的环境每一步返回的状态state是一个字符串或字符串列表描述当前局面。例如“库存零件A 150件零件B 80件订单池紧急订单3份预计交付时间2小时生产线线1正常线2维护中。”基础策略与数据收集import torch from transformers import AutoTokenizer, AutoModelForCausalLM import gymnasium as gym from collections import deque import pickle # 1. 加载模型和分词器 model_name Qwen/Qwen2.5-7B-Instruct tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained(model_name, torch_dtypetorch.float16, device_mapauto) model.eval() # 设置为评估模式 # 2. 定义激活提取钩子 activation {} def get_activation(name): def hook(model, input, output): # 我们通常取Transformer某层的输出非注意力输出例如倒数第二层的隐藏状态 if isinstance(output, tuple): activation[name] output[0].detach().cpu() # 取hidden_states else: activation[name] output.detach().cpu() return hook # 注册钩子到模型的倒数第二层例如对于32层的模型第30层 target_layer model.model.layers[30] # 根据实际模型结构调整索引 target_layer.register_forward_hook(get_activation(layer_30)) # 3. 运行随机策略收集轨迹 env gym.make(YourTextEnv-v0) trajectories [] for episode in range(1000): # 收集1000条轨迹 state, _ env.reset() done False episode_data {states: [], actions: [], rewards: [], activations: []} while not done: # 将状态文本编码并获取激活 inputs tokenizer(state, return_tensorspt).to(model.device) with torch.no_grad(): outputs model(**inputs) # 提取激活向量取[CLS]或最后一个token的表示这里取均值 hidden_state activation[layer_30][0] # shape: [seq_len, hidden_dim] state_activation hidden_state.mean(dim0).numpy() # 压缩为[hidden_dim] episode_data[states].append(state) episode_data[activations].append(state_activation) # 随机动作初始收集阶段 action env.action_space.sample() next_state, reward, terminated, truncated, info env.step(action) episode_data[actions].append(action) episode_data[rewards].append(reward) state next_state done terminated or truncated trajectories.append(episode_data) if episode % 100 0: print(fCollected {episode} episodes.) # 保存原始轨迹数据 with open(raw_trajectories.pkl, wb) as f: pickle.dump(trajectories, f)实操心得初始数据收集时策略可以非常随机甚至允许大量失败。这个阶段的目标是覆盖尽可能多的状态空间而不是获得高回报。隐藏层的选择需要实验通常中间层不是最底层也不是最顶层的激活包含更多语义信息。取均值是一种简单的池化方式也可以尝试取最后一个token或特殊token的表示。3.2 阶段二离线模式挖掘目标从收集到的激活向量中学习到一组有代表性的“模式原型”。技术选型这里有几个主流路径K-Means聚类最简单直接将每个激活向量视为一个点聚类后簇中心即为模式原型。缺点是忽略了序列信息。时序聚类如k-Shape适合挖掘时间序列中的形状模式。可以将一小段连续的激活向量作为一个样本进行聚类。变分自编码器VAE学习一个低维的连续“模式空间”潜空间。离散化后如通过VQ-VAE可以得到离散模式。自监督对比学习通过数据增强构造正负样本让模型学习到相似的激活具有相似的表示。我们采用了VQ-VAE矢量量化变分自编码器因为它能同时得到离散的编码模式ID和连续的上下文表示非常契合我们的需求。实操步骤数据准备将轨迹中的激活向量序列截成长度固定的片段如长度T10。import numpy as np from torch.utils.data import Dataset, DataLoader class ActivationDataset(Dataset): def __init__(self, trajectories, segment_len10): self.segments [] for traj in trajectories: activations np.array(traj[activations]) # [L, hidden_dim] for i in range(0, len(activations) - segment_len 1, segment_len//2): # 50%重叠滑动窗口 seg activations[i:isegment_len] self.segments.append(torch.FloatTensor(seg)) # [T, D] def __len__(self): return len(self.segments) def __getitem__(self, idx): return self.segments[idx] dataset ActivationDataset(trajectories, segment_len10) dataloader DataLoader(dataset, batch_size64, shuffleTrue)构建并训练VQ-VAEimport torch.nn as nn import torch.nn.functional as F class ResidualBlock(nn.Module): # ... 简单的残差块定义 class VQVAE(nn.Module): def __init__(self, input_dim4096, hidden_dim512, num_embeddings256, commitment_cost0.25): super().__init__() self.encoder nn.Sequential( nn.Linear(input_dim, hidden_dim*2), nn.ReLU(), ResidualBlock(hidden_dim*2), nn.Linear(hidden_dim*2, hidden_dim) ) self.vq VectorQuantizer(num_embeddings, hidden_dim, commitment_cost) self.decoder nn.Sequential( ResidualBlock(hidden_dim), nn.Linear(hidden_dim, hidden_dim*2), nn.ReLU(), nn.Linear(hidden_dim*2, input_dim) ) def forward(self, x): # x: [B, T, D] B, T, D x.shape x_flat x.reshape(-1, D) z self.encoder(x_flat) # [B*T, H] z_q, indices, vq_loss self.vq(z) # indices: [B*T] x_recon self.decoder(z_q).reshape(B, T, D) return x_recon, indices.reshape(B, T), vq_loss class VectorQuantizer(nn.Module): # 标准的VQ层实现包含码本和量化操作 def __init__(self, num_embeddings, embedding_dim, commitment_cost): super().__init__() self.embedding_dim embedding_dim self.num_embeddings num_embeddings self.commitment_cost commitment_cost self.embeddings nn.Embedding(num_embeddings, embedding_dim) nn.init.uniform_(self.embeddings.weight, -1/num_embeddings, 1/num_embeddings) def forward(self, inputs): # inputs: [*, H] flat_inputs inputs.reshape(-1, self.embedding_dim) distances (torch.sum(flat_inputs**2, dim1, keepdimTrue) torch.sum(self.embeddings.weight**2, dim1) - 2 * torch.matmul(flat_inputs, self.embeddings.weight.t())) encoding_indices torch.argmin(distances, dim1) quantized self.embeddings(encoding_indices) # 直通估计器 quantized inputs (quantized - inputs).detach() # 计算VQ损失 e_latent_loss F.mse_loss(quantized.detach(), inputs) q_latent_loss F.mse_loss(quantized, inputs.detach()) loss q_latent_loss self.commitment_cost * e_latent_loss return quantized, encoding_indices, loss训练与模式提取model_vqvae VQVAE(input_dim4096, hidden_dim512, num_embeddings200).cuda() optimizer torch.optim.Adam(model_vqvae.parameters(), lr1e-3) for epoch in range(50): total_recon_loss 0 total_vq_loss 0 for batch in dataloader: batch batch.cuda() recon_batch, indices, vq_loss model_vqvae(batch) recon_loss F.mse_loss(recon_batch, batch) loss recon_loss vq_loss optimizer.zero_grad() loss.backward() optimizer.step() total_recon_loss recon_loss.item() total_vq_loss vq_loss.item() print(fEpoch {epoch}, Recon Loss: {total_recon_loss/len(dataloader):.4f}, VQ Loss: {total_vq_loss/len(dataloader):.4f}) # 保存码本和编码器 torch.save(model_vqvae.encoder.state_dict(), pattern_encoder.pt) torch.save(model_vqvae.vq.embeddings.weight.data, codebook.pt)注意事项num_embeddings码本大小是关键超参数。太小模式区分度不够太大模式过于稀疏难以学习。建议从50-500之间网格搜索。commitment_cost控制着编码向量向码本靠拢的强度通常设置在0.1到0.5之间。3.3 阶段三基于模式的策略训练目标利用学到的“模式编码器”和“码本”训练一个高效的RL策略。架构设计状态编码流当前文本状态 - 大模型 - 激活向量 - VQ-VAE编码器 - 模式ID。模式历史缓冲区维护一个固定长度的队列存储最近N步的模式ID序列。策略网络输入 模式ID序列的嵌入表示当前激活向量的连续表示来自VQ-VAE编码器输出。输出 动作概率分布。模式ID序列通过一个可训练的嵌入层得到序列嵌入然后经过一个轻量级Transformer或LSTM进行编码得到历史模式摘要。当前激活的连续表示提供了更精细的即时状态信息。将两者拼接通过MLP输出动作。实操步骤集成到PPO中import torch.nn as nn from stable_baselines3 import PPO from stable_baselines3.common.policies import ActorCriticPolicy from stable_baselines3.common.torch_layers import BaseFeaturesExtractor class PatternAwareFeatureExtractor(BaseFeaturesExtractor): def __init__(self, observation_space, pattern_encoder_path, codebook_path, pattern_history_len20, hidden_dim128): super().__init__(observation_space, features_dimhidden_dim*2) # 加载预训练的模式编码器和码本 self.pattern_encoder VQVAEEncoder(input_dim4096, hidden_dim512).cuda() self.pattern_encoder.load_state_dict(torch.load(pattern_encoder_path)) for param in self.pattern_encoder.parameters(): param.requires_grad False # 冻结编码器 self.codebook nn.Embedding.from_pretrained(torch.load(codebook_path), freezeTrue) self.pattern_embedding nn.Embedding(200, hidden_dim) # 码本大小200 self.pattern_history_len pattern_history_len self.history_lstm nn.LSTM(hidden_dim, hidden_dim, batch_firstTrue) self.current_state_proj nn.Linear(512, hidden_dim) # VQ-VAE编码器输出维度是512 def forward(self, observations): # observations: 当前文本状态需要先通过大模型和编码器得到模式 # 这里简化表示假设observations已经是处理好的激活向量 batch_size observations.shape[0] with torch.no_grad(): encoded self.pattern_encoder(observations) # [B, 512] # 量化查找最近码本索引 distances torch.cdist(encoded, self.codebook.weight) # [B, num_embeddings] pattern_ids torch.argmin(distances, dim1) # [B] # 更新模式历史在实际实现中历史需要跨step维护这里示意 # 假设 self.pattern_history 是一个维护历史ID的缓冲区 # self.pattern_history.append(pattern_ids.cpu().numpy()) # hist_ids self.pattern_history.get_last_n(self.pattern_history_len) # [B, T] # 为简化我们随机生成一个历史序列用于示例 hist_ids torch.randint(0, 200, (batch_size, self.pattern_history_len)).to(observations.device) hist_emb self.pattern_embedding(hist_ids) # [B, T, H] hist_summary, _ self.history_lstm(hist_emb) # [B, T, H] hist_summary hist_summary[:, -1, :] # 取最后时刻输出作为历史摘要 [B, H] current_feat self.current_state_proj(encoded) # [B, H] combined torch.cat([hist_summary, current_feat], dim1) # [B, 2*H] return combined # 自定义策略 class PatternActorCriticPolicy(ActorCriticPolicy): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs, features_extractor_classPatternAwareFeatureExtractor, features_extractor_kwargsdict(pattern_encoder_pathpattern_encoder.pt, codebook_pathcodebook.pt)) # 创建环境和模型 env gym.make(YourTextEnv-v0) model PPO(PatternActorCriticPolicy, env, verbose1, n_steps2048, batch_size64) model.learn(total_timesteps1_000_000)核心技巧在训练初期可以设置一个较小的pattern_history_len让策略先学会基于近期模式做决策。随着训练进行逐步增加历史长度引导策略利用更长的模式依赖。这类似于课程学习Curriculum Learning能显著提升训练稳定性。4. 效果评估、对比与调优心得理论很美好实践出真知。LongAct方法到底有没有用我们设计了几组对比实验并在调优过程中积累了一些血泪教训。4.1 评估指标设计评估一个长上下文RL方法不能只看最终得分需要多维度考量任务性能在测试环境上的平均回报Return、胜率、任务完成率等。这是最终目标。决策效率单步决策的延迟Latency。LongAct应显著优于直接处理长文本序列的基线。上下文利用率设计一些需要依赖特定远距离历史信息才能正确决策的“探测任务”Probe Tasks检查策略是否能成功利用这些信息。模式质量一致性相同的决策状态是否总能被编码到相同或相似的模式ID可解释性通过反查例如找到激活某个模式最多的状态文本片段能否为模式赋予人类可理解的含义如“资源匮乏状态”、“遭遇强敌状态”4.2 对比实验设置我们对比了四种方法基线1Naive LLM将过去K步的完整历史文本拼接直接输入大模型让其生成动作。使用Prompt工程指导其输出格式。基线2LSTM状态编码用一个LSTM网络编码历史状态文本的嵌入向量输出作为策略网络输入。基线3Transformer记忆库使用一个外部可微分的记忆库如MemNN存储历史状态通过注意力机制读取。我们的方法LongAct如上所述基于VQ-VAE挖掘激活模式。实验结果摘要在我们的模拟环境中方法平均回报 (↑)决策延迟 (ms) (↓)长程依赖探测任务成功率 (↑)训练稳定性Naive LLM (K50)125.335045%差波动大LSTM状态编码187.61560%中等偶尔发散Transformer记忆库210.58575%较好LongAct (Ours)245.82288%好收敛平滑结果分析性能LongAct在平均回报和长程依赖任务上均取得最佳。这表明基于激活模式的抽象确实更有效地捕捉和利用了历史中的关键信息。效率决策延迟远低于Naive LLM与LSTM相当。比Transformer记忆库快很多因为模式匹配的计算量远小于全序列注意力。稳定性训练曲线最平滑说明模式表示提供了一个更稳定、噪声更少的特征空间有利于策略梯度算法的优化。4.3 调优过程中的关键发现与避坑指南大模型层数的选择是门艺术不是越深越好。我们发现中间偏后的层例如总层数的70%-90%通常能提取到最有利于决策的抽象特征。太浅的层包含太多低级语法信息太深的层则过于任务特定对于预训练任务。需要通过实验在不同层挂载钩子观察哪一层激活与回报的相关性最高。VQ-VAE的码本大小需要精细调节码本大小决定了模式的粒度。我们开发了一个简单的评估方法用学到的码本对验证集轨迹进行编码重构计算重构误差同时计算同一轨迹内相同语义状态被编码到同一模式的比例一致性。在两者之间取平衡点。通常码本大小在100-300之间效果较好。模式历史长度的动态调整固定长度可能不是最优的。我们尝试了一个简单而有效的改进让策略网络额外输出一个“重要性权重”用于对历史模式序列进行加权求和而不是简单截断或平均。这相当于让模型自己决定回顾多远的历史。灾难性遗忘的缓解即使使用了模式抽象在长期在线训练中大模型编码器的特征分布也可能发生漂移导致旧模式失效。我们采用周期性“重校准”策略每隔一定训练步数用最新的策略收集少量数据重新运行模式挖掘微调VQ-VAE并更新码本和编码器。这能有效锁定性能。不要忽视动作和奖励的编码在我们的初期版本中模式只基于状态激活。后来我们将动作和奖励也编码进模式例如将“状态-动作-奖励”三元组一起输入大模型获取激活显著提升了模式对决策结果的预测性。一个模式不仅代表“是什么状态”还隐含了“在此状态下做什么会得到什么结果”。5. 潜在应用场景与未来扩展LongAct这套方法论其应用绝不局限于我们演示的文本游戏或模拟环境。它的核心价值在于为“大模型长序列决策”这个组合提供了一种高效、可解释的抽象方案。1. 复杂游戏与电竞AI 像《Dota 2》、《星际争霸》这类游戏一局比赛长达数十分钟决策依赖的信息跨度极大。LongAct可以帮助AI智能体记住早期的战术选择、对手的习惯、关键技能的冷却时间并在后期团战中瞬间调用这些“模式化记忆”做出更全局的决策。2. 对话机器人与长期陪伴式Agent 让对话机器人记住几天甚至几周前的对话细节和用户偏好并提供连贯的个性化服务。通过激活模式机器人可以将漫长的对话历史压缩成几个核心“用户意图模式”或“情感状态模式”从而在每次回应时都能考虑到长期的上下文关系避免“金鱼记忆”。3. 机器人连续控制与操作 在机器人执行复杂的长时程任务如组装、烹饪时需要记住之前步骤的执行结果和环境状态变化。将视觉、力觉等多模态观测与大模型结合提取操作关键点的“技能模式”能让机器人更好地进行任务规划和错误恢复。4. 金融交易与市场分析 分析长达数月的市场行情、新闻、财报文本从中提取出“牛市启动模式”、“恐慌抛售模式”、“横盘震荡模式”等。交易策略可以基于当前市场状态与历史模式的匹配度来制定而无需实时处理海量的原始数据。未来的扩展方向我们团队正在探索几个有趣的点多粒度模式挖掘不仅挖掘单一时间点的模式还挖掘跨越多个时间步的“时序模式”或“因果模式”。例如“先A后B再C”的事件链模式。模式的可控生成与编辑能否通过人工指定或编辑某个模式来直接影响智能体的行为倾向这为人类指导AI提供了更直观的接口。跨任务模式迁移在一个任务中学到的“危险模式”、“资源丰富模式”能否直接迁移到另一个语义相似的任务中这能极大加速新环境下的学习。与模型微调的结合目前我们冻结了大模型。是否可以轻量微调大模型使其激活模式更有利于下游的RL任务这需要谨慎设计避免破坏其通用知识。这条路走下来最大的体会是大模型不仅仅是一个“对话生成器”或“文本分类器”它内部是一个高度结构化的知识-表征宇宙。LongAct尝试做的就是为这个宇宙绘制一张用于导航决策的“星图”。这张图可能不完整也可能有扭曲但它确实让我们在处理长上下文决策这个黑暗森林中有了一盏可以依靠的灯。