CB commited on
Commit
299e637
·
verified ·
1 Parent(s): 2d57381

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +9 -54
streamlit_app.py CHANGED
@@ -40,10 +40,10 @@ settings_exp = st.sidebar.expander("Settings", expanded=False)
40
  env_api_key = os.getenv("GOOGLE_API_KEY", "")
41
  API_KEY = settings_exp.text_input("Google API Key", value=env_api_key, placeholder="Set GOOGLE_API_KEY in .env or enter here")
42
 
43
- # Normalize model input: accept either "gemini-2.0-flash-lite" or "models/gemini-2.0-flash-lite"
44
  raw_model = settings_exp.text_input("Gemini Model (model name)", "gemini-2.0-flash-lite")
45
- model_id = raw_model.strip()
46
- if model_id and not model_id.startswith("models/"):
47
  model_id = f"models/{model_id}"
48
 
49
  analysis_prompt = settings_exp.text_area("Enter analysis", "watch entire video and describe")
@@ -52,7 +52,6 @@ settings_exp.text_input("Video Password", key="video-password", placeholder="Ent
52
  if not API_KEY:
53
  settings_exp.warning("No Google API key provided. Uploading/processing will not work.", icon="⚠️")
54
 
55
- # Safety settings (optional)
56
  safety_settings = [
57
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "OFF"},
58
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "OFF"},
@@ -95,7 +94,6 @@ def download_video_ytdlp(url: str, save_dir: str, video_password: str = None) ->
95
  raise FileNotFoundError("Downloaded video not found")
96
  return convert_video_to_mp4(matches[0])
97
 
98
- # Load video
99
  if st.sidebar.button("Load Video", use_container_width=True):
100
  try:
101
  video_password = st.session_state.get("video-password", "")
@@ -104,7 +102,6 @@ if st.sidebar.button("Load Video", use_container_width=True):
104
  except Exception as e:
105
  st.sidebar.error(f"Failed to load video: {e}")
106
 
107
- # Sidebar preview & options
108
  if st.session_state["videos"]:
109
  try:
110
  st.sidebar.video(st.session_state["videos"], loop=st.session_state.get("loop_video", True))
@@ -137,13 +134,11 @@ if st.session_state["videos"]:
137
 
138
  st.sidebar.write("Title:", Path(st.session_state["videos"]).name)
139
 
140
- # Helper: upload via SDK if available, else use direct HTTP
141
  def upload_video(filepath: str):
142
  if not API_KEY:
143
  raise RuntimeError("No API key provided")
144
  if HAS_GENAI and callable(upload_file):
145
  return upload_file(filepath)
146
- # Fallback: use REST upload (multipart/form-data)
147
  url = "https://generative.googleapis.com/v1beta2/files?uploadType=multipart"
148
  headers = {"Authorization": f"Bearer {API_KEY}"}
149
  metadata = {"mimeType": "video/mp4", "displayName": Path(filepath).name}
@@ -155,10 +150,8 @@ def upload_video(filepath: str):
155
  r.raise_for_status()
156
  return r.json()
157
 
158
- # Helper: poll file processing; SDK get_file returns object with state; fallback to REST GET
159
  def poll_file_processed(file_obj, timeout=180):
160
  start = time.time()
161
- # If SDK returned an object with .name and .state, use SDK get_file
162
  if HAS_GENAI and hasattr(file_obj, "name"):
163
  name = file_obj.name
164
  while getattr(file_obj, "state", None) and getattr(file_obj.state, "name", None) == "PROCESSING":
@@ -167,11 +160,9 @@ def poll_file_processed(file_obj, timeout=180):
167
  time.sleep(2)
168
  file_obj = get_file(name)
169
  return file_obj
170
- # If file_obj is a dict from REST upload, it should have "name" field or "id"
171
  fid = file_obj.get("name") or file_obj.get("id")
172
  if not fid:
173
  return file_obj
174
- # Poll via REST GET
175
  url = f"https://generative.googleapis.com/v1beta2/{fid}"
176
  headers = {"Authorization": f"Bearer {API_KEY}"}
177
  while True:
