Adityaz23 commited on
Commit
1cb43fb
·
verified ·
1 Parent(s): c0b114e

Uploading with claude

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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
+ chroma_db/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text
37
+ cover-not-found.png filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pandas as pd
3
+ import numpy as np
4
+ import gradio as gr
5
+
6
+ from langchain_community.document_loaders import TextLoader
7
+ from langchain_text_splitters import CharacterTextSplitter
8
+ from langchain_chroma import Chroma
9
+ from langchain_huggingface import HuggingFaceEmbeddings
10
+
11
+
12
+ # =========================================================
13
+ # BASE DIRECTORY — works both locally and on HuggingFace
14
+ # =========================================================
15
+
16
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
17
+
18
+
19
+ # =========================================================
20
+ # EMBEDDING MODEL
21
+ # =========================================================
22
+
23
+ embedding_model = HuggingFaceEmbeddings(
24
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
25
+ )
26
+
27
+
28
+ # =========================================================
29
+ # LOAD BOOK DATASET
30
+ # =========================================================
31
+
32
+ books = pd.read_csv(os.path.join(BASE_DIR, "books_with_emotions.csv"))
33
+
34
+
35
+ # =========================================================
36
+ # CLEAN CATEGORY COLUMN
37
+ # =========================================================
38
+
39
+ books["simple_categories"] = (
40
+ books["simple_categories"]
41
+ .fillna("")
42
+ .astype(str)
43
+ .str.strip()
44
+ )
45
+
46
+
47
+ # =========================================================
48
+ # HANDLE THUMBNAILS
49
+ # =========================================================
50
+
51
+ books["thumbnail"] = books["thumbnail"].fillna("")
52
+
53
+ books["large_thumbnail"] = np.where(
54
+ books["thumbnail"] != "",
55
+ books["thumbnail"] + "&fife=w800",
56
+ "cover-not-found.png"
57
+ )
58
+
59
+
60
+ # =========================================================
61
+ # LOAD EXISTING VECTOR DATABASE
62
+ # NOTE: ChromaDB files must be inside a "chroma_db" folder
63
+ # at the root of your HuggingFace Space repo.
64
+ # Required files inside chroma_db/:
65
+ # - chroma.sqlite3
66
+ # - data_level0.bin
67
+ # - header.bin
68
+ # - length.bin
69
+ # - link_lists.bin
70
+ # - index_metadata.pickle
71
+ # =========================================================
72
+
73
+ CHROMA_PATH = os.path.join(BASE_DIR, "chroma_db")
74
+
75
+ db_books = Chroma(
76
+ persist_directory=CHROMA_PATH,
77
+ embedding_function=embedding_model
78
+ )
79
+
80
+
81
+ # =========================================================
82
+ # RETRIEVE SEMANTIC RECOMMENDATIONS
83
+ # =========================================================
84
+
85
+ def retrieve_semantic_recommendations(
86
+ query: str,
87
+ category: str,
88
+ tone: str = "All",
89
+ initial_top_k: int = 50,
90
+ final_top_k: int = 16
91
+ ) -> pd.DataFrame:
92
+
93
+ recs = db_books.similarity_search(query, k=initial_top_k)
94
+
95
+ books_list = []
96
+
97
+ for rec in recs:
98
+ try:
99
+ isbn = int(rec.page_content.strip('"').split()[0])
100
+ books_list.append(isbn)
101
+ except Exception:
102
+ continue
103
+
104
+ # Preserve vector search order and deduplicate
105
+ seen = set()
106
+ valid_isbns = []
107
+
108
+ for isbn in books_list:
109
+ if isbn in books["isbn13"].values and isbn not in seen:
110
+ valid_isbns.append(isbn)
111
+ seen.add(isbn)
112
+
113
+ if len(valid_isbns) == 0:
114
+ return pd.DataFrame()
115
+
116
+ book_recs = (
117
+ books
118
+ .set_index("isbn13")
119
+ .loc[valid_isbns]
120
+ .reset_index()
121
+ )
122
+
123
+ # Category filter
124
+ if category != "All":
125
+ book_recs = book_recs[
126
+ book_recs["simple_categories"].str.lower()
127
+ == category.strip().lower()
128
+ ]
129
+
130
+ # Emotional tone filter
131
+ tone_map = {
132
+ "Happy": "joy",
133
+ "Surprising": "surprise",
134
+ "Angry": "anger",
135
+ "Suspenseful": "fear",
136
+ "Sad": "sadness",
137
+ }
138
+
139
+ if tone in tone_map:
140
+ book_recs = book_recs.sort_values(
141
+ by=tone_map[tone], ascending=False
142
+ )
143
+
144
+ return book_recs.head(final_top_k)
145
+
146
+
147
+ # =========================================================
148
+ # GENERATE HTML BOOK CARDS
149
+ # =========================================================
150
+
151
+ def recommend_books(query: str, category: str, tone: str):
152
+
153
+ if not query.strip():
154
+ return """
155
+ <div style="text-align:center; padding:50px; color:white; font-size:20px;">
156
+ 💡 Please enter a book description to get started.
157
+ </div>
158
+ """
159
+
160
+ recommendations = retrieve_semantic_recommendations(
161
+ query=query,
162
+ category=category,
163
+ tone=tone
164
+ )
165
+
166
+ if recommendations.empty:
167
+ return """
168
+ <div style="text-align:center; padding:50px; color:white; font-size:24px;">
169
+ 😔 No books found for this combination.
170
+ </div>
171
+ """
172
+
173
+ html = """
174
+ <div style="
175
+ display:grid;
176
+ grid-template-columns:repeat(auto-fill, minmax(250px, 1fr));
177
+ gap:25px;
178
+ padding:20px;
179
+ ">
180
+ """
181
+
182
+ for _, row in recommendations.iterrows():
183
+
184
+ title = str(row["title"])
185
+ authors = str(row["authors"])
186
+ description = str(row["description"])
187
+
188
+ short_description = " ".join(description.split()[:35]) + "..."
189
+
190
+ authors_split = authors.split(";")
191
+
192
+ if len(authors_split) == 2:
193
+ authors_str = f"{authors_split[0]} and {authors_split[1]}"
194
+ elif len(authors_split) > 2:
195
+ authors_str = (
196
+ f"{', '.join(authors_split[:-1])} and {authors_split[-1]}"
197
+ )
198
+ else:
199
+ authors_str = authors
200
+
201
+ google_books_link = (
202
+ f"https://books.google.com/books?vid=ISBN{row['isbn13']}"
203
+ )
204
+ amazon_link = (
205
+ f"https://www.amazon.com/s?k={title.replace(' ', '+')}"
206
+ )
207
+
208
+ html += f"""
209
+ <div style="
210
+ background:#111827;
211
+ border-radius:20px;
212
+ overflow:hidden;
213
+ box-shadow:0 8px 20px rgba(0,0,0,0.4);
214
+ transition:0.3s;
215
+ border:1px solid #374151;
216
+ ">
217
+ <img
218
+ src="{row['large_thumbnail']}"
219
+ onerror="this.src='cover-not-found.png'"
220
+ style="width:100%; height:380px; object-fit:cover;"
221
+ >
222
+ <div style="padding:18px;">
223
+ <h3 style="color:white; margin-bottom:10px; font-size:20px; line-height:1.3;">
224
+ {title}
225
+ </h3>
226
+ <p style="color:#9CA3AF; font-size:14px; margin-bottom:12px;">
227
+ by {authors_str}
228
+ </p>
229
+ <p style="color:#D1D5DB; font-size:14px; line-height:1.6; margin-bottom:20px;">
230
+ {short_description}
231
+ </p>
232
+ <div style="display:flex; gap:10px; flex-wrap:wrap;">
233
+ <a
234
+ href="{google_books_link}"
235
+ target="_blank"
236
+ style="
237
+ background:#2563EB;
238
+ color:white;
239
+ padding:10px 14px;
240
+ border-radius:10px;
241
+ text-decoration:none;
242
+ font-size:14px;
243
+ font-weight:600;
244
+ "
245
+ >
246
+ 📖 Read Preview
247
+ </a>
248
+ <a
249
+ href="{amazon_link}"
250
+ target="_blank"
251
+ style="
252
+ background:#F59E0B;
253
+ color:black;
254
+ padding:10px 14px;
255
+ border-radius:10px;
256
+ text-decoration:none;
257
+ font-size:14px;
258
+ font-weight:600;
259
+ "
260
+ >
261
+ 🛒 Buy Book
262
+ </a>
263
+ </div>
264
+ </div>
265
+ </div>
266
+ """
267
+
268
+ html += "</div>"
269
+ return html
270
+
271
+
272
+ # =========================================================
273
+ # DROPDOWNS
274
+ # =========================================================
275
+
276
+ categories = ["All"] + sorted(
277
+ books["simple_categories"]
278
+ .dropna()
279
+ .str.strip()
280
+ .unique()
281
+ .tolist()
282
+ )
283
+
284
+ tones = ["All", "Happy", "Surprising", "Angry", "Suspenseful", "Sad"]
285
+
286
+
287
+ # =========================================================
288
+ # GRADIO DASHBOARD
289
+ # =========================================================
290
+
291
+ with gr.Blocks(
292
+ theme=gr.themes.Soft(),
293
+ css="footer { visibility: hidden; }"
294
+ ) as dashboard:
295
+
296
+ gr.Markdown(
297
+ """
298
+ # 📚 Semantic Book Recommender
299
+ Discover books using AI-powered semantic search, emotional tones, and category filtering.
300
+ """
301
+ )
302
+
303
+ with gr.Row():
304
+ user_query = gr.Textbox(
305
+ label="Enter Book Description",
306
+ placeholder="e.g., A dark fantasy story with dragons and magic...",
307
+ scale=3
308
+ )
309
+ category_dropdown = gr.Dropdown(
310
+ choices=categories,
311
+ label="Select Category",
312
+ value="All",
313
+ scale=1
314
+ )
315
+ tone_dropdown = gr.Dropdown(
316
+ choices=tones,
317
+ label="Select Emotional Tone",
318
+ value="All",
319
+ scale=1
320
+ )
321
+
322
+ submit_button = gr.Button("🔍 Find Recommendations", variant="primary")
323
+ output = gr.HTML()
324
+
325
+ submit_button.click(
326
+ fn=recommend_books,
327
+ inputs=[user_query, category_dropdown, tone_dropdown],
328
+ outputs=output
329
+ )
330
+
331
+
332
+ # =========================================================
333
+ # RUN APP
334
+ # =========================================================
335
+
336
+ if __name__ == "__main__":
337
+ dashboard.launch(server_name="0.0.0.0", server_port=7860)
books_with_emotions.csv ADDED
The diff for this file is too large to render. See raw diff
 
