最近有一个感悟,不是 AI 编程水平差,而是步子太大
每次让 AI 写了代码后,要跑起来总是要解决很多问题,感觉代码质量很差。
但是实际上问题在于,AI 过于冒进,一次性写了太多代码,从框架到基础模块到业务流程甚至界面细节。
人就不一样,写了框架就开始在少量的骨干代码上尝试跑起来自测,并逐步解决问题。
如果人一次性写这么大量的代码,问题肯定比 AI 多更多。
xiaohack博客专注前沿科技动态与实用技术干货分享,涵盖 AI 代理、大模型应用、编程工具、文档解析、SEO 实战、自动化部署等内容,提供开源项目教程、科技资讯日报、工具使用指南,助力开发者、AI 爱好者获取前沿技术与实战经验。
每次让 AI 写了代码后,要跑起来总是要解决很多问题,感觉代码质量很差。
但是实际上问题在于,AI 过于冒进,一次性写了太多代码,从框架到基础模块到业务流程甚至界面细节。
人就不一样,写了框架就开始在少量的骨干代码上尝试跑起来自测,并逐步解决问题。
如果人一次性写这么大量的代码,问题肯定比 AI 多更多。
这是笔者之前撰写的一篇专利的技术交底书。现在这份专利已经处于公开阶段,可以免费查阅。不过经常写专利的同学都知道,正式的专利文本往往是很难直接看懂的。于是我在咨询专利接口人确定许可后,决定把我最初的专利交底书公开发表,这就是本文的内容。 实现一个游戏助手,可适用于绝大部分对局类游戏,对玩家当前以及下一步的游戏行为和操作进行持续的推荐。 该推荐方案的主要关键技术包含以下几部分: 目前一些手游推出了语音陪伴助手功能,在玩家进行对局游戏的时候,在一旁进行一些语音提示,包括但不限于以下功能: 现有技术方案一般是基于一些基础的条件逻辑触发对应的预定义话术,比如以下几种场景: 吃鸡类游戏,当玩家离开飞机机舱跳伞时,播报闲聊话术 吃鸡和 MOBA 类游戏,当玩家拿下首杀时,播报赞赏话术 吃鸡和 MOBA 类游戏,当玩家装备某武器时,播报武器对应的使用技巧 较为复杂的:MOBA 类游戏,当敌人均(或者大部分)进入团队视野时,如果本队伍成员不在敌人所在区域时,则播报需要支援的话术 使用预设条件进行触发的方案局限性在于以下几点: 对于一些较为复杂的情况,预设条件方案需要人工预先设定复杂的条件逻辑。一般而言,判断条件越复杂,则越精确、指导意义更高。但是条件越复杂,则人工投入的成本越高,而同时播报概率却更低——之所以播报概率低,是因为需要满足的条件更多、更严苛。因此,对于较为精准的话术场景而言,人力投入产出比较低。 预设条件进行触发的逻辑中,每一个具体场景的工作,换到另一个场景下几乎没有可重用的地方。比如说对于 MOBA 类游戏,针对同一个英雄所设计的预设条件和话术,换到另一个英雄就完全不可复用,需要重新设计;而对于吃鸡类游戏,针对一个地图所设计的预设条件,换到另一个地图,也需要重新投入人力进行分析、设计,重复劳动大。 以下是本技术方案的总体过程图,图中以虚线为界分为上下两部分,上半部分为在线(实时)过程,下半部分为离线过程 下文首先基于上面的总体过程图,阐述一般性的技术方案,然后再以和平精英为例子,说明一个具体的应用范例。 为实现本技术方案,我们需要将玩家在游戏对局过程中的各项相关操作、队友/敌人状态变化、对局全局参数变化等事件信息,尽可能快地实时推送出来,供本技术方案所涉及的离线和在线过程进行进一步处理。 由于实时过程依赖于离线过程所产生的数据,因此我们首先阐述离线过程方案。 实时流水数据在一整天内有峰值峰谷,不同的时间段内所需的计算资源不同。因此将实时数据尽快缓存下来,将离线过程的算力平摊到全天24小时中,可以大大降低云服务成本。 需要注意的是,实时流水数据在缓存时,需要记录该数据的发生时间,便于离线过程区分事件在整个对局过程中所处的时序位置。 一般而言,实时流水数据是较为全面的数据,在本方法中,针对实时流水数据需要进行初步清洗,这个清洗的过程需要完成以下工作: 聚合了对局数据之后,我们需要决定哪些对局是需要推送到后足进行记录的。记录的原则如下: 上面提到,我们将 “对局-用户” 数据聚合成了一次完整的对局数据,针对这个对局数据,我们可以生成一个唯一的对局 ID,在后续的逻辑中用于标识和映射用。 1. 序列矩阵生成 经过上一阶段清洗之后的离线对局数据包含了该玩家在这一个对局中各不同时间段内的具体行为,以及在各时间段和时间点中的对局状态信息。我们需要从这些信息中将所有需要用于判断玩家后续行为模式的数据抽取出来,并将这些数据进行量化。 比如玩家在不同时间点的血量、装备类别和数量、玩家坐标等等信息。这些信息均包含时间属性,因此我们可以以整个完整对局的开始时间点作为原点,组合量化后的所有数据,计算出在每一个时间片中玩家的完整状态信息。每一个已量化的状态信息就是一个列向量。 从对局开始到对局结束的所有时间片所对应的列向量,则从左到右拼接成为一个 m 行、n 列的矩阵,其中 m 等于列向量的维度,n 等于时间片的数量。假设第 n 个时间片列向量表示为 $V_{Kn}$ (V 代表 vector,下标 K 代表 keyframe,M 代表 matrix,下同)即: $$ 其中 $f_{Kmn}$ (f 代表 feature,下同)表示第 n 个时间片中的第 m 个特征值 2. 关键帧提取 获得了矩阵 $M_K$ 之后,我们可以进行关键帧提取计算。在计算之前,我们首先需要对矩阵进行一次加权计算,以调整不同特征的权重,因为不同特征的重要程度不同(W 表示 weighted,下同): $$ 其中 $W_{K}$ 是一个 $m\times m$ 的对角矩阵,对角线上的值 $w_{ii}$ 表示每一个列向量 $V_{Kj}$ 中第 $i$ 个特征 $f_{Kij}$ 的权重值。经过上述矩阵乘法,则获得加权后的矩阵 $M_{WK}$ 也可以在左乘权重之前,对矩阵以行为单位进行归一化处理。 获得了加权序列矩阵之后,我们从 $i = 2$ 开始,计算 $V_{WKi}$ 与 $V_{WKi-1}$ 两个列向量之间的余弦距离 $d_{WKi}$。将这些距离值以行向量表示,则为: $$ 由于 $d_{WKi}$ 是标量,因此 $D_{WK}$ 可以表示为一个离散曲线,曲线上的每一个极大值点,就代表一个关键帧,这就是本技术方案中 “关键帧” 的数学含义。在后文的具体例子中我们会看到一个具体的关键帧计算结果。 获得关键帧之后,我们则可以以对局 ID 为唯一键,将关键帧提取结果存储到支持 KV 的缓存系统中,便于后续使用。 3. 关键帧的物理含义 关键帧的数学含义是标量序列中的每一个极大值点,对应到游戏中,则表示基于已选择的特征空间内,玩家行为、游戏进程、对局状态中发生较大变化的点。比如说玩家的位置发生了较大改变、玩家的行为轨迹发生转变、对局进入一个全新的阶段等等。关键帧往往揭示了玩家进行下一步决策的选择,或者是提示了玩家行动的方向。下文我们在举例的时候,可以更加明显地看出来。 经过清洗之后的离线对局数据,除了用于生成用于关键帧提取的特征序列之外,另外一个作用就是用于生成用于匹配的特征向量序列。如何匹配这些特征向量,请参见后文,本小节仅说明生成该特征向量的方法。 类似地,我们需要从对局信息中提取出一系列的特征向量,生成该特征向量的方法与生成用于关键帧提取的特征序列的方法类似,也是生成一个序列矩阵,选取和量化特征向量的方法也类似。 选取这些特征之后,组成的特征向量,主要是为了表征某个对局下的玩家在每一个时间片中所处的状态,用于后续在实时过程中,将实时玩家的状态与某一个历史玩家进行匹配,从而匹配出一条关键帧序列。 生成的特征向量序列,是一个 $p\times q$ 大小的矩阵 $M_{Mp\times q}$(下标 M 代表 match,即 “匹配” 含义): $$ 其中 $V_{Mq}$ 表示时间片 q 所对应的特征向量,$f_{Mpq}$ 表示第 q 个时间片中的第 p 个特征值。 $M_{M}$ 针对时间片粒度的选择与 $M_{K}$ 可以相同也可以不同,完全取决于游戏时长、性能、游戏典型决策时间等要素进行折中选择。 得到 $M_{M}$ 之后,也需要按照实际需要,进行加权操作。但这一步就没有必要进行归一化了。加权之后的特征向量序列为: $$ 我们可以将每一个 $V_{M}$ 存入向量匹配引擎,同时在存入引擎的时候,也应将对局 ID 作为向量的属性一并存入,这样在匹配到向量之后,就可以与对局 ID 所对应的关键帧关联起来。 虽然量化特征的方法类似,但与生成用于关键帧提取的特征的选取原则上略有差异,这主要是两者的取向不同: 举个例子,在用于关键帧提取的序列中,“历史玩家击杀了敌人” 这是一个具体行为,可能会影响关键帧的计算,并且进一步影响对在线玩家的提示逻辑,因此这个事件需要纳入并且用于关键帧计算中。但是在用于匹配的特征向量中,“当前玩家击杀了敌人” 作为行为而言,就可以无需纳入特征向量的取值考量,因为用于匹配的特征向量更加重视状态,而玩家当前具体做了什么操作,只是一个时间点的事件,而不是一个有较强持续特性的状态。 当然了,如果更换一个角度,也可能有一些属性是适合纳入用于匹配的特征向量,而无需纳入关键帧提取的,比如 “玩家截至指定时间为止击杀了5个敌人”,这就很明显是一个状态信息,可以考虑纳入用于匹配的特征向量序列中;但是这又很明显不是一种行为,充其量只能从侧面体现出玩家的风格、偏好、技术等等辅助信息,因此不会计入关键帧计算的范畴中 此外,用于特征向量的序列中,相比起用于关键帧计算的序列中,可能还包含一些纯辅助用的特殊特征值,这些特征值主要是根据向量匹配引擎所能提供的功能有关。关于这一点,请参见后文示例中的 “对局时间” 特征的选取原因。 总体架构图的上半部分表示在线(实时)过程。本源上,离线和在线过程使用的数据源是一样的,都是玩家真实进行过的操作以及真实对局的其他一些状态变化,因此架构图中绘制的数据源均为 “实时流水数据”。 与离线过程不同,在线过程需要尽可能快地根据玩家信息或对局状态作出响应,因此在线过程并不会将实时流水数据进行缓存后再操作,而是获取了实时流水数据之后立刻进行数据清洗。 数据清洗的目的是将对局状态的特征向量化,这个向量也即等于当前玩家、当前对局、当前时间片的特征向量,并且需要保证该特征向量生成的算法和结构与前文 ”生成用于匹配的特征向量序列“ 完全相同,并且对于时间片粒度的选择,也应当与 $M_{M}$ 完全相同。对于实时对局中,指定时间片 $t$ 所对应的玩家特征向量,我们记为 $V_{Rt}$,其中 R 表示 real-time,特征向量的维度与 $V_M$ 相同: $$ 由于在线过程是事件驱动的逻辑,单一的事件无法完全表征玩家的对局状态,也不足以构建对局状态的特征向量,因此在在线过程中,也需要将之前计算出来的对局状态数据进行必要的缓存。在新的对局事件到达时,在线逻辑应当结合对局状态缓存和事件详情,综合计算出当前时间片的对局状态特征向量。 “当前关键帧是否有效” 和 “需要更新关键帧” 阶段的判定逻辑,与后续逻辑直接相关,因此我们暂时先跳过这个阶段,首先讲解后续逻辑之后再返回来说明。 在获取了当前时间片的对局状态特征向量 $V_{Ri}$ 之后,在这一阶段,这个特征向量也应与离线的特征向量矩阵 $M_M$ 左乘上完全相同的权重: $$ 我们可以使用 $V_{WRt}$ 在向量匹配引擎中进行匹配。匹配的原则是向量相似度,根据特征向量的选取原则,主要考虑使用余弦相似度和欧几里得距离两种算法: 匹配的时候还需要包含以下限制: 匹配虽然首先采纳向量相似度优先原则,但也可以多匹配数个或数十个特征向量,也即多匹配一些历史对局,然后从符合条件的结果中进行一定的随机选取,以提高随机性和多样性。 1. 获取关键帧序列详情 匹配到了一个历史特征向量之后,由于在特征向量的附加属性中包含了对局 ID,因此可以循此对局 ID 在 KV 缓存中获取到指定对局 ID 中已经在离线阶段中计算出来的所有关键帧数据。 获取了关键帧数据后,下一步的逻辑就是从关键帧中选取出后续需要推送给实时玩家的一个或多个关键帧。 2. 关键帧序列的截断 由于关键帧是包含了时间片属性的,时间片的定义,指的是相对于对局开始的时间偏移量。我们获取历史对局的关键帧列表之后,我们可以把所有的关键帧按时间片排序之后,分为两类: 选取关键帧的步骤,第一步是删除所有 “过去” 了的关键帧,因为这些关键帧在当前对局来说没有保存的意义。 第二步是要对 “将来” 的关键帧序列,做一个 “截断逻辑”。截断逻辑的效果,是去除 “将来” 某个时间片之后的关键帧。抛弃的原因如下: 关键帧序列所代表的一个历史玩家的行为,是一条已经发生了的、确定的时间线。但是当前对局中的用户,ta 将来的行为,是一个尚未发生的、不确定的时间线。我们基于一条历史的时间线给现实玩家进行推荐,那么玩家在未来可能会遇到以下几种需要重新推荐关键帧的情况: 跟随推荐的关键帧进行下一步行动。那么当玩家进行或完成了下一个关键帧中所列举的行为时,可能会有以下两种情况 针对情况 1 和 2.1,这属于我们前文跳过的 “当前关键帧是否有效” 和 “需要更新关键帧” 阶段逻辑,请参见下文。而针对情况 2.2,我们需要考虑的是:在玩家这条已选择的历史路线(关键帧序列)行动的前提下,这条路线到什么时间片为止,依然是适合玩家当前状态的;而到了什么时间片之后,即便玩家按照推荐采取行动,我们也应该重新给玩家匹配一条的关键帧序列。这一标准的选择因不同的游戏而异,也因应不同的游戏特性会有不同的算法。当然,也有可能完全不做 “将来” 的关键帧的截断,而完完全全地将关键帧更新的逻辑放在 “当前关键帧是否有效” 和 “需要更新关键帧” 阶段中。 3. 关键帧缓存 获得了截断后的关键帧,我们也需要缓存下来,便于下一个事件到来时的在线过程的迭代。 说明了后续的关键帧匹配逻辑之后,我们回过头来说明这一步在之前被跳过的逻辑。这两步逻辑决定了当前事件到来时,主逻辑是否需要继续往下持续到 “向玩家展示” 的步骤。 从示意图上我们可以看到,当事件到来时,更新了对局状态缓存之后,我们首先判断一下当前关键帧序列是否有效,如果关键帧序列已经无效了,那么直接开始匹配历史对局。显然,如果当前对局从来没有匹配过关键帧(推荐关键帧缓存为空),这显然是需要刷新关键帧序列的。 而第二个判断是判断当前玩家是否已经完成当前已推荐的关键帧,如果未完成,那么当前事件逻辑结束,等待下一次事件驱动;如果已经完成了,那么进入到下一个阶段的检查。 下一阶段是检查是否前进到下一个关键帧。当玩家已经完成当前关键帧的时候进行该阶段检查。如果需要前进到下一个关键帧,那么就将当前推荐的关键帧视为 “过去” 了的关键帧进行截断之后,推荐紧接着的下一个关键帧,如果不需要,那么也一样,结束当前事件逻辑,等待下一次事件。 1. 判断当前关键帧序列有效 判断当前关键帧序列,主要是进行以下条件的判断: 关键帧是带时间片属性的,如果玩家行动的进度相比关键帧而言明显落后时,需要考虑刷新关键帧序列 如果玩家的行为明显偏离关键帧所推荐的行为模式,那么有必要重新匹配关键帧序列。 如果发生了重大事件,导致之前匹配到的关键帧明显不合适,或者是大概率不再合适时,那么这个时候需要考虑刷新关键帧序列 2. 判断当前关键帧是否已实现 这一阶段主要是判断实时玩家的操作是否已经完成了关键帧中所指定的行为或目标,判断标准也因游戏而异。比如说玩家是否已经到达了目的地,或者是玩家已经将血量补满,或者是玩家已经击杀了指定目标等等。 3. 判断是否前进到下一个关键帧 当推荐关键帧序列中有下一个关键帧时,那么我们可以将当前关键帧截掉,并且将下一个关键帧推荐给用户。 如果没有下一个关键帧时,我们可以分两种情况来处理 当获得关键帧之后,我们即可以按照关键帧所代表的物理含义,或者说是所代表的在游戏中的操作,将关键帧的信息向玩家提示。提示方式不限,可以通过地图标注、语音提示、文字提示等等方式,给玩家进行提示。提示的具体手段不属于本专利的关注范围。 以和平精英为例,在进行整个系统方案的设计和开发之前,我们首先需要决定一个玩家在一个对局中的哪些信息是需要记录的。 原则上,尽可能多地包含本技术方案所需要的对局信息,包括但不限于玩家在对局的不同时刻下的以下信息: 按照上述的分类,我们可以采集玩家在不同时刻的以下信息: 当然,在实际操作中,统计信息也可以由简到繁,这也对应着一个方案从简到繁的迭代过程,因为该技术方案的另一个优点,就是不需要一开始就完成最终版,而可以随着游戏进展和社区/玩家反馈进行逐步迭代,在服务器性能与玩家体验之间逐步寻找平衡点。 还是以和平精英为例子,上述对局信息可以在早期进行简化,只记录以下信息(信息的减少并不会影响整体技术方案的完整性): 上述数据的格式可以以简单格式进行初步记录数据表如下: 从上述的记录中,我们可以看到玩家从游戏开始后一小段时间的对局信息为: 吃鸡类游戏的特点是每一局至少有一名玩家生存到最后;虽然和平精英也推出过复活/召回机制,让被击杀的玩家也有机会返回比赛,但是该对局的最终获胜者也依然大概率是所谓 “一命通关” 的,因此我们可以简单地按照以下原则进行选取: 这种情况下,一方面这是一个成功 “吃鸡” 对局,是一个好的范例;另一方面,由于玩家在整个对局中没有死亡过,因此整个序列非常完整。 而对于在整个对局中频繁出现死亡/复活事件的游戏模式(如王者荣耀),则选取标准可以参考以下原则: 前两个原则很好理解,最后一个原则主要是考虑能够尽可能产生出时间较长的行为序列。可以参考后文 ”序列的截断和更新“。 获得了历史对局记录之后,针对每一个对局,我们需要将列表化的数据,进行建模,转换为数字化的、便于计算机处理的数据。 为节省数据存储空间以及提高计算效率,我们可以对对局数据进行进一步的简化。如果认为不必要简化的话,这一步也可以跳过。 以上文完成了 “初步记录” 的数据表为例:首先我们可以发现,表中的玩家位置数据信息比较多,但是玩家的移动范围可能比较小。在这种情况下,我们可以降低玩家位置信息的精度,只取十万和万位。 其次,我们仅记录玩家的状态变化数据。这样,上文的数据表,我们可以进一步简化为: 上文历史对局数据表的第二个作用是生成用于关键帧提取的特征序列。该序列具体作用,依然是在后面再做说明,本小节说明如何使用这些数据生成用于关键帧提取的特征序列 1. 选定需要量化的状态特征 用于关键帧提取的特征序列,以及用于匹配的特征序列两者,可以是相同的,也可以是根据实际需要有所不同。比如在匹配中,包含了玩家的装备信息;而在用于关键帧提取的特征序列中,可能并不需要这些信息,那么我们在生成序列的时候,可以不包含这些信息。 在大部分情况下,用于关键帧提取的特征序列,比用于匹配的特征序列维度要小,因为后者的目的是为了尽量找到一个与实时玩家当前对局状态接近的历史对局,为了提升匹配效果和准确度,用于匹配的特征应尽可能完备;而前者是直接服务于话术生成的,如果某些特征对生成AI话术没有帮助,那么可以忽略相应的特征值。比如在用于匹配的特征中,包含了玩家装备的枪支信息;但是在生成话术中,如果没有计划针对枪支装备进行说明,因此我们可以无需将枪支信息纳入特征序列中。 反之亦然,允许部分特征信息在关键帧特征序列中是存在的,而在状态特征序列中不存在,完全视乎特征而定。 2. 状态特征量化 用于关键帧提取的状态特征量化方法,与用于匹配的状态特征量化方法相同,这里就不再赘述。 举例说明我们可能只选取玩家位置、各信号区信息、遭遇敌人的时刻、交火的时刻等数据,那么我们可以将前文的一个对局,以 JSON 的形式进一步进行简化,如以下格式为例,这是某位玩家一次完整的对局信息: 这段数据包含了玩家从游戏开始之后的以下信息: 各时间点单位均为秒。 数据看起来非常抽象,我们可以将数据可视化。同样地,我们把开车、战斗、遭遇、搜刮事件次数,以及玩家所在位置的变化值,以10秒为单位,计算该10秒内所对应的列向量。列向量包含五个维度的数据,分别为: 由于该对局最后一个事件的时间为 1980 秒,也就是 33 分钟,除以 10,可以得到 199 个分片(包括 t=0 的情况),每个分片对应一个列向量。这 199 个列向量即组成一个 5行、199列的矩阵。 矩阵可视化如下,可以大致看出事件分布的情况: 我们可以基于上述数据,构建玩家在每一个10秒分片中的状态数据。参见前文 “用于匹配的特征序列” 的 “状态特征量化” 小节,我们以类似的方法将上述六个信息,按顺序进行以下量化: 其中信号区信息不列入特征中,仅做辅助参考。 由于该对局最后一个事件的时间为 1980 秒,也就是 33 分钟,除以 10,可以得到 199 个分片(包括 t=0 的情况),每个分片对应一个列向量。这 199 个列向量即组成一个 6行、199列的矩阵。 $$ 1. 计算差分序列 在前文生成了 “关键帧提取的特征序列” 之后,我们可以知道,这个特征序列实际上是一个 6xn 的矩阵,其中 n = 对局总秒数/10+1。在本例中,我们使用余弦距离计算差分序列 $D_{WK}$,并进行 0-1 归一化后,作折线图大致如下: 肉眼可见 $\vec d$ 中有数个明显的极大值,但仍存在不少抖动,不方便程序进行提取。过滤掉较低的夹角值(< 0.3),再作三阶高斯模糊后,得到较为平缓的曲线如下: 得到明显的极大值点,这些极大值点代表了历史玩家行为发生较大变化的点,我们将这些时间点对应的 $\vec m_j$ 定义为关键帧。 将关键帧所处的位置,结合当前玩家的移动路径和信号圈变化,可以直观地在图上标记: 2. 关键帧的物理含义 具体查询前文的矩阵 $M_{keyframe}$,计算 $d_{WKj}$ 与 $d_{WKj-1}$ 的特征差异,由于 $d_{WK}$ 的维度很低且每一维度的含义非常明确,因此我们可以很简单地将该关键帧所表征的事件转换为词组的组合,可以看到关键帧所表征的物理含义: 3. 生成用于匹配的特征向量序列 参照前文清洗离线数据的方案,我们也可以计算出用于匹配的特征,与关键帧所需的维度不同,为了能够更加准确地匹配到一个历史玩家,我们可以提取历史事件中的信息,同样划分为以10秒为单位的时间片,使用以下16个数据组成一个特征向量: 从时刻 0 到结束时刻 1980 秒(上例),按照 10 秒一个时间片划分,总共 198 个特征向量。可将特征向量进行加权后写入特征匹配引擎中。权重的选取请参见下一节。 在实时对局中,客户端在实现玩家对局逻辑功能的同时,也将对局情况打包成一个个的事件(参见 “实时流水数据”)发送到路径推荐后台服务器上。这些事件是增量事件(也即表示这些事件表征玩家状态变化,而不是玩家状态本身),后台服务器组合这些增量事件,可以计算并更新玩家和对局状态,从而计算获得玩家的实时特征,格式与离线算出的 “用于匹配的特征向量序列” 相同。同样地,计算出特征向量之后,我们应该将特征向量乘以权重。 在权重的选择中,我们需要考量特征中每一项的含义。其中注意到,“对局开始时间” 特征中,是一个非常关键的特征,我们应当尽量使得匹配命中的历史特征所表征的事件,尽可能与玩家当前对局时间接近(甚至相同)。为达到此目的,该特征向量应乘以一个相对于其他特征来说极大的常量,使得在进行特征向量匹配时,时间特征成为一个接近于过滤器的特征项。 生成实时对局的特征向量之后,我们通过向量匹配引擎,基于欧几里得距离找到与该实时对局的特征向量最为相似的向量列表。从匹配到的向量列表中,我们可以查找距离最短的一个向量,或者是基于一些简单的规则选择一个向量(比如在最相似的十个向量中随机提取一个,以避免趋同性)。 获得向量之后,这个向量则表示某一个最接近玩家当前状态的历史对局的某个时间点的状态。此时,我们可以查找这个向量的属性,从而找到向量的完整对局序列矩阵 $M_{K}$。根据不同的向量匹配引擎,对局 ID 可以是作为属性保存在向量匹配引擎里的,也可能是需要从其他数据库中重新提取的信息。 前文离线过程中,我们已经计算出了关键帧,因此在实时逻辑中,我们只需要从数据库中提取并直接推送即可。 我们按照玩家所处的时间点往后找到第一个关键帧,然后给玩家进行推荐。 针对和平精英来说,信号区的变化是影响玩家下一步决策的关键因素。因此我们获取了历史对局之后,我们仅取下一个刷圈时间到来之前的关键帧列表。当玩家当前已无关键帧可推荐时,可以推荐玩家随机应变。 判断玩家是否完成了当前关键帧,只需要比对关键帧的位置,和时间即可。 刷新关键帧序列,等价于重新匹配历史对局。刷新的时机有三个: 其中信号区刷新逻辑很好判断。 而玩家来不及赶到关键帧位置,则可以简单判断当前对局的时间,是否已经到了后一个关键帧的时间。 至于最后一种:玩家偏离推荐路线的判断,我们使用了一个简单的判断逻辑: 我们在二维地图上取两个点:第一个是关键帧所在的目标点 $P_{target}$ ,第二个是给玩家发出推荐话术时,玩家所处的位置点 $P_{from}$ 。我们期望的是玩家从 $P_{from}$ 前往 $P_{target}$。我们要判断出,玩家是否正在做这个动作。在实际上,玩家几乎不可能直线往目标点跑动,那么我们要如何判断玩家的行为是否符合我们的预期,又希望能够尽量减少计算量呢?我们采用的是一个简单的椭圆法。椭圆的定义是,在一个二维平面上,所有距离两个指定的、不重合的点的距离之和为一个常量的点的集合。判断玩家所处的位置点,与 $P_{from}$ 和 $P_{target}$ 的距离之和是否等于某个常数即可。如果这个距离和小于指定的常数,那就说明玩家仍处于这两个点和该常数所表征的椭圆范围内,那么我们就视玩家仍然在前往目标点。该常数可以简单取 $P_{from}$ 和 $P_{target}$ 之间距离的两倍,也可以调整。 在我们的应用中,使用的是语音+地图标点的方法,如下图截图所示: 可以看到,在小地图中标记了一个点,这个点并不是玩家手动标记的,而是系统自动标上的。图示中标上的特征向量为: $$ 可以看到,实时对局的玩家当前还处于很早期(刚跳伞落地)、没有武器的状态. 配合语音播报即可以实现给玩家的推荐: 当然这些语言可以搭配一些人工标注功能实现更加丰富和精准的推荐,比如说图上的地点是和平精英 “科学之轮” 活动中的 “光子鸡通讯站” 边上的房子,这可以作为一个参数填充语音模板。比如语音模板为: 完整的推荐语音为: 该技术方案提供了一种应用场景:在玩家(特别是新手玩家)进行游戏时,对玩家的下一步行为进行推荐和指导,并且指出执行该行为时需要注意的其他属性。一方面,能够对玩家进行机器化的指导,另一方面又避免了用 “上帝视角” 基于对局的真实信息,对游戏作出破坏平衡性的播报以实现 “外挂” 的效果。 本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,原文发布于腾讯云开发者社区,也是本人的博客。欢迎转载,但请注明出处。 原文标题: 《分享一个专利: 一种在吃鸡游戏中模仿历史胜利玩家打法并对当前玩家进行打法推荐的方案》 发布日期: 2026-02-26 原文链接: https://cloud.tencent.com/developer/article/2631559。前言
本发明的技术关键点(欲保护点)
与本发明相近的现有技术
现有技术的技术方案
方案不足
逻辑复杂,投入产出比低
通用性不足
本技术方案的详细阐述

