Anusha806 commited on
Commit
f974ed7
·
1 Parent(s): 4e4e05b
Files changed (1) hide show
  1. app.py +290 -491
app.py CHANGED
@@ -769,447 +769,6 @@ def search_by_image(uploaded_image, alpha=0.5, start=0, end=12):
769
 
770
  return imgs_with_captions
771
 
772
- # import gradio as gr
773
- # import whisper
774
-
775
- # asr_model = whisper.load_model("base")
776
-
777
- # def handle_voice_search(vf_path, a, offset, gender_ui):
778
- # try:
779
- # transcription = asr_model.transcribe(vf_path)["text"].strip()
780
- # except:
781
- # transcription = ""
782
- # filters = extract_intent_from_openai(transcription) if transcription else {}
783
- # gender_override = gender_ui if gender_ui else filters.get("gender")
784
- # results = search_fashion(transcription, a, 0, 12, gender_override)
785
- # seen_ids = {r[1] for r in results}
786
- # return results, 12, transcription, None, gender_override, results, seen_ids
787
-
788
-
789
- # custom_css = """
790
- # /* === Global Styling === */
791
- # /* === Override Gradio default background === */
792
-
793
- # html, body {
794
- # height: 100% !important;
795
- # margin: 0 !important;
796
- # padding: 0 !important;
797
- # background: radial-gradient(circle at center, #0b1f36 0%, #033e3e 100%) !important;
798
- # background-attachment: fixed;
799
- # }
800
-
801
- # .gr-root, .gr-block {
802
- # background: transparent !important;
803
- # }
804
-
805
-
806
- # body::before {
807
- # content: "";
808
- # position: fixed;
809
- # top: 0; left: 0;
810
- # width: 100%; height: 100%;
811
- # background: radial-gradient(circle at center, rgba(0, 255, 255, 0.08), transparent);
812
- # z-index: -1;
813
- # }
814
- # #app-bg {
815
- # min-height: 100vh;
816
- # padding: 0;
817
- # margin: 0;
818
- # background: radial-gradient(circle at center, #0b1f36 0%, #033e3e 100%);
819
- # display: flex;
820
- # justify-content: center;
821
- # align-items: flex-start;
822
- # background-attachment: fixed;
823
- # position: relative;
824
- # # overflow: hidden;
825
- # overflow-y: auto;
826
-
827
- # }
828
-
829
- # #app-bg::before {
830
- # content: "";
831
- # position: absolute;
832
- # top: 0; left: 0;
833
- # width: 100%; height: 100%;
834
- # background: radial-gradient(circle at center, rgba(0, 255, 255, 0.08), transparent);
835
- # z-index: 0;
836
- # }
837
-
838
- # #main-container {
839
- # z-index: 1;
840
- # position: relative;
841
- # overflow-y: auto;
842
- # }
843
-
844
-
845
-
846
-
847
- # /* === Heading Style === */
848
- # h1, .gr-markdown h1 {
849
- # font-size: 2.2rem !important;
850
- # font-weight: bold;
851
- # color: #f5f2f2;
852
- # text-align: center;
853
- # margin-bottom: 1rem;
854
- # }
855
-
856
- # /* === Tabs === */
857
- # .gr-tab {
858
- # border-radius: 12px !important;
859
- # background-color: #ffffff !important;
860
- # box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
861
- # padding: 16px !important;
862
- # margin-top: 12px;
863
- # }
864
-
865
- # /* === Textbox, Dropdown, Slider === */
866
- # input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
867
- # border-radius: 8px !important;
868
- # border: 1px solid #ccc !important;
869
- # padding: 10px !important;
870
- # font-size: 16px;
871
- # box-shadow: 0 1px 3px rgba(0,0,0,0.05);
872
- # }
873
-
874
- # /* === Image Upload === */
875
- # .gr-image {
876
- # width: 100% !important;
877
- # max-width: 100% !important;
878
- # border-radius: 12px;
879
- # box-shadow: 0 2px 10px rgba(0,0,0,0.1);
880
- # }
881
-
882
- # /* === Buttons (custom style .button-36) === */
883
- # .gr-button {
884
- # background-color: #DBDBDB !important;
885
- # background-image: linear-gradient(92.88deg, #455EB5 9.16%, #5643CC 43.89%, #673FD7 64.72%);
886
- # border-radius: 8px !important;
887
- # border-style: none !important;
888
- # box-sizing: border-box;
889
- # color: #FFFFFF !important;
890
- # cursor: pointer;
891
- # flex-shrink: 0;
892
- # font-family: "Inter UI","SF Pro Display",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;
893
- # font-size: 16px;
894
- # font-weight: 500;
895
- # height: 4rem;
896
- # padding: 0 1.6rem;
897
- # text-align: center;
898
- # text-shadow: rgba(0, 0, 0, 0.25) 0 3px 8px;
899
- # transition: all .5s;
900
- # user-select: none;
901
- # -webkit-user-select: none;
902
- # touch-action: manipulation;
903
- # }
904
-
905
- # .gr-button:hover {
906
- # box-shadow: rgba(80, 63, 205, 0.5) 0 1px 30px;
907
- # transition-duration: .1s;
908
- # }
909
-
910
- # /* === Responsive padding === */
911
- # @media (min-width: 768px) {
912
- # .gr-button {
913
- # padding: 0 2.6rem;
914
- # }
915
- # }
916
-
917
- # /* === Gallery Grid === */
918
- # .gr-gallery {
919
- # padding-top: 12px;
920
- # }
921
- # .gr-gallery-item {
922
- # width: 128px !important;
923
- # height: 128px !important;
924
- # transition: transform 0.3s ease-in-out;
925
- # border-radius: 8px;
926
- # overflow: hidden;
927
- # }
928
- # .gr-gallery-item:hover {
929
- # transform: scale(1.06);
930
- # box-shadow: 0 3px 12px rgba(0,0,0,0.15);
931
- # }
932
- # .gr-gallery-item img {
933
- # object-fit: cover !important;
934
- # width: 100% !important;
935
- # height: 100% !important;
936
- # border-radius: 8px;
937
- # }
938
-
939
- # /* === Audio Upload === */
940
- # .gr-audio {
941
- # width: 100% !important;
942
- # border-radius: 12px;
943
- # background-color: #fff !important;
944
- # box-shadow: 0 1px 5px rgba(0,0,0,0.1);
945
- # }
946
-
947
- # /* === Footer === */
948
- # .gr-markdown:last-child {
949
- # text-align: center;
950
- # font-size: 14px;
951
- # color: #666;
952
- # padding-top: 1rem;
953
- # }
954
-
955
- # # /* === Main Container Centered and Wide === */
956
- # # #main-container {
957
- # # max-width: 90%;
958
- # # width: 1100px;
959
- # # margin: 40px auto !important;
960
- # # padding: 24px;
961
- # # background: #ffffff;
962
- # # border-radius: 18px;
963
- # # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
964
- # # border: 3px solid orange; /* Orange border */
965
- # # }
966
- # # #main-container {
967
- # # max-width: 90%;
968
- # # width: 1100px;
969
- # # height: 90vh;
970
- # # overflow-y: auto;
971
- # # padding: 24px;
972
- # # background: #ffffff;
973
- # # border-radius: 18px;
974
- # # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
975
- # # border: 3px solid orange;
976
- # # margin: 40px auto;
977
- # # position: relative;
978
- # # display: flex;
979
- # # flex-direction: column;
980
- # # }
981
-
982
- # # #main-container {
983
- # # width: 95%;
984
- # # max-width: 1100px;
985
- # # margin: 20px auto !important;
986
- # # padding: 16px;
987
- # # background: #ffffff;
988
- # # border-radius: 18px;
989
- # # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
990
- # # border: 3px solid orange;
991
- # # overflow-y: auto;
992
- # # max-height: 90vh;
993
- # # }
994
-
995
-
996
- # #trying to update the container bcz the title is being compressed
997
- # #main-container {
998
- # width: 95%;
999
- # max-width: 1100px;
1000
- # margin: 20px auto !important;
1001
- # padding: 16px;
1002
- # background: #ffffff;
1003
- # border-radius: 18px;
1004
- # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
1005
- # border: 3px solid orange;
1006
-
1007
- # /* Remove height restriction */
1008
- # # overflow: visible;
1009
- # overflow-y: auto;
1010
- # }
1011
-
1012
-
1013
-
1014
-
1015
-
1016
- # /* For phones and smaller devices */
1017
- # @media (max-width: 768px) {
1018
- # #main-container {
1019
- # width: 100%;
1020
- # margin: 8px;
1021
- # padding: 12px;
1022
- # border-radius: 12px;
1023
- # max-height: none;
1024
- # }
1025
-
1026
- # .gr-button {
1027
- # font-size: 14px;
1028
- # height: 3.2rem;
1029
- # }
1030
-
1031
- # input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
1032
- # font-size: 14px;
1033
- # padding: 8px !important;
1034
- # }
1035
-
1036
- # h1, .gr-markdown h1 {
1037
- # font-size: 1.6rem !important;
1038
- # }
1039
-
1040
- # .gr-gallery-item {
1041
- # width: 100px !important;
1042
- # height: 100px !important;
1043
- # }
1044
-
1045
- # .gr-image {
1046
- # height: auto !important;
1047
- # }
1048
- # }
1049
-
1050
-
1051
-
1052
- # /* === Tab Label Styling === */
1053
- # button[role="tab"] {
1054
- # color: #000000 !important; /* Default tab text color: black */
1055
- # font-weight: 500;
1056
- # transition: color 0.3s ease-in-out;
1057
- # font-size: 16px;
1058
- # }
1059
-
1060
- # /* Active tab title */
1061
- # button[role="tab"][aria-selected="true"] {
1062
- # color: #f57c00 !important; /* Active tab text color: orange */
1063
- # font-weight: bold !important;
1064
- # }
1065
-
1066
- # /* Hover effect on tab titles */
1067
- # button[role="tab"]:hover {
1068
- # color: #f57c00 !important; /* Orange on hover */
1069
- # font-weight: 600;
1070
- # cursor: pointer;
1071
- # }
1072
- # /* === Uniform Input Sizes for Text, Audio, Image === */
1073
- # .gr-textbox, .gr-audio, .gr-image {
1074
- # max-width: 100% !important;
1075
- # width: 100% !important;
1076
- # }
1077
-
1078
- # .gr-audio, .gr-image {
1079
- # max-width: 500px !important;
1080
- # margin: 0 auto;
1081
- # }
1082
-
1083
- # .gr-image {
1084
- # height: 256px !important;
1085
- # }
1086
-
1087
- # """
1088
-
1089
- # with gr.Blocks(css=custom_css) as demo:
1090
- # with gr.Column(elem_id="app-bg"):
1091
- # gr.Markdown("# 🛍️ Fashion Product Hybrid Search")
1092
-
1093
- # alpha = gr.Slider(0, 1, value=0.5, label="Hybrid Weight (alpha: 0=sparse, 1=dense)")
1094
-
1095
- # with gr.Tabs():
1096
- # with gr.Tab("Text Search"):
1097
- # query = gr.Textbox(
1098
- # label="Text Query",
1099
- # placeholder="e.g., floral summer dress for women"
1100
- # )
1101
- # gender_dropdown = gr.Dropdown(
1102
- # ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1103
- # label="Gender Filter (optional)"
1104
- # )
1105
- # text_search_btn = gr.Button("Search by Text", elem_classes="search-btn")
1106
-
1107
- # with gr.Tab("🎙️ Voice Search"):
1108
- # voice_input = gr.Audio(label="Speak Your Query", type="filepath")
1109
- # voice_gender_dropdown = gr.Dropdown(
1110
- # ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1111
- # label="Gender"
1112
- # )
1113
- # voice_search_btn = gr.Button("Search by Voice")
1114
-
1115
- # with gr.Tab("Image Search"):
1116
- # image_input = gr.Image(
1117
- # type="pil",
1118
- # label="Upload an image",
1119
- # sources=["upload", "clipboard"],
1120
- # height=400
1121
- # )
1122
- # image_gender_dropdown = gr.Dropdown(
1123
- # ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1124
- # label="Gender Filter (optional)"
1125
- # )
1126
- # image_search_btn = gr.Button("Search by Image", elem_classes="search-btn")
1127
-
1128
- # gallery = gr.Gallery(label="Search Results", columns=6, height=None)
1129
- # load_more_btn = gr.Button("Load More")
1130
-
1131
- # # --- UI State Holders ---
1132
- # search_offset = gr.State(0)
1133
- # current_query = gr.State("")
1134
- # current_image = gr.State(None)
1135
- # current_gender = gr.State("")
1136
- # shown_results = gr.State([])
1137
- # shown_ids = gr.State(set())
1138
-
1139
- # # --- Unified Search Function ---
1140
- # def unified_search(q, uploaded_image, a, offset, gender_ui):
1141
- # start = 0
1142
- # end = 12
1143
- # filters = extract_intent_from_openai(q) if q.strip() else {}
1144
- # gender_override = gender_ui if gender_ui else filters.get("gender")
1145
-
1146
- # if uploaded_image is not None:
1147
- # results = search_by_image(uploaded_image, a, start, end)
1148
- # elif q.strip():
1149
- # results = search_fashion(q, a, start, end, gender_override)
1150
- # else:
1151
- # results = []
1152
-
1153
- # seen_ids = {r[1] for r in results}
1154
- # return results, end, q, uploaded_image, gender_override, results, seen_ids
1155
-
1156
- # # --- Text Search Click Handler ---
1157
- # text_search_btn.click(
1158
- # unified_search,
1159
- # inputs=[query, gr.State(None), alpha, search_offset, gender_dropdown],
1160
- # outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1161
- # )
1162
-
1163
- # # --- Voice Search Click Handler ---
1164
- # voice_search_btn.click(
1165
- # handle_voice_search,
1166
- # inputs=[voice_input, alpha, search_offset, voice_gender_dropdown],
1167
- # outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1168
- # )
1169
-
1170
- # # --- Image Search Click Handler ---
1171
- # image_search_btn.click(
1172
- # unified_search,
1173
- # inputs=[gr.State(""), image_input, alpha, search_offset, image_gender_dropdown],
1174
- # outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1175
- # )
1176
-
1177
- # # --- Load More Button Function ---
1178
- # def load_more_fn(a, offset, q, img, gender_ui, prev_results, prev_ids):
1179
- # start = offset
1180
- # end = offset + 12
1181
- # gender_override = gender_ui
1182
-
1183
- # if img is not None:
1184
- # new_results = search_by_image(img, a, start, end)
1185
- # elif q.strip():
1186
- # new_results = search_fashion(q, a, start, end, gender_override)
1187
- # else:
1188
- # new_results = []
1189
-
1190
- # filtered_new = []
1191
- # new_ids = set()
1192
- # for item in new_results:
1193
- # img_obj, caption = item
1194
- # if caption not in prev_ids:
1195
- # filtered_new.append(item)
1196
- # new_ids.add(caption)
1197
-
1198
- # combined = prev_results + filtered_new
1199
- # updated_ids = prev_ids.union(new_ids)
1200
-
1201
- # return combined, end, combined, updated_ids
1202
-
1203
- # load_more_btn.click(
1204
- # load_more_fn,
1205
- # inputs=[alpha, search_offset, current_query, current_image, current_gender, shown_results, shown_ids],
1206
- # outputs=[gallery, search_offset, shown_results, shown_ids]
1207
- # )
1208
-
1209
- # demo.launch()
1210
-
1211
-
1212
-
1213
  import gradio as gr
