saakshigupta commited on
Commit
e1419e7
Β·
verified Β·
1 Parent(s): d11c6ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -33
app.py CHANGED
@@ -8,9 +8,71 @@ import tempfile
8
  import os
9
 
10
  # App title and description
11
- st.set_page_config(page_title="Deepfake Analyzer", layout="wide")
 
 
 
 
 
 
12
  st.title("Deepfake Image Analyzer")
13
- st.markdown("Upload an image to analyze it for potential deepfake manipulation")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  # Function to fix cross-attention masks
16
  def fix_cross_attention_mask(inputs):
@@ -26,8 +88,11 @@ def fix_cross_attention_mask(inputs):
26
  # Load model function
27
  @st.cache_resource
28
  def load_model():
29
- with st.spinner("Loading model... This may take a minute or two..."):
30
  try:
 
 
 
31
  # Load base model and tokenizer using Unsloth
32
  base_model_id = "unsloth/llama-3.2-11b-vision-instruct"
33
  model, tokenizer = FastVisionModel.from_pretrained(
@@ -48,12 +113,18 @@ def load_model():
48
  return None, None
49
 
50
  # Analyze image function
51
- def analyze_image(image, question, model, tokenizer):
 
 
 
 
 
 
52
  # Format the message
53
  messages = [
54
  {"role": "user", "content": [
55
  {"type": "image"},
56
- {"type": "text", "text": question}
57
  ]}
58
  ]
59
 
@@ -72,13 +143,13 @@ def analyze_image(image, question, model, tokenizer):
72
  inputs = fix_cross_attention_mask(inputs)
73
 
74
  # Generate response
75
- with st.spinner("Analyzing image... (this may take a moment)"):
76
  with torch.no_grad():
77
  output_ids = model.generate(
78
  **inputs,
79
- max_new_tokens=512,
80
  use_cache=True,
81
- temperature=0.7,
82
  top_p=0.9
83
  )
84
 
@@ -86,8 +157,8 @@ def analyze_image(image, question, model, tokenizer):
86
  response = tokenizer.decode(output_ids[0], skip_special_tokens=True)
87
 
88
  # Try to extract just the model's response (after the prompt)
89
- if question in response:
90
- result = response.split(question)[-1].strip()
91
  else:
92
  result = response
93
 
@@ -95,34 +166,81 @@ def analyze_image(image, question, model, tokenizer):
95
 
96
  # Main app
97
  def main():
98
- # Load model
99
- model, tokenizer = load_model()
 
 
 
100
 
101
- if model is not None and tokenizer is not None:
 
 
 
 
 
 
 
 
 
 
 
102
  st.success("βœ… Model loaded successfully! You can now analyze images.")
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- # Image upload section
105
- st.subheader("Upload an Image")
106
- uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
107
-
108
- # Default question with option to customize
109
- default_question = "Analyze this image and tell me if it's a deepfake. Provide both technical and non-technical explanations."
110
- question = st.text_area("Question/Prompt:", value=default_question, height=100)
111
-
112
- if uploaded_file is not None:
113
- # Display the uploaded image
114
- image = Image.open(uploaded_file).convert("RGB")
115
- st.image(image, caption="Uploaded Image", use_column_width=True)
116
-
117
- # Analyze button
118
- if st.button("Analyze Image"):
119
- result = analyze_image(image, question, model, tokenizer)
120
 
121
  # Display results
122
- st.subheader("Analysis Results")
123
- st.markdown(result)
124
- else:
125
- st.warning("Failed to load the model. Please check the console for errors.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  if __name__ == "__main__":
128
  main()
 
8
  import os
9
 
10
  # App title and description
11
+ st.set_page_config(
12
+ page_title="Deepfake Analyzer",
13
+ layout="wide",
14
+ page_icon="πŸ”"
15
+ )
16
+
17
+ # Main title and description
18
  st.title("Deepfake Image Analyzer")
19
+ st.markdown("Upload an image to analyze it for possible deepfake manipulation")
20
+
21
+ # Check for GPU availability
22
+ def check_gpu():
23
+ if torch.cuda.is_available():
24
+ gpu_info = torch.cuda.get_device_properties(0)
25
+ st.sidebar.success(f"βœ… GPU available: {gpu_info.name} ({gpu_info.total_memory / (1024**3):.2f} GB)")
26
+ return True
27
+ else:
28
+ st.sidebar.warning("⚠️ No GPU detected. Analysis will be slower.")
29
+ return False
30
+
31
+ # Sidebar components
32
+ st.sidebar.title("Options")
33
+
34
+ # Temperature slider
35
+ temperature = st.sidebar.slider(
36
+ "Temperature",
37
+ min_value=0.1,
38
+ max_value=1.0,
39
+ value=0.7,
40
+ step=0.1,
41
+ help="Higher values make output more random, lower values more deterministic"
42
+ )
43
+
44
+ # Max response length slider
45
+ max_tokens = st.sidebar.slider(
46
+ "Maximum Response Length",
47
+ min_value=100,
48
+ max_value=1000,
49
+ value=500,
50
+ step=50,
51
+ help="The maximum number of tokens in the response"
52
+ )
53
+
54
+ # Custom instruction text area in sidebar
55
+ custom_instruction = st.sidebar.text_area(
56
+ "Custom Instructions (Advanced)",
57
+ value="Analyze for facial inconsistencies, lighting irregularities, mismatched shadows, and other signs of manipulation.",
58
+ help="Add specific instructions for the model"
59
+ )
60
+
61
+ # About section in sidebar
62
+ st.sidebar.markdown("---")
63
+ st.sidebar.subheader("About")
64
+ st.sidebar.markdown("""
65
+ This analyzer looks for:
66
+ - Facial inconsistencies
67
+ - Unnatural movements
68
+ - Lighting issues
69
+ - Texture anomalies
70
+ - Edge artifacts
71
+ - Blending problems
72
+
73
+ **Model**: Fine-tuned Llama 3.2 Vision
74
+ **Creator**: [Saakshi Gupta](https://huggingface.co/saakshigupta)
75
+ """)
76
 
77
  # Function to fix cross-attention masks
78
  def fix_cross_attention_mask(inputs):
 
88
  # Load model function
89
  @st.cache_resource
90
  def load_model():
91
+ with st.spinner("Loading model... This may take a few minutes. Please be patient..."):
92
  try:
93
+ # Check for GPU
94
+ has_gpu = check_gpu()
95
+
96
  # Load base model and tokenizer using Unsloth
97
  base_model_id = "unsloth/llama-3.2-11b-vision-instruct"
98
  model, tokenizer = FastVisionModel.from_pretrained(
 
113
  return None, None
114
 
115
  # Analyze image function
116
+ def analyze_image(image, question, model, tokenizer, temperature=0.7, max_tokens=500, custom_instruction=""):
117
+ # Combine question with custom instruction if provided
118
+ if custom_instruction.strip():
119
+ full_prompt = f"{question}\n\nAdditional instructions: {custom_instruction}"
120
+ else:
121
+ full_prompt = question
122
+
123
  # Format the message
124
  messages = [
125
  {"role": "user", "content": [
126
  {"type": "image"},
127
+ {"type": "text", "text": full_prompt}
128
  ]}
129
  ]
130
 
 
143
  inputs = fix_cross_attention_mask(inputs)
144
 
145
  # Generate response
146
+ with st.spinner("Analyzing image... (this may take 15-30 seconds)"):
147
  with torch.no_grad():
148
  output_ids = model.generate(
149
  **inputs,
150
+ max_new_tokens=max_tokens,
151
  use_cache=True,
152
+ temperature=temperature,
153
  top_p=0.9
154
  )
155
 
 
157
  response = tokenizer.decode(output_ids[0], skip_special_tokens=True)
158
 
159
  # Try to extract just the model's response (after the prompt)
160
+ if full_prompt in response:
161
+ result = response.split(full_prompt)[-1].strip()
162
  else:
163
  result = response
164
 
 
166
 
167
  # Main app
168
  def main():
169
+ # Create a button to load the model
170
+ if 'model_loaded' not in st.session_state:
171
+ st.session_state.model_loaded = False
172
+ st.session_state.model = None
173
+ st.session_state.tokenizer = None
174
 
175
+ # Load model button
176
+ if not st.session_state.model_loaded:
177
+ if st.button("πŸ“₯ Load Deepfake Analysis Model", type="primary"):
178
+ model, tokenizer = load_model()
179
+ if model is not None and tokenizer is not None:
180
+ st.session_state.model = model
181
+ st.session_state.tokenizer = tokenizer
182
+ st.session_state.model_loaded = True
183
+ st.success("βœ… Model loaded successfully! You can now analyze images.")
184
+ else:
185
+ st.error("❌ Failed to load model. Please check the logs for errors.")
186
+ else:
187
  st.success("βœ… Model loaded successfully! You can now analyze images.")
188
+
189
+ # Image upload section
190
+ st.subheader("Upload an Image")
191
+ uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
192
+
193
+ # Default question with option to customize
194
+ default_question = "Analyze this image and tell me if it's a deepfake. Provide both technical and non-technical explanations."
195
+ question = st.text_area("Question/Prompt:", value=default_question, height=100)
196
+
197
+ if uploaded_file is not None:
198
+ # Display the uploaded image
199
+ image = Image.open(uploaded_file).convert("RGB")
200
+ st.image(image, caption="Uploaded Image", use_column_width=True)
201
 
202
+ # Analyze button - only enabled if model is loaded
203
+ if st.session_state.model_loaded:
204
+ if st.button("πŸ” Analyze Image", type="primary"):
205
+ result = analyze_image(
206
+ image,
207
+ question,
208
+ st.session_state.model,
209
+ st.session_state.tokenizer,
210
+ temperature=temperature,
211
+ max_tokens=max_tokens,
212
+ custom_instruction=custom_instruction
213
+ )
 
 
 
 
214
 
215
  # Display results
216
+ st.success("βœ… Analysis complete!")
217
+
218
+ # Check if the result contains both technical and non-technical explanations
219
+ if "Technical" in result and "Non-Technical" in result:
220
+ # Split the result into technical and non-technical sections
221
+ parts = result.split("Non-Technical")
222
+ technical = parts[0]
223
+ non_technical = "Non-Technical" + parts[1]
224
+
225
+ # Display in two columns
226
+ col1, col2 = st.columns(2)
227
+ with col1:
228
+ st.subheader("Technical Analysis")
229
+ st.markdown(technical)
230
+
231
+ with col2:
232
+ st.subheader("Simple Explanation")
233
+ st.markdown(non_technical)
234
+ else:
235
+ # Just display the whole result
236
+ st.subheader("Analysis Result")
237
+ st.markdown(result)
238
+ else:
239
+ st.warning("⚠️ Please load the model first before analyzing images.")
240
+
241
+ # Footer
242
+ st.markdown("---")
243
+ st.caption("Deepfake Image Analyzer")
244
 
245
  if __name__ == "__main__":
246
  main()