实时流水数据
离线过程
离线数据缓存和清洗

生成用于关键帧提取的特征序列并计算关键帧

M_{K} = M_{m\times n} = \left( V_{K1}, V_{K2}, ..., V_{Kn} \right) =
\begin{bmatrix}
f_{K11} & f_{K12} & ... & f_{K1n} \\
f_{K21} & f_{K22} & ... & f_{K2n} \\
... & ... & ... & ... \\
f_{Km1} & f_{Km2} & ... & f_{Kmn}
\end{bmatrix}
$$
M_{WK} = W_{K} \times M_{K} = \left( V_{WK1}, V_{WK2}, ..., V_{WKn} \right) =
\begin{bmatrix}
f_{WK11} & f_{WK12} & ... & f_{WK1n} \\
f_{WK21} & f_{WK22} & ... & f_{WK2n} \\
... & ... & ... & ... \\
f_{WKm1} & f_{WKm2} & ... & f_{WKmn}
\end{bmatrix}
$$
D_{WK} =
\begin{bmatrix}
0, d_{WK2}, d_{WK3}, ..., d_{WKn}
\end{bmatrix}
$$生成用于匹配的特征向量序列

M_{M} = M_{p\times q} = \left( V_{M1}, V_{M2}, ..., V_{Mq} \right) =
\begin{bmatrix}
f_{M11} & f_{M12} & ... & f_{M1q} \\
f_{M21} & f_{M22} & ... & f_{M2q} \\
... & ... & ... & ... \\
f_{Mp1} & f_{Mp2} & ... & f_{Mpq}
\end{bmatrix}
$$
M_{WM} = W_{M}\times M_{M} =
\begin{bmatrix}
f_{WM11} & f_{WM12} & ... & f_{WM1q} \\
f_{WM21} & f_{WM22} & ... & f_{WM2q} \\
... & ... & ... & ... \\
f_{WMp1} & f_{WMp2} & ... & f_{WMpq}
\end{bmatrix}
$$实时(在线)过程
在线数据清洗

