opex792 commited on
Commit
17d8908
·
verified ·
1 Parent(s): b98faae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -33
app.py CHANGED
@@ -16,7 +16,9 @@ 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')
@@ -57,6 +59,15 @@ movies_table = "Movies" # Имя таблицы с фильмами
57
  # FastAPI приложение
58
  app = FastAPI()
59
 
 
 
 
 
 
 
 
 
 
60
  def get_db_connection():
61
  """Устанавливает соединение с базой данных."""
62
  try:
@@ -159,7 +170,7 @@ def get_movie_data_from_db(conn, movie_ids):
159
  logging.error(f"Ошибка при получении данных фильмов из БД: {e}")
160
  return movie_data_dict
161
 
162
- def rerank_with_api(query, results, top_k):
163
  """Переранжирует результаты с помощью Jina AI Reranker API."""
164
  logging.info(f"Начало переранжирования для запроса: '{query}'")
165
 
@@ -184,7 +195,7 @@ def rerank_with_api(query, results, top_k):
184
  data = {
185
  "model": JINA_RERANKER_MODEL,
186
  "query": query,
187
- "top_n": top_k,
188
  "documents": documents
189
  }
190
  logging.info(f"Отправка данных на реранжировку (documents count): {len(data['documents'])}")
@@ -211,7 +222,7 @@ def rerank_with_api(query, results, top_k):
211
  logging.error(f"Ошибка при запросе к API реранжировщика: {e}")
212
  return []
213
 
214
- def search_movies_internal(query: str, top_k: int = 25):
215
  """Внутренняя функция для поиска фильмов по запросу (используется и в Gradio, и в API)."""
216
  start_time = time.time()
217
 
@@ -263,7 +274,7 @@ def search_movies_internal(query: str, top_k: int = 25):
263
  conn.close()
264
 
265
  # Переранжируем результаты с помощью API
266
- reranked_results = rerank_with_api(query, results, top_k)
267
 
268
  conn = get_db_connection()
269
  movie_ids = [movie_id for movie_id, _ in reranked_results]
@@ -295,41 +306,106 @@ def search_movies_internal(query: str, top_k: int = 25):
295
  logging.error(f"Ошибка при выполнении поиска: {e}")
296
  raise
297
 
298
- def search_movies(query, top_k=25):
299
- """Функция поиска фильмов для Gradio интерфейса."""
300
- try:
301
- results, search_time = search_movies_internal(query, top_k)
302
- output = f"<p>Время поиска: {search_time:.2f} сек</p>"
303
- for result in results:
304
- output += f"<h3>{result['name']} ({result['year']})</h3>\n"
305
- output += f"<p><strong>Жанры:</strong> {', '.join(result['genres'])}</p>\n"
306
- output += f"<p><strong>Описание:</strong> {result['description']}</p>\n"
307
- output += f"<p><strong>Релевантность (reranker score):</strong> {result['relevance_score']:.4f}</p>\n"
308
- output += "<hr>\n"
309
- return output
310
- except Exception as e:
311
- return f"<p>Произошла ошибка при выполнении поиска: {e}</p>"
312
-
313
  @app.get("/search/", response_model=List[dict])
314
- async def api_search_movies(query: str = Query(..., description="Поисковый запрос"), top_k: int = Query(25, description="Количество возвращаемых результатов")):
 
 
315
  """API endpoint для поиска фильмов."""
316
  try:
317
- results, _ = search_movies_internal(query, top_k)
318
  return results
319
  except Exception as e:
320
  raise HTTPException(status_code=500, detail=str(e))
321
 
322
- # Создаем интерфейс Gradio
323
- iface = gr.Interface(
324
- fn=search_movies,
325
- inputs=gr.Textbox(lines=2, placeholder="Введите запрос для поиска фильмов..."),
326
- outputs=gr.HTML(label="Результаты поиска"),
327
- title="Семантический поиск фильмов",
328
- description="Введите описание фильма, который вы ищете, и система найдет наиболее похожие фильмы."
329
- )
330
-
331
- # Встраиваем Gradio в FastAPI
332
- app = gr.mount_gradio_app(app, iface, path="/")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
 
334
  # Рут-эндпоинт для демонстрации, что FastAPI работает
335
  @app.get("/api")
 
16
  from typing import List
17
  import uvicorn
18
  from starlette.requests import Request
19
+ from starlette.responses import HTMLResponse, JSONResponse
20
+ from fastapi.responses import HTMLResponse
21
+ from fastapi.middleware.cors import CORSMiddleware
22
 
23
  # Настройка логирования
24
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
59
  # FastAPI приложение
60
  app = FastAPI()
61
 
62
+ # Разрешаем CORS, чтобы Gradio мог обращаться к API
63
+ app.add_middleware(
64
+ CORSMiddleware,
65
+ allow_origins=["*"], # Разрешаем все источники, в продакшене лучше указать конкретные
66
+ allow_credentials=True,
67
+ allow_methods=["*"],
68
+ allow_headers=["*"],
69
+ )
70
+
71
  def get_db_connection():
72
  """Устанавливает соединение с базой данных."""
73
  try:
 
170
  logging.error(f"Ошибка при получении данных фильмов из БД: {e}")
