AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时

凌晨两点,用户群里发来一张截图:AI 客服回复工单时,把另一个用户的手机号和收货地址带了出来。我第一反应是模型幻觉,结果查 Redis 发现,两个不同 user_id 的会话共用了同一个 session_id 作为 key,上下文直接串号。这不是模型的问题,是记忆层在裸奔。后来我用 pytest + Redis 搭了一套一致性验证,才把这类 bug 摁死。

问题拆解

AI Agent 的记忆存储跟普通缓存不一样:缓存丢了只是慢一点,记忆串了会直接泄露隐私、带偏对话。我们团队用 Redis 存 Agent 的短期记忆,多轮对话靠它保持连贯。上线后偶发出现 A 用户看到 B 的历史消息。根因不是模型,而是记忆层的三类问题:key 设计缺少用户维度、TTL 刷新逻辑混乱、序列化协议不统一。常规方案为什么不行?靠 code review 和手工测试发现不了,因为串号是并发、边界条件叠加后的结果;mock Redis 又验证不了真实 TTL 和原子性。最后我决定把记忆层当基础设施,用 pytest + Redis 写一致性测试。

方案设计

选 pytest + Redis 而不是单测 mock,核心原因是 Redis 的真实行为------TTL 计算、WATCH 乐观锁、序列化后的二进制差异------是 mock 模拟不出来的。pytest 的 fixture 可以给每个测试一个干净的 db,真实 Redis 用 Docker 起一个即可。设计上我们把记忆读写封装成 MemoryStore,然后针对三类不变量写测试:key 隔离性、TTL 与版本兼容、并发追加一致性。为什么不选直接用生产库测?太危险;为什么不选只写单测?因为单测会把 Redis 当普通 dict 用,掩盖 TTL 和并发问题。

核心实现

这段代码解决测试隔离问题:每个测试用例拿到一个独立的 Redis db,避免数据串号影响断言。

python 复制代码
# conftest.py
import pytest
import redis

@pytest.fixture
def redis_client():
    """连接本地 Redis,测试前清空当前 db,保证隔离"""
    client = redis.Redis(host="localhost", port=6379, db=15, decode_responses=True)
    client.flushdb()
    yield client
    client.flushdb()
    client.close()

这个类封装了生产级的 Redis 记忆读写,包含 key 命名空间、JSON 版本化、SETEX TTL、以及并发安全的 WATCH 追加。关键行加了注释。

python 复制代码
# memory_store.py
import json
from typing import Any, Dict, List, Optional

import redis
from redis.exceptions import WatchError

class MemoryStore:
    """AI Agent 短期记忆存储,负责 key 隔离、TTL 和版本化序列化"""

    def __init__(self, client: redis.Redis, ttl: int = 3600):
        self.client = client
        self.ttl = ttl
        self.version = 1  # 序列化
相关推荐
孟健1 小时前
Claude Code 同需求写两版对比:装不装 frontend-design 差多远?
前端·ai编程·claude
梦de天空一米16883 小时前
【一个重复id让游戏卡在62%,聊聊配置表检查】
前端
用户3434612783203 小时前
用户认证系统在高并发下的幂等性与限流策略踩坑实录
css
ryn483983 小时前
01 一个功能模块,怎么分层才不乱
前端·ai编程·claude
Amos_Web3 小时前
通过 Rspack 源码学 Rust(五):读懂 Result 与问号运算符的错误返回
前端
杨航 AI3 小时前
JEV的用法
java·前端·数据库
Amos_Web3 小时前
Rspack 源码解析(三十五):rspack_error 如何用 miette 渲染带源码定位的错误链
前端
去伪存真3 小时前
高敏资产场景下的大模型协同设计架构
前端·agent
修炼的dance3 小时前
OCR预处理测了108组,纠斜去噪有用,坑在顺序和力度
前端
疯华整猫3 小时前
Android 16 后台常驻适配:用 Trae 搭一套“前台服务 + 加急 Job”的可存活架构
前端