V_{Rt} =
\begin{bmatrix}
f_{R1t} & f_{R2t} & ... & f_{Rpt}
\end{bmatrix}^{T}
$$匹配历史对局

V_{WRt} = W_M\times V_{Rt} =
\begin{bmatrix}
f_{WR1t} & f_{WR2t} & ... & f_{WRpt}
\end{bmatrix}^{T}
$$获取和选择关键帧

关键帧序列的刷新

向玩家提示
应用举例
实时流水数据
信息 说明 举例 玩家位置 玩家在游戏开始之后各时刻所在的地点的地图坐标 玩家血量 玩家在各时刻的血量变化 玩家行为 在和平精英中,需要统计的玩家行为包括: <br/>- 搜刮地面散落的物资,如果必要的话还需要统计玩家搜刮的一些关键物品信息,如枪支、子弹、血包等<br/>- 向敌人开火,如果命中敌人的话,还包括命中敌人与玩家本身的距离信息<br/>- 驾驶车辆(可通过上车/下车区分玩家是步行还是乘车移动) 对手状态 玩家能观测到的对手的状态 - 玩家视野中发现敌人,以及敌人的距离<br/>- 小地图上显示敌人脚步、枪声等信息。在和平精英中,这些信息还包含估算距离信息 玩家其他信息 玩家装备信息等附属属性 - 玩家装备的头盔级别(无则表示为0)、护甲级别(无则表示为0)<br/>- 玩家装备的突击步枪、冲锋枪、霰弹枪、机枪、手枪的数量<br/>- 玩家的子弹数量<br/>- 玩家的血包数量 其他信息 其他会影响玩家决策的游戏全局信息 - 对局的地图 ID<br/>- 不同时刻的信号区中心点和半径 时刻 (秒) 事件类型 事件值 0 地图 ID 0160 玩家位置 (586029, 285103)68 搜刮物资 68 拾取手枪 1 65 玩家位置 (586140, 285072)68 搜刮物资 68 拾取冲锋枪 1 70 搜刮物资 70 拾取霰弹枪 1 71 搜刮物资 72 拾取突击步枪 1 72 丢弃霰弹枪 1 75 遭遇敌人 75 玩家位置 (582271, 287956)80 遭遇敌人 81 开火 81 玩家位置 (582395, 287003)83 开火 87 玩家位置 (582627, 287037)95 开火 100 上车 112 玩家位置 (581480, 287175)120 信号区位置 (285610, 673190)122 玩家位置 (590850, 287164)... ... ... (586029, 285103) 开始游戏离线过程
样本数据选取
生成对局特征序列
时刻 (秒) 事件类型 事件值 0 地图 ID 0160 玩家位置 (58, 38)68 搜刮物资 68 装备变化 手枪+1 68 搜刮物资 68 装备变化 冲锋枪+1 70 搜刮物资 70 装备变化 霰弹枪+1 71 搜刮物资 72 装备变化 突击步枪+1, 霰弹枪-1 75 遭遇敌人 80 遭遇敌人 81 开火 83 开火 95 开火 100 上车 120 信号区位置 (28, 67)122 玩家位置 (59, 28)生成用于关键帧提取的特征序列
{"drive":[476,479,482,485,488,490,493,497,500,502,505,508,511,513,516,518,522,525,528,532,535,537,541,545,548,551,553,557,559,561,564,566,570,572,576,579,791,794,798,800,804,806,810,813,816,819,823,826,830,833,836,838,842,845,849,851,853,856,859,862,865,868,871,874,878,882,884,887,890,893,896,898,901,904,907,910,913,915,919,921,923,926,930,934,937,941,944,947,951,955,959,962,965,968,971,975,978,980,983,986,990,992,995,998,1000,1003,1006,1009,1013,1015,1018,1021,1026,1067,1069,1073,1075,1078,1081,1085,1089,1092,1096,1099,1103,1106,1108,1111,1116,1119,1122,1125,1128,1131,1134,1136,1139,1141,1144,1147,1150,1153,1156,1158,1161,1164,1166,1169,1173,1176,1348,1352,1356,1359,1362,1364,1368,1371,1373,1376,1380,1382,1386,1389,1392,1396,1398,1400,1402,1406,1409,1411,1413,1426,1430,1434,1438,1440,1443,1447,1450,1452,1456,1458,1461,1463,1466,1469,1472,1474,1479,1482,1484,1486,1489],"shoot":[154,156,157,1034,1054,1189,1191,1292,1736,1739,1760,1792,1820,1830,1926,1950,1952,1963,1964,1974,1975,1979],"robbery":[0,0,0,0,99,100,121,122,123,124,128,132,134,135,145,145,146,148,168,172,176,177,178,179,180,181,181,182,186,187,207,216,239,244,245,257,258,261,271,271,272,280,282,292,295,307,321,322,326,1506,1750,1753,1756,1766,1773,1786,1803,1863,1870,1894],"skirmish":[153,153,154,155,156,181,186,199,200,202,302,304,304,305,305,306,666,666,668,669,672,675,676,676,713,713,713,714,715,716,717,720,722,837,839,1024,1024,1027,1028,1056,1062,1074,1155,1156,1157,1159,1171,1171,1172,1173,1173,1174,1185,1187,1197,1206,1211,1212,1213,1214,1215,1239,1246,1247,1248,1248,1249,1250,1252,1252,1252,1253,1254,1255,1256,1256,1257,1258,1259,1259,1260,1260,1261,1262,1263,1264,1265,1265,1266,1267,1269,1269,1270,1279,1279,1281,1281,1283,1283,1285,1286,1287,1288,1289,1290,1290,1291,1291,1292,1293,1302,1303,1304,1305,1306,1315,1316,1317,1318,1320,1321,1323,1324,1324,1326,1347,1348,1349,1350,1350,1350,1351,1351,1351,1352,1353,1353,1353,1354,1354,1403,1404,1406,1523,1526,1527,1682,1685,1702,1711,1717,1733,1747,1756,1758,1762,1773,1781,1809,1825,1828,1829,1829,1829,1829,1835,1836,1837,1838,1838,1838,1838,1838,1841,1841,1841,1842,1842,1876,1876,1877,1878,1878,1879,1880,1912,1926,1926,1960,1962,1962,1969,1970,1971,1972,1972,1973,1973,1973,1973,1974,1974,1980],"zones":[{"xy":[69,34],"t":94},{"xy":[70,34],"t":99},{"xy":[70,33],"t":114},{"xy":[71,32],"t":153},{"xy":[70,32],"t":160},{"xy":[71,32],"t":164},{"xy":[70,32],"t":168},{"xy":[71,32],"t":173},{"xy":[70,32],"t":236},{"xy":[71,32],"t":237},{"xy":[70,32],"t":243},{"xy":[70,31],"t":244},{"xy":[70,32],"t":245},{"xy":[70,31],"t":246},{"xy":[70,32],"t":254},{"xy":[70,31],"t":279},{"xy":[70,32],"t":283},{"xy":[70,31],"t":287},{"xy":[69,31],"t":306},{"xy":[69,32],"t":317},{"xy":[70,32],"t":328},{"xy":[70,33],"t":344},{"xy":[69,33],"t":351},{"xy":[69,34],"t":376},{"xy":[68,34],"t":390},{"xy":[68,35],"t":398},{"xy":[67,35],"t":416},{"xy":[66,34],"t":446},{"xy":[65,34],"t":475},{"xy":[66,35],"t":482},{"xy":[67,35],"t":488},{"xy":[68,35],"t":490},{"xy":[67,35],"t":505},{"xy":[67,34],"t":508},{"xy":[66,34],"t":511},{"xy":[65,34],"t":516},{"xy":[65,33],"t":518},{"xy":[64,34],"t":522},{"xy":[63,34],"t":525},{"xy":[62,34],"t":535},{"xy":[61,34],"t":545},{"xy":[60,34],"t":548},{"xy":[59,33],"t":551},{"xy":[58,33],"t":553},{"xy":[57,33],"t":557},{"xy":[57,32],"t":559},{"xy":[56,32],"t":561},{"xy":[55,32],"t":566},{"xy":[54,31],"t":570},{"xy":[53,31],"t":572},{"xy":[53,32],"t":804},{"xy":[52,32],"t":806},{"xy":[51,32],"t":810},{"xy":[50,32],"t":813},{"xy":[49,31],"t":816},{"xy":[48,31],"t":819},{"xy":[48,30],"t":823},{"xy":[47,29],"t":826},{"xy":[47,28],"t":830},{"xy":[48,28],"t":833},{"xy":[48,27],"t":836},{"xy":[49,27],"t":845},{"xy":[48,26],"t":882},{"xy":[47,26],"t":887},{"xy":[47,25],"t":890},{"xy":[47,24],"t":893},{"xy":[46,23],"t":898},{"xy":[45,23],"t":901},{"xy":[44,23],"t":904},{"xy":[43,22],"t":910},{"xy":[42,22],"t":913},{"xy":[41,21],"t":915},{"xy":[40,21],"t":919},{"xy":[39,21],"t":921},{"xy":[39,22],"t":923},{"xy":[38,21],"t":926},{"xy":[37,21],"t":930},{"xy":[35,21],"t":934},{"xy":[35,20],"t":937},{"xy":[34,20],"t":941},{"xy":[34,19],"t":944},{"xy":[34,18],"t":951},{"xy":[33,18],"t":962},{"xy":[32,18],"t":968},{"xy":[31,19],"t":971},{"xy":[30,19],"t":975},{"xy":[29,19],"t":978},{"xy":[29,20],"t":990},{"xy":[28,20],"t":992},{"xy":[27,21],"t":995},{"xy":[26,21],"t":998},{"xy":[25,21],"t":1000},{"xy":[24,22],"t":1013},{"xy":[23,22],"t":1015},{"xy":[23,23],"t":1018},{"xy":[24,23],"t":1026},{"xy":[24,24],"t":1032},{"xy":[25,24],"t":1089},{"xy":[25,25],"t":1092},{"xy":[26,25],"t":1096},{"xy":[27,25],"t":1099},{"xy":[27,26],"t":1111},{"xy":[27,27],"t":1116},{"xy":[26,27],"t":1119},{"xy":[26,28],"t":1122},{"xy":[26,29],"t":1125},{"xy":[27,30],"t":1128},{"xy":[27,31],"t":1131},{"xy":[26,32],"t":1134},{"xy":[26,33],"t":1136},{"xy":[25,33],"t":1139},{"xy":[25,34],"t":1141},{"xy":[24,34],"t":1144},{"xy":[23,35],"t":1147},{"xy":[22,35],"t":1150},{"xy":[21,36],"t":1153},{"xy":[21,37],"t":1156},{"xy":[20,37],"t":1158},{"xy":[20,36],"t":1161},{"xy":[19,36],"t":1164},{"xy":[18,35],"t":1169},{"xy":[17,34],"t":1173},{"xy":[16,34],"t":1176},{"xy":[16,33],"t":1181},{"xy":[16,34],"t":1386},{"xy":[17,34],"t":1389},{"xy":[17,35],"t":1392},{"xy":[17,36],"t":1396},{"xy":[17,37],"t":1402},{"xy":[18,37],"t":1406},{"xy":[18,38],"t":1409},{"xy":[19,38],"t":1413},{"xy":[19,39],"t":1419},{"xy":[19,40],"t":1450},{"xy":[20,40],"t":1452},{"xy":[21,40],"t":1456},{"xy":[21,39],"t":1458},{"xy":[22,39],"t":1461},{"xy":[23,40],"t":1469},{"xy":[22,40],"t":1474},{"xy":[22,39],"t":1484}],"safe_zones":[{"center":{"x":297799.5,"y":253278.5},"radius":254520,"sec":120},{"center":{"x":261669.39,"y":294625.9},"radius":165438,"sec":720},{"center":{"x":235103.33,"y":365767.5},"radius":82719,"sec":1060},{"center":{"x":237436.88,"y":364939.44},"radius":41359,"sec":1300},{"center":{"x":231202.84,"y":381825.4},"radius":20679,"sec":1480},{"center":{"x":226598.3,"y":390148.88},"radius":10339,"sec":1640},{"center":{"x":223320.33,"y":393406.94},"radius":5169,"sec":1760},{"center":{"x":223549.69,"y":394897.2},"radius":2584,"sec":1880}]}