171
  return movie_data_dict
172
 
173
+ def rerank_with_api(query, results, top_k, rerank_top_k=None):
174
  """Переранжирует результаты с помощью Jina AI Reranker API."""
175
  logging.info(f"Начало переранжирования для запроса: '{query}'")
176
 
 
195
  data = {
196
  "model": JINA_RERANKER_MODEL,
197
  "query": query,
198
+ "top_n": rerank_top_k or top_k*2,
199
  "documents": documents
200
  }
201
  logging.info(f"Отправка данных на реранжировку (documents count): {len(data['documents'])}")
 
222
  logging.error(f"Ошибка при запросе к API реранжировщика: {e}")
223
  return []
224
 
225
+ def search_movies_internal(query: str, top_k: int = 25, rerank_top_k: int = None):
226
  """Внутренняя функция для поиска фильмов по запросу (используется и в Gradio, и в API)."""
227
  start_time = time.time()
228
 
 
274
  conn.close()
275
 
276
  # Переранжируем результаты с помощью API
277
+ reranked_results = rerank_with_api(query, results, top_k, rerank_top_k)
278
 
279
  conn = get_db_connection()
280
  movie_ids = [movie_id for movie_id, _ in reranked_results]
 
306
  logging.error(f"Ошибка при выполнении поиска: {e}")
307
  raise
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  @app.get("/search/", response_model=List[dict])
310
+ async def api_search_movies(query: str = Query(..., description="Поисковый запрос"),
311
+ top_k: int = Query(25, description="Количество возвращаемых результатов"),
312
+ rerank_top_k: int = Query(None, description="Количество фильмов для передачи в реранкер (если не указано, то top_k*2)")):
313
  """API endpoint для поиска фильмов."""
314
  try:
315
+ results, _ = search_movies_internal(query, top_k, rerank_top_k)
316
  return results
317
  except Exception as e:
318
  raise HTTPException(status_code=500, detail=str(e))
319
 
320
+ # Рут-эндпоинт, который отдаёт HTML-страницу
321
+ @app.get("/", response_class=HTMLResponse)
322
+ async def root():
323
+ return """
324
+ <!DOCTYPE html>
325
+ <html>
326
+ <head>
327
+ <title>Семантический поиск фильмов</title>
328
+ <style>
329
+ body {
330
+ font-family: sans-serif;
331
+ margin: 20px;
332
+ }
333
+ h1 {
334
+ text-align: center;
335
+ }
336
+ label {
337
+ display: block;
338
+ margin-bottom: 5px;
339
+ }
340
+ input[type="text"] {
341
+ width: 100%;
342
+ padding: 10px;
343
+ margin-bottom: 10px;
344
+ border: 1px solid #ccc;
345
+ box-sizing: border-box;
346
+ }
347
+ button {
348
+ padding: 10px 20px;
349
+ background-color: #4CAF50;
350
+ color: white;
351
+ border: none;
352
+ cursor: pointer;
353
+ }
354
+ #results {
355
+ margin-top: 20px;
356
+ }
357
+ .movie {
358
+ border: 1px solid #ccc;
359
+ padding: 10px;
360
+ margin-bottom: 10px;
361
+ }
362
+ .movie h3 {
363
+ margin-top: 0;
364
+ }
365
+ </style>
366
+ </head>
367
+ <body>
368
+ <h1>Семантический поиск фильмов</h1>
369
+ <label for="query">Введите запрос:</label>
370
+ <input type="text" id="query" name="query" placeholder="Введите описание фильма...">
371
+ <button onclick="searchMovies()">Искать</button>
372
+ <div id="results"></div>
373
+
374
+ <script>
375
+ function searchMovies() {
376
+ const query = document.getElementById("query").value;
377
+ const resultsDiv = document.getElementById("results");
378
+ resultsDiv.innerHTML = "<p>Поиск...</p>";
379
+
380
+ fetch(`/search/?query=${encodeURIComponent(query)}`)
381
+ .then(response => response.json())
382
+ .then(data => {
383
+ resultsDiv.innerHTML = "";
384
+ if (data.length === 0) {
385
+ resultsDiv.innerHTML = "<p>Ничего не найдено.</p>";
386
+ } else {
387
+ data.forEach(movie => {
388
+ const movieDiv = document.createElement("div");
389
+ movieDiv.classList.add("movie");
390
+ movieDiv.innerHTML = `
391
+ <h3>${movie.name} (${movie.year})</h3>
392
+ <p><strong>Жанры:</strong> ${movie.genres.join(", ")}</p>
393
+ <p><strong>Описание:</strong> ${movie.description}</p>
394
+ <p><strong>Релевантность:</strong> ${movie.relevance_score.toFixed(4)}</p>
395
+ `;
396
+ resultsDiv.appendChild(movieDiv);
397
+ });
398
+ }
399
+ })
400
+ .catch(error => {
401
+ console.error("Ошибка:", error);
402
+ resultsDiv.innerHTML = "<p>Произошла ошибка при поиске.</p>";
403
+ });
404
+ }
405
+ </script>
406
+ </body>
407
+ </html>
408
+ """
409
 
410
  # Рут-эндпоинт для демонстрации, что FastAPI работает
411
  @app.get("/api")