|  | 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)}") | 
					
						
						|  |  |