1111from app .user .auth import get_current_user
1212from app .diary .models import Diary , RecommendedSong
1313from app .diary .schemas import DiaryCreateRequest , DiaryUpdateRequest , DiaryResponse , DiaryCountResponse , SongResponse , \
14- DiaryPreviewResponse , RecommendSongResponse
14+ DiaryPreviewResponse , RecommendSongResponse , EmotionTag
1515from app .user .models import User
1616from app .embedding .models import kobert , save_diary_embedding , split_sentences , get_user_preferred_genres , \
1717 get_songs_by_genre
3030logging .basicConfig (level = logging .INFO )
3131logger = logging .getLogger (__name__ )
3232
33+ emotion_to_genres = {
34+ 0 : ["댄스" , "록/메탈" ],
35+ 1 : ["댄스" , "포크/블루스" ],
36+ 2 : ["포크/블루스" , "R&B/Soul" ],
37+ 3 : ["포크/블루스" , "인디음악" , "R&B/Soul" ],
38+ 4 : ["포크/블루스" , "인디음악" , "R&B/Soul" ],
39+ 5 : ["발라드" , "포크/블루스" ],
40+ 6 : ["발라드" , "R&B/Soul" , "포크/블루스" ],
41+ 7 : ["랩/힙합" , "록/메탈" ]
42+ }
3343
3444def get_recently_recommended_lyrics (session , user_id : int , limit : int = 20 ) -> Set [str ]:
3545 """
@@ -553,16 +563,6 @@ async def create_diary_with_emotion_based_recommendation(
553563
554564 combined_embedding = kobert .get_embedding (best_sentence )
555565
556- emotion_to_genres = {
557- 0 : ["댄스" , "록/메탈" ], # 신남 → 에너지 + 감성 믹스
558- 1 : ["인디음악" , "댄스" , "포크/블루스" ], # 기대 → 발랄하거나 설레는 곡
559- 2 : ["포크/블루스" , "인디음악" , "R&B/Soul" ], # 편안 → 부드럽고 서정적인 계열
560- 3 : ["포크/블루스" , "인디음악" , "R&B/Soul" ], # 만족 → 감정 공감형 감성 음악
561- 4 : ["포크/블루스" , "인디음악" , "R&B/Soul" ], # 허무 → 무기력하거나 담담한 정서
562- 5 : ["발라드" , "포크/블루스" ], # 우울 → 조용하거나 격한 감정 침잠
563- 6 : ["발라드" , "R&B/Soul" , "포크/블루스" ], # 슬픔 → 애절함 + 회상적 감정
564- 7 : ["랩/힙합" , "록/메탈" ] # 분노 → 파워풀한 표현 위주
565- }
566566 genre_names = emotion_to_genres .get (emotion_id_full )
567567 if not genre_names :
568568 raise HTTPException (status_code = 400 , detail = "감정에 대응되는 장르가 없습니다." )
@@ -641,15 +641,15 @@ async def create_diary_with_emotion_based_recommendation(
641641 }
642642 ))
643643
644- top_3_raw = heapq .nlargest (7 , heap , key = lambda x : (x [0 ], x [1 ]))
644+ top_6_raw = heapq .nlargest (10 , heap , key = lambda x : (x [0 ], x [1 ]))
645645
646646 recent_lyrics = get_recently_recommended_lyrics (session , user_id = current_user .id )
647647
648648 seen_song_ids = set ()
649649 seen_lyrics = set ()
650- top_3 = []
650+ top_6 = []
651651
652- for sim , _ , match in top_3_raw :
652+ for sim , _ , match in top_6_raw :
653653 song_id = match ["song_id" ]
654654 lyric_chunk = " " .join (match ["lyric_chunk" ]).strip ()
655655
@@ -659,14 +659,14 @@ async def create_diary_with_emotion_based_recommendation(
659659 logger .info (f"최근 추천된 동일 가사 블럭 제외됨: { lyric_chunk } " )
660660 continue
661661
662- top_3 .append ((sim , match ))
662+ top_6 .append ((sim , match ))
663663 seen_song_ids .add (song_id )
664664 seen_lyrics .add (lyric_chunk )
665665
666- if len (top_3 ) >= 3 :
666+ if len (top_6 ) >= 6 :
667667 break
668668
669- if not top_3 :
669+ if not top_6 :
670670 raise HTTPException (status_code = 404 , detail = "적합한 노래를 찾을 수 없습니다." )
671671
672672 new_diary = Diary (
@@ -694,7 +694,7 @@ async def create_diary_with_emotion_based_recommendation(
694694 save_diary_embedding (session , new_diary .id , combined_embedding )
695695
696696 recommended_songs = []
697- for sim , match in top_3 :
697+ for sim , match in top_6 :
698698 song_data = RecommendedSong (
699699 diary_id = new_diary .id ,
700700 song_id = match ["song_id" ],
@@ -729,7 +729,7 @@ async def create_diary_with_emotion_based_recommendation(
729729 "best_sentence" : new_diary .best_sentence ,
730730 "created_at" : new_diary .created_at ,
731731 "updated_at" : new_diary .updated_at ,
732- "recommended_songs" : recommended_songs ,
732+ "recommended_songs" : recommended_songs [: 3 ] ,
733733 "top_emotions" : [
734734 {"emotion_id" : eid , "score" : round (score , 4 )}
735735 for eid , score in sorted (emotion_vote_counter .items (), key = lambda x : - x [1 ])[:3 ]
@@ -881,6 +881,26 @@ def delete_diary(
881881
882882 return {"message" : "일기가 삭제되었습니다!" }
883883
884+ @router .get ("/{diary_id}/emotion-tags" , response_model = List [EmotionTag ],
885+ summary = "감정 태그 조회" , description = "특정 일기의 감정 분석 결과(상위 3개)를 조회합니다." )
886+ def get_emotion_tags_by_diary (
887+ diary_id : int ,
888+ current_user : User = Depends (get_current_user ),
889+ db : Session = Depends (get_db )
890+ ):
891+ diary = db .query (Diary ).filter (
892+ Diary .id == diary_id ,
893+ Diary .user_id == current_user .id
894+ ).first ()
895+ if not diary :
896+ raise HTTPException (status_code = 404 , detail = "일기를 찾을 수 없습니다." )
897+
898+ tags = db .query (DiaryEmotionTag ).filter (
899+ DiaryEmotionTag .diary_id == diary_id
900+ ).order_by (DiaryEmotionTag .score .desc ()).all ()
901+
902+ return tags
903+
884904@router .get ("/{year}/{month}" , response_model = List [DiaryResponse ],
885905 summary = "특정 연도/월의 일기 조회" ,
886906 description = "입력한 연도와 월에 해당하는 일기를 모두 조회합니다." )
@@ -978,6 +998,32 @@ async def set_main_song(
978998 "youtube_url" : song .youtube_url
979999 }
9801000
1001+ @router .get ("/{diary_id}/recommended-songs/extra" , response_model = List [RecommendSongResponse ],
1002+ summary = "일기 리롤 버튼" ,
1003+ description = "일기 리롤 가능합니다. 1회." )
1004+ def get_additional_recommended_songs (
1005+ diary_id : int ,
1006+ current_user : User = Depends (get_current_user ),
1007+ db : Session = Depends (get_db )
1008+ ):
1009+ diary = db .query (Diary ).filter (
1010+ Diary .id == diary_id ,
1011+ Diary .user_id == current_user .id
1012+ ).first ()
1013+
1014+ if not diary :
1015+ raise HTTPException (404 , detail = "일기를 찾을 수 없습니다." )
1016+
1017+ all_songs = db .query (RecommendedSong ).filter (
1018+ RecommendedSong .diary_id == diary_id
1019+ ).order_by (RecommendedSong .similarity_score .desc ()).all ()
1020+
1021+ if len (all_songs ) <= 3 :
1022+ raise HTTPException (404 , detail = "추가 추천곡이 없습니다." )
1023+
1024+ return all_songs [3 :]
1025+
1026+
9811027"""
9821028안 씀
9831029@router.get("/recommended-songs/{recommended_song_id}/youtube-link-direct")
0 commit comments