1214
  import whisper
1215
 
@@ -1226,59 +785,136 @@ def handle_voice_search(vf_path, a, offset, gender_ui):
1226
  seen_ids = {r[1] for r in results}
1227
  return results, 12, transcription, None, gender_override, results, seen_ids
1228
 
 
1229
  custom_css = """
 
 
 
1230
  html, body {
1231
  height: 100% !important;
1232
- margin: 0;
1233
- padding: 0;
1234
  background: radial-gradient(circle at center, #0b1f36 0%, #033e3e 100%) !important;
1235
  background-attachment: fixed;
1236
- overflow: hidden;
1237
  }
1238
 
1239
  .gr-root, .gr-block {
1240
  background: transparent !important;
1241
  }
1242
 
 
 
 
 
 
 
 
 
 
1243
  #app-bg {
1244
  min-height: 100vh;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1245
  overflow-y: auto;
1246
- padding: 24px;
1247
  }
1248
 
 
 
 
 
1249
  h1, .gr-markdown h1 {
1250
- font-size: 2rem;
1251
  font-weight: bold;
1252
- color: #ffffff;
1253
  text-align: center;
1254
  margin-bottom: 1rem;
1255
  }
1256
 
 
1257
  .gr-tab {
1258
  border-radius: 12px !important;
1259
  background-color: #ffffff !important;
1260
- padding: 16px;
 
1261
  margin-top: 12px;
1262
  }
1263
 
 
1264
  input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
1265
- border-radius: 8px;
1266
- border: 1px solid #ccc;
1267
- padding: 10px;
1268
  font-size: 16px;
 
 
 
 
 
 
 
 
 
1269
  }
1270
 
 
1271
  .gr-button {
1272
- background-image: linear-gradient(92.88deg, #455EB5 9.16%, #5643CC 43.89%, #673FD7 64.72%);
1273
- color: white !important;
1274
- border-radius: 8px;
1275
- font-size: 16px;
1276
- font-weight: 500;
1277
- height: 3.5rem;
1278
- padding: 0 1.5rem;
1279
- box-shadow: rgba(80, 63, 205, 0.5) 0 1px 30px;
 
 
 
 
 
 
 
 
 
 
 
1280
  }
1281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1282
  .gr-gallery {
1283
  padding-top: 12px;
1284
  }
@@ -1300,19 +936,154 @@ input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
1300
  border-radius: 8px;
1301
  }
1302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1303
  @media (max-width: 768px) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1304
  h1, .gr-markdown h1 {
1305
  font-size: 1.6rem !important;
1306
  }
 
1307
  .gr-gallery-item {
1308
  width: 100px !important;
1309
  height: 100px !important;
1310
  }
1311
- .gr-button {
1312
- font-size: 14px;
1313
- height: 3rem;
1314
  }
1315
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1316
  """
