FayssalJ commited on
Commit
5ba0958
·
1 Parent(s): f940ef1

Simplify app.py - use gr.Interface instead of gr.Blocks

Browse files
Files changed (1) hide show
  1. hf-space/app.py +32 -79
hf-space/app.py CHANGED
@@ -1,10 +1,5 @@
1
  """
2
  Visual Search API - HuggingFace Space
3
-
4
- Provides image embedding endpoint using Jina CLIP v2.
5
- Queries Pinecone for similar products.
6
-
7
- Deploy to HuggingFace Spaces with ZeroGPU (free).
8
  """
9
 
10
  import os
@@ -31,8 +26,6 @@ def load_model():
31
  "jinaai/jina-clip-v2",
32
  trust_remote_code=True
33
  )
34
- if torch.cuda.is_available():
35
- model = model.cuda()
36
  model.eval()
37
  print("Model loaded!")
38
  return model
@@ -47,7 +40,7 @@ def get_embedding(image: Image.Image) -> list:
47
  if hasattr(emb, 'cpu'):
48
  emb = emb.cpu().numpy()
49
  emb = emb.flatten()
50
- emb = emb / np.linalg.norm(emb) # L2 normalize
51
  if len(emb) > 512:
52
  emb = emb[:512]
53
  return emb.tolist()
@@ -83,80 +76,40 @@ def query_pinecone(embedding: list, top_k: int = 12) -> list:
83
  'handle': m.get('metadata', {}).get('handle', m.get('id')),
84
  'title': m.get('metadata', {}).get('title', ''),
85
  'score': m.get('score', 0),
86
- 'image_url': m.get('metadata', {}).get('image_url', '')
87
  }
88
  for m in matches
89
  ]
90
 
91
 
92
- def search(image: Image.Image) -> dict:
93
- """
94
- Main search function.
95
- Returns embedding and similar products.
96
- """
97
  if image is None:
98
- return {"error": "No image provided"}
99
-
100
- # Get embedding
101
- embedding = get_embedding(image)
102
-
103
- # Query Pinecone
104
- products = query_pinecone(embedding)
105
-
106
- return {
107
- "embedding": embedding,
108
- "products": products
109
- }
110
-
111
-
112
- def search_simple(image: Image.Image) -> str:
113
- """Simple search returning product handles."""
114
- if image is None:
115
- return "No image"
116
-
117
- embedding = get_embedding(image)
118
- products = query_pinecone(embedding)
119
-
120
- if not products:
121
- return "No similar products found"
122
-
123
- return "\n".join([
124
- f"{i+1}. {p['title']} ({p['handle']}) - {p['score']:.2f}"
125
- for i, p in enumerate(products)
126
- ])
127
-
128
-
129
- # Gradio Interface
130
- with gr.Blocks(title="Visual Search API") as demo:
131
- gr.Markdown("# Visual Product Search")
132
- gr.Markdown("Upload an image to find similar products.")
133
-
134
- with gr.Row():
135
- with gr.Column():
136
- image_input = gr.Image(type="pil", label="Upload Image")
137
- search_btn = gr.Button("Search", variant="primary")
138
-
139
- with gr.Column():
140
- output = gr.Textbox(label="Results", lines=15)
141
-
142
- search_btn.click(
143
- fn=search_simple,
144
- inputs=[image_input],
145
- outputs=[output]
146
- )
147
-
148
- gr.Markdown("---")
149
- gr.Markdown("### API Endpoint")
150
- gr.Markdown("""
151
- Use the `/api/predict` endpoint for programmatic access:
152
-
153
- ```python
154
- from gradio_client import Client
155
-
156
- client = Client("YOUR_SPACE_URL")
157
- result = client.predict(image_path, api_name="/predict")
158
- ```
159
- """)
160
-
161
-
162
- # HF Spaces handles the launch automatically - do not call demo.launch()
 
1
  """
2
  Visual Search API - HuggingFace Space
 
 
 
 
 
3
  """
4
 
5
  import os
 
26
  "jinaai/jina-clip-v2",
27
  trust_remote_code=True
28
  )
 
 
29
  model.eval()
30
  print("Model loaded!")
31
  return model
 
40
  if hasattr(emb, 'cpu'):
41
  emb = emb.cpu().numpy()
42
  emb = emb.flatten()
43
+ emb = emb / np.linalg.norm(emb)
44
  if len(emb) > 512:
45
  emb = emb[:512]
46
  return emb.tolist()
 
76
  'handle': m.get('metadata', {}).get('handle', m.get('id')),
77
  'title': m.get('metadata', {}).get('title', ''),
78
  'score': m.get('score', 0),
 
79
  }
80
  for m in matches
81
  ]
82
 
83
 
84
+ def search(image):
85
+ """Main search function."""
 
 
 
86
  if image is None:
87
+ return "No image provided"
88
+
89
+ try:
90
+ embedding = get_embedding(image)
91
+ products = query_pinecone(embedding)
92
+
93
+ if not products:
94
+ return "No similar products found"
95
+
96
+ result = "\n".join([
97
+ f"{i+1}. {p['title']} ({p['handle']}) - score: {p['score']:.3f}"
98
+ for i, p in enumerate(products)
99
+ ])
100
+ return result
101
+ except Exception as e:
102
+ return f"Error: {str(e)}"
103
+
104
+
105
+ # Simple Gradio interface
106
+ demo = gr.Interface(
107
+ fn=search,
108
+ inputs=gr.Image(type="pil", label="Upload Image"),
109
+ outputs=gr.Textbox(label="Similar Products", lines=15),
110
+ title="Visual Product Search",
111
+ description="Upload an image to find similar products."
112
+ )
113
+
114
+ if __name__ == "__main__":
115
+ demo.launch()