vivek9chavan commited on
Commit
ccd7572
·
verified ·
1 Parent(s): 88a06ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -60
app.py CHANGED
@@ -17,25 +17,20 @@ try:
17
  except KeyError:
18
  raise gr.Error("FATAL: GEMINI_API_KEY not found. Please set it in your Hugging Face Space secrets.")
19
 
20
- # --- Main Gradio Function ---
21
  def full_analysis(video_file_path, user_observations):
22
  if not video_file_path:
23
- # Return empty values for all components
24
- return "Please upload a video first.", "", "", None, None
 
25
 
26
- # --- DINO Analysis (runs in parallel with Gemini upload) ---
27
- print("--- Starting DINO Analysis ---")
28
- try:
29
- dino_results = process_video_with_dino(video_file_path)
30
- overlay_images = [res[0] for res in dino_results]
31
- attention_maps = [res[1] for res in dino_results]
32
- print("--- DINO Analysis Complete ---")
33
- except Exception as e:
34
- print(f"ERROR during DINO processing: {e}")
35
- return f"Error in DINO processing: {e}", "", "", None, None
36
 
37
- # --- Gemini Analysis ---
38
- print("--- Starting Gemini Analysis ---")
39
  uploaded_file = None
40
  try:
41
  uploaded_file = client.files.upload(file=video_file_path)
@@ -45,42 +40,22 @@ def full_analysis(video_file_path, user_observations):
45
  if uploaded_file.state.name != "ACTIVE":
46
  raise Exception(f"File processing failed for Gemini. State: {uploaded_file.state.name}")
47
 
48
- # --- NEW, MORE ADVANCED PROMPT ---
49
  prompt = f"""
50
  Analyze the provided video and the user's observations. Respond ONLY with a valid JSON object.
51
-
52
  User Observations: "{user_observations if user_observations else 'None'}"
53
-
54
  Follow these steps:
55
- 1. First, identify the primary object in the video. Is it an electronic device or a white good (e.g., refrigerator, washing machine, microwave)?
56
- 2. If it IS an electronic device or white good, respond with a JSON object with these three keys:
57
- - "device_type": A short string identifying the specific device (e.g., "iPhone 13 Pro", "Samsung Washing Machine").
58
- - "condition": A single word describing its visual condition. Choose ONLY from: "unusable", "poor", "functional", "good", "excellent".
59
- - "reason": A very brief, concise string explaining the condition (e.g., "heavy screen cracks", "minor scratches on body", "clean with no visible marks").
60
- 3. If it is NOT an electronic device or white good, respond with a JSON object with only ONE key:
61
- - "device_type": A string starting with "Invalid: " followed by the object's category (e.g., "Invalid: Water Bottle", "Invalid: Shoe").
62
-
63
- Example for a valid device:
64
- {{
65
- "device_type": "Dell XPS Laptop",
66
- "condition": "functional",
67
- "reason": "Visible scratches and paint erosion on the lid."
68
- }}
69
-
70
- Example for an invalid object:
71
- {{
72
- "device_type": "Invalid: Coffee Mug"
73
- }}
74
  """
75
 
76
- model_name = "gemini-1.5-flash-latest"
77
  config = types.GenerateContentConfig(temperature=0.2, response_mime_type="application/json")
78
  contents = [uploaded_file, prompt]
79
 
80
  response = client.models.generate_content(model=f"models/{model_name}", contents=contents, config=config)
81
  parsed_json = json.loads(response.text)
82
 
83
- # Check if the device was valid or not
84
  device_type = parsed_json.get("device_type", "N/A")
85
  if "Invalid:" in device_type:
86
  condition = "N/A"
@@ -89,7 +64,7 @@ def full_analysis(video_file_path, user_observations):
89
  condition = parsed_json.get("condition", "N/A")
90
  reason = parsed_json.get("reason", "N/A")
91
 
92
- print("--- Gemini Analysis Complete ---")
93
 
94
  except Exception as e:
95
  print(f"ERROR during Gemini processing: {e}")
@@ -98,46 +73,58 @@ def full_analysis(video_file_path, user_observations):
98
  if uploaded_file:
