Spaces:
Sleeping
Sleeping
| 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 | |
| # --- Optional: translate_query ๋ฐ ๊ด๋ จ ์์ ์ ์ (์ค์ ๊ตฌํ์ ๋ง๊ฒ ์์ ) --- | |
| 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" | |
| } | |
| # ------------------------------------------------------------------------- | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="DeepSeek Chatbot", | |
| page_icon="๐ค", | |
| layout="centered" | |
| ) | |
| # Initialize session state for chat history | |
| if "messages" not in st.session_state: | |
| st.session_state.messages = [] | |
| # Sidebar configuration | |
| with st.sidebar: | |
| st.header("Model Configuration") | |
| st.markdown("[Get HuggingFace Token](https://huggingface.co/settings/tokens)") | |
| # Dropdown to select model | |
| 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) | |
| # Function to query the Hugging Face API | |
| 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" | |
| # ์ต๊ทผ 24์๊ฐ ๊ธฐ๊ฐ ์ค์ | |
| 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", # ์ํ๋ ๊ฒฝ์ฐ "news" ๋ฑ์ผ๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ | |
| "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) # ์ฐ๊ฒฐ ๋ฐ ์ฝ๊ธฐ ํ์์์ 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() | |
| # Chat interface | |
| st.title("๐ค DeepSeek Chatbot") | |
| st.caption("Powered by Hugging Face Inference API - Configure in sidebar") | |
| # Display chat history | |
| for message in st.session_state.messages: | |
| with st.chat_message(message["role"]): | |
| st.markdown(message["content"]) | |
| # Handle input | |
| 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 ๋์ ๊ตฌ์ฑ | |
| api_url = f"/static-proxy?url=https%3A%2F%2Fapi-inference.huggingface.co%2Fmodels%2F%3Cspan class="hljs-subst">{selected_model}" | |
| logger.info(f"Selected model: {selected_model}, API URL: {api_url}") | |
| # Hugging Face API์ ์ฟผ๋ฆฌ ์ ์ก | |
| output = query(payload, api_url) | |
| # API ์๋ต ์ฒ๋ฆฌ | |
| 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)}") | |