File size: 16,568 Bytes
1f1f6a2
 
 
 
 
 
 
434dc20
1f1f6a2
 
 
434dc20
1f1f6a2
dc92774
 
1f1f6a2
434dc20
dc92774
434dc20
dc92774
434dc20
bdd397f
 
434dc20
bdd397f
434dc20
bdd397f
 
 
 
434dc20
bdd397f
 
 
434dc20
bdd397f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434dc20
bdd397f
 
434dc20
17082b6
434dc20
bdd397f
434dc20
bdd397f
 
434dc20
 
bdd397f
434dc20
dc92774
 
434dc20
dc92774
 
434dc20
81be010
434dc20
81be010
 
434dc20
3bf9017
7ab2f8a
434dc20
6ce4225
dcd9353
434dc20
6ce4225
 
dcd9353
434dc20
dcd9353
6ce4225
81be010
7ab2f8a
81be010
6ce4225
81be010
 
434dc20
 
 
65f1795
434dc20
6ce4225
dc92774
 
434dc20
6ce4225
dc92774
434dc20
 
17082b6
434dc20
dc92774
434dc20
bdd397f
434dc20
6ce4225
 
434dc20
6ce4225
 
 
434dc20
6ce4225
 
 
434dc20
6ce4225
 
 
 
434dc20
6ce4225
434dc20
 
6ce4225
434dc20
 
 
6ce4225
2ee6e2d
6ce4225
434dc20
6ce4225
2ee6e2d
 
434dc20
2ee6e2d
6ce4225
dc92774
434dc20
6ce4225
 
434dc20
 
 
6ce4225
434dc20
 
6ce4225
 
 
 
 
434dc20
6ce4225
dc92774
434dc20
81be010
7ab2f8a
 
6ce4225
434dc20
 
 
 
2ee6e2d
434dc20
 
1f1f6a2
434dc20
dc92774
1f1f6a2
434dc20
1f1f6a2
 
dc92774
bdd397f
dc92774
81be010
434dc20
 
81be010
434dc20
 
81be010
434dc20
81be010
434dc20
81be010
434dc20
bdd397f
 
 
434dc20
 
bdd397f
434dc20
81be010
434dc20
81be010
434dc20
 
dc92774
434dc20
1f1f6a2
 
 
 
 
434dc20
dc92774
434dc20
dc92774
 
434dc20
1f1f6a2
 
434dc20
1f1f6a2
 
 
 
 
 
 
 
 
 
434dc20
1f1f6a2
 
 
 
 
 
 
 
434dc20
1f1f6a2
434dc20
1f1f6a2
434dc20
1f1f6a2
bdd397f
434dc20
bdd397f
 
1f1f6a2
434dc20
bdd397f
1f1f6a2
434dc20
1f1f6a2
 
 
 
434dc20
1f1f6a2
 
 
434dc20
1f1f6a2
 
 
 
434dc20
1f1f6a2
 
 
 
 
434dc20
1f1f6a2
 
 
 
 
434dc20
1f1f6a2
 
 
434dc20
1f1f6a2
434dc20
1f1f6a2
 
434dc20
1f1f6a2
434dc20
1f1f6a2
 
434dc20
 
1f1f6a2
 
 
434dc20
1f1f6a2
434dc20
dc92774
434dc20
1f1f6a2
 
 
493b65b
1f1f6a2
 
434dc20
dc92774
81be010
 
434dc20
 
81be010
 
 
434dc20
81be010
434dc20
81be010
434dc20
81be010
434dc20
81be010
434dc20
dc92774
434dc20
1f1f6a2
 
434dc20
 
1f1f6a2
 
 
434dc20
1f1f6a2
434dc20
1f1f6a2
434dc20
1f1f6a2
434dc20
1f1f6a2
 
434dc20
 
 
1f1f6a2
 
 
dc92774
434dc20
dc92774
1f1f6a2
434dc20
1f1f6a2
 
dc92774
1f1f6a2
 
 
 
 
 
 
434dc20
1f1f6a2
 
dc92774
1f1f6a2
 
 
 
 
 
 
 
 
434dc20
1f1f6a2
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
import gradio as gr
import os
import requests
import json
import time
from dotenv import load_dotenv

# Load .env file (if it exists)
load_dotenv()

def create_deepseek_interface():
    # Get API keys from environment variables
    api_key = os.getenv("FW_API_KEY")
    serphouse_api_key = os.getenv("SERPHOUSE_API_KEY")
    
    if not api_key:
        print("Warning: FW_API_KEY environment variable is not set.")
    if not serphouse_api_key:
        print("Warning: SERPHOUSE_API_KEY environment variable is not set.")
    
    # Keyword extraction function (LLM-based)
    def extract_keywords_with_llm(query):
        if not api_key:
            return "FW_API_KEY not set for LLM keyword extraction.", query
        
        # Extract keywords using LLM (DeepSeek model)
        url = "https://api.fireworks.ai/inference/v1/chat/completions"
        payload = {
            "model": "accounts/fireworks/models/deepseek-v3-0324",
            "max_tokens": 200,
            "temperature": 0.1,  # Low temperature for consistent results
            "messages": [
                {
                    "role": "system",
                    "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'"
                },
                {
                    "role": "user",
                    "content": query
                }
            ]
        }
        headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        }
        
        try:
            response = requests.post(url, headers=headers, json=payload)
            response.raise_for_status()
            result = response.json()
            
            # Extract keywords from response
            keywords = result["choices"][0]["message"]["content"].strip()
            
            # Use original query if keywords are too long or improperly formatted
            if len(keywords) > 100:
                return f"Extracted keywords: {keywords}", query
                
            return f"Extracted keywords: {keywords}", keywords
            
        except Exception as e:
            print(f"Error during keyword extraction: {str(e)}")
            return f"Error during keyword extraction: {str(e)}", query
    
    # Search function using SerpHouse API
    def search_with_serphouse(query):
        if not serphouse_api_key:
            return "SERPHOUSE_API_KEY is not set."
        
        try:
            # Extract keywords
            extraction_result, search_query = extract_keywords_with_llm(query)
            print(f"Original query: {query}")
            print(extraction_result)
            
            # Basic GET method seems best after analyzing documentation
            url = "https://api.serphouse.com/serp/live"
            
            # Check if query is in Korean
            is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
            
            # Simplified parameters
            params = {
                "q": search_query,
                "domain": "google.com",
                "serp_type": "web",  # Changed to basic web search
                "device": "desktop",
                "lang": "ko" if is_korean else "en"
            }
            
            headers = {
                "Authorization": f"Bearer {serphouse_api_key}"
            }
            
            print(f"Calling SerpHouse API with basic GET method...")
            print(f"Search term: {search_query}")
            print(f"Request URL: {url} - Parameters: {params}")
            
            # Execute GET request
            response = requests.get(url, headers=headers, params=params)
            response.raise_for_status()
            
            print(f"SerpHouse API response status code: {response.status_code}")
            search_results = response.json()
            
            # Check response structure
            print(f"Response structure: {list(search_results.keys()) if isinstance(search_results, dict) else 'Not a dictionary'}")
            
            # Parse and format search results (in Markdown)
            formatted_results = []
            formatted_results.append(f"## Search term: {search_query}\n\n")
            
            # Handle various possible response structures
            organic_results = None
            
            # Possible response structure 1
            if "results" in search_results and "organic" in search_results["results"]:
                organic_results = search_results["results"]["organic"]
                
            # Possible response structure 2
            elif "organic" in search_results:
                organic_results = search_results["organic"]
                
            # Possible response structure 3 (nested results)
            elif "results" in search_results and "results" in search_results["results"]:
                if "organic" in search_results["results"]["results"]:
                    organic_results = search_results["results"]["results"]["organic"]
            
            # Process organic results if available
            if organic_results and len(organic_results) > 0:
                # Output response structure
                print(f"First organic result structure: {organic_results[0].keys() if len(organic_results) > 0 else 'empty'}")
                
                for i, result in enumerate(organic_results[:5], 1):  # Show only top 5 results
                    title = result.get("title", "No title")
                    snippet = result.get("snippet", "No content")
                    link = result.get("link", "#")
                    displayed_link = result.get("displayed_link", link)
                    
                    # Format in Markdown (including number and link)
                    formatted_results.append(
                        f"### {i}. [{title}]({link})\n\n"
                        f"{snippet}\n\n"
                        f"**Source**: [{displayed_link}]({link})\n\n"
                        f"---\n\n"
                    )
                
                print(f"Found {len(organic_results)} search results")
                return "".join(formatted_results)
            
            # Handle case with no results or unexpected structure
            print("No search results or unexpected response structure")
            print(f"Detailed response structure: {search_results.keys() if hasattr(search_results, 'keys') else 'Unclear structure'}")
            
            # Find error messages in response
            error_msg = "No search results found or response format is different than expected"
            if "error" in search_results:
                error_msg = search_results["error"]
            elif "message" in search_results:
                error_msg = search_results["message"]
                
            return f"## Results for '{search_query}'\n\n{error_msg}"
            
        except Exception as e:
            error_msg = f"Error during search: {str(e)}"
            print(error_msg)
            import traceback
            print(traceback.format_exc())
            
            # Add API request details for debugging (in Markdown)
            return f"## Error Occurred\n\n" + \
                   f"An error occurred during search: **{str(e)}**\n\n" + \
                   f"### API Request Details:\n" + \
                   f"- **URL**: {url}\n" + \
                   f"- **Search Term**: {search_query}\n" + \
                   f"- **Parameters**: {params}\n"
    
    # Function to call DeepSeek API with streaming
    def query_deepseek_streaming(message, history, use_deep_research):
        if not api_key:
            yield history, "Environment variable FW_API_KEY is not set. Please check the environment variables on the server."
            return
        
        search_context = ""
        search_info = ""
        if use_deep_research:
            try:
                # Start search (first message)
                yield history + [(message, "๐Ÿ” Extracting optimal keywords and searching the web...")], ""
                
                # Execute search - add logs for debugging
                print(f"Deep Research activated: Starting search for '{message}'")
                search_results = search_with_serphouse(message)
                print(f"Search results received: {search_results[:100]}...")  # Output first part of results
                
                if not search_results.startswith("Error during search") and not search_results.startswith("SERPHOUSE_API_KEY"):
                    search_context = f"""
Here are recent search results related to the user's question. Use this information to provide an accurate response with the latest information:

{search_results}

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.
When citing search results, mention the source, and ensure your answer reflects the latest information.
"""
                    search_info = f"๐Ÿ” Deep Research feature activated: Generating response based on relevant web search results..."
                else:
                    print(f"Search failed or no results: {search_results}")
            except Exception as e:
                print(f"Exception occurred during Deep Research: {str(e)}")
                search_info = f"๐Ÿ” Deep Research feature error: {str(e)}"
        
        # Prepare conversation history for API request
        messages = []
        for user, assistant in history:
            messages.append({"role": "user", "content": user})
            messages.append({"role": "assistant", "content": assistant})
        
        # Add system message with search context if available
        if search_context:
            # DeepSeek model supports system messages
            messages.insert(0, {"role": "system", "content": search_context})
        
        # Add new user message
        messages.append({"role": "user", "content": message})
        
        # Prepare API request
        url = "https://api.fireworks.ai/inference/v1/chat/completions"
        payload = {
            "model": "accounts/fireworks/models/deepseek-v3-0324",
            "max_tokens": 20480,
            "top_p": 1,
            "top_k": 40,
            "presence_penalty": 0,
            "frequency_penalty": 0,
            "temperature": 0.6,
            "messages": messages,
            "stream": True  # Enable streaming
        }
        headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        }
        
        try:
            # Request streaming response
            response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
            response.raise_for_status()  # Raise exception for HTTP errors
            
            # Add message and start with initial response
            new_history = history.copy()
            
            # Include search_info in starting message if available
            start_msg = search_info if search_info else ""
            new_history.append((message, start_msg))
            
            # Full response text
            full_response = start_msg
            
            # Process streaming response
            for line in response.iter_lines():
                if line:
                    line_text = line.decode('utf-8')
                    
                    # Remove 'data: ' prefix
                    if line_text.startswith("data: "):
                        line_text = line_text[6:]
                    
                    # Check for stream end message
                    if line_text == "[DONE]":
                        break
                    
                    try:
                        # Parse JSON
                        chunk = json.loads(line_text)
                        chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
                        
                        if chunk_content:
                            full_response += chunk_content
                            # Update chat history
                            new_history[-1] = (message, full_response)
                            yield new_history, ""
                    except json.JSONDecodeError:
                        continue
            
            # Return final response
            yield new_history, ""
            
        except requests.exceptions.RequestException as e:
            error_msg = f"API error: {str(e)}"
            if hasattr(e, 'response') and e.response and e.response.status_code == 401:
                error_msg = "Authentication failed. Please check your FW_API_KEY environment variable."
            yield history, error_msg
    
    # Create Gradio interface
    with gr.Blocks(theme="soft", fill_height=True) as demo:
        # Header section
        gr.Markdown(
            """
            # ๐Ÿค– DeepSeek V3-0324 + Research 
            ### DeepSeek V3-0324 Latest Model + Real-time 'Deep Research' Agentic AI System @ https://discord.gg/openfreeai
            """
        )
        
        # Main layout
        with gr.Row():
            # Main content area
            with gr.Column():
                # Chat interface
                chatbot = gr.Chatbot(
                    height=500,
                    show_label=False,
                    container=True
                )
                
                # Add Deep Research toggle and status display
                with gr.Row():
                    with gr.Column(scale=3):
                        use_deep_research = gr.Checkbox(
                            label="Enable Deep Research",
                            info="Utilize optimal keyword extraction and web search for latest information",
                            value=False
                        )
                    with gr.Column(scale=1):
                        api_status = gr.Markdown("API Status: Ready")
                
                # Check and display API key status
                if not serphouse_api_key:
                    api_status.value = "โš ๏ธ SERPHOUSE_API_KEY is not set"
                if not api_key:
                    api_status.value = "โš ๏ธ FW_API_KEY is not set"
                if api_key and serphouse_api_key:
                    api_status.value = "โœ… API keys configured"
                
                # Input area
                with gr.Row():
                    msg = gr.Textbox(
                        label="Message",
                        placeholder="Enter your prompt here...",
                        show_label=False,
                        scale=9
                    )
                    submit = gr.Button("Send", variant="primary", scale=1)
                
                # Clear conversation button
                with gr.Row():
                    clear = gr.ClearButton([msg, chatbot], value="๐Ÿงน Clear Conversation")
                    
                # Example queries
                gr.Examples(
                    examples=[
                        "Explain the difference between Transformers and RNNs in deep learning.",
                        "Write a Python function to find prime numbers within a specific range.",
                        "Summarize the key concepts of reinforcement learning."
                    ],
                    inputs=msg
                )
                
                # Error message display
                error_box = gr.Markdown("")
        
        # Connect buttons to functions
        submit.click(
            query_deepseek_streaming,
            inputs=[msg, chatbot, use_deep_research],
            outputs=[chatbot, error_box]
        ).then(
            lambda: "",
            None,
            [msg]
        )
        
        # Allow Enter key submission
        msg.submit(
            query_deepseek_streaming,
            inputs=[msg, chatbot, use_deep_research],
            outputs=[chatbot, error_box]
        ).then(
            lambda: "",
            None,
            [msg]
        )
        
    return demo

# Run interface
if __name__ == "__main__":
    demo = create_deepseek_interface()
    demo.launch(debug=True)