opex792 commited on
Commit
7a48d04
·
verified ·
1 Parent(s): 857b65b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -31
app.py CHANGED
@@ -151,7 +151,10 @@ def get_embedding_from_db(conn, table_name, crc32_column, crc32_value, model_nam
151
  return None
152
 
153
  def get_movie_data_from_db(conn, movie_ids):
154
- """Получает данные фильмов из таблицы Movies по списку ID."""
 
 
 
155
  movie_data_dict = {}
156
  try:
157
  with conn.cursor() as cur:
@@ -161,14 +164,21 @@ def get_movie_data_from_db(conn, movie_ids):
161
  'Название', data->>'name',
162
  'Год', data->>'year',
163
  'Жанры', (SELECT string_agg(genre->>'name', ', ') FROM jsonb_array_elements(data->'genres') AS genre),
164
- 'Описание', COALESCE(data->>'description', '')
 
 
165
  ) AS prepared_json
166
  FROM "{movies_table}"
167
  WHERE id IN %s
168
  """, (tuple(movie_ids),))
169
  for movie_id, movie_data, prepared_json in cur.fetchall():
170
- prepared_string = f"Название: {prepared_json['Название']}\nГод: {prepared_json['Год']}\nЖанры: {prepared_json['Жанры']}\nОписание: {prepared_json['Описание']}"
171
- movie_data_dict[movie_id] = (movie_data, prepared_string)
 
 
 
 
 
172
  except Exception as e:
173
  logging.error(f"Ошибка при получении данных фильмов из БД: {e}")
174
  return movie_data_dict
@@ -207,7 +217,7 @@ def rerank_with_api(query, results, top_k, rerank_top_k=None, api_key=None):
207
 
208
  documents = []
209
  for movie_id, _ in results:
210
- movie_data, prepared_string = movie_data_dict.get(movie_id, (None, None))
211
  if movie_data:
212
  documents.append(prepared_string)
213
  else:
@@ -344,14 +354,16 @@ def search_movies_internal(query: str, top_k: int = 25, rerank_top_k: Optional[i
344
  formatted_results = []
345
  for movie_id, score in reranked_results:
346
  # Находим данные фильма
347
- movie_data, _ = movie_data_dict.get(movie_id, (None, None))
348
  if movie_data:
349
  formatted_results.append({
350
  "movie_id": movie_id,
351
- "name": movie_data['name'],
352
- "year": movie_data['year'],
353
- "genres": [genre['name'] for genre in movie_data['genres']],
354
- "description": movie_data.get('description', ''),
 
 
355
  "relevance_score": score if rerank_success else (
356
  movie_data_dict.get(movie_id, (None, None))[1] if movie_data_dict.get(movie_id,(None, None)) is not None else 0.0) # Сохраняем similarity, если нет реранжировки
357
  })
@@ -537,40 +549,80 @@ async def root():
537
  gap: 20px;
538
  }
539
  .movie-card {
 
540
  border-radius: 10px;
541
  overflow: hidden;
542
  background-color: #111;
543
  transition: transform 0.1s ease;
 
544
  }
545
  .movie-card:hover,
546
  .movie-card:focus {
547
  transform: scale(1.05);
548
  }
 
 
 
 
 
549
  .movie-info {
550
- padding: 10px;
 
 
 
 
 
 
 
551
  }
552
  .movie-title {
 
 
553
  font-size: 1.1em;
554
  font-weight: bold;
555
- margin-bottom: 5px;
 
 
556
  }
557
- .movie-year {
558
- font-size: 0.9em;
 
 
 
 
 
559
  color: #ccc;
560
- margin-bottom: 5px;
561
  }
562
- .movie-genres {
563
- font-size: 0.9em;
564
- margin-bottom: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
565
  }
566
- .movie-description {
 
567
  font-size: 0.9em;
568
  line-height: 1.4;
569
- margin-bottom: 5px;
570
- }
571
- .relevance-score {
572
- font-size: 0.8em;
573
- color: #ccc;
574
  }
575
 
576
  @media (min-width: 769px) {
@@ -591,6 +643,9 @@ async def root():
591
  .movie-grid {
592
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
593
  }
 
 
 
594
  .logo {
595
  font-size: 1.5em;
596
  }
@@ -599,6 +654,9 @@ async def root():
599
  .movie-grid {
600
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
601
  }
 
 
 
602
  .logo {
603
  font-size: 1.3em;
604
  }
@@ -621,7 +679,12 @@ async def root():
621
  <div class="movie-grid" id="movieGrid"></div>
622
  </main>
623
  </div>
624
-
 
 
 
 
 
625
  <script>
626
  document.getElementById('searchForm').addEventListener('submit', function(event) {
627
  event.preventDefault();
@@ -641,15 +704,20 @@ async def root():
641
  data.results.forEach(movie => {
642
  const movieCard = document.createElement('div');
643
  movieCard.className = 'movie-card';
 
644
  movieCard.innerHTML = `
645
- <div class="movie-info">
646
- <div class="movie-title">${movie.name}</div>
647
- <div class="movie-year">${movie.year}</div>
648
- <div class="movie-genres">${movie.genres.join(', ')}</div>
649
- <div class="movie-description">${movie.description}</div>
650
- <div class="relevance-score">Релевантность: ${movie.relevance_score.toFixed(4)}</div>
651
  </div>
 
 
652
  `;
 
 
 
653
  movieGrid.appendChild(movieCard);
654
  });
655
  } else {
@@ -661,6 +729,25 @@ async def root():
661
  movieGrid.innerHTML = '<p>Произошла ошибка при поиске.</p>';
662
  });
663
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  </script>
665
  </body>
666
  </html>
 
151
  return None
152
 
153
  def get_movie_data_from_db(conn, movie_ids):
154
+ """
155
+ Получает данные фильмов из таблицы Movies по списку ID,
156
+ включая предположительно URL-адрес постера и рейтинг.
157
+ """
158
  movie_data_dict = {}
159
  try:
160
  with conn.cursor() as cur:
 
164
  'Название', data->>'name',
165
  'Год', data->>'year',
166
  'Жанры', (SELECT string_agg(genre->>'name', ', ') FROM jsonb_array_elements(data->'genres') AS genre),
167
+ 'Описание', COALESCE(data->>'description', ''),
168
+ 'Постер', data->'poster'->'previewUrl',
169
+ 'Рейтинг', data->'rating'->'kp'
170
  ) AS prepared_json
171
  FROM "{movies_table}"
172
  WHERE id IN %s
173
  """, (tuple(movie_ids),))
