Metadata-Version: 2.4
Name: mem1
Version: 0.0.6
Summary: 基于云服务的用户记忆系统
Project-URL: Homepage, https://github.com/sougannkyou/mem1
Project-URL: Repository, https://github.com/sougannkyou/mem1
Author: Song
License: MIT
Keywords: langchain,llm,memory,user-profile
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.12
Requires-Dist: dashscope>=1.14.0
Requires-Dist: elasticsearch>=8.0.0
Requires-Dist: openai>=1.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: dev
Requires-Dist: ipython>=8.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# mem1 - 用户记忆系统

让 AI 真正"记住"用户：三层记忆架构 + 图片记忆 + 话题隔离 + 业务场景解耦。

## 核心特性

- **三层记忆架构**：短期会话 → 用户画像 → 长期记录
- **话题隔离**：同一用户可有多个话题，对话按话题隔离，画像跨话题共享
- **图片记忆**：存储图片时自动调用 VL 模型生成描述（OCR + 内容理解），搜索时基于文字描述召回
- **业务解耦**：通过 ProfileTemplate 适配不同场景
- **画像自动更新**：基于对话轮数/时间自动触发 LLM 更新用户画像

## 安装

```bash
pip install mem1
```

## 快速开始

```python
from mem1 import Mem1Memory, Mem1Config

# 从环境变量加载配置
config = Mem1Config.from_env()

# 创建记忆实例（绑定用户和话题）
memory = Mem1Memory(config, user_id="user001", topic_id="project_a")

# 添加对话
memory.add_conversation(
    messages=[
        {"role": "user", "content": "你好，我是张明"},
        {"role": "assistant", "content": "你好张明！"}
    ]
)

# 获取上下文（含用户画像 + 最近对话）
ctx = memory.get_context()
print(ctx['import_content'])   # 用户画像
print(ctx['normal_content'])   # 最近对话记录
print(ctx['current_time'])     # 当前时间
```

## 环境变量配置

```bash
# LLM 配置
MEM1_LLM_API_KEY=your-api-key
MEM1_LLM_BASE_URL=https://api.deepseek.com
MEM1_LLM_MODEL=deepseek-chat

# ES 配置
MEM1_ES_HOSTS=http://localhost:9200
MEM1_ES_INDEX=conversation_history

# 记忆配置
MEM1_MEMORY_DIR=./memories
MEM1_AUTO_UPDATE_PROFILE=true
MEM1_MAX_PROFILE_CHARS=3000
MEM1_UPDATE_INTERVAL_ROUNDS=5
MEM1_UPDATE_INTERVAL_MINUTES=3
MEM1_SAVE_ASSISTANT_MESSAGES=true
MEM1_MAX_ASSISTANT_CHARS=500
MEM1_CONTEXT_DAYS_LIMIT=31

# VL 视觉模型（可选，配置 MODEL 即启用，使用 dashscope SDK）
MEM1_VL_MODEL=qwen-vl-max
MEM1_VL_API_KEY=your-dashscope-key
```

## 图片记忆

### 实现机制

1. **存储阶段**：`add_conversation()` 遇到图片时自动调用 VL 模型（如 Qwen-VL）
2. **VL 处理**：生成包含三部分的描述文本
   - 【用户描述】用户发送图片时的文字说明
   - 【文字内容】OCR 识别图片中的文字
   - 【图片描述】VL 模型对图片内容的理解
3. **数据存储**：图片信息存入 ES 对话记录的 `images` 字段，图片文件存本地
4. **搜索召回**：`search_images()` 基于描述文本进行关键词匹配，返回图片路径

### ES 数据结构

```json
{
  "user_id": "user001",
  "topic_id": "default",
  "timestamp": "2026-01-06 16:46:03",
  "messages": [
    {"role": "user", "content": "...", "image_refs": ["20260106_164603_report.png"]}
  ],
  "images": [
    {
      "filename": "20260106_164603_report.png",
      "description": "【用户描述】...\n\n【文字内容】...\n\n【图片描述】...",
      "timestamp": "2026-01-06 16:46:16",
      "original_name": "report.png"
    }
  ]
}
```

### 使用示例

```python
# 添加带图片的对话
memory.add_conversation(
    messages=[{"role": "user", "content": "这是今天的报表"}],
    images=[{"path": "./report.png", "filename": "report.png"}]
)

# 搜索图片（基于 VL 生成的描述）
results = memory.search_images(query="报表")
# 返回: [{"filename": "...", "description": "...", "abs_path": "..."}]
```

## 核心接口

```python
memory = Mem1Memory(config, user_id="user001", topic_id="project_a")

# 添加对话
memory.add_conversation(messages=[...], images=[...], metadata={...})

# 获取上下文（画像 + 最近 N 天对话）
ctx = memory.get_context(days_limit=31)

# 查询对话
convs = memory.get_conversations(days_limit=7)
all_convs = memory.get_all_conversations(days_limit=7)

# 图片搜索
results = memory.search_images(query="麻花")

# 话题管理
topics = memory.list_topics()
memory.delete_topic()
memory.delete_user()
```

## ES 索引

| 索引 | 用途 |
|------|------|
| `conversation_history` | 对话记录（含图片索引） |
| `mem1_user_state` | 用户状态 |
| `mem1_user_profile` | 用户画像 |

## LLM 提示词建议

使用 `get_context()` 获取上下文后，建议在 system prompt 中加入以下规则，避免 LLM 编造信息：

```
## 重要规则
1. 回答必须基于上述对话记录中的实际内容，严禁编造任何信息
2. 涉及数字（金额、数量、百分比、日期等）时，必须从对话记录中原样提取，不得估算或编造
3. 需要汇总累加时，必须列出计算过程（如：23+31+18+25=97）
4. 涉及人名、公司名、账号名等实体时，必须使用对话中的原始名称
5. 如果对话记录中没有相关信息，请明确说"对话记录中未提及"，不要猜测
```

## License

MIT
