seawolf2357's picture
Update app.py
91f7b07 verified
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"https://api-inference.huggingface.co/models/{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)}")