chore: initialize sandbox and overwrite remote content
Some checks failed
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_en (ubuntu-latest, 3.10) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_zh (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.12) (push) Has been cancelled
Some checks failed
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_en (ubuntu-latest, 3.10) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_zh (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.12) (push) Has been cancelled
This commit is contained in:
158
examples/functionality/long_term_memory/mem0/README.md
Normal file
158
examples/functionality/long_term_memory/mem0/README.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Mem0 Long-Term Memory in AgentScope
|
||||
|
||||
This example demonstrates how to
|
||||
|
||||
- use Mem0LongTermMemory to provide persistent semantic memory storage for AgentScope agents,
|
||||
- record and retrieve conversation history and user preferences across sessions,
|
||||
- integrate long-term memory with ReAct agents for context-aware conversations, and
|
||||
- configure DashScope embedding models and Qdrant vector store for memory management.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10 or higher
|
||||
- DashScope API key from Alibaba Cloud
|
||||
|
||||
|
||||
## QuickStart
|
||||
|
||||
Install agentscope and ensure you have a valid DashScope API key in your environment variables.
|
||||
|
||||
> Note: The example is built with DashScope chat model and embedding model. If you want to use OpenAI models instead,
|
||||
> modify the model initialization in the example code accordingly.
|
||||
|
||||
```bash
|
||||
# Install agentscope from source
|
||||
cd {PATH_TO_AGENTSCOPE}
|
||||
pip install -e .
|
||||
# Install dependencies
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
Set up your API key:
|
||||
|
||||
```bash
|
||||
export DASHSCOPE_API_KEY='YOUR_API_KEY'
|
||||
```
|
||||
|
||||
Run the example:
|
||||
|
||||
```bash
|
||||
python memory_example.py
|
||||
```
|
||||
|
||||
The example will:
|
||||
1. Initialize a Mem0LongTermMemory instance with DashScope models and Qdrant vector store
|
||||
2. Record a basic conversation to long-term memory
|
||||
3. Retrieve memories using semantic search
|
||||
4. Demonstrate ReAct agent integration with long-term memory for storing and retrieving user preferences
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Vector-based Storage**: Uses Qdrant vector database for efficient semantic search and retrieval
|
||||
- **Flexible Configuration**: Support for multiple embedding models (OpenAI, DashScope) and vector stores
|
||||
- **Async Operations**: Full async support for non-blocking memory operations
|
||||
- **ReAct Agent Integration**: Seamless integration with AgentScope's ReActAgent and tool system
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Initialize Memory
|
||||
|
||||
```python
|
||||
import os
|
||||
from agentscope.memory import Mem0LongTermMemory
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from mem0.vector_stores.configs import VectorStoreConfig
|
||||
|
||||
# Initialize with DashScope models and Qdrant vector store
|
||||
long_term_memory = Mem0LongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max-latest",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY")
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v3",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024
|
||||
),
|
||||
vector_store_config=VectorStoreConfig(
|
||||
provider="qdrant",
|
||||
config={
|
||||
"on_disk": True,
|
||||
"path": "./qdrant_data", # Your customized storage path
|
||||
"embedding_model_dims": 1024
|
||||
}
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
> **Important**: If you change to a different embedding model or modify `embedding_model_dims`, you must either set a new storage path or delete the existing database files. Otherwise, a dimension mismatch error will occur.
|
||||
|
||||
### Integrate with ReAct Agent
|
||||
|
||||
```python
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.tool import Toolkit
|
||||
|
||||
# Create a ReAct agent with long-term memory
|
||||
toolkit = Toolkit()
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt=(
|
||||
"You are a helpful assistant named Friday. "
|
||||
"If you think there is relevant information about "
|
||||
"the user's preferences, you can record it to long-term "
|
||||
"memory using the tool `record_to_memory`. "
|
||||
"If you need to retrieve information from long-term "
|
||||
"memory, use the tool `retrieve_from_memory`."
|
||||
),
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max-latest",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY")
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=long_term_memory,
|
||||
long_term_memory_mode="both"
|
||||
)
|
||||
|
||||
# Use the agent
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content="When I travel to Hangzhou, I prefer to stay in a homestay",
|
||||
name="user"
|
||||
)
|
||||
response = await agent(msg)
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
You can customize the mem0 config by directly set :
|
||||
|
||||
```python
|
||||
long_term_memory = Mem0LongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
mem0_config=your_mem0_config # Pass your custom mem0 configuration
|
||||
)
|
||||
```
|
||||
|
||||
For more configuration options, refer to the [mem0 documentation](https://github.com/mem0ai/mem0).
|
||||
|
||||
## What's in the Example
|
||||
|
||||
The `memory_example.py` file demonstrates:
|
||||
|
||||
1. **Basic Memory Recording**: Recording user conversations to long-term memory
|
||||
2. **Memory Retrieval**: Searching for stored memories using semantic similarity
|
||||
3. **ReAct Agent Integration**: Using long-term memory with ReAct agents to store and retrieve user preferences automatically
|
||||
|
||||
## Reference
|
||||
|
||||
- [mem0 Documentation](https://github.com/mem0ai/mem0)
|
||||
- [Qdrant Vector Database](https://qdrant.tech/)
|
||||
185
examples/functionality/long_term_memory/mem0/memory_example.py
Normal file
185
examples/functionality/long_term_memory/mem0/memory_example.py
Normal file
@@ -0,0 +1,185 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Memory example demonstrating long-term memory functionality with mem0.
|
||||
|
||||
This module provides examples of how to use the Mem0LongTermMemory class
|
||||
for recording and retrieving persistent memories.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from mem0.vector_stores.configs import VectorStoreConfig
|
||||
from agentscope.memory import Mem0LongTermMemory
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.message import Msg
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.tool import Toolkit
|
||||
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Run the memory examples."""
|
||||
# Initialize long term memory
|
||||
long_term_memory = Mem0LongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max-latest",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v3",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024,
|
||||
),
|
||||
vector_store_config=VectorStoreConfig(
|
||||
provider="qdrant",
|
||||
config={
|
||||
"on_disk": True,
|
||||
"path": "../memory/qdrant_data", # Specify custom path
|
||||
"embedding_model_dims": 1024,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
# If you want to also use graph memory in mem0,
|
||||
# the following is an example of using Neo4j graph store.
|
||||
# from mem0.configs.base import MemoryConfig
|
||||
# from mem0.graphs.configs import GraphStoreConfig
|
||||
# long_term_memory = Mem0LongTermMemory(
|
||||
# agent_name="Friday",
|
||||
# user_name="user_123",
|
||||
# embedding_model=DashScopeTextEmbedding(
|
||||
# model_name="text-embedding-v3",
|
||||
# api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
# dimensions=1024,
|
||||
# ),
|
||||
# model=DashScopeChatModel(
|
||||
# model_name="qwen-max-latest",
|
||||
# api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
# stream=False,
|
||||
# ),
|
||||
# vector_store_config=VectorStoreConfig(
|
||||
# provider="qdrant",
|
||||
# config={
|
||||
# "on_disk": True,
|
||||
# "path": "../memory/qdrant_data", # Specify custom path
|
||||
# "embedding_model_dims": 1024,
|
||||
# }),
|
||||
# mem0_config=MemoryConfig(
|
||||
# graph_store=GraphStoreConfig(
|
||||
# provider="neo4j",
|
||||
# config={
|
||||
# "url": os.environ.get("NEO4J_URL",
|
||||
# "neo4j://localhost:7687"),
|
||||
# "username": os.environ.get("NEO4J_USER", "neo4j"),
|
||||
# "password": os.environ.get("NEO4J_PASSWORD",
|
||||
# "12345678"),
|
||||
# "database": "neo4j",
|
||||
# },
|
||||
# ),
|
||||
# ),
|
||||
# )
|
||||
|
||||
print("=== Long Term Memory Examples with mem0 ===\n")
|
||||
|
||||
# Example 1: Basic conversation recording
|
||||
print("1. Basic Conversation Recording")
|
||||
print("-" * 40)
|
||||
results = await long_term_memory.record(
|
||||
msgs=[
|
||||
Msg(
|
||||
role="user",
|
||||
content="Please help me book a hotel, preferably homestay",
|
||||
name="user",
|
||||
),
|
||||
],
|
||||
)
|
||||
print(f"Recorded conversation: {results}\n")
|
||||
|
||||
# Example 2: Retrieving memories
|
||||
print("2. Retrieving Memories")
|
||||
print("-" * 40)
|
||||
print("Searching for weather-related memories...")
|
||||
weather_memories = await long_term_memory.retrieve(
|
||||
msg=[
|
||||
Msg(
|
||||
role="user",
|
||||
content="What's the weather like today?",
|
||||
name="user",
|
||||
),
|
||||
],
|
||||
)
|
||||
print(f"Retrieved weather memories: {weather_memories}\n")
|
||||
|
||||
print("Searching for user preference memories...")
|
||||
preference_memories = await long_term_memory.retrieve(
|
||||
msg=[
|
||||
Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"I prefer temperatures in Celsius and wind speed in km/h"
|
||||
),
|
||||
name="user",
|
||||
),
|
||||
],
|
||||
)
|
||||
print(f"Retrieved preference memories: {preference_memories}\n")
|
||||
|
||||
# Example 3: ReActAgent with long term memory
|
||||
print("3. ReActAgent with long term memory")
|
||||
print("-" * 40)
|
||||
|
||||
toolkit = Toolkit()
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt=(
|
||||
"You are a helpful assistant named Friday. "
|
||||
"If you think there is relevant information about "
|
||||
"user's preference, you can record it to the long term "
|
||||
"memory by tool call `record_to_memory`. "
|
||||
"If you need to retrieve information from the long term "
|
||||
"memory, you can use the tool call `retrieve_from_memory`."
|
||||
),
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max-latest",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=long_term_memory,
|
||||
long_term_memory_mode="both",
|
||||
)
|
||||
|
||||
await agent.memory.clear()
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content="When I travel to Hangzhou, I prefer to stay in a homestay",
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"ReActAgent response: {msg.get_text_content()}\n")
|
||||
|
||||
msg = Msg(role="user", content="what preference do I have?", name="user")
|
||||
msg = await agent(msg)
|
||||
print(f"ReActAgent response: {msg.get_text_content()}\n")
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content="I prefer to visit the West Lake",
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"ReActAgent response: {msg.get_text_content()}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
609
examples/functionality/long_term_memory/reme/README.md
Normal file
609
examples/functionality/long_term_memory/reme/README.md
Normal file
@@ -0,0 +1,609 @@
|
||||
# ReMe Long-Term Memory in AgentScope
|
||||
|
||||
This example demonstrates how to:
|
||||
|
||||
- Use ReMe (Reflection Memory) to provide three specialized types of persistent memory storage for AgentScope agents
|
||||
- Record and retrieve personal information, task execution trajectories, and tool usage patterns across sessions
|
||||
- Integrate long-term memory with ReActAgent for context-aware conversations and continuous learning
|
||||
- Configure DashScope embedding models and vector stores for efficient memory management
|
||||
|
||||
## Overview
|
||||
|
||||
ReMe (Reflection Memory) provides three types of long-term memory for intelligent agents:
|
||||
|
||||
1. **Personal Memory** (`ReMePersonalLongTermMemory`) - Records and retrieves persistent personal information, preferences, and facts about users
|
||||
2. **Task Memory** (`ReMeTaskLongTermMemory`) - Learns from task execution trajectories and retrieves relevant past experiences for similar tasks
|
||||
3. **Tool Memory** (`ReMeToolLongTermMemory`) - Records tool execution results and generates usage guidelines to improve tool calling
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.12 or higher
|
||||
- DashScope API key from Alibaba Cloud (for the examples)
|
||||
|
||||
## QuickStart
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Install agentscope from source
|
||||
cd {PATH_TO_AGENTSCOPE}
|
||||
pip install -e .
|
||||
|
||||
# Install required dependencies
|
||||
pip install reme-ai python-dotenv
|
||||
```
|
||||
|
||||
### Setup
|
||||
|
||||
Set up your API key:
|
||||
|
||||
```bash
|
||||
export DASHSCOPE_API_KEY='YOUR_API_KEY'
|
||||
```
|
||||
|
||||
Or create a `.env` file:
|
||||
|
||||
```bash
|
||||
DASHSCOPE_API_KEY=YOUR_API_KEY
|
||||
```
|
||||
|
||||
### Run Examples
|
||||
|
||||
```bash
|
||||
# Personal Memory Example - 5 core interfaces
|
||||
python personal_memory_example.py
|
||||
|
||||
# Task Memory Example - 5 core interfaces
|
||||
python task_memory_example.py
|
||||
|
||||
# Tool Memory Example - Complete workflow with ReActAgent
|
||||
python tool_memory_example.py
|
||||
```
|
||||
|
||||
> **Note**: The examples use DashScope models by default. To use OpenAI or other models, modify the model initialization in the example code accordingly.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Three Specialized Memory Types**: Personal, Task, and Tool memory for different use cases
|
||||
- **Dual Interface Design**: Both tool functions (for agent calling) and direct methods (for programmatic use)
|
||||
- **Vector-based Retrieval**: Efficient semantic search using embedding models and vector stores
|
||||
- **Async-first Architecture**: Full async/await support for non-blocking operations
|
||||
- **ReActAgent Integration**: Seamless integration with AgentScope's ReActAgent and Toolkit
|
||||
- **Automatic Context Management**: Uses async context managers for proper resource handling
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Memory Types and Their Use Cases
|
||||
|
||||
| Memory Type | Purpose | When to Use |
|
||||
|------------|---------|-------------|
|
||||
| **Personal Memory** | Store user preferences, habits, and personal facts | User profiles, personalized assistants, long-term user context |
|
||||
| **Task Memory** | Learn from task execution trajectories | Problem-solving, debugging, repeated workflows, learning from past successes |
|
||||
| **Tool Memory** | Record tool usage patterns and generate guidelines | Tool-using agents, improving tool call accuracy, avoiding past errors |
|
||||
|
||||
### Interface Design
|
||||
|
||||
**Personal Memory** and **Task Memory** provide **5 core interfaces**:
|
||||
|
||||
1. **`record_to_memory()`** - Tool function for agents to record memories (returns `ToolResponse`)
|
||||
2. **`retrieve_from_memory()`** - Tool function for agents to retrieve memories (returns `ToolResponse`)
|
||||
3. **`record()`** - Direct method for programmatic recording (returns `None`)
|
||||
4. **`retrieve()`** - Direct method for programmatic retrieval (returns `str`)
|
||||
5. **ReActAgent Integration** - Use memory with `long_term_memory` and `long_term_memory_mode` parameters
|
||||
|
||||
**Tool Memory** provides **2 core interfaces** (no tool functions):
|
||||
|
||||
1. **`record()`** - Direct method for recording tool execution results (returns `None`)
|
||||
2. **`retrieve()`** - Direct method for retrieving tool usage guidelines (returns `str`)
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### 1. Personal Memory
|
||||
|
||||
**Use Case**: Record and retrieve user preferences, habits, and personal information.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import os
|
||||
from agentscope.memory import ReMePersonalLongTermMemory
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from agentscope.message import Msg
|
||||
from agentscope.model import DashScopeChatModel
|
||||
|
||||
|
||||
async def main():
|
||||
# Initialize personal memory
|
||||
personal_memory = ReMePersonalLongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen3-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v4",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024,
|
||||
),
|
||||
)
|
||||
|
||||
# Use async context manager (required!)
|
||||
async with personal_memory:
|
||||
# Interface 1: record_to_memory (tool function)
|
||||
result = await personal_memory.record_to_memory(
|
||||
thinking="User sharing travel preferences",
|
||||
content=[
|
||||
"I prefer to stay in homestays when traveling to Hangzhou",
|
||||
"I like to visit the West Lake in the morning",
|
||||
"I enjoy drinking Longjing tea",
|
||||
],
|
||||
)
|
||||
|
||||
# Interface 2: retrieve_from_memory (tool function)
|
||||
result = await personal_memory.retrieve_from_memory(
|
||||
keywords=["Hangzhou travel", "tea preference"],
|
||||
)
|
||||
|
||||
# Interface 3: record (direct method)
|
||||
await personal_memory.record(
|
||||
msgs=[
|
||||
Msg(role="user", content="I work as a software engineer", name="user"),
|
||||
Msg(role="assistant", content="Got it!", name="assistant"),
|
||||
],
|
||||
)
|
||||
|
||||
# Interface 4: retrieve (direct method)
|
||||
memories = await personal_memory.retrieve(
|
||||
msg=Msg(role="user", content="What do you know about my work?", name="user"),
|
||||
)
|
||||
print(memories)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
**Integration with ReActAgent** (Interface 5):
|
||||
|
||||
```python
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.tool import Toolkit
|
||||
|
||||
async def use_with_agent():
|
||||
personal_memory = ReMePersonalLongTermMemory(...)
|
||||
|
||||
async with personal_memory:
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt="You are Friday with long-term memory. Always record user information and retrieve memories when needed.",
|
||||
model=DashScopeChatModel(...),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=Toolkit(),
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=personal_memory, # Attach personal memory
|
||||
long_term_memory_mode="both", # Enable both record and retrieve tools
|
||||
)
|
||||
|
||||
# Agent can now use record_to_memory and retrieve_from_memory as tools
|
||||
msg = Msg(role="user", content="I prefer staying in homestays", name="user")
|
||||
response = await agent(msg)
|
||||
```
|
||||
|
||||
### 2. Task Memory
|
||||
|
||||
**Use Case**: Learn from task execution trajectories and retrieve relevant experiences.
|
||||
|
||||
```python
|
||||
from agentscope.memory import ReMeTaskLongTermMemory
|
||||
|
||||
|
||||
async def main():
|
||||
# Initialize task memory
|
||||
task_memory = ReMeTaskLongTermMemory(
|
||||
agent_name="TaskAssistant",
|
||||
user_name="task_workspace_123", # Acts as workspace_id
|
||||
model=DashScopeChatModel(...),
|
||||
embedding_model=DashScopeTextEmbedding(...),
|
||||
)
|
||||
|
||||
async with task_memory:
|
||||
# Interface 1: record_to_memory with score
|
||||
result = await task_memory.record_to_memory(
|
||||
thinking="Recording successful debugging approach",
|
||||
content=[
|
||||
"For API 404 errors: Check route definition, verify URL path, ensure correct port",
|
||||
"Always use linter to catch typos in route paths",
|
||||
],
|
||||
score=0.95, # High score for successful trajectory
|
||||
)
|
||||
|
||||
# Interface 2: retrieve_from_memory
|
||||
result = await task_memory.retrieve_from_memory(
|
||||
keywords=["debugging", "API errors"],
|
||||
)
|
||||
|
||||
# Interface 3: record with score in direct method
|
||||
await task_memory.record(
|
||||
msgs=[
|
||||
Msg(role="user", content="I'm getting a 404 error", name="user"),
|
||||
Msg(role="assistant", content="Let's check the route path...", name="assistant"),
|
||||
Msg(role="user", content="Found the typo!", name="user"),
|
||||
],
|
||||
score=0.95, # Optional score for this trajectory
|
||||
)
|
||||
|
||||
# Interface 4: retrieve (direct method)
|
||||
experiences = await task_memory.retrieve(
|
||||
msg=Msg(role="user", content="How to debug API errors?", name="user"),
|
||||
)
|
||||
print(experiences)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
**Integration with ReActAgent** (Interface 5):
|
||||
|
||||
```python
|
||||
async def use_with_agent():
|
||||
task_memory = ReMeTaskLongTermMemory(...)
|
||||
|
||||
async with task_memory:
|
||||
agent = ReActAgent(
|
||||
name="TaskAssistant",
|
||||
sys_prompt="You are a task assistant. Record solutions and retrieve past experiences before solving problems.",
|
||||
model=DashScopeChatModel(...),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=Toolkit(),
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=task_memory,
|
||||
long_term_memory_mode="both",
|
||||
)
|
||||
|
||||
# Agent learns from task executions over time
|
||||
msg = Msg(role="user", content="How should I optimize database queries?", name="user")
|
||||
response = await agent(msg)
|
||||
```
|
||||
|
||||
### 3. Tool Memory
|
||||
|
||||
**Use Case**: Record tool execution results and generate usage guidelines for better tool calling.
|
||||
|
||||
**Complete Workflow**:
|
||||
|
||||
```python
|
||||
import json
|
||||
from datetime import datetime
|
||||
from agentscope.memory import ReMeToolLongTermMemory
|
||||
from agentscope.tool import Toolkit, ToolResponse
|
||||
from agentscope.message import Msg, TextBlock
|
||||
|
||||
|
||||
# Step 1: Define tools
|
||||
async def web_search(query: str, max_results: int = 5) -> ToolResponse:
|
||||
"""Search the web for information."""
|
||||
result = f"Found {max_results} results for query: '{query}'"
|
||||
return ToolResponse(content=[TextBlock(type="text", text=result)])
|
||||
|
||||
|
||||
async def main():
|
||||
# Initialize tool memory
|
||||
tool_memory = ReMeToolLongTermMemory(
|
||||
agent_name="ToolBot",
|
||||
user_name="tool_workspace_demo",
|
||||
model=DashScopeChatModel(...),
|
||||
embedding_model=DashScopeTextEmbedding(...),
|
||||
)
|
||||
|
||||
async with tool_memory:
|
||||
# Step 2: Record tool execution history (accepts JSON strings in msgs)
|
||||
tool_result = {
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "web_search",
|
||||
"input": {"query": "Python asyncio tutorial", "max_results": 10},
|
||||
"output": "Found 10 results for query: 'Python asyncio tutorial'",
|
||||
"token_cost": 150,
|
||||
"success": True,
|
||||
"time_cost": 2.3
|
||||
}
|
||||
|
||||
# Interface 1: record (accepts JSON strings in message content)
|
||||
await tool_memory.record(
|
||||
msgs=[Msg(role="assistant", content=json.dumps(tool_result), name="assistant")],
|
||||
)
|
||||
|
||||
# Step 3: Retrieve tool guidelines
|
||||
# Interface 2: retrieve returns summarized guidelines
|
||||
guidelines = await tool_memory.retrieve(
|
||||
msg=Msg(role="user", content="web_search", name="user"),
|
||||
)
|
||||
|
||||
# Step 4: Inject guidelines into agent system prompt
|
||||
toolkit = Toolkit()
|
||||
toolkit.register_tool_function(web_search)
|
||||
|
||||
base_prompt = "You are ToolBot, a helpful AI assistant."
|
||||
enhanced_prompt = f"{base_prompt}\n\n# Tool Guidelines:\n{guidelines}"
|
||||
|
||||
agent = ReActAgent(
|
||||
name="ToolBot",
|
||||
sys_prompt=enhanced_prompt, # Guidelines enhance tool usage
|
||||
model=DashScopeChatModel(...),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
)
|
||||
|
||||
# Agent now uses tools with learned guidelines
|
||||
msg = Msg(role="user", content="Search for Python design patterns", name="user")
|
||||
response = await agent(msg)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
> **Note**: Tool Memory does NOT provide `record_to_memory()` and `retrieve_from_memory()` tool functions. It only provides direct `record()` and `retrieve()` methods. Tool Memory is designed to be used programmatically to enhance agent system prompts, not as agent-callable tools.
|
||||
|
||||
## API Reference
|
||||
|
||||
### Common Parameters
|
||||
|
||||
All memory types share these initialization parameters:
|
||||
|
||||
```python
|
||||
ReMePersonalLongTermMemory(
|
||||
agent_name: str, # Name of the agent using this memory
|
||||
user_name: str, # User identifier (acts as workspace_id in ReMe)
|
||||
model: ModelWrapper, # LLM for summarization and processing
|
||||
embedding_model: EmbeddingWrapper, # Embedding model for vector retrieval
|
||||
vector_store_dir: str = "./memory_vector_store", # Storage location
|
||||
)
|
||||
```
|
||||
|
||||
### Interface Specifications
|
||||
|
||||
#### Personal Memory
|
||||
|
||||
| Interface | Type | Signature | Returns | Description |
|
||||
|-----------|------|-----------|---------|-------------|
|
||||
| `record_to_memory` | Tool Function | `(thinking: str, content: list[str])` | `ToolResponse` | Record personal information with reasoning |
|
||||
| `retrieve_from_memory` | Tool Function | `(keywords: list[str], limit: int = 3)` | `ToolResponse` | Retrieve memories by keywords |
|
||||
| `record` | Direct Method | `(msgs: list[Msg])` | `None` | Record message conversations |
|
||||
| `retrieve` | Direct Method | `(msg: Msg, top_k: int = 3)` | `str` | Query-based retrieval |
|
||||
|
||||
**Parameters**:
|
||||
- `thinking`: Reasoning about what to record
|
||||
- `content`: List of strings to remember
|
||||
- `keywords`: Search keywords
|
||||
- `limit`: Results per keyword (tool function, default: 3)
|
||||
- `top_k`: Total results to retrieve (direct method, default: 3)
|
||||
|
||||
#### Task Memory
|
||||
|
||||
| Interface | Type | Signature | Returns | Description |
|
||||
|-----------|------|-----------|---------|-------------|
|
||||
| `record_to_memory` | Tool Function | `(thinking: str, content: list[str], score: float = 1.0)` | `ToolResponse` | Record task trajectory with score |
|
||||
| `retrieve_from_memory` | Tool Function | `(keywords: list[str], top_k: int = 5)` | `ToolResponse` | Retrieve experiences by keywords |
|
||||
| `record` | Direct Method | `(msgs: list[Msg], score: float = 1.0)` | `None` | Record message conversations with score |
|
||||
| `retrieve` | Direct Method | `(msg: Msg, top_k: int = 5)` | `str` | Query-based experience retrieval |
|
||||
|
||||
**Parameters**:
|
||||
- `thinking`: Reasoning about the task execution
|
||||
- `content`: Task execution information and insights
|
||||
- `score`: Success score for the trajectory (0.0-1.0, default: 1.0)
|
||||
- `keywords`: Search keywords (e.g., task type, domain)
|
||||
- `top_k`: Number of results to retrieve (default: 5)
|
||||
|
||||
#### Tool Memory
|
||||
|
||||
| Interface | Type | Signature | Returns | Description |
|
||||
|-----------|------|-----------|---------|-------------|
|
||||
| `record` | Direct Method | `(msgs: list[Msg])` | `None` | Record tool results as messages (JSON format) |
|
||||
| `retrieve` | Direct Method | `(msg: Msg)` | `str` | Retrieve guidelines for tools |
|
||||
|
||||
**Parameters**:
|
||||
- `msgs`: List of messages where `content` contains JSON strings with tool execution metadata:
|
||||
- `create_time`: Timestamp (`"%Y-%m-%d %H:%M:%S"`)
|
||||
- `tool_name`: Tool identifier
|
||||
- `input`: Parameters used (dict)
|
||||
- `output`: Execution result (str)
|
||||
- `token_cost`: Token usage (int)
|
||||
- `success`: Execution status (bool)
|
||||
- `time_cost`: Duration in seconds (float)
|
||||
- `msg`: Message containing tool name to retrieve guidelines for
|
||||
- **Note**: Tool Memory does NOT provide tool functions (`record_to_memory` and `retrieve_from_memory`). It only provides direct methods for programmatic use.
|
||||
|
||||
### ReActAgent Integration Modes
|
||||
|
||||
When attaching **Personal Memory** or **Task Memory** to ReActAgent, use the `long_term_memory_mode` parameter:
|
||||
|
||||
```python
|
||||
agent = ReActAgent(
|
||||
name="Assistant",
|
||||
long_term_memory=memory, # ReMePersonalLongTermMemory or ReMeTaskLongTermMemory
|
||||
long_term_memory_mode="both", # Options: "record", "retrieve", "both"
|
||||
# ... other parameters
|
||||
)
|
||||
```
|
||||
|
||||
**Modes**:
|
||||
- `"record"`: Only adds `record_to_memory` tool to agent
|
||||
- `"retrieve"`: Only adds `retrieve_from_memory` tool to agent
|
||||
- `"both"`: Adds both tools (recommended for most use cases)
|
||||
|
||||
> **Note**: Tool Memory does NOT support ReActAgent integration with tool functions. Use Tool Memory programmatically to enhance system prompts as shown in the Tool Memory example.
|
||||
|
||||
### Async Context Manager (Required!)
|
||||
|
||||
All ReMe memory types **must** be used with async context managers:
|
||||
|
||||
```python
|
||||
async with long_term_memory:
|
||||
# All memory operations must be within this context
|
||||
await long_term_memory.record(msgs=[...])
|
||||
result = await long_term_memory.retrieve(msg=...)
|
||||
```
|
||||
|
||||
This ensures:
|
||||
- Proper initialization of the ReMe backend
|
||||
- Resource cleanup after operations
|
||||
- Vector store connection management
|
||||
|
||||
### Custom Configuration
|
||||
|
||||
```python
|
||||
from agentscope.memory import ReMePersonalLongTermMemory
|
||||
|
||||
# Custom storage location and models
|
||||
memory = ReMePersonalLongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
model=your_custom_model, # Any AgentScope-compatible LLM
|
||||
embedding_model=your_embedding, # Any AgentScope-compatible embedding model
|
||||
vector_store_dir="./custom_path", # Custom storage directory
|
||||
)
|
||||
```
|
||||
|
||||
## Example Files Overview
|
||||
|
||||
### `personal_memory_example.py`
|
||||
|
||||
Demonstrates **5 core interfaces** for personal memory:
|
||||
|
||||
1. **`record_to_memory()`** - Record user preferences using tool function
|
||||
2. **`retrieve_from_memory()`** - Search memories by keywords using tool function
|
||||
3. **`record()`** - Direct recording of message conversations
|
||||
4. **`retrieve()`** - Direct query-based retrieval
|
||||
5. **ReActAgent Integration** - Agent autonomously uses memory tools
|
||||
|
||||
**Key Features**:
|
||||
- Recording travel preferences, work habits, and personal information
|
||||
- Keyword-based and query-based retrieval
|
||||
- System prompt guidelines for agent memory usage
|
||||
- Automatic memory tool calling by ReActAgent
|
||||
|
||||
### `task_memory_example.py`
|
||||
|
||||
Demonstrates **5 core interfaces** for task memory:
|
||||
|
||||
1. **`record_to_memory()`** - Record task experiences with scores
|
||||
2. **`retrieve_from_memory()`** - Retrieve relevant experiences by keywords
|
||||
3. **`record()`** - Direct recording with trajectory scores
|
||||
4. **`retrieve()`** - Direct experience retrieval
|
||||
5. **ReActAgent Integration** - Agent learns from past task executions
|
||||
|
||||
**Key Features**:
|
||||
- Recording project planning, debugging, and development experiences
|
||||
- Score-based trajectory evaluation (0.0-1.0)
|
||||
- Learning from successful and failed attempts
|
||||
- Continuous improvement through experience retrieval
|
||||
|
||||
### `tool_memory_example.py`
|
||||
|
||||
Demonstrates the **complete workflow** for tool memory:
|
||||
|
||||
1. **Mock tools** - Define and register tools to Toolkit
|
||||
2. **Record tool history** - Store execution results with metadata using `record()`
|
||||
3. **Retrieve guidelines** - Get summarized usage guidelines using `retrieve()`
|
||||
4. **Enhance agent prompt** - Inject guidelines into system prompt
|
||||
5. **Use ReActAgent** - Agent uses tools with learned guidelines
|
||||
|
||||
**Key Features**:
|
||||
- JSON-formatted tool execution recording via direct `record()` method
|
||||
- Automatic guideline generation through summarization
|
||||
- Multi-tool guideline retrieval via direct `retrieve()` method
|
||||
- System prompt enhancement for better tool usage
|
||||
- **Note**: Tool Memory does NOT provide agent-callable tool functions
|
||||
|
||||
## Architecture
|
||||
|
||||
### Inheritance Hierarchy
|
||||
|
||||
```
|
||||
ReMeLongTermMemoryBase (abstract base)
|
||||
├── ReMePersonalLongTermMemory
|
||||
├── ReMeTaskLongTermMemory
|
||||
└── ReMeToolLongTermMemory
|
||||
```
|
||||
|
||||
**`ReMeLongTermMemoryBase`** provides:
|
||||
- Integration with ReMe library's `ReMeApp`
|
||||
- Async context manager implementation
|
||||
- Common interface definitions
|
||||
- Vector store and embedding management
|
||||
|
||||
### Memory Storage
|
||||
|
||||
- **Location**: `./memory_vector_store/` (configurable)
|
||||
- **Isolation**: Each `user_name` maintains separate storage
|
||||
- **Persistence**: Memories persist across sessions
|
||||
- **Format**: Vector embeddings with metadata
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. System Prompt Design
|
||||
|
||||
For agents with long-term memory, clearly specify when to record and retrieve:
|
||||
|
||||
```python
|
||||
sys_prompt = """
|
||||
You are an assistant with long-term memory.
|
||||
|
||||
Recording Guidelines:
|
||||
- Record when users share personal information, preferences, or important facts
|
||||
- Record successful task execution approaches and solutions
|
||||
- Record tool execution results with detailed metadata
|
||||
|
||||
Retrieval Guidelines:
|
||||
- ALWAYS retrieve before answering questions about past information
|
||||
- Retrieve when dealing with similar tasks to past executions
|
||||
- Check tool guidelines before using tools
|
||||
"""
|
||||
```
|
||||
|
||||
### 2. Score Assignment (Task Memory)
|
||||
|
||||
Use meaningful scores to prioritize experiences:
|
||||
|
||||
```python
|
||||
# Successful trajectory
|
||||
await task_memory.record_to_memory(..., score=0.95)
|
||||
|
||||
# Partially successful
|
||||
await task_memory.record_to_memory(..., score=0.6)
|
||||
|
||||
# Failed trajectory (still useful to learn from)
|
||||
await task_memory.record_to_memory(..., score=0.2)
|
||||
```
|
||||
|
||||
### 3. Tool Memory Workflow
|
||||
|
||||
Follow this pattern for tool memory:
|
||||
|
||||
```
|
||||
1. Execute tool → 2. Record result → 3. Trigger summarization → 4. Retrieve guidelines → 5. Use in agent
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue**: `RuntimeError: Memory not initialized`
|
||||
- **Solution**: Always use `async with memory:` context manager
|
||||
|
||||
**Issue**: No memories retrieved
|
||||
- **Solution**: Ensure you've recorded memories first and check `user_name` matches
|
||||
|
||||
**Issue**: Tool memory not generating guidelines
|
||||
- **Solution**: Record multiple tool executions to trigger summarization
|
||||
|
||||
**Issue**: Agent not using memory tools
|
||||
- **Solution**: Check `long_term_memory_mode="both"` and verify system prompt encourages memory usage
|
||||
|
||||
## References
|
||||
|
||||
- [ReMe Library](https://github.com/modelscope/ReMe) - Core memory implementation
|
||||
- [AgentScope Documentation](https://github.com/modelscope/agentscope) - Framework documentation
|
||||
- [DashScope API](https://dashscope.aliyun.com/) - Model API for examples
|
||||
@@ -0,0 +1,295 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Personal memory example demonstrating ReMe personal memory.
|
||||
|
||||
This module provides examples of how to use the ReMePersonalMemory
|
||||
class.
|
||||
|
||||
The example demonstrates 5 core interfaces:
|
||||
1. record_to_memory - Tool function for explicit memory recording
|
||||
2. retrieve_from_memory - Tool function for keyword-based retrieval
|
||||
3. record - Direct method for recording message conversations
|
||||
4. retrieve - Direct method for query-based retrieval
|
||||
5. ReActAgent integration - Using personal memory with ReActAgent
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.memory import ReMePersonalLongTermMemory
|
||||
from agentscope.message import Msg
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.tool import ToolResponse, Toolkit
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def test_record_to_memory(
|
||||
memory: ReMePersonalLongTermMemory,
|
||||
) -> None:
|
||||
"""Test the record_to_memory tool function interface."""
|
||||
print("Interface 1: record_to_memory (Tool Function)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Explicit memory recording with structured content")
|
||||
print("Test case: Recording user's travel preferences...")
|
||||
|
||||
result: ToolResponse = await memory.record_to_memory(
|
||||
thinking=("The user is sharing their travel preferences and habits"),
|
||||
content=[
|
||||
"I prefer to stay in homestays when traveling to Hangzhou",
|
||||
"I like to visit the West Lake in the morning",
|
||||
"I enjoy drinking Longjing tea",
|
||||
],
|
||||
)
|
||||
result_text = " ".join(
|
||||
block.get("text", "")
|
||||
for block in result.content
|
||||
if block.get("type") == "text"
|
||||
)
|
||||
print(f"✓ Result: {result_text}")
|
||||
print(
|
||||
f"✓ Status: {'Success' if 'Success' in result_text else 'Failed'}",
|
||||
)
|
||||
print()
|
||||
|
||||
|
||||
async def test_retrieve_from_memory(
|
||||
memory: ReMePersonalLongTermMemory,
|
||||
) -> None:
|
||||
"""Test the retrieve_from_memory tool function interface."""
|
||||
print("Interface 2: retrieve_from_memory (Tool Function)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Keyword-based memory retrieval")
|
||||
print()
|
||||
|
||||
result = await memory.retrieve_from_memory(
|
||||
keywords=["Hangzhou travel", "tea preference"],
|
||||
)
|
||||
retrieved_text = " ".join(
|
||||
block.get("text", "")
|
||||
for block in result.content
|
||||
if block.get("type") == "text"
|
||||
)
|
||||
print("✓ Retrieved memories:")
|
||||
print(f"{retrieved_text}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_record_direct(memory: ReMePersonalLongTermMemory) -> None:
|
||||
"""Test the direct record method interface."""
|
||||
print("Interface 3: record (Direct Recording)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Direct recording of message conversations")
|
||||
print()
|
||||
print("Test case: Recording work preferences and habits...")
|
||||
|
||||
try:
|
||||
await memory.record(
|
||||
msgs=[
|
||||
Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"I work as a software engineer and prefer "
|
||||
"remote work"
|
||||
),
|
||||
name="user",
|
||||
),
|
||||
Msg(
|
||||
role="assistant",
|
||||
content=(
|
||||
"Understood! You're a software engineer who "
|
||||
"values remote work flexibility."
|
||||
),
|
||||
name="assistant",
|
||||
),
|
||||
Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"I usually start my day at 9 AM with a "
|
||||
"cup of coffee"
|
||||
),
|
||||
name="user",
|
||||
),
|
||||
],
|
||||
)
|
||||
print("✓ Status: Successfully recorded conversation messages")
|
||||
print(
|
||||
"✓ Messages recorded: 3 messages (user-assistant dialogue)",
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"✗ Status: Failed - {str(e)}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_retrieve_direct(memory: ReMePersonalLongTermMemory) -> None:
|
||||
"""Test the direct retrieve method interface."""
|
||||
print("Interface 4: retrieve (Direct Retrieval)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Query-based memory retrieval using messages")
|
||||
print()
|
||||
print(
|
||||
"Test case: Querying 'What do you know about my "
|
||||
"work preferences?'...",
|
||||
)
|
||||
|
||||
memories = await memory.retrieve(
|
||||
msg=Msg(
|
||||
role="user",
|
||||
content="What do you know about my work preferences?",
|
||||
name="user",
|
||||
),
|
||||
)
|
||||
print("✓ Retrieved memories:")
|
||||
print(f"{memories if memories else 'No memories found'}")
|
||||
status = (
|
||||
"Success - Found memories"
|
||||
if memories
|
||||
else "No relevant memories found"
|
||||
)
|
||||
print(f"✓ Status: {status}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_react_agent_with_memory(
|
||||
memory: ReMePersonalLongTermMemory,
|
||||
) -> None:
|
||||
"""Test ReActAgent integration with personal memory."""
|
||||
print("Interface 5: ReActAgent with Personal Memory")
|
||||
print("-" * 70)
|
||||
print(
|
||||
"Purpose: Demonstrate how ReActAgent uses personal memory tools",
|
||||
)
|
||||
print()
|
||||
print("Test case: Agent-driven memory recording and retrieval...")
|
||||
|
||||
toolkit = Toolkit()
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt=(
|
||||
"You are a helpful assistant named Friday with long-term "
|
||||
"memory capabilities. "
|
||||
"\n\n## Memory Management Guidelines:\n"
|
||||
"1. **Recording Memories**: When users share personal "
|
||||
"information, preferences, "
|
||||
"habits, or facts about themselves, ALWAYS record them "
|
||||
"using `record_to_memory` "
|
||||
"for future reference.\n"
|
||||
"\n2. **Retrieving Memories**: BEFORE answering questions "
|
||||
"about the user's preferences, "
|
||||
"past information, or personal details, you MUST FIRST "
|
||||
"call `retrieve_from_memory` "
|
||||
"to check if you have any relevant stored information. "
|
||||
"Do NOT rely solely on the "
|
||||
"current conversation context.\n"
|
||||
"\n3. **When to Retrieve**: Call `retrieve_from_memory` "
|
||||
"when:\n"
|
||||
" - User asks questions like 'what do I like?', "
|
||||
"'what are my preferences?', "
|
||||
"'what do you know about me?'\n"
|
||||
" - User asks about their past behaviors, habits, or "
|
||||
"preferences\n"
|
||||
" - User refers to information they mentioned before\n"
|
||||
" - You need context about the user to provide "
|
||||
"personalized responses\n"
|
||||
"\nAlways check your memory first before claiming you "
|
||||
"don't know something about the user."
|
||||
),
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen3-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=memory,
|
||||
long_term_memory_mode="both",
|
||||
)
|
||||
|
||||
await agent.memory.clear()
|
||||
|
||||
print(
|
||||
"→ User: 'When I travel to Hangzhou, I prefer to stay in "
|
||||
"a homestay'",
|
||||
)
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"When I travel to Hangzhou, I prefer to stay in " "a homestay"
|
||||
),
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"✓ Agent response: {msg.get_text_content()}\n")
|
||||
|
||||
print("→ User: 'what preference do I have?'")
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content="what preference do I have?",
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"✓ Agent response: {msg.get_text_content()}\n")
|
||||
|
||||
print(
|
||||
"✓ Status: Successfully demonstrated ReActAgent with "
|
||||
"personal memory",
|
||||
)
|
||||
print()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Demonstrate the 5 core interfaces of ReMePersonalMemory.
|
||||
|
||||
This example shows how to use:
|
||||
1. record_to_memory - Tool function for explicit memory recording
|
||||
2. retrieve_from_memory - Tool function for keyword-based retrieval
|
||||
3. record - Direct method for recording message conversations
|
||||
4. retrieve - Direct method for query-based retrieval
|
||||
5. ReActAgent integration - Using personal memory with ReActAgent
|
||||
"""
|
||||
long_term_memory = ReMePersonalLongTermMemory(
|
||||
agent_name="Friday",
|
||||
user_name="user_123",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen3-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v4",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024,
|
||||
),
|
||||
)
|
||||
|
||||
print("=" * 70)
|
||||
print("ReMePersonalMemory - Testing 5 Core Interfaces")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
# Use async context manager to ensure proper initialization
|
||||
async with long_term_memory:
|
||||
# await test_record_to_memory(long_term_memory)
|
||||
# await test_retrieve_from_memory(long_term_memory)
|
||||
# await test_record_direct(long_term_memory)
|
||||
# await test_retrieve_direct(long_term_memory)
|
||||
await test_react_agent_with_memory(long_term_memory)
|
||||
|
||||
# Alternative way: manually call __aenter__ and __aexit__
|
||||
# This is equivalent to using "async with long_term_memory" above
|
||||
# await long_term_memory.__aenter__()
|
||||
# await test_react_agent_with_memory(long_term_memory)
|
||||
# await long_term_memory.__aexit__()
|
||||
|
||||
print("=" * 70)
|
||||
print("Testing Complete: All 5 Core Interfaces Verified!")
|
||||
print("=" * 70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,342 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Task memory example demonstrating ReMe task memory.
|
||||
|
||||
This module provides examples of how to use the ReMeTaskMemory class
|
||||
using the ReMe library.
|
||||
|
||||
The example demonstrates 5 core interfaces:
|
||||
1. record_to_memory - Tool function for recording task information
|
||||
2. retrieve_from_memory - Tool function for keyword-based retrieval
|
||||
3. record - Direct method for recording message conversations
|
||||
with scores
|
||||
4. retrieve - Direct method for retrieving task experiences
|
||||
5. ReActAgent integration - Using task memory with ReActAgent
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.memory import ReMeTaskLongTermMemory
|
||||
from agentscope.message import Msg
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.tool import ToolResponse, Toolkit
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def test_record_to_memory(memory: ReMeTaskLongTermMemory) -> None:
|
||||
"""Test the record_to_memory tool function interface."""
|
||||
print("Interface 1: record_to_memory (Tool Function)")
|
||||
print("-" * 70)
|
||||
print(
|
||||
"Purpose: Record task execution information with thinking and content",
|
||||
)
|
||||
print()
|
||||
print("Test case: Recording project planning task information...")
|
||||
|
||||
result: ToolResponse = await memory.record_to_memory(
|
||||
thinking=(
|
||||
"Recording project planning best practices and "
|
||||
"development approach"
|
||||
),
|
||||
content=[
|
||||
"For web application projects, break down into phases: "
|
||||
"Requirements gathering, Design, Development, Testing, "
|
||||
"Deployment",
|
||||
"Development phase recommendations: Frontend (React), "
|
||||
"Backend (FastAPI), Database (PostgreSQL), Agile "
|
||||
"methodology with 2-week sprints",
|
||||
"Dependency management: Use npm for frontend and pip for "
|
||||
"Python backend, maintain requirements.txt and "
|
||||
"package.json files",
|
||||
],
|
||||
score=0.9, # Optional: score for this trajectory (1.0)
|
||||
)
|
||||
result_text = " ".join(
|
||||
block.get("text", "")
|
||||
for block in result.content
|
||||
if block.get("type") == "text"
|
||||
)
|
||||
print(f"✓ Result: {result_text}")
|
||||
print(
|
||||
f"✓ Status: {'Success' if 'Success' in result_text else 'Failed'}",
|
||||
)
|
||||
print()
|
||||
|
||||
|
||||
async def test_retrieve_from_memory(
|
||||
memory: ReMeTaskLongTermMemory,
|
||||
) -> None:
|
||||
"""Test the retrieve_from_memory tool function interface."""
|
||||
print("Interface 2: retrieve_from_memory (Tool Function)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Keyword-based retrieval of task experiences")
|
||||
print()
|
||||
print(
|
||||
"Test case: Searching with keywords 'project planning', "
|
||||
"'development phase'...",
|
||||
)
|
||||
|
||||
result = await memory.retrieve_from_memory(
|
||||
keywords=["project planning", "development phase"],
|
||||
)
|
||||
retrieved_text = " ".join(
|
||||
block.get("text", "")
|
||||
for block in result.content
|
||||
if block.get("type") == "text"
|
||||
)
|
||||
print("✓ Retrieved experiences:")
|
||||
print(f"{retrieved_text}")
|
||||
has_experiences = (
|
||||
retrieved_text and "No task experiences found" not in retrieved_text
|
||||
)
|
||||
status = (
|
||||
"Success - Found experiences"
|
||||
if has_experiences
|
||||
else "No relevant experiences found"
|
||||
)
|
||||
print(f"✓ Status: {status}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_record_direct(memory: ReMeTaskLongTermMemory) -> None:
|
||||
"""Test the direct record method interface."""
|
||||
print("Interface 3: record (Direct Recording)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Direct recording of message conversations with scores")
|
||||
print()
|
||||
print("Test case: Recording debugging task conversation...")
|
||||
|
||||
try:
|
||||
await memory.record(
|
||||
msgs=[
|
||||
Msg(
|
||||
role="user",
|
||||
content="I'm getting a 404 error on my API endpoint",
|
||||
name="user",
|
||||
),
|
||||
Msg(
|
||||
role="assistant",
|
||||
content=(
|
||||
"Let's troubleshoot: 1) Check if the route is "
|
||||
"properly defined, 2) Verify the URL path, "
|
||||
"3) Ensure the server is running on the correct "
|
||||
"port"
|
||||
),
|
||||
name="assistant",
|
||||
),
|
||||
Msg(
|
||||
role="user",
|
||||
content="Found it! The route path had a typo.",
|
||||
name="user",
|
||||
),
|
||||
Msg(
|
||||
role="assistant",
|
||||
content=(
|
||||
"Great! Always double-check route paths and use "
|
||||
"a linter to catch typos early."
|
||||
),
|
||||
name="assistant",
|
||||
),
|
||||
],
|
||||
score=0.95, # Optional: score (default: 1.0)
|
||||
)
|
||||
print("✓ Status: Successfully recorded debugging trajectory")
|
||||
print("✓ Messages recorded: 4 messages with score 0.95")
|
||||
except Exception as e:
|
||||
print(f"✗ Status: Failed - {str(e)}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_retrieve_direct(memory: ReMeTaskLongTermMemory) -> None:
|
||||
"""Test the direct retrieve method interface."""
|
||||
print("Interface 4: retrieve (Direct Retrieval)")
|
||||
print("-" * 70)
|
||||
print("Purpose: Query-based retrieval using messages")
|
||||
print()
|
||||
print("Test case: Querying 'How to debug API errors?'...")
|
||||
|
||||
memories = await memory.retrieve(
|
||||
msg=Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"How should I approach debugging API errors in my "
|
||||
"application?"
|
||||
),
|
||||
name="user",
|
||||
),
|
||||
)
|
||||
print("✓ Retrieved experiences:")
|
||||
print(f"{memories if memories else 'No experiences found'}")
|
||||
status = (
|
||||
"Success - Found experiences"
|
||||
if memories
|
||||
else "No relevant experiences found"
|
||||
)
|
||||
print(f"✓ Status: {status}")
|
||||
print()
|
||||
|
||||
|
||||
async def test_react_agent_with_memory(
|
||||
memory: ReMeTaskLongTermMemory,
|
||||
) -> None:
|
||||
"""Test ReActAgent integration with task memory."""
|
||||
print("Interface 5: ReActAgent with Task Memory")
|
||||
print("-" * 70)
|
||||
print(
|
||||
"Purpose: Demonstrate how ReActAgent uses task memory tools",
|
||||
)
|
||||
print()
|
||||
print(
|
||||
"Test case: Agent-driven task experience recording and "
|
||||
"retrieval...",
|
||||
)
|
||||
|
||||
toolkit = Toolkit()
|
||||
agent = ReActAgent(
|
||||
name="TaskAssistant",
|
||||
sys_prompt=(
|
||||
"You are a helpful task assistant named TaskAssistant "
|
||||
"with long-term task memory. "
|
||||
"\n\n## Task Memory Management Guidelines:\n"
|
||||
"1. **Recording Task Experiences**: When you provide "
|
||||
"technical solutions, solve problems, "
|
||||
"or complete tasks, ALWAYS record the key insights using "
|
||||
"`record_to_memory`. Include:\n"
|
||||
" - Specific techniques and approaches used\n"
|
||||
" - Best practices and implementation details\n"
|
||||
" - Lessons learned and important considerations\n"
|
||||
" - Step-by-step procedures that worked well\n"
|
||||
"\n2. **Retrieving Past Experiences**: BEFORE solving a "
|
||||
"problem or answering technical "
|
||||
"questions, you MUST FIRST call `retrieve_from_memory` "
|
||||
"to check if you have relevant "
|
||||
"past experiences. This helps you:\n"
|
||||
" - Avoid repeating past mistakes\n"
|
||||
" - Leverage proven solutions\n"
|
||||
" - Provide more accurate and tested approaches\n"
|
||||
"\n3. **When to Retrieve**: Always retrieve when:\n"
|
||||
" - Asked about technical topics or problem-solving "
|
||||
"approaches\n"
|
||||
" - Asked to provide recommendations or best practices\n"
|
||||
" - Dealing with tasks similar to ones you may have "
|
||||
"handled before\n"
|
||||
" - User explicitly asks 'what do you know about...?' "
|
||||
"or 'have you seen this before?'\n"
|
||||
"\nAlways check your task memory first to provide the "
|
||||
"most informed responses."
|
||||
),
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen3-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
long_term_memory=memory,
|
||||
long_term_memory_mode="both",
|
||||
)
|
||||
|
||||
await agent.memory.clear()
|
||||
|
||||
print(
|
||||
"→ User: 'Here are some database optimization techniques "
|
||||
"I learned'",
|
||||
)
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"I just learned some valuable database optimization "
|
||||
"techniques for slow queries: "
|
||||
"1) Add indexes on foreign keys and WHERE clause columns "
|
||||
"to speed up joins and filtering. "
|
||||
"2) Use table partitioning to divide large tables by "
|
||||
"date or category for faster queries. "
|
||||
"3) Implement query result caching with Redis to avoid "
|
||||
"repeated database hits. "
|
||||
"4) Optimize JOIN order - put smallest tables first to "
|
||||
"reduce intermediate result sets. "
|
||||
"5) Use EXPLAIN ANALYZE to identify bottlenecks and "
|
||||
"missing indexes. "
|
||||
"Please record these optimization techniques for future "
|
||||
"reference."
|
||||
),
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"✓ Agent response: {msg.get_text_content()}\n")
|
||||
|
||||
print(
|
||||
"→ User: 'What do you know about database optimization?'",
|
||||
)
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content=(
|
||||
"What do you know about database optimization? "
|
||||
"Can you retrieve any past experiences?"
|
||||
),
|
||||
name="user",
|
||||
)
|
||||
msg = await agent(msg)
|
||||
print(f"✓ Agent response: {msg.get_text_content()}\n")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Demonstrate the 5 core interfaces of ReMeTaskMemory.
|
||||
|
||||
This example shows how to use:
|
||||
1. record_to_memory - Tool function for recording task information
|
||||
2. retrieve_from_memory - Tool function for keyword-based retrieval
|
||||
3. record - Direct method for recording message conversations with scores
|
||||
4. retrieve - Direct method for retrieving task experiences
|
||||
5. ReActAgent integration - Using task memory with ReActAgent
|
||||
"""
|
||||
long_term_memory = ReMeTaskLongTermMemory(
|
||||
agent_name="TaskAssistant",
|
||||
user_name="task_workspace_123",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen3-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v4",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024,
|
||||
),
|
||||
)
|
||||
|
||||
print("=" * 70)
|
||||
print("ReMeTaskMemory - Testing 5 Core Interfaces")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
# Use async context manager to ensure proper initialization
|
||||
async with long_term_memory:
|
||||
# await test_record_to_memory(long_term_memory)
|
||||
# await test_retrieve_from_memory(long_term_memory)
|
||||
# await test_record_direct(long_term_memory)
|
||||
# await test_retrieve_direct(long_term_memory)
|
||||
await test_react_agent_with_memory(long_term_memory)
|
||||
|
||||
# Alternative way: manually call __aenter__ and __aexit__
|
||||
# This is equivalent to using "async with long_term_memory" above
|
||||
# await long_term_memory.__aenter__()
|
||||
# await test_react_agent_with_memory(long_term_memory)
|
||||
# await long_term_memory.__aexit__()
|
||||
|
||||
print("=" * 70)
|
||||
print("Testing Complete: All 5 Core Interfaces Verified!")
|
||||
print("=" * 70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,436 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tool memory example demonstrating ReMe tool memory with ReActAgent.
|
||||
|
||||
This module demonstrates the complete workflow:
|
||||
1. Mock a tool function and register it to Toolkit
|
||||
2. Record tool execution results to tool memory using record()
|
||||
3. Retrieve tool usage guidelines using retrieve()
|
||||
4. Inject guidelines into ReActAgent's system prompt
|
||||
5. Use ReActAgent with tool memory
|
||||
|
||||
This workflow helps LLMs learn from past tool usage patterns and
|
||||
improve their tool calling decisions over time.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.embedding import DashScopeTextEmbedding
|
||||
from agentscope.formatter import DashScopeChatFormatter
|
||||
from agentscope.memory import InMemoryMemory
|
||||
from agentscope.memory import ReMeToolLongTermMemory
|
||||
from agentscope.message import Msg
|
||||
from agentscope.message import TextBlock
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.tool import Toolkit, ToolResponse
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Step 1: Mock tool functions
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def web_search(query: str, max_results: int = 5) -> ToolResponse:
|
||||
"""Search the web for information.
|
||||
|
||||
Args:
|
||||
query: The search query string
|
||||
max_results: Maximum number of results to return
|
||||
|
||||
Returns:
|
||||
ToolResponse containing search results
|
||||
"""
|
||||
# Simulate web search
|
||||
result = f"Found {max_results} results for query: '{query}'"
|
||||
return ToolResponse(
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text=result,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
async def calculate(expression: str) -> ToolResponse:
|
||||
"""Calculate a mathematical expression.
|
||||
|
||||
Args:
|
||||
expression: Mathematical expression to evaluate
|
||||
|
||||
Returns:
|
||||
ToolResponse containing calculation result
|
||||
"""
|
||||
try:
|
||||
# Simple calculation (in real scenario, use safer evaluation)
|
||||
result = eval(expression) # noqa: S307
|
||||
return ToolResponse(
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text=f"Result: {result}",
|
||||
),
|
||||
],
|
||||
)
|
||||
except Exception as e:
|
||||
return ToolResponse(
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text=f"Error calculating '{expression}': {str(e)}",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Step 2: Record tool execution history to tool memory
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def record_tool_history(
|
||||
tool_memory: ReMeToolLongTermMemory,
|
||||
) -> None:
|
||||
"""Record historical tool execution results to tool memory.
|
||||
|
||||
This simulates past tool usage that the agent can learn from.
|
||||
"""
|
||||
print("=" * 70)
|
||||
print("Step 1: Recording Tool Execution History to Memory")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
# Record successful web_search examples
|
||||
web_search_histories = [
|
||||
{
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "web_search",
|
||||
"input": {
|
||||
"query": "Python asyncio tutorial",
|
||||
"max_results": 10,
|
||||
},
|
||||
"output": (
|
||||
"Found 10 results for query: 'Python asyncio tutorial'"
|
||||
),
|
||||
"token_cost": 150,
|
||||
"success": True,
|
||||
"time_cost": 2.3,
|
||||
},
|
||||
{
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "web_search",
|
||||
"input": {
|
||||
"query": "machine learning basics",
|
||||
"max_results": 5,
|
||||
},
|
||||
"output": ("Found 5 results for query: 'machine learning basics'"),
|
||||
"token_cost": 120,
|
||||
"success": True,
|
||||
"time_cost": 1.8,
|
||||
},
|
||||
]
|
||||
|
||||
# Record failed web_search example (empty query)
|
||||
web_search_fail = {
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "web_search",
|
||||
"input": {
|
||||
"query": "",
|
||||
"max_results": 5,
|
||||
},
|
||||
"output": "Error: Query cannot be empty",
|
||||
"token_cost": 20,
|
||||
"success": False,
|
||||
"time_cost": 0.1,
|
||||
}
|
||||
|
||||
# Record calculate examples
|
||||
calculate_histories = [
|
||||
{
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "calculate",
|
||||
"input": {
|
||||
"expression": "2 + 2",
|
||||
},
|
||||
"output": "Result: 4",
|
||||
"token_cost": 30,
|
||||
"success": True,
|
||||
"time_cost": 0.05,
|
||||
},
|
||||
{
|
||||
"create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"tool_name": "calculate",
|
||||
"input": {
|
||||
"expression": "10 * 5 + 3",
|
||||
},
|
||||
"output": "Result: 53",
|
||||
"token_cost": 30,
|
||||
"success": True,
|
||||
"time_cost": 0.05,
|
||||
},
|
||||
]
|
||||
|
||||
# Record all histories
|
||||
all_histories = (
|
||||
web_search_histories + [web_search_fail] + calculate_histories
|
||||
)
|
||||
|
||||
print(f"Recording {len(all_histories)} tool execution histories...")
|
||||
await tool_memory.record(
|
||||
msgs=[
|
||||
Msg(
|
||||
role="assistant",
|
||||
content=json.dumps(history),
|
||||
name="assistant",
|
||||
)
|
||||
for history in all_histories
|
||||
],
|
||||
)
|
||||
print(f"✓ Successfully recorded {len(all_histories)} tool executions")
|
||||
print()
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Step 3: Retrieve tool guidelines and create enhanced system prompt
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def retrieve_tool_guidelines(
|
||||
tool_memory: ReMeToolLongTermMemory,
|
||||
tool_names: list[str],
|
||||
) -> str:
|
||||
"""Retrieve tool usage guidelines from memory.
|
||||
|
||||
Args:
|
||||
tool_memory: The ReMeToolMemory instance
|
||||
tool_names: List of tool names to retrieve guidelines for
|
||||
|
||||
Returns:
|
||||
Combined guidelines text to be added to system prompt
|
||||
"""
|
||||
print("=" * 70)
|
||||
print("Step 2: Retrieving Tool Usage Guidelines from Memory")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
all_guidelines = []
|
||||
|
||||
for tool_name in tool_names:
|
||||
print(f"Retrieving guidelines for '{tool_name}'...")
|
||||
guidelines = await tool_memory.retrieve(
|
||||
msg=Msg(
|
||||
role="user",
|
||||
content=tool_name,
|
||||
name="user",
|
||||
),
|
||||
)
|
||||
|
||||
if guidelines:
|
||||
all_guidelines.append(
|
||||
f"## Guidelines for {tool_name}:\n{guidelines}",
|
||||
)
|
||||
print(f"✓ Retrieved guidelines for '{tool_name}'")
|
||||
print(f" Preview: {guidelines}")
|
||||
else:
|
||||
print(
|
||||
f"✓ No guidelines found for '{tool_name}' " "(first time use)",
|
||||
)
|
||||
print()
|
||||
|
||||
if all_guidelines:
|
||||
combined_guidelines = "\n\n".join(all_guidelines)
|
||||
guidelines_prompt = f"""
|
||||
# Tool Usage Guidelines (from past experience)
|
||||
|
||||
{combined_guidelines}
|
||||
|
||||
Please follow these guidelines when using the tools.
|
||||
"""
|
||||
return guidelines_prompt
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Step 4: Use ReActAgent with tool memory
|
||||
# ============================================================================
|
||||
|
||||
|
||||
async def use_react_agent_with_tool_memory(
|
||||
toolkit: Toolkit,
|
||||
tool_guidelines: str,
|
||||
) -> None:
|
||||
"""Create and use ReActAgent with tool memory guidelines.
|
||||
|
||||
Args:
|
||||
toolkit: The Toolkit with registered tools
|
||||
tool_guidelines: Retrieved tool usage guidelines
|
||||
"""
|
||||
print("=" * 70)
|
||||
print("Step 3: Using ReActAgent with Tool Memory")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
# Create enhanced system prompt with tool guidelines
|
||||
base_sys_prompt = (
|
||||
"You are a helpful AI assistant named ToolBot.\n"
|
||||
"You have access to various tools to help users complete "
|
||||
"their tasks.\n"
|
||||
"Please use the tools appropriately based on the user's "
|
||||
"requests."
|
||||
)
|
||||
|
||||
if tool_guidelines:
|
||||
sys_prompt = f"{base_sys_prompt}\n{tool_guidelines}"
|
||||
print(
|
||||
"✓ System prompt enhanced with tool memory guidelines",
|
||||
)
|
||||
else:
|
||||
sys_prompt = base_sys_prompt
|
||||
print(
|
||||
"✓ Using base system prompt (no guidelines available)",
|
||||
)
|
||||
|
||||
print()
|
||||
|
||||
# Create ReActAgent
|
||||
agent = ReActAgent(
|
||||
name="ToolBot",
|
||||
sys_prompt=sys_prompt,
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
memory=InMemoryMemory(),
|
||||
max_iters=5,
|
||||
)
|
||||
|
||||
print("✓ ReActAgent created successfully")
|
||||
print()
|
||||
|
||||
# Test queries
|
||||
test_queries = [
|
||||
"Search the web for 'Python design patterns'",
|
||||
"Calculate 15 * 7 + 23",
|
||||
]
|
||||
|
||||
print("-" * 70)
|
||||
print("Testing ReActAgent with tool memory...")
|
||||
print("-" * 70)
|
||||
print()
|
||||
|
||||
for i, query in enumerate(test_queries, 1):
|
||||
print(f"Query {i}: {query}")
|
||||
print("-" * 70)
|
||||
|
||||
msg = Msg(
|
||||
role="user",
|
||||
content=query,
|
||||
name="user",
|
||||
)
|
||||
|
||||
response = await agent(msg)
|
||||
print(f"Response: {response.get_text_content()}")
|
||||
print()
|
||||
print()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Demonstrate the workflow of using ReMeToolMemory with ReActAgent.
|
||||
|
||||
This example shows:
|
||||
1. Create mock tools and register them to Toolkit
|
||||
2. Record historical tool execution results to tool memory
|
||||
3. Retrieve tool usage guidelines from memory
|
||||
4. Inject guidelines into ReActAgent's system prompt
|
||||
5. Use ReActAgent to complete tasks with tool memory
|
||||
"""
|
||||
print("=" * 70)
|
||||
print("ReMeToolMemory + ReActAgent Integration Example")
|
||||
print("=" * 70)
|
||||
print()
|
||||
print("This workflow demonstrates:")
|
||||
print("1. Mock tools → Register to Toolkit")
|
||||
print("2. Record tool execution history → Tool Memory")
|
||||
print("3. Retrieve guidelines → Enhance system prompt")
|
||||
print("4. Use ReActAgent with tool memory")
|
||||
print()
|
||||
|
||||
# Initialize tool memory
|
||||
tool_memory = ReMeToolLongTermMemory(
|
||||
agent_name="ToolBot",
|
||||
user_name="tool_workspace_demo",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
stream=False,
|
||||
),
|
||||
embedding_model=DashScopeTextEmbedding(
|
||||
model_name="text-embedding-v4",
|
||||
api_key=os.environ.get("DASHSCOPE_API_KEY"),
|
||||
dimensions=1024,
|
||||
),
|
||||
)
|
||||
|
||||
# Create and register tools to toolkit
|
||||
toolkit = Toolkit()
|
||||
toolkit.register_tool_function(web_search)
|
||||
toolkit.register_tool_function(calculate)
|
||||
print()
|
||||
|
||||
# Use async context manager for tool memory
|
||||
async with tool_memory:
|
||||
# Step 1: Record historical tool executions to memory
|
||||
await record_tool_history(tool_memory)
|
||||
|
||||
# Step 2: Retrieve tool usage guidelines
|
||||
tool_names = ["web_search", "calculate"]
|
||||
tool_guidelines = await retrieve_tool_guidelines(
|
||||
tool_memory,
|
||||
tool_names,
|
||||
)
|
||||
|
||||
# Step 3: Use ReActAgent with enhanced system prompt
|
||||
await use_react_agent_with_tool_memory(
|
||||
toolkit,
|
||||
tool_guidelines,
|
||||
)
|
||||
|
||||
# Alternative way: manually call __aenter__ and __aexit__
|
||||
# This is equivalent to using "async with tool_memory" above
|
||||
# await tool_memory.__aenter__()
|
||||
# tool_guidelines = await retrieve_tool_guidelines(tool_memory, tool_names)
|
||||
# await tool_memory.__aexit__()
|
||||
|
||||
print("=" * 70)
|
||||
print("Workflow Complete!")
|
||||
print("=" * 70)
|
||||
print()
|
||||
print("Summary:")
|
||||
print("✓ Mock tools created and registered to Toolkit")
|
||||
print("✓ Historical tool executions recorded to tool memory")
|
||||
print("✓ Tool usage guidelines retrieved from memory")
|
||||
print("✓ ReActAgent system prompt enhanced with guidelines")
|
||||
print(
|
||||
"✓ ReActAgent successfully used tools with memory guidance",
|
||||
)
|
||||
print()
|
||||
print("Benefits:")
|
||||
print("- Agent learns from past tool usage patterns")
|
||||
print("- Reduced errors by following proven guidelines")
|
||||
print("- Better tool parameter selection")
|
||||
print("- Improved success rate over time")
|
||||
print("=" * 70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user