Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -79,9 +79,6 @@ def text_to_speech(text: str) -> bytes:
|
|
| 79 |
print(f"[TTS] β Exception: {e}")
|
| 80 |
return b""
|
| 81 |
|
| 82 |
-
# =========================
|
| 83 |
-
# π SerpAPI with Base64 Image Conversion
|
| 84 |
-
# =========================
|
| 85 |
def serpapi_search(query: str, location=None, num_results=3):
|
| 86 |
print(f"\n[SEARCH] π Starting search for: '{query}'")
|
| 87 |
|
|
@@ -110,34 +107,20 @@ def serpapi_search(query: str, location=None, num_results=3):
|
|
| 110 |
"hl": lang
|
| 111 |
}
|
| 112 |
|
| 113 |
-
results = []
|
| 114 |
-
images = []
|
| 115 |
-
|
| 116 |
-
# π§© Helper: convert image URL to base64 safely
|
| 117 |
-
def url_to_base64(img_url):
|
| 118 |
-
try:
|
| 119 |
-
r = requests.get(img_url, timeout=6)
|
| 120 |
-
if r.status_code == 200 and r.content:
|
| 121 |
-
mime = r.headers.get("Content-Type", "image/jpeg")
|
| 122 |
-
encoded = base64.b64encode(r.content).decode()
|
| 123 |
-
return f"data:{mime};base64,{encoded}"
|
| 124 |
-
except Exception as e:
|
| 125 |
-
print(f"[IMG] β οΈ Failed to convert {img_url}: {e}")
|
| 126 |
-
return None
|
| 127 |
-
|
| 128 |
try:
|
| 129 |
# --- TEXT SEARCH ---
|
| 130 |
r = requests.get(url, params=params, timeout=10)
|
| 131 |
r.raise_for_status()
|
| 132 |
data = r.json()
|
| 133 |
|
|
|
|
|
|
|
| 134 |
if "organic_results" in data:
|
| 135 |
-
for item in data["organic_results"][:num_results]:
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
})
|
| 141 |
|
| 142 |
# --- IMAGE SEARCH ---
|
| 143 |
img_params = {
|
|
@@ -156,23 +139,14 @@ def serpapi_search(query: str, location=None, num_results=3):
|
|
| 156 |
for img in img_data["images_results"][:3]:
|
| 157 |
img_url = img.get("original", img.get("thumbnail", ""))
|
| 158 |
if img_url:
|
| 159 |
-
|
| 160 |
-
if img_base64:
|
| 161 |
-
images.append(img_base64)
|
| 162 |
-
|
| 163 |
-
# Debug JSON
|
| 164 |
-
print("[DEBUG] πΉ SerpAPI JSON output (base64 images trimmed):")
|
| 165 |
-
print(json.dumps({
|
| 166 |
-
"results": results,
|
| 167 |
-
"images": [i[:100] + "..." for i in images]
|
| 168 |
-
}, indent=2))
|
| 169 |
|
| 170 |
-
|
|
|
|
| 171 |
|
| 172 |
except Exception as e:
|
| 173 |
print(f"[SEARCH] β Error: {e}")
|
| 174 |
-
return
|
| 175 |
-
|
| 176 |
# =========================
|
| 177 |
# π¬ Stream Chat
|
| 178 |
# =========================
|
|
@@ -277,10 +251,8 @@ def chat():
|
|
| 277 |
keywords = ["hotel", "mall", "resort", "villa", "tempat wisata", "restaurant", "cafe"]
|
| 278 |
has_keyword = any(k in prompt.lower() for k in keywords)
|
| 279 |
if has_keyword:
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
imgs = " ".join(serp["images"])
|
| 283 |
-
prompt = f"{prompt}\n\nGoogle Results:\n{text}\n\nImages: {imgs}\n\nExplain & recommend."
|
| 284 |
|
| 285 |
def generate():
|
| 286 |
for chunk in stream_chat(prompt, history):
|
|
|
|
| 79 |
print(f"[TTS] β Exception: {e}")
|
| 80 |
return b""
|
| 81 |
|
|
|
|
|
|
|
|
|
|
| 82 |
def serpapi_search(query: str, location=None, num_results=3):
|
| 83 |
print(f"\n[SEARCH] π Starting search for: '{query}'")
|
| 84 |
|
|
|
|
| 107 |
"hl": lang
|
| 108 |
}
|
| 109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
try:
|
| 111 |
# --- TEXT SEARCH ---
|
| 112 |
r = requests.get(url, params=params, timeout=10)
|
| 113 |
r.raise_for_status()
|
| 114 |
data = r.json()
|
| 115 |
|
| 116 |
+
text_block = f"π **Hasil Google untuk:** {query}\n\n"
|
| 117 |
+
|
| 118 |
if "organic_results" in data:
|
| 119 |
+
for i, item in enumerate(data["organic_results"][:num_results], 1):
|
| 120 |
+
title = item.get("title", "")
|
| 121 |
+
snippet = item.get("snippet", "")
|
| 122 |
+
link = item.get("link", "")
|
| 123 |
+
text_block += f"**{i}. {title}**\n{snippet}\nπ {link}\n\n"
|
|
|
|
| 124 |
|
| 125 |
# --- IMAGE SEARCH ---
|
| 126 |
img_params = {
|
|
|
|
| 139 |
for img in img_data["images_results"][:3]:
|
| 140 |
img_url = img.get("original", img.get("thumbnail", ""))
|
| 141 |
if img_url:
|
| 142 |
+
text_block += f"\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
|
| 144 |
+
print("[SEARCH] β
Search text assembled for AI stream.")
|
| 145 |
+
return text_block.strip()
|
| 146 |
|
| 147 |
except Exception as e:
|
| 148 |
print(f"[SEARCH] β Error: {e}")
|
| 149 |
+
return f"Tidak dapat menemukan hasil untuk: {query}"
|
|
|
|
| 150 |
# =========================
|
| 151 |
# π¬ Stream Chat
|
| 152 |
# =========================
|
|
|
|
| 251 |
keywords = ["hotel", "mall", "resort", "villa", "tempat wisata", "restaurant", "cafe"]
|
| 252 |
has_keyword = any(k in prompt.lower() for k in keywords)
|
| 253 |
if has_keyword:
|
| 254 |
+
serp_text = serpapi_search(prompt)
|
| 255 |
+
prompt = f"{prompt}\n\n{serp_text}\n\nπ§ Explain this search."
|
|
|
|
|
|
|
| 256 |
|
| 257 |
def generate():
|
| 258 |
for chunk in stream_chat(prompt, history):
|