99
  client.files.delete(name=uploaded_file.name)
100
 
101
- # Return all the results to the Gradio UI
102
- return device_type, condition, reason, overlay_images, attention_maps
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # --- Gradio Interface ---
105
- # Define a custom theme
106
  theme = gr.themes.Soft(
107
- primary_hue="green",
108
- secondary_hue="emerald",
109
  ).set(
110
- body_background_fill="#E0F2F1", # A light aquatic green
111
- block_background_fill="white",
112
- block_border_width="1px",
113
- block_shadow="*shadow_drop_lg",
114
- button_primary_background_fill="*primary_500",
115
- button_primary_text_color="white",
116
  )
117
 
118
  with gr.Blocks(theme=theme) as demo:
119
- # Using a refrigerator emoji for white goods 🧊 or 🔌
120
  gr.Markdown("# 🧊 KIKERP: AI Assessment Tool")
121
  gr.Markdown("Upload a video of a device or white good for a complete visual and AI-driven analysis.")
122
 
123
  with gr.Row():
124
  with gr.Column(scale=1):
125
  video_input = gr.Video(label="Upload or Record Video", sources=["upload", "webcam"], format="mp4")
126
- # NEW: Optional text input for user observations
127
  observations_input = gr.Textbox(
128
  label="Optional: User Observations",
129
- placeholder="e.g., Device overheats, screen flickers, makes a strange noise..."
130
  )
131
  submit_button = gr.Button("Run Full Analysis", variant="primary")
132
 
133
  with gr.Column(scale=2):
134
- gr.Markdown("## Gemini Condition Analysis")
135
  with gr.Row():
136
- device_type_output = gr.Textbox(label="Device Type")
137
- condition_output = gr.Textbox(label="Condition")
138
- reason_output = gr.Textbox(label="Reason / Details")
139
 
140
- gr.Markdown("---") # Adds a horizontal line for separation
141
 
142
  gr.Markdown("## DINO: Visual Feature Analysis")
143
  with gr.Row():
@@ -148,9 +135,10 @@ with gr.Blocks(theme=theme) as demo:
148
  gr.Markdown("### Self-Attention Maps")
149
  attention_gallery = gr.Gallery(label="Self-Attention Maps", elem_id="gallery", columns=5)
150
 
 
 
