Vibow commited on
Commit
7d18b9a
Β·
verified Β·
1 Parent(s): 6ecf8ee

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -96
app.py CHANGED
@@ -14,7 +14,7 @@ app.secret_key = os.getenv("FLASK_SECRET_KEY")
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"
@@ -27,7 +27,7 @@ SYSTEM_PROMPT = (
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 (```). "
@@ -36,7 +36,7 @@ SYSTEM_PROMPT = (
36
  )
37
 
38
  # =========================
39
- # πŸ”Š STT
40
  # =========================
41
  def transcribe_audio(file_path: str) -> str:
42
  try:
@@ -72,18 +72,57 @@ def text_to_speech(text: str) -> bytes:
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):
86
- messages.extend(history)
87
  messages.append({"role": "user", "content": prompt})
88
 
89
  payload = {
@@ -99,116 +138,56 @@ def stream_chat(prompt: str, history=None):
99
  try:
100
  with requests.post(GROQ_URL_CHAT, headers=headers, json=payload, stream=True) as r:
101
  for line in r.iter_lines():
102
- if not line:
103
- continue
104
  line = line.decode("utf-8")
105
  if line.startswith("data: "):
106
  data = line[6:]
107
- if data == "[DONE]":
108
- break
109
  try:
110
- chunk = json.loads(data)
111
- delta = chunk["choices"][0]["delta"].get("content", "")
112
- if delta:
113
- yield delta
114
- except:
115
- continue
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"
156
- audio_file.save(temp_path)
157
-
158
- user_text = transcribe_audio(temp_path)
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({
174
- "mode": "voice",
175
- "transcript": user_text,
176
- "reply_text": ai_reply,
177
- "error": "TTS failed"
178
- }), 500
179
-
180
- audio_b64 = base64.b64encode(audio_bytes).decode("utf-8")
181
- return jsonify({
182
- "mode": "voice",
183
- "transcript": user_text,
184
- "reply_text": ai_reply,
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)
 
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")
18
 
19
  # ==== URL ====
20
  GROQ_URL_CHAT = "https://api.groq.com/openai/v1/chat/completions"
 
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 (```). "
 
36
  )
37
 
38
  # =========================
39
+ # 🎀 STT
40
  # =========================
41
  def transcribe_audio(file_path: str) -> str:
42
  try:
 
72
  return b""
73
 
74
  # =========================
75
+ # 🌐 SerpAPI Search (now with images)
76
+ # =========================
77
+ def serpapi_search(query: str, location: str = None, num_results: int = 3):
78
+ url = "https://serpapi.com/search.json"
79
+ params = {
80
+ "q": query,
81
+ "location": location or "",
82
+ "engine": "google",
83
+ "api_key": SERPAPI_KEY,
84
+ "num": num_results
85
+ }
86
+ try:
87
+ r = requests.get(url, params=params, timeout=10)
88
+ r.raise_for_status()
89
+ data = r.json()
90
+
91
+ results = []
92
+ images = []
93
+
94
+ # text results
95
+ if "organic_results" in data:
96
+ for item in data["organic_results"][:num_results]:
97
+ results.append({
98
+ "title": item.get("title", ""),
99
+ "snippet": item.get("snippet", ""),
100
+ "link": item.get("link", "")
101
+ })
102
+
103
+ # image results
104
+ if "images_results" in data:
105
+ for img in data["images_results"][:3]:
106
+ images.append(img.get("thumbnail", ""))
107
+
108
+ return {"results": results, "images": images}
109
+
110
+ except Exception as e:
111
+ print(f"[SerpAPI Error] {e}")
112
+ return {"results": [], "images": []}
113
+
114
+ # =========================
115
+ # πŸ’¬ Chat Stream
116
  # =========================
117
  def stream_chat(prompt: str, history=None):
118
  wib = timezone(timedelta(hours=7))
119
  now = datetime.now(wib)
120
  formatted_time = now.strftime("%A, %d %B %Y β€” %H:%M:%S WIB")
121
 
122
+ sys_prompt = SYSTEM_PROMPT + f"\nCurrent date and time: {formatted_time}."
123
 
124
+ messages = [{"role": "system", "content": sys_prompt}]
125
+ if history: messages += history
 
126
  messages.append({"role": "user", "content": prompt})
127
 
128
  payload = {
 
138
  try:
139
  with requests.post(GROQ_URL_CHAT, headers=headers, json=payload, stream=True) as r:
140
  for line in r.iter_lines():
141
+ if not line: continue
 
142
  line = line.decode("utf-8")
143
  if line.startswith("data: "):
144
  data = line[6:]
145
+ if data == "[DONE]": break
 
146
  try:
147
+ delta = json.loads(data)["choices"][0]["delta"].get("content", "")
148
+ if delta: yield delta
149
+ except: continue
 
 
 
150
  except Exception as e:
151
  print(f"[Stream Error] {e}")
152
 
153
  # =========================
154
+ # 🧠 /chat endpoint
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  # =========================
156
  @app.route("/chat", methods=["POST"])
157
  def chat():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  data = request.get_json(force=True)
159
  prompt = data.get("prompt", "").strip()
160
  history = data.get("history", [])
161
+ if not prompt: return jsonify({"error": "No input text provided"}), 400
162
+
163
+ keywords = ["hotel", "mall", "resort", "tempat wisata", "villa"]
164
+
165
+ # add search results if needed
166
+ if any(k in prompt.lower() for k in keywords):
167
+ serp = serpapi_search(prompt)
168
+ text = "\n".join([f"{r['title']} β€” {r['snippet']} β€” {r['link']}" for r in serp["results"]])
169
+ imgs = "\n".join(serp["images"])
170
+
171
+ combined = (
172
+ prompt
173
+ + "\n\nGoogle Results:\n"
174
+ + text
175
+ + "\n\nImages:\n"
176
+ + imgs
177
+ + "\n\nExplain & recommend."
178
+ )
179
  else:
180
+ combined = prompt
181
 
182
  def generate():
183
+ for chunk in stream_chat(combined, history):
184
  yield chunk
185
 
186
  return Response(generate(), mimetype="text/plain")
187
 
188
  # =========================
189
+ # πŸš€ Run
190
  # =========================
191
  if __name__ == "__main__":
192
+ print("πŸš€ Vibow AI Chat Server started")
193
  app.run(host="0.0.0.0", port=7860, debug=True, threaded=True)