Update app.py
Browse files
app.py
CHANGED
@@ -5,34 +5,34 @@ import json
|
|
5 |
import time
|
6 |
from dotenv import load_dotenv
|
7 |
|
8 |
-
# .env
|
9 |
load_dotenv()
|
10 |
|
11 |
def create_deepseek_interface():
|
12 |
-
#
|
13 |
api_key = os.getenv("FW_API_KEY")
|
14 |
serphouse_api_key = os.getenv("SERPHOUSE_API_KEY")
|
15 |
|
16 |
if not api_key:
|
17 |
-
print("
|
18 |
if not serphouse_api_key:
|
19 |
-
print("
|
20 |
|
21 |
-
#
|
22 |
def extract_keywords_with_llm(query):
|
23 |
if not api_key:
|
24 |
-
return "
|
25 |
|
26 |
-
#
|
27 |
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
28 |
payload = {
|
29 |
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
30 |
"max_tokens": 200,
|
31 |
-
"temperature": 0.1, #
|
32 |
"messages": [
|
33 |
{
|
34 |
"role": "system",
|
35 |
-
"content": "
|
36 |
},
|
37 |
{
|
38 |
"role": "user",
|
@@ -51,41 +51,41 @@ def create_deepseek_interface():
|
|
51 |
response.raise_for_status()
|
52 |
result = response.json()
|
53 |
|
54 |
-
#
|
55 |
keywords = result["choices"][0]["message"]["content"].strip()
|
56 |
|
57 |
-
#
|
58 |
if len(keywords) > 100:
|
59 |
-
return f"
|
60 |
|
61 |
-
return f"
|
62 |
|
63 |
except Exception as e:
|
64 |
-
print(f"
|
65 |
-
return f"
|
66 |
|
67 |
-
#
|
68 |
def search_with_serphouse(query):
|
69 |
if not serphouse_api_key:
|
70 |
-
return "SERPHOUSE_API_KEY
|
71 |
|
72 |
try:
|
73 |
-
#
|
74 |
extraction_result, search_query = extract_keywords_with_llm(query)
|
75 |
-
print(f"
|
76 |
print(extraction_result)
|
77 |
|
78 |
-
#
|
79 |
url = "https://api.serphouse.com/serp/live"
|
80 |
|
81 |
-
#
|
82 |
is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
|
83 |
|
84 |
-
#
|
85 |
params = {
|
86 |
"q": search_query,
|
87 |
"domain": "google.com",
|
88 |
-
"serp_type": "web", #
|
89 |
"device": "desktop",
|
90 |
"lang": "ko" if is_korean else "en"
|
91 |
}
|
@@ -94,138 +94,138 @@ def create_deepseek_interface():
|
|
94 |
"Authorization": f"Bearer {serphouse_api_key}"
|
95 |
}
|
96 |
|
97 |
-
print(f"SerpHouse API
|
98 |
-
print(f"
|
99 |
-
print(f"
|
100 |
|
101 |
-
# GET
|
102 |
response = requests.get(url, headers=headers, params=params)
|
103 |
response.raise_for_status()
|
104 |
|
105 |
-
print(f"SerpHouse API
|
106 |
search_results = response.json()
|
107 |
|
108 |
-
#
|
109 |
-
print(f"
|
110 |
|
111 |
-
#
|
112 |
formatted_results = []
|
113 |
-
formatted_results.append(f"##
|
114 |
|
115 |
-
#
|
116 |
organic_results = None
|
117 |
|
118 |
-
#
|
119 |
if "results" in search_results and "organic" in search_results["results"]:
|
120 |
organic_results = search_results["results"]["organic"]
|
121 |
|
122 |
-
#
|
123 |
elif "organic" in search_results:
|
124 |
organic_results = search_results["organic"]
|
125 |
|
126 |
-
#
|
127 |
elif "results" in search_results and "results" in search_results["results"]:
|
128 |
if "organic" in search_results["results"]["results"]:
|
129 |
organic_results = search_results["results"]["results"]["organic"]
|
130 |
|
131 |
-
#
|
132 |
if organic_results and len(organic_results) > 0:
|
133 |
-
#
|
134 |
-
print(f"
|
135 |
|
136 |
-
for i, result in enumerate(organic_results[:5], 1): #
|
137 |
-
title = result.get("title", "
|
138 |
-
snippet = result.get("snippet", "
|
139 |
link = result.get("link", "#")
|
140 |
displayed_link = result.get("displayed_link", link)
|
141 |
|
142 |
-
#
|
143 |
formatted_results.append(
|
144 |
f"### {i}. [{title}]({link})\n\n"
|
145 |
f"{snippet}\n\n"
|
146 |
-
f"
|
147 |
f"---\n\n"
|
148 |
)
|
149 |
|
150 |
-
print(f"
|
151 |
return "".join(formatted_results)
|
152 |
|
153 |
-
#
|
154 |
-
print("
|
155 |
-
print(f"
|
156 |
|
157 |
-
#
|
158 |
-
error_msg = "
|
159 |
if "error" in search_results:
|
160 |
error_msg = search_results["error"]
|
161 |
elif "message" in search_results:
|
162 |
error_msg = search_results["message"]
|
163 |
|
164 |
-
return f"##
|
165 |
|
166 |
except Exception as e:
|
167 |
-
error_msg = f"
|
168 |
print(error_msg)
|
169 |
import traceback
|
170 |
print(traceback.format_exc())
|
171 |
|
172 |
-
#
|
173 |
-
return f"##
|
174 |
-
f"
|
175 |
-
f"### API
|
176 |
f"- **URL**: {url}\n" + \
|
177 |
-
f"-
|
178 |
-
f"-
|
179 |
|
180 |
-
#
|
181 |
def query_deepseek_streaming(message, history, use_deep_research):
|
182 |
if not api_key:
|
183 |
-
yield history, "
|
184 |
return
|
185 |
|
186 |
search_context = ""
|
187 |
search_info = ""
|
188 |
if use_deep_research:
|
189 |
try:
|
190 |
-
#
|
191 |
-
yield history + [(message, "🔍
|
192 |
|
193 |
-
#
|
194 |
-
print(f"Deep Research
|
195 |
search_results = search_with_serphouse(message)
|
196 |
-
print(f"
|
197 |
|
198 |
-
if not search_results.startswith("
|
199 |
search_context = f"""
|
200 |
-
|
201 |
|
202 |
{search_results}
|
203 |
|
204 |
-
|
205 |
-
|
206 |
"""
|
207 |
-
search_info = f"🔍 Deep Research
|
208 |
else:
|
209 |
-
print(f"
|
210 |
except Exception as e:
|
211 |
-
print(f"
|
212 |
-
search_info = f"🔍 Deep Research
|
213 |
|
214 |
-
#
|
215 |
messages = []
|
216 |
for user, assistant in history:
|
217 |
messages.append({"role": "user", "content": user})
|
218 |
messages.append({"role": "assistant", "content": assistant})
|
219 |
|
220 |
-
#
|
221 |
if search_context:
|
222 |
-
# DeepSeek
|
223 |
messages.insert(0, {"role": "system", "content": search_context})
|
224 |
|
225 |
-
#
|
226 |
messages.append({"role": "user", "content": message})
|
227 |
|
228 |
-
# API
|
229 |
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
230 |
payload = {
|
231 |
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
@@ -236,7 +236,7 @@ def create_deepseek_interface():
|
|
236 |
"frequency_penalty": 0,
|
237 |
"temperature": 0.6,
|
238 |
"messages": messages,
|
239 |
-
"stream": True #
|
240 |
}
|
241 |
headers = {
|
242 |
"Accept": "application/json",
|
@@ -245,123 +245,123 @@ def create_deepseek_interface():
|
|
245 |
}
|
246 |
|
247 |
try:
|
248 |
-
#
|
249 |
response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
|
250 |
-
response.raise_for_status() #
|
251 |
|
252 |
-
#
|
253 |
new_history = history.copy()
|
254 |
|
255 |
-
# search_info
|
256 |
start_msg = search_info if search_info else ""
|
257 |
new_history.append((message, start_msg))
|
258 |
|
259 |
-
#
|
260 |
full_response = start_msg
|
261 |
|
262 |
-
#
|
263 |
for line in response.iter_lines():
|
264 |
if line:
|
265 |
line_text = line.decode('utf-8')
|
266 |
|
267 |
-
# 'data: '
|
268 |
if line_text.startswith("data: "):
|
269 |
line_text = line_text[6:]
|
270 |
|
271 |
-
#
|
272 |
if line_text == "[DONE]":
|
273 |
break
|
274 |
|
275 |
try:
|
276 |
-
# JSON
|
277 |
chunk = json.loads(line_text)
|
278 |
chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
|
279 |
|
280 |
if chunk_content:
|
281 |
full_response += chunk_content
|
282 |
-
#
|
283 |
new_history[-1] = (message, full_response)
|
284 |
yield new_history, ""
|
285 |
except json.JSONDecodeError:
|
286 |
continue
|
287 |
|
288 |
-
#
|
289 |
yield new_history, ""
|
290 |
|
291 |
except requests.exceptions.RequestException as e:
|
292 |
-
error_msg = f"API
|
293 |
if hasattr(e, 'response') and e.response and e.response.status_code == 401:
|
294 |
-
error_msg = "
|
295 |
yield history, error_msg
|
296 |
|
297 |
-
# Gradio
|
298 |
with gr.Blocks(theme="soft", fill_height=True) as demo:
|
299 |
-
#
|
300 |
gr.Markdown(
|
301 |
"""
|
302 |
-
# 🤖 DeepSeek V3-0324 +
|
303 |
-
### DeepSeek V3-0324
|
304 |
"""
|
305 |
)
|
306 |
|
307 |
-
#
|
308 |
with gr.Row():
|
309 |
-
#
|
310 |
with gr.Column():
|
311 |
-
#
|
312 |
chatbot = gr.Chatbot(
|
313 |
height=500,
|
314 |
show_label=False,
|
315 |
container=True
|
316 |
)
|
317 |
|
318 |
-
# Deep Research
|
319 |
with gr.Row():
|
320 |
with gr.Column(scale=3):
|
321 |
use_deep_research = gr.Checkbox(
|
322 |
-
label="Deep Research
|
323 |
-
info="
|
324 |
value=False
|
325 |
)
|
326 |
with gr.Column(scale=1):
|
327 |
-
api_status = gr.Markdown("API
|
328 |
|
329 |
-
#
|
330 |
if not serphouse_api_key:
|
331 |
-
api_status.value = "⚠️ SERPHOUSE_API_KEY
|
332 |
if not api_key:
|
333 |
-
api_status.value = "⚠️ FW_API_KEY
|
334 |
if api_key and serphouse_api_key:
|
335 |
-
api_status.value = "✅ API
|
336 |
|
337 |
-
#
|
338 |
with gr.Row():
|
339 |
msg = gr.Textbox(
|
340 |
-
label="
|
341 |
-
placeholder="
|
342 |
show_label=False,
|
343 |
scale=9
|
344 |
)
|
345 |
-
submit = gr.Button("
|
346 |
|
347 |
-
#
|
348 |
with gr.Row():
|
349 |
-
clear = gr.ClearButton([msg, chatbot], value="🧹
|
350 |
|
351 |
-
#
|
352 |
gr.Examples(
|
353 |
examples=[
|
354 |
-
"
|
355 |
-
"
|
356 |
-
"
|
357 |
],
|
358 |
inputs=msg
|
359 |
)
|
360 |
|
361 |
-
#
|
362 |
error_box = gr.Markdown("")
|
363 |
|
364 |
-
#
|
365 |
submit.click(
|
366 |
query_deepseek_streaming,
|
367 |
inputs=[msg, chatbot, use_deep_research],
|
@@ -372,7 +372,7 @@ def create_deepseek_interface():
|
|
372 |
[msg]
|
373 |
)
|
374 |
|
375 |
-
# Enter
|
376 |
msg.submit(
|
377 |
query_deepseek_streaming,
|
378 |
inputs=[msg, chatbot, use_deep_research],
|
@@ -385,7 +385,7 @@ def create_deepseek_interface():
|
|
385 |
|
386 |
return demo
|
387 |
|
388 |
-
#
|
389 |
if __name__ == "__main__":
|
390 |
demo = create_deepseek_interface()
|
391 |
demo.launch(debug=True)
|
|
|
5 |
import time
|
6 |
from dotenv import load_dotenv
|
7 |
|
8 |
+
# Load .env file (if it exists)
|
9 |
load_dotenv()
|
10 |
|
11 |
def create_deepseek_interface():
|
12 |
+
# Get API keys from environment variables
|
13 |
api_key = os.getenv("FW_API_KEY")
|
14 |
serphouse_api_key = os.getenv("SERPHOUSE_API_KEY")
|
15 |
|
16 |
if not api_key:
|
17 |
+
print("Warning: FW_API_KEY environment variable is not set.")
|
18 |
if not serphouse_api_key:
|
19 |
+
print("Warning: SERPHOUSE_API_KEY environment variable is not set.")
|
20 |
|
21 |
+
# Keyword extraction function (LLM-based)
|
22 |
def extract_keywords_with_llm(query):
|
23 |
if not api_key:
|
24 |
+
return "FW_API_KEY not set for LLM keyword extraction.", query
|
25 |
|
26 |
+
# Extract keywords using LLM (DeepSeek model)
|
27 |
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
28 |
payload = {
|
29 |
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
30 |
"max_tokens": 200,
|
31 |
+
"temperature": 0.1, # Low temperature for consistent results
|
32 |
"messages": [
|
33 |
{
|
34 |
"role": "system",
|
35 |
+
"content": "Extract key search terms from the user's question that would be effective for web searches. Provide these as a search query with words separated by spaces only, without commas. For example: 'Prime Minister Han Duck-soo impeachment results'"
|
36 |
},
|
37 |
{
|
38 |
"role": "user",
|
|
|
51 |
response.raise_for_status()
|
52 |
result = response.json()
|
53 |
|
54 |
+
# Extract keywords from response
|
55 |
keywords = result["choices"][0]["message"]["content"].strip()
|
56 |
|
57 |
+
# Use original query if keywords are too long or improperly formatted
|
58 |
if len(keywords) > 100:
|
59 |
+
return f"Extracted keywords: {keywords}", query
|
60 |
|
61 |
+
return f"Extracted keywords: {keywords}", keywords
|
62 |
|
63 |
except Exception as e:
|
64 |
+
print(f"Error during keyword extraction: {str(e)}")
|
65 |
+
return f"Error during keyword extraction: {str(e)}", query
|
66 |
|
67 |
+
# Search function using SerpHouse API
|
68 |
def search_with_serphouse(query):
|
69 |
if not serphouse_api_key:
|
70 |
+
return "SERPHOUSE_API_KEY is not set."
|
71 |
|
72 |
try:
|
73 |
+
# Extract keywords
|
74 |
extraction_result, search_query = extract_keywords_with_llm(query)
|
75 |
+
print(f"Original query: {query}")
|
76 |
print(extraction_result)
|
77 |
|
78 |
+
# Basic GET method seems best after analyzing documentation
|
79 |
url = "https://api.serphouse.com/serp/live"
|
80 |
|
81 |
+
# Check if query is in Korean
|
82 |
is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
|
83 |
|
84 |
+
# Simplified parameters
|
85 |
params = {
|
86 |
"q": search_query,
|
87 |
"domain": "google.com",
|
88 |
+
"serp_type": "web", # Changed to basic web search
|
89 |
"device": "desktop",
|
90 |
"lang": "ko" if is_korean else "en"
|
91 |
}
|
|
|
94 |
"Authorization": f"Bearer {serphouse_api_key}"
|
95 |
}
|
96 |
|
97 |
+
print(f"Calling SerpHouse API with basic GET method...")
|
98 |
+
print(f"Search term: {search_query}")
|
99 |
+
print(f"Request URL: {url} - Parameters: {params}")
|
100 |
|
101 |
+
# Execute GET request
|
102 |
response = requests.get(url, headers=headers, params=params)
|
103 |
response.raise_for_status()
|
104 |
|
105 |
+
print(f"SerpHouse API response status code: {response.status_code}")
|
106 |
search_results = response.json()
|
107 |
|
108 |
+
# Check response structure
|
109 |
+
print(f"Response structure: {list(search_results.keys()) if isinstance(search_results, dict) else 'Not a dictionary'}")
|
110 |
|
111 |
+
# Parse and format search results (in Markdown)
|
112 |
formatted_results = []
|
113 |
+
formatted_results.append(f"## Search term: {search_query}\n\n")
|
114 |
|
115 |
+
# Handle various possible response structures
|
116 |
organic_results = None
|
117 |
|
118 |
+
# Possible response structure 1
|
119 |
if "results" in search_results and "organic" in search_results["results"]:
|
120 |
organic_results = search_results["results"]["organic"]
|
121 |
|
122 |
+
# Possible response structure 2
|
123 |
elif "organic" in search_results:
|
124 |
organic_results = search_results["organic"]
|
125 |
|
126 |
+
# Possible response structure 3 (nested results)
|
127 |
elif "results" in search_results and "results" in search_results["results"]:
|
128 |
if "organic" in search_results["results"]["results"]:
|
129 |
organic_results = search_results["results"]["results"]["organic"]
|
130 |
|
131 |
+
# Process organic results if available
|
132 |
if organic_results and len(organic_results) > 0:
|
133 |
+
# Output response structure
|
134 |
+
print(f"First organic result structure: {organic_results[0].keys() if len(organic_results) > 0 else 'empty'}")
|
135 |
|
136 |
+
for i, result in enumerate(organic_results[:5], 1): # Show only top 5 results
|
137 |
+
title = result.get("title", "No title")
|
138 |
+
snippet = result.get("snippet", "No content")
|
139 |
link = result.get("link", "#")
|
140 |
displayed_link = result.get("displayed_link", link)
|
141 |
|
142 |
+
# Format in Markdown (including number and link)
|
143 |
formatted_results.append(
|
144 |
f"### {i}. [{title}]({link})\n\n"
|
145 |
f"{snippet}\n\n"
|
146 |
+
f"**Source**: [{displayed_link}]({link})\n\n"
|
147 |
f"---\n\n"
|
148 |
)
|
149 |
|
150 |
+
print(f"Found {len(organic_results)} search results")
|
151 |
return "".join(formatted_results)
|
152 |
|
153 |
+
# Handle case with no results or unexpected structure
|
154 |
+
print("No search results or unexpected response structure")
|
155 |
+
print(f"Detailed response structure: {search_results.keys() if hasattr(search_results, 'keys') else 'Unclear structure'}")
|
156 |
|
157 |
+
# Find error messages in response
|
158 |
+
error_msg = "No search results found or response format is different than expected"
|
159 |
if "error" in search_results:
|
160 |
error_msg = search_results["error"]
|
161 |
elif "message" in search_results:
|
162 |
error_msg = search_results["message"]
|
163 |
|
164 |
+
return f"## Results for '{search_query}'\n\n{error_msg}"
|
165 |
|
166 |
except Exception as e:
|
167 |
+
error_msg = f"Error during search: {str(e)}"
|
168 |
print(error_msg)
|
169 |
import traceback
|
170 |
print(traceback.format_exc())
|
171 |
|
172 |
+
# Add API request details for debugging (in Markdown)
|
173 |
+
return f"## Error Occurred\n\n" + \
|
174 |
+
f"An error occurred during search: **{str(e)}**\n\n" + \
|
175 |
+
f"### API Request Details:\n" + \
|
176 |
f"- **URL**: {url}\n" + \
|
177 |
+
f"- **Search Term**: {search_query}\n" + \
|
178 |
+
f"- **Parameters**: {params}\n"
|
179 |
|
180 |
+
# Function to call DeepSeek API with streaming
|
181 |
def query_deepseek_streaming(message, history, use_deep_research):
|
182 |
if not api_key:
|
183 |
+
yield history, "Environment variable FW_API_KEY is not set. Please check the environment variables on the server."
|
184 |
return
|
185 |
|
186 |
search_context = ""
|
187 |
search_info = ""
|
188 |
if use_deep_research:
|
189 |
try:
|
190 |
+
# Start search (first message)
|
191 |
+
yield history + [(message, "🔍 Extracting optimal keywords and searching the web...")], ""
|
192 |
|
193 |
+
# Execute search - add logs for debugging
|
194 |
+
print(f"Deep Research activated: Starting search for '{message}'")
|
195 |
search_results = search_with_serphouse(message)
|
196 |
+
print(f"Search results received: {search_results[:100]}...") # Output first part of results
|
197 |
|
198 |
+
if not search_results.startswith("Error during search") and not search_results.startswith("SERPHOUSE_API_KEY"):
|
199 |
search_context = f"""
|
200 |
+
Here are recent search results related to the user's question. Use this information to provide an accurate response with the latest information:
|
201 |
|
202 |
{search_results}
|
203 |
|
204 |
+
Based on the above search results, answer the user's question. If you cannot find a clear answer in the search results, use your knowledge to provide the best answer.
|
205 |
+
When citing search results, mention the source, and ensure your answer reflects the latest information.
|
206 |
"""
|
207 |
+
search_info = f"🔍 Deep Research feature activated: Generating response based on relevant web search results..."
|
208 |
else:
|
209 |
+
print(f"Search failed or no results: {search_results}")
|
210 |
except Exception as e:
|
211 |
+
print(f"Exception occurred during Deep Research: {str(e)}")
|
212 |
+
search_info = f"🔍 Deep Research feature error: {str(e)}"
|
213 |
|
214 |
+
# Prepare conversation history for API request
|
215 |
messages = []
|
216 |
for user, assistant in history:
|
217 |
messages.append({"role": "user", "content": user})
|
218 |
messages.append({"role": "assistant", "content": assistant})
|
219 |
|
220 |
+
# Add system message with search context if available
|
221 |
if search_context:
|
222 |
+
# DeepSeek model supports system messages
|
223 |
messages.insert(0, {"role": "system", "content": search_context})
|
224 |
|
225 |
+
# Add new user message
|
226 |
messages.append({"role": "user", "content": message})
|
227 |
|
228 |
+
# Prepare API request
|
229 |
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
230 |
payload = {
|
231 |
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
|
|
236 |
"frequency_penalty": 0,
|
237 |
"temperature": 0.6,
|
238 |
"messages": messages,
|
239 |
+
"stream": True # Enable streaming
|
240 |
}
|
241 |
headers = {
|
242 |
"Accept": "application/json",
|
|
|
245 |
}
|
246 |
|
247 |
try:
|
248 |
+
# Request streaming response
|
249 |
response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
|
250 |
+
response.raise_for_status() # Raise exception for HTTP errors
|
251 |
|
252 |
+
# Add message and start with initial response
|
253 |
new_history = history.copy()
|
254 |
|
255 |
+
# Include search_info in starting message if available
|
256 |
start_msg = search_info if search_info else ""
|
257 |
new_history.append((message, start_msg))
|
258 |
|
259 |
+
# Full response text
|
260 |
full_response = start_msg
|
261 |
|
262 |
+
# Process streaming response
|
263 |
for line in response.iter_lines():
|
264 |
if line:
|
265 |
line_text = line.decode('utf-8')
|
266 |
|
267 |
+
# Remove 'data: ' prefix
|
268 |
if line_text.startswith("data: "):
|
269 |
line_text = line_text[6:]
|
270 |
|
271 |
+
# Check for stream end message
|
272 |
if line_text == "[DONE]":
|
273 |
break
|
274 |
|
275 |
try:
|
276 |
+
# Parse JSON
|
277 |
chunk = json.loads(line_text)
|
278 |
chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
|
279 |
|
280 |
if chunk_content:
|
281 |
full_response += chunk_content
|
282 |
+
# Update chat history
|
283 |
new_history[-1] = (message, full_response)
|
284 |
yield new_history, ""
|
285 |
except json.JSONDecodeError:
|
286 |
continue
|
287 |
|
288 |
+
# Return final response
|
289 |
yield new_history, ""
|
290 |
|
291 |
except requests.exceptions.RequestException as e:
|
292 |
+
error_msg = f"API error: {str(e)}"
|
293 |
if hasattr(e, 'response') and e.response and e.response.status_code == 401:
|
294 |
+
error_msg = "Authentication failed. Please check your FW_API_KEY environment variable."
|
295 |
yield history, error_msg
|
296 |
|
297 |
+
# Create Gradio interface
|
298 |
with gr.Blocks(theme="soft", fill_height=True) as demo:
|
299 |
+
# Header section
|
300 |
gr.Markdown(
|
301 |
"""
|
302 |
+
# 🤖 DeepSeek V3-0324 + Research
|
303 |
+
### DeepSeek V3-0324 Latest Model + Real-time 'Deep Research' Agentic AI System @ https://discord.gg/openfreeai
|
304 |
"""
|
305 |
)
|
306 |
|
307 |
+
# Main layout
|
308 |
with gr.Row():
|
309 |
+
# Main content area
|
310 |
with gr.Column():
|
311 |
+
# Chat interface
|
312 |
chatbot = gr.Chatbot(
|
313 |
height=500,
|
314 |
show_label=False,
|
315 |
container=True
|
316 |
)
|
317 |
|
318 |
+
# Add Deep Research toggle and status display
|
319 |
with gr.Row():
|
320 |
with gr.Column(scale=3):
|
321 |
use_deep_research = gr.Checkbox(
|
322 |
+
label="Enable Deep Research",
|
323 |
+
info="Utilize optimal keyword extraction and web search for latest information",
|
324 |
value=False
|
325 |
)
|
326 |
with gr.Column(scale=1):
|
327 |
+
api_status = gr.Markdown("API Status: Ready")
|
328 |
|
329 |
+
# Check and display API key status
|
330 |
if not serphouse_api_key:
|
331 |
+
api_status.value = "⚠️ SERPHOUSE_API_KEY is not set"
|
332 |
if not api_key:
|
333 |
+
api_status.value = "⚠️ FW_API_KEY is not set"
|
334 |
if api_key and serphouse_api_key:
|
335 |
+
api_status.value = "✅ API keys configured"
|
336 |
|
337 |
+
# Input area
|
338 |
with gr.Row():
|
339 |
msg = gr.Textbox(
|
340 |
+
label="Message",
|
341 |
+
placeholder="Enter your prompt here...",
|
342 |
show_label=False,
|
343 |
scale=9
|
344 |
)
|
345 |
+
submit = gr.Button("Send", variant="primary", scale=1)
|
346 |
|
347 |
+
# Clear conversation button
|
348 |
with gr.Row():
|
349 |
+
clear = gr.ClearButton([msg, chatbot], value="🧹 Clear Conversation")
|
350 |
|
351 |
+
# Example queries
|
352 |
gr.Examples(
|
353 |
examples=[
|
354 |
+
"Explain the difference between Transformers and RNNs in deep learning.",
|
355 |
+
"Write a Python function to find prime numbers within a specific range.",
|
356 |
+
"Summarize the key concepts of reinforcement learning."
|
357 |
],
|
358 |
inputs=msg
|
359 |
)
|
360 |
|
361 |
+
# Error message display
|
362 |
error_box = gr.Markdown("")
|
363 |
|
364 |
+
# Connect buttons to functions
|
365 |
submit.click(
|
366 |
query_deepseek_streaming,
|
367 |
inputs=[msg, chatbot, use_deep_research],
|
|
|
372 |
[msg]
|
373 |
)
|
374 |
|
375 |
+
# Allow Enter key submission
|
376 |
msg.submit(
|
377 |
query_deepseek_streaming,
|
378 |
inputs=[msg, chatbot, use_deep_research],
|
|
|
385 |
|
386 |
return demo
|
387 |
|
388 |
+
# Run interface
|
389 |
if __name__ == "__main__":
|
390 |
demo = create_deepseek_interface()
|
391 |
demo.launch(debug=True)
|