157 lines
5.1 KiB
Python
157 lines
5.1 KiB
Python
from pydantic import Field
|
|
from pydantic.dataclasses import dataclass
|
|
|
|
from astrbot.core.agent.tool import FunctionTool, ToolExecResult
|
|
from astrbot.core.astr_agent_context import AstrAgentContext, ContextWrapper
|
|
|
|
|
|
@dataclass
|
|
class AddMemory(FunctionTool[AstrAgentContext]):
|
|
"""Tool for adding memories to user's long-term memory storage"""
|
|
|
|
name: str = "astr_add_memory"
|
|
description: str = (
|
|
"Add a new memory to the user's long-term memory storage. "
|
|
"Use this tool only when the user explicitly asks you to remember something, "
|
|
"or when they share stable preferences, identity, or long-term goals that will be useful in future interactions."
|
|
)
|
|
parameters: dict = Field(
|
|
default_factory=lambda: {
|
|
"type": "object",
|
|
"properties": {
|
|
"fact": {
|
|
"type": "string",
|
|
"description": (
|
|
"The concrete memory content to store, such as a user preference, "
|
|
"identity detail, long-term goal, or stable profile fact."
|
|
),
|
|
},
|
|
"memory_type": {
|
|
"type": "string",
|
|
"enum": ["persona", "fact", "ephemeral"],
|
|
"description": (
|
|
"The relative importance of this memory. "
|
|
"Use 'persona' for core identity or highly impactful information, "
|
|
"'fact' for normal long-term preferences, "
|
|
"and 'ephemeral' for minor or tentative facts."
|
|
),
|
|
},
|
|
},
|
|
"required": ["fact", "memory_type"],
|
|
}
|
|
)
|
|
|
|
async def call(
|
|
self, context: ContextWrapper[AstrAgentContext], **kwargs
|
|
) -> ToolExecResult:
|
|
"""Add a memory to long-term storage
|
|
|
|
Args:
|
|
context: Agent context
|
|
**kwargs: Must contain 'fact' and 'memory_type'
|
|
|
|
Returns:
|
|
ToolExecResult with success message
|
|
|
|
"""
|
|
mm = context.context.context.memory_manager
|
|
fact = kwargs.get("fact")
|
|
memory_type = kwargs.get("memory_type", "fact")
|
|
|
|
if not fact:
|
|
return "Missing required parameter: fact"
|
|
|
|
try:
|
|
# Get owner_id from context
|
|
owner_id = context.context.event.unified_msg_origin
|
|
|
|
# Add memory using memory manager
|
|
memory = await mm.add_memory(
|
|
fact=fact,
|
|
owner_id=owner_id,
|
|
memory_type=memory_type,
|
|
)
|
|
|
|
return f"Memory added successfully (ID: {memory.mem_id})"
|
|
|
|
except Exception as e:
|
|
return f"Failed to add memory: {str(e)}"
|
|
|
|
|
|
@dataclass
|
|
class QueryMemory(FunctionTool[AstrAgentContext]):
|
|
"""Tool for querying user's long-term memories"""
|
|
|
|
name: str = "astr_query_memory"
|
|
description: str = (
|
|
"Query the user's long-term memory storage and return the most relevant memories. "
|
|
"Use this tool when you need user-specific context, preferences, or past facts "
|
|
"that are not explicitly present in the current conversation."
|
|
)
|
|
parameters: dict = Field(
|
|
default_factory=lambda: {
|
|
"type": "object",
|
|
"properties": {
|
|
"top_k": {
|
|
"type": "integer",
|
|
"description": (
|
|
"Maximum number of memories to retrieve after retention-based ranking. "
|
|
"Typically between 3 and 10."
|
|
),
|
|
"default": 5,
|
|
"minimum": 1,
|
|
"maximum": 20,
|
|
},
|
|
},
|
|
"required": [],
|
|
}
|
|
)
|
|
|
|
async def call(
|
|
self, context: ContextWrapper[AstrAgentContext], **kwargs
|
|
) -> ToolExecResult:
|
|
"""Query memories from long-term storage
|
|
|
|
Args:
|
|
context: Agent context
|
|
**kwargs: Optional 'top_k' parameter
|
|
|
|
Returns:
|
|
ToolExecResult with formatted memory list
|
|
|
|
"""
|
|
mm = context.context.context.memory_manager
|
|
top_k = kwargs.get("top_k", 5)
|
|
|
|
try:
|
|
# Get owner_id from context
|
|
owner_id = context.context.event.unified_msg_origin
|
|
|
|
# Query memories using memory manager
|
|
memories = await mm.query_memory(
|
|
owner_id=owner_id,
|
|
top_k=top_k,
|
|
)
|
|
|
|
if not memories:
|
|
return "No memories found for this user."
|
|
|
|
# Format memories for output
|
|
formatted_memories = []
|
|
for i, mem in enumerate(memories, 1):
|
|
formatted_memories.append(
|
|
f"{i}. [{mem.memory_type.upper()}] {mem.fact} "
|
|
f"(retrieved {mem.retrieval_count} times, "
|
|
f"last: {mem.last_retrieval_at.strftime('%Y-%m-%d')})"
|
|
)
|
|
|
|
result_text = "Retrieved memories:\n" + "\n".join(formatted_memories)
|
|
return result_text
|
|
|
|
except Exception as e:
|
|
return f"Failed to query memories: {str(e)}"
|
|
|
|
|
|
ADD_MEMORY_TOOL = AddMemory()
|
|
QUERY_MEMORY_TOOL = QueryMemory()
|