MarfinF commited on
Commit
1e0a8d5
ยท
1 Parent(s): 8393125

retrieve information location.host

Browse files
Files changed (2) hide show
  1. backend/app.py +182 -35
  2. frontend/index.html +2 -1
backend/app.py CHANGED
@@ -1,41 +1,188 @@
 
1
  from fastapi import FastAPI, WebSocket
2
- from fastapi.responses import HTMLResponse
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  app = FastAPI()
5
 
6
- html = """
7
- <!DOCTYPE html>
8
- <html>
9
- <head>
10
- <title>WebSocket Chat</title>
11
- </head>
12
- <body>
13
- <h1>WebSocket Chat</h1>
14
- <textarea id="messages" rows="10" cols="30"></textarea><br>
15
- <input id="messageInput" type="text"><button onclick="sendMessage()">Send</button>
16
- <script>
17
- let ws = new WebSocket("wss://" + location.host + "/ws");
18
- ws.onmessage = function(event) {
19
- document.getElementById("messages").value += event.data + "\\n";
20
- };
21
- function sendMessage() {
22
- let input = document.getElementById("messageInput");
23
- ws.send(input.value);
24
- input.value = "";
25
- }
26
- </script>
27
- </body>
28
- </html>
29
- """
30
-
31
- @app.get("/")
32
- async def get():
33
- return HTMLResponse(html)
34
-
35
- @app.websocket("/ws")
36
- async def websocket_endpoint(websocket: WebSocket):
37
- await websocket.accept()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  while True:
39
- data = await websocket.receive_text()
40
- await websocket.send_text(f"Message received: {data}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
 
 
 
1
+ import asyncio
2
  from fastapi import FastAPI, WebSocket
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import FileResponse
5
+ import uvicorn
6
+ import json
7
+ from transformers import pipeline
8
+ from collections import deque
9
+ from collections import defaultdict
10
+ import math
11
+ import sys
12
+ import random
13
+ import os
14
+ from fastapi.middleware.cors import CORSMiddleware
15
+
16
+
17
+ sys.path.append(".")
18
 
19
  app = FastAPI()
20
 
21
+ # app.mount("/", StaticFiles(directory="frontend", html=True), name="frontend")
22
+
23
+ app.add_middleware(
24
+ CORSMiddleware,
25
+ allow_origins=["*"], # Bisa diubah ke domain spesifik untuk keamanan
26
+ allow_credentials=True,
27
+ allow_methods=["*"],
28
+ allow_headers=["*"],
29
+ )
30
+
31
+
32
+ # ๐Ÿ”น Load Emotion Detection Model
33
+ emotion_classifier = pipeline(
34
+ "zero-shot-classification",
35
+ model="MarfinF/marfin_emotion",
36
+ framework="pt"
37
+ )
38
+
39
+ # ๐Ÿ”น Emotion-to-Mood Mapping
40
+ emotion_to_mood = {
41
+ "senang": "happy",
42
+ "sedih": "sad",
43
+ "marah": "excited",
44
+ "takut": "relaxed",
45
+ "cinta": "romantic"
46
+ }
47
+
48
+ # ๐Ÿ”น WebSocket Clients
49
+ clients = {}
50
+ chat_history = deque(maxlen=4)
51
+
52
+ mood_to_genre = {
53
+ "happy": "pop",
54
+ "sad": "acoustic",
55
+ "excited": "rock",
56
+ "intense": "cinematic",
57
+ "romantic": "rnb",
58
+ "chill": "chill"
59
+ }
60
+
61
+ # ๐Ÿ”น Detect Emotion
62
+ def detect_emotion(text):
63
+ labels = ["takut", "marah", "sedih", "senang", "cinta"]
64
+ result = emotion_classifier(text, candidate_labels=labels)
65
+ top_emotion = result['labels'][0]
66
+ top_scores = result['scores'][0]
67
+ return top_emotion, top_scores
68
+
69
+ # ๐Ÿ”น Get Music Recommendations
70
+ def get_recommendations_by_mood(mood):
71
+ genre_folder = mood_to_genre.get(mood, "pop")
72
+ folder_path = f"music/{genre_folder}"
73
+ print("folder path")
74
+ print(folder_path)
75
+
76
+ # Check if folder exists
77
+ if not os.path.exists(folder_path):
78
+ return []
79
+ print("folder exist")
80
+
81
+ # List and shuffle songs
82
+ songs = [f"music/{genre_folder}/{song}" for song in os.listdir(folder_path) if song.endswith(".mp3")]
83
+ random.shuffle(songs)
84
+ return songs[:3] # Return top 3 shuffled songs
85
+
86
+ def softmax(scores):
87
+ exp_scores = [math.exp(score) for score in scores]
88
+ total = sum(exp_scores)
89
+ return [exp_score / total for exp_score in exp_scores]
90
+
91
+ # ๐Ÿ”น Broadcast User List
92
+ async def broadcast_user_list():
93
+ user_list = list(clients.keys())
94
+ message = json.dumps({
95
+ "type": "user_list",
96
+ "users": user_list
97
+ })
98
+ for client in clients.values():
99
+ await client.send_text(message)
100
+
101
+ # ๐Ÿ”น Periodic Music Recommender every 30 seconds
102
+ async def periodic_recommendation():
103
  while True:
104
+ user_list = list(clients.keys())
105
+ if len(user_list) >= 2:
106
+ await asyncio.sleep(10)
107
+ if clients: # Only run if someone is connected
108
+ if len(chat_history) > 0:
109
+ # 1. Detect emotion dan ambil (label, score)
110
+ print("chat history")
111
+ print(chat_history)
112
+ emotions = [detect_emotion(msg) for msg in chat_history]
113
+ print("Detected Emotions:", emotions)
114
+
115
+ # 2. Group by emotion + sum score
116
+ emotion_score_sum = defaultdict(float)
117
+ for label, score in emotions:
118
+ emotion_score_sum[label] += score
119
+
120
+ # 3. Softmax
121
+ labels = list(emotion_score_sum.keys())
122
+ scores = list(emotion_score_sum.values())
123
+ softmax_scores = softmax(scores)
124
+
125
+ # 4. Pair label + softmax_score
126
+ softmax_result = list(zip(labels, softmax_scores))
127
+ print("Softmax Result:", softmax_result)
128
+
129
+ # 5. Dominant emotion
130
+ most_common_emotion = max(softmax_result, key=lambda x: x[1])[0]
131
+ print("Dominant Emotion:", most_common_emotion)
132
+ mood = emotion_to_mood.get(most_common_emotion, "chill")
133
+ music_recommendations = get_recommendations_by_mood(mood)
134
+ else:
135
+ music_recommendations = ["chill"] # default if no chat
136
+
137
+ recommendation_response = {
138
+ "recommendations": music_recommendations,
139
+ "genre": mood_to_genre.get(mood, "pop")
140
+ }
141
+
142
+ for client in clients.values():
143
+ await client.send_text(json.dumps(recommendation_response))
144
+ else:
145
+ await asyncio.sleep(2)
146
+ await broadcast_user_list()
147
+
148
+ # ๐Ÿ”น Start periodic task
149
+ @app.on_event("startup")
150
+ async def start_recommender():
151
+ asyncio.create_task(periodic_recommendation())
152
+
153
+ # ๐Ÿ”น WebSocket Endpoint
154
+ @app.websocket("/chat/{username}")
155
+ async def chat_endpoint(websocket: WebSocket, username: str):
156
+ await websocket.accept()
157
+ clients[username] = websocket
158
+ print(f"{username} joined")
159
+
160
+ await broadcast_user_list()
161
+
162
+ try:
163
+ while True:
164
+ data = await websocket.receive_text()
165
+ message_data = json.loads(data)
166
+
167
+ chat_history.append(message_data["message"])
168
+ response = {
169
+ "username": message_data["username"],
170
+ "message": message_data["message"]
171
+ }
172
+
173
+ # Broadcast message to all clients
174
+ for client in clients.values():
175
+ await client.send_text(json.dumps(response))
176
+
177
+ except Exception as e:
178
+ print(f"{username} disconnected: {e}")
179
+ del clients[username]
180
+ await broadcast_user_list()
181
+
182
+ @app.get("/frontend")
183
+ def read_root():
184
+ print("frontend")
185
+ return FileResponse("frontend/index.html")
186
 
187
+ if __name__ == "__main__":
188
+ uvicorn.run(app, host="0.0.0.0", port=7860)
frontend/index.html CHANGED
@@ -176,7 +176,8 @@
176
  alert("Please enter a username!");
177
  return;
178
  }
179
-
 
180
  ws = new WebSocket(`${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/chat/${username}`);
181
 
182
  document.getElementById("music-player").addEventListener("play", () => {
 
176
  alert("Please enter a username!");
177
  return;
178
  }
179
+ console.log("location host")
180
+ console.log(location.host)
181
  ws = new WebSocket(`${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/chat/${username}`);
182
 
183
  document.getElementById("music-player").addEventListener("play", () => {