Spaces:
Sleeping
Sleeping
| import json | |
| import numpy as np | |
| import torch | |
| from flask import Flask, request, jsonify, render_template | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| from sentence_transformers import SentenceTransformer | |
| import os | |
| # --- μ€μ --- | |
| VERSION = "v1.5" # λλ v1.3 λ± μ¬μ©νμλ λ²μ μ λ§κ² μμ | |
| TOP_K = 3 | |
| DEFAULT_EMOTION_WEIGHT = 0.8 | |
| DEFAULT_CONTEXT_WEIGHT = 0.2 | |
| # --- νμΌ κ²½λ‘ μ μ --- | |
| EMOTION_MODEL_PATH = f'./my_emotion_model_{VERSION}' | |
| MUSIC_DB_SONG_INFO_PATH = f'./lyrics_recommend/song_database_{VERSION}.json' | |
| MUSIC_DB_EMOTION_VECTORS_PATH = f'./lyrics_recommend/lyrics_emotion_embeddings_{VERSION}.npy' | |
| MUSIC_DB_CONTEXT_VECTORS_PATH = f'./lyrics_recommend/lyrics_context_embeddings_{VERSION}.npy' | |
| FLOWER_DB_FLOWER_INFO_PATH = f'./flower_recommend/flower_database_{VERSION}.json' | |
| FLOWER_DB_EMOTION_VECTORS_PATH = f'./flower_recommend/flower_emotion_embeddings_{VERSION}.npy' | |
| FLOWER_DB_CONTEXT_VECTORS_PATH = f'./flower_recommend/flower_context_embeddings_{VERSION}.npy' | |
| # --- λͺ¨λΈ λ° λ°μ΄ν° λ‘λ --- | |
| print("μλ² μμ: λͺ¨λΈκ³Ό λ°μ΄ν°λ² μ΄μ€λ₯Ό λ‘λν©λλ€...") | |
| try: | |
| emotion_tokenizer = AutoTokenizer.from_pretrained(EMOTION_MODEL_PATH) | |
| emotion_model = AutoModelForSequenceClassification.from_pretrained(EMOTION_MODEL_PATH, output_hidden_states=True) | |
| emotion_model.eval() | |
| ## BM-K/KoSimCSE-roberta or jhgan/ko-sbert-nli | |
| context_model = SentenceTransformer('BM-K/KoSimCSE-roberta') | |
| music_emotion_vectors = np.load(MUSIC_DB_EMOTION_VECTORS_PATH) | |
| music_context_vectors = np.load(MUSIC_DB_CONTEXT_VECTORS_PATH) | |
| with open(MUSIC_DB_SONG_INFO_PATH, 'r', encoding='utf-8') as f: | |
| music_db_info = json.load(f) | |
| print("- μμ DB λ‘λ μλ£!") | |
| flower_emotion_vectors = np.load(FLOWER_DB_EMOTION_VECTORS_PATH) | |
| flower_context_vectors = np.load(FLOWER_DB_CONTEXT_VECTORS_PATH) | |
| with open(FLOWER_DB_FLOWER_INFO_PATH, 'r', encoding='utf-8') as f: | |
| flower_db_info = json.load(f) | |
| print("- κ½ DB λ‘λ μλ£!") | |
| except FileNotFoundError as e: | |
| print(f"μ€λ₯: νμ νμΌμ μ°Ύμ μ μμ΅λλ€. ({e})") | |
| print("λͺ¨λ νμΌμ΄ app.pyμ κ°μ ν΄λ ꡬ쑰μ μλμ§ νμΈνμΈμ.") | |
| exit() | |
| # --- Flask μ± μμ± --- | |
| app = Flask(__name__) | |
| def cosine_similarity(vec1, vec2_matrix): | |
| vec1_norm = np.linalg.norm(vec1) | |
| vec2_matrix_norm = np.linalg.norm(vec2_matrix, axis=1) | |
| epsilon = 1e-8 | |
| return np.dot(vec2_matrix, vec1) / (vec1_norm * vec2_matrix_norm + epsilon) | |
| def home(): | |
| return render_template('index.html') | |
| def flower_page(): | |
| return render_template('flower.html') | |
| def recommend_music_api(): | |
| data = request.json | |
| user_input = data.get('text') | |
| emotion_weight = data.get('emotion_weight', 0.8) | |
| context_weight = data.get('context_weight', 0.2) | |
| if not user_input: | |
| return jsonify({"error": "ν μ€νΈλ₯Ό μ λ ₯ν΄μ£ΌμΈμ."}), 400 | |
| inputs = emotion_tokenizer(user_input, return_tensors="pt", max_length=128, truncation=True) | |
| with torch.no_grad(): | |
| outputs = emotion_model(**inputs) | |
| user_emotion_label = emotion_model.config.id2label[torch.argmax(outputs.logits, dim=-1).item()] | |
| user_emotion_vector = outputs.hidden_states[-1][:, 0, :].numpy().flatten() | |
| user_context_vector = context_model.encode(user_input) | |
| candidate_indices = [i for i, song in enumerate(music_db_info) ] | |
| ##if song['emotion'] == user_emotion_label | |
| if not candidate_indices: | |
| return jsonify({"emotion": user_emotion_label, "recommendations": []}) | |
| cand_emotion_vectors = music_emotion_vectors[candidate_indices] | |
| cand_context_vectors = music_context_vectors[candidate_indices] | |
| emotion_sims = cosine_similarity(user_emotion_vector, cand_emotion_vectors) | |
| context_sims = cosine_similarity(user_context_vector, cand_context_vectors) | |
| total_scores = (emotion_weight * emotion_sims) + (context_weight * context_sims) | |
| sorted_indices = np.argsort(total_scores)[::-1] | |
| recommendations = [] | |
| for i in range(min(TOP_K, len(sorted_indices))): | |
| original_idx = candidate_indices[sorted_indices[i]] | |
| song = music_db_info[original_idx] | |
| score = total_scores[sorted_indices[i]] | |
| recommendations.append({ | |
| "rank": i + 1, "artist": song['artist'], "title": song['title'], | |
| "score": float(score), "videoId": song.get('videoId', '') | |
| }) | |
| return jsonify({"emotion": user_emotion_label, "recommendations": recommendations}) | |
| def recommend_flower_api(): | |
| data = request.json | |
| user_input = data.get('text') | |
| emotion_weight = data.get('emotion_weight', 0.2) | |
| context_weight = data.get('context_weight', 0.8) | |
| if not user_input: | |
| return jsonify({"error": "ν μ€νΈλ₯Ό μ λ ₯ν΄μ£ΌμΈμ."}), 400 | |
| inputs = emotion_tokenizer(user_input, return_tensors="pt", max_length=128, truncation=True) | |
| with torch.no_grad(): | |
| outputs = emotion_model(**inputs) | |
| user_emotion_label = emotion_model.config.id2label[torch.argmax(outputs.logits, dim=-1).item()] | |
| user_emotion_vector = outputs.hidden_states[-1][:, 0, :].numpy().flatten() | |
| user_context_vector = context_model.encode(user_input) | |
| candidate_indices = [i for i, flower in enumerate(flower_db_info) if flower['emotion'] == user_emotion_label] | |
| if not candidate_indices: | |
| return jsonify({"emotion": user_emotion_label, "recommendations": []}) | |
| cand_emotion_vectors = flower_emotion_vectors[candidate_indices] | |
| cand_context_vectors = flower_context_vectors[candidate_indices] | |
| emotion_sims = cosine_similarity(user_emotion_vector, cand_emotion_vectors) | |
| context_sims = cosine_similarity(user_context_vector, cand_context_vectors) | |
| total_scores = (emotion_weight * emotion_sims) + (context_weight * context_sims) | |
| sorted_indices = np.argsort(total_scores)[::-1] | |
| recommendations = [] | |
| for i in range(min(TOP_K, len(sorted_indices))): | |
| original_idx = candidate_indices[sorted_indices[i]] | |
| flower = flower_db_info[original_idx] | |
| score = total_scores[sorted_indices[i]] | |
| recommendations.append({ | |
| "rank": i + 1, "name": flower['name'], "meaning": flower['words'], | |
| "score": float(score) | |
| }) | |
| return jsonify({"emotion": user_emotion_label, "recommendations": recommendations}) | |
| # Hugging Face Spacesλ κΈ°λ³Έμ μΌλ‘ 7860 ν¬νΈλ₯Ό μ¬μ©ν©λλ€. | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=7860, debug=True) | |