Solar-Iz commited on
Commit
34e52df
1 Parent(s): a157a92

Upload 15 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ data/desc_faiss_index_eng.index filter=lfs diff=lfs merge=lfs -text
37
+ data/desc_faiss_index_final.index filter=lfs diff=lfs merge=lfs -text
38
+ data/eng_data.csv filter=lfs diff=lfs merge=lfs -text
39
+ data/final_data.csv filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,12 +1,75 @@
1
  ---
2
- title: Find My Movie
3
- emoji: 🐠
4
- colorFrom: red
5
- colorTo: yellow
6
  sdk: streamlit
7
- sdk_version: 1.31.0
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: FindMyMovie
3
+ emoji: 🔥
4
+ colorFrom: indigo
5
+ colorTo: green
6
  sdk: streamlit
7
+ sdk_version: 1.29.0
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # Find my movie
13
+
14
+ ## Умный поиск фильмов
15
+
16
+ **Elbrus data science - проект Фазы 2**
17
+
18
+ ## Наша команда:
19
+ - **[Татьяна](https://github.com/Proseccovna)**
20
+ - **[Светлана](https://github.com/Solar-Iz)**
21
+ - **[Алексей](https://github.com/Alex-Dolgikh)**
22
+
23
+ ### О проекте:
24
+
25
+ - Приложение, которое рекомендует фильмы на основе их описания
26
+
27
+ - Пользователь вводит описание фильма
28
+
29
+ - Система предлаагет ему список фильмов, соотествующих данному описанию
30
+
31
+ - Фильмы предлагаются из более чем 7000, представленных на сайте kinoafisha.info
32
+
33
+
34
+ ### Как пользоваться:
35
+
36
+ - Проект доступен [здесь](https://huggingface.co/spaces/HaggiVaggi/FindMyMovie)
37
+
38
+ - Просто откройте сртримлит-приложение и следуйте оставленным там инструкциям
39
+
40
+ - Обратная связь приветсвуется
41
+
42
+
43
+ # Find my movie
44
+
45
+ ## Smart movie search
46
+
47
+ **Elbrus data science - Phase 2 project**
48
+
49
+ ## Our team:
50
+ - **[Tatiana](https://github.com/Proseccovna)**
51
+ - **[Svetlana](https://github.com/Solar-Iz)**
52
+ - **[Alexey](https://github.com/Alex-Dolgikh)**
53
+
54
+
55
+ ### About project:
56
+
57
+ - An app that recomends a movie based on its description
58
+
59
+ - The user enters a movie description
60
+
61
+ - The system recomends a list of movies that fit the description
62
+
63
+ - Movies are chosen from a set of 7000+ from kinoafisha.info website
64
+
65
+
66
+ ### How to use:
67
+
68
+ - The project is deployed [here](https://huggingface.co/spaces/HaggiVaggi/FindMyMovie)
69
+
70
+ - Simply use the streamlit app in your browser and follow the instructions there
71
+
72
+ - Feel free to leave feedback
73
+
74
+
75
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import torch
4
+ from transformers import AutoTokenizer, AutoModel
5
+ import faiss
6
+ import numpy as np
7
+
8
+ @st.cache_data
9
+ def load_data(url):
10
+ df = pd.read_csv(url) # 👈 Download the data
11
+ return df
12
+
13
+ df = load_data('data/final_data.csv')
14
+
15
+ st.title('Умный поиск фильмов 🔍🎦')
16
+
17
+
18
+ st.header('Выполнила команда "FindMyMovie":')
19
+ st.subheader('🎥Алексей')
20
+ st.subheader('🎬Светлана')
21
+ st.subheader('🍿Тата')
22
+
23
+
24
+
25
+ st.subheader('Наши задачи:')
26
+ st.markdown("""
27
+ <span style='font-size:18px; color:purple;'>Задача 1:</span> Спарсить информацию по 5 тыс. фильмов и обработать ее
28
+
29
+ <span style='font-size:18px; color:purple;'>Задача 2:</span> Разработать систему поиска фильма по пользовательскому запросу
30
+ """, unsafe_allow_html=True)
31
+
32
+ st.markdown(
33
+ f"<div style='border: 2px solid #800080; padding: 10px; text-align: center;'><span style='font-size: 20px; color: violet;'>Мы любезно позаимствовали данные о фильмах с \
34
+ Киноафиши, ни один участник команды при этом не пострадал 💟</span></div>",
35
+ unsafe_allow_html=True
36
+ )
37
+
38
+ st.subheader(' '*10)
39
+
40
+
41
+ st.info('🌟Сервис принимает на вход описание фильма от пользователя и возвращает заданное количество подходящих вариантов')
42
+
43
+
44
+ st.info('🌟Если не знаете, что посмотреть, нажмите кнопку "Сгенерировать" - сервис предложит вам 10 случайных фильмов из библиотеки')
45
+
46
+
47
+ # Отображаем HTML-разметку в Streamlit
48
+ if st.button("Сгенерировать 🎲"):
49
+ # Получение случайных 10 строк, включая 'image_url' и 'actors'
50
+ random_rows = df[['movie_title', 'description', 'actors', 'image_url', 'page_url']].sample(n=10).reset_index(drop=True)
51
+ random_rows.index = random_rows.index + 1
52
+ st.markdown(f"<span style='font-size:{20}px; color:violet'>{'Сегодня мы подобрали для вас следующие фильмы:'}</span>", unsafe_allow_html=True)
53
+
54
+
55
+
56
+ for i in range(5):
57
+ st.markdown(f"<span style='font-size:{20}px; color:purple'>{random_rows['movie_title'].iloc[i]}</span>", unsafe_allow_html=True)
58
+ col1, col2 = st.columns([2, 1])
59
+ col1.info(random_rows['description'].iloc[i])
60
+ col1.markdown(f"**В ролях:** {random_rows['actors'].iloc[i]}")
61
+ col1.markdown(f"**Фильм можно посмотреть [здесь]({random_rows['page_url'].iloc[i]})**")
62
+ col2.image(random_rows['image_url'].iloc[i], caption=random_rows['movie_title'].iloc[i], width=200)
63
+
apps/1.png ADDED
apps/2.jpg ADDED
data/.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.csv filter=lfs diff=lfs merge=lfs -text
data/desc_faiss_index_eng.index ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4130d7742406402173d6e0baad2820ff396e009605d05676bbcaac9b19025c2e
3
+ size 8279085
data/desc_faiss_index_final.index ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c645564c7543ebf505584d4191fec57ee6649150fb7eca4c45b8936438386ac8
3
+ size 21633069
data/embeddings_eng.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:df3274afc661f2d791ad695af2451b6d53b9bad6372167ab1f4312dd4e9bd81a
3
+ size 8279168
data/embeddings_final.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d1f6eaf09c7a6cf43065869814720f3ed98f58bc0c4784e3bbdf8a80eb99cdb
3
+ size 21633152
data/eng_data.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d2e9692f30661c1eb29ae2b8b0c46aff6a5d968064ffcb06187136e9945e9913
3
+ size 35269233
data/final_data.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:203f00b121ce8d38c4c0485aac14af75ce942db8c57a27e44f9ed174525463a3
3
+ size 120362756
pages/1 Подбор фильмов по описанию✏️🔍.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import torch
4
+ from transformers import AutoTokenizer, AutoModel
5
+ import faiss
6
+ import numpy as np
7
+
8
+ @st.cache_data
9
+ def load_data(url):
10
+ df = pd.read_csv(url)
11
+ return df
12
+
13
+ @st.cache_data
14
+ def embedding_and_index():
15
+ embeddings_array = np.load('data/embeddings_final.npy')
16
+ index = faiss.read_index('data/desc_faiss_index_final.index')
17
+ return embeddings_array, index
18
+
19
+ @st.cache_data
20
+ def load_model():
21
+ model = AutoModel.from_pretrained("DeepPavlov/rubert-base-cased-sentence")
22
+ return model
23
+
24
+
25
+ st.header("Подбор фильмов по описанию ✏️🔍")
26
+
27
+ # Загрузка данных
28
+ tokenizer = AutoTokenizer.from_pretrained("DeepPavlov/rubert-base-cased-sentence")
29
+ df = load_data('data/final_data.csv')
30
+ embeddings_array, index = embedding_and_index()
31
+ model = load_model()
32
+
33
+ # Пользовательский ввод
34
+ user_input = st.text_input("Введите описание фильма:", value="", help="Чем подробнее будет ваше описание, тем точнее мы сможем подобрать для вас фильм 🤗'")
35
+ genre_list = ['анимация', 'аниме', 'балет', 'биография', 'боевик', 'вестерн', 'военный', 'детектив', 'детский', 'документальный', 'драма', 'исторический', 'катастрофа', 'комедия', 'концерт', 'короткометражный', 'криминал', 'мелодрама', 'мистика', 'музыка', 'мюзикл', 'нуар', 'приключения', 'сборник', 'семейный', 'сказка', 'спорт', 'триллер', 'ужасы', 'фантастика', 'фэнтези', 'эротика']
36
+
37
+ user_select_genre = st.multiselect('Выберите жанр', genre_list)
38
+
39
+ if st.button("Искать🔍🎦"):
40
+ if user_input:
41
+ def encode_description(description, tokenizer, model):
42
+ tokens = tokenizer(description, return_tensors="pt")
43
+ with torch.no_grad():
44
+ outputs = model(**tokens)
45
+ embeddings = outputs.last_hidden_state.mean(dim=1)
46
+ return embeddings.cpu().numpy().astype('float32')
47
+
48
+ # Векторизация введенного запроса с использованием переданных tokenizer и model
49
+ input_embedding = encode_description(user_input, tokenizer, model)
50
+
51
+ # Поиск с использованием Faiss
52
+ _, sorted_indices = index.search(input_embedding.reshape(1, -1), 5)
53
+
54
+ # Используйте индексы для извлечения строк из DataFrame
55
+ recs = df.iloc[sorted_indices[0]].reset_index(drop=True)
56
+ recs.index = recs.index + 1
57
+
58
+ if user_select_genre:
59
+ genres_selected = pd.Series(user_select_genre)
60
+ genre_mask = df['genre'].str.contains('')
61
+ for i in range(len(genres_selected)):
62
+ genre_mask_i = df['genre'].str.contains(genres_selected.iloc[i])
63
+ genre_mask = genre_mask & genre_mask_i
64
+ recs = recs[genre_mask]
65
+
66
+ if not recs.empty:
67
+ # Вывод рекомендованных фильмов с изображениями
68
+ st.subheader("Рекомендованные фильмы 🎉:")
69
+ for i in range(min(5, len(recs))):
70
+ st.markdown(f"<span style='font-size:{20}px; color:purple'>{recs['movie_title'].iloc[i]}</span>", unsafe_allow_html=True)
71
+ # Создаем две колонки: одну для текста, другую для изображения
72
+ col1, col2 = st.columns([2, 1])
73
+
74
+ # В колонке отображаем название фильма, описание, роли и ссылку
75
+ col1.info(recs['description'].iloc[i])
76
+ col1.markdown(f"**В ролях:** {recs['actors'].iloc[i]}")
77
+ col1.markdown(f"**Фильм можно посмотреть [здесь]({recs['page_url'].iloc[i]})**")
78
+
79
+ # В колонке отображаем изображение
80
+ col2.image(recs['image_url'].iloc[i], caption=recs['movie_title'].iloc[i], width=200)
81
+
82
+ with st.sidebar:
83
+ st.info("""
84
+ #### Мы смогли помочь вам с выбором?
85
+ """)
86
+ feedback = st.text_input('Поделитесь с нами вашим мнением')
87
+
88
+ feedback_button = st.button("Отправить отзыв", key="feedback_button")
89
+
90
+ if feedback_button and feedback:
91
+ st.success("Спасибо, каждый день мы стараемся быть лучше для вас 💟")
92
+ elif feedback_button:
93
+ st.warning("Пожалуйста, введите отзыв перед отп��авкой.")
94
+ else:
95
+ st.subheader("Подходящих фильмов не найдено, ослабьте фильтры 😔:")
pages/2 Selection of films by description✏️🔍.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import torch
4
+ from transformers import BertTokenizer, BertModel
5
+ import faiss
6
+ import numpy as np
7
+ import re
8
+ import nltk
9
+ from nltk.corpus import stopwords
10
+
11
+ # Загрузка стоп-слов для английского языка
12
+ nltk.download('stopwords')
13
+ stop_words = set(stopwords.words('english'))
14
+
15
+ @st.cache_data
16
+ def load_data(url):
17
+ df = pd.read_csv(url)
18
+ return df
19
+
20
+ @st.cache_data
21
+ def embedding_and_index():
22
+ embeddings_array = np.load('data/embeddings_eng.npy')
23
+ index = faiss.read_index('data/desc_faiss_index_eng.index')
24
+ return embeddings_array, index
25
+
26
+ @st.cache_data
27
+ def load_model():
28
+ model = BertModel.from_pretrained('bert-base-uncased')
29
+ return model
30
+
31
+ def clean_text(text):
32
+ text = text.lower()
33
+ text = re.sub(r'[^\w\s]', '', text)
34
+ text = ' '.join(word for word in text.split() if word not in stop_words)
35
+
36
+ return text
37
+
38
+ st.header("Selection of films by description✏️🔍")
39
+
40
+ # Загрузка данных
41
+ tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
42
+ df = load_data('data/eng_data.csv')
43
+ embeddings_array, index = embedding_and_index()
44
+ model = load_model()
45
+
46
+ # Пользовательский ввод
47
+ user_input = st.text_input("Enter a movie description:", value="", help="The more detailed your description is, the more accurately we can choose a film for you 🤗'")
48
+
49
+ if st.button("Search🔍🎦"):
50
+ if user_input:
51
+ def encode_description(description, tokenizer, model):
52
+ tokens = tokenizer(description, return_tensors="pt")
53
+ with torch.no_grad():
54
+ outputs = model(**tokens)
55
+ embeddings = outputs.last_hidden_state.mean(dim=1)
56
+ return embeddings.cpu().numpy().astype('float32')
57
+
58
+ # Применяем очистку текста к пользовательскому вводу
59
+ cleaned_input = clean_text(user_input)
60
+
61
+ # Векторизация очищенного запроса
62
+ input_embedding = encode_description(cleaned_input, tokenizer, model)
63
+
64
+ # Поиск с использованием Faiss
65
+ _, sorted_indices = index.search(input_embedding.reshape(1, -1), 5)
66
+
67
+ # Используйте индексы для извлечения строк из DataFrame
68
+ recs = df.iloc[sorted_indices[0]].reset_index(drop=True)
69
+ recs.index = recs.index + 1
70
+
71
+ # Вывод рекомендованных фильмов с изображениями
72
+ st.subheader("Recommended movies 🎉:")
73
+ for i in range(5):
74
+ st.markdown(f"<span style='font-size:{20}px; color:purple'>{recs['movie_title'].iloc[i]}</span>", unsafe_allow_html=True)
75
+ # Создаем две колонки: одну для текста, другую для изображения
76
+ col1, col2 = st.columns([2, 1])
77
+
78
+ # В колонке отображаем название фильма, описание, роли и ссылку
79
+ col1.info(recs['description'].iloc[i])
80
+ col1.markdown(f"**You can watch the film [here]({recs['page_url'].iloc[i]})**")
81
+
82
+ # В колонке отображаем изображение
83
+ col2.image(recs['image_url'].iloc[i], caption=recs['movie_title'].iloc[i], width=200)
84
+ with st.sidebar:
85
+ st.info("""
86
+ #### Were we able to help you with the choice?
87
+ """)
88
+ feedback = st.text_input('Share with us')
89
+
90
+ feedback_button = st.button("Send feedback", key="feedback_button")
91
+
92
+ if feedback_button and feedback:
93
+ feedback_container.success("Thank you, every day we try to be better for you 💟")
94
+ elif feedback_button:
95
+ feedback_container.warning("Please enter a review before submitting")
pages/3 Итоги проекта🏆.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ st.header('Инструменты для создания проекта: ')
4
+
5
+ st.subheader('Для русской версии: ')
6
+
7
+ list_text = """
8
+ <div style='color: violet; border: 2px solid purple; padding: 10px;'>
9
+ <ul>
10
+ <li>Используемые языковые модели: rubert-base-cased-sentence, rubert-tiny2</li>
11
+ <li>Библиотека Sentence Transformers</li>
12
+ <li>Faiss (для уменьшения времени генерации подборки фильмов)</li>
13
+ <li>Сайт-жертва для парсинга - <a href="https://www.kinoafisha.info/" style='color: purple;'>Киноафиша</a></li>
14
+ </ul>
15
+ </div>
16
+ """
17
+
18
+ # Отображение HTML-разметки в Streamlit
19
+ st.markdown(list_text, unsafe_allow_html=True)
20
+
21
+ st.subheader('Для английской версии: ')
22
+
23
+ list_text2 = """
24
+ <div style='color: pink; border: 2px solid violet; padding: 10px;'>
25
+ <ul>
26
+ <li>Используемые языковые модели: bert-base-uncased</li>
27
+ <li>Очистка текста: приведение к нижнему регистру, очистка от знаков препинания, стоп-слова</li>
28
+ <li>Библиотека Sentence Transformers</li>
29
+ <li>Faiss (для уменьшения времени генерации подборки фильмов)</li>
30
+ <li>Сайт-жертва для парсинга - <a href="https://www.themoviedb.org/" style='color: violet;'>TMDB</a></li>
31
+ </ul>
32
+ </div>
33
+ """
34
+
35
+ st.markdown(list_text2, unsafe_allow_html=True)
36
+
37
+
38
+ st.markdown("<p style='color: pink; font-size: 28px; text-align: center;'>"
39
+ "А теперь, когда фильм успешно выбран, вооружайтесь теплым пледом и глинтвейном и бегите смотреть 🎄🍿"
40
+ "</p>", unsafe_allow_html=True)
41
+
42
+ st.image("apps/2.jpg", use_column_width=True)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ transformers==4.35.2
2
+ sentence-transformers==2.2.2
3
+ torch==1.11.0
4
+ streamlit==0.86.0
5
+ pandas==1.3.3
6
+ scikit-learn==1.3.2
7
+ faiss-gpu==1.7.2