video-finder-algorithm/dashboard_api.py
Gauri Joshi d6f59d2d94 final
2025-08-25 21:48:03 +02:00

243 lines
9.0 KiB
Python

import os
from flask import Flask, jsonify, render_template, request
from flask_cors import CORS
from dotenv import load_dotenv
from src.database.manager import setup_database_tables
from src.database.preference_operations import get_training_data_from_database, get_unrated_videos_with_features_from_database, get_rated_count_from_database, save_video_rating_to_database
from src.database.video_operations import get_unrated_videos_from_database
from src.ml.model_training import create_recommendation_model, train_model_on_user_preferences
from src.ml.predictions import predict_video_preferences_with_model
load_dotenv()
app = Flask(__name__)
CORS(app)
class DashboardAPI:
def __init__(self):
self.db_path = "video_inspiration.db"
self.model = None
self.model_trained = False
setup_database_tables(self.db_path)
self._initialize_model()
def _initialize_model(self):
rated_count = get_rated_count_from_database(self.db_path)
if rated_count >= 10:
self.model = create_recommendation_model()
training_data = get_training_data_from_database(self.db_path)
success = train_model_on_user_preferences(self.model, training_data)
if success:
self.model_trained = True
def get_recommendations(self):
if self.model_trained and self.model:
video_features = get_unrated_videos_with_features_from_database(self.db_path)
recommendations = predict_video_preferences_with_model(self.model, video_features)
return recommendations[:12] # Return 12 videos for dashboard
else:
fallback_videos = get_unrated_videos_from_database(12, self.db_path)
for video in fallback_videos:
video['like_probability'] = 0.5 # Default probability
return fallback_videos
def get_liked_videos(self):
"""Get videos that user liked, ordered by AI match confidence"""
import sqlite3
try:
conn = sqlite3.connect(self.db_path)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
# Get liked videos with features
query = """
SELECT v.*, vf.*, p.liked
FROM videos v
JOIN video_features vf ON v.id = vf.video_id
JOIN preferences p ON v.id = p.video_id
WHERE p.liked = 1
ORDER BY v.view_count DESC
"""
cursor.execute(query)
results = cursor.fetchall()
conn.close()
liked_videos = []
for row in results:
video = {
'id': row['id'],
'title': row['title'],
'channel_name': row['channel_name'],
'view_count': row['view_count'],
'url': f"https://www.youtube.com/watch?v={row['id']}"
}
liked_videos.append(video)
# If model is trained, predict confidence for liked videos
if self.model_trained and self.model and liked_videos:
# Create pandas DataFrame for prediction
import pandas as pd
df_data = []
for row in results:
row_data = {
'id': row['id'],
'title': row['title'],
'channel_name': row['channel_name'],
'view_count': row['view_count'],
'title_length': row['title_length'],
'description_length': row['description_length'],
'view_like_ratio': row['view_like_ratio'],
'engagement_score': row['engagement_score'],
'title_sentiment': row['title_sentiment'],
'has_tutorial_keywords': row['has_tutorial_keywords'],
'has_beginner_keywords': row['has_beginner_keywords'],
'has_ai_keywords': row['has_ai_keywords'],
'has_challenge_keywords': row['has_challenge_keywords'],
'has_time_constraint': row['has_time_constraint']
}
df_data.append(row_data)
video_features_df = pd.DataFrame(df_data)
# Get predictions for confidence scores
predictions = predict_video_preferences_with_model(self.model, video_features_df)
# Sort by confidence and return
return sorted(predictions, key=lambda x: x.get('like_probability', 0), reverse=True)
# If no model, return with default confidence
for video in liked_videos:
video['like_probability'] = 0.8 # High default for liked videos
return liked_videos
except Exception as e:
print(f"Error getting liked videos: {e}")
return []
dashboard_api = DashboardAPI()
@app.route('/')
def dashboard():
return render_template('dashboard.html')
@app.route('/api/recommendations')
def get_recommendations():
try:
recommendations = dashboard_api.get_recommendations()
formatted_recommendations = []
for video in recommendations:
formatted_recommendations.append({
'id': video['id'],
'title': video['title'],
'channel_name': video['channel_name'],
'view_count': video['view_count'],
'url': video['url'],
'thumbnail': f"https://img.youtube.com/vi/{video['id']}/hqdefault.jpg",
'confidence': round(video.get('like_probability', 0.5) * 100),
'views_formatted': format_view_count(video['view_count'])
})
return jsonify({
'success': True,
'videos': formatted_recommendations,
'model_trained': dashboard_api.model_trained,
'total_ratings': get_rated_count_from_database(dashboard_api.db_path)
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
}), 500
@app.route('/api/rate', methods=['POST'])
def rate_video():
try:
data = request.json
video_id = data.get('video_id')
liked = data.get('liked')
if not video_id or liked is None:
return jsonify({
'success': False,
'error': 'Missing video_id or liked parameter'
}), 400
# Save the rating
save_video_rating_to_database(video_id, liked, "", dashboard_api.db_path)
# Check if we should retrain the model
model_retrained = False
rated_count = get_rated_count_from_database(dashboard_api.db_path)
if rated_count >= 10: # Minimum ratings needed for training
# Retrain the model with new data
if not dashboard_api.model:
dashboard_api.model = create_recommendation_model()
training_data = get_training_data_from_database(dashboard_api.db_path)
success = train_model_on_user_preferences(dashboard_api.model, training_data)
if success:
dashboard_api.model_trained = True
model_retrained = True
return jsonify({
'success': True,
'message': 'Rating saved successfully',
'model_retrained': model_retrained,
'total_ratings': rated_count
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
}), 500
@app.route('/api/liked')
def get_liked_videos():
try:
liked_videos = dashboard_api.get_liked_videos()
formatted_videos = []
for video in liked_videos:
formatted_videos.append({
'id': video['id'],
'title': video['title'],
'channel_name': video['channel_name'],
'view_count': video['view_count'],
'url': video['url'],
'thumbnail': f"https://img.youtube.com/vi/{video['id']}/hqdefault.jpg",
'confidence': round(video.get('like_probability', 0.8) * 100),
'views_formatted': format_view_count(video['view_count'])
})
return jsonify({
'success': True,
'videos': formatted_videos,
'total_liked': len(formatted_videos)
})
except Exception as e:
return jsonify({
'success': False,
'error': str(e)
}), 500
def format_view_count(count):
if count >= 1000000:
return f"{count/1000000:.1f}M views"
elif count >= 1000:
return f"{count/1000:.1f}K views"
else:
return f"{count} views"
if __name__ == '__main__':
app.run(debug=True, port=5001)