chroma_db/.DS_Store ADDED
Binary file (6.15 kB). View file
 
chroma_db/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02bf4b0a8383a8ea908ab5b62ab1aa7cfa619aa96e7fa2794bb676b70ac14e03
3
+ size 56733696
chroma_db/e24a8b8f-9579-4d39-ac1a-5bc76ad72f57/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:517624ea599acd11cd230bd1e8eef6af4e100c9ebff4bac3991fcc734b28fa29
3
+ size 10334216
chroma_db/e24a8b8f-9579-4d39-ac1a-5bc76ad72f57/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8f8be673bb4a6dae512bbd61d8bd3695e1ff2b58f3c6db6bec36547ee560f383
3
+ size 100
chroma_db/e24a8b8f-9579-4d39-ac1a-5bc76ad72f57/index_metadata.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3c0788ded149a4180ca5dd98aff0a071819d865bd1618ed6328dacccc1e50127
3
+ size 567424
chroma_db/e24a8b8f-9579-4d39-ac1a-5bc76ad72f57/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:30604bc53ac00e91203093ad69fc26d7957193fa25172b07f7b82846065ca848
3
+ size 24664
chroma_db/e24a8b8f-9579-4d39-ac1a-5bc76ad72f57/link_lists.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5e562cc417b517e53ab5a47774a5821bb8e3a66168e938ac6875a60df524f7df
3
+ size 54992
cover-not-found.png ADDED

Git LFS Details

  • SHA256: 056b6b38dd33e213341ecf3738c5fc48011ffa15b85ef868be6df510ed335e48
  • Pointer size: 132 Bytes
  • Size of remote file: 1.9 MB
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio
2
+ pandas
3
+ numpy
4
+ torch
5
+ python-dotenv
6
+ langchain
7
+ langchain-community
8
+ langchain-text-splitters
9
+ langchain-chroma
10
+ langchain-huggingface
11
+ sentence-transformers
12
+ chromadb
13
+ transformers
tagged_description.txt ADDED
The diff for this file is too large to render. See raw diff