欢迎光临
我们一直在努力

使用 Docker 部署 PostgreSQL + pgvector 完整步骤(映射端口 5433),适用于memu项目数据库支持!

测试代码

"""
MemU 框架完整 CRUD 操作示例

这个脚本演示了如何使用 MemU 框架进行:
– Create(创建):创建新的记忆项
– Read(读取):读取和查询记忆项
– Update(更新):更新现有记忆项
– Delete(删除):删除记忆项
– Retrieve(检索):使用自然语言检索记忆

使用方法:
python test.py
"""

import asyncio
import os
from typing import Dict, List, Any

from memu.app import MemoryService

class MemUCRUDDemo:
"""MemU CRUD 操作演示类"""

def __init__(self, api_key: str):
"""初始化 MemoryService"""
self.service = MemoryService(
# LLM 配置
llm_profiles={
"default": {
"base_url": "https://api.siliconflow.cn/v1",
"api_key": api_key,
"chat_model": "Qwen/Qwen2.5-Coder-32B-Instruct",
"client_backend": "sdk"
},
"embedding": {
"base_url": "https://api.siliconflow.cn/v1",
"api_key": api_key,
"embed_model": "BAAI/bge-large-zh-v1.5"
}
},
# PostgreSQL 数据库配置(Docker 容器,端口 5433)
database_config={
"metadata_store": {
"provider": "postgres",
"dsn": "postgresql://root:123456@localhost:5433/root"
}
},
# 记忆类别配置
memorize_config={
"memory_categories": [
{"name": "personal_info", "description": "个人信息和基本资料"},
{"name": "skills", "description": "技能和专业能力"},
{"name": "preferences", "description": "偏好和习惯"},
{"name": "work_experience", "description": "工作经验和项目经历"},
]
},
)
self.created_items = [] # 存储创建的记忆项 ID

async def demo_create(self) > List[str]:
"""演示创建(Create)操作"""
print("\\n" + "="*60)
print("1. CREATE(创建)操作演示")
print("="*60)

# 创建多个不同类型的记忆项
memories_to_create = [
{
"memory_type": "profile",
"memory_content": "用户名叫张三,是一位30岁的软件工程师,居住在北京",
"memory_categories": ["personal_info"],
},
{
"memory_type": "skill",
"memory_content": "精通 Python、JavaScript 和 Go 语言,有5年全栈开发经验",
"memory_categories": ["skills"],
},
{
"memory_type": "behavior",
"memory_content": "喜欢早上编码,习惯使用 VS Code 编辑器,偏好敏捷开发方法",
"memory_categories": ["preferences"],
},
{
"memory_type": "event",
"memory_content": "2023年主导开发了一个微服务架构的电商平台,服务百万用户",
"memory_categories": ["work_experience"],
},
]

created_ids = []
for idx, memory_data in enumerate(memories_to_create, 1):
try:
result = await self.service.create_memory_item(**memory_data)
item_id = result.get("memory_item", {}).get("id")
created_ids.append(item_id)

print(f"\\n[OK] 记忆项 {idx} 创建成功:")
print(f" – ID: {item_id}")
print(f" – 类型: {memory_data['memory_type']}")
print(f" – 内容: {memory_data['memory_content'][:50]}…")
print(f" – 分类: {', '.join(memory_data['memory_categories'])}")

except Exception as e:
print(f"\\n[FAIL] 记忆项 {idx} 创建失败: {e}")

self.created_items = created_ids
print(f"\\n总计创建了 {len(created_ids)} 个记忆项")
return created_ids

async def demo_read(self, item_ids: List[str]):
"""演示读取(Read)操作"""
print("\\n" + "="*60)
print("2. READ(读取)操作演示")
print("="*60)

if not item_ids:
print("\\n没有可读取的记忆项")
return

# 读取单个记忆项(通过 list 方法)
print("\\n— 读取单个记忆项 —")
try:
first_item_id = item_ids[0]
# MemU 没有 get_memory_item 方法,使用 list_memory_items 获取所有项
all_items_result = await self.service.list_memory_items()
all_items = all_items_result.get('items', [])

# 在结果中查找指定 ID 的项
item = next((i for i in all_items if i.get('id') == first_item_id), None)

if item:
print(f"\\n[OK] 成功读取记忆项:")
print(f" – ID: {item.get('id')}")
print(f" – 类型: {item.get('memory_type')}")
print(f" – 摘要: {item.get('summary')}")
print(f" – 创建时间: {item.get('created_at')}")
else:
print(f"\\n[FAIL] 未找到 ID 为 {first_item_id} 的记忆项")

except Exception as e:
print(f"\\n[FAIL] 读取失败: {e}")

