mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-07 07:08:31 +00:00
Compare commits
1 Commits
1.5.0
...
lg-memory-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df4754301a |
@@ -255,6 +255,17 @@ CrewAI provides a wide range of events that you can listen for:
|
|||||||
- **LLMCallFailedEvent**: Emitted when an LLM call fails
|
- **LLMCallFailedEvent**: Emitted when an LLM call fails
|
||||||
- **LLMStreamChunkEvent**: Emitted for each chunk received during streaming LLM responses
|
- **LLMStreamChunkEvent**: Emitted for each chunk received during streaming LLM responses
|
||||||
|
|
||||||
|
### Memory Events
|
||||||
|
|
||||||
|
- **MemoryQueryStartedEvent**: Emitted when a memory query is started. Contains the query, limit, and optional score threshold.
|
||||||
|
- **MemoryQueryCompletedEvent**: Emitted when a memory query is completed successfully. Contains the query, results, limit, score threshold, and query execution time.
|
||||||
|
- **MemoryQueryFailedEvent**: Emitted when a memory query fails. Contains the query, limit, score threshold, and error message.
|
||||||
|
- **MemorySaveStartedEvent**: Emitted when a memory save operation is started. Contains the value to be saved, metadata, and optional agent role.
|
||||||
|
- **MemorySaveCompletedEvent**: Emitted when a memory save operation is completed successfully. Contains the saved value, metadata, agent role, and save execution time.
|
||||||
|
- **MemorySaveFailedEvent**: Emitted when a memory save operation fails. Contains the value, metadata, agent role, and error message.
|
||||||
|
- **MemoryRetrievalStartedEvent**: Emitted when memory retrieval for a task prompt starts. Contains the optional task ID.
|
||||||
|
- **MemoryRetrievalCompletedEvent**: Emitted when memory retrieval for a task prompt completes successfully. Contains the task ID, memory content, and retrieval execution time.
|
||||||
|
|
||||||
## Event Handler Structure
|
## Event Handler Structure
|
||||||
|
|
||||||
Each event handler receives two parameters:
|
Each event handler receives two parameters:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ icon: database
|
|||||||
The CrewAI framework provides a sophisticated memory system designed to significantly enhance AI agent capabilities. CrewAI offers **three distinct memory approaches** that serve different use cases:
|
The CrewAI framework provides a sophisticated memory system designed to significantly enhance AI agent capabilities. CrewAI offers **three distinct memory approaches** that serve different use cases:
|
||||||
|
|
||||||
1. **Basic Memory System** - Built-in short-term, long-term, and entity memory
|
1. **Basic Memory System** - Built-in short-term, long-term, and entity memory
|
||||||
2. **User Memory** - User-specific memory with Mem0 integration (legacy approach)
|
2. **User Memory** - User-specific memory with Mem0 integration (legacy approach)
|
||||||
3. **External Memory** - Standalone external memory providers (new approach)
|
3. **External Memory** - Standalone external memory providers (new approach)
|
||||||
|
|
||||||
## Memory System Components
|
## Memory System Components
|
||||||
@@ -62,7 +62,7 @@ By default, CrewAI uses the `appdirs` library to determine storage locations fol
|
|||||||
```
|
```
|
||||||
~/Library/Application Support/CrewAI/{project_name}/
|
~/Library/Application Support/CrewAI/{project_name}/
|
||||||
├── knowledge/ # Knowledge base ChromaDB files
|
├── knowledge/ # Knowledge base ChromaDB files
|
||||||
├── short_term_memory/ # Short-term memory ChromaDB files
|
├── short_term_memory/ # Short-term memory ChromaDB files
|
||||||
├── long_term_memory/ # Long-term memory ChromaDB files
|
├── long_term_memory/ # Long-term memory ChromaDB files
|
||||||
├── entities/ # Entity memory ChromaDB files
|
├── entities/ # Entity memory ChromaDB files
|
||||||
└── long_term_memory_storage.db # SQLite database
|
└── long_term_memory_storage.db # SQLite database
|
||||||
@@ -252,7 +252,7 @@ chroma_path = os.path.join(storage_path, "knowledge")
|
|||||||
if os.path.exists(chroma_path):
|
if os.path.exists(chroma_path):
|
||||||
client = chromadb.PersistentClient(path=chroma_path)
|
client = chromadb.PersistentClient(path=chroma_path)
|
||||||
collections = client.list_collections()
|
collections = client.list_collections()
|
||||||
|
|
||||||
print("ChromaDB Collections:")
|
print("ChromaDB Collections:")
|
||||||
for collection in collections:
|
for collection in collections:
|
||||||
print(f" - {collection.name}: {collection.count()} documents")
|
print(f" - {collection.name}: {collection.count()} documents")
|
||||||
@@ -269,7 +269,7 @@ crew = Crew(agents=[...], tasks=[...], memory=True)
|
|||||||
|
|
||||||
# Reset specific memory types
|
# Reset specific memory types
|
||||||
crew.reset_memories(command_type='short') # Short-term memory
|
crew.reset_memories(command_type='short') # Short-term memory
|
||||||
crew.reset_memories(command_type='long') # Long-term memory
|
crew.reset_memories(command_type='long') # Long-term memory
|
||||||
crew.reset_memories(command_type='entity') # Entity memory
|
crew.reset_memories(command_type='entity') # Entity memory
|
||||||
crew.reset_memories(command_type='knowledge') # Knowledge storage
|
crew.reset_memories(command_type='knowledge') # Knowledge storage
|
||||||
```
|
```
|
||||||
@@ -596,7 +596,7 @@ providers_to_test = [
|
|||||||
{
|
{
|
||||||
"name": "Ollama",
|
"name": "Ollama",
|
||||||
"config": {
|
"config": {
|
||||||
"provider": "ollama",
|
"provider": "ollama",
|
||||||
"config": {"model": "mxbai-embed-large"}
|
"config": {"model": "mxbai-embed-large"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,7 +604,7 @@ providers_to_test = [
|
|||||||
|
|
||||||
for provider in providers_to_test:
|
for provider in providers_to_test:
|
||||||
print(f"\nTesting {provider['name']} embeddings...")
|
print(f"\nTesting {provider['name']} embeddings...")
|
||||||
|
|
||||||
# Create crew with specific embedder
|
# Create crew with specific embedder
|
||||||
crew = Crew(
|
crew = Crew(
|
||||||
agents=[...],
|
agents=[...],
|
||||||
@@ -612,7 +612,7 @@ for provider in providers_to_test:
|
|||||||
memory=True,
|
memory=True,
|
||||||
embedder=provider['config']
|
embedder=provider['config']
|
||||||
)
|
)
|
||||||
|
|
||||||
# Run your test and measure performance
|
# Run your test and measure performance
|
||||||
result = crew.kickoff()
|
result = crew.kickoff()
|
||||||
print(f"{provider['name']} completed successfully")
|
print(f"{provider['name']} completed successfully")
|
||||||
@@ -655,17 +655,17 @@ import time
|
|||||||
|
|
||||||
def test_embedding_performance(embedder_config, test_text="This is a test document"):
|
def test_embedding_performance(embedder_config, test_text="This is a test document"):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
crew = Crew(
|
crew = Crew(
|
||||||
agents=[...],
|
agents=[...],
|
||||||
tasks=[...],
|
tasks=[...],
|
||||||
memory=True,
|
memory=True,
|
||||||
embedder=embedder_config
|
embedder=embedder_config
|
||||||
)
|
)
|
||||||
|
|
||||||
# Simulate memory operation
|
# Simulate memory operation
|
||||||
crew.kickoff()
|
crew.kickoff()
|
||||||
|
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
return end_time - start_time
|
return end_time - start_time
|
||||||
|
|
||||||
@@ -676,7 +676,7 @@ openai_time = test_embedding_performance({
|
|||||||
})
|
})
|
||||||
|
|
||||||
ollama_time = test_embedding_performance({
|
ollama_time = test_embedding_performance({
|
||||||
"provider": "ollama",
|
"provider": "ollama",
|
||||||
"config": {"model": "mxbai-embed-large"}
|
"config": {"model": "mxbai-embed-large"}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -783,7 +783,7 @@ os.environ["MEM0_API_KEY"] = "your-api-key"
|
|||||||
# Create external memory instance
|
# Create external memory instance
|
||||||
external_memory = ExternalMemory(
|
external_memory = ExternalMemory(
|
||||||
embedder_config={
|
embedder_config={
|
||||||
"provider": "mem0",
|
"provider": "mem0",
|
||||||
"config": {"user_id": "U-123"}
|
"config": {"user_id": "U-123"}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -808,8 +808,8 @@ class CustomStorage(Storage):
|
|||||||
|
|
||||||
def save(self, value, metadata=None, agent=None):
|
def save(self, value, metadata=None, agent=None):
|
||||||
self.memories.append({
|
self.memories.append({
|
||||||
"value": value,
|
"value": value,
|
||||||
"metadata": metadata,
|
"metadata": metadata,
|
||||||
"agent": agent
|
"agent": agent
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -986,7 +986,201 @@ crew = Crew(
|
|||||||
- 🫡 **Enhanced Personalization:** Memory enables agents to remember user preferences and historical interactions, leading to personalized experiences.
|
- 🫡 **Enhanced Personalization:** Memory enables agents to remember user preferences and historical interactions, leading to personalized experiences.
|
||||||
- 🧠 **Improved Problem Solving:** Access to a rich memory store aids agents in making more informed decisions, drawing on past learnings and contextual insights.
|
- 🧠 **Improved Problem Solving:** Access to a rich memory store aids agents in making more informed decisions, drawing on past learnings and contextual insights.
|
||||||
|
|
||||||
|
## Memory Events
|
||||||
|
|
||||||
|
CrewAI's event system provides powerful insights into memory operations. By leveraging memory events, you can monitor, debug, and optimize your memory system's performance and behavior.
|
||||||
|
|
||||||
|
### Available Memory Events
|
||||||
|
|
||||||
|
CrewAI emits the following memory-related events:
|
||||||
|
|
||||||
|
| Event | Description | Key Properties |
|
||||||
|
| :---- | :---------- | :------------- |
|
||||||
|
| **MemoryQueryStartedEvent** | Emitted when a memory query begins | `query`, `limit`, `score_threshold` |
|
||||||
|
| **MemoryQueryCompletedEvent** | Emitted when a memory query completes successfully | `query`, `results`, `limit`, `score_threshold`, `query_time_ms` |
|
||||||
|
| **MemoryQueryFailedEvent** | Emitted when a memory query fails | `query`, `limit`, `score_threshold`, `error` |
|
||||||
|
| **MemorySaveStartedEvent** | Emitted when a memory save operation begins | `value`, `metadata`, `agent_role` |
|
||||||
|
| **MemorySaveCompletedEvent** | Emitted when a memory save operation completes successfully | `value`, `metadata`, `agent_role`, `save_time_ms` |
|
||||||
|
| **MemorySaveFailedEvent** | Emitted when a memory save operation fails | `value`, `metadata`, `agent_role`, `error` |
|
||||||
|
| **MemoryRetrievalStartedEvent** | Emitted when memory retrieval for a task prompt starts | `task_id` |
|
||||||
|
| **MemoryRetrievalCompletedEvent** | Emitted when memory retrieval completes successfully | `task_id`, `memory_content`, `retrieval_time_ms` |
|
||||||
|
|
||||||
|
### Practical Applications
|
||||||
|
|
||||||
|
#### 1. Memory Performance Monitoring
|
||||||
|
|
||||||
|
Track memory operation timing to optimize your application:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from crewai.utilities.events.base_event_listener import BaseEventListener
|
||||||
|
from crewai.utilities.events import (
|
||||||
|
MemoryQueryCompletedEvent,
|
||||||
|
MemorySaveCompletedEvent
|
||||||
|
)
|
||||||
|
import time
|
||||||
|
|
||||||
|
class MemoryPerformanceMonitor(BaseEventListener):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.query_times = []
|
||||||
|
self.save_times = []
|
||||||
|
|
||||||
|
def setup_listeners(self, crewai_event_bus):
|
||||||
|
@crewai_event_bus.on(MemoryQueryCompletedEvent)
|
||||||
|
def on_memory_query_completed(source, event: MemoryQueryCompletedEvent):
|
||||||
|
self.query_times.append(event.query_time_ms)
|
||||||
|
print(f"Memory query completed in {event.query_time_ms:.2f}ms. Query: '{event.query}'")
|
||||||
|
print(f"Average query time: {sum(self.query_times)/len(self.query_times):.2f}ms")
|
||||||
|
|
||||||
|
@crewai_event_bus.on(MemorySaveCompletedEvent)
|
||||||
|
def on_memory_save_completed(source, event: MemorySaveCompletedEvent):
|
||||||
|
self.save_times.append(event.save_time_ms)
|
||||||
|
print(f"Memory save completed in {event.save_time_ms:.2f}ms")
|
||||||
|
print(f"Average save time: {sum(self.save_times)/len(self.save_times):.2f}ms")
|
||||||
|
|
||||||
|
# Create an instance of your listener
|
||||||
|
memory_monitor = MemoryPerformanceMonitor()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Memory Content Logging
|
||||||
|
|
||||||
|
Log memory operations for debugging and insights:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from crewai.utilities.events.base_event_listener import BaseEventListener
|
||||||
|
from crewai.utilities.events import (
|
||||||
|
MemorySaveStartedEvent,
|
||||||
|
MemoryQueryStartedEvent,
|
||||||
|
MemoryRetrievalCompletedEvent
|
||||||
|
)
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger = logging.getLogger('memory_events')
|
||||||
|
|
||||||
|
class MemoryLogger(BaseEventListener):
|
||||||
|
def setup_listeners(self, crewai_event_bus):
|
||||||
|
@crewai_event_bus.on(MemorySaveStartedEvent)
|
||||||
|
def on_memory_save_started(source, event: MemorySaveStartedEvent):
|
||||||
|
if event.agent_role:
|
||||||
|
logger.info(f"Agent '{event.agent_role}' saving memory: {event.value[:50]}...")
|
||||||
|
else:
|
||||||
|
logger.info(f"Saving memory: {event.value[:50]}...")
|
||||||
|
|
||||||
|
@crewai_event_bus.on(MemoryQueryStartedEvent)
|
||||||
|
def on_memory_query_started(source, event: MemoryQueryStartedEvent):
|
||||||
|
logger.info(f"Memory query started: '{event.query}' (limit: {event.limit})")
|
||||||
|
|
||||||
|
@crewai_event_bus.on(MemoryRetrievalCompletedEvent)
|
||||||
|
def on_memory_retrieval_completed(source, event: MemoryRetrievalCompletedEvent):
|
||||||
|
if event.task_id:
|
||||||
|
logger.info(f"Memory retrieved for task {event.task_id} in {event.retrieval_time_ms:.2f}ms")
|
||||||
|
else:
|
||||||
|
logger.info(f"Memory retrieved in {event.retrieval_time_ms:.2f}ms")
|
||||||
|
logger.debug(f"Memory content: {event.memory_content}")
|
||||||
|
|
||||||
|
# Create an instance of your listener
|
||||||
|
memory_logger = MemoryLogger()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Error Tracking and Notifications
|
||||||
|
|
||||||
|
Capture and respond to memory errors:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from crewai.utilities.events.base_event_listener import BaseEventListener
|
||||||
|
from crewai.utilities.events import (
|
||||||
|
MemorySaveFailedEvent,
|
||||||
|
MemoryQueryFailedEvent
|
||||||
|
)
|
||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger = logging.getLogger('memory_errors')
|
||||||
|
|
||||||
|
class MemoryErrorTracker(BaseEventListener):
|
||||||
|
def __init__(self, notify_email: Optional[str] = None):
|
||||||
|
super().__init__()
|
||||||
|
self.notify_email = notify_email
|
||||||
|
self.error_count = 0
|
||||||
|
|
||||||
|
def setup_listeners(self, crewai_event_bus):
|
||||||
|
@crewai_event_bus.on(MemorySaveFailedEvent)
|
||||||
|
def on_memory_save_failed(source, event: MemorySaveFailedEvent):
|
||||||
|
self.error_count += 1
|
||||||
|
agent_info = f"Agent '{event.agent_role}'" if event.agent_role else "Unknown agent"
|
||||||
|
error_message = f"Memory save failed: {event.error}. {agent_info}"
|
||||||
|
logger.error(error_message)
|
||||||
|
|
||||||
|
if self.notify_email and self.error_count % 5 == 0:
|
||||||
|
self._send_notification(error_message)
|
||||||
|
|
||||||
|
@crewai_event_bus.on(MemoryQueryFailedEvent)
|
||||||
|
def on_memory_query_failed(source, event: MemoryQueryFailedEvent):
|
||||||
|
self.error_count += 1
|
||||||
|
error_message = f"Memory query failed: {event.error}. Query: '{event.query}'"
|
||||||
|
logger.error(error_message)
|
||||||
|
|
||||||
|
if self.notify_email and self.error_count % 5 == 0:
|
||||||
|
self._send_notification(error_message)
|
||||||
|
|
||||||
|
def _send_notification(self, message):
|
||||||
|
# Implement your notification system (email, Slack, etc.)
|
||||||
|
print(f"[NOTIFICATION] Would send to {self.notify_email}: {message}")
|
||||||
|
|
||||||
|
# Create an instance of your listener
|
||||||
|
error_tracker = MemoryErrorTracker(notify_email="admin@example.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integrating with Analytics Platforms
|
||||||
|
|
||||||
|
Memory events can be forwarded to analytics and monitoring platforms to track performance metrics, detect anomalies, and visualize memory usage patterns:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from crewai.utilities.events.base_event_listener import BaseEventListener
|
||||||
|
from crewai.utilities.events import (
|
||||||
|
MemoryQueryCompletedEvent,
|
||||||
|
MemorySaveCompletedEvent
|
||||||
|
)
|
||||||
|
|
||||||
|
class MemoryAnalyticsForwarder(BaseEventListener):
|
||||||
|
def __init__(self, analytics_client):
|
||||||
|
super().__init__()
|
||||||
|
self.client = analytics_client
|
||||||
|
|
||||||
|
def setup_listeners(self, crewai_event_bus):
|
||||||
|
@crewai_event_bus.on(MemoryQueryCompletedEvent)
|
||||||
|
def on_memory_query_completed(source, event: MemoryQueryCompletedEvent):
|
||||||
|
# Forward query metrics to analytics platform
|
||||||
|
self.client.track_metric({
|
||||||
|
"event_type": "memory_query",
|
||||||
|
"query": event.query,
|
||||||
|
"duration_ms": event.query_time_ms,
|
||||||
|
"result_count": len(event.results) if hasattr(event.results, "__len__") else 0,
|
||||||
|
"timestamp": event.timestamp
|
||||||
|
})
|
||||||
|
|
||||||
|
@crewai_event_bus.on(MemorySaveCompletedEvent)
|
||||||
|
def on_memory_save_completed(source, event: MemorySaveCompletedEvent):
|
||||||
|
# Forward save metrics to analytics platform
|
||||||
|
self.client.track_metric({
|
||||||
|
"event_type": "memory_save",
|
||||||
|
"agent_role": event.agent_role,
|
||||||
|
"duration_ms": event.save_time_ms,
|
||||||
|
"timestamp": event.timestamp
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Best Practices for Memory Event Listeners
|
||||||
|
|
||||||
|
1. **Keep handlers lightweight**: Avoid complex processing in event handlers to prevent performance impacts
|
||||||
|
2. **Use appropriate logging levels**: Use INFO for normal operations, DEBUG for details, ERROR for issues
|
||||||
|
3. **Batch metrics when possible**: Accumulate metrics before sending to external systems
|
||||||
|
4. **Handle exceptions gracefully**: Ensure your event handlers don't crash due to unexpected data
|
||||||
|
5. **Consider memory consumption**: Be mindful of storing large amounts of event data
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
Integrating CrewAI's memory system into your projects is straightforward. By leveraging the provided memory components and configurations,
|
Integrating CrewAI's memory system into your projects is straightforward. By leveraging the provided memory components and configurations,
|
||||||
you can quickly empower your agents with the ability to remember, reason, and learn from their interactions, unlocking new levels of intelligence and capability.
|
you can quickly empower your agents with the ability to remember, reason, and learn from their interactions, unlocking new levels of intelligence and capability.
|
||||||
|
|||||||
Reference in New Issue
Block a user