CB commited on
Commit
9589f67
·
verified ·
1 Parent(s): 1c6309c

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +47 -46
streamlit_app.py CHANGED
@@ -1,4 +1,3 @@
1
- # streamlit_app.py
2
  import os
3
  import time
4
  import hashlib
@@ -216,7 +215,7 @@ st.sidebar.text_input("Video URL", key="url", placeholder="https://")
216
  settings = st.sidebar.expander("Settings", expanded=False)
217
 
218
  env_key = os.getenv("GOOGLE_API_KEY", "")
219
- API_KEY_INPUT = settings.text_input("Google API Key (one-time)", value="", type="password", help="Provide only if you want uploads/generation. Not stored in session.")
220
  model_input = settings.text_input("Gemini Model (short name)", "gemini-2.0-flash-lite")
221
  model_id = model_input.strip() or "gemini-2.0-flash-lite"
222
  model_arg = model_id if not model_id.startswith("models/") else model_id.split("/", 1)[1]
@@ -236,7 +235,7 @@ settings.checkbox("Enable compression for large files (>50MB)", value=True, key=
236
  settings.number_input("Max output tokens", key="max_output_tokens", value=1024, min_value=128, max_value=8192, step=128)
237
 
238
  if not API_KEY_INPUT and not env_key:
239
- settings.info("No Google API key provided; upload/generation disabled. Use local-only demos or provide key for real analysis.", icon="ℹ️")
240
 
241
  if st.sidebar.button("Load Video", use_container_width=True):
242
  try:
@@ -298,33 +297,38 @@ def get_runtime_api_key():
298
  return key
299
  return os.getenv("GOOGLE_API_KEY", "").strip() or None
300
 
301
- # Responses caller supporting SDK variants and HTTP fallback
302
  def responses_generate(model, messages, files, max_output_tokens, api_key):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  genai.configure(api_key=api_key)
304
- # preferred SDK style
305
  if hasattr(genai, "responses") and getattr(genai, "responses") is not None:
306
- try:
307
- return genai.responses.generate(model=model, messages=messages, files=files, max_output_tokens=max_output_tokens)
308
- except Exception:
309
- # let higher level handle retries/errors
310
- raise
311
- # older/newer SDKs might expose different helpers; attempt generic client POST
312
- # fallback: directly call the REST endpoint via genai.client/_client if available
313
  client_attr = getattr(genai, "client", None) or getattr(genai, "_client", None) or getattr(genai, "transport", None)
314
  if client_attr:
315
- try:
316
- # construct payload similar to Responses API
317
  payload = {"model": model, "messages": messages, "max_output_tokens": max_output_tokens}
318
  headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
319
- # try to find a requests-like post method
320
- post = getattr(client_attr, "post", None) or getattr(client_attr, "request", None)
321
- if post:
322
- # endpoint path used by Google Generative API
323
- url = "/v1/responses"
324
- resp = post(url, json=payload, headers=headers)
325
  return resp
326
- except Exception:
327
- pass
328
  raise RuntimeError("genai.responses not available and HTTP fallback failed")
329
 
330
  if (st.session_state.get("busy") is False) and ('generate_now' in locals() and generate_now):
@@ -334,8 +338,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
334
  runtime_key = get_runtime_api_key()
335
  if not runtime_key:
336
  st.error("Google API key not set. Provide in Settings or set GOOGLE_API_KEY in environment.")
337
- elif not HAS_GENAI:
338
- st.error("google.generativeai SDK not available. Install the SDK to enable uploads/generation.")
339
  else:
340
  try:
341
  st.session_state["busy"] = True
@@ -369,14 +371,21 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
369
  except Exception:
370
  upload_path = local_path
371
 
372
- genai.configure(api_key=runtime_key)
373
- with st.spinner("Uploading video..."):
374
- uploaded = upload_video_sdk(upload_path)
375
- processed = wait_for_processed(uploaded, timeout=600)
376
- st.session_state["uploaded_file"] = uploaded
377
- st.session_state["processed_file"] = processed
378
- st.session_state["last_loaded_path"] = current_path
379
- st.session_state["file_hash"] = current_hash
 
 
 
 
 
 
 
380
  else:
381
  uploaded = st.session_state.get("uploaded_file")
382
  processed = st.session_state.get("processed_file")
@@ -395,7 +404,8 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
395
  def call_responses_once(model_used, system_msg, user_msg, fname, max_tokens):
396
  for attempt in range(2):
397
  try:
398
- resp = responses_generate(model_used, [system_msg, user_msg], [{"name": fname}], max_tokens, api_key=runtime_key)
 
399
  return resp
400
  except Exception:
401
  if attempt == 0:
@@ -404,26 +414,17 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
404
  raise
405
 
406
  fname = file_name_or_id(processed) or file_name_or_id(uploaded)
407
- if not fname:
408
- try:
409
- uri = getattr(processed, "uri", None) or (processed.get("uri") if isinstance(processed, dict) else None)
410
- if uri:
411
- tail = str(uri).rstrip("/").split("/")[-1]
412
- fname = tail if tail.startswith("files/") else f"files/{tail}"
413
- except Exception:
414
- pass
415
- if not fname:
416
- raise RuntimeError("Uploaded file missing name/id/uri; cannot reference for Responses API.")
417
-
418
  response = call_responses_once(model_used, system_msg, user_msg, fname, max_tokens)
419
 
420
  def extract_text_from_response(response):
421
  outputs = getattr(response, "output", None) or (response.get("output") if isinstance(response, dict) else None) or []
422
- if not outputs and isinstance(response, dict):
423
- outputs = response.get("output", [])
424
  text_pieces = []
425
  for item in outputs or []:
426
  contents = getattr(item, "content", None) or (item.get("content") if isinstance(item, dict) else None) or []
 
 
427
  for c in contents:
428
  ctype = getattr(c, "type", None) or (c.get("type") if isinstance(c, dict) else None)
429
  if ctype in ("output_text", "text") or ctype is None:
 
 
1
  import os
2
  import time
3
  import hashlib
 
215
  settings = st.sidebar.expander("Settings", expanded=False)
216
 
217
  env_key = os.getenv("GOOGLE_API_KEY", "")
218
+ API_KEY_INPUT = settings.text_input("Google API Key (one-time)", value="", type="password")
219
  model_input = settings.text_input("Gemini Model (short name)", "gemini-2.0-flash-lite")
220
  model_id = model_input.strip() or "gemini-2.0-flash-lite"
221
  model_arg = model_id if not model_id.startswith("models/") else model_id.split("/", 1)[1]
 
235
  settings.number_input("Max output tokens", key="max_output_tokens", value=1024, min_value=128, max_value=8192, step=128)
236
 
237
  if not API_KEY_INPUT and not env_key:
238
+ settings.info("No Google API key provided; upload/generation disabled.", icon="ℹ️")
239
 
240
  if st.sidebar.button("Load Video", use_container_width=True):
241
  try:
 
297
  return key
298
  return os.getenv("GOOGLE_API_KEY", "").strip() or None
299
 
300
+ # Robust responses caller: SDK preferred, then attempt HTTP fallback via requests
301
  def responses_generate(model, messages, files, max_output_tokens, api_key):
302
+ if not api_key:
303
+ raise RuntimeError("No API key for responses_generate")
304
+ if not HAS_GENAI:
305
+ # try HTTP directly using requests
306
+ import requests
307
+ url = "https://gen-ai.googleapis.com/v1/responses"
308
+ payload = {"model": model, "messages": messages, "max_output_tokens": max_output_tokens}
309
+ headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
310
+ try:
311
+ r = requests.post(url, json=payload, headers=headers, timeout=60)
312
+ r.raise_for_status()
313
+ return r.json()
314
+ except Exception as e:
315
+ raise RuntimeError(f"HTTP fallback to Responses API failed: {e}")
316
  genai.configure(api_key=api_key)
317
+ # preferred SDK call
318
  if hasattr(genai, "responses") and getattr(genai, "responses") is not None:
319
+ return genai.responses.generate(model=model, messages=messages, files=files, max_output_tokens=max_output_tokens)
320
+ # try client-level post if exposed
 
 
 
 
 
321
  client_attr = getattr(genai, "client", None) or getattr(genai, "_client", None) or getattr(genai, "transport", None)
322
  if client_attr:
323
+ post = getattr(client_attr, "post", None) or getattr(client_attr, "request", None)
324
+ if post:
325
  payload = {"model": model, "messages": messages, "max_output_tokens": max_output_tokens}
326
  headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
327
+ try:
328
+ resp = post("/v1/responses", json=payload, headers=headers)
 
 
 
 
329
  return resp
330
+ except Exception:
331
+ pass
332
  raise RuntimeError("genai.responses not available and HTTP fallback failed")
333
 
334
  if (st.session_state.get("busy") is False) and ('generate_now' in locals() and generate_now):
 
338
  runtime_key = get_runtime_api_key()
339
  if not runtime_key:
340
  st.error("Google API key not set. Provide in Settings or set GOOGLE_API_KEY in environment.")
 
 
341
  else:
342
  try:
343
  st.session_state["busy"] = True
 
371
  except Exception:
372
  upload_path = local_path
373
 
374
+ if HAS_GENAI and upload_file is not None:
375
+ genai.configure(api_key=runtime_key)
376
+ with st.spinner("Uploading video..."):
377
+ uploaded = upload_video_sdk(upload_path)
378
+ processed = wait_for_processed(uploaded, timeout=600)
379
+ st.session_state["uploaded_file"] = uploaded
380
+ st.session_state["processed_file"] = processed
381
+ st.session_state["last_loaded_path"] = current_path
382
+ st.session_state["file_hash"] = current_hash
383
+ else:
384
+ # no SDK upload support: continue without upload and try HTTP responses with no file reference
385
+ uploaded = None
386
+ processed = None
387
+ st.session_state["uploaded_file"] = None
388
+ st.session_state["processed_file"] = None
389
  else:
390
  uploaded = st.session_state.get("uploaded_file")
391
  processed = st.session_state.get("processed_file")
 
404
  def call_responses_once(model_used, system_msg, user_msg, fname, max_tokens):
405
  for attempt in range(2):
406
  try:
407
+ files = [{"name": fname}] if fname else None
408
+ resp = responses_generate(model_used, [system_msg, user_msg], files, max_tokens, api_key=runtime_key)
409
  return resp
410
  except Exception:
411
  if attempt == 0:
 
414
  raise
415
 
416
  fname = file_name_or_id(processed) or file_name_or_id(uploaded)
 
 
 
 
 
 
 
 
 
 
 
417
  response = call_responses_once(model_used, system_msg, user_msg, fname, max_tokens)
418
 
419
  def extract_text_from_response(response):
420
  outputs = getattr(response, "output", None) or (response.get("output") if isinstance(response, dict) else None) or []
421
+ if isinstance(outputs, dict):
422
+ outputs = outputs.get("contents") or outputs.get("items") or []
423
  text_pieces = []
424
  for item in outputs or []:
425
  contents = getattr(item, "content", None) or (item.get("content") if isinstance(item, dict) else None) or []
426
+ if isinstance(contents, dict):
427
+ contents = [contents]
428
  for c in contents:
429
  ctype = getattr(c, "type", None) or (c.get("type") if isinstance(c, dict) else None)
430
  if ctype in ("output_text", "text") or ctype is None: