Spaces:
Runtime error
Runtime error
File size: 5,672 Bytes
7c5c440 666646e 27514c1 7116b90 666646e c559bc7 294389b afa5ea3 27514c1 afa5ea3 666646e afa5ea3 666646e 27514c1 afa5ea3 666646e afa5ea3 666646e afa5ea3 666646e 27514c1 afa5ea3 27514c1 666646e 27514c1 666646e 7fae8fb 666646e afa5ea3 666646e afa5ea3 666646e afa5ea3 666646e afa5ea3 666646e afa5ea3 666646e dd67299 7c5c440 afa5ea3 666646e c559bc7 666646e afa5ea3 666646e 27514c1 afa5ea3 666646e afa5ea3 03852d5 afa5ea3 666646e 7116b90 afa5ea3 666646e afa5ea3 666646e 294389b 666646e 22ef1d5 666646e 7c5c440 666646e 22ef1d5 afa5ea3 666646e afa5ea3 7116b90 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
import gradio as gr
import uuid
import base64
import io
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct, VectorParams, Distance
from sentence_transformers import SentenceTransformer
from PIL import Image
# --------------------------
# Qdrant Cloud Connection
# --------------------------
QDRANT_URL = "https://ff4da494-27b1-413c-ba58-d5ea14932fe1.europe-west3-0.gcp.cloud.qdrant.io:6333" # π Replace with your cluster URL
QDRANT_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIn0.jjeB1JgnUSlb1hOOKMdRpVvMrUER57-udT-X1AWXT1E" # π Replace with your API key
COLLECTION_NAME = "lost_and_found"
# CLIP model (text + image embeddings)
MODEL_NAME = "sentence-transformers/clip-ViT-B-32"
embedder = SentenceTransformer(MODEL_NAME)
# CLIP ViT-B/32 always gives 512-dimensional embeddings
VECTOR_SIZE = 512
# Qdrant Client (Cloud)
qclient = QdrantClient(
url=QDRANT_URL,
api_key=QDRANT_API_KEY
)
# Ensure collection exists
qclient.recreate_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(size=VECTOR_SIZE, distance=Distance.COSINE),
)
# --------------------------
# Helper Functions
# --------------------------
def image_to_base64(img: Image.Image) -> str:
"""Convert PIL image to base64 string"""
buf = io.BytesIO()
img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode("utf-8")
def base64_to_image(b64_str: str) -> Image.Image:
"""Convert base64 string back to PIL image"""
img_bytes = base64.b64decode(b64_str)
return Image.open(io.BytesIO(img_bytes))
def embed_text(text: str):
return embedder.encode(text).tolist()
def embed_image(img: Image.Image):
return embedder.encode(img).tolist()
def add_item(image, description, finder_name, finder_phone):
"""Add a found item to Qdrant database"""
if image is None or description.strip() == "":
return "β Please provide both an image and a description."
# Encode image
embedding = embed_image(image)
img_b64 = image_to_base64(image)
# Store metadata including image
metadata = {
"description": description,
"finder_name": finder_name if finder_name.strip() else "NA",
"finder_phone": finder_phone if finder_phone.strip() else "NA",
"image_b64": img_b64
}
# Insert into Qdrant
qclient.upsert(
collection_name=COLLECTION_NAME,
points=[
PointStruct(
id=str(uuid.uuid4()),
vector=embedding,
payload=metadata
)
]
)
return "β
Item successfully added!"
def search_items(query_text, query_image):
"""Search by text or image"""
if not query_text and query_image is None:
return "β Please enter text or upload an image to search.", []
# Use text or image embedding
if query_image:
query_vector = embed_image(query_image)
else:
query_vector = embed_text(query_text)
# Search Qdrant
results = qclient.search(
collection_name=COLLECTION_NAME,
query_vector=query_vector,
limit=5
)
if not results:
return "β No matches found.", []
# Format results
gallery = []
output_text = "β
Found Matches:\n\n"
for r in results:
desc = r.payload.get("description", "No description")
name = r.payload.get("finder_name", "NA")
phone = r.payload.get("finder_phone", "NA")
output_text += f"- **{desc}** (Finder: {name}, Phone: {phone})\n"
if "image_b64" in r.payload:
try:
img = base64_to_image(r.payload["image_b64"])
gallery.append(img)
except Exception:
pass
return output_text, gallery
def clear_database():
"""Clear all stored items in Qdrant"""
qclient.delete_collection(COLLECTION_NAME)
qclient.recreate_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(size=VECTOR_SIZE, distance=Distance.COSINE),
)
return "ποΈ Database cleared!"
# --------------------------
# Gradio UI
# --------------------------
with gr.Blocks() as demo:
gr.Markdown("# π Lost & Found System")
with gr.Tab("β Add Found Item"):
with gr.Row():
image_in = gr.Image(type="pil", label="Upload Found Item Image")
desc_in = gr.Textbox(label="Item Description")
with gr.Row():
finder_name = gr.Textbox(label="Finder's Name")
finder_phone = gr.Textbox(label="Finder's Phone Number")
add_btn = gr.Button("Add Item")
add_output = gr.Textbox(label="Status")
with gr.Tab("π Search Items"):
with gr.Row():
search_text = gr.Textbox(label="Search by Text")
search_image = gr.Image(type="pil", label="Or Search by Image")
search_btn = gr.Button("Search")
search_output = gr.Markdown(label="Results")
gallery = gr.Gallery(label="Matched Items", show_label=True, elem_id="gallery")
with gr.Tab("β οΈ Admin"):
clear_btn = gr.Button("Clear Entire Database")
clear_output = gr.Textbox(label="Status")
# Button actions
add_btn.click(add_item, inputs=[image_in, desc_in, finder_name, finder_phone], outputs=add_output)
search_btn.click(search_items, inputs=[search_text, search_image], outputs=[search_output, gallery])
clear_btn.click(clear_database, outputs=clear_output)
# --------------------------
# Launch App
# --------------------------
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
|