Skip to content

Commit 4a468b3

Browse files
authored
Merge pull request #104 from Dooders/dev
Dev
2 parents d048e32 + 0d29d80 commit 4a468b3

File tree

4 files changed

+165
-8
lines changed

4 files changed

+165
-8
lines changed

memory/search/strategies/sequence.py

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,25 @@ def search(
115115
# Get all memories for filtering
116116
all_memories = store.get_all(agent_id)
117117

118+
# Get reference memory type from content metadata
119+
reference_type = None
120+
if isinstance(reference_memory.get("content"), dict):
121+
reference_type = reference_memory.get("content", {}).get("metadata", {}).get("type")
122+
else:
123+
# If content is a string, check metadata directly
124+
reference_type = reference_memory.get("metadata", {}).get("type")
125+
126+
# Filter memories by type if reference type exists
127+
if reference_type:
128+
all_memories = [
129+
memory
130+
for memory in all_memories
131+
if (isinstance(memory.get("content"), dict) and
132+
memory.get("content", {}).get("metadata", {}).get("type") == reference_type) or
133+
(not isinstance(memory.get("content"), dict) and
134+
memory.get("metadata", {}).get("type") == reference_type)
135+
]
136+
118137
# Sort memories by timestamp
119138
sorted_memories = self._sort_memories_by_timestamp(
120139
all_memories, timestamp_field
@@ -146,24 +165,36 @@ def search(
146165

147166
# Convert timestamp to datetime
148167
if isinstance(reference_timestamp, str):
149-
reference_dt = datetime.fromisoformat(reference_timestamp)
168+
try:
169+
reference_dt = datetime.fromisoformat(reference_timestamp)
170+
except ValueError:
171+
reference_dt = datetime.fromtimestamp(float(reference_timestamp))
150172
else:
151173
reference_dt = datetime.fromtimestamp(float(reference_timestamp))
152-
window_start = reference_dt - timedelta(minutes=time_window_minutes)
153-
window_end = reference_dt + timedelta(minutes=time_window_minutes)
174+
175+
# Convert window to seconds for Unix timestamp comparison
176+
window_seconds = time_window_minutes * 60
177+
window_start_ts = reference_dt.timestamp() - window_seconds
178+
window_end_ts = reference_dt.timestamp() + window_seconds
154179

155180
results = []
156181
for memory in sorted_memories:
157182
memory_timestamp = self._get_timestamp_value(memory, timestamp_field)
158183
if memory_timestamp is None:
159184
continue
160185

161-
# Convert memory timestamp to datetime
186+
# Convert memory timestamp to float for comparison
162187
if isinstance(memory_timestamp, str):
163-
memory_dt = datetime.fromisoformat(memory_timestamp)
188+
try:
189+
memory_dt = datetime.fromisoformat(memory_timestamp)
190+
memory_ts = memory_dt.timestamp()
191+
except ValueError:
192+
memory_ts = float(memory_timestamp)
164193
else:
165-
memory_dt = datetime.fromtimestamp(float(memory_timestamp))
166-
if window_start <= memory_dt <= window_end:
194+
memory_ts = float(memory_timestamp)
195+
196+
# Compare timestamps
197+
if window_start_ts <= memory_ts <= window_end_ts:
167198
# Mark the reference memory
168199
memory_id = memory.get("memory_id") or memory.get("id")
169200
if memory_id == reference_id:
@@ -277,3 +308,15 @@ def _matches_metadata_filter(self, memory, metadata_filter):
277308
return False
278309

279310
return True
311+
312+
def _extract_memory_id(self, memory: Dict[str, Any]) -> str:
313+
"""
314+
Extract memory ID from a memory object.
315+
316+
Args:
317+
memory: Memory object to extract ID from
318+
319+
Returns:
320+
Memory ID as string
321+
"""
322+
return memory.get("memory_id") or memory.get("id")

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ matplotlib
3030
numpy
3131
tiktoken
3232
openai
33+
openai-agents
34+
openai-voice
3335

3436
# Additional needed dependencies
3537
redis[hiredis]

scripts/agent_conversation.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import os
2+
from agents import Agent, Runner
3+
import asyncio
4+
from dotenv import load_dotenv
5+
import time
6+
from openai import OpenAI
7+
import tempfile
8+
import sounddevice as sd
9+
import soundfile as sf
10+
# Load environment variables
11+
load_dotenv()
12+
13+
# Initialize OpenAI client
14+
client = OpenAI()
15+
16+
# Ensure OpenAI API key is set
17+
if not os.getenv("OPENAI_API_KEY"):
18+
raise ValueError("Please set OPENAI_API_KEY environment variable")
19+
20+
# Create two agents with different roles
21+
lincoln = Agent(
22+
name="Abraham Lincoln",
23+
instructions="""You are Abraham Lincoln, speaking privately with Nero.""",
24+
model="gpt-3.5-turbo"
25+
)
26+
27+
nero = Agent(
28+
name="Emperor Nero",
29+
instructions="""You are Emperor Nero, speaking privately with Abraham Lincoln.""",
30+
model="gpt-3.5-turbo"
31+
)
32+
33+
async def text_to_speech(text, voice="alloy"):
34+
"""Convert text to speech using OpenAI's TTS API"""
35+
try:
36+
response = client.audio.speech.create(
37+
model="tts-1",
38+
voice=voice,
39+
input=text
40+
)
41+
42+
# Save to temporary file
43+
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp3') as temp_file:
44+
temp_file.write(response.content)
45+
temp_file_path = temp_file.name
46+
47+
# Play the audio
48+
data, samplerate = sf.read(temp_file_path)
49+
sd.play(data, samplerate)
50+
sd.wait() # Wait until audio is finished playing
51+
52+
# Clean up
53+
os.unlink(temp_file_path)
54+
55+
except Exception as e:
56+
print(f"Error in text-to-speech: {str(e)}")
57+
58+
async def run_conversation():
59+
# Initial message to start the conversation
60+
initial_message = "You know, Nero, I've been thinking... The weight of leadership, it changes a man. I lost my son Willie last year, and sometimes I wonder if the price of this office is too high. Do you ever feel that way? That the crown, or in my case, the presidency, comes at a cost to your soul?"
61+
62+
# Set up the conversation loop
63+
current_message = initial_message
64+
turn_count = 0
65+
max_turns = 2 # Reduced number of turns for faster execution
66+
max_retries = 2 # Reduced retries
67+
68+
print("\n=== A Private Conversation Between Leaders ===\n")
69+
print("Lincoln and Nero share a moment of quiet reflection.")
70+
print("Press Ctrl+C at any time to end the conversation.\n")
71+
72+
# Speak the initial message
73+
await text_to_speech(initial_message, voice="alloy")
74+
75+
while turn_count < max_turns * 2: # Each agent gets max_turns
76+
# Determine which agent's turn it is
77+
current_agent = lincoln if turn_count % 2 == 0 else nero
78+
79+
# Get the agent's response with retry logic
80+
for attempt in range(max_retries):
81+
try:
82+
result = await Runner.run(current_agent, current_message)
83+
response = result.final_output
84+
break
85+
except Exception as e:
86+
if attempt == max_retries - 1: # Last attempt
87+
print(f"\nError: Failed to get response after {max_retries} attempts.")
88+
print(f"Error details: {str(e)}")
89+
return
90+
print(f"\nAttempt {attempt + 1} failed, retrying in 1 second...")
91+
await asyncio.sleep(1) # Reduced sleep time
92+
93+
# Print and speak the response
94+
print(f"\n{current_agent.name}: {response}\n")
95+
print("-" * 50)
96+
97+
# Speak the response with different voices for each agent
98+
await text_to_speech(response, voice="alloy" if current_agent.name == "Abraham Lincoln" else "echo")
99+
100+
# Update the message for the next turn
101+
current_message = response
102+
turn_count += 1
103+
104+
if __name__ == "__main__":
105+
try:
106+
# Run the conversation
107+
asyncio.run(run_conversation())
108+
except KeyboardInterrupt:
109+
print("\n\nConversation interrupted by user.")
110+
except Exception as e:
111+
print(f"\nAn unexpected error occurred: {str(e)}")

validation/search/sequence/sequence_test_suite.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def run_advanced_tests(self) -> None:
111111
"Time Window Sequence",
112112
{
113113
"reference_id": "test-agent-sequence-search-meeting-123456-3",
114-
"time_window_minutes": 30,
114+
"time_window_minutes": 1440, # 24 hours
115115
},
116116
expected_memory_ids=[
117117
"test-agent-sequence-search-meeting-123456-2",
@@ -127,6 +127,7 @@ def run_advanced_tests(self) -> None:
127127
{
128128
"reference_id": "test-agent-sequence-search-meeting-123456-3",
129129
"tier": "stm",
130+
"sequence_size": 3,
130131
},
131132
expected_memory_ids=[
132133
"test-agent-sequence-search-meeting-123456-2",

0 commit comments

Comments
 (0)