Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +16 -90
src/streamlit_app.py
CHANGED
|
@@ -260,10 +260,8 @@ def get_similar_content(content, n_recommendations=5):
|
|
| 260 |
"accept": "application/json"
|
| 261 |
}
|
| 262 |
|
| 263 |
-
# Debug: Print the title and show_id we're searching for
|
| 264 |
title = content.get('title', '')
|
| 265 |
show_id = content.get('show_id', '')
|
| 266 |
-
st.write(f"๐ Searching for similar content to: {title} (ID: {show_id})")
|
| 267 |
|
| 268 |
# URLs for similarity tables using table IDs
|
| 269 |
similarity_table_urls = [
|
|
@@ -272,57 +270,30 @@ def get_similar_content(content, n_recommendations=5):
|
|
| 272 |
"https://mtoft20-potm.hf.space/api/v1/db/data/noco/p9pozkcw81t9aee/m2driodimid10k6" # Part 3 similarities
|
| 273 |
]
|
| 274 |
|
| 275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
|
| 277 |
-
# Check both tables for similarities
|
| 278 |
for table_url in similarity_table_urls:
|
| 279 |
-
# Debug: Get a sample row to see table structure
|
| 280 |
-
sample_params = {
|
| 281 |
-
"limit": 1
|
| 282 |
-
}
|
| 283 |
-
sample_response = requests.get(table_url, headers=headers, params=sample_params)
|
| 284 |
-
if sample_response.status_code == 200:
|
| 285 |
-
sample_data = sample_response.json()
|
| 286 |
-
if sample_data.get('list'):
|
| 287 |
-
st.write(f"๐ Table structure for {table_url.split('/')[-1]}:")
|
| 288 |
-
st.write("Columns:", list(sample_data['list'][0].keys()))
|
| 289 |
-
st.write("Sample row:", sample_data['list'][0])
|
| 290 |
-
|
| 291 |
-
# Try finding by both show_id and title
|
| 292 |
-
escaped_title = title.replace('"', '\\"') # Escape any quotes in the title
|
| 293 |
-
query = f'where=(show_id,eq,{show_id})~and(title,eq,"{escaped_title}")' # Add quotes around title
|
| 294 |
-
params = {
|
| 295 |
-
"where": query
|
| 296 |
-
}
|
| 297 |
-
|
| 298 |
-
# Debug: Print the request details
|
| 299 |
-
st.write(f"๐ก Querying table: {table_url.split('/')[-1]}")
|
| 300 |
-
st.write(f"๐ Query params: {params}")
|
| 301 |
-
|
| 302 |
-
# Try first query format
|
| 303 |
try:
|
| 304 |
response = requests.get(table_url, headers=headers, params=params)
|
| 305 |
-
st.write(f"๐ฅ Response status: {response.status_code}")
|
| 306 |
-
st.write("๐ฅ Request URL:", response.url)
|
| 307 |
|
| 308 |
if response.status_code == 200:
|
| 309 |
data = response.json()
|
| 310 |
if data.get('list'):
|
| 311 |
-
st.write(f"โ
Found exact match")
|
| 312 |
for entry in data['list']:
|
| 313 |
-
st.write(f"Entry title: {entry.get('title')}, show_id: {entry.get('show_id')}")
|
| 314 |
-
|
| 315 |
# Parse similar items
|
| 316 |
try:
|
| 317 |
similar_items = json.loads(entry['similar_items'])
|
| 318 |
-
st.write(f"โ
Successfully parsed {len(similar_items)} similar items")
|
| 319 |
|
| 320 |
# Get full content details for each similar item
|
| 321 |
similar_content = []
|
| 322 |
-
for item in similar_items:
|
| 323 |
# Query main content table for full details using show_id
|
| 324 |
show_id = item.get('show_id', '')
|
| 325 |
-
query = f'where=(show_id,eq,
|
| 326 |
content_params = {
|
| 327 |
"where": query
|
| 328 |
}
|
|
@@ -334,58 +305,15 @@ def get_similar_content(content, n_recommendations=5):
|
|
| 334 |
content_dict = content_data['list'][0]
|
| 335 |
content_dict['similarity'] = f"{item['similarity']:.2%}"
|
| 336 |
similar_content.append(content_dict)
|
| 337 |
-
st.write(f"โ
Found details for: {item['title']}")
|
| 338 |
-
else:
|
| 339 |
-
st.write(f"โ No content details found for: {item['title']}")
|
| 340 |
|
| 341 |
-
return similar_content
|
| 342 |
except Exception as parse_error:
|
| 343 |
-
|
| 344 |
-
st.write("Raw data:", entry)
|
| 345 |
-
else:
|
| 346 |
-
st.write("โ No exact match found")
|
| 347 |
except Exception as e:
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
st.write(f"๐ Total similar items found: {len(similar_items)}")
|
| 351 |
-
|
| 352 |
-
if similar_items:
|
| 353 |
-
# Sort by similarity score and limit to requested number
|
| 354 |
-
similar_items.sort(key=lambda x: x['similarity'], reverse=True)
|
| 355 |
-
similar_items = similar_items[:n_recommendations]
|
| 356 |
-
|
| 357 |
-
# Get full content details for each similar item
|
| 358 |
-
similar_content = []
|
| 359 |
-
for item in similar_items:
|
| 360 |
-
# Query main content table for full details using show_id if available
|
| 361 |
-
show_id = item.get('show_id', '')
|
| 362 |
-
if show_id:
|
| 363 |
-
query = f'(show_id,eq,"{show_id}")'
|
| 364 |
-
else:
|
| 365 |
-
# Fallback to title if show_id not available
|
| 366 |
-
query = f'(title,eq,"{item["title"]}")'
|
| 367 |
-
|
| 368 |
-
content_params = {
|
| 369 |
-
"where": query
|
| 370 |
-
}
|
| 371 |
-
content_response = requests.get(NOCODB_URL, headers=headers, params=content_params)
|
| 372 |
-
|
| 373 |
-
if content_response.status_code == 200:
|
| 374 |
-
content_data = content_response.json()
|
| 375 |
-
if content_data and len(content_data.get('list', [])) > 0:
|
| 376 |
-
content_dict = content_data['list'][0]
|
| 377 |
-
content_dict['similarity'] = f"{item['similarity']:.2%}"
|
| 378 |
-
similar_content.append(content_dict)
|
| 379 |
-
st.write(f"โ
Found details for: {item['title']}")
|
| 380 |
-
else:
|
| 381 |
-
st.write(f"โ No content details found for: {item['title']}")
|
| 382 |
-
|
| 383 |
-
return similar_content
|
| 384 |
|
| 385 |
return []
|
| 386 |
except Exception as e:
|
| 387 |
-
st.error(f"Error fetching similar content: {str(e)}")
|
| 388 |
-
st.write("Full error details:", e)
|
| 389 |
return []
|
| 390 |
|
| 391 |
# =============================================================================
|
|
@@ -643,33 +571,31 @@ def main():
|
|
| 643 |
similar_button = st.button(f"๐ Find Similar Content", key=f"similar_{i}")
|
| 644 |
if similar_button:
|
| 645 |
with st.spinner("Finding similar content..."):
|
| 646 |
-
similar_content = get_similar_content(content)
|
| 647 |
|
| 648 |
if similar_content:
|
| 649 |
# Create tabs for different aspects of recommendations
|
| 650 |
sim_tab1, sim_tab2 = st.tabs(["๐บ Similar Titles", "๐ Why These Recommendations"])
|
| 651 |
|
| 652 |
with sim_tab1:
|
| 653 |
-
for sim_content in similar_content:
|
| 654 |
with st.container():
|
| 655 |
col1, col2 = st.columns([3, 1])
|
| 656 |
with col1:
|
| 657 |
st.write(f"**{sim_content.get('title')}** ({sim_content.get('type')}, {sim_content.get('release_year')})")
|
| 658 |
st.write(f"*Available on:* {sim_content.get('streaming_service')}")
|
| 659 |
st.write(f"*Genres:* {sim_content.get('listed_in')}")
|
|
|
|
|
|
|
|
|
|
| 660 |
with col2:
|
| 661 |
st.write(f"**Match:** {sim_content.get('similarity', 'N/A')}")
|
| 662 |
-
|
| 663 |
-
with st.expander("See more details"):
|
| 664 |
-
st.write(f"**Cast:** {sim_content.get('cast', 'N/A')}")
|
| 665 |
-
st.write(f"**Director:** {sim_content.get('director', 'N/A')}")
|
| 666 |
-
st.write(f"**Description:** {sim_content.get('description', 'N/A')}")
|
| 667 |
st.write("---")
|
| 668 |
|
| 669 |
with sim_tab2:
|
| 670 |
st.write("**Why these recommendations?**")
|
| 671 |
st.write("""
|
| 672 |
-
These recommendations are
|
| 673 |
- Genre and theme matching
|
| 674 |
- Plot similarity analysis
|
| 675 |
- Cast and director relationships
|
|
|
|
| 260 |
"accept": "application/json"
|
| 261 |
}
|
| 262 |
|
|
|
|
| 263 |
title = content.get('title', '')
|
| 264 |
show_id = content.get('show_id', '')
|
|
|
|
| 265 |
|
| 266 |
# URLs for similarity tables using table IDs
|
| 267 |
similarity_table_urls = [
|
|
|
|
| 270 |
"https://mtoft20-potm.hf.space/api/v1/db/data/noco/p9pozkcw81t9aee/m2driodimid10k6" # Part 3 similarities
|
| 271 |
]
|
| 272 |
|
| 273 |
+
# Try finding by both show_id and title
|
| 274 |
+
query = f'where=(show_id,eq,{show_id})~and(title,eq,{title})'
|
| 275 |
+
params = {
|
| 276 |
+
"where": query
|
| 277 |
+
}
|
| 278 |
|
|
|
|
| 279 |
for table_url in similarity_table_urls:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
try:
|
| 281 |
response = requests.get(table_url, headers=headers, params=params)
|
|
|
|
|
|
|
| 282 |
|
| 283 |
if response.status_code == 200:
|
| 284 |
data = response.json()
|
| 285 |
if data.get('list'):
|
|
|
|
| 286 |
for entry in data['list']:
|
|
|
|
|
|
|
| 287 |
# Parse similar items
|
| 288 |
try:
|
| 289 |
similar_items = json.loads(entry['similar_items'])
|
|
|
|
| 290 |
|
| 291 |
# Get full content details for each similar item
|
| 292 |
similar_content = []
|
| 293 |
+
for item in similar_items[:n_recommendations]: # Only process top N items
|
| 294 |
# Query main content table for full details using show_id
|
| 295 |
show_id = item.get('show_id', '')
|
| 296 |
+
query = f'where=(show_id,eq,{show_id})'
|
| 297 |
content_params = {
|
| 298 |
"where": query
|
| 299 |
}
|
|
|
|
| 305 |
content_dict = content_data['list'][0]
|
| 306 |
content_dict['similarity'] = f"{item['similarity']:.2%}"
|
| 307 |
similar_content.append(content_dict)
|
|
|
|
|
|
|
|
|
|
| 308 |
|
| 309 |
+
return similar_content[:n_recommendations] # Return top N items
|
| 310 |
except Exception as parse_error:
|
| 311 |
+
continue
|
|
|
|
|
|
|
|
|
|
| 312 |
except Exception as e:
|
| 313 |
+
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
|
| 315 |
return []
|
| 316 |
except Exception as e:
|
|
|
|
|
|
|
| 317 |
return []
|
| 318 |
|
| 319 |
# =============================================================================
|
|
|
|
| 571 |
similar_button = st.button(f"๐ Find Similar Content", key=f"similar_{i}")
|
| 572 |
if similar_button:
|
| 573 |
with st.spinner("Finding similar content..."):
|
| 574 |
+
similar_content = get_similar_content(content, n_recommendations=5)
|
| 575 |
|
| 576 |
if similar_content:
|
| 577 |
# Create tabs for different aspects of recommendations
|
| 578 |
sim_tab1, sim_tab2 = st.tabs(["๐บ Similar Titles", "๐ Why These Recommendations"])
|
| 579 |
|
| 580 |
with sim_tab1:
|
| 581 |
+
for sim_content in similar_content[:5]: # Show top 5 similar items
|
| 582 |
with st.container():
|
| 583 |
col1, col2 = st.columns([3, 1])
|
| 584 |
with col1:
|
| 585 |
st.write(f"**{sim_content.get('title')}** ({sim_content.get('type')}, {sim_content.get('release_year')})")
|
| 586 |
st.write(f"*Available on:* {sim_content.get('streaming_service')}")
|
| 587 |
st.write(f"*Genres:* {sim_content.get('listed_in')}")
|
| 588 |
+
st.write(f"*Cast:* {sim_content.get('cast')}")
|
| 589 |
+
st.write(f"*Director:* {sim_content.get('director')}")
|
| 590 |
+
st.write(f"*Description:* {sim_content.get('description')}")
|
| 591 |
with col2:
|
| 592 |
st.write(f"**Match:** {sim_content.get('similarity', 'N/A')}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 593 |
st.write("---")
|
| 594 |
|
| 595 |
with sim_tab2:
|
| 596 |
st.write("**Why these recommendations?**")
|
| 597 |
st.write("""
|
| 598 |
+
These recommendations are based on multiple factors:
|
| 599 |
- Genre and theme matching
|
| 600 |
- Plot similarity analysis
|
| 601 |
- Cast and director relationships
|