openfree's picture
Update app.py
65f1795 verified
raw
history blame
17 kB
import gradio as gr
import os
import requests
import json
import time
from dotenv import load_dotenv
# .env ํŒŒ์ผ ๋กœ๋“œ (์žˆ๋Š” ๊ฒฝ์šฐ)
load_dotenv()
def create_deepseek_interface():
# ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๊ฐ€์ ธ์˜ค๊ธฐ
api_key = os.getenv("FW_API_KEY")
serphouse_api_key = os.getenv("SERPHOUSE_API_KEY")
if not api_key:
print("๊ฒฝ๊ณ : FW_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
if not serphouse_api_key:
print("๊ฒฝ๊ณ : SERPHOUSE_API_KEY ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
# ํ‚ค์›Œ๋“œ ์ถ”์ถœ ํ•จ์ˆ˜ (LLM ๊ธฐ๋ฐ˜)
def extract_keywords_with_llm(query):
if not api_key:
return "LLM ํ‚ค์›Œ๋“œ ์ถ”์ถœ์„ ์œ„ํ•œ FW_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.", query
# LLM์„ ์‚ฌ์šฉํ•˜์—ฌ ํ‚ค์›Œ๋“œ ์ถ”์ถœ (DeepSeek ๋ชจ๋ธ ์‚ฌ์šฉ)
url = "https://api.fireworks.ai/inference/v1/chat/completions"
payload = {
"model": "accounts/fireworks/models/deepseek-v3-0324",
"max_tokens": 200,
"temperature": 0.1, # ์ผ๊ด€๋œ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•ด ๋‚ฎ์€ ์˜จ๋„ ์‚ฌ์šฉ
"messages": [
{
"role": "system",
"content": "์‚ฌ์šฉ์ž์˜ ์งˆ๋ฌธ์—์„œ ์›น ๊ฒ€์ƒ‰์— ํšจ๊ณผ์ ์ธ ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”์ถœํ•˜์„ธ์š”. ํ‚ค์›Œ๋“œ ์‚ฌ์ด์— ์‰ผํ‘œ๋‚˜ ๊ณต๋ฐฑ์„ ๋„ฃ์ง€ ๋ง๊ณ  ํ•˜๋‚˜์˜ ๊ฒ€์ƒ‰์–ด์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•ด์„œ ์ œ๊ณตํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด 'ํ•œ๋•์ˆ˜ ๊ตญ๋ฌด์ด๋ฆฌ ํƒ„ํ•ต ๊ฒฐ๊ณผ'์ฒ˜๋Ÿผ ๊ณต๋ฐฑ์œผ๋กœ๋งŒ ๊ตฌ๋ถ„ํ•˜์„ธ์š”."
},
{
"role": "user",
"content": query
}
]
}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
result = response.json()
# ์‘๋‹ต์—์„œ ํ‚ค์›Œ๋“œ ์ถ”์ถœ
keywords = result["choices"][0]["message"]["content"].strip()
# ํ‚ค์›Œ๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ๊ฑฐ๋‚˜ ํ˜•์‹์ด ์ž˜๋ชป๋œ ๊ฒฝ์šฐ ์›๋ณธ ์ฟผ๋ฆฌ ์‚ฌ์šฉ
if len(keywords) > 100:
return f"์ถ”์ถœ๋œ ํ‚ค์›Œ๋“œ: {keywords}", query
return f"์ถ”์ถœ๋œ ํ‚ค์›Œ๋“œ: {keywords}", keywords
except Exception as e:
print(f"ํ‚ค์›Œ๋“œ ์ถ”์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
return f"ํ‚ค์›Œ๋“œ ์ถ”์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}", query
# SerpHouse API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ ํ•จ์ˆ˜
def search_with_serphouse(query):
if not serphouse_api_key:
return "SERPHOUSE_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
try:
# ํ‚ค์›Œ๋“œ ์ถ”์ถœ
extraction_result, search_query = extract_keywords_with_llm(query)
print(f"์›๋ณธ ์ฟผ๋ฆฌ: {query}")
print(extraction_result)
# ํ•œ๊ธ€ ๊ฒ€์ƒ‰์–ด์ธ์ง€ ํ™•์ธํ•˜๊ณ  ์ ์ ˆํ•œ ์„ค์ • ์„ ํƒ
is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
lang = "ko" if is_korean else "en"
loc = "kr" if is_korean else "us"
# MoneyRadar ๋ฐฉ์‹ ์ •ํ™•ํžˆ ๋”ฐ๋ฅด๊ธฐ - serp_type์„ news๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚ ์งœ ๋ฒ”์œ„ ์ถ”๊ฐ€
from datetime import datetime, timedelta
now = datetime.utcnow()
yesterday = now - timedelta(days=1)
date_range = f"{yesterday.strftime('%Y-%m-%d')},{now.strftime('%Y-%m-%d')}"
# SerpHouse API ํ˜ธ์ถœ ์‹คํ–‰ - POST ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ (MoneyRadar ์ฝ”๋“œ ์ฐธ๊ณ )
url = "https://api.serphouse.com/serp/live"
# MoneyRadar ๋ฐฉ์‹์œผ๋กœ ํŽ˜์ด๋กœ๋“œ ๊ตฌ์„ฑ
payload = {
"data": {
"q": search_query.replace(',', ' ').strip(),
"domain": "google.com",
"loc": loc,
"lang": lang,
"device": "desktop",
"serp_type": "news", # web์—์„œ news๋กœ ๋ณ€๊ฒฝ
"page": "1",
"num": "5",
"date_range": date_range, # ๋‚ ์งœ ๋ฒ”์œ„ ์ถ”๊ฐ€
"sort_by": "date" # ๋‚ ์งœ์ˆœ ์ •๋ ฌ ์ถ”๊ฐ€
}
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": f"Bearer {serphouse_api_key}"
}
print(f"SerpHouse API ํ˜ธ์ถœ ์ค‘... ๊ฒ€์ƒ‰์–ด: {search_query}")
print(f"์š”์ฒญ ๋ฐฉ์‹: POST, ํŽ˜์ด๋กœ๋“œ: {payload}")
# POST ์š”์ฒญ ์ˆ˜ํ–‰ (์„ธ์…˜๊ณผ ์žฌ์‹œ๋„ ๋กœ์ง ์ถ”๊ฐ€)
session = requests.Session()
retries = requests.packages.urllib3.util.retry.Retry(
total=5,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504, 429],
allowed_methods=["POST"]
)
adapter = requests.adapters.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()
print(f"SerpHouse API ์‘๋‹ต ์ƒํƒœ ์ฝ”๋“œ: {response.status_code}")
search_results = response.json()
# MoneyRadar์˜ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ ๋ถ„์„ ๋ฐ ์ ์šฉ
print(f"์‘๋‹ต ๊ตฌ์กฐ: {list(search_results.keys()) if isinstance(search_results, dict) else '๋”•์…”๋„ˆ๋ฆฌ ์•„๋‹˜'}")
# ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํŒŒ์‹ฑ ๋ฐ ํฌ๋งทํŒ…
formatted_results = []
formatted_results.append(f"๊ฒ€์ƒ‰์–ด: {search_query}\n\n")
# ๊ฒฐ๊ณผ ๊ตฌ์กฐ ํŒŒ์‹ฑ (MoneyRadar์™€ ๋™์ผํ•˜๊ฒŒ)
if "results" in search_results and "results" in search_results["results"]:
# ๋‰ด์Šค ๊ฒฐ๊ณผ ํŒŒ์‹ฑ
news_results = search_results["results"]["results"].get("news", [])
if news_results:
for result in news_results[:5]:
title = result.get("title", "์ œ๋ชฉ ์—†์Œ")
snippet = result.get("snippet", "๋‚ด์šฉ ์—†์Œ")
url = result.get("url", result.get("link", "#"))
source = result.get("source", result.get("channel", "์•Œ ์ˆ˜ ์—†์Œ"))
time = result.get("time", result.get("date", "์‹œ๊ฐ„ ์ •๋ณด ์—†์Œ"))
formatted_results.append(
f"์ œ๋ชฉ: {title}\n"
f"์ถœ์ฒ˜: {source}\n"
f"์‹œ๊ฐ„: {time}\n"
f"๋‚ด์šฉ: {snippet}\n"
f"๋งํฌ: {url}\n\n"
)
print(f"๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ {len(news_results)}๊ฐœ ์ฐพ์Œ")
return "".join(formatted_results)
print("๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์—†์Œ ๋˜๋Š” ์‘๋‹ต ํ˜•์‹ ๋ถˆ์ผ์น˜")
print(f"์‘๋‹ต ๋‚ด์šฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ: {str(search_results)[:300]}...")
return f"๊ฒ€์ƒ‰์–ด '{search_query}'์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†๊ฑฐ๋‚˜ API ์‘๋‹ต ํ˜•์‹์ด ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค."
except Exception as e:
error_msg = f"๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
print(error_msg)
import traceback
print(traceback.format_exc())
return error_msg
# ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ DeepSeek API ํ˜ธ์ถœ ํ•จ์ˆ˜
def query_deepseek_streaming(message, history, use_deep_research):
if not api_key:
yield history, "ํ™˜๊ฒฝ ๋ณ€์ˆ˜ FW_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
return
search_context = ""
search_info = ""
if use_deep_research:
try:
# ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ (์ฒซ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ)
yield history + [(message, "๐Ÿ” ์ตœ์ ์˜ ํ‚ค์›Œ๋“œ ์ถ”์ถœ ๋ฐ ์›น ๊ฒ€์ƒ‰ ์ค‘...")], ""
# ๊ฒ€์ƒ‰ ์‹คํ–‰ - ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ๋กœ๊ทธ ์ถ”๊ฐ€
print(f"Deep Research ํ™œ์„ฑํ™”๋จ: ๋ฉ”์‹œ์ง€ '{message}'์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰ ์‹œ์ž‘")
search_results = search_with_serphouse(message)
print(f"๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ˆ˜์‹  ์™„๋ฃŒ: {search_results[:100]}...") # ๊ฒฐ๊ณผ ์•ž๋ถ€๋ถ„๋งŒ ์ถœ๋ ฅ
if not search_results.startswith("๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ") and not search_results.startswith("SERPHOUSE_API_KEY"):
search_context = f"""
๋‹ค์Œ์€ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ์ตœ์‹  ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ •ํ™•ํ•˜๊ณ  ์ตœ์‹  ์ •๋ณด๊ฐ€ ๋ฐ˜์˜๋œ ์‘๋‹ต์„ ์ œ๊ณตํ•˜์„ธ์š”:
{search_results}
์œ„ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ๋‹ค์Œ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•˜์„ธ์š”. ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์—์„œ ๋ช…ํ™•ํ•œ ๋‹ต๋ณ€์„ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ๋‹น์‹ ์˜ ์ง€์‹์„ ํ™œ์šฉํ•˜์—ฌ ์ตœ์„ ์˜ ๋‹ต๋ณ€์„ ์ œ๊ณตํ•˜์„ธ์š”.
๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ธ์šฉํ•  ๋•Œ๋Š” ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•˜๊ณ , ๋‹ต๋ณ€์ด ์ตœ์‹  ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•˜๋„๋ก ํ•˜์„ธ์š”.
"""
search_info = f"๐Ÿ” Deep Research ๊ธฐ๋Šฅ ํ™œ์„ฑํ™”: ๊ด€๋ จ ์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‘๋‹ต ์ƒ์„ฑ ์ค‘..."
else:
print(f"๊ฒ€์ƒ‰ ์‹คํŒจ ๋˜๋Š” ๊ฒฐ๊ณผ ์—†์Œ: {search_results}")
except Exception as e:
print(f"Deep Research ์ฒ˜๋ฆฌ ์ค‘ ์˜ˆ์™ธ ๋ฐœ์ƒ: {str(e)}")
search_info = f"๐Ÿ” Deep Research ๊ธฐ๋Šฅ ์˜ค๋ฅ˜: {str(e)}"
# API ์š”์ฒญ์„ ์œ„ํ•œ ๋Œ€ํ™” ๊ธฐ๋ก ์ค€๋น„
messages = []
for user, assistant in history:
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", "content": assistant})
# ๊ฒ€์ƒ‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
if search_context:
# DeepSeek ๋ชจ๋ธ์€ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค
messages.insert(0, {"role": "system", "content": search_context})
# ์ƒˆ ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
messages.append({"role": "user", "content": message})
# API ์š”์ฒญ ์ค€๋น„
url = "https://api.fireworks.ai/inference/v1/chat/completions"
payload = {
"model": "accounts/fireworks/models/deepseek-v3-0324",
"max_tokens": 20480,
"top_p": 1,
"top_k": 40,
"presence_penalty": 0,
"frequency_penalty": 0,
"temperature": 0.6,
"messages": messages,
"stream": True # ์ŠคํŠธ๋ฆฌ๋ฐ ํ™œ์„ฑํ™”
}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
try:
# ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์š”์ฒญ
response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
response.raise_for_status() # HTTP ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์˜ˆ์™ธ ๋ฐœ์ƒ
# ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ดˆ๊ธฐ ์‘๋‹ต์œผ๋กœ ์‹œ์ž‘
new_history = history.copy()
# search_info๊ฐ€ ์žˆ์œผ๋ฉด ์‹œ์ž‘ ๋ฉ”์‹œ์ง€์— ํฌํ•จ
start_msg = search_info if search_info else ""
new_history.append((message, start_msg))
# ์‘๋‹ต ์ „์ฒด ํ…์ŠคํŠธ
full_response = start_msg
# ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
for line in response.iter_lines():
if line:
line_text = line.decode('utf-8')
# 'data: ' ์ ‘๋‘์‚ฌ ์ œ๊ฑฐ
if line_text.startswith("data: "):
line_text = line_text[6:]
# ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ๋ฉ”์‹œ์ง€ ํ™•์ธ
if line_text == "[DONE]":
break
try:
# JSON ํŒŒ์‹ฑ
chunk = json.loads(line_text)
chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
if chunk_content:
full_response += chunk_content
# ์ฑ„ํŒ… ๊ธฐ๋ก ์—…๋ฐ์ดํŠธ
new_history[-1] = (message, full_response)
yield new_history, ""
except json.JSONDecodeError:
continue
# ์ตœ์ข… ์‘๋‹ต ๋ฐ˜ํ™˜
yield new_history, ""
except requests.exceptions.RequestException as e:
error_msg = f"API ์˜ค๋ฅ˜: {str(e)}"
if hasattr(e, 'response') and e.response and e.response.status_code == 401:
error_msg = "์ธ์ฆ ์‹คํŒจ. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ FW_API_KEY๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
yield history, error_msg
# Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
with gr.Blocks(theme="soft", fill_height=True) as demo:
# ํ—ค๋” ์„น์…˜
gr.Markdown(
"""
# ๐Ÿค– DeepSeek V3 ์ŠคํŠธ๋ฆฌ๋ฐ ์ธํ„ฐํŽ˜์ด์Šค
### Fireworks AI๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ณ ๊ธ‰ AI ๋ชจ๋ธ - ์‹ค์‹œ๊ฐ„ ์‘๋‹ต ์ง€์›
"""
)
# ๋ฉ”์ธ ๋ ˆ์ด์•„์›ƒ
with gr.Row():
# ๋ฉ”์ธ ์ฝ˜ํ…์ธ  ์˜์—ญ
with gr.Column():
# ์ฑ„ํŒ… ์ธํ„ฐํŽ˜์ด์Šค
chatbot = gr.Chatbot(
height=500,
show_label=False,
container=True
)
# Deep Research ํ† ๊ธ€ ๋ฐ ์ƒํƒœ ํ‘œ์‹œ ์ถ”๊ฐ€
with gr.Row():
with gr.Column(scale=3):
use_deep_research = gr.Checkbox(
label="Deep Research ํ™œ์„ฑํ™”",
info="์ตœ์ ์˜ ํ‚ค์›Œ๋“œ ์ถ”์ถœ ๋ฐ ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ์ตœ์‹  ์ •๋ณด ํ™œ์šฉ",
value=False
)
with gr.Column(scale=1):
api_status = gr.Markdown("API ์ƒํƒœ: ์ค€๋น„๋จ")
# API ํ‚ค ์ƒํƒœ ํ™•์ธ ๋ฐ ํ‘œ์‹œ
if not serphouse_api_key:
api_status.value = "โš ๏ธ SERPHOUSE_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค"
if not api_key:
api_status.value = "โš ๏ธ FW_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค"
if api_key and serphouse_api_key:
api_status.value = "โœ… API ํ‚ค ์„ค์ • ์™„๋ฃŒ"
# ์ž…๋ ฅ ์˜์—ญ
with gr.Row():
msg = gr.Textbox(
label="๋ฉ”์‹œ์ง€",
placeholder="์—ฌ๊ธฐ์— ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”...",
show_label=False,
scale=9
)
submit = gr.Button("์ „์†ก", variant="primary", scale=1)
# ๋Œ€ํ™” ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ
with gr.Row():
clear = gr.ClearButton([msg, chatbot], value="๐Ÿงน ๋Œ€ํ™” ์ดˆ๊ธฐํ™”")
# ์˜ˆ์ œ ์ฟผ๋ฆฌ
gr.Examples(
examples=[
"๋”ฅ๋Ÿฌ๋‹์—์„œ ํŠธ๋žœ์Šคํฌ๋จธ์™€ RNN์˜ ์ฐจ์ด์ ์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.",
"ํŠน์ • ๋ฒ”์œ„ ๋‚ด์˜ ์†Œ์ˆ˜๋ฅผ ์ฐพ๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.",
"๊ฐ•ํ™”ํ•™์Šต์˜ ์ฃผ์š” ๊ฐœ๋…์„ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
],
inputs=msg
)
# ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
error_box = gr.Markdown("")
# ๋ฒ„ํŠผ๊ณผ ๊ธฐ๋Šฅ ์—ฐ๊ฒฐ
submit.click(
query_deepseek_streaming,
inputs=[msg, chatbot, use_deep_research],
outputs=[chatbot, error_box]
).then(
lambda: "",
None,
[msg]
)
# Enter ํ‚ค ์ œ์ถœ ํ—ˆ์šฉ
msg.submit(
query_deepseek_streaming,
inputs=[msg, chatbot, use_deep_research],
outputs=[chatbot, error_box]
).then(
lambda: "",
None,
[msg]
)
return demo
# ์ธํ„ฐํŽ˜์ด์Šค ์‹คํ–‰
if __name__ == "__main__":
demo = create_deepseek_interface()
demo.launch(debug=True)