konniedeveloping commited on
Commit
df626d6
·
verified ·
1 Parent(s): eb7bff7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -8
app.py CHANGED
@@ -5,6 +5,7 @@ from google.genai import types
5
  from pymongo import UpdateOne
6
  from pymongo import MongoClient
7
  from bson import ObjectId
 
8
  import bcrypt
9
  import os
10
  import re
@@ -106,6 +107,14 @@ Mode: English-guided learning.
106
  pushing.
107
  - Correct mistakes gently and explain the grammar point in English."""
108
 
 
 
 
 
 
 
 
 
109
 
110
  def normalize_word(w):
111
  return re.sub(r"[^\w']", "", w, flags=re.UNICODE).strip().lower()
@@ -164,12 +173,18 @@ def build_config(mode, pronunciation_notes=""):
164
  )
165
 
166
 
167
- def call_intyoza(message, history, mode):
168
  contents = []
169
  for turn in history:
170
  role = "user" if turn["role"] == "user" else "model"
171
  contents.append(types.Content(role=role, parts=[types.Part(text=str(turn["content"]))]))
172
- contents.append(types.Content(role="user", parts=[types.Part(text=message)]))
 
 
 
 
 
 
173
 
174
  config = build_config(mode, lookup_pronunciation_notes(message, history))
175
 
@@ -457,14 +472,17 @@ def send_message():
457
  message = (data.get("message") or "").strip()
458
  mode = data.get("mode", "Kinyarwanda immersion")
459
  chat_id = data.get("chat_id")
 
460
 
461
- if not message:
462
  return jsonify(ok=False, message="Empty message."), 400
 
 
463
 
464
  username = require_login()
465
 
466
  if not (username and chat_id):
467
- reply = call_intyoza(message, data.get("history", []), mode)
468
  return jsonify(ok=True, reply=reply)
469
 
470
  chat_doc = chats_col.find_one({"_id": ObjectId(chat_id), "username": username})
@@ -476,24 +494,24 @@ def send_message():
476
  for d in messages_col.find({"chat_id": chat_id}).sort("timestamp", 1)
477
  ]
478
 
479
- reply = call_intyoza(message, history, mode)
480
  now = datetime.datetime.utcnow()
481
 
 
482
  user_doc = messages_col.insert_one(
483
- {"chat_id": chat_id, "role": "user", "content": message, "timestamp": now})
484
  bot_doc = messages_col.insert_one(
485
  {"chat_id": chat_id, "role": "assistant", "content": reply,
486
  "timestamp": now + datetime.timedelta(milliseconds=1)})
487
 
488
  full_history = history + [
489
- {"role": "user", "content": message},
490
  {"role": "assistant", "content": reply},
491
  ]
492
  exchanges = len(full_history) // 2
493
  stage = chat_doc.get("auto_titled_at", 0)
494
 
495
  new_title = None
496
- # Title after the first exchange, then refine once the conversation has shape.
497
  if stage < 999 and (exchanges == 1 or (exchanges >= 4 and stage < 4)):
498
  candidate = generate_title(snippet_from(full_history))
499
  if candidate:
 
5
  from pymongo import UpdateOne
6
  from pymongo import MongoClient
7
  from bson import ObjectId
8
+ import base64
9
  import bcrypt
10
  import os
11
  import re
 
107
  pushing.
108
  - Correct mistakes gently and explain the grammar point in English."""
109
 
110
+ def parse_data_url(data_url):
111
+ try:
112
+ header, b64data = data_url.split(",", 1)
113
+ mime = header.split(":")[1].split(";")[0]
114
+ return mime, base64.b64decode(b64data)
115
+ except Exception:
116
+ return None, None
117
+
118
 
119
  def normalize_word(w):
120
  return re.sub(r"[^\w']", "", w, flags=re.UNICODE).strip().lower()
 
173
  )
174
 
175
 
176
+ def call_intyoza(message, history, mode, image_data_url=None):
177
  contents = []
178
  for turn in history:
179
  role = "user" if turn["role"] == "user" else "model"
180
  contents.append(types.Content(role=role, parts=[types.Part(text=str(turn["content"]))]))
181
+
182
+ parts = [types.Part(text=message)]
183
+ if image_data_url:
184
+ mime, raw = parse_data_url(image_data_url)
185
+ if raw:
186
+ parts.append(types.Part.from_bytes(data=raw, mime_type=mime))
187
+ contents.append(types.Content(role="user", parts=parts))
188
 
189
  config = build_config(mode, lookup_pronunciation_notes(message, history))
190
 
 
472
  message = (data.get("message") or "").strip()
473
  mode = data.get("mode", "Kinyarwanda immersion")
474
  chat_id = data.get("chat_id")
475
+ image_data_url = data.get("image")
476
 
477
+ if not message and not image_data_url:
478
  return jsonify(ok=False, message="Empty message."), 400
479
+ if image_data_url and len(image_data_url) > 4_000_000:
480
+ return jsonify(ok=False, message="Image is too large (4MB max)."), 400
481
 
482
  username = require_login()
483
 
484
  if not (username and chat_id):
485
+ reply = call_intyoza(message or "What is in this image?", data.get("history", []), mode, image_data_url)
486
  return jsonify(ok=True, reply=reply)
487
 
488
  chat_doc = chats_col.find_one({"_id": ObjectId(chat_id), "username": username})
 
494
  for d in messages_col.find({"chat_id": chat_id}).sort("timestamp", 1)
495
  ]
496
 
497
+ reply = call_intyoza(message or "What is in this image?", history, mode, image_data_url)
498
  now = datetime.datetime.utcnow()
499
 
500
+ stored_message = message or "[Sent an image]"
501
  user_doc = messages_col.insert_one(
502
+ {"chat_id": chat_id, "role": "user", "content": stored_message, "timestamp": now})
503
  bot_doc = messages_col.insert_one(
504
  {"chat_id": chat_id, "role": "assistant", "content": reply,
505
  "timestamp": now + datetime.timedelta(milliseconds=1)})
506
 
507
  full_history = history + [
508
+ {"role": "user", "content": stored_message},
509
  {"role": "assistant", "content": reply},
510
  ]
511
  exchanges = len(full_history) // 2
512
  stage = chat_doc.get("auto_titled_at", 0)
513
 
514
  new_title = None
 
515
  if stage < 999 and (exchanges == 1 or (exchanges >= 4 and stage < 4)):
516
  candidate = generate_title(snippet_from(full_history))
517
  if candidate: