Spaces:
Runtime error
Runtime error
Anusha806
commited on
Commit
·
f974ed7
1
Parent(s):
4e4e05b
commit39
Browse files
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: #
|
| 1253 |
text-align: center;
|
| 1254 |
margin-bottom: 1rem;
|
| 1255 |
}
|
| 1256 |
|
|
|
|
| 1257 |
.gr-tab {
|
| 1258 |
border-radius: 12px !important;
|
| 1259 |
background-color: #ffffff !important;
|
| 1260 |
-
|
|
|
|
| 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 |
-
|
| 1273 |
-
|
| 1274 |
-
|
| 1275 |
-
|
| 1276 |
-
|
| 1277 |
-
|
| 1278 |
-
|
| 1279 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 1312 |
-
|
| 1313 |
-
height:
|
| 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(
|
| 1327 |
-
|
| 1328 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1329 |
|
| 1330 |
with gr.Tab("🎙️ Voice Search"):
|
| 1331 |
voice_input = gr.Audio(label="Speak Your Query", type="filepath")
|
| 1332 |
-
voice_gender_dropdown = gr.Dropdown(
|
|
|
|
|
|
|
|
|
|
| 1333 |
voice_search_btn = gr.Button("Search by Voice")
|
| 1334 |
|
| 1335 |
with gr.Tab("Image Search"):
|
| 1336 |
-
image_input = gr.Image(
|
| 1337 |
-
|
| 1338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1339 |
|
| 1340 |
gallery = gr.Gallery(label="Search Results", columns=6, height=None)
|
| 1341 |
load_more_btn = gr.Button("Load More")
|
| 1342 |
|
| 1343 |
-
# UI
|
| 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 |
-
|
|
|
|
| 1380 |
filtered_new.append(item)
|
| 1381 |
-
new_ids.add(
|
| 1382 |
|
| 1383 |
combined = prev_results + filtered_new
|
| 1384 |
updated_ids = prev_ids.union(new_ids)
|
| 1385 |
-
return combined, end, combined, updated_ids
|
| 1386 |
|
| 1387 |
-
|
| 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 |
+
|