saad-sust commited on
Commit
9083275
Β·
verified Β·
1 Parent(s): 984fba2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -32
app.py CHANGED
@@ -396,6 +396,12 @@ if "current_chat_id" not in st.session_state:
396
  st.session_state.current_chat_id = None
397
  if "show_uploader" not in st.session_state:
398
  st.session_state.show_uploader = False
 
 
 
 
 
 
399
 
400
  # ════════════════════════════════════════════════════════════════════
401
  # SUPABASE β€” Persistent chat history
@@ -2312,9 +2318,11 @@ def ask_gemini_vision(image_b64: str, mime_type: str, user_note: str) -> str:
2312
 
2313
  if "429" in last_error or "quota" in last_error:
2314
  return (
2315
- "⚠️ **All Gemini keys are rate-limited.**\n\n"
2316
- "Free tier resets every minute (15 req/min) and daily at midnight Pacific.\n"
2317
- "Wait 60 seconds and try again."
 
 
2318
  )
2319
  if "API_KEY_INVALID" in last_error or "403" in last_error:
2320
  return (
@@ -2708,7 +2716,7 @@ for i, msg in enumerate(st.session_state.messages):
2708
  st.code(msg["content"], language=None)
2709
 
2710
  # ════════════════════════════════════════════════════════════════════
2711
- # FILE UPLOAD β€” ChatGPT-style: paperclip toggle above input bar
2712
  # ════════════════════════════════════════════════════════════════════
2713
 
2714
  # Toolbar row: paperclip button (left-aligned, compact)
@@ -2720,7 +2728,6 @@ with col_attach:
2720
  st.rerun()
2721
 
2722
  # Compact uploader β€” only visible when toggled ON
2723
- uploaded_file = None
2724
  if st.session_state.show_uploader:
2725
  uploaded_file = st.file_uploader(
2726
  "Upload image or PDF of your math problem",
@@ -2728,33 +2735,28 @@ if st.session_state.show_uploader:
2728
  label_visibility="collapsed",
2729
  help="JPG Β· PNG Β· WEBP Β· PDF β€” max 5 MB"
2730
  )
2731
-
2732
- if uploaded_file:
2733
- # Use size+type as key β€” works with ANY filename including spaces/brackets
2734
- file_key = f"{uploaded_file.size}_{uploaded_file.type}"
2735
- if file_key != st.session_state.get("last_uploaded_file", ""):
2736
- st.session_state["last_uploaded_file"] = file_key
2737
- st.session_state.show_uploader = False # auto-close after upload
2738
- user_note = ""
2739
-
2740
- with st.chat_message("user", avatar="πŸ§‘β€πŸŽ“"):
2741
- st.markdown(f"πŸ“Ž **Uploaded:** `{uploaded_file.name}`")
2742
-
2743
- with st.chat_message("assistant", avatar="πŸ“"):
2744
- with st.spinner("πŸ“– Reading your file..."):
2745
- answer = handle_uploaded_file(uploaded_file, user_note)
2746
- st.markdown(answer)
2747
- with st.expander("πŸ“‹ Copy"):
2748
- st.code(answer, language=None)
2749
-
2750
- if not st.session_state.current_chat_id:
2751
- new_chat()
2752
- st.session_state.messages.append({
2753
- "role": "user",
2754
- "content": f"πŸ“Ž Uploaded: `{uploaded_file.name}`"
2755
- })
2756
- st.session_state.messages.append({"role": "assistant", "content": answer})
2757
- save_current_chat()
2758
 
2759
  # ════════════════════════════════════════════════════════════════════
2760
  # INPUT β€” ChatGPT-style input bar
@@ -2781,6 +2783,40 @@ else:
2781
  if problem and problem != st.session_state.last_submitted:
2782
  st.session_state.last_submitted = problem
2783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2784
  # ── Detect casual / non-math messages ───────────────────────────
2785
  p_lower = problem.lower().strip()
2786
  casual_keywords = [
 
396
  st.session_state.current_chat_id = None
397
  if "show_uploader" not in st.session_state:
398
  st.session_state.show_uploader = False
399
+ if "pending_file_bytes" not in st.session_state:
400
+ st.session_state.pending_file_bytes = None
401
+ if "pending_file_name" not in st.session_state:
402
+ st.session_state.pending_file_name = None
403
+ if "pending_file_mime" not in st.session_state:
404
+ st.session_state.pending_file_mime = None
405
 
406
  # ════════════════════════════════════════════════════════════════════
407
  # SUPABASE β€” Persistent chat history
 
2318
 
2319
  if "429" in last_error or "quota" in last_error:
2320
  return (
2321
+ f"⚠️ **All Gemini keys are rate-limited.**\n\n"
2322
+ f"Exact error: `{last_error}`\n\n"
2323
+ "**Per-minute limit** (15 req/min): wait 60 seconds.\n"
2324
+ "**Daily limit** (1500 req/day): resets at midnight Pacific β€” must wait until then.\n\n"
2325
+ "Make sure each key is from a **different Google account** β€” keys from the same account share the same quota pool."
2326
  )
2327
  if "API_KEY_INVALID" in last_error or "403" in last_error:
2328
  return (
 
2716
  st.code(msg["content"], language=None)
2717
 
2718
  # ════════════════════════════════════════════════════════════════════
2719
+ # FILE UPLOAD β€” True ChatGPT-style: attach file THEN type question
2720
  # ════════════════════════════════════════════════════════════════════
2721
 
2722
  # Toolbar row: paperclip button (left-aligned, compact)
 
2728
  st.rerun()
2729
 
2730
  # Compact uploader β€” only visible when toggled ON
 
2731
  if st.session_state.show_uploader:
2732
  uploaded_file = st.file_uploader(
2733
  "Upload image or PDF of your math problem",
 
2735
  label_visibility="collapsed",
2736
  help="JPG Β· PNG Β· WEBP Β· PDF β€” max 5 MB"
2737
  )
2738
+ if uploaded_file:
2739
+ file_key = f"{uploaded_file.size}_{uploaded_file.type}"
2740
+ if file_key != st.session_state.get("last_uploaded_file", ""):
2741
+ st.session_state["last_uploaded_file"] = file_key
2742
+ # Store file bytes in session state β€” wait for user's typed question
2743
+ st.session_state.pending_file_bytes = uploaded_file.read()
2744
+ st.session_state.pending_file_name = uploaded_file.name
2745
+ st.session_state.pending_file_mime = uploaded_file.type or "application/octet-stream"
2746
+ st.session_state.show_uploader = False
2747
+ st.rerun()
2748
+
2749
+ # Show attached file pill above input bar so user knows it's ready
2750
+ if st.session_state.pending_file_bytes is not None:
2751
+ col_pill, col_x = st.columns([9, 1])
2752
+ with col_pill:
2753
+ st.info(f"πŸ“Ž **{st.session_state.pending_file_name}** attached β€” type your question below and press Enter")
2754
+ with col_x:
2755
+ if st.button("βœ•", key="remove_pending", help="Remove attached file"):
2756
+ st.session_state.pending_file_bytes = None
2757
+ st.session_state.pending_file_name = None
2758
+ st.session_state.pending_file_mime = None
2759
+ st.rerun()
 
 
 
 
 
2760
 
2761
  # ════════════════════════════════════════════════════════════════════
2762
  # INPUT β€” ChatGPT-style input bar
 
2783
  if problem and problem != st.session_state.last_submitted:
2784
  st.session_state.last_submitted = problem
2785
 
2786
+ # ── If a file is attached, send file + question to Gemini Vision ─
2787
+ if st.session_state.pending_file_bytes is not None:
2788
+ import base64
2789
+
2790
+ file_bytes = st.session_state.pending_file_bytes
2791
+ file_name = st.session_state.pending_file_name
2792
+ file_mime = st.session_state.pending_file_mime
2793
+
2794
+ # Clear pending file immediately so it's not re-sent on rerun
2795
+ st.session_state.pending_file_bytes = None
2796
+ st.session_state.pending_file_name = None
2797
+ st.session_state.pending_file_mime = None
2798
+
2799
+ with st.chat_message("user", avatar="πŸ§‘β€πŸŽ“"):
2800
+ st.markdown(f"πŸ“Ž **{file_name}** β€” {problem}")
2801
+
2802
+ with st.chat_message("assistant", avatar="πŸ“"):
2803
+ with st.spinner("πŸ“– Reading your file with Gemini..."):
2804
+ image_b64 = base64.b64encode(file_bytes).decode("utf-8")
2805
+ answer = ask_gemini_vision(image_b64, file_mime, problem)
2806
+ st.markdown(answer)
2807
+ with st.expander("πŸ“‹ Copy"):
2808
+ st.code(answer, language=None)
2809
+
2810
+ if not st.session_state.current_chat_id:
2811
+ new_chat()
2812
+ st.session_state.messages.append({
2813
+ "role": "user",
2814
+ "content": f"πŸ“Ž {file_name} β€” {problem}"
2815
+ })
2816
+ st.session_state.messages.append({"role": "assistant", "content": answer})
2817
+ save_current_chat()
2818
+ st.stop()
2819
+
2820
  # ── Detect casual / non-math messages ───────────────────────────
2821
  p_lower = problem.lower().strip()
2822
  casual_keywords = [