@@ -185,22 +176,19 @@ def poll_file_processed(file_obj, timeout=180):
185
  raise TimeoutError("File processing timed out")
186
  time.sleep(2)
187
 
188
- # Updated helper to call Responses API correctly (use /v1 or /v1beta2 responses:generate depending on model string)
189
  def call_model_with_file(prompt_text: str, uploaded_file_obj):
190
  if not API_KEY:
191
  raise RuntimeError("No API key provided")
192
 
193
- # Resolve file reference name from upload response
194
  file_ref_name = (
195
  uploaded_file_obj.name
196
  if hasattr(uploaded_file_obj, "name")
197
  else uploaded_file_obj.get("name") or uploaded_file_obj.get("id")
198
  )
199
 
200
- # If SDK present, prefer it (some SDKs expose GENAI.responses.generate or http.post)
201
  if HAS_GENAI:
202
  try:
203
- # If SDK exposes a responses.generate style, use it
204
  if hasattr(GENAI, "responses") and hasattr(GENAI.responses, "generate"):
205
  request = {
206
  "model": model_id,
@@ -209,20 +197,11 @@ def call_model_with_file(prompt_text: str, uploaded_file_obj):
209
  "maxOutputTokens": 1000,
210
  }
211
  return GENAI.responses.generate(**request)
212
- # Fallback to http.post if available
213
- if hasattr(GENAI, "http") and hasattr(GENAI.http, "post"):
214
- path = f"/v1beta2/{model_id}:generate"
215
- body = {
216
- "prompt": prompt_text,
217
- "fileReferences": [{"fileName": file_ref_name}],
218
- "safetySettings": safety_settings,
219
- "maxOutputTokens": 1000,
220
- }
221
- return GENAI.http.post(path, json=body)
222
  except Exception:
223
  pass
224
 
225
- # REST fallback use Responses API's generate endpoint.
 
