Liss, Alex (NYC-HUG) commited on
Commit
207499a
·
1 Parent(s): 33f621e

Remove z_utils from git tracking while preserving local files

Browse files
.gitignore CHANGED
@@ -64,5 +64,5 @@ logs/
64
  **/niners_output/schedule_with_result_embedding.csv
65
  **/niners_output/schedule_with_result_embedding.gsheet
66
 
67
- Utilility files
68
  z_utils/
 
64
  **/niners_output/schedule_with_result_embedding.csv
65
  **/niners_output/schedule_with_result_embedding.gsheet
66
 
67
+ # Utility files
68
  z_utils/
z_utils/neo4j_cleanup.py DELETED
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- Script to perform Neo4j cleanup: Remove the 'embedding' property from all :Game nodes.
4
- This is part of Task 1.3 housekeeping.
5
-
6
- Run once: python ifx-sandbox/z_utils/neo4j_cleanup.py
7
- """
8
-
9
- import os
10
- import sys
11
-
12
- # Adjust path to import graph object from the parent directory (ifx-sandbox)
13
- # Assumes script is run from the workspace root directory
14
- workspace_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
15
- ifx_sandbox_path = os.path.join(workspace_root, 'ifx-sandbox')
16
-
17
- if ifx_sandbox_path not in sys.path:
18
- print(f"Adding {ifx_sandbox_path} to sys.path")
19
- sys.path.insert(0, ifx_sandbox_path)
20
-
21
- try:
22
- # Import the configured graph instance from ifx-sandbox directory
23
- from gradio_graph import graph
24
- print("Successfully imported graph object from gradio_graph.")
25
- except ImportError as e:
26
- print(f"Error importing gradio_graph: {e}")
27
- print("Please ensure gradio_graph.py exists in the 'ifx-sandbox' directory and is configured correctly.")
28
- print("Make sure you are running this script from the workspace root directory.")
29
- sys.exit(1)
30
- except Exception as e:
31
- print(f"An unexpected error occurred during import: {e}")
32
- sys.exit(1)
33
-
34
- def cleanup_game_embeddings():
35
- """Removes the embedding property from all Game nodes in Neo4j."""
36
- print("Starting Neo4j cleanup: Removing 'embedding' property from :Game nodes...")
37
-
38
- cleanup_query = """
39
- MATCH (g:Game)
40
- WHERE g.embedding IS NOT NULL
41
- REMOVE g.embedding
42
- RETURN count(g) as removed_count
43
- """
44
-
45
- try:
46
- result = graph.query(cleanup_query)
47
-
48
- if result and isinstance(result, list) and len(result) > 0 and 'removed_count' in result[0]:
49
- count = result[0]['removed_count']
50
- print(f"Successfully removed 'embedding' property from {count} :Game node(s).")
51
- else:
52
- # Query might return empty list if no nodes matched or had the property
53
- print("Cleanup query executed. No 'embedding' properties found or removed from :Game nodes (or query result format unexpected).")
54
- print(f"Raw query result: {result}")
55
-
56
- except Exception as e:
57
- print(f"Error executing Neo4j cleanup query: {e}")
58
- print("Cleanup failed.")
59
-
60
- if __name__ == "__main__":
61
- print("Running Neo4j Game Embedding Cleanup script...")
62
- # Basic check: Does 'ifx-sandbox' exist relative to script location?
63
- if not os.path.isdir(ifx_sandbox_path):
64
- print("Error: Cannot find 'ifx-sandbox' directory.")
65
- print("Please ensure you run this script from the workspace root directory.")
66
- sys.exit(1)
67
-
68
- cleanup_game_embeddings()
69
- print("Script execution complete.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
z_utils/persona_session_ids.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "Casual Fan": "241b3478c7634492abee9f178b5341cb",
3
- "Super Fan": "dedcf5cb0d71475f976f4f66d98d6400"
4
- }
 
 
 
 
 
z_utils/persona_uuids.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "Casual Fan": "bdfc78a0-069a-48bf-af11-a843b7c6844e",
3
- "Super Fan": "2e28be0a-8e2f-4480-8caf-975f58db0bca"
4
- }
 
 
 
 
 
z_utils/restart_space.py DELETED
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env python
2
- import os
3
- import time
4
- import subprocess
5
- from huggingface_hub import HfApi
6
-
7
- # Get token from environment or from stored token
8
- def get_token():
9
- # Try to get token from cached location
10
- try:
11
- token_path = os.path.expanduser("~/.cache/huggingface/token")
12
- if os.path.exists(token_path):
13
- with open(token_path, "r") as f:
14
- return f.read().strip()
15
- except:
16
- pass
17
-
18
- # If that fails, try using the huggingface-cli to print the token
19
- try:
20
- result = subprocess.run(["huggingface-cli", "whoami", "--token"],
21
- capture_output=True, text=True, check=True)
22
- if result.stdout:
23
- return result.stdout.strip()
24
- except:
25
- pass
26
-
27
- return None
28
-
29
- # Get the token
30
- token = get_token()
31
- if not token:
32
- print("No Hugging Face token found. Please login using 'huggingface-cli login'")
33
- exit(1)
34
-
35
- # Hugging Face repo ID
36
- repo_id = "aliss77777/IFX-sandbox"
37
-
38
- # Initialize the Hugging Face API with the token
39
- api = HfApi(token=token)
40
-
41
- print(f"Restarting Space: {repo_id}")
42
-
43
- try:
44
- # Restart the Space
45
- api.restart_space(repo_id=repo_id)
46
- print(f"✓ Space restart request sent!")
47
- print(f"The Space should restart shortly. You can check its status at: https://huggingface.co/spaces/{repo_id}")
48
- except Exception as e:
49
- print(f"Error restarting Space: {str(e)}")
50
- exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
z_utils/set_secrets.py DELETED
@@ -1,77 +0,0 @@
1
- #!/usr/bin/env python
2
- import os
3
- import subprocess
4
- from dotenv import load_dotenv
5
- from huggingface_hub import HfApi
6
-
7
- # Load environment variables from .env file
8
- load_dotenv()
9
-
10
- # Get Neo4j credentials
11
- AURA_CONNECTION_URI = os.environ.get("AURA_CONNECTION_URI")
12
- AURA_USERNAME = os.environ.get("AURA_USERNAME")
13
- AURA_PASSWORD = os.environ.get("AURA_PASSWORD")
14
-
15
- # Get OpenAI credentials
16
- OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
17
- OPENAI_MODEL = os.environ.get("OPENAI_MODEL")
18
-
19
- # Get token from environment or from stored token
20
- def get_token():
21
- # Try to get token from cached location
22
- try:
23
- token_path = os.path.expanduser("~/.cache/huggingface/token")
24
- if os.path.exists(token_path):
25
- with open(token_path, "r") as f:
26
- return f.read().strip()
27
- except:
28
- pass
29
-
30
- # If that fails, try using the huggingface-cli to print the token
31
- try:
32
- result = subprocess.run(["huggingface-cli", "whoami", "--token"],
33
- capture_output=True, text=True, check=True)
34
- if result.stdout:
35
- return result.stdout.strip()
36
- except:
37
- pass
38
-
39
- return None
40
-
41
- # Get the token
42
- token = get_token()
43
- if not token:
44
- print("No Hugging Face token found. Please login using 'huggingface-cli login'")
45
- exit(1)
46
-
47
- # Hugging Face repo ID
48
- repo_id = "aliss77777/IFX-sandbox"
49
-
50
- # Initialize the Hugging Face API with the token
51
- api = HfApi(token=token)
52
-
53
- print("Setting secrets for", repo_id)
54
-
55
- # Set each secret
56
- try:
57
- # Set Neo4j credentials
58
- api.add_space_secret(repo_id=repo_id, key="AURA_CONNECTION_URI", value=AURA_CONNECTION_URI)
59
- print("✓ Set AURA_CONNECTION_URI")
60
-
61
- api.add_space_secret(repo_id=repo_id, key="AURA_USERNAME", value=AURA_USERNAME)
62
- print("✓ Set AURA_USERNAME")
63
-
64
- api.add_space_secret(repo_id=repo_id, key="AURA_PASSWORD", value=AURA_PASSWORD)
65
- print("✓ Set AURA_PASSWORD")
66
-
67
- # Set OpenAI credentials
68
- api.add_space_secret(repo_id=repo_id, key="OPENAI_API_KEY", value=OPENAI_API_KEY)
69
- print("✓ Set OPENAI_API_KEY")
70
-
71
- api.add_space_secret(repo_id=repo_id, key="OPENAI_MODEL", value=OPENAI_MODEL)
72
- print("✓ Set OPENAI_MODEL")
73
-
74
- print("\nAll secrets set successfully!")
75
- except Exception as e:
76
- print(f"Error setting secrets: {str(e)}")
77
- exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
z_utils/zep_setup.py DELETED
@@ -1,445 +0,0 @@
1
- # file: z_utils/zep_setup.py
2
- """
3
- Create two persona users in Zep Cloud and preload their memory graphs.
4
- Run once: python z_utils/zep_setup.py
5
- """
6
-
7
- import asyncio, os, uuid, json
8
- from datetime import datetime, timezone
9
- from dotenv import load_dotenv
10
- from pathlib import Path
11
- from zep_cloud.client import AsyncZep
12
- from zep_cloud.errors import NotFoundError
13
- from zep_cloud.types import User, Message
14
-
15
- # Define the path for the UUIDs file relative to this script
16
- UUID_FILE_PATH = Path(__file__).parent / "persona_uuids.json"
17
- SESSION_ID_FILE_PATH = Path(__file__).parent / "persona_session_ids.json"
18
-
19
- # Load environment variables from .env file
20
- load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), '..', '.env')) # Look for .env in parent dir
21
- API_KEY = os.getenv("ZEP_API_KEY")
22
- BASE_URL = os.getenv("ZEP_API_URL") # optional for self-hosted
23
-
24
- if not API_KEY:
25
- raise RuntimeError("ZEP_API_KEY missing in environment variables. Please ensure it's in ifx-sandbox/.env")
26
-
27
- # Initialize AsyncZep client, handling optional base_url
28
- zep_client_args = {"api_key": API_KEY}
29
- if BASE_URL:
30
- zep_client_args["base_url"] = BASE_URL
31
- zep = AsyncZep(**zep_client_args)
32
-
33
- # -------- persona blue-prints -------------------------------------------------
34
- # Removed FactRatingExamples definition as it's not part of the SDK
35
- # FACT_EXAMPLES = FactRatingExamples(
36
- # high="Brock Purdy led the 49ers to the Super Bowl in 2024.",
37
- # medium="The 49ers play in the NFC West.",
38
- # low="Football games are played on a field."
39
- # )
40
-
41
- PERSONAS = {
42
- "Casual Fan": {
43
- "user_id": None, # Will be generated or loaded
44
- "session_id": None, # Will be generated or loaded
45
- "email": "[email protected]",
46
- "first_name": "Casual",
47
- "last_name": "Fan",
48
- "metadata": {"fan_type": "casual"}
49
- },
50
- "Super Fan": {
51
- "user_id": None, # Will be generated or loaded
52
- "session_id": None, # Will be generated or loaded
53
- "email": "[email protected]",
54
- "first_name": "Super",
55
- "last_name": "Fan",
56
- "metadata": {"fan_type": "super"}
57
- }
58
- }
59
-
60
- # --- Message histories for each persona based on their knowledge ---
61
-
62
- CASUAL_FAN_MESSAGES = [
63
- {"role": "user", "content": "Who are the 49ers?"},
64
- {"role": "assistant", "content": "The San Francisco 49ers are a professional football team in the NFL. They play at Levi's Stadium in Santa Clara."},
65
- {"role": "user", "content": "Who is their quarterback?"},
66
- {"role": "assistant", "content": "Brock Purdy is the current starting quarterback for the 49ers. He emerged as the starter after being the final pick in the 2022 NFL Draft, often called 'Mr. Irrelevant.'"},
67
- {"role": "user", "content": "Who are their best players?"},
68
- {"role": "assistant", "content": "The 49ers have several star players! Christian McCaffrey (often called CMC) is their key running back and an offensive weapon. George Kittle is their star tight end known for his catching and blocking abilities. On defense, Nick Bosa is a dominant defensive end who frequently pressures quarterbacks."},
69
- {"role": "user", "content": "Did they do well last season?"},
70
- {"role": "assistant", "content": "Yes! The 49ers have been very competitive recently, making several playoff runs. They've established themselves as one of the stronger teams in the NFC."},
71
- {"role": "user", "content": "What was their most exciting game?"},
72
- {"role": "assistant", "content": "While there have been several exciting games, casual fans often remember the big moments - like playoff victories and games with spectacular, highlight-reel plays. The 49ers have had many memorable comeback wins and offensive explosions that got fans on their feet!"}
73
- ]
74
-
75
- SUPER_FAN_MESSAGES = [
76
- {"role": "user", "content": "Explain the 49ers' offensive scheme"},
77
- {"role": "assistant", "content": "The 49ers primarily run Kyle Shanahan's offensive scheme, which heavily features the outside zone run, play-action passing, and pre-snap motion. This system relies on precise timing, versatile players who can both block and catch, and a strong offensive line. Trent Williams, their All-Pro left tackle, is particularly crucial for their run game success, creating lanes for their zone running attack."},
78
- {"role": "user", "content": "What defensive system do they use?"},
79
- {"role": "assistant", "content": "Under their defensive coordinator, the 49ers utilize a scheme that emphasizes pressure from their front four, led by Nick Bosa, without excessive blitzing. This allows them to drop seven defenders into coverage while still disrupting the quarterback. Fred Warner is the key middle linebacker who orchestrates the defense, handling both run stops and pass coverage responsibilities."},
80
- {"role": "user", "content": "What's happening with their salary cap situation?"},
81
- {"role": "assistant", "content": "The 49ers' salary cap management is a constant challenge. Currently, they're navigating extensions for key players like Brandon Aiyuk while planning for Brock Purdy's future contract when he becomes eligible for an extension. They've become adept at structuring contracts to maintain their core while finding value in mid-round draft picks and undrafted free agents who fit their systems perfectly."},
82
- {"role": "user", "content": "What's their draft strategy been like?"},
83
- {"role": "assistant", "content": "Their draft strategy often focuses on finding scheme fits rather than just raw talent or conventional wisdom. They prioritize specific traits that work in their systems and aren't afraid to draft players earlier than consensus would suggest if they believe in the fit. They've been particularly good at replenishing depth on both lines and finding mid-round receivers who thrive in Shanahan's offense."},
84
- {"role": "user", "content": "Tell me about some of their role players beyond the stars"},
85
- {"role": "assistant", "content": "Beyond the stars, the 49ers get significant contributions from role players like their nickel cornerback, rotational defensive linemen who keep the pass rush fresh, and versatile offensive weapons. Players like Jauan Jennings (clutch third-down receiver), Tashaun Gipson (veteran safety presence), and Elijah Mitchell (change-of-pace running back) may not make headlines but are crucial to the team's success and highly valued by die-hard fans who understand their specific contributions."},
86
- {"role": "user", "content": "How does their current team compare historically?"},
87
- {"role": "assistant", "content": "The current 49ers team continues their tradition of innovative coaching and physical play that dates back to their dynasty years. While they haven't yet matched the Super Bowl success of the teams led by Joe Montana, Jerry Rice, and Steve Young, they've returned to being perennial contenders. The current team emphasizes a strong run game and defense, similar to their historical identity, though the specific schemes have evolved with the modern NFL."}
88
- ]
89
-
90
- CASUAL_FAN_KNOWLEDGE = [
91
- {
92
- "type": "text",
93
- "data": """
94
- General knowledge about the San Francisco 49ers for a casual fan.
95
- Focuses on major stars and recent performance.
96
- - The 49ers play at Levi's Stadium in Santa Clara.
97
- - Brock Purdy is the current starting quarterback.
98
- - Christian McCaffrey (CMC) is a key running back and offensive weapon.
99
- - George Kittle is a star tight end.
100
- - Nick Bosa is a dominant defensive end.
101
- - The team has been competitive recently, often making playoff runs.
102
- - Big plays and game outcomes are the main interest.
103
- """
104
- }
105
- ]
106
-
107
- SUPER_FAN_KNOWLEDGE = [
108
- {
109
- "type": "text",
110
- "data": """
111
- Detailed knowledge base for a San Francisco 49ers super fan.
112
- Includes strategic insights, player roles, and historical context.
113
- - The 49ers primarily run a Kyle Shanahan offensive scheme, heavily featuring the outside zone run, play-action passing, and pre-snap motion.
114
- - Key offensive line players are crucial for the run game's success (e.g., Trent Williams).
115
- - Defensive scheme under Steve Wilks (or current DC) utilizes a strong front four, led by Nick Bosa, aiming for pressure without excessive blitzing.
116
- - Fred Warner is the crucial middle linebacker, orchestrating the defense.
117
- - Salary cap management is a constant discussion point, especially regarding extensions for players like Brandon Aiyuk or Brock Purdy's future contract.
118
- - Draft strategy often focuses on finding scheme fits and replenishing depth.
119
- - Understanding specific player roles beyond stars (e.g., slot corner, rotational defensive linemen) is important.
120
- - Historical context, like past Super Bowl appearances or legendary players (Montana, Rice, Young), is frequently referenced.
121
- """
122
- },
123
- {
124
- "type": "json",
125
- "data": json.dumps({
126
- "team_focus": "49ers Strategy and Depth",
127
- "key_concepts": [
128
- "Shanahan Offense",
129
- "Outside Zone Scheme",
130
- "Defensive Line Pressure",
131
- "Salary Cap Implications",
132
- "Draft Capital Management",
133
- "Player Contract Negotiations"
134
- ],
135
- "recent_topics": [
136
- "Brandon Aiyuk contract situation",
137
- "Ricky Pearsall draft pick impact",
138
- "Defensive coordinator adjustments",
139
- "Offensive line performance analysis"
140
- ]
141
- })
142
- }
143
- ]
144
-
145
- PERSONA_KNOWLEDGE_MAP = {
146
- "Casual Fan": CASUAL_FAN_KNOWLEDGE,
147
- "Super Fan": SUPER_FAN_KNOWLEDGE,
148
- }
149
-
150
- # Add mapping for persona message histories
151
- PERSONA_MESSAGES_MAP = {
152
- "Casual Fan": CASUAL_FAN_MESSAGES,
153
- "Super Fan": SUPER_FAN_MESSAGES,
154
- }
155
-
156
- def load_or_generate_uuids():
157
- """Loads existing UUIDs from file or generates new ones if file doesn't exist."""
158
- uuids_changed = False
159
- if UUID_FILE_PATH.exists():
160
- try:
161
- with open(UUID_FILE_PATH, 'r') as f:
162
- saved_uuids = json.load(f)
163
- # Check if saved_uuids is a dict mapping names to strings
164
- if isinstance(saved_uuids, dict):
165
- for name in PERSONAS:
166
- if name in saved_uuids and isinstance(saved_uuids[name], str):
167
- PERSONAS[name]["user_id"] = saved_uuids[name]
168
- print(f"Loaded existing UUID for {name}: {saved_uuids[name]}")
169
- else:
170
- # Generate new if name missing, value isn't string, or empty
171
- PERSONAS[name]["user_id"] = str(uuid.uuid4())
172
- print(f"UUID for {name} not found or invalid in file, generated new: {PERSONAS[name]['user_id']}")
173
- uuids_changed = True
174
- else:
175
- # Invalid format, generate all new
176
- print(f"UUID file ({UUID_FILE_PATH}) has unexpected format. Generating new UUIDs.")
177
- for name in PERSONAS:
178
- PERSONAS[name]["user_id"] = str(uuid.uuid4())
179
- print(f"Generated new UUID for {name}: {PERSONAS[name]['user_id']}")
180
- uuids_changed = True
181
-
182
- except (json.JSONDecodeError, IOError) as e:
183
- print(f"Error loading UUID file ({UUID_FILE_PATH}): {e}. Generating new UUIDs.")
184
- for name in PERSONAS:
185
- PERSONAS[name]["user_id"] = str(uuid.uuid4())
186
- print(f"Generated new UUID for {name}: {PERSONAS[name]['user_id']}")
187
- uuids_changed = True
188
- else:
189
- # File doesn't exist, generate all new UUIDs
190
- print(f"UUID file ({UUID_FILE_PATH}) not found. Generating new UUIDs.")
191
- for name in PERSONAS:
192
- PERSONAS[name]["user_id"] = str(uuid.uuid4())
193
- print(f"Generated new UUID for {name}: {PERSONAS[name]['user_id']}")
194
- uuids_changed = True
195
-
196
- if uuids_changed:
197
- save_persona_uuids() # Save if any UUIDs were generated or changed
198
-
199
-
200
- def load_or_generate_session_ids():
201
- """Loads existing session IDs from file or generates new ones if file doesn't exist."""
202
- session_ids_changed = False
203
-
204
- # Use the specific session IDs from the task document for these personas
205
- hardcoded_session_ids = {
206
- "Casual Fan": "241b3478c7634492abee9f178b5341cb",
207
- "Super Fan": "dedcf5cb0d71475f976f4f66d98d6400"
208
- }
209
-
210
- if SESSION_ID_FILE_PATH.exists():
211
- try:
212
- with open(SESSION_ID_FILE_PATH, 'r') as f:
213
- saved_session_ids = json.load(f)
214
- # Check if saved_session_ids is a dict mapping names to strings
215
- if isinstance(saved_session_ids, dict):
216
- for name in PERSONAS:
217
- # Use hardcoded session IDs regardless of what's in the file
218
- PERSONAS[name]["session_id"] = hardcoded_session_ids[name]
219
- print(f"Using required session ID for {name}: {PERSONAS[name]['session_id']}")
220
-
221
- # If the saved value differs from hardcoded, we'll need to update the file
222
- if name not in saved_session_ids or saved_session_ids[name] != hardcoded_session_ids[name]:
223
- session_ids_changed = True
224
- else:
225
- # Invalid format, use hardcoded IDs
226
- print(f"Session ID file ({SESSION_ID_FILE_PATH}) has unexpected format. Using required session IDs.")
227
- for name in PERSONAS:
228
- PERSONAS[name]["session_id"] = hardcoded_session_ids[name]
229
- print(f"Using required session ID for {name}: {PERSONAS[name]['session_id']}")
230
- session_ids_changed = True
231
- except (json.JSONDecodeError, IOError) as e:
232
- print(f"Error loading session ID file ({SESSION_ID_FILE_PATH}): {e}. Using required session IDs.")
233
- for name in PERSONAS:
234
- PERSONAS[name]["session_id"] = hardcoded_session_ids[name]
235
- print(f"Using required session ID for {name}: {PERSONAS[name]['session_id']}")
236
- session_ids_changed = True
237
- else:
238
- # File doesn't exist, use hardcoded IDs
239
- print(f"Session ID file ({SESSION_ID_FILE_PATH}) not found. Using required session IDs.")
240
- for name in PERSONAS:
241
- PERSONAS[name]["session_id"] = hardcoded_session_ids[name]
242
- print(f"Using required session ID for {name}: {PERSONAS[name]['session_id']}")
243
- session_ids_changed = True
244
-
245
- if session_ids_changed:
246
- save_persona_session_ids() # Save if any session IDs were updated
247
-
248
-
249
- def save_persona_uuids():
250
- """Saves the current persona UUIDs (name -> user_id string) to the JSON file."""
251
- # Ensure we only save the user_id string
252
- uuids_to_save = {name: data["user_id"] for name, data in PERSONAS.items() if isinstance(data.get("user_id"), str)}
253
- if len(uuids_to_save) != len(PERSONAS):
254
- print("Warning: Not all personas had valid string UUIDs during save.")
255
- # Potentially raise an error or handle more robustly
256
-
257
- try:
258
- with open(UUID_FILE_PATH, 'w') as f:
259
- json.dump(uuids_to_save, f, indent=4)
260
- print(f"Persona UUIDs saved to {UUID_FILE_PATH}")
261
- except IOError as e:
262
- print(f"Error saving UUIDs to {UUID_FILE_PATH}: {e}")
263
-
264
-
265
- def save_persona_session_ids():
266
- """Saves the current persona session IDs (name -> session_id string) to the JSON file."""
267
- # Ensure we only save the session_id string
268
- session_ids_to_save = {name: data["session_id"] for name, data in PERSONAS.items() if isinstance(data.get("session_id"), str)}
269
- if len(session_ids_to_save) != len(PERSONAS):
270
- print("Warning: Not all personas had valid string session IDs during save.")
271
- # Potentially raise an error or handle more robustly
272
-
273
- try:
274
- with open(SESSION_ID_FILE_PATH, 'w') as f:
275
- json.dump(session_ids_to_save, f, indent=4)
276
- print(f"Persona session IDs saved to {SESSION_ID_FILE_PATH}")
277
- except IOError as e:
278
- print(f"Error saving session IDs to {SESSION_ID_FILE_PATH}: {e}")
279
-
280
-
281
- async def create_zep_user(client: AsyncZep, user_data: dict):
282
- """Creates or updates a Zep user, checking if they exist first."""
283
- user_id = user_data["user_id"]
284
- try:
285
- # Check if user exists
286
- await client.user.get(user_id)
287
- print(f"User {user_id} ({user_data.get('first_name', '')}) already exists. Updating...")
288
- # Update existing user (optional, could just skip)
289
- await client.user.update(
290
- user_id=user_id,
291
- email=user_data.get("email"),
292
- first_name=user_data.get("first_name"),
293
- last_name=user_data.get("last_name"),
294
- metadata=user_data.get("metadata")
295
- )
296
- print(f"User {user_id} updated.")
297
- except NotFoundError:
298
- # User does not exist, create them
299
- print(f"User {user_id} ({user_data.get('first_name', '')}) not found. Creating...")
300
- try:
301
- await client.user.add(**user_data)
302
- print(f"User {user_id} created successfully.")
303
- except Exception as e:
304
- print(f"Error creating user {user_id}: {e}")
305
- except Exception as e:
306
- print(f"Error checking or updating user {user_id}: {e}")
307
-
308
-
309
- async def preload_knowledge(client: AsyncZep, user_id: str, knowledge_items: list):
310
- """Preloads foundational knowledge into the user's graph using graph.add."""
311
- print(f"Preloading knowledge for user {user_id}...")
312
- success_count = 0
313
- for i, item in enumerate(knowledge_items):
314
- try:
315
- print(f" Adding knowledge item {i+1}/{len(knowledge_items)} (type: {item['type']})...")
316
- await client.graph.add(
317
- user_id=user_id,
318
- type=item["type"],
319
- data=item["data"] # Expects string data, JSON already dumped
320
- )
321
- success_count += 1
322
- print(f" Item {i+1} added successfully.")
323
- # Add a small delay to avoid overwhelming the API if adding many items
324
- await asyncio.sleep(0.5)
325
- except Exception as e:
326
- print(f" Error adding knowledge item {i+1} for user {user_id}: {e}")
327
- # Decide whether to continue or stop on error
328
- # break # Uncomment to stop on first error
329
- print(f"Knowledge preloading completed for user {user_id}. {success_count}/{len(knowledge_items)} items added.")
330
-
331
-
332
- async def preload_message_history(client: AsyncZep, user_id: str, session_id: str, messages: list):
333
- """Preloads message history for a user in a specific session."""
334
- print(f"Preloading message history for user {user_id} in session {session_id}...")
335
-
336
- try:
337
- # First, ensure the session exists or create it
338
- try:
339
- # Try to get the session to see if it exists
340
- await client.memory.get_session(session_id=session_id)
341
- print(f"Session {session_id} already exists.")
342
- except NotFoundError:
343
- # Session does not exist, create it
344
- await client.memory.add_session(
345
- session_id=session_id,
346
- user_id=user_id
347
- )
348
- print(f"Created new session {session_id} for user {user_id}")
349
-
350
- # Then add messages to the session
351
- zep_messages = []
352
- for msg in messages:
353
- # Map 'role' field to proper Zep role_type
354
- role_type = msg["role"]
355
- # If role is 'user', set role_type to 'user'
356
- # If role is 'assistant', keep role_type as 'assistant'
357
-
358
- zep_messages.append(
359
- Message(
360
- role_type=role_type, # Use the role directly as role_type
361
- content=msg["content"],
362
- role=None # Using default role
363
- )
364
- )
365
-
366
- # Add the messages to the session
367
- await client.memory.add(
368
- session_id=session_id,
369
- messages=zep_messages
370
- )
371
- print(f"Added {len(zep_messages)} messages to session {session_id}")
372
-
373
- except Exception as e:
374
- print(f"Error preloading message history: {e}")
375
-
376
-
377
- async def main():
378
- """Main function to set up Zep users and preload knowledge."""
379
- print("Starting Zep setup...")
380
- load_dotenv()
381
-
382
- api_key = os.environ.get("ZEP_API_KEY")
383
- api_url = os.environ.get("ZEP_API_URL") # Optional
384
-
385
- if not api_key:
386
- print("Error: ZEP_API_KEY environment variable not set.")
387
- return
388
-
389
- client_params = {"api_key": api_key}
390
- if api_url:
391
- client_params["api_url"] = api_url
392
-
393
- client = None # Initialize client variable
394
- try:
395
- # Instantiate client directly, remove async with
396
- client = AsyncZep(**client_params)
397
- print("Zep client initialized.")
398
-
399
- # Load or generate UUIDs and update PERSONAS dict
400
- load_or_generate_uuids()
401
-
402
- # Load or use hardcoded session IDs from the task document
403
- load_or_generate_session_ids()
404
-
405
- # Create/Update users
406
- for persona_name, data in PERSONAS.items():
407
- await create_zep_user(client, data)
408
-
409
- # Preload knowledge for each persona
410
- for persona_name, data in PERSONAS.items():
411
- user_id = data["user_id"]
412
- knowledge = PERSONA_KNOWLEDGE_MAP.get(persona_name, [])
413
- if knowledge:
414
- await preload_knowledge(client, user_id, knowledge)
415
- else:
416
- print(f"No knowledge defined for persona: {persona_name}")
417
-
418
- # Preload message history for each persona
419
- for persona_name, data in PERSONAS.items():
420
- user_id = data["user_id"]
421
- session_id = data["session_id"]
422
- messages = PERSONA_MESSAGES_MAP.get(persona_name, [])
423
- if messages:
424
- await preload_message_history(client, user_id, session_id, messages)
425
- else:
426
- print(f"No message history defined for persona: {persona_name}")
427
-
428
- except Exception as e:
429
- print(f"An error occurred during Zep client initialization or operation: {e}")
430
- # finally:
431
- # Optional: Add any explicit cleanup if the client required it,
432
- # but typically SDK clients manage their own connections.
433
- # if client and hasattr(client, 'close') and asyncio.iscoroutinefunction(client.close):
434
- # await client.close()
435
- # print("Zep client closed.")
436
-
437
- print("Zep setup finished.")
438
-
439
-
440
- if __name__ == "__main__":
441
- # Ensure the script runs in an environment where asyncio is available
442
- # If running in a Jupyter notebook, you might need nest_asyncio
443
- # import nest_asyncio
444
- # nest_asyncio.apply()
445
- asyncio.run(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
z_utils/zep_test.py DELETED
@@ -1,97 +0,0 @@
1
- """
2
- Simple Zep test script to retrieve chat history from a pre-defined session.
3
- This follows step 2 of Task 1.3 Memory & Persona Implementation.
4
- """
5
- import os
6
- import json
7
- import argparse
8
- from dotenv import load_dotenv
9
- from zep_cloud.client import Zep
10
- from langchain_core.messages import HumanMessage, AIMessage
11
-
12
- # Load environment variables from .env file
13
- load_dotenv()
14
-
15
- # Get Zep API key
16
- ZEP_API_KEY = os.environ.get("ZEP_API_KEY")
17
- if not ZEP_API_KEY:
18
- raise RuntimeError("ZEP_API_KEY missing in environment variables.")
19
-
20
- # Initialize Zep client
21
- zep = Zep(api_key=ZEP_API_KEY)
22
-
23
- def retrieve_chat_history(session_id):
24
- """
25
- Retrieve chat history for a specific session from Zep.
26
-
27
- Args:
28
- session_id (str): The session ID to retrieve history for
29
-
30
- Returns:
31
- dict: The memory object containing context and messages
32
- """
33
- try:
34
- # Use Zep's memory.get API to retrieve chat history
35
- memory = zep.memory.get(session_id=session_id)
36
- return memory
37
- except Exception as e:
38
- print(f"Error retrieving chat history: {e}")
39
- return None
40
-
41
- def get_zep_history(session_id):
42
- """
43
- Retrieve chat history directly from Zep using the client.
44
-
45
- Args:
46
- session_id (str): The session ID to retrieve history for
47
-
48
- Returns:
49
- list: Formatted messages for LangChain
50
- """
51
- try:
52
- zep = Zep(api_key=os.environ.get("ZEP_API_KEY"))
53
- memory = zep.memory.get(session_id=session_id)
54
-
55
- # Convert Zep messages to LangChain format
56
- formatted_messages = []
57
- if memory and memory.messages:
58
- for msg in memory.messages:
59
- if msg.role_type == "user":
60
- formatted_messages.append(HumanMessage(content=msg.content))
61
- elif msg.role_type == "assistant":
62
- formatted_messages.append(AIMessage(content=msg.content))
63
-
64
- return formatted_messages
65
- except Exception as e:
66
- print(f"Error retrieving Zep history: {e}")
67
- return []
68
-
69
- def main():
70
- # Set up command line argument parsing
71
- parser = argparse.ArgumentParser(description='Retrieve chat history from Zep')
72
- parser.add_argument('--session_id', type=str,
73
- default="241b3478c7634492abee9f178b5341cb",
74
- help='Session ID to retrieve (default: Casual Fan)')
75
- args = parser.parse_args()
76
-
77
- session_id = args.session_id
78
-
79
- print(f"Retrieving chat history for session ID: {session_id}")
80
-
81
- # Get the memory for the session
82
- memory = retrieve_chat_history(session_id)
83
-
84
- if memory:
85
- print("\n===== MEMORY CONTEXT =====")
86
- print(memory.context)
87
-
88
- print("\n===== CHAT MESSAGES =====")
89
- for msg in memory.messages:
90
- print(f"{msg.role_type} ({msg.role}): {msg.content}")
91
-
92
- print("\nSuccessfully retrieved chat history!")
93
- else:
94
- print("Failed to retrieve chat history.")
95
-
96
- if __name__ == "__main__":
97
- main()