1317
 
1318
  with gr.Blocks(css=custom_css) as demo:
@@ -1323,24 +1094,41 @@ with gr.Blocks(css=custom_css) as demo:
1323
 
1324
  with gr.Tabs():
1325
  with gr.Tab("Text Search"):
1326
- query = gr.Textbox(label="Text Query", placeholder="e.g., floral summer dress for women")
1327
- gender_dropdown = gr.Dropdown(["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"], label="Gender Filter (optional)")
1328
- text_search_btn = gr.Button("Search by Text")
 
 
 
 
 
 
1329
 
1330
  with gr.Tab("🎙️ Voice Search"):
1331
  voice_input = gr.Audio(label="Speak Your Query", type="filepath")
1332
- voice_gender_dropdown = gr.Dropdown(["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"], label="Gender")
 
 
 
1333
  voice_search_btn = gr.Button("Search by Voice")
1334
 
1335
  with gr.Tab("Image Search"):
1336
- image_input = gr.Image(type="pil", label="Upload an image", sources=["upload", "clipboard"], height=400)
1337
- image_gender_dropdown = gr.Dropdown(["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"], label="Gender Filter (optional)")
1338
- image_search_btn = gr.Button("Search by Image")
 
 
 
 
 
 
 
 
1339
 
1340
  gallery = gr.Gallery(label="Search Results", columns=6, height=None)
1341
  load_more_btn = gr.Button("Load More")
1342
 
1343
- # UI States
1344
  search_offset = gr.State(0)
1345
  current_query = gr.State("")
1346
  current_image = gr.State(None)
@@ -1348,24 +1136,50 @@ with gr.Blocks(css=custom_css) as demo:
1348
  shown_results = gr.State([])
1349
  shown_ids = gr.State(set())
1350
 
 
1351
  def unified_search(q, uploaded_image, a, offset, gender_ui):
1352
  start = 0
1353
  end = 12
1354
  filters = extract_intent_from_openai(q) if q.strip() else {}
1355
  gender_override = gender_ui if gender_ui else filters.get("gender")
 
1356
  if uploaded_image is not None:
1357
  results = search_by_image(uploaded_image, a, start, end)
1358
  elif q.strip():
1359
  results = search_fashion(q, a, start, end, gender_override)
1360
  else:
1361
  results = []
 
1362
  seen_ids = {r[1] for r in results}
1363
  return results, end, q, uploaded_image, gender_override, results, seen_ids
1364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
  def load_more_fn(a, offset, q, img, gender_ui, prev_results, prev_ids):
1366
  start = offset
1367
  end = offset + 12
1368
  gender_override = gender_ui
 
1369
  if img is not None:
1370
  new_results = search_by_image(img, a, start, end)
1371
  elif q.strip():
@@ -1376,32 +1190,15 @@ with gr.Blocks(css=custom_css) as demo:
1376
  filtered_new = []
1377
  new_ids = set()
1378
  for item in new_results:
1379
- if item[1] not in prev_ids:
 
1380
  filtered_new.append(item)
1381
- new_ids.add(item[1])
1382
 
1383
  combined = prev_results + filtered_new
1384
  updated_ids = prev_ids.union(new_ids)
1385
- return combined, end, combined, updated_ids
1386
 
1387
- # Button Bindings
1388
- text_search_btn.click(
1389
- unified_search,
1390
- inputs=[query, gr.State(None), alpha, search_offset, gender_dropdown],
1391
- outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1392
- )
1393
-
1394
- voice_search_btn.click(
1395
- handle_voice_search,
1396
- inputs=[voice_input, alpha, search_offset, voice_gender_dropdown],
1397
- outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1398
- )
1399
-
1400
- image_search_btn.click(
1401
- unified_search,
1402
- inputs=[gr.State(""), image_input, alpha, search_offset, image_gender_dropdown],
1403
- outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1404
- )
1405
 
1406
  load_more_btn.click(
1407
  load_more_fn,
@@ -1410,3 +1207,5 @@ with gr.Blocks(css=custom_css) as demo:
1410
  )
1411
 
1412
  demo.launch()
 
 
 
769
 
770
  return imgs_with_captions
771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
772
  import gradio as gr
773
  import whisper
774
 
 
785
  seen_ids = {r[1] for r in results}
786
  return results, 12, transcription, None, gender_override, results, seen_ids
787
 
788
+
789
  custom_css = """
790
+ /* === Global Styling === */
791
+ /* === Override Gradio default background === */
792
+
793
  html, body {
794
  height: 100% !important;
795
+ margin: 0 !important;
796
+ padding: 0 !important;
797
  background: radial-gradient(circle at center, #0b1f36 0%, #033e3e 100%) !important;
798
  background-attachment: fixed;
 
799
  }
800
 
801
  .gr-root, .gr-block {
802
  background: transparent !important;
803
  }
804
 
805
+
806
+ body::before {
807
+ content: "";
808
+ position: fixed;
809
+ top: 0; left: 0;
810
+ width: 100%; height: 100%;
811
+ background: radial-gradient(circle at center, rgba(0, 255, 255, 0.08), transparent);
812
+ z-index: -1;
813
+ }
814
  #app-bg {
815
  min-height: 100vh;
816
+ padding: 0;
817
+ margin: 0;
818
+ background: radial-gradient(circle at center, #0b1f36 0%, #033e3e 100%);
819
+ display: flex;
820
+ justify-content: center;
821
+ align-items: flex-start;
822
+ background-attachment: fixed;
823
+ position: relative;
824
+ # overflow: hidden;
825
+ overflow-y: auto;
826
+
827
+ }
828
+
829
+ #app-bg::before {
830
+ content: "";
831
+ position: absolute;
832
+ top: 0; left: 0;
833
+ width: 100%; height: 100%;
834
+ background: radial-gradient(circle at center, rgba(0, 255, 255, 0.08), transparent);
835
+ z-index: 0;
836
+ }
837
+
838
+ #main-container {
839
+ z-index: 1;
840
+ position: relative;
841
  overflow-y: auto;
 
842
  }
843
 
844
+
845
+
846
+
847
+ /* === Heading Style === */
848
  h1, .gr-markdown h1 {
849
+ font-size: 2.2rem !important;
850
  font-weight: bold;
851
+ color: #f5f2f2;
852
  text-align: center;
853
  margin-bottom: 1rem;
854
  }
855
 
856
+ /* === Tabs === */
857
  .gr-tab {
858
  border-radius: 12px !important;
859
  background-color: #ffffff !important;
860
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
861
+ padding: 16px !important;
862
  margin-top: 12px;
863
  }
864
 
865
+ /* === Textbox, Dropdown, Slider === */
866
  input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
867
+ border-radius: 8px !important;
868
+ border: 1px solid #ccc !important;
869
+ padding: 10px !important;
870
  font-size: 16px;
871
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
872
+ }
873
+
874
+ /* === Image Upload === */
875
+ .gr-image {
876
+ width: 100% !important;
877
+ max-width: 100% !important;
878
+ border-radius: 12px;
879
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
880
  }
881
 
882
+ /* === Buttons (custom style .button-36) === */
883
  .gr-button {
884
+ background-color: #DBDBDB !important;
885
+ background-image: linear-gradient(92.88deg, #455EB5 9.16%, #5643CC 43.89%, #673FD7 64.72%);
886
+ border-radius: 8px !important;
887
+ border-style: none !important;
888
+ box-sizing: border-box;
889
+ color: #FFFFFF !important;
890
+ cursor: pointer;
891
+ flex-shrink: 0;
892
+ font-family: "Inter UI","SF Pro Display",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;
893
+ font-size: 16px;
894
+ font-weight: 500;
895
+ height: 4rem;
896
+ padding: 0 1.6rem;
897
+ text-align: center;
898
+ text-shadow: rgba(0, 0, 0, 0.25) 0 3px 8px;
899
+ transition: all .5s;
900
+ user-select: none;
901
+ -webkit-user-select: none;
902
+ touch-action: manipulation;
903
  }
904
 
905
+ .gr-button:hover {
906
+ box-shadow: rgba(80, 63, 205, 0.5) 0 1px 30px;
907
+ transition-duration: .1s;
908
+ }
909
+
910
+ /* === Responsive padding === */
911
+ @media (min-width: 768px) {
912
+ .gr-button {
913
+ padding: 0 2.6rem;
914
+ }
915
+ }
916
+
917
+ /* === Gallery Grid === */
918
  .gr-gallery {
919
  padding-top: 12px;
920
  }
 
936
  border-radius: 8px;
937
  }
938
 
939
+ /* === Audio Upload === */
940
+ .gr-audio {
941
+ width: 100% !important;
942
+ border-radius: 12px;
943
+ background-color: #fff !important;
944
+ box-shadow: 0 1px 5px rgba(0,0,0,0.1);
945
+ }
946
+
947
+ /* === Footer === */
948
+ .gr-markdown:last-child {
949
+ text-align: center;
950
+ font-size: 14px;
951
+ color: #666;
952
+ padding-top: 1rem;
953
+ }
954
+
955
+ # /* === Main Container Centered and Wide === */
956
+ # #main-container {
957
+ # max-width: 90%;
958
+ # width: 1100px;
959
+ # margin: 40px auto !important;
960
+ # padding: 24px;
961
+ # background: #ffffff;
962
+ # border-radius: 18px;
963
+ # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
964
+ # border: 3px solid orange; /* Orange border */
965
+ # }
966
+ # #main-container {
967
+ # max-width: 90%;
968
+ # width: 1100px;
969
+ # height: 90vh;
970
+ # overflow-y: auto;
971
+ # padding: 24px;
972
+ # background: #ffffff;
973
+ # border-radius: 18px;
974
+ # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
975
+ # border: 3px solid orange;
976
+ # margin: 40px auto;
977
+ # position: relative;
978
+ # display: flex;
979
+ # flex-direction: column;
980
+ # }
981
+
982
+ # #main-container {
983
+ # width: 95%;
984
+ # max-width: 1100px;
985
+ # margin: 20px auto !important;
986
+ # padding: 16px;
987
+ # background: #ffffff;
988
+ # border-radius: 18px;
989
+ # box-shadow: 0 10px 30px rgba(0,0,0,0.08);
990
+ # border: 3px solid orange;
991
+ # overflow-y: auto;
992
+ # max-height: 90vh;
993
+ # }
994
+
995
+
996
+ #trying to update the container bcz the title is being compressed
997
+ #main-container {
998
+ width: 95%;
999
+ max-width: 1100px;
1000
+ margin: 20px auto !important;
1001
+ padding: 16px;
1002
+ background: #ffffff;
1003
+ border-radius: 18px;
1004
+ box-shadow: 0 10px 30px rgba(0,0,0,0.08);
1005
+ border: 3px solid orange;
1006
+
1007
+ /* Remove height restriction */
1008
+ # overflow: visible;
1009
+ overflow-y: auto;
1010
+ }
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+ /* For phones and smaller devices */
1017
  @media (max-width: 768px) {
1018
+ #main-container {
1019
+ width: 100%;
1020
+ margin: 8px;
1021
+ padding: 12px;
1022
+ border-radius: 12px;
1023
+ max-height: none;
1024
+ }
1025
+
1026
+ .gr-button {
1027
+ font-size: 14px;
1028
+ height: 3.2rem;
1029
+ }
1030
+
1031
+ input[type="text"], .gr-textbox textarea, .gr-dropdown, .gr-slider {
1032
+ font-size: 14px;
1033
+ padding: 8px !important;
1034
+ }
1035
+
1036
  h1, .gr-markdown h1 {
1037
  font-size: 1.6rem !important;
1038
  }
1039
+
1040
  .gr-gallery-item {
1041
  width: 100px !important;
1042
  height: 100px !important;
1043
  }
1044
+
1045
+ .gr-image {
1046
+ height: auto !important;
1047
  }
1048
  }
1049
+
1050
+
1051
+
1052
+ /* === Tab Label Styling === */
1053
+ button[role="tab"] {
1054
+ color: #000000 !important; /* Default tab text color: black */
1055
+ font-weight: 500;
1056
+ transition: color 0.3s ease-in-out;
1057
+ font-size: 16px;
1058
+ }
1059
+
1060
+ /* Active tab title */
1061
+ button[role="tab"][aria-selected="true"] {
1062
+ color: #f57c00 !important; /* Active tab text color: orange */
1063
+ font-weight: bold !important;
1064
+ }
1065
+
1066
+ /* Hover effect on tab titles */
1067
+ button[role="tab"]:hover {
1068
+ color: #f57c00 !important; /* Orange on hover */
1069
+ font-weight: 600;
1070
+ cursor: pointer;
1071
+ }
1072
+ /* === Uniform Input Sizes for Text, Audio, Image === */
1073
+ .gr-textbox, .gr-audio, .gr-image {
1074
+ max-width: 100% !important;
1075
+ width: 100% !important;
1076
+ }
1077
+
1078
+ .gr-audio, .gr-image {
1079
+ max-width: 500px !important;
1080
+ margin: 0 auto;
1081
+ }
1082
+
1083
+ .gr-image {
1084
+ height: 256px !important;
1085
+ }
1086
+
1087
  """
1088
 
1089
  with gr.Blocks(css=custom_css) as demo:
 
1094
 
1095
  with gr.Tabs():
1096
  with gr.Tab("Text Search"):
1097
+ query = gr.Textbox(
1098
+ label="Text Query",
1099
+ placeholder="e.g., floral summer dress for women"
1100
+ )
1101
+ gender_dropdown = gr.Dropdown(
1102
+ ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1103
+ label="Gender Filter (optional)"
1104
+ )
1105
+ text_search_btn = gr.Button("Search by Text", elem_classes="search-btn")
1106
 
1107
  with gr.Tab("🎙️ Voice Search"):
1108
  voice_input = gr.Audio(label="Speak Your Query", type="filepath")
1109
+ voice_gender_dropdown = gr.Dropdown(
1110
+ ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1111
+ label="Gender"
1112
+ )
1113
  voice_search_btn = gr.Button("Search by Voice")
1114
 
1115
  with gr.Tab("Image Search"):
1116
+ image_input = gr.Image(
1117
+ type="pil",
1118
+ label="Upload an image",
1119
+ sources=["upload", "clipboard"],
1120
+ height=400
1121
+ )
1122
+ image_gender_dropdown = gr.Dropdown(
1123
+ ["", "Men", "Women", "Boys", "Girls", "Kids", "Unisex"],
1124
+ label="Gender Filter (optional)"
1125
+ )
1126
+ image_search_btn = gr.Button("Search by Image", elem_classes="search-btn")
1127
 
1128
  gallery = gr.Gallery(label="Search Results", columns=6, height=None)
1129
  load_more_btn = gr.Button("Load More")
1130
 
1131
+ # --- UI State Holders ---
1132
  search_offset = gr.State(0)
1133
  current_query = gr.State("")
1134
  current_image = gr.State(None)
 
1136
  shown_results = gr.State([])
1137
  shown_ids = gr.State(set())
1138
 
1139
+ # --- Unified Search Function ---
1140
  def unified_search(q, uploaded_image, a, offset, gender_ui):
1141
  start = 0
1142
  end = 12
1143
  filters = extract_intent_from_openai(q) if q.strip() else {}
1144
  gender_override = gender_ui if gender_ui else filters.get("gender")
1145
+
1146
  if uploaded_image is not None:
1147
  results = search_by_image(uploaded_image, a, start, end)
1148
  elif q.strip():
1149
  results = search_fashion(q, a, start, end, gender_override)
1150
  else:
1151
  results = []
1152
+
1153
  seen_ids = {r[1] for r in results}
1154
  return results, end, q, uploaded_image, gender_override, results, seen_ids
1155
 
1156
+ # --- Text Search Click Handler ---
1157
+ text_search_btn.click(
1158
+ unified_search,
1159
+ inputs=[query, gr.State(None), alpha, search_offset, gender_dropdown],
1160
+ outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1161
+ )
1162
+
1163
+ # --- Voice Search Click Handler ---
1164
+ voice_search_btn.click(
1165
+ handle_voice_search,
1166
+ inputs=[voice_input, alpha, search_offset, voice_gender_dropdown],
1167
+ outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1168
+ )
1169
+
1170
+ # --- Image Search Click Handler ---
1171
+ image_search_btn.click(
1172
+ unified_search,
1173
+ inputs=[gr.State(""), image_input, alpha, search_offset, image_gender_dropdown],
1174
+ outputs=[gallery, search_offset, current_query, current_image, current_gender, shown_results, shown_ids]
1175
+ )
1176
+
1177
+ # --- Load More Button Function ---
1178
  def load_more_fn(a, offset, q, img, gender_ui, prev_results, prev_ids):
1179
  start = offset
1180
  end = offset + 12
1181
  gender_override = gender_ui
1182
+
1183
  if img is not None:
1184
  new_results = search_by_image(img, a, start, end)
1185
  elif q.strip():
 
1190
  filtered_new = []
1191
  new_ids = set()
1192
  for item in new_results:
1193
+ img_obj, caption = item
1194
+ if caption not in prev_ids:
1195
  filtered_new.append(item)
1196
+ new_ids.add(caption)
1197
 
1198
  combined = prev_results + filtered_new
1199
  updated_ids = prev_ids.union(new_ids)
 
1200
 
1201
+ return combined, end, combined, updated_ids
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1202
 
1203
  load_more_btn.click(
1204
  load_more_fn,
 
1207
  )
1208
 
1209
  demo.launch()
1210
+
1211
+