面向长期 LLM 代理的偏好感知记忆更新

面向长期 LLM 代理的偏好感知记忆更新

ArXiv ID: 2510.09720
作者: Haoran Sun, Zekun Zhang, Shaoning Zeng
机构: Hong Kong Polytechnic University
发布日期: 2025-10-10


摘要

影响基于 LLM 代理推理能力的关键因素之一是其利用长期记忆的能力。虽然最近的进展显著改进了存储和检索组件,但大多数现有方法在记忆更新方面存在不足——缺乏根据不断演变的用户行为和上下文动态优化偏好记忆表示的机制。本文提出 PAMU(Preference-Aware Memory Update),通过整合滑动窗口平均(SW)和指数移动平均(EMA),构建融合的偏好感知表示。在 LoCoMo 数据集上,PAMU 在五个任务场景中准确率提升15-25%


问题背景

长期代理中的记忆挑战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
长期对话代理中的偏好演变:

场景:个性化助手
┌─────────────────────────────────────────┐
│ Day 1: 用户喜欢详细的解释 │
│ Day 7: 用户开始偏好简洁回答 │
│ Day 14: 在技术话题上希望详细,其他简洁 │
│ Day 30: 根据时间(工作日/周末)变化 │
└─────────────────────────────────────────┘

核心问题:
- 用户偏好不是静态的,而是动态演变的
- 现有记忆系统存储但很少更新偏好
- 过时的偏好导致不准确的个性化

现有方法的局限

方法 记忆存储 记忆检索 记忆更新
向量检索 ✅ 密集编码 ✅ 相似度搜索 ❌ 静态
知识图谱 ✅ 结构化 ✅ 图遍历 ❌ 手动
简单摘要 ✅ 压缩 ⚠️ 关键词 ❌ 覆盖
PAMU ✅ 双层表示 ✅ 偏好加权 动态更新

关键洞察

  • 短期波动(temporary preferences)需要快速响应
  • 长期趋势(stable preferences)需要稳定保持
  • 单层记忆无法同时捕捉两者

PAMU 方法

整体架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
┌─────────────────────────────────────────────────────────┐
│ Preference-Aware Memory Update │
│ (PAMU Framework) │
│ │
│ 用户交互流 │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 偏好提取模块 │ │
│ │ Preference │ │
│ │ Extractor │ │
│ └─────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ 双层记忆更新系统 │ │
│ │ │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ Short-term Window │ │ ← 滑动窗口 (捕捉波动) │
│ │ │ (SW, α=0.3) │ │ │
│ │ └─────────────────────┘ │ │
│ │ ↓ │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ Long-term EMA │ │ ← 指数移动 (保持趋势) │
│ │ │ (EMA, β=0.95) │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 融合偏好表示 │ │
│ │ Fused │ │
│ │ Representation │ │
│ └─────────────────┘ │
│ │ │
│ ▼ │
│ 个性化响应生成 │
└─────────────────────────────────────────────────────────┘

组件 1:偏好提取

隐式偏好检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import numpy as np
from typing import List, Dict

class PreferenceExtractor:
"""从用户交互中提取偏好"""

def __init__(self, llm):
self.llm = llm

def extract_preference(self, interaction_history: List[Dict]) -> Dict:
"""
提取用户偏好

偏好类别:
- 响应长度(简洁 vs 详细)
- 响应风格(正式 vs 随意)
- 信息密度(概览 vs 深入)
- 交互频率(主动 vs 被动)
"""
# 分析用户对历史响应的反馈
feedback_signals = self._analyze_feedback(interaction_history)

# 推断偏好维度
preferences = {
'response_length': self._infer_length_pref(feedback_signals),
'response_style': self._infer_style_pref(feedback_signals),
'information_density': self._infer_density_pref(feedback_signals),
'interaction_frequency': self._infer_frequency_pref(feedback_signals)
}

return preferences

def _analyze_feedback(self, history: List[Dict]) -> List[float]:
"""
分析用户反馈信号

正面信号:
- 明确表扬("很好"、"谢谢")
- 继续使用(追问)
- 正面表情

负面信号:
- 批评("太长了"、"不够详细")
- 重新提问(表明不理解)
- 负面表情
"""
signals = []

for turn in history:
if turn['role'] == 'user':
content = turn['content']

# 简单情感分析
if any(word in content for word in ['很好', '谢谢', ' helpful']):
signals.append(1.0) # 正面
elif any(word in content for word in ['太长', '太短', '不清楚']):
signals.append(-1.0) # 负面
else:
signals.append(0.0) # 中性

return signals

显式偏好捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def capture_explicit_preference(self, user_statement: str) -> Dict:
"""
捕获用户明确表达的偏好

示例:
- "请简洁一点" → response_length = short
- "我需要详细解释" → response_length = detailed
- "用简单的语言" → response_style = casual
"""
prompt = f"""
分析用户的偏好表达:
"{user_statement}"

提取偏好(JSON 格式):
{{
"dimension": "response_length|response_style|...",
"value": "short|detailed|formal|casual|...",
"confidence": 0.0-1.0
}}
"""
response = self.llm.generate(prompt)
return parse_json(response)

组件 2:双层记忆更新

滑动窗口平均(Short-term)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class ShortTermMemory:
"""短期记忆:滑动窗口捕捉快速变化"""

def __init__(self, window_size=10, alpha=0.3):
self.window_size = window_size
self.alpha = alpha # 滑动窗口衰减因子
self.window = []

def update(self, preference_vector: np.ndarray):
"""
更新短期记忆

SW 公式:
SW_t = α * P_t + (1-α) * SW_{t-1}

但只考虑最近 window_size 个样本
"""
self.window.append(preference_vector)

# 保持窗口大小
if len(self.window) > self.window_size:
self.window.pop(0)