226
  body = {
227
  "input": [
228
  {
@@ -235,33 +214,10 @@ def call_model_with_file(prompt_text: str, uploaded_file_obj):
235
  }
236
  headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
237
 
238
- # Normalize model path: model_id already has "models/" prefix from above normalization
239
- endpoints_to_try = [
240
- f"https://api.generativeai.googleapis.com/v1/{model_id}:generate",
241
- f"https://api.generativeai.googleapis.com/v1/models/{model_id}:generate",
242
- f"https://generative.googleapis.com/v1/{model_id}:generate",
243
- f"https://generative.googleapis.com/v1/models/{model_id}:generate",
244
- # fallback to v1beta2 legacy URLs
245
- f"https://generative.googleapis.com/v1beta2/models/{model_id}:generate",
246
- f"https://generative.googleapis.com/v1beta2/{model_id}:generate",
247
- ]
248
-
249
- last_exc = None
250
- for endpoint in endpoints_to_try:
251
- try:
252
- r = requests.post(endpoint, headers=headers, json=body, timeout=180)
253
- r.raise_for_status()
254
- return r.json()
255
- except requests.HTTPError as e:
256
- last_exc = e
257
- if e.response is not None and e.response.status_code not in (404,):
258
- raise
259
- except Exception as e:
260
- last_exc = e
261
-
262
- raise last_exc or RuntimeError("Failed to call model endpoint")
263
 
264
- # Main action
265
  if st.button("Generate the story", type="primary"):
266
  if not st.session_state.get("videos"):
267
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
@@ -278,7 +234,6 @@ if st.button("Generate the story", type="primary"):
278
  with st.spinner("Generating description..."):
279
  result = call_model_with_file(prompt_text, processed)
280
 
281
- # Result may be SDK object or dict from REST; try extracting text
282
  text_out = ""
283
  if isinstance(result, dict):
284
  if "output" in result:
 
40
  env_api_key = os.getenv("GOOGLE_API_KEY", "")
41
  API_KEY = settings_exp.text_input("Google API Key", value=env_api_key, placeholder="Set GOOGLE_API_KEY in .env or enter here")
42
 
43
+ # Accept short model name like "gemini-2.0-flash-lite" and normalize to "models/..."
44
  raw_model = settings_exp.text_input("Gemini Model (model name)", "gemini-2.0-flash-lite")
45
+ model_id = raw_model.strip() or "gemini-2.0-flash-lite"
46
+ if not model_id.startswith("models/"):
47
  model_id = f"models/{model_id}"
48
 
49
  analysis_prompt = settings_exp.text_area("Enter analysis", "watch entire video and describe")
 
52
  if not API_KEY:
53
  settings_exp.warning("No Google API key provided. Uploading/processing will not work.", icon="⚠️")
54
 
 
55
  safety_settings = [
56
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "OFF"},
57
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "OFF"},
 
94
  raise FileNotFoundError("Downloaded video not found")
95
  return convert_video_to_mp4(matches[0])
96
 
 
97
  if st.sidebar.button("Load Video", use_container_width=True):
98
  try:
99
  video_password = st.session_state.get("video-password", "")
 
102
  except Exception as e:
103
  st.sidebar.error(f"Failed to load video: {e}")
104
 
 
105
  if st.session_state["videos"]:
106
  try:
107
  st.sidebar.video(st.session_state["videos"], loop=st.session_state.get("loop_video", True))
 
134
 
135
  st.sidebar.write("Title:", Path(st.session_state["videos"]).name)
136
 
 
137
  def upload_video(filepath: str):
138
  if not API_KEY:
139
  raise RuntimeError("No API key provided")
140
  if HAS_GENAI and callable(upload_file):
141
  return upload_file(filepath)
 
142
  url = "https://generative.googleapis.com/v1beta2/files?uploadType=multipart"
143
  headers = {"Authorization": f"Bearer {API_KEY}"}
144
  metadata = {"mimeType": "video/mp4", "displayName": Path(filepath).name}
 
150
  r.raise_for_status()
151
  return r.json()
152
 
 
153
  def poll_file_processed(file_obj, timeout=180):
154
  start = time.time()
 
155
  if HAS_GENAI and hasattr(file_obj, "name"):
156
  name = file_obj.name
157
  while getattr(file_obj, "state", None) and getattr(file_obj.state, "name", None) == "PROCESSING":
 
160
  time.sleep(2)
161
  file_obj = get_file(name)
162
  return file_obj
 
163
  fid = file_obj.get("name") or file_obj.get("id")
164
  if not fid:
165
  return file_obj
 
166
  url = f"https://generative.googleapis.com/v1beta2/{fid}"
167
  headers = {"Authorization": f"Bearer {API_KEY}"}
168
  while True:
 
176
  raise TimeoutError("File processing timed out")
177
  time.sleep(2)
178
 
 
179
  def call_model_with_file(prompt_text: str, uploaded_file_obj):
180
  if not API_KEY:
181
  raise RuntimeError("No API key provided")
182
 
 
183
  file_ref_name = (
184
  uploaded_file_obj.name
185
  if hasattr(uploaded_file_obj, "name")
186
  else uploaded_file_obj.get("name") or uploaded_file_obj.get("id")
187
  )
188
 
189
+ # Prefer SDK responses.generate if available
190
  if HAS_GENAI:
191
  try:
 
192
  if hasattr(GENAI, "responses") and hasattr(GENAI.responses, "generate"):
193
  request = {
194
  "model": model_id,
 
197
  "maxOutputTokens": 1000,
198
  }
199
  return GENAI.responses.generate(**request)
 
 
 
 
 
 
 
 
 
 
200
  except Exception:
201
  pass
202
 
203
+ # Use the v1 Responses API host and normalized model_id (models/...)
204
+ endpoint = f"https://api.generativeai.googleapis.com/v1/{model_id}:generate"
205
  body = {
206
  "input": [
207
  {
 
214
  }
215
  headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
216
 
217
+ r = requests.post(endpoint, headers=headers, json=body, timeout=180)
218
+ r.raise_for_status()
219
+ return r.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
 
221
  if st.button("Generate the story", type="primary"):
222
  if not st.session_state.get("videos"):
223
  st.error("No video loaded. Use 'Load Video' in the sidebar.")
 
234
  with st.spinner("Generating description..."):
235
  result = call_model_with_file(prompt_text, processed)
236
 
 
237
  text_out = ""
238
  if isinstance(result, dict):
239
  if "output" in result: