|
import streamlit as st |
|
import requests |
|
import logging |
|
import json |
|
import re |
|
from datetime import datetime, timedelta |
|
from requests.adapters import HTTPAdapter |
|
from urllib3.util.retry import Retry |
|
|
|
|
|
def translate_query(query, country): |
|
|
|
return query |
|
|
|
COUNTRY_LOCATIONS = { |
|
"United States": "United States", |
|
"South Korea": "South Korea" |
|
} |
|
COUNTRY_LANGUAGES = { |
|
"United States": "en", |
|
"South Korea": "ko" |
|
} |
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
st.set_page_config( |
|
page_title="DeepSeek Chatbot", |
|
page_icon="๐ค", |
|
layout="centered" |
|
) |
|
|
|
|
|
if "messages" not in st.session_state: |
|
st.session_state.messages = [] |
|
|
|
|
|
with st.sidebar: |
|
st.header("Model Configuration") |
|
st.markdown("[Get HuggingFace Token](https://huggingface.co/settings/tokens)") |
|
|
|
|
|
model_options = [ |
|
"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B", |
|
] |
|
selected_model = st.selectbox("Select Model", model_options, index=0) |
|
|
|
system_message = st.text_area( |
|
"System Message", |
|
value=( |
|
"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." |
|
), |
|
height=100 |
|
) |
|
|
|
max_tokens = st.slider("Max Tokens", 10, 4000, 1000) |
|
temperature = st.slider("Temperature", 0.1, 4.0, 0.3) |
|
top_p = st.slider("Top-p", 0.1, 1.0, 0.6) |
|
|
|
|
|
def query(payload, api_url): |
|
headers = {"Authorization": f"Bearer {st.secrets['HF_TOKEN']}"} |
|
logger.info(f"Sending request to {api_url} with payload: {payload}") |
|
response = requests.post(api_url, headers=headers, json=payload) |
|
logger.info(f"Received response: {response.status_code}, {response.text}") |
|
try: |
|
return response.json() |
|
except requests.exceptions.JSONDecodeError: |
|
logger.error(f"Failed to decode JSON response: {response.text}") |
|
return None |
|
|
|
|
|
def search_web(query, country="United States", page=1, num_result=10): |
|
url = "https://api.serphouse.com/serp/live" |
|
|
|
|
|
now = datetime.utcnow() |
|
yesterday = now - timedelta(days=1) |
|
date_range = f"{yesterday.strftime('%Y-%m-%d')},{now.strftime('%Y-%m-%d')}" |
|
|
|
|
|
translated_query = translate_query(query, country) |
|
|
|
payload = { |
|
"data": { |
|
"q": translated_query, |
|
"domain": "google.com", |
|
"loc": COUNTRY_LOCATIONS.get(country, "United States"), |
|
"lang": COUNTRY_LANGUAGES.get(country, "en"), |
|
"device": "desktop", |
|
"serp_type": "web", |
|
"page": str(page), |
|
"num": str(num_result), |
|
"date_range": date_range, |
|
"sort_by": "date" |
|
} |
|
} |
|
|
|
api_key = st.secrets.get("SERPHOUSE_API_TOKEN") |
|
if not api_key: |
|
logger.error("SERPHOUSE_API_TOKEN not found in st.secrets") |
|
return {"error": "API token not configured."} |
|
|
|
headers = { |
|
"accept": "application/json", |
|
"content-type": "application/json", |
|
"authorization": f"Bearer {api_key}" |
|
} |
|
|
|
try: |
|
session = requests.Session() |
|
retries = Retry( |
|
total=5, |
|
backoff_factor=1, |
|
status_forcelist=[500, 502, 503, 504, 429], |
|
allowed_methods=["POST"] |
|
) |
|
adapter = HTTPAdapter(max_retries=retries) |
|
session.mount('http://', adapter) |
|
session.mount('https://', adapter) |
|
|
|
response = session.post( |
|
url, |
|
json=payload, |
|
headers=headers, |
|
timeout=(30, 30) |
|
) |
|
response.raise_for_status() |
|
return {"results": response.json(), "translated_query": translated_query} |
|
|
|
except requests.exceptions.Timeout: |
|
return { |
|
"error": "๊ฒ์ ์๊ฐ์ด ์ด๊ณผ๋์์ต๋๋ค. ์ ์ ํ ๋ค์ ์๋ํด์ฃผ์ธ์.", |
|
"translated_query": query |
|
} |
|
except requests.exceptions.RequestException as e: |
|
return { |
|
"error": f"๊ฒ์ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}", |
|
"translated_query": query |
|
} |
|
except Exception as e: |
|
return { |
|
"error": f"์๊ธฐ์น ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}", |
|
"translated_query": query |
|
} |
|
|
|
|
|
|
|
def remove_chain_of_thought(text): |
|
cleaned_text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL) |
|
return cleaned_text.strip() |
|
|
|
|
|
st.title("๐ค DeepSeek Chatbot") |
|
st.caption("Powered by Hugging Face Inference API - Configure in sidebar") |
|
|
|
|
|
for message in st.session_state.messages: |
|
with st.chat_message(message["role"]): |
|
st.markdown(message["content"]) |
|
|
|
|
|
if prompt := st.chat_input("Type your message..."): |
|
st.session_state.messages.append({"role": "user", "content": prompt}) |
|
|
|
with st.chat_message("user"): |
|
st.markdown(prompt) |
|
|
|
try: |
|
with st.spinner("Generating response..."): |
|
|
|
search_results = search_web(prompt, country="United States", page=1, num_result=10) |
|
|
|
|
|
if search_results and "results" in search_results: |
|
if 'organic' in search_results["results"]: |
|
search_content = "\n".join( |
|
[f"**{item['title']}**: {item['snippet']}" for item in search_results["results"]["organic"]] |
|
) |
|
search_content = f"Here are some search results related to your question:\n\n{search_content}\n\n" |
|
else: |
|
search_content = "Sorry, no relevant search results found.\n\n" |
|
|
|
full_prompt = f"{system_message}\n\n{search_content}User: {prompt}\nAssistant:" |
|
else: |
|
full_prompt = f"{system_message}\n\nUser: {prompt}\nAssistant:" |
|
|
|
payload = { |
|
"inputs": full_prompt, |
|
"parameters": { |
|
"max_new_tokens": max_tokens, |
|
"temperature": temperature, |
|
"top_p": top_p, |
|
"return_full_text": False |
|
} |
|
} |
|
|
|
|
|
api_url = f"https://api-inference.huggingface.co/models/{selected_model}" |
|
logger.info(f"Selected model: {selected_model}, API URL: {api_url}") |
|
|
|
|
|
output = query(payload, api_url) |
|
|
|
|
|
if output is not None and isinstance(output, list) and len(output) > 0: |
|
if 'generated_text' in output[0]: |
|
assistant_response = output[0]['generated_text'].strip() |
|
|
|
unique_response = remove_chain_of_thought(assistant_response) |
|
|
|
logger.info(f"Generated response: {unique_response}") |
|
|
|
with st.chat_message("assistant"): |
|
st.markdown(unique_response) |
|
|
|
st.session_state.messages.append({"role": "assistant", "content": unique_response}) |
|
else: |
|
logger.error(f"Unexpected API response structure: {output}") |
|
st.error("Error: Unexpected response from the model. Please try again.") |
|
else: |
|
logger.error(f"Empty or invalid API response: {output}") |
|
st.error("Error: Unable to generate a response. Please check the model and try again.") |
|
|
|
except Exception as e: |
|
logger.error(f"Application Error: {str(e)}", exc_info=True) |
|
st.error(f"Application Error: {str(e)}") |
|
|