174
  for movie_id, movie_data, prepared_json in cur.fetchall():
175
+ prepared_string = (
176
+ f"Название: {prepared_json['Название']}\n"
177
+ f"Год: {prepared_json['Год']}\n"
178
+ f"Жанры: {prepared_json['Жанры']}\n"
179
+ f"Описание: {prepared_json['Описание']}"
180
+ )
181
+ movie_data_dict[movie_id] = (movie_data, prepared_string, prepared_json)
182
  except Exception as e:
183
  logging.error(f"Ошибка при получении данных фильмов из БД: {e}")
184
  return movie_data_dict
 
217
 
218
  documents = []
219
  for movie_id, _ in results:
220
+ movie_data, prepared_string, _ = movie_data_dict.get(movie_id, (None, None, None))
221
  if movie_data:
222
  documents.append(prepared_string)
223
  else:
 
354
  formatted_results = []
355
  for movie_id, score in reranked_results:
356
  # Находим данные фильма
357
+ movie_data, _, prepared_json = movie_data_dict.get(movie_id, (None, None, None))
358
  if movie_data:
359
  formatted_results.append({
360
  "movie_id": movie_id,
361
+ "name": prepared_json['Название'],
362
+ "year": prepared_json['Год'],
363
+ "genres": prepared_json['Жанры'],
364
+ "description": prepared_json['Описание'],
365
+ "poster_preview_url": prepared_json['Постер'],
366
+ "rating_kp": prepared_json['Рейтинг'],
367
  "relevance_score": score if rerank_success else (
368
  movie_data_dict.get(movie_id, (None, None))[1] if movie_data_dict.get(movie_id,(None, None)) is not None else 0.0) # Сохраняем similarity, если нет реранжировки
369
  })
 
549
  gap: 20px;
550
  }
551
  .movie-card {
552
+ position: relative;
553
  border-radius: 10px;
554
  overflow: hidden;
555
  background-color: #111;
556
  transition: transform 0.1s ease;
557
+ cursor: pointer;
558
  }
559
  .movie-card:hover,
560
  .movie-card:focus {
561
  transform: scale(1.05);
562
  }
