opex792 commited on
Commit
efb7248
·
verified ·
1 Parent(s): bbf6f5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -17
app.py CHANGED
@@ -12,6 +12,11 @@ import logging
12
  from sklearn.preprocessing import normalize
13
  from concurrent.futures import ThreadPoolExecutor
14
  import requests
 
 
 
 
 
15
 
16
  # Настройка логирования
17
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@@ -70,6 +75,9 @@ batch_size = 32
70
  # Количество потоков для параллельной обработки
71
  num_threads = 5
72
 
 
 
 
73
  def get_db_connection():
74
  """Устанавливает соединение с базой данных."""
75
  try:
@@ -354,9 +362,9 @@ def rerank_with_api(query, results, top_k):
354
  except requests.exceptions.RequestException as e:
355
  logging.error(f"Ошибка при запросе к API реранжировщика: {e}")
356
  return []
357
-
358
- def search_movies(query, top_k=25):
359
- """Выполняет поиск фильмов по запросу."""
360
  global search_in_progress
361
  search_in_progress = True
362
  start_time = time.time()
@@ -364,7 +372,7 @@ def search_movies(query, top_k=25):
364
  try:
365
  conn = get_db_connection()
366
  if conn is None:
367
- return "<p>Ошибка подключения к базе данных</p>"
368
 
369
  query_crc32 = calculate_crc32(query)
370
  query_embedding = get_embedding_from_db(conn, query_cache_table, "query_crc32", query_crc32, model_name)
@@ -416,34 +424,65 @@ def search_movies(query, top_k=25):
416
  movie_data_dict = get_movie_data_from_db(conn, movie_ids)
417
  conn.close()
418
 
419
- output = ""
420
  for movie_id, score in reranked_results:
421
  # Находим данные фильма
422
  movie_data, _ = movie_data_dict.get(movie_id, (None, None))
423
  if movie_data:
424
- output += f"<h3>{movie_data['name']} ({movie_data['year']})</h3>\n"
425
- output += f"<p><strong>Жанры:</strong> {', '.join([genre['name'] for genre in movie_data['genres']])}</p>\n"
426
- output += f"<p><strong>Описание:</strong> {movie_data.get('description', '')}</p>\n"
427
- output += f"<p><strong>Релевантность (reranker score):</strong> {score:.4f}</p>\n"
428
- output += "<hr>\n"
 
 
 
429
  else:
430
  logging.warning(f"Данные для фильма с ID {movie_id} не найдены в БД.")
431
 
432
  search_time = time.time() - start_time
433
  logging.info(f"Поиск выполнен за {search_time:.2f} секунд.")
434
 
435
- return f"<p>Время поиска: {search_time:.2f} сек</p>{output}"
436
 
437
  except Exception as e:
438
  logging.error(f"Ошибка при выполнении поиска: {e}")
439
- return "<p>Произошла ошибка при выполнении поиска.</p>"
440
 
441
  finally:
442
  search_in_progress = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
- # Запускаем обработку фильмов в отдельном потоке
445
- processing_thread = threading.Thread(target=process_movies)
446
- processing_thread.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
447
 
448
  # Создаем интерфейс Gradio
449
  iface = gr.Interface(
@@ -454,5 +493,14 @@ iface = gr.Interface(
454
  description="Введите описание фильма, который вы ищете, и система найдет наиболее похожие фильмы."
455
  )
456
 
457
- # Запускаем интерфейс
458
- iface.launch()
 
 
 
 
 
 
 
 
 
 
12
  from sklearn.preprocessing import normalize
13
  from concurrent.futures import ThreadPoolExecutor
14
  import requests
15
+ from fastapi import FastAPI, HTTPException, Query
16
+ from typing import List
17
+ import uvicorn
18
+ from starlette.requests import Request
19
+ from starlette.responses import HTMLResponse
20
 
21
  # Настройка логирования
22
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
75
  # Количество потоков для параллельной обработки
76
  num_threads = 5
77
 
78
+ # FastAPI приложение
79
+ app = FastAPI()
80
+
81
  def get_db_connection():
82
  """Устанавливает соединение с базой данных."""
83
  try:
 
362
  except requests.exceptions.RequestException as e:
363
  logging.error(f"Ошибка при запросе к API реранжировщика: {e}")
364
  return []
365
+
366
+ def search_movies_internal(query: str, top_k: int = 25):
367
+ """Внутренняя функция для поиска фильмов по запросу (используется и в Gradio, и в API)."""
368
  global search_in_progress
369
  search_in_progress = True
370
  start_time = time.time()
 
372
  try:
373
  conn = get_db_connection()
374
  if conn is None:
375
+ raise Exception("Ошибка подключения к базе данных")
376
 
377
  query_crc32 = calculate_crc32(query)
378
  query_embedding = get_embedding_from_db(conn, query_cache_table, "query_crc32", query_crc32, model_name)
 
424
  movie_data_dict = get_movie_data_from_db(conn, movie_ids)
425
  conn.close()
426
 
427
+ formatted_results = []
428
  for movie_id, score in reranked_results:
429
  # Находим данные фильма
430
  movie_data, _ = movie_data_dict.get(movie_id, (None, None))
431
  if movie_data:
432
+ formatted_results.append({
433
+ "movie_id": movie_id,
434
+ "name": movie_data['name'],
435
+ "year": movie_data['year'],
436
+ "genres": [genre['name'] for genre in movie_data['genres']],
437
+ "description": movie_data.get('description', ''),
438
+ "relevance_score": score
439
+ })
440
  else:
441
  logging.warning(f"Данные для фильма с ID {movie_id} не найдены в БД.")
442
 
443
  search_time = time.time() - start_time
444
  logging.info(f"Поиск выполнен за {search_time:.2f} секунд.")
445
 
446
+ return formatted_results, search_time
447
 
448
  except Exception as e:
449
  logging.error(f"Ошибка при выполнении поиска: {e}")
450
+ raise
451
 
452
  finally:
453
  search_in_progress = False
454
+
455
+ def search_movies(query, top_k=25):
456
+ """Функция поиска фильмов для Gradio интерфейса."""
457
+ try:
458
+ results, search_time = search_movies_internal(query, top_k)
459
+ output = f"<p>Время поиска: {search_time:.2f} сек</p>"
460
+ for result in results:
461
+ output += f"<h3>{result['name']} ({result['year']})</h3>\n"
462
+ output += f"<p><strong>Жанры:</strong> {', '.join(result['genres'])}</p>\n"
463
+ output += f"<p><strong>Описание:</strong> {result['description']}</p>\n"
464
+ output += f"<p><strong>Релевантность (reranker score):</strong> {result['relevance_score']:.4f}</p>\n"
465
+ output += "<hr>\n"
466
+ return output
467
+ except Exception as e:
468
+ return f"<p>Произошла ошибка при выполнении поиска: {e}</p>"
469
 
470
+ @app.get("/search/", response_model=List[dict])
471
+ async def api_search_movies(query: str = Query(..., description="Поисковый ��апрос"), top_k: int = Query(25, description="Количество возвращаемых результатов")):
472
+ """API endpoint для поиска фильмов."""
473
+ try:
474
+ results, _ = search_movies_internal(query, top_k)
475
+ return results
476
+ except Exception as e:
477
+ raise HTTPException(status_code=500, detail=str(e))
478
+
479
+ # Запускаем обработку фильмов в отдельном потоке (если ещё не запущена)
480
+ if not 'processing_thread' in globals():
481
+ processing_thread = threading.Thread(target=process_movies)
482
+ processing_thread.start()
483
+ elif not processing_thread.is_alive():
484
+ processing_thread = threading.Thread(target=process_movies)
485
+ processing_thread.start()
486
 
487
  # Создаем интерфейс Gradio
488
  iface = gr.Interface(
 
493
  description="Введите описание фильма, который вы ищете, и система найдет наиболее похожие фильмы."
494
  )
495
 
496
+ # Встраиваем Gradio в FastAPI
497
+ app = gr.mount_gradio_app(app, iface, path="/")
498
+
499
+ # Рут-эндпоинт для демонстрации, что FastAPI работает
500
+ @app.get("/api")
501
+ async def root():
502
+ return {"message": "FastAPI is running. Access the API documentation at /docs"}
503
+
504
+ # Запускаем FastAPI
505
+ if __name__ == "__main__":
506
+ uvicorn.run(app, host="0.0.0.0", port=7860)