dbeck22 commited on
Commit
821310d
Β·
1 Parent(s): 45a3202

the coin expert initial setup and build

Browse files
Files changed (8) hide show
  1. README.md +7 -0
  2. app.py +27 -4
  3. firebase_setup.py +22 -0
  4. main.py +45 -0
  5. requirements.txt +6 -0
  6. utils/__init__.py +0 -0
  7. utils/coin_tools.py +22 -0
  8. utils/image_tools.py +39 -0
README.md CHANGED
@@ -12,3 +12,10 @@ short_description: Can identify valuable error coins and varieties.
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
15
+
16
+
17
+ # Coin Identification AI
18
+
19
+ Upload a photo of a suspected error coin and tell us what you think it is. Coin Expert will fetch information, compare images, and help determine if your coin matches a known error or variety.
20
+
21
+ Built with OpenAI Vision + Firebase.
app.py CHANGED
@@ -1,7 +1,30 @@
1
  import gradio as gr
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
1
  import gradio as gr
2
+ from main import suspected_coin_name, user_image_path # or refactor main logic into functions
3
 
4
+ def analyze_coin(coin_name, image):
5
+ with open("uploaded_image.jpg", "wb") as f:
6
+ f.write(image.read())
7
+
8
+ # Assign file path to global variable for downstream logic
9
+ global user_image_path, suspected_coin_name
10
+ user_image_path = "uploaded_image.jpg"
11
+ suspected_coin_name = coin_name
12
+
13
+ # Import and re-run main logic
14
+ import main # assumes main logic runs on import
15
+
16
+ return f"Uploaded {coin_name} and processed. See terminal or logs for detailed output."
17
+
18
+ interface = gr.Interface(
19
+ fn=analyze_coin,
20
+ inputs=[
21
+ gr.Textbox(label="Enter the Coin Name (e.g. 1955 Lincoln Cent DDO-001)"),
22
+ gr.File(label="Upload a Coin Image")
23
+ ],
24
+ outputs="text",
25
+ title="Coin Expert - AI Coin Identifier",
26
+ description="Upload a photo of a suspected error coin and enter what you think it is. We'll try to match it and tell you if it's real."
27
+ )
28
+
29
+ interface.launch()
30
 
 
 
