|
import gradio as gr |
|
import os |
|
import requests |
|
import json |
|
import time |
|
from dotenv import load_dotenv |
|
|
|
|
|
load_dotenv() |
|
|
|
def create_deepseek_interface(): |
|
|
|
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.") |
|
|
|
|
|
def extract_keywords_with_llm(query): |
|
if not api_key: |
|
return "FW_API_KEY not set for LLM keyword extraction.", query |
|
|
|
|
|
url = "https://api.fireworks.ai/inference/v1/chat/completions" |
|
payload = { |
|
"model": "accounts/fireworks/models/llama4-maverick-instruct-basic", |
|
"max_tokens": 200, |
|
"temperature": 0.1, |
|
"messages": [ |
|
{ |
|
"role": "system", |
|
"content": "You are a deep thinking AI, you may use extremely long chains of thought to deeply consider the problem and deliberate with yourself via systematic reasoning processes to help come to a correct solution prior to answering. You should enclose your thoughts and internal monologue inside tags, and then provide your solution or response to the problem. 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() |
|
|
|
|
|
keywords = result["choices"][0]["message"]["content"].strip() |
|
|
|
|
|
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 |
|
|
|
|
|
def search_with_serphouse(query): |
|
if not serphouse_api_key: |
|
return "SERPHOUSE_API_KEY is not set." |
|
|
|
try: |
|
|
|
extraction_result, search_query = extract_keywords_with_llm(query) |
|
print(f"Original query: {query}") |
|
print(extraction_result) |
|
|
|
|
|
url = "https://api.serphouse.com/serp/live" |
|
|
|
|
|
is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query) |
|
|
|
|
|
params = { |
|
"q": search_query, |
|
"domain": "google.com", |
|
"serp_type": "web", |
|
"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}") |
|
|
|
|
|
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() |
|
|
|
|
|
print(f"Response structure: {list(search_results.keys()) if isinstance(search_results, dict) else 'Not a dictionary'}") |
|
|
|
|
|
formatted_results = [] |
|
formatted_results.append(f"## Search term: {search_query}\n\n") |
|
|
|
|
|
organic_results = None |
|
|
|
|
|
if "results" in search_results and "organic" in search_results["results"]: |
|
organic_results = search_results["results"]["organic"] |
|
|
|
|
|
elif "organic" in search_results: |
|
organic_results = search_results["organic"] |
|
|
|
|
|
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"] |
|
|
|
|
|
if organic_results and len(organic_results) > 0: |
|
|
|
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): |
|
title = result.get("title", "No title") |
|
snippet = result.get("snippet", "No content") |
|
link = result.get("link", "#") |
|
displayed_link = result.get("displayed_link", 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) |
|
|
|
|
|
print("No search results or unexpected response structure") |
|
print(f"Detailed response structure: {search_results.keys() if hasattr(search_results, 'keys') else 'Unclear structure'}") |
|
|
|
|
|
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()) |
|
|
|
|
|
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" |
|
|
|
|
|
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: |
|
|
|
yield history + [(message, "🔍 Extracting optimal keywords and searching the web...")], "" |
|
|
|
|
|
print(f"Deep Research activated: Starting search for '{message}'") |
|
search_results = search_with_serphouse(message) |
|
print(f"Search results received: {search_results[:100]}...") |
|
|
|
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)}" |
|
|
|
|
|
messages = [] |
|
for user, assistant in history: |
|
messages.append({"role": "user", "content": user}) |
|
messages.append({"role": "assistant", "content": assistant}) |
|
|
|
|
|
if search_context: |
|
|
|
messages.insert(0, {"role": "system", "content": search_context}) |
|
|
|
|
|
messages.append({"role": "user", "content": message}) |
|
|
|
|
|
url = "https://api.fireworks.ai/inference/v1/chat/completions" |
|
payload = { |
|
"model": "accounts/fireworks/models/llama4-maverick-instruct-basic", |
|
"max_tokens": 20480, |
|
"top_p": 1, |
|
"top_k": 40, |
|
"presence_penalty": 0, |
|
"frequency_penalty": 0, |
|
"temperature": 0.6, |
|
"messages": messages, |
|
"stream": True |
|
} |
|
headers = { |
|
"Accept": "application/json", |
|
"Content-Type": "application/json", |
|
"Authorization": f"Bearer {api_key}" |
|
} |
|
|
|
try: |
|
|
|
response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True) |
|
response.raise_for_status() |
|
|
|
|
|
new_history = history.copy() |
|
|
|
|
|
start_msg = search_info if search_info else "" |
|
new_history.append((message, start_msg)) |
|
|
|
|
|
full_response = start_msg |
|
|
|
|
|
for line in response.iter_lines(): |
|
if line: |
|
line_text = line.decode('utf-8') |
|
|
|
|
|
if line_text.startswith("data: "): |
|
line_text = line_text[6:] |
|
|
|
|
|
if line_text == "[DONE]": |
|
break |
|
|
|
try: |
|
|
|
chunk = json.loads(line_text) |
|
chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "") |
|
|
|
if chunk_content: |
|
full_response += chunk_content |
|
|
|
new_history[-1] = (message, full_response) |
|
yield new_history, "" |
|
except json.JSONDecodeError: |
|
continue |
|
|
|
|
|
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 |
|
|
|
|
|
with gr.Blocks(theme="soft", fill_height=True) as demo: |
|
|
|
gr.Markdown( |
|
""" |
|
# 🤖 Llama-4-Maverick-17B + Research |
|
### Llama-4-Maverick-17B Model + Real-time 'Deep Research' Agentic AI System @ https://discord.gg/openfreeai |
|
""" |
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
|
with gr.Column(): |
|
|
|
chatbot = gr.Chatbot( |
|
height=500, |
|
show_label=False, |
|
container=True |
|
) |
|
|
|
|
|
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") |
|
|
|
|
|
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" |
|
|
|
|
|
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) |
|
|
|
|
|
with gr.Row(): |
|
clear = gr.ClearButton([msg, chatbot], value="🧹 Clear Conversation") |
|
|
|
|
|
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_box = gr.Markdown("") |
|
|
|
|
|
submit.click( |
|
query_deepseek_streaming, |
|
inputs=[msg, chatbot, use_deep_research], |
|
outputs=[chatbot, error_box] |
|
).then( |
|
lambda: "", |
|
None, |
|
[msg] |
|
) |
|
|
|
|
|
msg.submit( |
|
query_deepseek_streaming, |
|
inputs=[msg, chatbot, use_deep_research], |
|
outputs=[chatbot, error_box] |
|
).then( |
|
lambda: "", |
|
None, |
|
[msg] |
|
) |
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
demo = create_deepseek_interface() |
|
demo.launch(debug=True) |