danielle2003 commited on
Commit
d117f2c
Β·
verified Β·
1 Parent(s): ab5ec73

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +201 -0
app.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, RTCConfiguration
3
+ import av
4
+ import cv2
5
+ from pyzbar import pyzbar
6
+ import google.generativeai as genai
7
+ from google.generativeai import protos
8
+ import threading
9
+ import time
10
+ import json
11
+ import re
12
+ from google import genai
13
+ from google.genai import types
14
+ # ----------------------------
15
+ # App Configuration
16
+ # ----------------------------
17
+ st.set_page_config(
18
+ page_title="Real-Time Drug Code Verifier",
19
+ page_icon="πŸ”",
20
+ layout="wide"
21
+ )
22
+
23
+ # ----------------------------
24
+ # API Key Setup
25
+ # ----------------------------
26
+ # It's recommended to use st.secrets for API keys in a deployed app
27
+ GOOGLE_API_KEY = "AIzaSyAXFL0YdFIKUNISOQuV9FH-JTSnMC3PSMA"
28
+
29
+ # Load key from secrets
30
+ try:
31
+ if not GOOGLE_API_KEY:
32
+ GOOGLE_API_KEY = st.secrets["GOOGLE_API_KEY"]
33
+ except (FileNotFoundError, KeyError):
34
+ st.error("πŸ”‘ GOOGLE_API_KEY not found. Please add it to your Streamlit secrets.")
35
+ st.stop()
36
+
37
+ #.configure(api_key=GOOGLE_API_KEY)
38
+ client = genai.Client(api_key=GOOGLE_API_KEY)
39
+ # Define the grounding tool
40
+ grounding_tool = types.Tool(
41
+ google_search=types.GoogleSearch()
42
+ )
43
+
44
+ # Configure generation settings
45
+ config = types.GenerateContentConfig(
46
+ tools=[grounding_tool]
47
+ )
48
+
49
+
50
+ # ----------------------------
51
+ # Main Gemini Verification Function
52
+ # ----------------------------
53
+ @st.cache_data(show_spinner=False)
54
+ def verify_code_with_gemini(code: str, barcode_type: str):
55
+ """
56
+ Verifies a product code by letting Gemini use its native Google Search tool.
57
+ """
58
+ # Define the built-in Google Search tool using the specific syntax required by the library
59
+
60
+
61
+ prompt = f"""
62
+ You are a product verification assistant. A user has scanned a product with the code '{code}' (type: {barcode_type}).
63
+ Your goal is to use your built-in Google Search tool to augment your own knowledge and provide a comprehensive analysis.
64
+
65
+ Follow these steps:
66
+ 1. Use your search tool to find information about the provided barcode and product type. This will give you real-time context.
67
+ 2. Combine the information from the web search with your own general knowledge about products, manufacturers, and barcode standards.
68
+ 3. Provide a detailed summary. This should include the likely product name, manufacturer, and a well-reasoned assessment of the code's authenticity. If the search results are inconclusive or suspicious, use your own knowledge to explain why (e.g., "This barcode format is unusual for this type of product," or "No major retailers list this code, which is suspicious.").
69
+ 4. From the search results, find the best, most representative image URL for the product. If no good image is found, return an empty string.
70
+ 5. IMPORTANT: Your final output MUST be ONLY the raw JSON object. Do not include ```json``` markers or any other explanatory text.
71
+
72
+ Example Output:
73
+ {{
74
+ "summary_text": "This EAN-13 code corresponds to 'Product Name' by 'Manufacturer'. The code format is valid and listed by several major retailers in the search results, suggesting it is authentic. No recalls or warnings were found.",
75
+ "image_url": "https://example.com/product_image.jpg"
76
+ }}
77
+ """
78
+ response = None # Initialize response to None
79
+ try:
80
+ st.write("🧠 Generating content with Gemini and Google Search...")
81
+ response = client.models.generate_content(
82
+ model="gemini-2.5-flash",
83
+ contents=prompt,
84
+ config=config,
85
+ )
86
+ st.write("βœ… Gemini response received. Parsing JSON...")
87
+ # Extract JSON from the response text, which might be wrapped in markdown
88
+ raw_text = response.text
89
+ json_match = re.search(r'\{.*\}', raw_text, re.DOTALL)
90
+
91
+ if json_match:
92
+ json_str = json_match.group(0)
93
+ result_data = json.loads(json_str)
94
+ st.write("πŸ‘ JSON parsed successfully!")
95
+ return result_data
96
+ else:
97
+ st.write("❌ No JSON object found in the response.")
98
+ return {
99
+ "summary_text": "Verification failed: The AI did not return a valid JSON object.",
100
+ "image_url": "",
101
+ "raw_response": raw_text
102
+ }
103
+
104
+ except Exception as e:
105
+ st.write(f"❌ An error occurred: {e}")
106
+ raw_response_text = response.text if response else "No response from model."
107
+ return {
108
+ "summary_text": f"An error occurred during verification. Please check the details below.",
109
+ "image_url": "",
110
+ "error_details": str(e),
111
+ "raw_response": raw_response_text
112
+ }
113
+
114
+ # ----------------------------
115
+ # Video Processing Class
116
+ # ----------------------------
117
+ class QRCodeScanner(VideoProcessorBase):
118
+ def __init__(self):
119
+ self.result = None
120
+ self.lock = threading.Lock()
121
+
122
+ def recv(self, frame: av.VideoFrame) -> av.VideoFrame:
123
+ image = frame.to_ndarray(format="bgr24")
124
+ decoded_objects = pyzbar.decode(image)
125
+
126
+ for obj in decoded_objects:
127
+ code_data = obj.data.decode("utf-8")
128
+ code_type = obj.type
129
+
130
+ with self.lock:
131
+ self.result = {"data": code_data, "type": code_type}
132
+
133
+ (x, y, w, h) = obj.rect
134
+ cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
135
+ text = f"Detected: {code_data}"
136
+ cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
137
+ break
138
+
139
+ return av.VideoFrame.from_ndarray(image, format="bgr24")
140
+
141
+ # ----------------------------
142
+ # Streamlit UI
143
+ # ----------------------------
144
+ st.title("πŸ” Real-Time Drug Code Verifier with AI Search")
145
+ st.markdown("Point a product's barcode or QR code at the camera. The app will use Gemini AI with Google Search to verify its authenticity.")
146
+
147
+ if "code_found" not in st.session_state:
148
+ st.session_state.update({"code_found": False, "last_code_data": "", "last_code_type": ""})
149
+
150
+ if not st.session_state["code_found"]:
151
+ st.subheader("πŸ“· Camera Feed")
152
+ webrtc_ctx = webrtc_streamer(
153
+ key="scanner",
154
+ video_processor_factory=QRCodeScanner,
155
+ rtc_configuration=RTCConfiguration({"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]}),
156
+ media_stream_constraints={"video": True, "audio": False},
157
+ async_processing=True,
158
+ )
159
+ st.info("The camera will stop automatically once a code is detected.")
160
+
161
+ if webrtc_ctx.video_processor:
162
+ while True:
163
+ with webrtc_ctx.video_processor.lock:
164
+ result = webrtc_ctx.video_processor.result
165
+ if result:
166
+ st.session_state.update(code_found=True, last_code_data=result["data"], last_code_type=result["type"])
167
+ st.rerun()
168
+ time.sleep(0.2)
169
+ else:
170
+ st.success("βœ… Code captured successfully! The camera has been turned off.")
171
+
172
+ col1, col2 = st.columns([1, 2])
173
+
174
+ with col1:
175
+ st.subheader("πŸ“¦ Detected Code")
176
+ st.code(f"Data: {st.session_state['last_code_data']}\nType: {st.session_state['last_code_type']}", language="text")
177
+
178
+ if st.button("πŸ”„ Scan Another Product"):
179
+ st.session_state.update({"code_found": False, "last_code_data": "", "last_code_type": ""})
180
+ st.rerun()
181
+
182
+ with col2:
183
+ st.subheader("πŸ€– Gemini AI Verification")
184
+ with st.spinner("πŸ” Using Gemini with Google Search to verify..."):
185
+ verification_result = verify_code_with_gemini(
186
+ st.session_state['last_code_data'],
187
+ st.session_state['last_code_type']
188
+ )
189
+
190
+ # Display the summary text
191
+ st.info(verification_result.get("summary_text", "No summary available."))
192
+
193
+ # Display the image if a URL was found
194
+ image_url = verification_result.get("image_url")
195
+ if image_url:
196
+ st.image(image_url, caption="Product Image (from web search)")
197
+
198
+ # Display error details if they exist
199
+ if "error_details" in verification_result:
200
+ st.error("An error occurred during verification:")
201
+ st.code(f"Error: {verification_result['error_details']}\n\nRaw AI Response:\n{verification_result['raw_response']}", language="text")