151
  submit_button.click(
152
  fn=full_analysis,
153
- # Add the new observations_input to the inputs list
154
  inputs=[video_input, observations_input],
155
  outputs=[
156
  device_type_output,
 
17
  except KeyError:
18
  raise gr.Error("FATAL: GEMINI_API_KEY not found. Please set it in your Hugging Face Space secrets.")
19
 
20
+ # --- Main Gradio Generator Function ---
21
  def full_analysis(video_file_path, user_observations):
22
  if not video_file_path:
23
+ # Yield a single update and stop
24
+ yield "Please upload a video first.", "", "", None, None
25
+ return
26
 
27
+ # --- Stage 1: Gemini Analysis (Fast) ---
28
+ print("--- Starting Device Analysis ---")
29
+ device_type, condition, reason = "Processing...", "Processing...", "Processing..."
30
+
31
+ # Immediately update the UI to show that Gemini is working
32
+ yield device_type, condition, reason, None, None
 
 
 
 
33
 
 
 
34
  uploaded_file = None
35
  try:
36
  uploaded_file = client.files.upload(file=video_file_path)
 
40
  if uploaded_file.state.name != "ACTIVE":
41
  raise Exception(f"File processing failed for Gemini. State: {uploaded_file.state.name}")
42
 
 
43
  prompt = f"""
44
  Analyze the provided video and the user's observations. Respond ONLY with a valid JSON object.
 
45
  User Observations: "{user_observations if user_observations else 'None'}"
 
46
  Follow these steps:
47
+ 1. Identify the primary object. Is it an electronic device or a white good?
48
+ 2. If YES, respond with a JSON object with keys: "device_type", "condition" (choose from "unusable", "poor", "functional", "good", "excellent"), and "reason" (a brief explanation).
49
+ 3. If NO, respond with a JSON object with only ONE key: "device_type" starting with "Invalid: " (e.g., "Invalid: Water Bottle").
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  """
51
 
52
+ model_name = "gemini-2.5-flash"
53
  config = types.GenerateContentConfig(temperature=0.2, response_mime_type="application/json")
54
  contents = [uploaded_file, prompt]
55
 
56
  response = client.models.generate_content(model=f"models/{model_name}", contents=contents, config=config)
57
  parsed_json = json.loads(response.text)
58
 
 
59
  device_type = parsed_json.get("device_type", "N/A")
60
  if "Invalid:" in device_type:
61
  condition = "N/A"
 
64
  condition = parsed_json.get("condition", "N/A")
65
  reason = parsed_json.get("reason", "N/A")
66
 
67
+ print("--- Device Analysis Complete ---")
68
 
69
  except Exception as e:
70
  print(f"ERROR during Gemini processing: {e}")
 
73
  if uploaded_file:
74
  client.files.delete(name=uploaded_file.name)
75
 
76
+ # --- YIELD 1: Update UI with Gemini results ---
77
+ # The DINO galleries are still empty (None) at this point.
78
+ yield device_type, condition, reason, None, None
79
+
80
+ # --- Stage 2: DINO Analysis (Slow) ---
81
+ print("--- Starting DINO Analysis ---")
82
+ try:
83
+ dino_results = process_video_with_dino(video_file_path)
84
+ overlay_images = [res[0] for res in dino_results]
85
+ attention_maps = [res[1] for res in dino_results]
86
+ print("--- DINO Analysis Complete ---")
87
+ except Exception as e:
88
+ print(f"ERROR during DINO processing: {e}")
89
+ # If DINO fails, we still want to keep the Gemini results.
90
+ # We can update one of the text fields to show the DINO error.
91
+ reason += f" | DINO Error: {e}"
92
+ overlay_images, attention_maps = None, None
93
+
94
+ # --- YIELD 2: Final update with all results ---
95
+ # This updates the galleries with the DINO images.
96
+ yield device_type, condition, reason, overlay_images, attention_maps
97
 
98
  # --- Gradio Interface ---
 
99
  theme = gr.themes.Soft(
100
+ primary_hue="green", secondary_hue="emerald"
 
101
  ).set(
102
+ body_background_fill="#E0F2F1", block_background_fill="white",
103
+ block_border_width="1px", block_shadow="*shadow_drop_lg",
104
+ button_primary_background_fill="*primary_500", button_primary_text_color="white",
 
 
 
105
  )
106
 
107
  with gr.Blocks(theme=theme) as demo:
 
108
  gr.Markdown("# 🧊 KIKERP: AI Assessment Tool")
109
  gr.Markdown("Upload a video of a device or white good for a complete visual and AI-driven analysis.")
110
 
111
  with gr.Row():
112
  with gr.Column(scale=1):
113
  video_input = gr.Video(label="Upload or Record Video", sources=["upload", "webcam"], format="mp4")
 
114
  observations_input = gr.Textbox(
115
  label="Optional: User Observations",
116
+ placeholder="e.g., Device overheats, screen flickers..."
117
  )
118
  submit_button = gr.Button("Run Full Analysis", variant="primary")
119
 
120
  with gr.Column(scale=2):
121
+ gr.Markdown("## Device Condition Analysis")
122
  with gr.Row():
123
+ device_type_output = gr.Textbox(label="Device Type", interactive=False)
124
+ condition_output = gr.Textbox(label="Condition", interactive=False)
125
+ reason_output = gr.Textbox(label="Reason / Details", interactive=False)
126
 
127
+ gr.Markdown("---")
128
 
129
  gr.Markdown("## DINO: Visual Feature Analysis")
130
  with gr.Row():
 
135
  gr.Markdown("### Self-Attention Maps")
136
  attention_gallery = gr.Gallery(label="Self-Attention Maps", elem_id="gallery", columns=5)
137
 
138
+ # The .click() event now points to a generator function.
139
+ # Gradio will automatically handle the multiple `yield` statements.
140
  submit_button.click(
141
  fn=full_analysis,
 
142
  inputs=[video_input, observations_input],
143
  outputs=[
144
  device_type_output,