seawolf2357's picture
Update app.py
91f7b07 verified
raw
history blame
8.68 kB
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)}")