opex792 commited on
Commit
8cbf970
·
verified ·
1 Parent(s): 4725242

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -39
app.py CHANGED
@@ -7,7 +7,6 @@ import queue
7
  import torch
8
  import psycopg2
9
  import zlib
10
- import numpy as np
11
  from urllib.parse import urlparse
12
 
13
  # Настройки базы данных PostgreSQL
@@ -76,32 +75,37 @@ def setup_database():
76
  return
77
 
78
  with conn.cursor() as cur:
79
- # Создаем расширение pgvector
80
  cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
81
 
 
 
 
82
  # Создаем таблицу для хранения эмбеддингов фильмов
83
  cur.execute(f"""
84
- CREATE TABLE IF NOT EXISTS {embeddings_table} (
85
  movie_id INTEGER PRIMARY KEY,
86
  embedding_crc32 BIGINT,
87
  string_crc32 BIGINT,
88
  model_name TEXT,
89
- embedding float8[]
90
  );
91
- CREATE INDEX IF NOT EXISTS idx_movie_embeddings_crc32 ON {embeddings_table} (string_crc32);
 
92
  """)
93
 
94
  # Создаем таблицу для кэширования запросов
95
  cur.execute(f"""
96
- CREATE TABLE IF NOT EXISTS {query_cache_table} (
97
  query_crc32 BIGINT PRIMARY KEY,
98
  query TEXT,
99
  model_name TEXT,
100
- embedding float8[],
101
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
102
  );
103
- CREATE INDEX IF NOT EXISTS idx_query_cache_crc32 ON {query_cache_table} (query_crc32);
104
- CREATE INDEX IF NOT EXISTS idx_query_cache_created ON {query_cache_table} (created_at);
 
105
  """)
106
 
107
  conn.commit()
@@ -138,14 +142,6 @@ def get_movies_without_embeddings():
138
  conn.close()
139
  return movies_to_process
140
 
141
- def vector_to_list(vector):
142
- """Преобразует вектор PyTorch в список float."""
143
- return vector.detach().cpu().numpy().tolist()
144
-
145
- def list_to_vector(lst):
146
- """Преобразует список float в вектор PyTorch."""
147
- return torch.tensor(lst)
148
-
149
  def get_embedding_from_db(conn, table_name, crc32_column, crc32_value, model_name):
150
  """Получает эмбеддинг из базы данных."""
151
  with conn.cursor() as cur:
@@ -153,12 +149,11 @@ def get_embedding_from_db(conn, table_name, crc32_column, crc32_value, model_nam
153
  (crc32_value, model_name))
154
  result = cur.fetchone()
155
  if result and result[0]:
156
- return list_to_vector(result[0])
157
  return None
158
 
159
  def insert_embedding(conn, table_name, movie_id, embedding_crc32, string_crc32, embedding):
160
  """Вставляет эмбеддинг в базу данных."""
161
- embedding_list = vector_to_list(embedding)
162
  with conn.cursor() as cur:
163
  try:
164
  cur.execute(f"""
@@ -166,7 +161,7 @@ def insert_embedding(conn, table_name, movie_id, embedding_crc32, string_crc32,
166
  (movie_id, embedding_crc32, string_crc32, model_name, embedding)
167
  VALUES (%s, %s, %s, %s, %s)
168
  ON CONFLICT (movie_id) DO NOTHING
169
- """, (movie_id, embedding_crc32, string_crc32, model_name, embedding_list))
170
  conn.commit()
171
  return True
172
  except Exception as e:
@@ -222,7 +217,7 @@ def process_movies():
222
 
223
  if existing_embedding is None:
224
  embedding = encode_string(embedding_string)
225
- embedding_crc32 = calculate_crc32(str(vector_to_list(embedding)))
226
 
227
  if insert_embedding(conn, embeddings_table, movie['id'], embedding_crc32, string_crc32, embedding):
228
  print(f"Сохранен эмбеддинг для '{movie['name']}'")
@@ -239,15 +234,12 @@ def get_movie_embeddings(conn):
239
  """Загружает все эмбеддинги фильмов из базы данных."""
240
  movie_embeddings = {}
241
  with conn.cursor() as cur:
242
- cur.execute(f"""
243
- SELECT e.movie_id, e.embedding
244
- FROM {embeddings_table} e
245
- """)
246
  for movie_id, embedding in cur.fetchall():
247
  # Находим название фильма по ID
248
  for movie in movies_data:
249
  if movie['id'] == movie_id:
250
- movie_embeddings[movie['name']] = list_to_vector(embedding)
251
  break
252
  return movie_embeddings
253
 
@@ -267,29 +259,38 @@ def search_movies(query, top_k=10):
267
 
268
  if query_embedding is None:
269
  query_embedding = encode_string(query)
270
- embedding_list = vector_to_list(query_embedding)
271
 
272
  with conn.cursor() as cur:
273
  cur.execute(f"""
274
  INSERT INTO {query_cache_table} (query_crc32, query, model_name, embedding)
275
  VALUES (%s, %s, %s, %s)
276
  ON CONFLICT (query_crc32) DO NOTHING
277
- """, (query_crc32, query, model_name, embedding_list))
278
  conn.commit()
279
 
280
- movie_embeddings = get_movie_embeddings(conn)
281
-
282
- similarities = []
283
- for title, movie_embedding in movie_embeddings.items():
284
- similarity = util.pytorch_cos_sim(query_embedding, movie_embedding).item()
285
- similarities.append((title, similarity))
286
-
287
- similarities.sort(key=lambda x: x[1], reverse=True)
288
- top_results = similarities[:top_k]
 
