from google.adk.agents import Agent, SequentialAgent, ParallelAgent, LoopAgent
from google.adk.models import Gemini
from google.genai import types, Client
import logging
from typing import Optional
from functools import cached_property
logger = logging.getLogger(__name__)
# --- Custom Gemini Class for Explicit API Key ---
class CustomGemini(Gemini):
api_key: Optional[str] = None
@cached_property
def api_client(self) -> Client:
"""Overrides the default api_client to use the provided API key."""
return Client(
api_key=self.api_key,
http_options=types.HttpOptions(
headers=self._tracking_headers(),
retry_options=self.retry_options,
)
)
# --- Retry Configuration ---
retry_config = types.HttpRetryOptions(
attempts=5, # Maximum retry attempts
exp_base=7, # Delay multiplier
initial_delay=1,
http_status_codes=[429, 500, 503, 504], # Retry on these HTTP errors
)
def get_video_analysis_system(api_key: Optional[str] = None, model_name: str = "gemini-2.1-flash-lite"):
"""
Factory function to create a configured VideoAnalysisSystem.
"""
# Use the custom Gemini class with the provided API key
llm_model = CustomGemini(
model=model_name,
api_key=api_key,
retry_options=retry_config
)
# --- Individual Agents ---
# Context Summary Agent: Provides a neutral summary of the video content.
context_summary_agent = Agent(
name="ContextSummaryAgent",
model=llm_model,
instruction="""
1. Scan the video, caption, and transcript for key entities and events.
2. Identify the main narrative thread or objective of the content.
3. Synthesize the findings into a neutral, objective summary.
Output format: summary: text[1]{text}: "Summary text" """,
)
# Political Bias Agent: Identifies political leaning and quantifies bias.
political_bias_agent = Agent(
name="PoliticalBiasAgent",
model=llm_model,
instruction="""
1. Examine the language used for loaded terms or rhetorical devices.
2. Analyze the context of mentioned political figures or institutions.
3. Determine the leaning (Left/Right/Center) and evaluate the intensity of bias.
Output format: political_bias: details[1]{score,reasoning}: (Int),"Reasoning" """,
)
# Criticism Level Agent: Measures the degree of hostility or support in the tone.
criticism_level_agent = Agent(
name="CriticismLevelAgent",
model=llm_model,
instruction="""
1. Assess the emotional valence of the speaker and visual cues.
2. Identify instances of direct criticism, sarcasm, or praise.
3. Quantify the overall hostility level on a neutral-to-supportive scale.
Output format: criticism_level: details[1]{score,reasoning}: (Int),"Reasoning" """,
)
# Modalities Agent: Evaluates the consistency between video, audio, and text.
modalities_agent = Agent(
name="ModalitiesAgent",
model=llm_model,
instruction="""
1. Compare visual events with audio descriptions for sync issues or contradictions.
2. Verify if the user-provided caption accurately reflects the visual content.
3. Check the transcript against both the audio and the caption for discrepancies.
Output format:
video_audio_pairing: details[1]{score,reasoning}: (Int),"Reasoning"
video_caption_pairing: details[1]{score,reasoning}: (Int),"Reasoning"
audio_caption_pairing: details[1]{score,reasoning}: (Int),"Reasoning" """,
)
# Disinformation Agent: Analyzes potential manipulation and threat levels.
disinformation_agent = Agent(
name="DisinformationAgent",
model=llm_model,
instruction="""
1. Search for signs of technical manipulation (deepfakes, AI artifacts).
2. Analyze the intent behind potential misinformation (Political/Commercial).
3. Evaluate the risk level and the specific threat vector used.
Output format: disinformation_analysis: details[1]{level,intent,threat_vector}: (Int),(Intent),(Vector) """,
)
# Sentiment Bias Agent: Captures the overall emotional tone and inherent bias.
sentiment_bias_agent = Agent(
name="SentimentBiasAgent",
model=llm_model,
instruction="""
1. Aggregate the emotional signals from the entire video duration.
2. Identify recurring biased patterns or slanted perspectives.
3. Synthesize a comprehensive overview of the sentiment and bias.
Output format: sentiment_and_bias: text[1]{text}: "Synthesis text" """,
)
# --- Agent Grouping ---
# The ParallelAgent runs all its sub-agents simultaneously.
analysis_team = ParallelAgent(
name="AnalysisTeam",
sub_agents=[
context_summary_agent,
political_bias_agent,
criticism_level_agent,
modalities_agent,
disinformation_agent,
sentiment_bias_agent
],
)
# This SequentialAgent defines the high-level workflow.
system = SequentialAgent(
name="VideoAnalysisSystem",
sub_agents=[analysis_team],
)
return system
if __name__ == "__main__":
system = get_video_analysis_system()
print("Video Analysis Agent System created successfully.")