490 lines
13 KiB
Markdown
490 lines
13 KiB
Markdown
# 青龙记忆系统配置文档
|
|
|
|
> 创建时间: 2026-02-09
|
|
> 状态: ✅ 已验证有效
|
|
> 适用: 青龙 (192.168.0.31)
|
|
|
|
---
|
|
|
|
## 1. 系统架构
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 青龙 (192.168.0.31) │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────┐ ┌─────────────────┐ ┌────────────────┐ │
|
|
│ │ Qdrant │────▶│ simple_memory │────▶│ OpenClaw │ │
|
|
│ │ (向量库) │ │ (记忆工具) │ │ Gateway │ │
|
|
│ │ localhost │ │ /opt/mem0/ │ │ :18789 │ │
|
|
│ │ :6333 │ └─────────────────┘ └────────────────┘ │
|
|
│ └─────────────┘ │
|
|
│ ▲ │
|
|
│ │ │
|
|
│ ┌─────┴─────┐ │
|
|
│ │ Ollama │ │
|
|
│ │ localhost │ │
|
|
│ │ :11434 │ │
|
|
│ └───────────┘ │
|
|
│ ▲ │
|
|
│ │ nomic-embed-text:latest (本地嵌入) │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│
|
|
│ REST API
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 192.168.0.66 (代理服务器) │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────┐ │
|
|
│ │ Ollama │ │
|
|
│ │ :11434 │ │
|
|
│ │ │ │
|
|
│ │ qwen3:4b │ ← LLM (语言模型) │
|
|
│ │ (2381MB) │ │
|
|
│ └─────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 组件配置
|
|
|
|
### 2.1 Qdrant 向量数据库
|
|
|
|
**部署方式**: Docker Compose
|
|
|
|
```yaml
|
|
# docker-compose.yml (位于 /opt/memos/)
|
|
services:
|
|
qdrant:
|
|
image: qdrant/qdrant:v1.7.0
|
|
ports:
|
|
- "6333:6333"
|
|
- "6334:6334"
|
|
volumes:
|
|
- qdrant_data:/qdrant/storage
|
|
|
|
volumes:
|
|
qdrant_data:
|
|
```
|
|
|
|
**启动命令**:
|
|
```bash
|
|
cd /opt/memos
|
|
docker compose up -d
|
|
```
|
|
|
|
**集合配置**:
|
|
| 参数 | 值 |
|
|
|------|-----|
|
|
| 集合名称 | `mem0_memories` |
|
|
| 向量维度 | 768 |
|
|
| 距离度量 | Cosine (余弦相似度) |
|
|
| 状态 | green (健康) |
|
|
|
|
**验证命令**:
|
|
```bash
|
|
# 检查服务状态
|
|
curl http://localhost:6333/collections
|
|
|
|
# 查看集合详情
|
|
curl http://localhost:6333/collections/mem0_memories
|
|
|
|
# 查看所有记忆
|
|
curl http://localhost:6333/collections/mem0_memories/points/scroll \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"limit":10,"with_payload":true}'
|
|
```
|
|
|
|
---
|
|
|
|
### 2.2 本地 Ollama 嵌入模型
|
|
|
|
**安装模型**:
|
|
```bash
|
|
# 安装 nomic-embed-text (用于向量化)
|
|
ollama pull nomic-embed-text:latest
|
|
|
|
# 查看已安装模型
|
|
ollama list
|
|
```
|
|
|
|
**模型信息**:
|
|
| 模型 | 大小 | 用途 | 维度 |
|
|
|------|------|------|------|
|
|
| nomic-embed-text:latest | 261MB | 文本向量化 | 768 |
|
|
| mxbai-embed-large:latest | 638MB | 备用嵌入 | 1024 |
|
|
|
|
**验证命令**:
|
|
```bash
|
|
# 测试嵌入功能
|
|
curl http://localhost:11434/v1/embeddings \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"model":"nomic-embed-text:latest","input":"测试文本"}'
|
|
```
|
|
|
|
**预期输出**:
|
|
```json
|
|
{
|
|
"data": [{
|
|
"embedding": [0.123, 0.456, ...], // 768 维向量
|
|
"index": 0,
|
|
"object": "embedding"
|
|
}],
|
|
"model": "nomic-embed-text:latest",
|
|
"object": "list",
|
|
"usage": {"prompt_tokens": 10, "total_tokens": 10}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.3 远程 LLM (192.168.0.66)
|
|
|
|
**部署服务器**: 192.168.0.66
|
|
|
|
**安装模型**:
|
|
```bash
|
|
# 安装 qwen3:4b
|
|
ollama pull qwen3:4b
|
|
```
|
|
|
|
**模型信息**:
|
|
| 模型 | 大小 | 用途 |
|
|
|------|------|------|
|
|
| qwen3:4b | 2381MB | 语言模型推理 |
|
|
|
|
**验证命令**:
|
|
```bash
|
|
# 测试 LLM
|
|
curl http://192.168.0.66:11434/v1/chat/completions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"model": "qwen3:4b",
|
|
"messages": [{"role": "user", "content": "你好"}],
|
|
"stream": false
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 记忆系统工具
|
|
|
|
### 3.1 工具位置
|
|
|
|
```
|
|
/opt/mem0/
|
|
├── simple_memory.py # 主工具 (推荐使用)
|
|
├── qinglong_memory.py # 备用工具
|
|
├── config.yaml # mem0ai 配置 (暂未使用)
|
|
└── test_*.py # 测试脚本
|
|
```
|
|
|
|
### 3.2 simple_memory.py 功能
|
|
|
|
**添加记忆**:
|
|
```bash
|
|
python3 /opt/mem0/simple_memory.py add "这是青龙的测试记忆"
|
|
```
|
|
|
|
**搜索记忆**:
|
|
```bash
|
|
python3 /opt/mem0/simple_memory.py search "青龙"
|
|
```
|
|
|
|
**基于记忆对话**:
|
|
```bash
|
|
python3 /opt/mem0/simple_memory.py chat "青龙会做什么?"
|
|
```
|
|
|
|
---
|
|
|
|
### 3.3 完整源代码
|
|
|
|
```python
|
|
#!/usr/bin/env python3
|
|
"""
|
|
青龙记忆系统 - 稳定版
|
|
- Embedder: 本地 nomic-embed-text:latest
|
|
- LLM: 192.168.0.66 qwen3:4b
|
|
- 向量库: Qdrant localhost:6333
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import requests
|
|
import hashlib
|
|
import numpy as np
|
|
|
|
OLLAMA_LOCAL = 'http://localhost:11434'
|
|
OLLAMA_66 = 'http://192.168.0.66:11434'
|
|
QDRANT = 'http://localhost:6333'
|
|
COLLECTION = 'mem0_memories'
|
|
|
|
def get_embedding(text):
|
|
"""获取向量 (本地 nomic)"""
|
|
resp = requests.post(
|
|
f'{OLLAMA_LOCAL}/v1/embeddings',
|
|
json={'model': 'nomic-embed-text:latest', 'input': text}
|
|
)
|
|
return resp.json()['data'][0]['embedding']
|
|
|
|
def cosine_sim(a, b):
|
|
"""计算余弦相似度"""
|
|
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
|
|
|
|
def add_memory(content, user_id='qinglong'):
|
|
"""添加记忆"""
|
|
vector = get_embedding(content)
|
|
point_id = int(hashlib.md5(content.encode()).hexdigest()[:8], 16)
|
|
|
|
requests.put(
|
|
f'{QDRANT}/collections/{COLLECTION}/points',
|
|
json={
|
|
'points': [{
|
|
'id': point_id,
|
|
'vector': vector,
|
|
'payload': {'content': content, 'user_id': user_id}
|
|
}]
|
|
}
|
|
)
|
|
print(f'ADDED: {point_id}')
|
|
|
|
def search_memory(query, limit=5):
|
|
"""搜索记忆"""
|
|
query_vec = get_embedding(query)
|
|
|
|
resp = requests.post(
|
|
f'{QDRANT}/collections/{COLLECTION}/points/scroll',
|
|
json={'limit': 100, 'with_vector': True}
|
|
)
|
|
|
|
results = []
|
|
for p in resp.json()['result']['points']:
|
|
if p.get('vector') and p.get('payload'):
|
|
score = cosine_sim(query_vec, p['vector'])
|
|
results.append((p['payload']['content'], score))
|
|
|
|
results.sort(key=lambda x: x[1], reverse=True)
|
|
|
|
for content, score in results[:limit]:
|
|
print(f'- {content} (score: {score:.3f})')
|
|
|
|
def chat_with_memory(prompt):
|
|
"""基于记忆的对话"""
|
|
query_vec = get_embedding(prompt)
|
|
|
|
resp = requests.post(
|
|
f'{QDRANT}/collections/{COLLECTION}/points/scroll',
|
|
json={'limit': 100, 'with_vector': True}
|
|
)
|
|
|
|
memories = []
|
|
for p in resp.json()['result']['points']:
|
|
if p.get('vector') and p.get('payload'):
|
|
score = cosine_sim(query_vec, p['vector'])
|
|
if score > 0.7:
|
|
memories.append((p['payload']['content'], score))
|
|
|
|
memories.sort(key=lambda x: x[1], reverse=True)
|
|
context = '\n'.join([m[0] for m in memories[:3]])
|
|
|
|
# 调用 qwen3:4b
|
|
resp = requests.post(
|
|
f'{OLLAMA_66}/v1/chat/completions',
|
|
json={
|
|
'model': 'qwen3:4b',
|
|
'messages': [{'role': 'user', 'content': f'相关记忆:\n{context}\n\n用户: {prompt}'}],
|
|
'stream': False
|
|
}
|
|
)
|
|
return resp.json()['choices'][0]['message']['content']
|
|
|
|
if __name__ == '__main__':
|
|
cmd = sys.argv[1] if len(sys.argv) > 1 else 'search'
|
|
|
|
if cmd == 'add':
|
|
content = sys.argv[2] if len(sys.argv) > 2 else ''
|
|
if content:
|
|
add_memory(content)
|
|
else:
|
|
print('Usage: python3 simple_memory.py add "内容"')
|
|
|
|
elif cmd == 'search':
|
|
query = sys.argv[2] if len(sys.argv) > 2 else ''
|
|
if query:
|
|
search_memory(query)
|
|
else:
|
|
print('Usage: python3 simple_memory.py search "关键词"')
|
|
|
|
elif cmd == 'chat':
|
|
prompt = ' '.join(sys.argv[2:]) if len(sys.argv) > 2 else ''
|
|
if prompt:
|
|
print(chat_with_memory(prompt))
|
|
else:
|
|
print('Usage: python3 simple_memory.py chat "用户问题"')
|
|
```
|
|
|
|
---
|
|
|
|
## 4. OpenClaw 集成
|
|
|
|
### 4.1 配置文件位置
|
|
|
|
```
|
|
/root/.openclaw/openclaw.json
|
|
```
|
|
|
|
### 4.2 关键配置
|
|
|
|
```json
|
|
{
|
|
"models": {
|
|
"providers": {
|
|
"minimax": { ... },
|
|
"deepseek": { ... },
|
|
"ollama": {
|
|
"baseUrl": "http://localhost:11434/v1",
|
|
"apiKey": "ollama-local",
|
|
"models": [
|
|
{
|
|
"id": "nomic-embed-text:latest",
|
|
"name": "Nomic Embed"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"agents": {
|
|
"defaults": {
|
|
"model": {
|
|
"primary": "minimax/minimax-m2.1"
|
|
},
|
|
"memorySearch": {
|
|
"provider": "openai",
|
|
"remote": {
|
|
"baseUrl": "http://localhost:11434/v1",
|
|
"apiKey": "sk-local-ollama-fake-key"
|
|
},
|
|
"model": "nomic-embed-text:latest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4.3 工具集成 (可选)
|
|
|
|
将 simple_memory.py 添加为 OpenClaw 工具:
|
|
|
|
```json
|
|
{
|
|
"tools": {
|
|
"custom": {
|
|
"memory_add": {
|
|
"command": "python3 /opt/mem0/simple_memory.py add",
|
|
"args": ["content"]
|
|
},
|
|
"memory_search": {
|
|
"command": "python3 /opt/mem0/simple_memory.py search",
|
|
"args": ["query"]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 问题排查
|
|
|
|
### 5.1 常见问题
|
|
|
|
| 问题 | 原因 | 解决方案 |
|
|
|------|------|----------|
|
|
| 向量维度不匹配 | 集合创建时维度错误 | 删除集合,重新创建 768 维 |
|
|
| 搜索无结果 | 没有设置 `with_vector` | 添加 `with_vector: true` |
|
|
| Qdrant 无法连接 | Docker 容器未运行 | `docker ps` 检查,`docker start` |
|
|
| Ollama 连接超时 | 服务未启动 | `ollama serve` 启动服务 |
|
|
| payload 为空 | 存储时未包含 payload | 确认 upsert 请求包含 payload |
|
|
|
|
### 5.2 调试命令
|
|
|
|
```bash
|
|
# 1. 检查 Qdrant 服务
|
|
curl http://localhost:6333/health
|
|
|
|
# 2. 检查集合
|
|
curl http://localhost:6333/collections/mem0_memories
|
|
|
|
# 3. 查看所有记忆 (带向量)
|
|
curl http://localhost:6333/collections/mem0_memories/points/scroll \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"limit":10,"with_vector":true}'
|
|
|
|
# 4. 测试嵌入
|
|
curl http://localhost:11434/v1/embeddings \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"model":"nomic-embed-text:latest","input":"测试"}'
|
|
|
|
# 5. 检查 Docker 状态
|
|
docker ps | grep qdrant
|
|
```
|
|
|
|
### 5.3 重置集合
|
|
|
|
```bash
|
|
# 删除旧集合
|
|
curl -X DELETE http://localhost:6333/collections/mem0_memories
|
|
|
|
# 重建集合 (768维)
|
|
curl -X PUT http://localhost:6333/collections/mem0_memories \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"vectors":{"size":768,"distance":"Cosine"}}'
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 性能指标
|
|
|
|
### 6.1 当前状态
|
|
|
|
| 指标 | 值 |
|
|
|------|-----|
|
|
| 记忆数量 | 3 条 |
|
|
| 向量维度 | 768 |
|
|
| 搜索相似度 | 0.6 - 0.9+ |
|
|
| Qdrant 状态 | green |
|
|
|
|
### 6.2 资源占用
|
|
|
|
| 组件 | 内存 | CPU |
|
|
|------|------|-----|
|
|
| Qdrant | ~100MB | 低 |
|
|
| Ollama (嵌入) | ~300MB | 低 |
|
|
| 192.168.0.66 qwen3:4b | ~2.4GB | 中 |
|
|
|
|
---
|
|
|
|
## 7. 未来优化
|
|
|
|
- [ ] 将 simple_memory.py 集成到 OpenClaw 工具
|
|
- [ ] 添加记忆自动过期机制
|
|
- [ ] 实现多用户记忆隔离
|
|
- [ ] 优化搜索算法 (使用 HNSW 索引)
|
|
- [ ] 添加记忆可视化界面
|
|
|
|
---
|
|
|
|
## 8. 参考资料
|
|
|
|
- Qdrant 文档: https://qdrant.tech/documentation/
|
|
- Ollama 文档: https://github.com/ollama/ollama
|
|
- OpenAI 兼容 API: https://github.com/ollama/ollama/blob/main/docs/openai.md
|
|
|
|
---
|
|
|
|
> 文档版本: v1.0 (2026-02-09)
|
|
> 作者: 2号机 (守护者)
|