feat: 新增 memory_query_archived 工具,支持按时间/关键词查询归档记忆
This commit is contained in:
@ -621,6 +621,74 @@ class EmbeddedGraphDB:
|
||||
"message": f"归档了 {archived} 条关系"
|
||||
}
|
||||
|
||||
def query_archived(self, days: int = None, keyword: str = "") -> Dict:
|
||||
"""
|
||||
查询已归档的记忆
|
||||
|
||||
Args:
|
||||
days: 可选,最近N天内的归档记录
|
||||
keyword: 可选,过滤包含指定关键词的实体名或关系
|
||||
|
||||
Returns:
|
||||
归档记录列表
|
||||
"""
|
||||
cursor = self.conn.cursor()
|
||||
|
||||
# 基础 SQL:查询已归档的关系及其关联实体
|
||||
conditions = ["r.status = 'archived'"]
|
||||
params = []
|
||||
|
||||
# 时间范围过滤(最近N天)
|
||||
if days is not None and days > 0:
|
||||
conditions.append("r.updated_at >= datetime('now', ?)")
|
||||
params.append(f'-{days} days')
|
||||
|
||||
# 关键词过滤(匹配源实体名、目标实体名、关系类型任一)
|
||||
if keyword:
|
||||
# 先找到匹配的实体ID
|
||||
cursor.execute("SELECT id FROM entities WHERE name LIKE ?", (f'%{keyword}%',))
|
||||
matched_ids = [str(row['id']) for row in cursor.fetchall()]
|
||||
|
||||
if matched_ids:
|
||||
id_list = ','.join(matched_ids)
|
||||
conditions.append(f"(r.source_id IN ({id_list}) OR r.target_id IN ({id_list}) OR r.relation_type LIKE ?)")
|
||||
params.append(f'%{keyword}%')
|
||||
else:
|
||||
conditions.append("r.relation_type LIKE ?")
|
||||
params.append(f'%{keyword}%')
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
||||
cursor.execute(f"""
|
||||
SELECT r.id, r.relation_type, r.created_at, r.updated_at,
|
||||
e.name AS source_name, t.name AS target_name
|
||||
FROM relations r
|
||||
JOIN entities e ON r.source_id = e.id
|
||||
JOIN entities t ON r.target_id = t.id
|
||||
WHERE {where_clause}
|
||||
ORDER BY r.updated_at DESC
|
||||
LIMIT 200
|
||||
""", params)
|
||||
|
||||
rows = cursor.fetchall()
|
||||
|
||||
results = []
|
||||
for row in rows:
|
||||
results.append({
|
||||
"id": row['id'],
|
||||
"source": row['source_name'],
|
||||
"relation": row['relation_type'],
|
||||
"target": row['target_name'],
|
||||
"archived_at": row['updated_at'],
|
||||
"created_at": row['created_at']
|
||||
})
|
||||
|
||||
return {
|
||||
"archived_relations": results,
|
||||
"total_relations": len(results),
|
||||
"message": f"找到 {len(results)} 条归档关系"
|
||||
}
|
||||
|
||||
def cleanup(self, dry_run: bool = True) -> Dict:
|
||||
"""清理已删除数据"""
|
||||
cursor = self.conn.cursor()
|
||||
|
||||
@ -282,6 +282,49 @@ class Neo4jGraph:
|
||||
|
||||
return {"archived_count": result.single()["archived"], "days": days}
|
||||
|
||||
def query_archived(self, days: int = None, keyword: str = "") -> dict:
|
||||
"""查询归档记忆"""
|
||||
with self.driver.session() as session:
|
||||
filters = []
|
||||
params = {}
|
||||
|
||||
filters.append("r.status = 'archived'")
|
||||
|
||||
if days is not None and days > 0:
|
||||
filters.append("r.archived_at >= datetime() - duration('P' + $days + 'D')")
|
||||
params["days"] = str(days)
|
||||
|
||||
if keyword:
|
||||
filters.append("(e.name CONTAINS $keyword OR t.name CONTAINS $keyword OR r.type CONTAINS $keyword)")
|
||||
params["keyword"] = keyword
|
||||
|
||||
where = " AND ".join(filters)
|
||||
|
||||
result = session.run(f"""
|
||||
MATCH (e:Entity)-[r:RELATES]->(t:Entity)
|
||||
WHERE {where}
|
||||
RETURN e.name as source, r.type as relation, t.name as target,
|
||||
r.archived_at as archived_at, r.created_at as created_at
|
||||
ORDER BY r.archived_at DESC
|
||||
LIMIT 200
|
||||
""", params)
|
||||
|
||||
records = []
|
||||
for row in result:
|
||||
records.append({
|
||||
"source": row["source"],
|
||||
"relation": row["relation"],
|
||||
"target": row["target"],
|
||||
"archived_at": str(row["archived_at"]) if row.get("archived_at") else "",
|
||||
"created_at": str(row["created_at"]) if row.get("created_at") else ""
|
||||
})
|
||||
|
||||
return {
|
||||
"archived_relations": records,
|
||||
"total_relations": len(records),
|
||||
"message": f"找到 {len(records)} 条归档关系"
|
||||
}
|
||||
|
||||
def cleanup(self, dry_run: bool = True) -> dict:
|
||||
"""清理无效数据"""
|
||||
with self.driver.session() as session:
|
||||
|
||||
@ -69,6 +69,13 @@ def execute_tool(graph: Any, tool_name: str, arguments: dict) -> str:
|
||||
result = graph.cleanup(dry_run=arguments.get("dry_run", True))
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
elif tool_name == "memory_query_archived":
|
||||
days = arguments.get("days")
|
||||
keyword = arguments.get("keyword", "")
|
||||
recorder.record("query", tool_name, f"days={days}, keyword={keyword}")
|
||||
result = graph.query_archived(days=days, keyword=keyword)
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
elif tool_name == "context_rewrite":
|
||||
result = execute_context_rewrite(graph, arguments)
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
@ -244,6 +244,36 @@ MEMORY_TOOLS = [
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "memory_query_archived",
|
||||
"description": """查询已归档的记忆。
|
||||
|
||||
【使用场景】
|
||||
- 想了解之前归档过哪些记忆
|
||||
- 按关键词搜索归档内容
|
||||
- 按时间范围查看最近归档的历史
|
||||
|
||||
【注意】
|
||||
- days 和 keyword 可以单独使用,也可以组合使用
|
||||
- 不加任何参数时返回最近的所有归档记录
|
||||
""",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days": {
|
||||
"type": "integer",
|
||||
"description": "最近N天内的归档记录,不指定则不限时间"
|
||||
},
|
||||
"keyword": {
|
||||
"type": "string",
|
||||
"description": "关键词,匹配实体名或关系类型"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
|
||||
Reference in New Issue
Block a user