# 列出所有记忆项
print("\\n— 列出所有记忆项 —")
try:
result = await self.service.list_memory_items()
items = result.get('items', [])

print(f"\\n[OK] 找到 {len(items)} 个记忆项:")
for idx, item in enumerate(items, 1):
print(f"\\n {idx}. ID: {item.get('id')}")
print(f" 类型: {item.get('memory_type')}")
print(f" 摘要: {item.get('summary', '')[:60]}…")

except Exception as e:
print(f"\\n[FAIL] 列出记忆项失败: {e}")

# 列出所有类别
print("\\n— 列出所有记忆类别 —")
try:
result = await self.service.list_memory_categories()
categories = result.get('categories', [])

print(f"\\n[OK] 找到 {len(categories)} 个类别:")
for idx, category in enumerate(categories, 1):
print(f"\\n {idx}. 名称: {category.get('name')}")
print(f" 描述: {category.get('description', 'N/A')}")
summary = category.get('summary', '')
if summary:
print(f" 摘要: {summary[:80]}…")

except Exception as e:
print(f"\\n[FAIL] 列出类别失败: {e}")

async def demo_update(self, item_ids: List[str]):
"""演示更新(Update)操作"""
print("\\n" + "="*60)
print("3. UPDATE(更新)操作演示")
print("="*60)

if not item_ids:
print("\\n没有可更新的记忆项")
return

# 更新第一个记忆项
try:
item_id = item_ids[0]

# 先读取原始内容
all_items_result = await self.service.list_memory_items()
all_items = all_items_result.get('items', [])
original = next((i for i in all_items if i.get('id') == item_id), None)

if original:
print(f"\\n原始内容:")
print(f" – 摘要: {original.get('summary')}")

# 更新内容(参数名是 memory_id,不是 item_id)
updated_content = "用户名叫张三,是一位30岁的高级软件工程师,居住在北京,拥有计算机硕士学位"

result = await self.service.update_memory_item(
memory_id=item_id, # 注意:参数名是 memory_id
memory_content=updated_content,
)

print(f"\\n[OK] 记忆项更新成功:")
print(f" – ID: {item_id}")
print(f" – 新内容: {updated_content}")

# 再次读取验证更新
await asyncio.sleep(1) # 等待更新完成
all_items_result = await self.service.list_memory_items()
all_items = all_items_result.get('items', [])
updated = next((i for i in all_items if i.get('id') == item_id), None)

if updated:
print(f"\\n更新后的摘要:")
print(f" – {updated.get('summary')}")
else:
print(f"\\n[FAIL] 未找到 ID 为 {item_id} 的记忆项")

except Exception as e:
print(f"\\n[FAIL] 更新失败: {e}")

async def demo_retrieve(self):
"""演示检索(Retrieve)操作"""
print("\\n" + "="*60)
print("4. RETRIEVE(检索)操作演示")
print("="*60)

# 定义多个查询
queries = [
"用户的基本信息是什么?",
"用户会哪些编程语言?",
"用户的工作习惯和偏好",
"用户有什么项目经验?",
]

for idx, query_text in enumerate(queries, 1):
print(f"\\n— 查询 {idx}: {query_text} —")

try:
# 使用 RAG 方法检索(方法在初始化时配置)
result = await self.service.retrieve(
queries=[{"role": "user", "content": {"text": query_text}}]
)

# 显示检索结果
items = result.get("items", [])
categories = result.get("categories", [])

print(f"\\n[OK] 找到 {len(items)} 个相关记忆项:")
for item_idx, item in enumerate(items[:3], 1): # 只显示前3个
print(f"\\n {item_idx}. 类型: {item.get('memory_type')}")
print(f" 摘要: {item.get('summary', '')[:80]}…")
if 'score' in item:
print(f" 相似度: {item.get('score', 0):.4f}")

if categories:
print(f"\\n 相关类别: {', '.join([c.get('name', '') for c in categories[:3]])}")

except Exception as e:
print(f"\\n[FAIL] 检索失败: {e}")

async def demo_delete(self, item_ids: List[str]):
"""演示删除(Delete)操作"""
print("\\n" + "="*60)
print("5. DELETE(删除)操作演示")
print("="*60)

if not item_ids:
print("\\n没有可删除的记忆项")
return

# 删除最后一个记忆项
if len(item_ids) > 0:
item_id = item_ids[1]

try:
# 先读取要删除的项
all_items_result = await self.service.list_memory_items()
all_items = all_items_result.get('items', [])
item = next((i for i in all_items if i.get('id') == item_id), None)

if item:
print(f"\\n准备删除记忆项:")
print(f" – ID: {item_id}")
print(f" – 类型: {item.get('memory_type')}")
print(f" – 摘要: {item.get('summary', '')[:60]}…")