289
 
290
  results_html = "<ol>"
291
- for title, score in top_results:
292
- results_html += f"<li><strong>{title}</strong> (Сходство: {score:.4f})</li>"
 
 
 
 
 
 
 
 
 
293
  results_html += "</ol>"
294
 
295
  search_time = time.time() - start_time
 
7
  import torch
8
  import psycopg2
9
  import zlib
 
10
  from urllib.parse import urlparse
11
 
12
  # Настройки базы данных PostgreSQL
 
75
  return
76
 
77
  with conn.cursor() as cur:
78
+ # Создаем расширение pgvector если его нет
79
  cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
80
 
81
+ # Удаляем существующие таблицы если они есть
82
+ cur.execute(f"DROP TABLE IF EXISTS {embeddings_table}, {query_cache_table};")
83
+
84
  # Создаем таблицу для хранения эмбеддингов фильмов
85
  cur.execute(f"""
86
+ CREATE TABLE {embeddings_table} (
87
  movie_id INTEGER PRIMARY KEY,
88
  embedding_crc32 BIGINT,
89
  string_crc32 BIGINT,
90
  model_name TEXT,
91
+ embedding vector(1024)
92
  );
93
+ CREATE INDEX ON {embeddings_table} USING ivfflat (embedding vector_cosine_ops);
94
+ CREATE INDEX ON {embeddings_table} (string_crc32);
95
  """)
96
 
97
  # Создаем таблицу для кэширования запросов
98
  cur.execute(f"""
99
+ CREATE TABLE {query_cache_table} (
100
  query_crc32 BIGINT PRIMARY KEY,
101
  query TEXT,
102
  model_name TEXT,
103
+ embedding vector(1024),
104
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
105
  );
106
+ CREATE INDEX ON {query_cache_table} USING ivfflat (embedding vector_cosine_ops);
107
+ CREATE INDEX ON {query_cache_table} (query_crc32);
108
+ CREATE INDEX ON {query_cache_table} (created_at);
109
  """)
110
 
111
  conn.commit()
 
142
  conn.close()
143
  return movies_to_process
144
 
 
 
 
 
 
 
 
 
145
  def get_embedding_from_db(conn, table_name, crc32_column, crc32_value, model_name):
146
  """Получает эмбеддинг из базы данных."""
147
  with conn.cursor() as cur:
 
149
  (crc32_value, model_name))
150
  result = cur.fetchone()
151
  if result and result[0]:
152
+ return torch.tensor(result[0])
153
  return None
154
 
155
  def insert_embedding(conn, table_name, movie_id, embedding_crc32, string_crc32, embedding):
156
  """Вставляет эмбеддинг в базу данных."""
 
157
  with conn.cursor() as cur:
158
  try:
159
  cur.execute(f"""
 
161
  (movie_id, embedding_crc32, string_crc32, model_name, embedding)
162
  VALUES (%s, %s, %s, %s, %s)
163
  ON CONFLICT (movie_id) DO NOTHING
164
+ """, (movie_id, embedding_crc32, string_crc32, model_name, embedding.tolist()))
165
  conn.commit()
166
  return True
167
  except Exception as e:
 
217
 
218
  if existing_embedding is None:
219
  embedding = encode_string(embedding_string)
220
+ embedding_crc32 = calculate_crc32(str(embedding.tolist()))
221
 
222
  if insert_embedding(conn, embeddings_table, movie['id'], embedding_crc32, string_crc32, embedding):
223
  print(f"Сохранен эмбеддинг для '{movie['name']}'")
 
234
  """Загружает все эмбеддинги фильмов из базы данных."""
235
  movie_embeddings = {}
236
  with conn.cursor() as cur:
237
+ cur.execute(f"SELECT movie_id, embedding FROM {embeddings_table}")
 
 
 
238
  for movie_id, embedding in cur.fetchall():
239
  # Находим название фильма по ID
240
  for movie in movies_data:
241
  if movie['id'] == movie_id:
242
+ movie_embeddings[movie['name']] = torch.tensor(embedding)
243
  break
244
  return movie_embeddings
245
 
 
259
 
260
  if query_embedding is None:
261
  query_embedding = encode_string(query)
 
262
 
263
  with conn.cursor() as cur:
264
  cur.execute(f"""
265
  INSERT INTO {query_cache_table} (query_crc32, query, model_name, embedding)
266
  VALUES (%s, %s, %s, %s)
267
  ON CONFLICT (query_crc32) DO NOTHING
268
+ """, (query_crc32, query, model_name, query_embedding.tolist()))
269
  conn.commit()
270
 
271
+ # Используем косинусное расстояние для поиска
272
+ with conn.cursor() as cur:
273
+ cur.execute(f"""
274
+ SELECT m.movie_id, m.embedding <=> %s as distance
275
+ FROM {embeddings_table} m
276
+ ORDER BY distance ASC
277
+ LIMIT %s
278
+ """, (query_embedding.tolist(), top_k))
279
+
280
+ results = cur.fetchall()
281
 
282
  results_html = "<ol>"
283
+ for movie_id, distance in results:
284
+ # Находим название фильма по ID
285
+ movie_title = None
286
+ for movie in movies_data:
287
+ if movie['id'] == movie_id:
288
+ movie_title = movie['name']
289
+ break
290
+
291
+ if movie_title:
292
+ similarity = 1 - distance # Конвертируем расстояние в сходство
293
+ results_html += f"<li><strong>{movie_title}</strong> (Сходство: {similarity:.4f})</li>"
294
  results_html += "</ol>"
295
 
296
  search_time = time.time() - start_time