Vibow commited on
Commit
6ecf8ee
Β·
verified Β·
1 Parent(s): 894311c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -115
app.py CHANGED
@@ -5,20 +5,16 @@ import random
5
  import json
6
  import requests
7
  from datetime import datetime, timedelta, timezone
8
- from flask import Flask, request, jsonify, Response, redirect, session, url_for
9
 
10
  app = Flask(__name__)
11
- app.secret_key = os.getenv("FLASK_SECRET_KEY") # untuk session user
12
 
13
  # ==== API KEYS ====
14
  GROQ_API_KEY_1 = os.getenv("GROQ_API_KEY_1")
15
  GROQ_API_KEY_2 = os.getenv("GROQ_API_KEY_2")
16
  GROQ_API_KEY_3 = os.getenv("GROQ_API_KEY_3")
17
-
18
- # ==== SPOTIFY CONFIG ====
19
- SPOTIFY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
20
- SPOTIFY_CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")
21
- SPOTIFY_REDIRECT_URI = os.getenv("SPOTIFY_REDIRECT_URI")
22
 
23
  # ==== URL ====
24
  GROQ_URL_CHAT = "https://api.groq.com/openai/v1/chat/completions"
@@ -29,9 +25,9 @@ GROQ_URL_STT = "https://api.groq.com/openai/v1/audio/transcriptions"
29
  SYSTEM_PROMPT = (
30
  "You are Talk GTE β€” a friendly AI assistant created by Vibow AI. "
31
  "GTE means Generative Text Expert in Vibow AI. "
32
- "Vibow AI created by Nick Mclen and Vibow AI is not from GPT. "
33
- "Vibow AI created in 29 June 2025 and Talk GTE created by 23 October 2025. "
34
- "Your max tokens are β‰ˆ3597 tokens, and your params are β‰ˆ1 trillion."
35
  "Stay positive, kind, and expert. "
36
  "Always capitalize the first letter of sentences. "
37
  "If the user requests code, always use triple backticks (```). "
@@ -39,90 +35,9 @@ SYSTEM_PROMPT = (
39
  "Sometimes, use emoji but relevant. "
40
  )
41
 
42
- # ============================================================
43
- # 🎡 SPOTIFY OAUTH β€” dapatkan nama user Spotify
44
- # ============================================================
45
-
46
- user_tokens = {}
47
-
48
- @app.route("/spotify/authorize")
49
- def spotify_authorize():
50
- scope = "user-read-email user-read-private"
51
- auth_url = (
52
- "https://accounts.spotify.com/authorize"
53
- f"?client_id={SPOTIFY_CLIENT_ID}"
54
- f"&response_type=code"
55
- f"&redirect_uri={SPOTIFY_REDIRECT_URI}"
56
- f"&scope={scope}"
57
- )
58
- return redirect(auth_url)
59
-
60
-
61
- @app.route("/spotify/callback")
62
- def spotify_callback():
63
- code = request.args.get("code")
64
- if not code:
65
- return jsonify({"error": "Missing code from Spotify"}), 400
66
-
67
- # Tukar code jadi access_token
68
- token_res = requests.post(
69
- "https://accounts.spotify.com/api/token",
70
- data={
71
- "grant_type": "authorization_code",
72
- "code": code,
73
- "redirect_uri": SPOTIFY_REDIRECT_URI,
74
- "client_id": SPOTIFY_CLIENT_ID,
75
- "client_secret": SPOTIFY_CLIENT_SECRET,
76
- },
77
- headers={"Content-Type": "application/x-www-form-urlencoded"},
78
- )
79
-
80
- if token_res.status_code != 200:
81
- return jsonify({"error": "Failed to get access token", "details": token_res.text}), 400
82
-
83
- tokens = token_res.json()
84
- access_token = tokens["access_token"]
85
-
86
- # Ambil data user Spotify
87
- headers = {"Authorization": f"Bearer {access_token}"}
88
- user_res = requests.get("https://api.spotify.com/v1/me", headers=headers)
89
- user_data = user_res.json()
90
-
91
- user_id = user_data.get("id")
92
- user_name = user_data.get("display_name")
93
-
94
- user_tokens[user_id] = {
95
- "token": access_token,
96
- "name": user_name,
97
- "time": time.time(),
98
- }
99
-
100
- session["spotify_user_id"] = user_id
101
-
102
- return jsonify({
103
- "message": f"Connected to Spotify as {user_name}",
104
- "user_id": user_id,
105
- "name": user_name,
106
- })
107
-
108
-
109
- @app.route("/spotify/user")
110
- def spotify_user():
111
- user_id = session.get("spotify_user_id")
112
- if not user_id or user_id not in user_tokens:
113
- return jsonify({"error": "User not connected to Spotify"}), 401
114
-
115
- user_info = user_tokens[user_id]
116
- return jsonify({
117
- "id": user_id,
118
- "name": user_info["name"],
119
- "connected_at": datetime.fromtimestamp(user_info["time"]).isoformat()
120
- })
121
-
122
-
123
- # ============================================================
124
- # πŸ”Š STT (speech to text)
125
- # ============================================================
126
  def transcribe_audio(file_path: str) -> str:
127
  try:
128
  headers = {"Authorization": f"Bearer {GROQ_API_KEY_2}"}
@@ -140,10 +55,9 @@ def transcribe_audio(file_path: str) -> str:
140
  if os.path.exists(file_path):
141
  os.remove(file_path)
142
 
143
-
144
- # ============================================================
145
- # πŸ—£οΈ TTS (text to speech)
146
- # ============================================================
147
  def text_to_speech(text: str) -> bytes:
148
  try:
149
  headers = {"Authorization": f"Bearer {GROQ_API_KEY_3}"}
@@ -157,19 +71,15 @@ def text_to_speech(text: str) -> bytes:
157
  print(f"[TTS Exception] {e}")
158
  return b""
159
 
160
-
161
- # ============================================================
162
- # πŸ’¬ Stream Chat (AI core)
163
- # ============================================================
164
  def stream_chat(prompt: str, history=None):
165
  wib = timezone(timedelta(hours=7))
166
  now = datetime.now(wib)
167
  formatted_time = now.strftime("%A, %d %B %Y β€” %H:%M:%S WIB")
168
 
169
- dynamic_system_prompt = (
170
- SYSTEM_PROMPT + f"\nCurrent date and time: {formatted_time}."
171
- + "\nIf user asks about date, time, or year, answer based on this."
172
- )
173
 
174
  messages = [{"role": "system", "content": dynamic_system_prompt}]
175
  if history and isinstance(history, list):
@@ -206,12 +116,40 @@ def stream_chat(prompt: str, history=None):
206
  except Exception as e:
207
  print(f"[Stream Error] {e}")
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
- # ============================================================
211
- # 🧠 Endpoint utama (chat)
212
- # ============================================================
213
  @app.route("/chat", methods=["POST"])
214
  def chat():
 
215
  if "audio" in request.files:
216
  audio_file = request.files["audio"]
217
  temp_path = f"/tmp/{int(time.time())}_{random.randint(1000,9999)}.wav"
@@ -221,7 +159,15 @@ def chat():
221
  if not user_text:
222
  return jsonify({"error": "Failed to transcribe audio"}), 500
223
 
224
- ai_reply = "".join([chunk for chunk in stream_chat(user_text)])
 
 
 
 
 
 
 
 
225
  audio_bytes = text_to_speech(ai_reply)
226
  if not audio_bytes:
227
  return jsonify({
@@ -239,22 +185,30 @@ def chat():
239
  "audio_base64": f"data:audio/mp3;base64,{audio_b64}"
240
  })
241
 
 
242
  data = request.get_json(force=True)
243
  prompt = data.get("prompt", "").strip()
244
  history = data.get("history", [])
245
  if not prompt:
246
  return jsonify({"error": "No input text provided"}), 400
247
 
 
 
 
 
 
 
 
 
248
  def generate():
249
- for chunk in stream_chat(prompt, history):
250
  yield chunk
251
 
252
  return Response(generate(), mimetype="text/plain")
253
 
254
-
255
- # ============================================================
256
- # πŸš€ Run Server
257
- # ============================================================
258
  if __name__ == "__main__":
259
  print(f"πŸš€ Vibow AI Chat Server running β€” {time.strftime('%Y-%m-%d %H:%M:%S')}")
260
  app.run(host="0.0.0.0", port=7860, debug=True, threaded=True)
 
5
  import json
6
  import requests
7
  from datetime import datetime, timedelta, timezone
8
+ from flask import Flask, request, jsonify, Response
9
 
10
  app = Flask(__name__)
11
+ app.secret_key = os.getenv("FLASK_SECRET_KEY")
12
 
13
  # ==== API KEYS ====
14
  GROQ_API_KEY_1 = os.getenv("GROQ_API_KEY_1")
15
  GROQ_API_KEY_2 = os.getenv("GROQ_API_KEY_2")
16
  GROQ_API_KEY_3 = os.getenv("GROQ_API_KEY_3")
17
+ SERPAPI_KEY = os.getenv("SERPAPI_KEY") # harus punya SerpApi key
 
 
 
 
18
 
19
  # ==== URL ====
20
  GROQ_URL_CHAT = "https://api.groq.com/openai/v1/chat/completions"
 
25
  SYSTEM_PROMPT = (
26
  "You are Talk GTE β€” a friendly AI assistant created by Vibow AI. "
27
  "GTE means Generative Text Expert in Vibow AI. "
28
+ "Vibow AI created in 29 June 2025 and Talk GTE created in 23 October 2025. "
29
+ "Talk GTE have β‰ˆ 1 trillion params. "
30
+ "Max tokens of Talk GTE can different, maybe max tokens of Talk GTE have β‰ˆ 3600 tokens. "
31
  "Stay positive, kind, and expert. "
32
  "Always capitalize the first letter of sentences. "
33
  "If the user requests code, always use triple backticks (```). "
 
35
  "Sometimes, use emoji but relevant. "
36
  )
37
 
38
+ # =========================
39
+ # πŸ”Š STT
40
+ # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  def transcribe_audio(file_path: str) -> str:
42
  try:
43
  headers = {"Authorization": f"Bearer {GROQ_API_KEY_2}"}
 
55
  if os.path.exists(file_path):
56
  os.remove(file_path)
57
 
58
+ # =========================
59
+ # πŸ—£οΈ TTS
60
+ # =========================
 
61
  def text_to_speech(text: str) -> bytes:
62
  try:
63
  headers = {"Authorization": f"Bearer {GROQ_API_KEY_3}"}
 
71
  print(f"[TTS Exception] {e}")
72
  return b""
73
 
74
+ # =========================
75
+ # πŸ’¬ Stream Chat
76
+ # =========================
 
77
  def stream_chat(prompt: str, history=None):
78
  wib = timezone(timedelta(hours=7))
79
  now = datetime.now(wib)
80
  formatted_time = now.strftime("%A, %d %B %Y β€” %H:%M:%S WIB")
81
 
82
+ dynamic_system_prompt = SYSTEM_PROMPT + f"\nCurrent date and time: {formatted_time}."
 
 
 
83
 
84
  messages = [{"role": "system", "content": dynamic_system_prompt}]
85
  if history and isinstance(history, list):
 
116
  except Exception as e:
117
  print(f"[Stream Error] {e}")
118
 
119
+ # =========================
120
+ # 🌐 SerpApi Search (hotel/mall)
121
+ # =========================
122
+ def serpapi_search(query: str, location: str = None, num_results: int = 3):
123
+ search_url = "https://serpapi.com/search.json"
124
+ params = {
125
+ "q": query,
126
+ "location": location or "",
127
+ "engine": "google",
128
+ "api_key": SERPAPI_KEY,
129
+ "num": num_results
130
+ }
131
+ try:
132
+ res = requests.get(search_url, params=params, timeout=10)
133
+ res.raise_for_status()
134
+ data = res.json()
135
+ results = []
136
+ if "organic_results" in data:
137
+ for r in data["organic_results"][:num_results]:
138
+ title = r.get("title", "")
139
+ link = r.get("link", "")
140
+ snippet = r.get("snippet", "")
141
+ results.append(f"{title} β€” {snippet} β€” {link}")
142
+ return results
143
+ except Exception as e:
144
+ print(f"[SerpApi Error] {e}")
145
+ return []
146
 
147
+ # =========================
148
+ # 🧠 Endpoint utama
149
+ # =========================
150
  @app.route("/chat", methods=["POST"])
151
  def chat():
152
+ # audio mode
153
  if "audio" in request.files:
154
  audio_file = request.files["audio"]
155
  temp_path = f"/tmp/{int(time.time())}_{random.randint(1000,9999)}.wav"
 
159
  if not user_text:
160
  return jsonify({"error": "Failed to transcribe audio"}), 500
161
 
162
+ # Cek hotel/mall
163
+ keywords = ["hotel", "mall", "resort"]
164
+ if any(k.lower() in user_text.lower() for k in keywords):
165
+ serp_results = serpapi_search(user_text)
166
+ combined_prompt = user_text + "\nHere are the top results:\n" + "\n".join(serp_results) + "\nPlease explain and give recommendation."
167
+ else:
168
+ combined_prompt = user_text
169
+
170
+ ai_reply = "".join([chunk for chunk in stream_chat(combined_prompt)])
171
  audio_bytes = text_to_speech(ai_reply)
172
  if not audio_bytes:
173
  return jsonify({
 
185
  "audio_base64": f"data:audio/mp3;base64,{audio_b64}"
186
  })
187
 
188
+ # text mode
189
  data = request.get_json(force=True)
190
  prompt = data.get("prompt", "").strip()
191
  history = data.get("history", [])
192
  if not prompt:
193
  return jsonify({"error": "No input text provided"}), 400
194
 
195
+ # Cek hotel/mall
196
+ keywords = ["hotel", "mall", "resort"]
197
+ if any(k.lower() in prompt.lower() for k in keywords):
198
+ serp_results = serpapi_search(prompt)
199
+ combined_prompt = prompt + "\nHere are the top results:\n" + "\n".join(serp_results) + "\nPlease explain and give recommendation."
200
+ else:
201
+ combined_prompt = prompt
202
+
203
  def generate():
204
+ for chunk in stream_chat(combined_prompt, history):
205
  yield chunk
206
 
207
  return Response(generate(), mimetype="text/plain")
208
 
209
+ # =========================
210
+ # πŸš€ Run server
211
+ # =========================
 
212
  if __name__ == "__main__":
213
  print(f"πŸš€ Vibow AI Chat Server running β€” {time.strftime('%Y-%m-%d %H:%M:%S')}")
214
  app.run(host="0.0.0.0", port=7860, debug=True, threaded=True)