firebase_setup.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import firebase_admin
3
+ from firebase_admin import credentials, storage
4
+
5
+ def init_firebase():
6
+ if not firebase_admin._apps:
7
+ cred = credentials.Certificate({
8
+ "type": "service_account",
9
+ "project_id": os.getenv("FIREBASE_PROJECT_ID"),
10
+ "private_key_id": "ignored",
11
+ "private_key": os.getenv("FIREBASE_PRIVATE_KEY").replace("\\n", "\n"),
12
+ "client_email": os.getenv("FIREBASE_CLIENT_EMAIL"),
13
+ "client_id": "ignored",
14
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
15
+ "token_uri": "https://oauth2.googleapis.com/token",
16
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
17
+ "client_x509_cert_url": f"https://www.googleapis.com/robot/v1/metadata/x509/{os.getenv('FIREBASE_CLIENT_EMAIL').replace('@', '%40')}"
18
+ })
19
+
20
+ firebase_admin.initialize_app(cred, {
21
+ 'storageBucket': f"{os.getenv('FIREBASE_PROJECT_ID')}.appspot.com"
22
+ })
main.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import openai
3
+ import firebase_admin
4
+ from firebase_admin import firestore
5
+ from firebase_setup import init_firebase
6
+ from utils.coin_tools import get_coin_data, save_coin_data
7
+ from utils.image_tools import compare_images
8
+
9
+ # Init Firebase
10
+ init_firebase()
11
+ db = firestore.client()
12
+
13
+ # Init OpenAI
14
+ openai.api_key = os.getenv("OPENAI_API_KEY")
15
+
16
+ # === USER INPUT (Simulated for now) ===
17
+ user_image_path = "images/user_coin.jpg"
18
+ suspected_coin_name = "1955 Lincoln Cent DDO-001"
19
+
20
+ # === Step 1: Check if coin already exists in Firebase ===
21
+ coin_doc = db.collection("coins").document(suspected_coin_name.replace(" ", "_")).get()
22
+
23
+ if coin_doc.exists:
24
+ print(f"βœ… Found {suspected_coin_name} in the database. Comparing now...")
25
+ ref_images = coin_doc.to_dict().get("reference_images", [])
26
+ result = compare_images(user_image_path, ref_images)
27
+ print(f"Match Confidence: {result['confidence']*100:.1f}%")
28
+ else:
29
+ print(f"πŸ” No match found in database. Performing web search...")
30
+
31
+ # === Step 2: Use web_search_preview tool to find data ===
32
+ response = openai.responses.create(
33
+ model="gpt-4.1",
34
+ tools=[{"type": "web_search_preview"}],
35
+ input=f"Find die marker info, image links, and estimated value for {suspected_coin_name}"
36
+ )
37
+
38
+ output_text = response.output[1]['content'][0]['text']
39
+ print("πŸ“„ AI Search Result:\n", output_text)
40
+
41
+ # === Step 3: Save AI result to Firebase ===
42
+ coin_data = get_coin_data(suspected_coin_name, output_text, user_image_path)
43
+ save_coin_data(suspected_coin_name, coin_data)
44
+
45
+ print(f"πŸ’Ύ Saved new coin info to Firebase under {suspected_coin_name}.")
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ openai
2
+ firebase-admin
3
+ requests
4
+ pillow
5
+ gradio
6
+ python-dotenv
utils/__init__.py ADDED
File without changes
utils/coin_tools.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from firebase_admin import firestore, storage
3
+
4
+ def get_coin_data(coin_name, description, image_path):
5
+ return {
6
+ "name": coin_name,
7
+ "description": description,
8
+ "reference_images": [upload_image_to_storage(image_path, coin_name)],
9
+ "source": "web_search_preview",
10
+ }
11
+
12
+ def upload_image_to_storage(image_path, coin_name):
13
+ bucket = storage.bucket()
14
+ blob = bucket.blob(f"coin_references/{coin_name.replace(' ', '_')}.jpg")
15
+ blob.upload_from_filename(image_path)
16
+ blob.make_public()
17
+ return blob.public_url
18
+
19
+ def save_coin_data(coin_name, data):
20
+ db = firestore.client()
21
+ doc_ref = db.collection("coins").document(coin_name.replace(" ", "_"))
22
+ doc_ref.set(data)
utils/image_tools.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import requests
3
+
4
+ # Use OpenAI Vision to compare a user-uploaded image to reference images
5
+ def compare_images(user_image_path, reference_image_urls):
6
+ with open(user_image_path, "rb") as user_img:
7
+ user_bytes = user_img.read()
8
+
9
+ # Download the first reference image for comparison
10
+ if not reference_image_urls:
11
+ return {"confidence": 0.0, "reason": "No reference images available."}
12
+
13
+ ref_response = requests.get(reference_image_urls[0])
14
+ if ref_response.status_code != 200:
15
+ return {"confidence": 0.0, "reason": "Failed to fetch reference image."}
16
+
17
+ ref_bytes = ref_response.content
18
+
19
+ # Use GPT-4 Vision to compare both images
20
+ response = openai.chat.completions.create(
21
+ model="gpt-4-vision-preview",
22
+ messages=[
23
+ {"role": "system", "content": "You are an expert in identifying error coins."},
24
+ {
25
+ "role": "user",
26
+ "content": [
27
+ {"type": "text", "text": "Do these images look like the same error coin?"},
28
+ {"type": "image", "image": user_bytes},
29
+ {"type": "image", "image": ref_bytes}
30
+ ]
31
+ }
32
+ ],
33
+ max_tokens=300
34
+ )
35
+
36
+ result_text = response.choices[0].message.content
37
+ # Very simple scoring logic based on confidence language
38
+ confidence = 0.8 if "yes" in result_text.lower() else 0.3
39
+ return {"confidence": confidence, "summary": result_text}