# 计算窗口平均
sw_vector = np.mean(self.window, axis=0)

return sw_vector

def get_vector(self) -> np.ndarray:
"""获取当前短期偏好向量"""
if not self.window:
return np.zeros(10) # 默认向量
return np.mean(self.window, axis=0)

指数移动平均(Long-term)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class LongTermMemory:
"""长期记忆:EMA 保持稳定趋势"""

def __init__(self, beta=0.95):
self.beta = beta # EMA 衰减因子
self.ema_vector = None
self.update_count = 0

def update(self, preference_vector: np.ndarray) -> np.ndarray:
"""
更新长期记忆

EMA 公式:
EMA_t = β * EMA_{t-1} + (1-β) * P_t

β 越大,越平滑稳定
β 越小,越敏感快速
"""
if self.ema_vector is None:
self.ema_vector = preference_vector.copy()
else:
self.ema_vector = (
self.beta * self.ema_vector +
(1 - self.beta) * preference_vector
)

self.update_count += 1
return self.ema_vector

def get_vector(self) -> np.ndarray:
"""获取当前长期偏好向量"""
if self.ema_vector is None:
return np.zeros(10)
return self.ema_vector

组件 3:偏好融合

双层融合策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class PreferenceFusion:
"""融合短期和长期偏好"""

def __init__(self, short_weight=0.4, long_weight=0.6):
self.short_weight = short_weight
self.long_weight = long_weight

self.short_term = ShortTermMemory(window_size=10, alpha=0.3)
self.long_term = LongTermMemory(beta=0.95)

def update_and_fuse(self, current_preference: np.ndarray) -> np.ndarray:
"""
更新并融合偏好

融合公式:
Fused = w_short * SW + w_long * EMA

其中 w_short + w_long = 1
"""
# 更新双层记忆
sw_vector = self.short_term.update(current_preference)
ema_vector = self.long_term.update(current_preference)

# 融合
fused = (
self.short_weight * sw_vector +
self.long_weight * ema_vector
)

return fused

def get_context(self) -> Dict:
"""获取偏好上下文(用于生成)"""
return {
'short_term': self.short_term.get_vector(),
'long_term': self.long_term.get_vector(),
'fused': self.get_fused_vector()
}

实验结果

实验设置

数据集:LoCoMo(Long-term Contextual Memory)

  • 5 个任务场景
  • 1000+ 长期对话
  • 人工标注偏好变化点

基线方法

  • No Memory(无记忆)
  • Static Memory(静态记忆)
  • Vector Retrieval(向量检索)
  • Knowledge Graph(知识图谱)
  • Simple Update(简单更新)

评估指标

  • 偏好预测准确率
  • 用户满意度评分
  • 任务完成率
  • 响应相关性

主要结果

偏好预测准确率

方法 长度偏好 风格偏好 密度偏好 平均
No Memory 45.2% 42.1% 38.5% 41.9%
Static Memory 58.3% 55.2% 52.1% 55.2%
Vector Retrieval 62.5% 59.8% 56.3% 59.5%
Simple Update 65.2% 62.1% 58.7% 62.0%
PAMU 78.5% 75.2% 72.3% 75.3%

提升:相比最佳基线 +13.3%

用户满意度

方法 1-5 分 推荐意愿
No Memory 2.8 15%
Static Memory 3.5 42%
Vector Retrieval 3.8 55%
PAMU 4.5 82%

任务完成率

场景 No Mem Static PAMU 提升
推荐系统 45% 62% 78% +16%
客户服务 52% 68% 82% +14%
个人助理 48% 65% 85% +20%
项目协作 42% 58% 75% +17%
学习辅导 55% 70% 88% +18%

消融实验

双层架构有效性

配置 准确率 说明
PAMU (完整) 75.3% SW + EMA
- SW (仅 EMA) 71.2% 缺失短期响应
- EMA (仅 SW) 68.5% 缺失长期稳定
无更新 55.2% 静态记忆

结论:双层架构各有贡献,协同效果最佳

超参数敏感性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
β (EMA 因子) 影响:

准确率

│ ● 最佳 (β=0.95)
│ ╱ ╲
│ ╱ ╲
│ ╱ ╲
└─────────────────────
0.5 0.7 0.9 0.99
β 值

β 太小:过度响应短期波动
β 太大:更新过慢,滞后于变化
推荐:β = 0.9-0.98

实践指南

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pamu import PAMUAgent
from langchain.llms import OpenAI

# 初始化
llm = OpenAI(model="gpt-4o")
agent = PAMUAgent(
llm=llm,
short_window_size=10,
ema_beta=0.95,
fusion_weights=(0.4, 0.6)
)

# 对话循环
for interaction in conversation:
# 提取偏好
preference = agent.extract_preference(interaction)

# 更新记忆
fused_pref = agent.update_memory(preference)

# 生成个性化响应
response = agent.generate(
query=interaction['content'],
preference_context=fused_pref
)

配置参数

参数 默认值 说明
short_window_size 10 短期窗口大小
short_alpha 0.3 短期衰减因子
long_beta 0.95 长期 EMA 因子
short_weight 0.4 短期融合权重
long_weight 0.6 长期融合权重

总结

PAMU 通过双层记忆更新机制实现了动态的偏好学习:

核心贡献

  1. 滑动窗口捕捉短期波动
  2. EMA 保持长期趋势
  3. 融合表示平衡两者

实际价值

  • 15-25% 准确率提升
  • 82% 用户推荐意愿
  • 适用于个性化助手、客服等场景

资源


评分: 4.4/5.0 ⭐⭐⭐⭐

推荐度: 推荐。长期代理个性化的有效解决方案。

© 2026 Generative AI Discovery All Rights Reserved.
Theme by hiero