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

310 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 记忆客户端
记忆客户端提供 AI 记忆存储能力,支持语义搜索。
## 概述
```python
from astrbot_sdk import Context
# 通过 Context 访问
ctx.memory # MemoryClient 实例
```
### Memory vs DB 的区别
| 特性 | DBClient | MemoryClient |
|------|----------|--------------|
| 存储方式 | 键值存储 | 语义向量存储 |
| 检索方式 | 精确匹配 | 语义搜索 |
| 适用场景 | 配置、计数器、简单数据 | AI 上下文、用户偏好、对话记忆 |
**选择建议**
- 需要精确键查找 → 使用 `db`
- 需要语义搜索 → 使用 `memory`
---
## 方法
### save()
保存记忆项。
```python
async def save(
self,
key: str,
value: dict[str, Any] | None = None,
**extra: Any,
) -> None
```
**参数**
- `key: str` - 记忆项的唯一标识键
- `value: dict | None` - 要存储的数据字典
- `**extra: Any` - 额外的键值对
**示例**
```python
# 保存用户偏好
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()
精确获取单个记忆项。
```python
async def get(self, key: str) -> dict[str, Any] | None
```
**参数**
- `key: str` - 记忆项的唯一键
**返回**`dict | None` - 记忆内容,不存在则返回 `None`
**示例**
```python
# 获取用户偏好
pref = await ctx.memory.get("user_pref")
if pref:
print(f"用户偏好主题: {pref.get('theme')}")
print(f"用户兴趣: {pref.get('interests')}")
```
---
### search()
语义搜索记忆项。
```python
async def search(self, query: str) -> list[dict[str, Any]]
```
**参数**
- `query: str` - 搜索查询文本
**返回**`list[dict]` - 匹配的记忆项列表,按相关度排序
**示例**
```python
# 搜索用户偏好相关记忆
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()
删除记忆项。
```python
async def delete(self, key: str) -> None
```
**示例**
```python
# 删除过期记忆
await ctx.memory.delete("old_note")
# 删除用户数据
await ctx.memory.delete(f"user_data:{user_id}")
```
---
## 使用场景
### 场景 1用户偏好记忆
```python
@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对话上下文记忆
```python
@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智能推荐
```python
@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. 使用结构化键名
```python
# 推荐:有层次结构的键名
"user:{user_id}:preferences"
"user:{user_id}:history:{session_id}"
"conversation:{session_id}:summary"
# 避免:无组织的键名
"data"
"info"
"temp"
```
### 2. 为搜索优化内容
```python
# 好:包含可搜索的描述性文本
await ctx.memory.save("user_pref", {
"description": "用户喜欢玩游戏和听音乐",
"interests": ["游戏", "音乐"],
"level": "advanced"
})
# 不好:过于抽象,难以语义搜索
await ctx.memory.save("user_pref", {
"a": ["x", "y"],
"b": 2
})
```
### 3. 结合 DB 和 Memory
```python
# DB存储精确配置
await ctx.db.set("config:theme", "dark")
# Memory存储语义可搜索的内容
await ctx.memory.save("user_interests", {
"description": "用户对游戏开发感兴趣",
"tags": ["游戏", "开发", "Unity"]
})
```
---
## 注意事项
1. **值必须是字典**`memory.save()` 的 value 参数必须是 `dict` 类型
```python
# 正确
await ctx.memory.save("key", {"value": 123})
# 错误
await ctx.memory.save("key", 123) # TypeError
```
2. **语义搜索依赖宿主实现**:搜索质量取决于宿主的向量存储配置
---
## 相关文档
- [API 参考](../api-reference.md)
- [DB 客户端](db.md) - 精确键值存储
- [LLM 客户端](llm.md) - 结合 AI 能力