# 执行删除(参数名是 memory_id,不是 item_id)
await self.service.delete_memory_item(memory_id=item_id)
print(f"\\n[OK] 记忆项删除成功")

# 验证删除
await asyncio.sleep(1) # 等待删除完成
all_items_result = await self.service.list_memory_items()
all_items = all_items_result.get('items', [])
deleted_item = next((i for i in all_items if i.get('id') == item_id), None)

if deleted_item:
print(f"\\n[FAIL] 警告: 记忆项仍然存在")
else:
print(f"[OK] 验证: 记忆项已被删除")
else:
print(f"\\n[FAIL] 未找到 ID 为 {item_id} 的记忆项")

except Exception as e:
print(f"\\n[FAIL] 删除失败: {e}")

async def demo_memorize(self):
"""演示 memorize() 方法 – 从文件提取记忆"""
print("\\n" + "="*60)
print("6. MEMORIZE(记忆化)操作演示")
print("="*60)

# 创建一个临时对话文件
import json
import tempfile

conversation = {
"messages": [
{"role": "user", "content": "我最近在学习 Rust 语言"},
{"role": "assistant", "content": "很好!Rust 是一门很棒的系统编程语言"},
{"role": "user", "content": "是的,我特别喜欢它的内存安全特性"},
{"role": "assistant", "content": "Rust 的所有权系统确实很独特"},
]
}

# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False, encoding='utf-8') as f:
json.dump(conversation, f, ensure_ascii=False)
temp_file = f.name

try:
print(f"\\n从对话文件提取记忆…")
print(f"文件: {temp_file}")

result = await self.service.memorize(
resource_url=temp_file,
modality="conversation"
)

items = result.get("items", [])
categories = result.get("categories", [])

print(f"\\n[OK] 记忆化成功:")
print(f" – 提取了 {len(items)} 个记忆项")
print(f" – 更新了 {len(categories)} 个类别")

if items:
print(f"\\n 提取的记忆项:")
for idx, item in enumerate(items, 1):
print(f"\\n {idx}. 类型: {item.get('memory_type')}")
print(f" 摘要: {item.get('summary', '')[:60]}…")

except Exception as e:
print(f"\\n[FAIL] 记忆化失败: {e}")
finally:
# 清理临时文件
try:
os.unlink(temp_file)
except:
pass

async def main():
"""主函数 – 运行所有 CRUD 演示"""
print("\\n" + "="*60)
print("MemU 框架 CRUD 操作完整演示")
print("="*60)

# 创建演示实例
api_key = "硅基流动秘钥!"
demo = MemUCRUDDemo(api_key)

try:
# 1. 创建记忆项
created_ids = await demo.demo_create()
print(created_ids)

# 等待一下,确保数据已保存
await asyncio.sleep(1)

# 2. 读取记忆项
await demo.demo_read(created_ids)

# 3. 更新记忆项
await demo.demo_update(created_ids)

# 4. 检索记忆
await demo.demo_retrieve()

# 5. 记忆化操作
await demo.demo_memorize()

# 6. 删除记忆项
await demo.demo_delete(created_ids)

except Exception as e:
print(f"\\n发生错误: {e}")
import traceback
traceback.print_exc()

if __name__ == "__main__":
asyncio.run(main())

前置条件

✅ Docker Desktop 已安装并运行

✅ 端口 5433 未被占用


步骤 1:拉取并启动 PostgreSQL 容器

打开命令行,执行:

docker run -d \\
–name memu-postgres \\
-e POSTGRES_USER=root \\
-e POSTGRES_PASSWORD=123456 \\
-e POSTGRES_DB=root \\
-p 5433:5432 \\
pgvector/pgvector:pg16

参数说明:

  • -d: 后台运行
  • –name memu-postgres: 容器名称
  • -e POSTGRES_USER=root: 数据库用户名
  • -e POSTGRES_PASSWORD=123456: 数据库密码
  • -e POSTGRES_DB=root: 默认数据库名
  • -p 5433:5432: 端口映射(宿主机5433 → 容器5432)
  • pgvector/pgvector:pg16: 使用带 pgvector 的 PostgreSQL 16 镜像

步骤 2:验证容器运行状态

docker ps | findstr memu-postgres

预期输出:
f045f26e59ce pgvector/pgvector:pg16 … Up X minutes 0.0.0.0:5433->5432/tcp memu-postgres


步骤 3:验证 pgvector 扩展

docker exec memu-postgres psql -U root -d root -c "CREATE EXTENSION IF NOT EXISTS vector;"

预期输出:
CREATE EXTENSION