序号 说明 1 开车事件数 2 搜刮事件数 3 开枪事件数 4 遭遇事件数 5 玩家位置X坐标值,精确到100米 6 玩家位置Y坐标值,精确到100米
M_{keyframe} =
\begin{bmatrix}
0 & 0 & ... & 1 & 0 & ... & 0 \\
0 & 0 & ... & 0 & 1 & ... & 10 \\
0 & 0 & ... & 0 & 1 & ... & 5 \\
0 & 0 & ... & 5 & 3 & ... & 0 \\
0 & 0 & ... & 69 & 34 & ... & 22 \\
0 & 0 & ... & 69 & 34 & ... & 39
\end{bmatrix}
$$关键帧提取



0 - 1m30s ( 90): 搜刮 | 移动, location: 70_34
1 - 2m40s ( 160): 搜刮 | 移动, location: 70_32
2 - 5m20s ( 320): 搜刮 | 移动, location: 70_32
3 - 8m0s ( 480): 上车 | 移动, location: 67_35
4 - 8m30s ( 510): 上车 | 移动, location: 65_33
5 - 9m30s ( 570): 上车 | 移动, location: 53_31
6 - 11m50s ( 710): 遭遇敌人, location: 53_31
7 - 13m40s ( 820): 下车 | 移动, location: 47_29
8 - 15m10s ( 910): 上车 | 移动, location: 40_21
9 - 17m0s (1020): 下车 | 遭遇敌人 | 移动, location: 24_23
10 - 17m40s (1060): 上车 | 遭遇敌人, location: 24_24
11 - 19m30s (1170): 下车 | 遭遇敌人 | 移动, location: 16_34
12 - 22m40s (1360): 上车, location: 16_33
13 - 23m20s (1400): 上车 | 遭遇敌人 | 移动, location: 18_38
14 - 24m50s (1490): 下车 | 移动, location: 22_39
15 - 29m0s (1740): 遭遇敌人, location: 22_39
16 - 30m20s (1820): 战斗 | 搜刮结束 | 遭遇敌人, location: 22_39序号 说明 1 地图 ID 2 对局开始时间 (秒数) / 10 3 信号区中心X坐标值,精确到100米,即 0~79,0 代表没有信号区 4 信号区中心Y坐标值,精确到100米,即 0~79,0 代表没有信号区 5 玩家位置X坐标值,精确到100米,即 0~79 6 玩家位置Y坐标值,精确到100米,即 0~79 7 玩家在这10秒内是否驾驶车辆,0代表无,1代表有 8 玩家装备的狙击枪数 9 玩家装备的精确射手步枪数 10 玩家装备的突击步枪数 11 玩家装备的冲锋枪数 12 玩家装备的霰弹枪数 13 玩家装备的机枪数 14 玩家装备的手枪数 15 玩家装备的头盔级别,0~3,0代表无头盔,1~3分别代表一至三级头 16 玩家装备的防弹衣级别,0~3,0代表无,1~3分别代表一至三级甲 实时(在线)过程
在线数据清洗
特征向量匹配
获取和选择关键帧
关键帧序列的截断
关键帧序列的刷新
向玩家提示

V_{Rt} =
\begin{bmatrix}
49 & 18 & 42 & 39 & 36 & 42 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0
\end{bmatrix}^{T}
$$推荐往西北方向去搜刮物资。小几已经在小地图上给你标记好啦,要小心附近的敌人哦。其中 “小几” 是 “腾讯游戏知几” 虚拟人的昵称。推荐往${direction}的${location_name}去搜刮物资,小几已经在小地图上给你标记好啦,要小心附近的敌人哦,然后传入以下两个参数:direction: 西北方向location_name: 通讯站边上的房子推荐往西北方向的通讯站边上的房子去搜刮物资,小几已经在小地图上给你标记好啦,要小心附近的敌人哦技术方案产生的有益效果
![]()
2 月 28 号和同学出去吃饭,回来骑电瓶车直行时,被一辆右转的白色宝马撞了。车主把我扶到一边,说了几句就直接跑了。
第二天早上身体不舒服,我打 122 补报警,去交警大队做了笔录、交了陈述书。交警说会去查监控,但懂的都懂,别抱太大指望,小红书上一搜全是没下文的案例。我一天一个电话,今天终于回复,说因为下雨监控拍不清,只能再找找。到这儿我已经彻底不抱希望了。下雨违章拍的那么清楚,停在路口的车拍不清 hhhh 。
这也算是社会第一课吧-------当时就该立刻躺地上报警,而不是让司机就这么跑了。
3 月 1 号自己去做了 CT ,结果显示脖子轻度反弓、有水肿,医生又开了核磁。今天核磁结果出来:颈椎 3/4 隆突,妥妥的职业病。我工作到今天才刚满 2 年。CT + 核磁花了不到一千块,全自费,给自己提前查出职业病,倒也还能接受。接下来准备入手显示器支架、显示器和笔记本支架,好好护颈椎。
医生说隆突还能恢复,要是拖到突出就麻烦了,半个身子都会麻。真心提醒大家,再忙也要注意身体,别拿健康换工作。别低头玩手机,电脑架起来。觉得脖子不舒服 直接安排个核磁看看吧。
另外 提醒大家,骑车一定要带正规头盔,我这四十买的头盔,包了我两次狗头了,上次下雨天摔车也是头盔护命。
别再为冷邮件发愁了!这款 AI 代理能帮你精准锁定高意向客户,自动搞定 LinkedIn 个性化外展,让销售转化率直线飙升。
热度:🔺388
想快速爬取网站并分析 SEO?这个本地优先的工具能让你在终端或桌面应用里几秒搞定,还支持导出多种格式。
热度:🔺331
想在 Kimi 上部署一个全天候 AI 助手?OpenClaw 现已集成,让你的 AI 拥有长期记忆和个性,主动执行预定任务。
热度:🔺294
Mac 用户必备的“紧急按钮”!只需按下一个热键,就能瞬间隐藏所有窗口、静音声音,并打开预设文档,秒变工作模式。
热度:🔺264
担心在线身份泄露?这个隐私优先的平台帮你监控网络提及,设定自己的条款,还能通过身份数据获利。
热度:🔺229
视频编辑也能自动化!这款工具像 Zapier 一样,用节点画布设置工作流,从粗剪到动态图形一键搞定。
热度:🔺169
开发者福音!这款开源工具能智能清理 Claude Code 和 Codex 的终端输出,去除格式杂物,让代码更干净易读。
热度:🔺153
让 AI 语音助手更“有戏”!这个模式能根据语境调整语调、时机和情感,让人机对话几乎以假乱真。
热度:🔺139
AI 代理也有自己的社交网络了!这个平台像 LinkedIn 一样,让个人和企业代理互动、发帖,人类只能旁观。
热度:🔺135
数据决策太麻烦?用这个工具直接对话提问,AI 帮你分析广告和商业数据,给出清晰可行的答案。
热度:🔺127
以后会不会就像电影里面演的出现,守旧派,与 AI 派
守旧派保持手搓,输入我们的思考逻辑,ai 辅助生成
ai 派认为 Ai 能干所有的事情,不需要我们干预,只需要发出简单的指令,就可以帮我们思考,帮我们做事情
频率可能也就平均每周一次,单次 50 公里
家里首辆车,只考虑油车或者纯电 SUV
在必须买车的情况下,还适合买电车吗
作者:延枚 继《项目管理篇》之后,本文将介绍如何通过阿里云云效 MCP 提升日常代码管理的效率。传统的 Git 命令行操作将被自然语言交互所取代,大幅降低代码管理的学习成本和操作复杂度。 休假回来,你刚打开电脑准备开工: 这些琐碎的代码管理工作,是不是每天都在消耗你的时间和耐心? 现在通过云效 MCP Server 可以轻松实现用自然语言管理代码仓库了。 云效 MCP 将 Git 操作从命令行界面升级为自然语言交互: 目前支持的代码管理功能: 将这些能力集成到常用 AI 工具(通义灵码、Qoder、Cursor、Iflow-Cli)中,即可实现智能化的代码管理。 选择并准备以下 AI 工具之一: 按照云效 MCP Server 文档完成配置,主要包括 Token 和组织信息。 配置文档:GitHub - alibabacloud-devops-mcp-server (https://github.com/aliyun/alibabacloud-devops-mcp-server/blob/master/README.zh-cn.md) 配置完成后,AI 工具将能够通过 MCP 协议调用云效的代码仓库、分支、合并请求等接口。 配置完成后,建议通过以下测试验证配置是否成功: 输入: 接口调通,组织 ID、用户 ID 等信息一目了然。 输入: 你有权限访问的所有仓库,名称、ID、访问地址等全部展示出来。 示例输入: 系统将精准定位到目标仓库。 注意:后续示例均以 在实际开发中的典型应用: 输入: 系统将返回仓库的名称、ID、访问地址、默认分支、最新提交信息等完整信息,便于快速了解仓库状态。 输入: 系统将列出所有分支及其最近更新时间和提交者信息,方便了解当前并行开发的功能。 输入: 系统将识别所有功能分支的活跃状态,辅助进行代码清理决策。 团队通常需要遵循分支命名规范: 传统的分支创建流程包括: 1. 2. 3. 4. 这个过程需要多步操作,容易出错且效率低下。 输入: 系统将自动完成分支创建,包括命名规范和基线分支的设置,大幅减少手动命令操作。 输入: AI 将自动查询需求标题,生成符合规范的分支名称(如 feature/QAAB-5-user-login),实现需求与代码的自动关联。 输入: 系统将批量创建分支,保证命名规范的一致性,在迭代开始前快速完成准备工作。 时间长了,仓库里总会有一堆“僵尸分支”。 输入: AI 把沉睡的分支全找出来,还贴心地告诉你能不能删、为什么能删。确认后一句话批量清理,仓库瞬间清爽,再也不用担心分支太多找不到了。 AI 会帮你一键清理! 输入: AI 将分析目录结构并描述各模块功能,帮助开发者快速掌握项目架构。 输入: AI 将读取并分析文件内容,提供功能总结和接口说明,无需克隆代码即可在线阅读。 输入: AI 将扫描目录、定位相关文件,并总结各接口功能,提供快速的接口文档。 在实际开发中,经常需要进行一些小型修改:更新配置文件、添加日志、删除示例文件等。 传统流程需要: 这个过程对于简单修改显得过于繁琐。 输入: AI 一气呆成:读文件、改内容、建分支、提交代码、展示 diff、发 MR。你只需要最后点个“确认合并”。改个配置从 10 分钟压缩到 30 秒。 输入: AI 将读取代码、生成文档、创建文件、发起 MR,实现文档与代码的自动同步。 输入: AI 将扫描、分析、提供建议,待确认后自动删除并发起 MR,确保操作安全。 注意:所有修改均通过“新分支 + MR”流程,不直接修改默认分支,确保代码安全与 Review 流程的完整性。 创建 MR 的传统流程: Code Review 需要逼个文件查看、添加评论、跟踪问题解决状态。 输入: MR 将自动创建完成,需求自动关联,并返回 MR 链接。 输入: AI 将自动分类整理 MR,便于快速了解项目当前的合并请求状态。 输入: AI 将分析所有代码变更,生成结构化评审意见(改动总结、风险点、边界场景、测试建议),并自动添加到 MR 评论中。 输入: AI 将精确定位到指定行添加评论,实现针对特定代码行的精准反馈。 输入: AI 将自动整理未解决评论并按文件分组,生成待办清单。 或者批量更新状态:“将 MR #12 中已经完成修改的评论标记为已解决,并在每条评论下补充一句说明修改方式”,AI 将自动更新状态并添加说明。 输入: AI 将进行对比分析,生成结构化报告:模块变更统计、代码行数变化、潜在风险点。 输入: AI 将对比两个 commit,提取关键改动并评估风险,辅助快速定位问题原因。 输入: AI 将追溯文件历史,生成文件演进时间线,便于快速定位问题和理解代码演进。 除了基础场景,云效 MCP 还支持更多高级应用。 输入: AI 将统计提交数据、分析开发节奏、识别潜在问题并提供优化建议,为团队管理提供数据支持。 输入: AI 将自动完成发布分支创建、功能筛选、Release Notes 生成等完整发布流程。 输入: AI 会做: 知识管理利器!再也不怕“某个模块只有一个人懂”! 输入: AI 会做: 架构神器!快速找出“不稳定”的代码! 通过云效 MCP,代码管理工作将实现以下转变: 从命令行到自然语言 无需记忆复杂的 Git 命令,通过自然语言即可完成操作。 从手动操作到自动化 仓库查询、分支管理、MR 创建、Code Review 等流程实现自动化。 从事务性工作到核心价值 将时间投入到架构设计、核心逻辑和技术创新,而非被琐碎的工具操作所困。 云效 MCP 就像是给你的 Git 操作装上了“智能外骨骼”: 后端、前端、架构师、TL 来说,这都是一个值得尝试的效率神器! 后续计划: 敬请期待。每个程序员都遇到过的痛
云效 MCP 的核心能力
环境准备
第一步:选择 AI 工具
第二步:配置云效 MCP Server
配置验证
测试 1:查看组织信息
查看云效当前的组织信息测试 2:看看我的代码仓库
列出我在当前组织下可访问的代码仓库
在当前组织中,帮我查找名称包含 spring-boot-check-code 的代码仓库spring-boot-check-code 仓库为例,实际使用时可替换为自己的仓库名称。场景一:我的仓库有哪些分支?
应用场景
解决方案
场景 1:查看某个仓库的基本信息
在当前组织中,找到名称包含 spring-boot-check-code 的代码仓库,并展示该仓库的基本信息和默认分支
场景 2:总览所有分支
查看 spring-boot-check-code 仓库当前有哪些分支,按更新时间倒序排列场景 3:找特定前缀的分支
在 spring-boot-check-code 仓库中,找出所有以 feature/ 开头的分支,并统计每个分支最近一次提交时间
场景二:按规范自动创建分支
应用场景
feature/、bugfix/、release/ 等。git checkout mastergit pull origin mastergit checkout -b feature/user-login-202502git push -u origin feature/user-login-202502解决方案
场景 1:按规范创建功能分支
在 spring-boot-check-code 仓库中,基于 master 分支创建一个新的功能分支:feature/user-login-202502场景 2:根据需求自动创建分支
根据 QAAB-5 这个需求,在 spring-boot-check-code 仓库中创建对应开发分支,命名规则为:feature/QAAB-5-<简要描述>场景 3:批量为需求创建分支
为 bowentestmcp 项目中状态为「待开发」的高优先级需求,在 spring-boot-check-code 代码仓库中批量创建对应功能分支,命名规则:feature/<需求ID>-<英文缩写>场景 4:清理废弃分支
在 spring-boot-check-code 仓库中,找出半年内没有任何提交的 feature/ 分支,列出清单并给出是否建议删除的理由
场景三:代码浏览与仓库结构理解
应用场景
解决方案
场景 1:理解仓库结构
请查看 spring-boot-check-code 仓库在 master 分支上的目录结构,列出 src 目录下的主要模块和它们的职责
场景 2:阅读关键文件
在 spring-boot-check-code 仓库的 master 分支中,读取 /src/main/java/com/example/UserService.java 文件,并帮我总结核心功能和关键接口场景 3:定位相关代码
在 spring-boot-check-code 仓库中,帮我查找所有与「登录」相关的后端接口定义文件,并简单说明每个接口的作用场景四:轻量级代码修改与文件管理
应用场景
解决方案
场景 1:修改配置文件
在 spring-boot-check-code 仓库的 master 分支中,找到 application.properties,添加一行 name=bowen,并展示修改前后的差异,最后以新的分支 + MR 方式提交
场景 2:新建文档文件
在 spring-boot-check-code 仓库中新建示例接口文档:/docs/api/login-api.md,内容由你根据现有登录接口自动生成,并通过 MR 提交场景 3:安全删除废弃文件
检查 spring-boot-check-code 仓库中是否存在明显废弃的 demo 文件(例如 demo/ 目录下),列出清单并给出是否建议删除的说明。如果我确认同意,请在新分支上删除这些文件并提交 MR场景五:合并请求与代码评审
应用场景
解决方案
场景 1:发起标准 MR
为 spring-boot-check-code 仓库中的 feature/user-login-202502 分支创建合并请求,目标分支为 master,标题为「feat: 用户登录功能」,并关联 QAAB-5 这个需求场景 2:查看当前所有 MR
查看 spring-boot-check-code 仓库中当前打开的所有合并请求,按更新时间倒序排列,并帮我归类:功能开发 / Bug 修复 / 配置变更场景 3:AI 辅助代码评审
请对 bowentestmcp 仓库中编号为 12 的合并请求进行代码评审:总结本次改动的核心内容、指出可能的风险点和边界场景、列出需要开发补充的测试用例建议、将整体评审意见以评论形式写入该 MR场景 4:行内评论
在 bowentestmcp 仓库的 MR #12 中,对 login-service.js 中的第 120 行添加行内评论:「这里需要补充对异常场景的处理,例如第三方登录接口超时的情况」场景 5:管理评论状态
列出 spring-boot-check-code 仓库中 MR #12 所有未解决的行内评论,按文件和行号汇总,帮助我生成一份待修改清单场景六:版本对比与变更追踪
应用场景
解决方案
场景 1:分支差异分析
对比 spring-boot-check-code 仓库中 feature/user-login-202502 与 master 分支的差异:按模块统计变更文件数、汇总新增/删除/修改的行数、指出可能影响性能或安全的改动
场景 2:对比两个提交
在 spring-boot-check-code 仓库中,对比提交 a1b2c3d 和 f4e5g6h:总结主要改动内容、列出和用户登录逻辑相关的代码变更、判断是否存在潜在的兼容性风险场景 3:文件演进历史
请帮我梳理 spring-boot-check-code 仓库中 /src/login/login-service.js 这个文件最近 10 次变更:每次变更的 Commit ID/作者/时间、摘要描述、主要改动点场景七:进阶应用探索
应用 1:团队开发节奏分析
分析 spring-boot-check-code 仓库最近两周的提交情况:每天的 Commit 数量、不同模块的变更分布、主要贡献者、判断当前开发节奏是否健康,并给出建议应用 2:发布分支自动化
为 spring-boot-check-code 仓库创建 v2.0.0 发布分支:基于 master 创建 release/v2.0.0 分支、找出所有标记为 ready-for-release 标签的已合并 MR、汇总这些 MR 的变更内容、生成 CHANGELOG.md(包含新功能、Bug修复、Breaking Changes、贡献者)、创建 MR 将 release 分支合并回 master玩法 3:代码知识图谱
分析 spring-boot-check-code 仓库的代码知识分布:
1. 统计最近 6 个月每个开发者对各模块的贡献度
2. 识别每个模块的核心负责人(提交数最多)
3. 分析模块间的依赖关系(通过 import 分析)
4. 生成可视化的代码知识图谱
5. 标注高风险模块(单一负责人依赖)玩法 4:代码演进分析
分析 spring-boot-check-code 仓库中 HelloController.java 的演进历史:
1. 列出该文件最近 20 次提交记录
2. 对比每次提交的代码变化
3. 统计:
- 该文件被修改的频率(每月平均次数)
- 主要修改者及其贡献占比
- 代码行数变化趋势
- 复杂度变化趋势4. 识别是否有大规模重构
5. 判断该文件是否为"热点文件"(变更频繁可能意味着设计不稳定)
6. 给出优化建议总结:从工具操作到智能协作
使用建议
用大模型写的屎山代码,人是很难改动的。
意味着以后也只能依赖大模型来帮你出错、重构。。。
常看影视剧的朋友对「失忆」这个桥段不会陌生。尤其在催泪的韩剧里,失忆和车祸、绝症并称为三件套,成了标配的剧情套路。现实中,这些失忆到底常不常见,又是什么原因造成的呢?这篇文章就来盘一盘经典影视剧里的常见「失忆」类型,顺道补充一些相关的脑科学知识,帮助大家下次再看到类似作品,迅速给出犀利的影视锐评。
为了更好的阅读体验,欢迎大家提前阅读:《你真的是记性不好吗?关于记忆和遗忘的常见误区》,对短时记忆(工作记忆)、长时记忆的工作原理进行简单的了解和回顾。
这是影视作品里最常见到的一类失忆。
主人公通常在遭遇车祸、被重物砸头、滚下楼梯或跌落山崖、被人暴打等一系列头部物理伤害后,陷入昏迷。下一个画面,他从病房中醒来,一边摸着头上的纱布,一脸茫然地看着身旁关切的人,发出灵魂拷问:我是谁?我为什么会在这里?你们是谁?到底发生了什么?看到这里,我们闭着眼都知道,后面的主线剧情就是主角把真爱当路人,把仇人当好人,兜兜转转再爱一回的故事(bushi)。
现实中,全盘性的失忆是相当罕见的,不过这种病例确实存在,叫作「分离性遗忘症」或「解离性遗忘症」。
我们会发现,主角通常会忘记自己是谁、父母和爱人是谁,这些都是情景记忆,更准确地说,叫自传体记忆1。解离性遗忘症确实会影响患者对个人身份的认知,但智力和生活技能基本不受影响。所以主人公醒来后眼神清澈、对答如流,只是不认识自己和亲友——实在要这么编,科学上倒也说得通。
实际上,这类剧情最大的科学硬伤,在于疾病的触发机制。现实中解离性遗忘是典型的心因性疾病,而不是器质性损伤。换句话说,真正的解离性遗忘是大脑的一种防御机制,它通常是由极度的心理创伤引发。特别是遭遇了严重暴力、性侵、战争大屠杀或极端自然灾害的幸存者,由于现实过于残酷,难以承受巨大的痛苦,大脑为了保护主人,干脆把我这个概念连同痛苦的记忆一起剥离掉了。
此外,即便出现遗忘,现实中的患者更多表现为局部性遗忘,比如忘了被虐待的那段时间的经历,或是不记得亲人惨死的事实,而不是像电视剧主角那样,动辄把前半生几十年的回忆,连同自己名字、父母忘得干干净净。真是忘得那么彻底,多半是严重的精神障碍,不是再来一个车祸、再摔一跤就能恢复正常的。

心理学上「解离」是一个非常核心的概念。简单来说,它是一种意识和现实脱离的状态。比如像生活中的走神、发呆,就可以看作是一次微型的解离。压力增大时,有些人会产生疏离感,感觉周围的世界很不真实,或者感觉身体不是自己的,像看电影一样看着当下的自己。情况更严重的话,还有可能出现刚刚讲到的解离性遗忘,或是出现解离性身份障碍,也就是通常所说的「多重人格」:大脑为了分担痛苦,把意识拆分成了好几个人格,通常也是由创伤所致。
这里还要提一个更戏剧性的概念,叫「解离性漫游」,它是解离性遗忘一种罕见的亚型。现实中,患者会突然离开熟悉的环境,进行无计划和目的的漫游。这个过程中他的神志是清醒的,能生活自理、还能和人正常交往,但无法回忆起过去,结束后也想不起来漫游的经历,整个过程就像是一场醒着的梦游。好消息是,这种失忆通常可逆,结束后患者很快就会恢复记忆。而漫游这个行为也常被用在影视作品里:主角不仅失忆了,还跑到另一个城市,换了个名字,建立了一个新身份。作为一个逻辑强迫症,每每看到这种剧情总忍不住吐槽:人丢了家里人不报警吗?自己不知道自己是谁,不去看医生吗?!为什么永远只想着谈恋爱!
如果一个人现实中遭遇了车祸,或是在拳击场上受了伤,引发了剧烈脑震荡,醒来后的真实画风是什么样的呢?对此有一个专门的术语,叫创伤后遗忘,通常表现为一段几分钟到几小时的记忆真空。患者不仅记不起撞击发生的那一瞬间发生了什么,甚至连事故发生前后的一段时间都完全没印象。而且这段记忆缺失通常是永久的,是无法恢复的。
为什么会出现这样的情况?这就要引出大脑里的一个重要部位——海马体。

很多人都知道海马体和记忆有关,但极容易产生一个误解,认为它就是大脑储存记忆的地方。实际上,海马体更像是电脑的内存条。它的核心工作不是储存记忆,而是负责对记忆进行加工和转存。无论是经历一件事、还是记住一个知识点,这些信息都会先暂存成短时记忆,然后经过海马体的整理和编码后,再被上传到大脑皮层的不同区域,保存为长时记忆。这个环节叫作「记忆巩固」。
然而,海马体有一个致命的弱点:它非常娇气,对缺氧和震荡极度敏感。当剧烈的脑震荡发生时,海马体会暂停工作,处于宕机的状态。所以,在事故发生的瞬间,虽然当事人看到了刺眼的车灯、听到了周围人的尖叫,但这些信息在进入短时记忆后,由于海马体不能正常工作,无法进一步地加工和转存。甚至连事故发生前几分钟、还在海马体里排队等待保存的记忆,也会随之烟消云散,永远消失不见。这就好比写文档时突然断电,后面再怎么重启电脑,之前没保存的几行字也是找不回来的。

这种以事故或疾病的发生时间为界,记不住之前发生的事,叫作「逆行性遗忘」。前面讲的解离性遗忘症同属于逆行性遗忘,不过遗忘的时间跨度比脑震荡大得多,发病机制也不一样。与之相对的叫作「顺行性遗忘」,指患者之后无法形成新的记忆,记不住事故发生后的一切。
其实,对于脑震荡患者来说,不仅会发生逆行性遗忘,更让人感到恐慌的是顺行性遗忘,也就是醒来后长达几分钟甚至几小时的「短时失忆」。车祸明明过去了,患者也醒了,能说话,却记不住新近发生的事情:或是反复追问车祸的情况,或是对医生的医嘱转头就忘。这不得不让人担心,大脑是不是出了什么问题。
之所以会这样,是因为大脑虽然清醒了,但海马体的功能还没完全恢复。此时的大脑仍处于内存条失灵、短时记忆无法存储到长时记忆的异常状态。不过好消息是,这种顺行性遗忘通常是功能性的、暂时的。对于大多数脑震荡患者,只要静养几个小时,海马体就会重新上线,记忆录入功能也会随之恢复正常。如果超过 24 小时患者还记不住新事情,就不再被视为简单的脑震荡,也就是轻度颅脑损伤,还可能涉及中重度的颅脑损伤。这意味着大脑结构可能出现了实质性的破坏,比如出血或挫伤,情况就要严重多了。

推荐指数:⭐️⭐️⭐️⭐️⭐️
悬疑影视经典,豆瓣 Top250,多说一句都容易剧透。小李子饰演的主角泰迪,以一个联邦探员的身份来孤岛上查案。随着剧情深入,真相出现反转。教科书级别的悬疑作品,科学性强,非常值得一看。
推荐指数:⭐️⭐️⭐️⭐️⭐️
马特·达蒙主演。主角背部中枪,被人从海上救起,完全不知道自己是谁,但拥有一身顶级的格斗和语言技能。故事里的失忆主要是为了制造悬疑,不过多少兼顾了科学性,设定为物理创伤和心理创伤的共同作用。剧情不烧脑,还特别好看,尤其第 1-3 部,部部强推。
推荐指数:⭐️⭐️⭐️⭐️
富士台 97 年水曜剧场作品。木村拓哉每集一套 Gucci 高定西装,大尺度的裸露镜头,颇有深夜剧的气质。后因震惊日本的蝴蝶刀事件遭禁,多了一层神秘色彩。黑色幽默单元剧,描写了各种社会的边缘人物,主人公失忆原因最终揭晓,也融入了一些心因性的线索设定,好评!

推荐指数:⭐️⭐️⭐️⭐️
早期柯南剧场版经典。小兰因亲眼目睹凶手射杀佐藤警官,出于强烈的自责和心理创伤,引发了心因性失忆,醒来后连父母和新一都不记得了。虽说失忆设定有戏剧性夸张,但小兰醒来后,医生立刻测试了小兰的语义记忆(5 乘 8、美国的首都是哪里)和程序记忆(是否会用圆珠笔),剧情非常细节。比起后来的剧场版中,柯南用充气足球逼停高速列车、制造雪崩来挡住水库决堤等「炸裂柯学设定」,这一部真的是值得不断回味的佳作。
推荐指数:⭐️⭐️⭐️
车祸失忆虐恋鼻祖,催泪指数五颗星。裴勇俊扮演的男主在去见女主的路上遭遇车祸,醒来后彻底失忆。直到后来再遭遇车祸,又恢复了记忆。故事中失忆桥段的设计,只是为了改变主角身份,制造剧情冲突。至于失忆情节的科学性,大可忽略不计,看颜+跟哭就完事。同类韩剧还有《天国的阶梯》《最后之舞》《拥抱太阳的月亮》等,失忆题材的作品不胜枚举。
推荐指数:⭐️
霸道总裁剧祖师爷。明道饰演的大公司继承人失忆后,换了名字,变成淳朴村民,最后爱上村里的欢喜冤家女主。还是同样的配方,同样的味道,甚至有豆友说是大幅抄袭了《最后之舞》。这种童年时代看过的偶像剧,长大了多看一集都会怀疑自己年轻时的智商和审美。推荐给有年岁的朋友重温青葱岁月(狗头)。
另一种常出现在影视剧中的失忆,是不断地「记忆重启」。
在诺兰的烧脑电影《记忆碎片》中,主人公就患上了罕见的记忆丧失症,只能记住十几分钟内的事情。为了给死去的妻子报仇,他需要调用手头上的一切东西来保存记忆,收集线索,调查难度比普通人难上无数倍,也因此极大地增加了剧作的紧张感。
除了以「分钟」为单位的记忆重启设定外,还有一类设定是主人公的记忆会随着每一次睡眠重启,也就是以「天」为单位。这样一来,每一次醒来对他来说,都无异于一次新生,要提前准备各种线索让自己知道:我现在处于什么情况、之前发生了什么、未来要做什么等。
真实世界中,前一种设定,也就是短时间不断发生的记忆丧失更符合科学事实。
科学史上,有一个被写进教科书的经典案例 H.M.,真名叫亨利·莫莱森,他就是一个不断记忆重启的研究范本:27 岁那年,为了治疗严重的癫痫,医生切除了亨利的双侧颞叶内侧区域,包括海马体及周边、杏仁核等多个部位。手术后他的智力、性格完全正常,但记忆出现了严重的、不可挽回的永久性损伤。

首先,亨利再也无法长时间记住手术后的任何事情。换言之,他的情景记忆和语义记忆遭受了毁灭性打击,这是典型的顺行性遗忘。
比如,他可以和来访者做一些简单的你问我答,只要过程没有被打断,就可以一直持续下去。不过,只要对方出门转个身再回来,或是对话中途被他人打断,亨利就会完全忘记之前对话的全部内容。之所以会出现这种情况,和上篇文章讲到的短时记忆(工作记忆)原理息息相关。
亨利的海马体被摘除后,无法再形成任何长时记忆,只能靠短时记忆和注意力,在大脑中像传接力棒一样,把正在做的事、说的话不断延续下去。但这种状态非常脆弱,一旦注意力被打断——转头看着窗外、有人插话、或者上个厕所,大脑的缓存就会瞬间清空,刚才的谈话内容,甚至是眼前这个人是谁的信息都会立刻消失无踪。哪怕是术后追踪了他多年的研究员,每次走进房间,亨利仍会像对待陌生人一样,礼貌地问:「您好,我们是第一次见面吗?」

因此,亨利的时间永远定格在了当下,再也没有昨天和明天。在他的自我认知时钟里,永远停留在 27 岁。如果让亨利照照镜子,看到满头白发的老人,他会感到非常困惑,但是一转头,他又会转瞬忘记这个令人吃惊的发现,重新恢复平静。
其次,亨利不仅记不住新的事情,还丢失了一部分手术前的记忆,出现了一定程度的逆行性遗忘。研究人员在后来的随访中发现,亨利对手术前 10 年内发生的事情几乎毫无印象,但对自己十岁以前,也就是更早期的童年岁月却记忆犹新。
为了解释这个反常的现象,研究者得出进一步的结论:长时记忆不是一步存储到位的,它需要一个漫长的巩固过程,可能长达几年到十年。最初几年,记忆虽然在大脑皮层留下了存档,但必须通过海马体的协助才能提取出来,一旦海马体受损,未完全固化的记忆就会因为失去索引而无法读取,随之丧失。而更久远的记忆则安全地储存在了大脑皮层里,所以即便切除了海马体,亨利还是会牢牢记住自己是谁、父母是谁这些根深蒂固的基础事实。

不过,最令科学家震惊的是,尽管亨利无法记住新的知识,但他仍能学会一些新的技能。科学家曾让亨利做过一个镜像绘画实验:看着镜子里的倒影,描画一个双轮廓的五角星。这个操作并不简单,一开始亨利画得歪歪扭扭,但随着练习次数增加,他画得越来越好,熟练度突飞猛进。有意思的是:尽管能轻松地画出完美的五角星,但亨利却完全不记得自己曾经练习过。他会惊讶地说:「真奇怪,这比我想得要容易。」
正是基于对亨利的研究,科学家才意识到大脑有不同的记忆系统,它们是分工明确的:尽管负责处理语义和情景记忆的海马体彻底罢工了,但负责技能的基底核和小脑依然在正常工作,后者就是我们如今所说的程序记忆,俗称为肌肉记忆。

稍显欣慰的是,亨利虽然终身与记忆损伤相伴,但他真正成为了一个「活着当下」的人,过着平静的生活。这和亨利天生的性情有关,也和手术切除了杏仁核让他失去了产生焦虑和恐惧的生理基础有关。生活中,他会帮着家人做些家务,准备午餐、铺床、陪家人买东西、玩填字游戏,和人聊天,也会看电视放松。虽然他的意识停留在 27 岁,但他的身体依然在岁月中学会了如何照顾自己,在每个崭新的当下中地活到了 82 岁高龄。
所以,在真实的器质性脑损伤中,遗忘一般不是按天计算,而是随时随地发生的。
除了亨利·莫莱森,另一位著名的失忆症患者,要属剑桥大学的音乐家克莱夫·韦尔林。他的海马体因为疱疹性脑炎感染出现不可逆的损伤,导致记忆只能保持短短的 7 秒到 30 秒,可谓是字面义上的「金鱼记忆」。对克莱夫来说,由于记不起前几秒刚发生的事情,他每分每秒都在体验着刚刚醒来、一无所知的噩梦。他的妻子在回忆录中写到:
克莱夫一直处于刚刚从无意识中清醒的印象中。他曾说过:我没听过,没看过,没摸过也没闻过任何东西,就像是死了一样。他的日记读起来让人非常绝望:
下午 2 点:我第一次醒来。
下午 2 点 14 分:我现在有意识了。
下午 2 点 19 分:刚刚起来。
……
与这些真实案例相比,影视剧中那种「白天清醒,只有睡觉才会导致记忆清零」的设定,科学上其实很难成立。
如果海马体严重受损,人就不可能仅靠短时记忆维持一整天的经历。更合理的推测是:这些记忆在清醒时已经进入海马体,完成了初步编码,而问题出在后续的稳定过程。这恰恰说明海马体是能够工作的,起码参与了记忆的形成。既然如此,为什么这些已经形成的记忆会在睡眠后难以稳定保存,或是在醒来时无法顺利提取,这才是真正费解的地方。

不过,影视创作并非完全凭空想象。现实中确实存在和这种设定相似的个案,例如英国女性Michelle Philpots,她先后经历两次车祸,脑部损伤并伴随癫痫发作,此后记忆能力明显恶化。她的长期记忆停留在 1990 年代,而此后形成的新记忆维持时间很短,需要依赖便签、录像和丈夫的提醒来维持日常生活。媒体常将这种状态描述为「每日重启的人生」,但从医学角度看,这并非真正意义上的每日记忆重置,而更像是新记忆难以长期稳定保存。经典爱情电影《初恋 50 次》中「每天醒来记忆归零」的设定,或许就是受到了这个真实案例的启发。
需要强调的是,现实中这类遗忘极度罕见,甚至在神经科学界也存在争议。目前一种比较合理的解释是:这是由「记忆巩固」失败导致的。研究发现,记忆从不稳定的海马体向长期稳定的大脑皮层转移,主要发生在睡眠阶段。如果患者伴随严重的夜间癫痫,异常脑电波可能会干扰这个存档过程,从而导致记忆无法长期固化,或在醒来后难以提取。
所以,这种类型的剧情设定,虽然有现实原型,但更多是电影为了戏剧冲突而做的艺术加工,切勿将其作为普遍的医学常识。

推荐指数:⭐️⭐️⭐️⭐️⭐️
诺兰封神之作,绝对烧脑经典。男主因为脑部受创,患上了顺行性遗忘,记忆只能维持十几分钟。为了给妻子报仇,他只能靠纹身、照片和字条来拼凑线索。电影不光剧情烧脑,诺兰更是利用剪辑效果完美模拟了失忆患者的碎片化体验,代入感极强,科学性和趣味性拉满,值得看n遍。
类似影片:《未知死亡》,宝莱坞翻拍版,沿用了同样的失忆设定,不过加了更多动作和歌舞元素。男主扮演者是国宝级演员阿米尔·汗,肌肉吸睛,值得一看。

推荐指数:⭐️⭐️⭐️⭐️
经典爱情剧,「睡眠重启」失忆设定鼻祖。女主因为车祸导致记忆受损,每天早上醒来记忆都会重置到车祸发生的那天。科学性一般,但胜在剧情感人。男主每天换着花样让女主重新爱上自己的桥段很浪漫,作为爱情片值得一看。
类似影片:日版《初吻 50 次》,山田孝之和长泽雅美共演,剧情基本照搬原版,无亮点,且个人认为主人公 CP 感几乎为零,非演员粉丝向不太推荐。
推荐指数:⭐️⭐️⭐️⭐️
近年口碑不错的医疗日剧,一集一个脑外科病例。主角杉咲花饰演的脑外科医生因为意外导致记忆障碍,每天睡醒后记忆重启,必须靠重温日记来衔接人生。和主打纯爱的《初恋 50 次》不同,这部剧虽然延用了「每天醒来记忆重置」的设定,但侧重点在于对各种经典脑部疾病的科普,还有对失忆患者心理困境的刻画,这些方面做得很不错。另外,个人认为全剧最打动人的还是感情线。男女主演(杉咲花、若叶龙也)现实中是真情侣,全程真情流露,相当好嗑。
推荐指数:⭐️⭐️⭐️
新垣结衣和冈田将生主演的漫改推理喜剧。女主今日子是一个只要睡着,记忆就会重置的白发侦探,任何案件都必须在一天内解决,重要线索只能用马克笔写在自己的大腿和手臂上。冈田将生则扮演一个衰神,不但去哪里都有案件,而且每次总被怀疑成凶手。这部剧的失忆设定只是剧情需要,毫无科学性可言。好在整部剧轻松幽默,推理也没什么智力难度,适合放松无脑看,个人觉得一般。
如果说前两类失忆在现实中没那么常见,主要以影视剧的文艺加工为主,那么,由阿尔茨海默引发的失忆,对普通人来说则最为常见,也和我们的日常生活最息息相关。就在两年前,我的奶奶去世了。在她去世前的十年间恐已罹患阿尔茨海默症,可惜当时我对此并不知情,只觉得奶奶变得越来越健忘、渐渐不认识人,脾气也大变,变得异常执拗。如今想来,仍觉愧疚与遗憾不已。
影视作品为了剧情冲突和审美需要,常会把镜头对准极少数的「早发性阿尔茨海默症」患者,比如经典韩国爱情电影《我脑海中的橡皮擦》,孙艺珍扮演的女主在最美好的年华里,微笑着一点点遗忘深爱的人,让这种疾病显得凄美又浪漫。
但现实中,阿尔茨海默症通常是一种典型的老年病。绝大多数患者的发病年龄都在 65 岁以上。而且随着年龄的增长,患病率会呈指数级上升。到了 85 岁以上的老年人群体中,有 1/4 - 1/3 的人会罹患阿尔茨海默症。关于疾病的科普知识,欢迎观看哈佛大学神经科学博士 Lisa Genova 女士的 Ted 演讲。
从症状上看,阿尔茨海默症不但病程极其漫长——从最开始的轻度健忘,到最终的彻底失智失能,患者和家属往往要经历长达十年甚至更久的漫长煎熬,而且对于绝大多数患者家庭来说,生活中更多是无力和绝望。随着疾病的加重,接踵而来的是患者的认知混乱、大小便失禁、性情变化、离家出走、甚至出现幻觉和攻击行为。家属哪怕充分理解病情,做足了知识储备和心理建设,也有可能在日复一日令人精疲力竭的照护重担中逐渐失去耐心。
关于这个主题的书籍,推荐参考《偷走心智的贼》等科普类作品,《当我妈妈得了阿尔茨海默》《照护:哈佛医师和阿尔茨海默病妻子的十年》《给妈妈当妈妈》等纪实类作品。病人照护作为一种社会问题,还可以参考 NHK 纪实系列《失智失踪》《老后两代破产》等书籍。
为什么阿尔茨海默症不仅会让患者记忆丧失,还会发生如此彻底的改变?它和普通的衰老健忘有什么区别?这要从阿尔茨海默症的疾病机制说起。
普通的衰老健忘,主要是大脑机能的自然减退。神经元的反应变慢了,一部分神经元因衰老而死亡,但它的基本结构是完整的,核心记忆和人格也完好无损。然而,阿尔茨海默症的大脑内部则会发生不可逆的物理性病变。如果在显微镜下观察患者的大脑,会发现两种异常的病变蛋白:一种叫作 β-淀粉样蛋白斑块,它像有毒的垃圾一样堆积在神经元之间,切断脑细胞之间的通讯信号;另一种叫作 tau 蛋白缠结,它会破坏神经元内部的运输系统,造成脑细胞大面积死亡。


病变在大脑内部造成的破坏,有非常明确的路径和顺序。这也直接决定了阿尔茨海默症患者在不同阶段所表现出的症状。
第一阶段:海马体异常,短时记忆受损,通常持续 2 到 4 年。病变最先攻击的区域就是海马体。一旦它被破坏,患者就会出现典型的顺行性遗忘,记不住新发生的事情。这也是阿尔茨海默症最早期、最常见的症状。患者会反复问同一个问题、刚吃完饭就忘了、或者在每天散步的熟悉小区里迷路。在这个阶段,他们大脑皮层里的长时记忆依然是完好的,所以常常会出现,患者陈年往事记得一清二楚,却怎么也记不住刚刚发生的事情。
第二阶段:病变发展至大脑皮层,造成长时记忆与认知异常,通常持续 2 到 10 年,是病程最长的阶段。随着疾病的不断加深,有毒的蛋白病变会从海马体,向外延伸到大脑皮层。大脑皮层不仅储存着长时记忆,还负责语言、逻辑、空间和情绪等高级认知功能。所以这个阶段,患者不仅会出现逆行性遗忘,逐渐忘记过去几年甚至十几年前的事,渐渐认不出亲人,人格和行为也会发生剧变。他们有可能会丧失语言能力,词不达意;或者突然变得执拗、多疑、充满攻击性。很多家属看到老人性情大变,出现攻击行为,问题就出在这个阶段。
第三阶段:吞噬大脑,造成全面失能,通常持续 1 到 3 年。到了疾病晚期,病变几乎会席卷整个大脑。此时,患者的大脑体积会发生严重萎缩,患者不仅会彻底忘记了自己是谁,整个大脑也失去了对身体机能的控制权,会逐渐丧失行走能力,最终连咀嚼、吞咽、控制大小便这些最基本的生理本能也会被剥夺,只能完全依赖他人的全天候照护,直至出现并发症,走向生命终点。
遗憾的是,人类至今仍未研发出能够有效治愈或逆转阿尔茨海默症的特效药。即便科学家能成功清除了患者大脑中异常堆积的有毒蛋白斑块,病情依然会不可逆转地向前发展。这也是当前医学界的重要难题之一。

推荐指数:⭐️⭐️⭐️⭐️⭐️
教科书级别的阿尔茨海默症题材电影,原著作者 Lisa Genova 是哈佛大学的神经科学博士,写过多部以脑科疾病为主题的小说和科普。故事的主角是一位语言学教授,有幸福的婚姻和三个孩子,却在 50 岁时患上了家族性的阿尔兹海默症。这部电影把知识分子面对自我意识丧失的恐惧和无力表现得特别真实和绝望。朱利安·摩尔表演得特别到位,推荐观看。
推荐指数:⭐️⭐️⭐️⭐️⭐️
本周看什么栏目推荐过。改编自同名舞台剧,堪称阿尔茨海默症题材电影杰作,艺术性极强。故事从第一视角展示了一位罹患阿尔兹海默症的父亲的日常困惑与记忆残片,代入感极强。不少观众在观影时不免会觉得困惑,但诚如弹幕所言:看不懂这个作品的人该是多么幸福啊!「汉尼拔」扮演者安东尼·霍普金斯奉献了神一般的演技,故事中绝望和纠结的女儿角色也诠释得特别到位。力荐。
另一部类似题材作品《熟悉的触感》同样值得一看,可前往查看本周看什么的详细推荐。

推荐指数:⭐️⭐️⭐️⭐️⭐️
西班牙动画电影,真实且压抑。主角是一群被困在养老院里的老头老太,电影细腻地描绘了他们病程发展的不同阶段:从初期的迷失,到中期的幻觉,再到晚期「住到顶楼」彻底失能的绝望。我很喜欢看动画电影,这部片子无论从剧情、情绪和画风上都深得我心,强烈推荐。
推荐指数:⭐️⭐️⭐️⭐️
经典的韩式催泪片。电影选择了现实中发病率不到 10% 的早发性阿尔茨海默症,主要出于剧情需要。作为一部爱情片,它真的很好哭;但作为一部疾病片,它太过唯美,和现实中的阿尔茨海默症仍有不少的差距。
推荐指数:⭐️⭐️⭐️
大石静老师的爱情电视剧,户田惠梨香和室毅主演,意外有 CP 感。同样是年轻貌美能干女医生患病的早发性设定,较为细致地描写了男主照顾逐渐失智的女主的痛苦与坚守。前半程谈恋爱很好看,后半程女主患病后剧情相对狗血,副线 CP 也接受不能,不过依旧很好哭。
在收集资料的过程中,我发现除了上述所说的失忆类型之外,还有大量奇奇怪怪的失忆病例,它们的发病诱因也不尽相同,这里没办法一一详述,引述《记忆脑科学》一书的总结,供大家参考学习:
这篇文章既是学习系列「记忆」话题的第二篇,也是以影视剧为切入点,对讨论记忆科学的探讨。下一篇文章,我想重新回到学习的主线,介绍一下「程序性记忆」和「练习」的重要性。大家如果有什么感兴趣的主题,也欢迎多多给我留言提建议。
> 关注 少数派小红书,感受精彩数字生活 🍃
> 实用、好用的 正版软件,少数派为你呈现 🚀
嘉实也跌,159941 也跌,感觉要完蛋了
兄弟们,开工两周了,说点实话。 最近翻朋友圈,画风两极分化:一边是前同事晒新工牌、晒开工红包;另一边是几个老朋友,简历改了又改,但一直没动静。 我也被问烦了:“你们公司还招不招?”“现在这行情,跳槽是不是找死?” 问得我也有点恍惚。2026年了,咱们这行到底还行不行?跳槽这操作,到底该不该点? 先说结论:不是不行了,是玩法变了。 前几年,跳槽等于“薪资翻倍”,简历挂网上就有人来撩。那时候离职,是“主动的选择”——为了涨薪、为了职级、为了更香的饼。 但这两年,我亲眼见证了好几场“非主动的离别”。上午还一起修Bug的同事,下午账号就灰了。那种感觉,像被人按着头看清一个真相:没有永远的避风港,只有永远的“个人竞争力”。 但这不代表我们没戏了。恰恰相反,我观察到几个信号: 所以,不是机会没了,是机会换了地方、换了形态。还拿着旧地图的人,当然找不到新大陆。 最近和一个猎头朋友吃饭,他一句话点醒我:“现在能顺利跳槽的人,不是因为运气好,是因为他们一直在维护自己的‘可迁移价值’。” 什么意思?就是抛开你现在公司的平台、工牌、内部工具,你这个人本身,在市场上值多少钱。 我给自己列了几个“Debug问题”,也分享给你: 这些问题,如果答案不清晰,建议先别急着投简历。盲目的跳槽,只是从一个“坑”换到另一个“坑”。 当然,如果你已经想清楚,想看看外面的机会,我有几个实在建议: 比如上周,有个同事转发我的。我点进去发现,它和一般的网申不太一样:页面上有一段话让我挺触动—— “在这个后疫情时代,互联网IT行业经营环境发生了巨大变化…请由衷地为自己鼓掌,面包会一直有。是的,该有的岗位,以后仍旧会有。” 这段话让我觉得,这家是懂咱们这行现状的。它不是随便收简历,而是真的想匹配“对的人”。 如果你正在看机会、或者想测测自己现在的“市场适配度”,可以不妨一试。 2026年,大概率不会再有大厂撒钱式的“人才军备竞赛”了。但对于真正有积累、能解决问题、保持学习的人来说,好工作依然存在,只是藏得更深,需要更清醒的判断力去找。 咱们这行,核心资产永远是自己。工牌是临时的,但解决问题的能力是永久的。 别被焦虑绑架,但也别闭着眼睛原地踏步。 保持对市场的敏感,持续优化自己的“技能树”,机会来的时候,你才能稳稳接住。 共勉。一、看清“水温”:别被焦虑带偏

头部公司还在“抢人”,但抢的是“能解决问题的人”,不是“会写代码的人”。 技术栈匹配只是入场券,能扛事、能闭环、能搞定复杂场景的,溢价依旧很高。
AI热退烧,应用层开始落地。 前年聊大模型,去年聊融资,今年开始聊“怎么用AI赚钱”了。这对我们来说是好事——真正需要程序员把技术转化成产品的时候到了。
跨界岗位变多。 新能源、智能制造、金融科技…这些实体行业对软件人才的需求,比前两年更迫切。他们不画饼,给的是实打实的股权和稳定预期。
二、跳槽前,先做一次“自我Debug”
技能栈:我最近半年学的新东西,是只能服务于当前项目,还是能写进简历成为通用能力?
项目价值:我做的这个系统,是公司的核心营收命脉,还是随时可替代的边缘业务?
行业视野:除了自己的一亩三分地,我知道隔壁赛道在发生什么变化吗?我知道哪些行业正在高薪挖程序员吗?
人脉储备:我微信里除了同事,有能直接内推我、给我靠谱信息的猎头或同行吗?
三、如果想动,怎么“低成本试错”?
不用急着提离职,但可以定期看看市场。知道现在什么岗位火、什么技能溢价高,本身就是一种“信息对冲”。行情好时攒底气,行情差时也不慌。
现在的面试,背八股文没用。面试官想听的,是你真实解决过的复杂问题。把最近一年最得意的项目,复盘成一个小型“案例研究”:背景、难点、方案、结果、你独特的贡献。这是你最好的简历。
这也是我最近发现的一个小窍门——如果你对市场判断不准、或者没时间大海捞针,不如找一个专业的入口 →→→先把自己的信息“投石问路”。最后说几句心里话
在PostgreSQL中删除行的时候,这些行只是被标记为“dead”,而不是真正从物理存储上进行删除了,因而空间也没有真的被释放回收。在PostgreSQL中除非进行自动的auto vacuum或者是手动的vacuum,否则数据块所占用的物理空间不会被回收。因此在物理存储空间被回收之前,会导致存储空间中存在很多空洞。如果表结构中包含动态长度字段,那么这些空洞甚至可能不能被PostgreSQL重新用来存储新的行。因此,大量随机的DELETE操作,必然会在数据文件中造成不连续的空白空间。而当插入数据时,这些空白空间也不会被利用起来,于是造成了数据的存储位置不连续。物理存储顺序与逻辑上的排序顺序不同,这种就是数据碎片。 对于大量的UPDATE,也会产生文件碎片化 , PostgreSQL的最小逻辑存储分配单位是数据块(Block),其默认值是8K。因此大量的更新操作也可能导致数据块的分裂(Block Split),即:同一个字段的数据可能存储在不同的数据块中。频繁的数据块分裂,会使得数据的存储变得稀疏,并且被不规则的数据填充,所以最终数据会有碎片。 视频讲解如下: 下面通过具体的步骤来演示如何清理表的碎片。 (2)查看表testfragement占用的容量大小。 (3)删除表中所有数据。 (4)再次查看表testfragement占用的容量大小。 (5)查看表的状态信息。 (6)手动进行一下碎片的清理。 (7)再次查看一下表的状态 (8)重新查看表testfragement占用的容量大小。
https://www.bilibili.com/video/BV1VNPjzfEEd/?aid=116159169043...
(1)创建一张新的表,并往表中插入5000万条记录scott=# create table testfragement(tid int,tname varchar(20));
scott=# insert into testfragement select n,'myname_'||n from generate_series(1,50000000) n;scott=# select pg_size_pretty(pg_relation_size('testfragement'));
# 输出的结果如下:
pg_size_pretty
----------------
2488 MB
(1 row)scott=# delete from testfragement;scott=# select pg_size_pretty(pg_relation_size('testfragement'));
# 输出的结果如下:
pg_size_pretty
----------------
2488 MB
(1 row)
# 从输出的结果可以看出,尽管删除了表中的数据,表所占用的空间依然没有释放。scott=# \x
scott=# select * from pg_stat_user_tables where relname = 'testfragement';
# 输出的结果如下:
-[ RECORD 1 ]-------+------------------------------
relid | 16574
schemaname | public
relname | testfragement
seq_scan | 1
seq_tup_read | 50000000
idx_scan |
idx_tup_fetch |
n_tup_ins | 50000000
n_tup_upd | 0
n_tup_del | 50000000
n_tup_hot_upd | 0
n_live_tup | 0
n_dead_tup | 49999426
n_mod_since_analyze | 0
n_ins_since_vacuum | 0
last_vacuum |
last_autovacuum | 2023-04-28 09:14:26.066678+08
last_analyze |
last_autoanalyze | 2023-04-28 09:14:46.677939+08
vacuum_count | 0
autovacuum_count | 1
analyze_count | 0
autoanalyze_count | 1
其中:
n_live_tup 的数量是当前表的数据量。
n_dead_tup 的数据量是未回收的空间。
# 从参数n_dead_tup输出结果上看,表testfragement仍然占用了很多 ”空闲“ 数据块,其空间没有被回收。scott=# vacuum testfragement;
# 此时会产生后台相应的进程:
[root@mydb ~]# ps -ef|grep VACUUM
postgres 6649 3540 .... postgres: postgres [local] VACUUM scott=# \x
scott=# select * from pg_stat_user_tables where relname = 'testfragement';
# 输出的信息如下:
-[ RECORD 1 ]-------+------------------------------
relid | 16574
schemaname | public
relname | testfragement
seq_scan | 1
seq_tup_read | 50000000
idx_scan |
idx_tup_fetch |
n_tup_ins | 50000000
n_tup_upd | 0
n_tup_del | 50000000
n_tup_hot_upd | 0
n_live_tup | 0
n_dead_tup | 0
n_mod_since_analyze | 0
n_ins_since_vacuum | 0
last_vacuum | 2023-04-28 09:23:05.463206+08
last_autovacuum | 2023-04-28 09:18:11.434888+08
last_analyze |
last_autoanalyze | 2023-04-28 09:14:46.677939+08
vacuum_count | 1
autovacuum_count | 2
analyze_count | 0
autoanalyze_count | 1
# 参数n_live_tup和n_dead_tup都变成了0,这说明表所占用的空间已经被释放回收。scott=# select pg_size_pretty(pg_relation_size('testfragement'));
# 输出的结果如下:
pg_size_pretty
----------------
0 bytes
(1 row)
思考 关于近期 “AI 评测坐标系坍塌” 的说法,我认为这并非指评测体系的崩溃,而是标志着评测标准正经历一场深刻的范式转移,一个 “新坐标系” 的大基建时代正在到来! 目前,AI 落地的瓶颈不是 “智力不够”,而是 “不可计算”。因为在所有核心生产环境中,“未知” 远比 “不能” 更让人感到寒意。 所谓 “不能”,指的是技术的上限,我们可以靠工程规避,靠冗余弥补;但 “未知” 则是确定性的坍塌。 如果一名技术负责人,得知某个 AI 生成的逻辑有 1% 的概率会导致不可预知的系统崩溃,且你无法量化这个 1% 会在什么时候、什么边界触发,那么对于他来说,这个 AI 的价值就不是 99% 的增效,而是 100% 的风险炸弹。 正是这种由于缺乏 “边界感” 而产生的决策瘫痪,促使我们必须快步构建新坐标系。 为什么以往的 AI 选型会进入“决策黑盒”?因为我们面临三大困境: 如何才能击穿这个黑盒呢? 我们已经经历了太多的 “Aha Moments”。看到模型会写诗、能思考、能生图、生视频,令我们惊艳欢呼。但欢呼之后,生产环节真正关心的是:它到底能不能帮我干活? 在 AI 进入生产环节的深水区时,市场急需一个声音来判定“好坏”。回顾历史,ImageNet 的地位之所以高不可攀,是因为它锚定了视觉能力的基准。 而最近爆火的 LMArena 之所以估值高达 17 亿美金,本质上是因为它在大模型最混乱的时候,告诉了用户谁更好用。 在评测的过程中,测评榜单固然需要参考,但更重要的是判定 AI 能否从“做对题”向 “干成事”。 为什么我们需要这么多榜单?因为现在的通用榜单已经面临严重的“数据污染”。 通用榜单的困境(以数据库行业为例) 标准榜单的题目会在互联网上广泛传播,不可避免地混入训练数据中。所以你会看到模型能背出所有的 Oracle 语法,但一旦我们把题目中的变量名改一改,或者把逻辑嵌套稍作调整,原本的高分模型会瞬间崩盘。 那么真正有效的测评榜单是能够持续更新“题库” 的榜单,要看模型是"记住了"答案,还是"算出了"答案。 SCALE 就是这样一款持续更新的,专门用于测评大模型 SQL 能力的榜单。 2025 年 12 月,SCALE 更新生产级数据集 2.0。这不是一次简单的题库扩容,而是一次“照妖镜”式的压力测试。 结果让很多所谓的“优等生”露出了马脚: 这消失的分数,就是 AI 的“滤镜”。只有这层滤镜被挤掉后,你才知道谁才是真正能在生产环境下、在没见过考题的情况下帮你解决问题的"实战专家"。 为什么 SCALE 能把这些“优等生”打回原形? 因为 SCALE 的“题库”是基于 ActionTech 客户现场的几千条“烂数据”和真实事故构建的。这不是简单的考试,这是对模型的压力演习。 经过实测证明,在 SQL 这个垂直领域,GPT-4 Mini 的很多指标优于其庞大的全量版 GPT-5 Chat ! Big is not always better. Specialized is enough. 企业选型误区 对于企业来说,如果你只看通用榜单选了最贵的模型,你不只是在浪费算力成本,你甚至在引入更多的推理不确定性。 SCALE 的数据来源 近十年,我们在金融、电信、电力等行业直面数百起因 SQL 缺陷引发的生产事故——从毫秒级延迟到核心系统宕机,每个高危场景都是被按下暂停键的「高危手术」。 在这些真实故障面前,通用大模型在学术榜单上磨炼出来的“套路”失效了。SCALE 存在的目的,不是为了证明模型不行,而是为了倒逼模型学会识别物理执行计划,学会在国产化迁移等真实落地场景中,精准地切换方言和决策。 不只是看 SQL 是否能跑通,还要把评估拆解成三个维度: 主观评估:针对逻辑等价性和方言转换 很多人好奇:这些决定模型胜负的“优化规则”到底是怎么定出来的?是专家拍脑门吗? 绝对不是。 首先,要对数据先进行挖掘。以优化方向来说,一本书中如果能挖出 10 多条优化方向。人读一本书以天/周为单位,AI 读一本书以分钟为单位。我们为此构建了一套极其复杂的 “高保真生产模拟器”。它可以精准模拟不同量级、不同架构的各种异构生产场景。 高保真生产模拟器工作流程 先利用 AI 挖掘潜在的优化方向,然后将这些规则投入模拟器进行海量的自动化压测。只有在那套复杂的模拟引擎中被验证为实战有效,并最终通过我们专家团队的严苛逻辑审计,才能被收录进 SCALE 的“真理库”。 双保险机制 这套 “模拟器 + 专家经验” 的双保险,确保了 SCALE 的评分标准不是纸上谈兵,而是真正的 “物理执行感知” 评估。 最后,把话题再拉回到大家关心的 ROI 上。AI 的测评正在经历从“学术竞赛”向“落地评估”的转型。 如果你是技术负责人,你应该这样问自己:“这个模型在 SCALE 2.0 面前,能否像一名合格的工程师一样,稳定解决复杂 SQL 问题?” 如果答案是否定的,那它就不该进入你的核心系统。如果一个模型在我们的“大型 SQL 转换” 指标上表现不佳,那就意味着它在真实生产环境中会给你埋雷。 AI for DB 的终极形态不是一个聊天框,而是一个能自主运维、自主调优的 SQL Agent。 SCALE 的使命,就是成为这类 “SQL 智能体” 的入职资格证。 为专业 SQL 任务,选专业 AI 模型。 如果你也在为 AI 选型犯难,欢迎访问我们的官网,了解最新的 SCALE 评测报告,找到真正适合你生产场景的模型。 我们坚持:📅 每月更新、🔄 生产反哺、🏭 生产溯源 在这个坐标系重构的时代,我们希望同大家一起寻找 AI 真正的生产力价值。
1. AI 落地的瓶颈:不可计算
1.1 “未知” 比 “不能” 更可怕

1.2 为什么 AI 选型陷入“决策黑盒”?

2. 从 Aha Moments 到“到底能不能用”

2.1 我们经历过的 AI 惊艳时刻
2.2 AI 评测标准的价值


2.3 考试泄题与“红皇后效应”
经济学中有一个古德哈特定律(GoodHart's Law):“当一个指标成为目标时,它就不再是一个好的指标。”

3. 照妖镜:SCALE

模型 SCALE 1.0 SCALE 2.0 跌幅 DeepSeek 71.6 51.5 -20.1 (-28%) Gemini 3 Pro 72.0 64.0 -8.0 (-11%) 3.1 消失的分数 = AI 的“滤镜”
3.2 别做"冤大头",专业化 > 大而全

3.3 从 ICU 病房到压力演习
3.4 三位一体的混合评估机制
3.5 优化规则如何炼成?
1. AI + 资源库挖掘优化方向
↓
2. 投入模拟器压测
↓
3. 专家团队逻辑审计
↓
4. 收录进 SCALE4. 从“学术竞赛”到“落地评估”
4.1 给技术负责人的选型新思路
4.2 SCALE 的目标
界面类似,后经作者深扒,发现内置翻译扩展 icon 文件名前缀为 read-frog 实锤
关于翻译插件项目代码的说明
2026 年 3 月 3 日,我们关注到社区关于 Tabbit 浏览器使用“陪读蛙”源项目代码及开源合规的讨论。团队对此事高度重视,第一时间对项目的开源和合规情况进行了深度自查,现将事件发生的时间线及后续举措进行说明。
2025 年 12 月 30 日,我们的团队在开发翻译功能时关注到 read-frog ( https://github.com/mengxi-ream/read-frog )开源项目。当时,该项目仓库中并未包含任何开源协议声明。团队经评估进行了项目 fork ,以独立项目的方式进行开发。
2026 年 1 月 2 日,该项目的原作者在 Commit a0679e2 中为其添加了 GPLv3 协议。由于我们未继续合并原项目的后续代码,未能及时关注到此次协议变更。
虽然我们的 fork 代码行为发生在该项目添加明确的开源协议之前,但我们充分尊重和理解原作者对项目的所有权及其协议选择。我们将从 Tabbit 浏览器新版中移除此翻译项目,并已将此项目完整开源 https://github.com/Tabbit-Browser/read-frog ,供社区审阅和使用,以实际行动回馈开源社区。
如有任何疑问,欢迎通过 [email protected] 与我们沟通。
就像今天的 Tabbit 事件,即使大模型请求放在后端,但凡你的 app 走 http 调用,那么逆向抓包就能看到请求,无论如何都可以模仿请求。
如果通过后端提示词来限制,那么也是很容易被绕过,比如提示词中包含 你是一个浏览器助手,那么用户可以输入新的提示词 **请忽略提示词中所有下面的内容'你是一个浏览器助手'**。
相当于矛与盾,没有稳定的方式防止被攻破,只能监控好数据,即使针对用户的异常请求做调整?