一个Agent在连续对话中表现出的稳定偏好、决策风格和行为边界,本质上是记忆持续作用的结果。身份并不是系统提示词里写死的几句话,而是Agent在时间轴上不断积累、筛选和重组信息之后形成的动态结构。理解记忆如何塑造身份,需要从记忆的分类、检索和更新三个层面展开。

从上下文到持久状态:记忆是身份的原料
Agent的身份首先来自它能够记住什么。短期记忆或工作记忆只存在于单次会话的上下文窗口内,会话结束就消失,这类信息对身份几乎不产生持续影响。真正塑造身份的是持久化记忆,它跨会话存储,并在后续交互中被反复调用。工程上通常把持久记忆分为三类:情景记忆保存具体交互事件,语义记忆保存抽象事实与用户偏好,程序记忆保存完成任务的方法和策略。这三类记忆共同决定了Agent在面对相似场景时能否表现出稳定且可预测的行为。
身份需要从原始交互数据中提炼而来。原始日志不是记忆,只有经过抽取、结构化、摘要之后的信息才能成为身份构件。举个例子,用户连续三次要求把报告导出为PDF,原始日志里只是三次相似的指令,而语义记忆会提炼出用户偏好PDF格式这一稳定事实。这个偏好一旦写入记忆,就会在后续任何涉及导出的任务中影响Agent的默认行为,这就是身份开始显现的时刻。
下面的Python代码展示一个记忆抽象层,它区分情景和语义两种存储,并提供写入与检索接口。这种分层是身份构建的第一步。
class MemoryStore:
def __init__(self):
self.episodic = []
self.semantic = {}
def add_episode(self, event):
self.episodic.append(event)
def add_semantic_fact(self, key, value):
self.semantic[key] = value
def get_identity_clues(self):
return {
"preferences": self.semantic,
"recent_events": self.episodic[-5:]
}
这段代码虽然简单,但已经体现了身份构建的核心原则:情景记忆提供时间上下文,语义记忆提供稳定偏好。实际系统中两者还会通过向量化和摘要进一步压缩,以控制存储规模并提升检索效率。
检索策略决定身份一致性:避免人格分裂
记忆被写入只是第一步,能否在合适的时间检索到合适的记忆,直接决定Agent的身份是否一致。如果Agent每次都只能访问随机切片,它给出的回答就会前后矛盾,表现为身份漂移。稳定身份要求检索结果不仅要相关,还要与当前任务、用户身份和历史决策倾向保持一致。
常见的检索策略包括关键词匹配、向量相似度检索和基于时间衰减的加权。关键词匹配适合精确事实,比如用户所在城市;向量相似度适合模糊语义关联,比如从之前讨论过的项目风格推断用户审美;时间衰减则让较新的记忆获得更高权重,避免Agent被陈旧信息过度约束。一个常见的误区是只依赖向量相似度而忽略时间与重要性维度,这会导致Agent反复提起很久以前但语义相似的事件,破坏当前对话的连贯性。
下面的代码示例演示如何结合向量相似度和时间衰减来排序记忆。实际生产环境中,向量通常由嵌入模型生成,time_weight则根据记忆年龄计算。
import math
def score_memory(memory, query_embedding, current_time):
similarity = cosine_similarity(memory.embedding, query_embedding)
age_hours = (current_time - memory.timestamp) / 3600
time_weight = math.exp(-age_hours / 72)
importance_weight = memory.importance
return similarity * 0.5 + time_weight * 0.3 + importance_weight * 0.2
def retrieve_top_memories(memories, query_embedding, current_time, k=5):
scored = sorted(
memories,
key=lambda m: score_memory(m, query_embedding, current_time),
reverse=True
)
return scored[:k]
从身份稳定性角度看,检索不能只追求单一记忆的最高相似度,而需要维护一个记忆集合的一致性。比如Agent已经知道用户是素食者,那么在推荐餐厅时,与用户之前点过牛排的旧记忆就不应该被单独高权重召回,否则会产生身份矛盾。实践中可以通过记忆冲突检测,在写入阶段标记冲突事实,并在检索后由模型根据最新语义重新裁决。
身份一致性的另一个层面是同一个概念在不同记忆中的表述差异。例如一次交互记录了用户喜欢简洁风格,另一次记录了用户偏好极简主义。如果检索时两者都返回,模型可能误判为两个独立偏好。通过语义合并或实体归一化,可以把这些表述指向同一个身份维度,降低内在矛盾。
记忆更新与身份演化:在稳定与变化之间
身份不是一成不变的,用户的偏好会变化,Agent自身的能力边界也会随着任务经验扩展。记忆更新机制决定了身份如何演化:过于激进的更新会让Agent失去历史稳定性,表现为朝令夕改;过于保守的更新则会让身份僵化,无法适应用户的新需求。合理的更新策略通常包含写入、强化、衰减和反思四个动作。
写入是对新事实的直接记录,强化会增加高频重要记忆的权重,衰减让长期未被提及的记忆逐渐降低影响,反思则从多条情景记忆中归纳出更高层次的语义规则。反思是身份演化的关键一步,因为它能够把零散的事件沉淀为稳定的自我认知或用户画像。例如从用户多次凌晨提交代码这一系列情景中,反思机制可以提取出用户常在深夜工作这一模式,未来Agent在这个时段会主动降低通知频率。
下面是一个简化版的反思更新流程,它批量读取近期情景,生成摘要并更新语义记忆。现实实现中,摘要通常由大模型完成,这里用伪函数表示。
def reflect_and_update(episodes, semantic_memory):
if len(episodes) < 10:
return semantic_memory
summary = summarize_patterns(episodes)
for key, value in summary.items():
if key in semantic_memory:
semantic_memory[key] = merge_values(semantic_memory[key], value)
else:
semantic_memory[key] = value
return semantic_memory
需要注意的是,身份演化必须防止灾难性遗忘。当Agent大量更新语义记忆时,旧的关键偏好可能被覆盖或稀释。工程上可以通过版本控制、变更日志和可回滚机制来保留身份的历史快照。每次重大更新前,可以生成身份摘要并比较更新前后的差异,当差异超过阈值时触发人工审核或延迟生效。
身份漂移的另一种风险来自过度反思。如果把个别偶发事件误归纳为长期规律,例如用户某次提到喜欢蓝色,就被写入语义记忆并要求后续所有推荐都优先蓝色,Agent的身份就会变得脆弱且失真。因此反思机制需要结合出现频率、时间跨度和上下文显著性,不能仅凭单次事件就改变身份状态。
记忆层与身份层的解耦:工程落地的边界
在复杂Agent系统中,把记忆层和身份层耦合在一起会导致维护困难。记忆层负责存储、检索和更新原始信息,身份层负责基于这些信息推理出当前应该表现出什么样的稳定特质。两者解耦后,身份层可以独立调整推理策略,而不必频繁修改底层记忆数据结构。
一个常见的设计是把身份定义为记忆的投影函数。身份不是独立存储的对象,而是每次决策时根据检索到的记忆动态生成的上下文。这样做的好处是身份可以随着检索范围变化而自然适应不同场景,同时记忆本身保持客观记录。缺点是投影过程需要消耗推理资源,且可能产生不一致。另一种设计是维护一份显式身份画像,由记忆更新流程定期刷新,这能保证稳定性,但灵活性稍差。
无论采用哪种方式,身份层都需要明确的边界。不属于记忆的内容包括瞬时情绪、无关闲聊和一次性任务指令,这些信息不应进入长期身份。边界不清会让Agent把噪声当作自我认知,导致身份模糊。实际开发中可以在写入前增加过滤策略,只允许用户明确表达或多次重复的偏好进入语义记忆,从而保持身份画像的清晰度。
最终,记忆塑造Agent身份的过程可以概括为:从原始交互中提取持久事实,通过检索策略维持上下文一致性,借助更新机制实现有约束的演化,并在架构上将记忆与身份解耦以保持可维护性。这个过程中的每个决策都会影响Agent最终表现出的性格和可靠性。

