CB commited on
Commit
03539b5
·
verified ·
1 Parent(s): b1d8f7e

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +14 -32
streamlit_app.py CHANGED
@@ -198,9 +198,9 @@ API_KEY_INPUT = settings.text_input("Google API Key (one-time)", value="", type=
198
  # Default model changed to text-bison@001 (broadly available). Replace if you have another.
199
  model_input = settings.text_input("Model (short name)", "text-bison@001")
200
  model_id = model_input.strip() or "text-bison@001"
201
- # model_arg used with SDK; model_for_url used for HTTP
202
- model_arg = model_id if not model_id.startswith("models/") else model_id.split("/", 1)[1]
203
- model_for_url_default = model_arg.split("/", 1)[0] if "@" not in model_arg else model_arg # keep @ if present
204
 
205
  default_prompt = (
206
  "You are an Indoor Human Behavior Analyzer. Watch the video and produce a detailed, evidence‑based behavioral report focused on human actions, "
@@ -282,19 +282,16 @@ def get_runtime_api_key():
282
  # ---- Simplified SDK-first + HTTP-fallback layer ----
283
  def _normalize_model_for_http(model: str) -> str:
284
  """
285
- Return a model identifier appropriate for the HTTP path.
286
- Accept inputs like:
287
- - "text-bison@001" -> "models/text-bison@001"
288
- - "models/text-bison@001" -> "models/text-bison@001"
289
- - "models/foo" -> "models/foo"
290
- - "foo" -> "models/foo"
291
  """
292
  if not model:
293
- return "models/text-bison@001"
294
  m = model.strip()
 
295
  if m.startswith("models/"):
296
- return m
297
- return f"models/{m}"
298
 
299
  def _messages_to_prompt(messages):
300
  if not messages:
@@ -309,11 +306,10 @@ def _messages_to_prompt(messages):
309
  def _http_generate(api_key: str, model: str, prompt: str, max_tokens: int):
310
  host = "https://generativelanguage.googleapis.com"
311
  norm = _normalize_model_for_http(model)
312
- # Try several API paths. norm already contains "models/..."
313
  candidates = [
314
- f"{host}/v1/{norm}:generate",
315
- f"{host}/v1beta3/{norm}:generate",
316
- f"{host}/v1beta2/{norm}:generate",
317
  ]
318
  payload = {"prompt": {"text": prompt}, "maxOutputTokens": int(max_tokens or 512)}
319
  headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
@@ -326,7 +322,6 @@ def _http_generate(api_key: str, model: str, prompt: str, max_tokens: int):
326
  return r.json()
327
  except Exception:
328
  return {"text": r.text}
329
- # Explicit 404 handling: try next candidate
330
  last_exc = RuntimeError(f"HTTP {r.status_code}: {r.text}")
331
  except Exception as e:
332
  last_exc = e
@@ -346,7 +341,6 @@ def responses_generate(model, messages, files, max_output_tokens, api_key):
346
  sdk_kwargs["files"] = files
347
  return responses_obj.generate(**sdk_kwargs)
348
  except Exception:
349
- # fall through to HTTP fallback
350
  pass
351
  # HTTP fallback
352
  prompt = _messages_to_prompt(messages)
@@ -367,15 +361,11 @@ def call_responses_once(model_used, system_msg, user_msg, fname, max_tokens):
367
  def extract_text_from_response(response):
368
  if response is None:
369
  return None
370
- # dict-like (HTTP)
371
  if isinstance(response, dict):
372
- # Try common shapes
373
- # 1) "candidates": [ { "content": "...", "text": "..." } ]
374
  if "candidates" in response and isinstance(response["candidates"], list) and response["candidates"]:
375
  cand = response["candidates"][0]
376
  if isinstance(cand, dict):
377
  return cand.get("content") or cand.get("text") or response.get("text")
378
- # 2) "output": [ { "content": "..."} ] or "output_text"
379
  if "output" in response and isinstance(response["output"], list):
380
  pieces = []
381
  for item in response["output"]:
@@ -389,12 +379,10 @@ def extract_text_from_response(response):
389
  return response["text"]
390
  if "outputText" in response and isinstance(response["outputText"], str):
391
  return response["outputText"]
392
- # fallback: try joining string fields
393
  for k in ("result", "generated_text", "description"):
394
  if k in response and isinstance(response[k], str):
395
  return response[k]
396
  return None
397
- # object-like (SDK)
398
  try:
399
  outputs = getattr(response, "output", None) or getattr(response, "candidates", None)
400
  if outputs:
@@ -414,7 +402,6 @@ def extract_text_from_response(response):
414
 
415
  # ---- end compatibility layer ----
416
 
417
- # The main generation block (patched, robust)
418
  if (st.session_state.get("busy") is False) and ('generate_now' in locals() and generate_now):
419
  if not st.session_state.get("videos"):
420
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
@@ -485,7 +472,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
485
  model_used = model_arg or "text-bison@001"
486
  max_tokens = int(st.session_state.get("max_output_tokens", 1024))
487
 
488
- # Ensure model_used is a short name (SDK accepts it; HTTP will normalize)
489
  system_msg = {"role": "system", "content": "You are a helpful assistant that summarizes videos concisely in vivid detail."}
490
  user_msg = {"role": "user", "content": prompt_text}
491
 
@@ -494,7 +480,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
494
 
495
  out = extract_text_from_response(response)
496
 
497
- # Try to read token info if present
498
  meta = getattr(response, "metrics", None) or (response.get("metrics") if isinstance(response, dict) else None) or {}
499
  output_tokens = 0
500
  try:
@@ -505,7 +490,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
505
  except Exception:
506
  output_tokens = 0
507
 
508
- # Retry strategies if no output
509
  if (not out or output_tokens == 0) and model_used:
510
  retry_prompt = "Summarize the video content briefly and vividly (2-4 paragraphs)."
511
  try:
@@ -530,7 +514,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
530
  st.subheader("Analysis Result")
531
  st.markdown(out or "_(no text returned)_")
532
 
533
- # Clean up compressed temporary file only (don't remove original unless it was a true temp)
534
  try:
535
  if reupload_needed:
536
  try:
@@ -540,8 +523,6 @@ if (st.session_state.get("busy") is False) and ('generate_now' in locals() and g
540
  p.unlink(missing_ok=True)
541
  except Exception:
542
  pass
543
- # don't delete original unless it's intended to be removed (conservative)
544
- # If you want original removed, enable a setting and handle carefully.
545
  except Exception:
546
  pass
547
 
@@ -590,7 +571,8 @@ with st.sidebar.expander("Manage uploads", expanded=False):
590
  st.session_state["uploaded_file"] = None
591
  st.session_state["processed_file"] = None
592
  st.session_state["last_loaded_path"] = ""
593
- st.session_state[""] = None
 
594
  try:
595
  fname = file_name_or_id(st.session_state.get("uploaded_file"))
596
  if fname and delete_file and HAS_GENAI:
 
198
  # Default model changed to text-bison@001 (broadly available). Replace if you have another.
199
  model_input = settings.text_input("Model (short name)", "text-bison@001")
200
  model_id = model_input.strip() or "text-bison@001"
201
+ # model_arg used with SDK; keep as short name like "text-bison@001"
202
+ model_arg = model_id
203
+ model_for_url_default = model_arg
204
 
205
  default_prompt = (
206
  "You are an Indoor Human Behavior Analyzer. Watch the video and produce a detailed, evidence‑based behavioral report focused on human actions, "
 
282
  # ---- Simplified SDK-first + HTTP-fallback layer ----
283
  def _normalize_model_for_http(model: str) -> str:
284
  """
285
+ Return a short model name appropriate for the HTTP path,
286
+ e.g. "text-bison@001" (no "models/" prefix).
 
 
 
 
287
  """
288
  if not model:
289
+ return "text-bison@001"
290
  m = model.strip()
291
+ # If user mistakenly provided "models/..." strip the prefix for HTTP path
292
  if m.startswith("models/"):
293
+ return m.split("/", 1)[1]
294
+ return m
295
 
296
  def _messages_to_prompt(messages):
297
  if not messages:
 
306
  def _http_generate(api_key: str, model: str, prompt: str, max_tokens: int):
307
  host = "https://generativelanguage.googleapis.com"
308
  norm = _normalize_model_for_http(model)
 
309
  candidates = [
310
+ f"{host}/v1/models/{norm}:generate",
311
+ f"{host}/v1beta3/models/{norm}:generate",
312
+ f"{host}/v1beta2/models/{norm}:generate",
313
  ]
314
  payload = {"prompt": {"text": prompt}, "maxOutputTokens": int(max_tokens or 512)}
315
  headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
 
322
  return r.json()
323
  except Exception:
324
  return {"text": r.text}
 
325
  last_exc = RuntimeError(f"HTTP {r.status_code}: {r.text}")
326
  except Exception as e:
327
  last_exc = e
 
341
  sdk_kwargs["files"] = files
342
  return responses_obj.generate(**sdk_kwargs)
343
  except Exception:
 
344
  pass
345
  # HTTP fallback
346
  prompt = _messages_to_prompt(messages)
 
361
  def extract_text_from_response(response):
362
  if response is None:
363
  return None
 
364
  if isinstance(response, dict):
 
 
365
  if "candidates" in response and isinstance(response["candidates"], list) and response["candidates"]:
366
  cand = response["candidates"][0]
367
  if isinstance(cand, dict):
368
  return cand.get("content") or cand.get("text") or response.get("text")
 
369
  if "output" in response and isinstance(response["output"], list):
370
  pieces = []
371
  for item in response["output"]:
 
379
  return response["text"]
380
  if "outputText" in response and isinstance(response["outputText"], str):
381
  return response["outputText"]
 
382
  for k in ("result", "generated_text", "description"):
383
  if k in response and isinstance(response[k], str):
384
  return response[k]
385
  return None
 
386
  try:
387
  outputs = getattr(response, "output", None) or getattr(response, "candidates", None)
388
  if outputs:
 
402
 
403
  # ---- end compatibility layer ----
404
 
 
405
  if (st.session_state.get("busy") is False) and ('generate_now' in locals() and generate_now):
406
  if not st.session_state.get("videos"):
407
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
 
472
  model_used = model_arg or "text-bison@001"
473
  max_tokens = int(st.session_state.get("max_output_tokens", 1024))
474
 
 
475
  system_msg = {"role": "system", "content": "You are a helpful assistant that summarizes videos concisely in vivid detail."}
476
  user_msg = {"role": "user", "content": prompt_text}
477
 
 
480
 
481
  out = extract_text_from_response(response)
482
 
 
483
  meta = getattr(response, "metrics", None) or (response.get("metrics") if isinstance(response, dict) else None) or {}
484
  output_tokens = 0
485
  try:
 
490
  except Exception:
491
  output_tokens = 0
492
 
 
493
  if (not out or output_tokens == 0) and model_used:
494
  retry_prompt = "Summarize the video content briefly and vividly (2-4 paragraphs)."
495
  try:
 
514
  st.subheader("Analysis Result")
515
  st.markdown(out or "_(no text returned)_")
516
 
 
517
  try:
518
  if reupload_needed:
519
  try:
 
523
  p.unlink(missing_ok=True)
524
  except Exception:
525
  pass
 
 
526
  except Exception:
527
  pass
528
 
 
571
  st.session_state["uploaded_file"] = None
572
  st.session_state["processed_file"] = None
573
  st.session_state["last_loaded_path"] = ""
574
+ st.session_state["analysis_out"] = ""
575
+ st.session_state["file_hash"] = None
576
  try:
577
  fname = file_name_or_id(st.session_state.get("uploaded_file"))
578
  if fname and delete_file and HAS_GENAI: