61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
"""客户长期记忆的 Neo4j 关系镜像。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from config.database.neo4j import client as configured_client
|
|
|
|
|
|
class Neo4jMemoryStore:
|
|
"""保存客户节点、记忆节点及其 HAS_MEMORY 关系。"""
|
|
|
|
def __init__(self, driver=None):
|
|
self.driver = driver or configured_client()
|
|
|
|
async def upsert(self, memory) -> str:
|
|
"""写入客户和记忆节点,返回图谱记忆节点 ID。"""
|
|
memory_id = str(memory.id)
|
|
query = """
|
|
MERGE (c:Customer {customer_id: $customer_id})
|
|
MERGE (m:CustomerMemory {memory_id: $memory_id})
|
|
SET m.memory_type = $memory_type,
|
|
m.tag = $tag,
|
|
m.content = $content,
|
|
m.status = $status
|
|
MERGE (c)-[:HAS_MEMORY]->(m)
|
|
RETURN m.memory_id AS memory_id
|
|
"""
|
|
async with self.driver.session() as session:
|
|
record = await session.run(
|
|
query,
|
|
customer_id=int(memory.customer_id),
|
|
memory_id=memory_id,
|
|
memory_type=memory.memory_type,
|
|
tag=memory.tag,
|
|
content=memory.content,
|
|
status=memory.status,
|
|
)
|
|
row = await record.single()
|
|
return row["memory_id"] if row else memory_id
|
|
|
|
async def list_by_customer(self, customer_id: int, *, limit: int = 100) -> list[dict]:
|
|
"""按客户查询图谱记忆关系。"""
|
|
query = """
|
|
MATCH (c:Customer {customer_id: $customer_id})-[:HAS_MEMORY]->(m:CustomerMemory)
|
|
RETURN m.memory_id AS memory_id, m.memory_type AS memory_type,
|
|
m.tag AS tag, m.content AS content, m.status AS status
|
|
LIMIT $limit
|
|
"""
|
|
async with self.driver.session() as session:
|
|
result = await session.run(query, customer_id=int(customer_id), limit=limit)
|
|
return [dict(record) async for record in result]
|
|
|
|
async def delete(self, memory_id: int | str) -> None:
|
|
"""删除记忆节点及其关系。"""
|
|
query = "MATCH (m:CustomerMemory {memory_id: $memory_id}) DETACH DELETE m"
|
|
async with self.driver.session() as session:
|
|
await session.run(query, memory_id=str(memory_id))
|
|
|
|
|
|
__all__ = ["Neo4jMemoryStore"]
|
|
|