import os import gradio as gr from msrest.authentication import CognitiveServicesCredentials from azure.cognitiveservices.search.visualsearch import VisualSearchClient from azure.cognitiveservices.search.visualsearch.models import VisualSearchRequest, ImageInfo # Загружаем из Secrets BING_KEY = os.environ["BING_KEY"] BING_ENDPOINT = os.environ["BING_ENDPOINT"] # Инициализируем клиент Azure Visual Search credentials = CognitiveServicesCredentials(BING_KEY) client = VisualSearchClient(endpoint=BING_ENDPOINT, credentials=credentials) def reverse_search(image, filter_text): """ 1) Преобразуем PIL.Image в байт-стрим для Azure 2) Делаем запрос Visual Search 3) Извлекаем PagesIncluding → title + url 4) Фильтруем по filter_text, если передан """ # Преобразуем картинку в байты JPEG import io buf = io.BytesIO() image.save(buf, format="JPEG") buf.seek(0) # Формируем и отправляем запрос request = VisualSearchRequest(image=ImageInfo(stream=buf)) response = client.images.visual_search(request=request) results = [] # Ищем все PagesIncluding в Actions if response.tags: for tag in response.tags: if not tag.actions: continue for action in tag.actions: if hasattr(action, "pages_including") and action.pages_including: for page in action.pages_including: title = page.name or "" url = page.web_search_url or "" if filter_text.lower() in title.lower() or not filter_text: results.append({"title": title, "url": url}) # Убираем дубликаты, оставляя первые вхождения seen = set() unique = [] for item in results: key = (item["title"], item["url"]) if key not in seen: seen.add(key) unique.append(item) return unique # Интерфейс Gradio iface = gr.Interface( fn=reverse_search, inputs=[ gr.Image(type="pil", label="Постер/кадр фильма"), gr.Textbox(label="Фильтр по названию (необязательно)") ], outputs=gr.JSON(label="Найденные страницы"), examples=[ ["example_poster.jpg", ""] ], title="Movie Reverse Image Search", description="Загрузи постер или кадр, получи ссылки на страницы (IMDb, Wiki, КиноПоиск)" ) if __name__ == "__main__": iface.launch()