563
+ .movie-poster {
564
+ width: 100%;
565
+ height: 350px;
566
+ object-fit: cover;
567
+ }
568
  .movie-info {
569
+ position: absolute;
570
+ top: 0;
571
+ left: 0;
572
+ width: 100%;
573
+ height: 100%;
574
+ display: flex;
575
+ flex-direction: column;
576
+ justify-content: space-between;
577
  }
578
  .movie-title {
579
+ width: 100%;
580
+ background-color: #111;
581
  font-size: 1.1em;
582
  font-weight: bold;
583
+ text-align: center;
584
+ padding: 10px;
585
+ box-sizing: border-box;
586
  }
587
+ .top-info {
588
+ display: flex;
589
+ justify-content: space-between;
590
+ padding: 10px;
591
+ }
592
+ .movie-year, .movie-rating {
593
+ font-size: 0.8em;
594
  color: #ccc;
 
595
  }
596
+ .movie-details {
597
+ display: none;
598
+ position: fixed;
599
+ top: 0;
600
+ left: 0;
601
+ width: 100%;
602
+ height: 100%;
603
+ background-color: rgba(0, 0, 0, 0.9);
604
+ z-index: 100;
605
+ overflow-y: auto;
606
+ }
607
+ .movie-details-content {
608
+ padding: 20px;
609
+ }
610
+ .close-button {
611
+ position: absolute;
612
+ top: 10px;
613
+ right: 10px;
614
+ background: none;
615
+ border: none;
616
+ color: #fff;
617
+ font-size: 30px;
618
+ cursor: pointer;
619
+ z-index: 101;
620
  }
621
+ .movie-description-modal {
622
+ color: #fff;
623
  font-size: 0.9em;
624
  line-height: 1.4;
625
+ margin-top: 20px;
 
 
 
 
626
  }
627
 
628
  @media (min-width: 769px) {
 
643
  .movie-grid {
644
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
645
  }
646
+ .movie-poster {
647
+ height: 225px;
648
+ }
649
  .logo {
650
  font-size: 1.5em;
651
  }
 
654
  .movie-grid {
655
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
656
  }
657
+ .movie-poster {
658
+ height: 180px;
659
+ }
660
  .logo {
661
  font-size: 1.3em;
662
  }
 
679
  <div class="movie-grid" id="movieGrid"></div>
680
  </main>
681
  </div>
682
+ <div id="movieDetails" class="movie-details">
683
+ <div class="movie-details-content">
684
+ <button class="close-button" onclick="closeMovieDetails()">×</button>
685
+ <div id="movieDescription" class="movie-description-modal"></div>
686
+ </div>
687
+ </div>
688
  <script>
689
  document.getElementById('searchForm').addEventListener('submit', function(event) {
690
  event.preventDefault();
 
704
  data.results.forEach(movie => {
705
  const movieCard = document.createElement('div');
706
  movieCard.className = 'movie-card';
707
+ const ratingColor = getRatingColor(movie.rating_kp);
708
  movieCard.innerHTML = `
709
+ <img src="${movie.poster_preview_url}" alt="${movie.name}" class="movie-poster">
710
+ <div class="movie-info">
711
+ <div class="top-info">
712
+ <span class="movie-year">${movie.year}</span>
713
+ <span class="movie-rating" style="color: ${ratingColor};">${movie.rating_kp}</span>
 
714
  </div>
715
+ <div class="movie-title">${movie.name}</div>
716
+ </div>
717
  `;
718
+ movieCard.addEventListener('click', () => {
719
+ openMovieDetails(movie.description);
720
+ });
721
  movieGrid.appendChild(movieCard);
722
  });
723
  } else {
 
729
  movieGrid.innerHTML = '<p>Произошла ошибка при поиске.</p>';
730
  });
731
  }
732
+ function getRatingColor(rating) {
733
+ if (rating >= 7) {
734
+ return 'green';
735
+ } else if (rating >= 5) {
736
+ return 'orange';
737
+ } else {
738
+ return 'red';
739
+ }
740
+ }
741
+ function openMovieDetails(description) {
742
+ const movieDetails = document.getElementById('movieDetails');
743
+ const movieDescription = document.getElementById('movieDescription');
744
+ movieDescription.textContent = description;
745
+ movieDetails.style.display = 'block';
746
+ }
747
+
748
+ function closeMovieDetails() {
749
+ document.getElementById('movieDetails').style.display = 'none';
750
+ }
751
  </script>
752
  </body>
753
  </html>