Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions src/processing_pipeline/stage_3.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from datetime import datetime, timezone
from datetime import datetime
from http import HTTPStatus
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Importing HTTPStatus is a good addition for handling specific HTTP error codes, which enhances the clarity and maintainability of the error handling logic.

import os
import time
from google import genai
from google.genai import errors
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Importing google.genai.errors is crucial for catching specific API errors, allowing for more granular error handling and the implementation of the fallback mechanism.

import json
import boto3
from pydantic import ValidationError
Expand Down Expand Up @@ -140,16 +142,52 @@ def __get_metadata(snippet):


@optional_task(log_prints=True)
def process_snippet(supabase_client, snippet, local_file, gemini_key, skip_review: bool):
def analyze_snippet(gemini_key, audio_file, metadata):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new analyze_snippet function effectively encapsulates the logic for calling the Gemini API, including the primary and fallback model attempts. This improves modularity and makes the process_snippet function cleaner.

main_model = GeminiModel.GEMINI_2_5_PRO
fallback_model = GeminiModel.GEMINI_FLASH_LATEST
Comment on lines +146 to +147
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Defining main_model and fallback_model as variables at the beginning of the function makes it clear which models are being used and allows for easy modification if needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the fallback model matches the PR objective.

The PR title specifies "Gemini 2.5 Flash Latest" as the fallback model, but the code uses GEMINI_FLASH_LATEST which maps to "gemini-flash-latest". From the constants file, there's also GEMINI_2_5_FLASH = "gemini-2.5-flash". Please confirm whether GEMINI_FLASH_LATEST is the correct model or if you intended to use a model that explicitly identifies as version 2.5.


🌐 Web query:

What is the difference between Google Gemini models "gemini-flash-latest" and "gemini-2.5-flash"?

💡 Result:

Short answer: gemini-flash-latest is an alias that always points to the most recent "flash" release (it can be stable, preview or experimental and may be hot‑swapped), whereas gemini-2.5-flash is the specific stable Gemini 2.5 Flash model (a fixed release with documented capabilities and limits). [1][2]

Details (concise):

  • Alias vs fixed name: gemini-flash-latest = latest release alias; gemini-2.5-flash = specific stable model. [1].
  • Capabilities/token limits: Gemini 2.5 Flash (gemini-2.5-flash) documents a 1,048,576 input token limit and 65,536 output token limit and lists its supported modalities and features. Use the stable model string for production to avoid unexpected changes from alias updates. [1][2]

Sources:
[1] Google Gemini models (model/version naming & gemini-2.5-flash).
[2] Google Gemini models (description of "latest" alias and guidance).


Clarify fallback model intent—consider using the stable model for production consistency.

The PR title states "Gemini 2.5 Flash Latest," but the code uses GEMINI_FLASH_LATEST which is an alias that can change and may not always remain Gemini 2.5. The specific gemini-2.5-flash model is the stable Gemini 2.5 Flash version with documented capabilities and limits, whereas gemini-flash-latest is a rolling alias that can be hot-swapped and may be preview or experimental.

If your intent is to use Gemini 2.5 Flash specifically (as the PR title suggests), consider using GEMINI_2_5_FLASH instead to ensure consistent, documented behavior in production. If the alias is intentional, update the PR title to clarify that you want the latest flash model regardless of version.

🤖 Prompt for AI Agents
In src/processing_pipeline/stage_3.py around line 147, the fallback_model is set
to the rolling alias GEMINI_FLASH_LATEST which can change; if the intent is to
pin to the stable Gemini 2.5 Flash for production consistency, replace the alias
with the explicit GEMINI_2_5_FLASH constant (or the string identifier for
gemini-2.5-flash) so the code always selects that stable model; if you
intentionally want the rolling latest, update the PR title/message to state that
fact instead of referencing Gemini 2.5 Flash.


try:
print(f"Processing snippet: {local_file} with Gemini 2.5 Flash")
print(f"Attempting analysis with {main_model}")
return Stage3Executor.run(
gemini_key=gemini_key,
model_name=main_model,
audio_file=audio_file,
metadata=metadata,
)
except errors.ServerError as e:
print(f"Server error with {main_model} (code {e.code}): {e.message}")
print(f"Falling back to {fallback_model}")
return Stage3Executor.run(
gemini_key=gemini_key,
model_name=fallback_model,
audio_file=audio_file,
metadata=metadata,
)
Comment on lines +157 to +165
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Handling errors.ServerError by falling back to fallback_model is a good strategy to improve the resilience of the system against transient server-side issues. This prevents complete failure and increases the chances of successful processing.

except errors.ClientError as e:
if e.code in [HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN]:
print(f"Auth error with {main_model} (code {e.code}): {e.message}")
raise
else:
print(f"Client error with {main_model} (code {e.code}): {e.message}")
print(f"Falling back to {fallback_model}")
return Stage3Executor.run(
gemini_key=gemini_key,
model_name=fallback_model,
audio_file=audio_file,
metadata=metadata,
)
Comment on lines +166 to +178
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The ClientError handling distinguishes between authentication/authorization errors (which should raise immediately) and other client errors, for which a fallback is attempted. This is a robust approach to error management, ensuring that critical configuration issues are surfaced quickly while other client-side problems can leverage the fallback.



@optional_task(log_prints=True)
def process_snippet(supabase_client, snippet, local_file, gemini_key, skip_review: bool):
print(f"Processing snippet: {local_file}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The print statement is now more generic, as the model name is handled within the analyze_snippet function. This keeps the logging consistent with the new modular structure.

print(f"Processing snippet: {local_file}")


try:
metadata = get_metadata(snippet)
print(f"Metadata:\n{json.dumps(metadata, indent=2, ensure_ascii=False)}")

response, grounding_metadata = Stage3Executor.run(
response, grounding_metadata = analyze_snippet(
gemini_key=gemini_key,
model_name=GeminiModel.GEMINI_2_5_PRO,
audio_file=local_file,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use consistent naming for the audio file parameter (audio_file vs local_file) for clarity.

metadata=metadata,
)
Expand Down