Pepguy commited on
Commit
9572d83
Β·
verified Β·
1 Parent(s): 0a95457

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -53
app.py CHANGED
@@ -3,7 +3,6 @@
3
 
4
  import os
5
  import time
6
- import threading
7
  import requests
8
  from flask import Flask, request, render_template_string, jsonify
9
  from google import genai
@@ -16,32 +15,11 @@ LAMBDA_URL = os.getenv("LAMBDA_URL", "https://your-lambda-function-url")
16
  GEMINI_KEY = os.getenv("GEMINI_API_KEY", "")
17
  FLUSH_INTERVAL = 30 # seconds between DB backups per user
18
  MAX_HISTORY_TURNS = 10 # Maximum conversation turns to keep in context
 
 
19
 
20
  client = genai.Client(api_key=GEMINI_KEY)
21
- user_memory = {} # { user_id: { "history": [], "last_sync": timestamp } }
22
-
23
- # --- Background thread for periodic flush ---
24
- def flush_loop():
25
- while True:
26
- time.sleep(5)
27
- now = time.time()
28
- for uid, data in list(user_memory.items()):
29
- if now - data.get("last_sync", 0) >= FLUSH_INTERVAL and data["history"]:
30
- try:
31
- # Only sync the most recent MAX_HISTORY_TURNS entries
32
- history_to_sync = data["history"][-MAX_HISTORY_TURNS:]
33
- payload = {"user_id": uid, "history": history_to_sync}
34
- print(f"πŸ”„ Attempting to sync {uid} to {LAMBDA_URL}")
35
- resp = requests.post(LAMBDA_URL, json=payload, timeout=5)
36
- resp.raise_for_status()
37
- user_memory[uid]["last_sync"] = now
38
- app.logger.info(f"Synced memory for {uid} ({len(history_to_sync)} turns)")
39
- print(f"βœ… Successfully synced memory for {uid} ({len(history_to_sync)} turns)")
40
- except Exception as e:
41
- app.logger.warning(f"Failed sync for {uid}: {e}")
42
- print(f"❌ Failed sync for {uid}: {e}")
43
-
44
- threading.Thread(target=flush_loop, daemon=True).start()
45
 
46
  # --- HTML Frontend ---
47
  HTML = """
@@ -139,35 +117,67 @@ def generate_from_gemini(prompt, image_bytes=None, history=None):
139
  }
140
  }
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  # --- History Management ---
143
  def get_user_history(uid):
144
  if uid not in user_memory:
145
  try:
146
- resp = requests.get(f"{LAMBDA_URL}?userid={uid}", timeout=5)
147
  resp.raise_for_status()
148
  loaded_history = resp.json().get("history", [])
149
- # Only keep the most recent MAX_HISTORY_TURNS when loading
150
  user_memory[uid] = {
151
- "history": loaded_history[-MAX_HISTORY_TURNS:],
152
- "last_sync": time.time()
 
153
  }
154
- app.logger.info(f"Loaded history for {uid} ({len(user_memory[uid]['history'])} turns)")
155
  except Exception as e:
156
  app.logger.warning(f"Failed to load history for {uid}: {e}")
157
- user_memory[uid] = {"history": [], "last_sync": time.time()}
 
 
 
 
 
 
 
158
  return user_memory[uid]["history"]
159
 
160
  def update_user_history(uid, prompt, response):
161
  entry = {"prompt": prompt, "response": response, "timestamp": time.time()}
162
  if uid not in user_memory:
163
- user_memory[uid] = {"history": [], "last_sync": time.time()}
 
 
 
 
164
 
165
  user_memory[uid]["history"].append(entry)
 
166
 
167
- # Trim history to MAX_HISTORY_TURNS to prevent unbounded growth
168
- if len(user_memory[uid]["history"]) > MAX_HISTORY_TURNS:
169
- user_memory[uid]["history"] = user_memory[uid]["history"][-MAX_HISTORY_TURNS:]
170
- app.logger.debug(f"Trimmed history for {uid} to {MAX_HISTORY_TURNS} turns")
 
 
171
 
172
  # --- Routes ---
173
  @app.route("/")
@@ -175,26 +185,43 @@ def index():
175
  return render_template_string(HTML)
176
 
177
 
178
- @app.route("/remote")
179
  def remote_saving():
 
180
  now = time.time()
 
 
 
 
 
 
 
181
  for uid, data in list(user_memory.items()):
182
- if now - data.get("last_sync", 0) >= FLUSH_INTERVAL and data["history"]:
183
- try:
184
- # Only sync the most recent MAX_HISTORY_TURNS entries
185
- history_to_sync = data["history"][-MAX_HISTORY_TURNS:]
186
- payload = {"user_id": uid, "history": history_to_sync}
187
- print(f"πŸ”„ Attempting to sync {uid} to {LAMBDA_URL}")
188
- resp = requests.post(LAMBDA_URL, json=payload, timeout=5)
189
- resp.raise_for_status()
190
- user_memory[uid]["last_sync"] = now
191
- app.logger.info(f"Synced memory for {uid} ({len(history_to_sync)} turns)")
192
- print(f"βœ… Successfully synced memory for {uid} ({len(history_to_sync)} turns)")
193
- return jsonify({"done": True}), 200
194
- except Exception as e:
195
- app.logger.warning(f"Failed sync for {uid}: {e}")
196
- print(f"❌ Failed sync for {uid}: {e}")
197
- return jsonify({"error": str(e)}), 500
 
 
 
 
 
 
 
 
 
198
 
199
 
200
  @app.route("/generate", methods=["POST"])
 
3
 
4
  import os
5
  import time
 
6
  import requests
7
  from flask import Flask, request, render_template_string, jsonify
8
  from google import genai
 
15
  GEMINI_KEY = os.getenv("GEMINI_API_KEY", "")
16
  FLUSH_INTERVAL = 30 # seconds between DB backups per user
17
  MAX_HISTORY_TURNS = 10 # Maximum conversation turns to keep in context
18
+ MAX_MEMORY_MESSAGES = 90 # Maximum messages to keep in memory per user
19
+ MEMORY_CLEANUP_TIMEOUT = 1800 # 30 minutes in seconds - remove inactive users
20
 
21
  client = genai.Client(api_key=GEMINI_KEY)
22
+ user_memory = {} # { user_id: { "history": [], "last_sync": timestamp, "last_activity": timestamp } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  # --- HTML Frontend ---
25
  HTML = """
 
117
  }
118
  }
119
 
120
+ # --- Memory Cleanup ---
121
+ def cleanup_inactive_users():
122
+ """Remove users who haven't had activity in MEMORY_CLEANUP_TIMEOUT seconds"""
123
+ now = time.time()
124
+ removed_count = 0
125
+ for uid in list(user_memory.keys()):
126
+ last_activity = user_memory[uid].get("last_activity", 0)
127
+ if now - last_activity >= MEMORY_CLEANUP_TIMEOUT:
128
+ del user_memory[uid]
129
+ removed_count += 1
130
+ app.logger.info(f"Cleaned up inactive user {uid}")
131
+ print(f"🧹 Cleaned up inactive user {uid}")
132
+
133
+ if removed_count > 0:
134
+ print(f"🧹 Cleaned up {removed_count} inactive user(s)")
135
+ return removed_count
136
+
137
  # --- History Management ---
138
  def get_user_history(uid):
139
  if uid not in user_memory:
140
  try:
141
+ resp = requests.get(f"{LAMBDA_URL}?user_id={uid}", timeout=5)
142
  resp.raise_for_status()
143
  loaded_history = resp.json().get("history", [])
144
+ # Only keep the most recent MAX_MEMORY_MESSAGES when loading
145
  user_memory[uid] = {
146
+ "history": loaded_history[-MAX_MEMORY_MESSAGES:],
147
+ "last_sync": time.time(),
148
+ "last_activity": time.time()
149
  }
150
+ app.logger.info(f"Loaded history for {uid} ({len(user_memory[uid]['history'])} messages)")
151
  except Exception as e:
152
  app.logger.warning(f"Failed to load history for {uid}: {e}")
153
+ user_memory[uid] = {
154
+ "history": [],
155
+ "last_sync": time.time(),
156
+ "last_activity": time.time()
157
+ }
158
+
159
+ # Update last activity timestamp
160
+ user_memory[uid]["last_activity"] = time.time()
161
  return user_memory[uid]["history"]
162
 
163
  def update_user_history(uid, prompt, response):
164
  entry = {"prompt": prompt, "response": response, "timestamp": time.time()}
165
  if uid not in user_memory:
166
+ user_memory[uid] = {
167
+ "history": [],
168
+ "last_sync": time.time(),
169
+ "last_activity": time.time()
170
+ }
171
 
172
  user_memory[uid]["history"].append(entry)
173
+ user_memory[uid]["last_activity"] = time.time()
174
 
175
+ # Trim history to MAX_MEMORY_MESSAGES to prevent unbounded growth
176
+ # This keeps the oldest messages in memory up to the limit
177
+ if len(user_memory[uid]["history"]) > MAX_MEMORY_MESSAGES:
178
+ user_memory[uid]["history"] = user_memory[uid]["history"][-MAX_MEMORY_MESSAGES:]
179
+ app.logger.debug(f"Trimmed history for {uid} to {MAX_MEMORY_MESSAGES} messages")
180
+ print(f"βœ‚οΈ Trimmed history for {uid} to {MAX_MEMORY_MESSAGES} messages")
181
 
182
  # --- Routes ---
183
  @app.route("/")
 
185
  return render_template_string(HTML)
186
 
187
 
188
+ @app.route("/cron/sync", methods=["GET", "POST"])
189
  def remote_saving():
190
+ """Cron job endpoint for syncing user memory to backend"""
191
  now = time.time()
192
+ synced_users = []
193
+ failed_users = []
194
+
195
+ # First, cleanup inactive users
196
+ cleanup_inactive_users()
197
+
198
+ # Then sync active users
199
  for uid, data in list(user_memory.items()):
200
+ if now - data.get("last_sync", 0) >= FLUSH_INTERVAL and data["history"]:
201
+ try:
202
+ # Sync all messages (up to MAX_MEMORY_MESSAGES)
203
+ history_to_sync = data["history"][-MAX_MEMORY_MESSAGES:]
204
+ payload = {"user_id": uid, "history": history_to_sync}
205
+ print(f"πŸ”„ Attempting to sync {uid} to {LAMBDA_URL}")
206
+ resp = requests.post(LAMBDA_URL, json=payload, timeout=5)
207
+ resp.raise_for_status()
208
+ user_memory[uid]["last_sync"] = now
209
+ app.logger.info(f"Synced memory for {uid} ({len(history_to_sync)} messages)")
210
+ print(f"βœ… Successfully synced memory for {uid} ({len(history_to_sync)} messages)")
211
+ synced_users.append(uid)
212
+ except Exception as e:
213
+ app.logger.warning(f"Failed sync for {uid}: {e}")
214
+ print(f"❌ Failed sync for {uid}: {e}")
215
+ failed_users.append({"user_id": uid, "error": str(e)})
216
+
217
+ return jsonify({
218
+ "success": True,
219
+ "synced_count": len(synced_users),
220
+ "failed_count": len(failed_users),
221
+ "synced_users": synced_users,
222
+ "failed_users": failed_users,
223
+ "active_users_in_memory": len(user_memory)
224
+ }), 200
225
 
226
 
227
  @app.route("/generate", methods=["POST"])