Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files- app.py +116 -0
- artifacts/book_names.pkl +3 -0
- artifacts/book_pivot.pkl +3 -0
- artifacts/final_rating.pkl +3 -0
- artifacts/model.pkl +3 -0
- style.css +84 -0
app.py
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pickle
|
2 |
+
import streamlit as st
|
3 |
+
import numpy as np
|
4 |
+
|
5 |
+
# Load artifacts
|
6 |
+
model = pickle.load(open('artifacts/model.pkl', 'rb'))
|
7 |
+
book_names = pickle.load(open('artifacts/book_names.pkl', 'rb'))
|
8 |
+
final_rating = pickle.load(open('artifacts/final_rating.pkl', 'rb'))
|
9 |
+
book_pivot = pickle.load(open('artifacts/book_pivot.pkl', 'rb'))
|
10 |
+
|
11 |
+
# Function to fetch poster URLs
|
12 |
+
def fetch_poster(suggestion):
|
13 |
+
book_name = []
|
14 |
+
ids_index = []
|
15 |
+
poster_url = []
|
16 |
+
|
17 |
+
for book_id in suggestion:
|
18 |
+
book_name.append(book_pivot.index[book_id])
|
19 |
+
|
20 |
+
for name in book_name[0]:
|
21 |
+
ids = np.where(final_rating['title'] == name)[0][0]
|
22 |
+
ids_index.append(ids)
|
23 |
+
|
24 |
+
for idx in ids_index:
|
25 |
+
url = final_rating.iloc[idx]['image_url']
|
26 |
+
poster_url.append(url)
|
27 |
+
|
28 |
+
return poster_url
|
29 |
+
|
30 |
+
# Function to recommend books
|
31 |
+
def recommend_book(book_name):
|
32 |
+
books_list = []
|
33 |
+
book_id = np.where(book_pivot.index == book_name)[0][0]
|
34 |
+
distance, suggestion = model.kneighbors(book_pivot.iloc[book_id, :].values.reshape(1, -1), n_neighbors=4)
|
35 |
+
|
36 |
+
poster_url = fetch_poster(suggestion)
|
37 |
+
|
38 |
+
for i in range(len(suggestion[0])):
|
39 |
+
book = book_pivot.index[suggestion[0][i]]
|
40 |
+
books_list.append(book)
|
41 |
+
|
42 |
+
return books_list[1:], poster_url[1:] # Skip the input book itself
|
43 |
+
|
44 |
+
# Apply custom CSS for glassmorphism
|
45 |
+
def local_css(file_name):
|
46 |
+
with open(file_name) as f:
|
47 |
+
st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
|
48 |
+
|
49 |
+
# Page configuration
|
50 |
+
st.set_page_config(page_title='Book Recommendation System', layout='centered')
|
51 |
+
|
52 |
+
# Load CSS for styling
|
53 |
+
local_css("style.css")
|
54 |
+
|
55 |
+
# Add a fancy header with emojis
|
56 |
+
st.markdown("""
|
57 |
+
<div class="glass">
|
58 |
+
<h1>📚Book Finder📚</h1>
|
59 |
+
<p>Let AI find your perfect book match.</p>
|
60 |
+
</div>
|
61 |
+
""", unsafe_allow_html=True)
|
62 |
+
|
63 |
+
# Centered dropdown for book selection with glass effect
|
64 |
+
st.markdown("""
|
65 |
+
<div class="glass">
|
66 |
+
<p>🔎 Type or select a book from the dropdown</p>
|
67 |
+
</div>
|
68 |
+
""", unsafe_allow_html=True)
|
69 |
+
|
70 |
+
# Dropdown for book selection
|
71 |
+
selected_books = st.selectbox("", book_names)
|
72 |
+
|
73 |
+
# Apply custom button styling to Streamlit's default button using CSS
|
74 |
+
st.markdown("""
|
75 |
+
<style>
|
76 |
+
.stButton > button {
|
77 |
+
background: linear-gradient(135deg, #8B5E3C, #B8860B); /* Warm vintage gold-brown gradient */
|
78 |
+
border: none;
|
79 |
+
color: white; /* White text */
|
80 |
+
padding: 12px 24px;
|
81 |
+
text-align: center;
|
82 |
+
text-decoration: none;
|
83 |
+
display: inline-block;
|
84 |
+
font-size: 16px;
|
85 |
+
margin: 10px 5px;
|
86 |
+
cursor: pointer;
|
87 |
+
border-radius: 12px; /* Rounded corners for a soft vintage touch */
|
88 |
+
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25); /* Soft, deep shadow for antique feel */
|
89 |
+
font-family: 'Georgia', serif; /* Classic serif font for the button */
|
90 |
+
text-transform: uppercase; /* Uppercase text for a formal touch */
|
91 |
+
}
|
92 |
+
|
93 |
+
.stButton > button:hover {
|
94 |
+
background: linear-gradient(135deg, #704214, #B8860B); /* Slightly darker gold-brown */
|
95 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); /* Stronger shadow for depth on hover */
|
96 |
+
transform: translateY(-2px); /* Lift effect */
|
97 |
+
}
|
98 |
+
</style>
|
99 |
+
""", unsafe_allow_html=True)
|
100 |
+
|
101 |
+
# Streamlit button with custom styling applied
|
102 |
+
if st.button('Show Recommendation', key='show_recommendation_button'):
|
103 |
+
recommended_books, poster_url = recommend_book(selected_books)
|
104 |
+
|
105 |
+
# Display recommendations in a grid
|
106 |
+
st.markdown("<h3>Recommended Books:</h3>", unsafe_allow_html=True)
|
107 |
+
col1, col2, col3 = st.columns(3)
|
108 |
+
with col1:
|
109 |
+
st.markdown(f"<div class='glass'><p>{recommended_books[0]}</p></div>", unsafe_allow_html=True)
|
110 |
+
st.image(poster_url[0])
|
111 |
+
with col2:
|
112 |
+
st.markdown(f"<div class='glass'><p>{recommended_books[1]}</p></div>", unsafe_allow_html=True)
|
113 |
+
st.image(poster_url[1])
|
114 |
+
with col3:
|
115 |
+
st.markdown(f"<div class='glass'><p>{recommended_books[2]}</p></div>", unsafe_allow_html=True)
|
116 |
+
st.image(poster_url[2])
|
artifacts/book_names.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:794d08c3eb7ee65bf95008096b99fdcba5376e3794e313ade38d5781451e46a2
|
3 |
+
size 20131
|
artifacts/book_pivot.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a84ce7b17434dc9cf1740e636e9c2a795f5c87f19b7b7e7414b3e8b2da5c97c0
|
3 |
+
size 5298853
|
artifacts/final_rating.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:8577344ac2ae44e75fadef7f0609903cb6c66972df8502ccb20eefd41ba92d0d
|
3 |
+
size 3811461
|
artifacts/model.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:e6765395bd37fd0ea566804123b3f8ddf28aed9ca04c2b590d3be3dc04120456
|
3 |
+
size 183212
|
style.css
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Apply the background image to the entire app */
|
2 |
+
.stApp {
|
3 |
+
background-image: url('https://i.postimg.cc/g2w7q0TM/books-1.jpg');
|
4 |
+
background-size: cover;
|
5 |
+
background-position: center;
|
6 |
+
background-repeat: no-repeat;
|
7 |
+
background-attachment: fixed; /* Ensure the background image stays fixed */
|
8 |
+
}
|
9 |
+
|
10 |
+
/* Glassmorphism design for elements with the class "glass" */
|
11 |
+
.glass {
|
12 |
+
background: rgba(255, 255, 255, 0.1); /* Translucent background */
|
13 |
+
backdrop-filter: blur(10px); /* Blurring effect */
|
14 |
+
border-radius: 10px; /* Rounded corners */
|
15 |
+
padding: 20px; /* Spacing inside the box */
|
16 |
+
margin: 20px; /* Space around the box */
|
17 |
+
color: #ffffff; /* Text color */
|
18 |
+
font-weight: bold; /* Bold text */
|
19 |
+
text-align: center; /* Center the text */
|
20 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); /* Add shadow */
|
21 |
+
}
|
22 |
+
|
23 |
+
/* Blurred dropdown styling */
|
24 |
+
.stSelectbox {
|
25 |
+
background: rgba(255, 255, 255, 0.1); /* Translucent background */
|
26 |
+
backdrop-filter: blur(8px); /* Blur effect */
|
27 |
+
color: #ffffff; /* White text */
|
28 |
+
font-weight: bold; /* Bold text */
|
29 |
+
border-radius: 10px; /* Rounded corners */
|
30 |
+
margin-top: 10px; /* Space above the dropdown */
|
31 |
+
}
|
32 |
+
|
33 |
+
/* Centered custom button container */
|
34 |
+
.custom-button-container {
|
35 |
+
display: flex;
|
36 |
+
justify-content: center;
|
37 |
+
margin-top: 20px; /* Space above the button */
|
38 |
+
}
|
39 |
+
|
40 |
+
/* Centered custom button styling for "Show Recommendation" */
|
41 |
+
.custom-button {
|
42 |
+
background: linear-gradient(135deg, #8B5E3C, #B8860B); /* Warm vintage gold-brown gradient */
|
43 |
+
border: none;
|
44 |
+
color: white; /* White text */
|
45 |
+
padding: 12px 24px;
|
46 |
+
text-align: center;
|
47 |
+
text-decoration: none;
|
48 |
+
display: inline-block;
|
49 |
+
font-size: 16px;
|
50 |
+
margin: 10px 5px;
|
51 |
+
cursor: pointer;
|
52 |
+
border-radius: 12px; /* Rounded corners for a soft vintage touch */
|
53 |
+
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25); /* Soft, deep shadow for antique feel */
|
54 |
+
font-family: 'Georgia', serif; /* Classic serif font for the button */
|
55 |
+
text-transform: uppercase; /* Uppercase text for a formal touch */
|
56 |
+
transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transitions */
|
57 |
+
}
|
58 |
+
|
59 |
+
/* Hover effect for "Show Recommendation" button */
|
60 |
+
.custom-button:hover {
|
61 |
+
background: linear-gradient(135deg, #704214, #B8860B); /* Slightly darker gold-brown */
|
62 |
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); /* Stronger shadow for depth on hover */
|
63 |
+
transform: translateY(-2px); /* Lift effect */
|
64 |
+
}
|
65 |
+
|
66 |
+
/* Button hover styling for specific button containers */
|
67 |
+
.stButton > button:hover {
|
68 |
+
background-color: #704214; /* Darker warm brown on hover */
|
69 |
+
border: 1px solid #B8860B; /* Add a border on hover */
|
70 |
+
}
|
71 |
+
|
72 |
+
/* Optional: Style for text and titles */
|
73 |
+
h1, h2, h3, h4 {
|
74 |
+
font-family: 'Georgia', serif; /* Elegant font family */
|
75 |
+
color: #ffffff;
|
76 |
+
text-align: center; /* Centered titles */
|
77 |
+
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); /* Subtle text shadow for emphasis */
|
78 |
+
}
|
79 |
+
|
80 |
+
p {
|
81 |
+
font-family: 'Georgia', serif;
|
82 |
+
color: #ffffff;
|
83 |
+
text-align: center;
|
84 |
+
}
|