saiteja-coder commited on
Commit
88c69e1
·
verified ·
1 Parent(s): 4fab7fb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import spaces
3
+ import torch
4
+ import json
5
+ import re
6
+ import urllib.request
7
+ import os
8
+ from transformers import AutoProcessor, AutoModelForMultimodalLM
9
+
10
+ MODEL_ID = "google/gemma-4-E2B-it"
11
+
12
+ print(f"Loading {MODEL_ID}...")
13
+ processor = AutoProcessor.from_pretrained(MODEL_ID)
14
+ model = AutoModelForMultimodalLM.from_pretrained(
15
+ MODEL_ID,
16
+ torch_dtype=torch.bfloat16,
17
+ device_map="auto"
18
+ )
19
+ print("Model loaded successfully.")
20
+
21
+ os.makedirs("sample_data", exist_ok=True)
22
+ SAMPLE_IMAGE = "sample_data/car_damage.jpg"
23
+ SAMPLE_AUDIO = "sample_data/driver_statement.wav"
24
+
25
+ if not os.path.exists(SAMPLE_IMAGE):
26
+ urllib.request.urlretrieve(
27
+ "https://www.driving.org/wp-content/uploads/2023/11/driver-hand-examining-dented-car-with-damaged-fend-2023-07-17-20-53-56-utc-e1699944140557.jpg",
28
+ SAMPLE_IMAGE
29
+ )
30
+
31
+ if not os.path.exists(SAMPLE_AUDIO):
32
+ urllib.request.urlretrieve(
33
+ "https://raw.githubusercontent.com/google-gemma/cookbook/refs/heads/main/apps/sample-data/journal1.wav",
34
+ SAMPLE_AUDIO
35
+ )
36
+
37
+ @spaces.GPU
38
+ def process_insurance_claim(image_path, audio_path):
39
+ if not image_path or not audio_path:
40
+ return {"error": "Both an image of the damage and an audio statement are required."}
41
+
42
+ system_prompt = """You are an expert AI Auto Insurance Claim Adjuster.
43
+ Your task is to analyze the provided image of vehicle damage and the audio statement from the driver.
44
+ Cross-reference the audio description with the visual evidence.
45
+ You must output ONLY a valid JSON object. Do not include markdown formatting like ```json.
46
+ The JSON must strictly follow this schema:
47
+ {
48
+ "damage_severity": "Low|Medium|High|Total Loss",
49
+ "affected_parts": ["list", "of", "damaged", "car", "parts"],
50
+ "driver_statement_summary": "Short 1-sentence summary of the audio transcript",
51
+ "consistency_check": "Match|Mismatch",
52
+ "flagged_for_review": true|false,
53
+ "reasoning": "Brief explanation of why it matches or doesn't match the visual evidence."
54
+ }"""
55
+
56
+ messages = [
57
+ {
58
+ "role": "system",
59
+ "content": [
60
+ {"type": "text", "text": system_prompt}
61
+ ]
62
+ },
63
+ {
64
+ "role": "user",
65
+ "content": [
66
+ {"type": "image", "url": image_path},
67
+ {"type": "audio", "audio": audio_path},
68
+ {"type": "text", "text": "Analyze this insurance claim and output the JSON report."}
69
+ ]
70
+ }
71
+ ]
72
+
73
+ inputs = processor.apply_chat_template(
74
+ messages,
75
+ tokenize=True,
76
+ return_dict=True,
77
+ return_tensors="pt",
78
+ add_generation_prompt=True,
79
+ enable_thinking=False
80
+ ).to(model.device)
81
+
82
+ input_len = inputs["input_ids"].shape[-1]
83
+
84
+ outputs = model.generate(
85
+ **inputs,
86
+ max_new_tokens=512,
87
+ temperature=0.2,
88
+ top_p=0.95,
89
+ top_k=64
90
+ )
91
+
92
+ response = processor.decode(outputs[0][input_len:], skip_special_tokens=True)
93
+
94
+ clean_response = re.sub(r"^```(?:json)?\s*", "", response).strip()
95
+ clean_response = re.sub(r"\s*```$", "", clean_response).strip()
96
+
97
+ try:
98
+ json_output = json.loads(clean_response)
99
+ return json_output
100
+ except json.JSONDecodeError:
101
+ return {
102
+ "error": "Failed to parse JSON output.",
103
+ "raw_output": response
104
+ }
105
+
106
+ css = """
107
+ #component-0 { max-width: 900px; margin: auto; }
108
+ .gr-button { background-color: #2563eb !important; color: white !important; }
109
+ """
110
+
111
+ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
112
+ gr.Markdown(
113
+ """
114
+ # 🚗 AI Auto Claim Adjuster (Gemma 4 E2B)
115
+ Upload a photo of the vehicle damage alongside an audio statement from the driver describing the incident.
116
+ Gemma 4 E2B natively processes **both the audio wave and the image** simultaneously, transcribing the story, analyzing the visual damage, and outputting a structured JSON claim adjustment report.
117
+ """
118
+ )
119
+
120
+ with gr.Row():
121
+ with gr.Column(scale=1):
122
+ img_input = gr.Image(type="filepath", label="1. Upload Vehicle Damage Image")
123
+ audio_input = gr.Audio(type="filepath", label="2. Upload Driver Audio Statement")
124
+ submit_btn = gr.Button("Generate Claim Report", size="lg")
125
+
126
+ with gr.Column(scale=1):
127
+ json_output = gr.JSON(label="Structured Claim JSON Output")
128
+
129
+ submit_btn.click(
130
+ fn=process_insurance_claim,
131
+ inputs=[img_input, audio_input],
132
+ outputs=[json_output]
133
+ )
134
+
135
+ gr.Examples(
136
+ examples=[[SAMPLE_IMAGE, SAMPLE_AUDIO]],
137
+ inputs=[img_input, audio_input],
138
+ outputs=[json_output],
139
+ fn=process_insurance_claim,
140
+ cache_examples=False,
141
+ label="Try Demo Example"
142
+ )
143
+
144
+ if __name__ == "__main__":
145
+ demo.launch()