Files
AstrBot/docs/v4/clients/memory.md
whatevertogo 1fec76eda1 feat: add platform client documentation and examples
- Introduced platform client documentation in `docs/v4/clients/platform.md` detailing methods for sending messages, images, and managing group members.
- Added example plugins for LLM chat and database functionalities in `docs/v4/examples/README.md`, `docs/v4/examples/llm-chat/README.md`, and `docs/v4/examples/database/README.md`.
- Enhanced quickstart guide with links to new documentation and example plugins.
- Implemented runtime contract tests to ensure compatibility of public capabilities and hooks.
2026-03-13 21:09:13 +08:00

6.6 KiB
Raw Blame History

记忆客户端

记忆客户端提供 AI 记忆存储能力,支持语义搜索。

概述

from astrbot_sdk import Context

# 通过 Context 访问
ctx.memory  # MemoryClient 实例

Memory vs DB 的区别

特性 DBClient MemoryClient
存储方式 键值存储 语义向量存储
检索方式 精确匹配 语义搜索
适用场景 配置、计数器、简单数据 AI 上下文、用户偏好、对话记忆

选择建议

  • 需要精确键查找 → 使用 db
  • 需要语义搜索 → 使用 memory

方法

save()

保存记忆项。

async def save(
    self,
    key: str,
    value: dict[str, Any] | None = None,
    **extra: Any,
) -> None

参数

  • key: str - 记忆项的唯一标识键
  • value: dict | None - 要存储的数据字典
  • **extra: Any - 额外的键值对

示例

# 保存用户偏好
await ctx.memory.save("user_pref", {
    "theme": "dark",
    "language": "zh",
    "interests": ["游戏", "音乐"]
})

# 使用关键字参数
await ctx.memory.save(
    "note:1",
    None,
    content="重要笔记",
    tags=["work", "urgent"],
    created_at="2024-01-01"
)

# 保存对话摘要
await ctx.memory.save("conversation:session_123", {
    "summary": "用户询问了天气,推荐了晴天出行",
    "topics": ["天气", "出行"],
    "sentiment": "positive"
})

get()

精确获取单个记忆项。

async def get(self, key: str) -> dict[str, Any] | None

参数

  • key: str - 记忆项的唯一键

返回dict | None - 记忆内容,不存在则返回 None

示例

# 获取用户偏好
pref = await ctx.memory.get("user_pref")
if pref:
    print(f"用户偏好主题: {pref.get('theme')}")
    print(f"用户兴趣: {pref.get('interests')}")

语义搜索记忆项。

async def search(self, query: str) -> list[dict[str, Any]]

参数

  • query: str - 搜索查询文本

返回list[dict] - 匹配的记忆项列表,按相关度排序

示例

# 搜索用户偏好相关记忆
results = await ctx.memory.search("用户喜欢什么颜色")
for item in results:
    print(f"键: {item['key']}")
    print(f"内容: {item['content']}")
    print(f"相关度: {item.get('score', 0)}")
    print("---")

# 搜索对话历史
results = await ctx.memory.search("之前讨论过天气吗")
if results:
    await event.reply("是的,我们之前讨论过天气话题")

delete()

删除记忆项。

async def delete(self, key: str) -> None

示例

# 删除过期记忆
await ctx.memory.delete("old_note")

# 删除用户数据
await ctx.memory.delete(f"user_data:{user_id}")

使用场景

场景 1用户偏好记忆

@on_command("remember")
async def remember_preference(self, event: MessageEvent, ctx: Context):
    """记住用户偏好"""
    preference = event.text.removeprefix("/remember").strip()

    # 保存偏好
    key = f"pref:{event.user_id}"
    prefs = await ctx.memory.get(key) or {"items": []}
    prefs["items"].append(preference)
    await ctx.memory.save(key, prefs)

    await event.reply(f"已记住:{preference}")

@on_command("what_do_i_like")
async def recall_preference(self, event: MessageEvent, ctx: Context):
    """回忆用户偏好"""
    query = "用户偏好 喜欢"
    results = await ctx.memory.search(query)

    if results:
        lines = ["您之前告诉过我:"]
        for item in results[:3]:
            lines.append(f"- {item.get('content', '未知')}")
        await event.reply("\n".join(lines))
    else:
        await event.reply("我还没有记住您的偏好")

场景 2对话上下文记忆

@on_message(keywords=["我"])
async def track_context(self, event: MessageEvent, ctx: Context):
    """跟踪用户提到的个人信息"""
    # 保存到记忆
    await ctx.memory.save(
        f"user_info:{event.user_id}:{event.session_id}",
        {
            "message": event.text,
            "timestamp": "2024-01-01",
            "type": "personal_info"
        }
    )

@on_command("recall")
async def recall_context(self, event: MessageEvent, ctx: Context):
    """回忆对话内容"""
    query = event.text.removeprefix("/recall").strip() or "用户说过什么"

    results = await ctx.memory.search(query)
    if results:
        await event.reply(f"您之前提到:{results[0].get('message', '未知')}")
    else:
        await event.reply("我没有找到相关记忆")

场景 3智能推荐

@on_command("recommend")
async def recommend(self, event: MessageEvent, ctx: Context):
    """基于记忆的智能推荐"""
    # 搜索用户兴趣相关的记忆
    interests = await ctx.memory.search(f"{event.user_id} 兴趣 爱好")

    if not interests:
        await event.reply("告诉我您的兴趣,我可以给您推荐内容!")
        return

    # 基于兴趣生成推荐
    interest_text = ", ".join(
        item.get("content", "")
        for item in interests[:3]
    )

    prompt = f"用户喜欢 {interest_text},推荐一些相关内容"
    recommendation = await ctx.llm.chat(prompt)
    await event.reply(recommendation)

最佳实践

1. 使用结构化键名

# 推荐:有层次结构的键名
"user:{user_id}:preferences"
"user:{user_id}:history:{session_id}"
"conversation:{session_id}:summary"

# 避免:无组织的键名
"data"
"info"
"temp"

2. 为搜索优化内容

# 好:包含可搜索的描述性文本
await ctx.memory.save("user_pref", {
    "description": "用户喜欢玩游戏和听音乐",
    "interests": ["游戏", "音乐"],
    "level": "advanced"
})

# 不好:过于抽象,难以语义搜索
await ctx.memory.save("user_pref", {
    "a": ["x", "y"],
    "b": 2
})

3. 结合 DB 和 Memory

# DB存储精确配置
await ctx.db.set("config:theme", "dark")

# Memory存储语义可搜索的内容
await ctx.memory.save("user_interests", {
    "description": "用户对游戏开发感兴趣",
    "tags": ["游戏", "开发", "Unity"]
})

注意事项

  1. 值必须是字典memory.save() 的 value 参数必须是 dict 类型
# 正确
await ctx.memory.save("key", {"value": 123})

# 错误
await ctx.memory.save("key", 123)  # TypeError
  1. 语义搜索依赖宿主实现:搜索质量取决于宿主的向量存储配置

相关文档