步骤 4:安装 Python 依赖

pip install psycopg2-binary asyncpg pgvector

预期输出:
Successfully installed asyncpg-0.31.0 psycopg2-binary-2.9.11 pgvector-0.4.2


步骤 5:配置 MemU 框架

编辑 test.py 文件,在 MemoryService 初始化中添加:

self.service = MemoryService(
llm_profiles={
"default": {
"base_url": "https://api.siliconflow.cn/v1",
"api_key": api_key,
"chat_model": "Qwen/Qwen2.5-Coder-32B-Instruct",
"client_backend": "sdk"
},
"embedding": {
"base_url": "https://api.siliconflow.cn/v1",
"api_key": api_key,
"embed_model": "BAAI/bge-large-zh-v1.5"
}
},
# PostgreSQL 数据库配置
database_config={
"metadata_store": {
"provider": "postgres",
"dsn": "postgresql://root:123456@localhost:5433/root"
}
},
memorize_config={
"memory_categories": [
{"name": "personal_info", "description": "个人信息和基本资料"},
{"name": "skills", "description": "技能和专业能力"},
{"name": "preferences", "description": "偏好和习惯"},
{"name": "work_experience", "description": "工作经验和项目经历"},
]
},
)


步骤 6:测试连接

运行测试脚本:

python test.py

预期输出:

============================================================
MemU 框架 CRUD 操作完整演示
============================================================

============================================================
1. CREATE(创建)操作演示
============================================================

[OK] 记忆项 1 创建成功:
– ID: b0e80599-1910-46a5-a7cf-bea4f4a35fbc
...

步骤 7:验证数据持久化

查看数据库表:

docker exec memu-postgres psql -U root -d root -c "\\dt"

预期输出:

Schema | Name | Type | Owner
——–+——————-+——-+——-
public | alembic_version | table | root
public | category_items | table | root
public | memory_categories | table | root
public | memory_items | table | root
public | resources | table | root

查看记忆项数量:

docker exec memu-postgres psql -U root -d root -c "SELECT COUNT(*) FROM memory_items;"


步骤 8:Navicat 连接配置

在 Navicat 中创建新的 PostgreSQL 连接:
连接名: MemU-PostgreSQL
主机: localhost
端口: 5433
初始数据库: root
用户名: root
密码: 123456

点击"测试连接""连接成功""确定"


常用容器管理命令

查看容器状态

docker ps | findstr memu-postgres

停止容器

docker stop memu-postgres

启动容器

docker start memu-postgres

重启容器

docker restart memu-postgres

查看容器日志

docker logs memu-postgres

删除容器(会丢失数据)

docker rm -f memu-postgres

数据库操作

进入 PostgreSQL 命令行

docker exec -it memu-postgres psql -U root -d root

查看所有表

docker exec memu-postgres psql -U root -d root -c "\\dt"

查看记忆项

docker exec memu-postgres psql -U root -d root -c "SELECT * FROM memory_items;"

查看记忆类别

docker exec memu-postgres psql -U root -d root -c "SELECT * FROM memory_categories;"

清空所有数据(慎用)

docker exec memu-postgres psql -U root -d root -c "TRUNCATE memory_items, category_items, memory_categories, resources CASCADE;"

数据备份与恢复

备份数据库

docker exec memu-postgres pg_dump -U root root > memu_backup.sql

恢复数据库

docker exec -i memu-postgres psql -U root -d root < memu_backup.sql


优势总结

✅ 一键安装:一条命令完成 PostgreSQL + pgvector 安装
✅ 环境隔离:不影响现有的 PostgreSQL(端口 5432)
✅ 数据持久化:数据存储在 Docker volume 中,容器重启不丢失
✅ 易于管理:使用 Docker 命令轻松管理
✅ 跨平台:Windows/Linux/Mac 都可以使用相同的命令

故障排查

问题 1:端口被占用

检查端口占用

netstat -ano | findstr :5433

使用其他端口(如 5434)

docker run -d –name memu-postgres ... -p 5434:5432 ...

记得修改 test.py 中的端口号

问题 2:容器无法启动

查看错误日志

docker logs memu-postgres

删除旧容器重新创建

docker rm -f memu-postgres

然后重新执行步骤 1

问题 3:连接被拒绝

确认容器正在运行

docker ps | findstr memu-postgres

确认端口映射正确

docker port memu-postgres


这就是完整的安装和配置流程!你现在已经有一个功能完整的 PostgreSQL + pgvector 数据库用于 MemU 框架了。🎉

赞(0)
未经允许不得转载:171主机测评 » 使用 Docker 部署 PostgreSQL + pgvector 完整步骤(映射端口 5433),适用于memu项目数据库支持!
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址