Create app-backup.py
Browse files- app-backup.py +385 -0
app-backup.py
ADDED
@@ -0,0 +1,385 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
import requests
|
4 |
+
import json
|
5 |
+
import time
|
6 |
+
from dotenv import load_dotenv
|
7 |
+
|
8 |
+
# .env ํ์ผ ๋ก๋ (์๋ ๊ฒฝ์ฐ)
|
9 |
+
load_dotenv()
|
10 |
+
|
11 |
+
def create_deepseek_interface():
|
12 |
+
# ํ๊ฒฝ ๋ณ์์์ API ํค ๊ฐ์ ธ์ค๊ธฐ
|
13 |
+
api_key = os.getenv("FW_API_KEY")
|
14 |
+
serphouse_api_key = os.getenv("SERPHOUSE_API_KEY")
|
15 |
+
|
16 |
+
if not api_key:
|
17 |
+
print("๊ฒฝ๊ณ : FW_API_KEY ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.")
|
18 |
+
if not serphouse_api_key:
|
19 |
+
print("๊ฒฝ๊ณ : SERPHOUSE_API_KEY ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.")
|
20 |
+
|
21 |
+
# ํค์๋ ์ถ์ถ ํจ์ (LLM ๊ธฐ๋ฐ)
|
22 |
+
def extract_keywords_with_llm(query):
|
23 |
+
if not api_key:
|
24 |
+
return "LLM ํค์๋ ์ถ์ถ์ ์ํ FW_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.", query
|
25 |
+
|
26 |
+
# LLM์ ์ฌ์ฉํ์ฌ ํค์๋ ์ถ์ถ (DeepSeek ๋ชจ๋ธ ์ฌ์ฉ)
|
27 |
+
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
28 |
+
payload = {
|
29 |
+
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
30 |
+
"max_tokens": 200,
|
31 |
+
"temperature": 0.1, # ์ผ๊ด๋ ๊ฒฐ๊ณผ๋ฅผ ์ํด ๋ฎ์ ์จ๋ ์ฌ์ฉ
|
32 |
+
"messages": [
|
33 |
+
{
|
34 |
+
"role": "system",
|
35 |
+
"content": "์ฌ์ฉ์์ ์ง๋ฌธ์์ ์น ๊ฒ์์ ํจ๊ณผ์ ์ธ ํต์ฌ ํค์๋๋ฅผ ์ถ์ถํ์ธ์. ํค์๋ ์ฌ์ด์ ์ผํ๋ ๊ณต๋ฐฑ์ ๋ฃ์ง ๋ง๊ณ ํ๋์ ๊ฒ์์ด์ฒ๋ผ ์์ ํด์ ์ ๊ณตํ์ธ์. ์๋ฅผ ๋ค์ด 'ํ๋์ ๊ตญ๋ฌด์ด๋ฆฌ ํํต ๊ฒฐ๊ณผ'์ฒ๋ผ ๊ณต๋ฐฑ์ผ๋ก๋ง ๊ตฌ๋ถํ์ธ์."
|
36 |
+
},
|
37 |
+
{
|
38 |
+
"role": "user",
|
39 |
+
"content": query
|
40 |
+
}
|
41 |
+
]
|
42 |
+
}
|
43 |
+
headers = {
|
44 |
+
"Accept": "application/json",
|
45 |
+
"Content-Type": "application/json",
|
46 |
+
"Authorization": f"Bearer {api_key}"
|
47 |
+
}
|
48 |
+
|
49 |
+
try:
|
50 |
+
response = requests.post(url, headers=headers, json=payload)
|
51 |
+
response.raise_for_status()
|
52 |
+
result = response.json()
|
53 |
+
|
54 |
+
# ์๋ต์์ ํค์๋ ์ถ์ถ
|
55 |
+
keywords = result["choices"][0]["message"]["content"].strip()
|
56 |
+
|
57 |
+
# ํค์๋๊ฐ ๋๋ฌด ๊ธธ๊ฑฐ๋ ํ์์ด ์๋ชป๋ ๊ฒฝ์ฐ ์๋ณธ ์ฟผ๋ฆฌ ์ฌ์ฉ
|
58 |
+
if len(keywords) > 100:
|
59 |
+
return f"์ถ์ถ๋ ํค์๋: {keywords}", query
|
60 |
+
|
61 |
+
return f"์ถ์ถ๋ ํค์๋: {keywords}", keywords
|
62 |
+
|
63 |
+
except Exception as e:
|
64 |
+
print(f"ํค์๋ ์ถ์ถ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}")
|
65 |
+
return f"ํค์๋ ์ถ์ถ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}", query
|
66 |
+
|
67 |
+
# SerpHouse API๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ ์ํ ํจ์
|
68 |
+
def search_with_serphouse(query):
|
69 |
+
if not serphouse_api_key:
|
70 |
+
return "SERPHOUSE_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค."
|
71 |
+
|
72 |
+
try:
|
73 |
+
# ํค์๋ ์ถ์ถ
|
74 |
+
extraction_result, search_query = extract_keywords_with_llm(query)
|
75 |
+
print(f"์๋ณธ ์ฟผ๋ฆฌ: {query}")
|
76 |
+
print(extraction_result)
|
77 |
+
|
78 |
+
# ๋ฌธ์ ์ฝ๋๋ฅผ ๋ ์์ธํ ๋ถ์ํด ๋ณด๋ ๊ธฐ๋ณธ GET ๋ฐฉ์ ํ์ฉ์ด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค
|
79 |
+
url = "https://api.serphouse.com/serp/live"
|
80 |
+
|
81 |
+
# ํ๊ธ ๊ฒ์์ด์ธ์ง ํ์ธ
|
82 |
+
is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
|
83 |
+
|
84 |
+
# ๊ฐ์ํ๋ ํ๋ผ๋ฏธํฐ๋ก ์๋
|
85 |
+
params = {
|
86 |
+
"q": search_query,
|
87 |
+
"domain": "google.com",
|
88 |
+
"serp_type": "web", # ๊ธฐ๋ณธ ์น ๊ฒ์์ผ๋ก ๋ณ๊ฒฝ
|
89 |
+
"device": "desktop",
|
90 |
+
"lang": "ko" if is_korean else "en"
|
91 |
+
}
|
92 |
+
|
93 |
+
headers = {
|
94 |
+
"Authorization": f"Bearer {serphouse_api_key}"
|
95 |
+
}
|
96 |
+
|
97 |
+
print(f"SerpHouse API ํธ์ถ ์ค... ๊ธฐ๋ณธ GET ๋ฐฉ์์ผ๋ก ์๋")
|
98 |
+
print(f"๊ฒ์์ด: {search_query}")
|
99 |
+
print(f"์์ฒญ URL: {url} - ํ๋ผ๋ฏธํฐ: {params}")
|
100 |
+
|
101 |
+
# GET ์์ฒญ ์ํ
|
102 |
+
response = requests.get(url, headers=headers, params=params)
|
103 |
+
response.raise_for_status()
|
104 |
+
|
105 |
+
print(f"SerpHouse API ์๋ต ์ํ ์ฝ๋: {response.status_code}")
|
106 |
+
search_results = response.json()
|
107 |
+
|
108 |
+
# ์๋ต ๊ตฌ์กฐ ํ์ธ
|
109 |
+
print(f"์๋ต ๊ตฌ์กฐ: {list(search_results.keys()) if isinstance(search_results, dict) else '๋์
๋๋ฆฌ ์๋'}")
|
110 |
+
|
111 |
+
# ๊ฒ์ ๊ฒฐ๊ณผ ํ์ฑ ๋ฐ ํฌ๋งทํ
|
112 |
+
formatted_results = []
|
113 |
+
formatted_results.append(f"๊ฒ์์ด: {search_query}\n\n")
|
114 |
+
|
115 |
+
# ๋ค์ํ ๊ฐ๋ฅํ ์๋ต ๊ตฌ์กฐ์ ๋ํ ์ฒ๋ฆฌ
|
116 |
+
organic_results = None
|
117 |
+
|
118 |
+
# ๊ฐ๋ฅํ ์๋ต ๊ตฌ์กฐ 1
|
119 |
+
if "results" in search_results and "organic" in search_results["results"]:
|
120 |
+
organic_results = search_results["results"]["organic"]
|
121 |
+
|
122 |
+
# ๊ฐ๋ฅํ ์๋ต ๊ตฌ์กฐ 2
|
123 |
+
elif "organic" in search_results:
|
124 |
+
organic_results = search_results["organic"]
|
125 |
+
|
126 |
+
# ๊ฐ๋ฅํ ์๋ต ๊ตฌ์กฐ 3 (์ค์ฒฉ๋ results)
|
127 |
+
elif "results" in search_results and "results" in search_results["results"]:
|
128 |
+
if "organic" in search_results["results"]["results"]:
|
129 |
+
organic_results = search_results["results"]["results"]["organic"]
|
130 |
+
|
131 |
+
# organic_results๊ฐ ์์ผ๋ฉด ์ฒ๋ฆฌ
|
132 |
+
if organic_results and len(organic_results) > 0:
|
133 |
+
# ์๋ต ๊ตฌ์กฐ ์ถ๋ ฅ
|
134 |
+
print(f"์ฒซ๋ฒ์งธ organic ๊ฒฐ๊ณผ ๊ตฌ์กฐ: {organic_results[0].keys() if len(organic_results) > 0 else 'empty'}")
|
135 |
+
|
136 |
+
for result in organic_results[:5]: # ์์ 5๊ฐ ๊ฒฐ๊ณผ๋ง ํ์
|
137 |
+
title = result.get("title", "์ ๋ชฉ ์์")
|
138 |
+
snippet = result.get("snippet", "๋ด์ฉ ์์")
|
139 |
+
link = result.get("link", "#")
|
140 |
+
|
141 |
+
formatted_results.append(
|
142 |
+
f"์ ๋ชฉ: {title}\n"
|
143 |
+
f"๋ด์ฉ: {snippet}\n"
|
144 |
+
f"๋งํฌ: {link}\n\n"
|
145 |
+
)
|
146 |
+
|
147 |
+
print(f"๊ฒ์ ๊ฒฐ๊ณผ {len(organic_results)}๊ฐ ์ฐพ์")
|
148 |
+
return "".join(formatted_results)
|
149 |
+
|
150 |
+
# ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ ์์์น ๋ชปํ ๊ตฌ์กฐ์ธ ๊ฒฝ์ฐ
|
151 |
+
print("๊ฒ์ ๊ฒฐ๊ณผ ์์ ๋๋ ์์์น ๋ชปํ ์๋ต ๊ตฌ์กฐ")
|
152 |
+
print(f"์๋ต ๊ตฌ์กฐ ์์ธ: {search_results.keys() if hasattr(search_results, 'keys') else '๋ถ๋ช
ํํ ๊ตฌ์กฐ'}")
|
153 |
+
|
154 |
+
# ์๋ต ๋ด์ฉ์์ ์ค๋ฅ ๋ฉ์์ง ์ฐพ๊ธฐ
|
155 |
+
error_msg = "๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ ์๋ต ํ์์ด ์์๊ณผ ๋ค๋ฆ
๋๋ค"
|
156 |
+
if "error" in search_results:
|
157 |
+
error_msg = search_results["error"]
|
158 |
+
elif "message" in search_results:
|
159 |
+
error_msg = search_results["message"]
|
160 |
+
|
161 |
+
return f"๊ฒ์์ด '{search_query}'์ ๋ํ ๊ฒฐ๊ณผ: {error_msg}"
|
162 |
+
|
163 |
+
except Exception as e:
|
164 |
+
error_msg = f"๊ฒ์ ์ค ์ค๋ฅ ๋ฐ์: {str(e)}"
|
165 |
+
print(error_msg)
|
166 |
+
import traceback
|
167 |
+
print(traceback.format_exc())
|
168 |
+
|
169 |
+
# ๋๋ฒ๊น
๋ชฉ์ ์ผ๋ก API ์์ฒญ ์์ธ ์ ๋ณด ์ถ๊ฐ
|
170 |
+
return f"๊ฒ์ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}\n\n" + \
|
171 |
+
f"API ์์ฒญ ์์ธ ์ ๋ณด:\n" + \
|
172 |
+
f"- URL: {url}\n" + \
|
173 |
+
f"- ๊ฒ์์ด: {search_query}\n" + \
|
174 |
+
f"- ํ๋ผ๋ฏธํฐ: {params}\n"
|
175 |
+
|
176 |
+
# ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก DeepSeek API ํธ์ถ ํจ์
|
177 |
+
def query_deepseek_streaming(message, history, use_deep_research):
|
178 |
+
if not api_key:
|
179 |
+
yield history, "ํ๊ฒฝ ๋ณ์ FW_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค. ์๋ฒ์์ ํ๊ฒฝ ๋ณ์๋ฅผ ํ์ธํด์ฃผ์ธ์."
|
180 |
+
return
|
181 |
+
|
182 |
+
search_context = ""
|
183 |
+
search_info = ""
|
184 |
+
if use_deep_research:
|
185 |
+
try:
|
186 |
+
# ๊ฒ์ ์ํ (์ฒซ ๋ฉ์์ง ์ ๋ฌ)
|
187 |
+
yield history + [(message, "๐ ์ต์ ์ ํค์๋ ์ถ์ถ ๋ฐ ์น ๊ฒ์ ์ค...")], ""
|
188 |
+
|
189 |
+
# ๊ฒ์ ์คํ - ๋๋ฒ๊น
์ ์ํ ๋ก๊ทธ ์ถ๊ฐ
|
190 |
+
print(f"Deep Research ํ์ฑํ๋จ: ๋ฉ์์ง '{message}'์ ๋ํ ๊ฒ์ ์์")
|
191 |
+
search_results = search_with_serphouse(message)
|
192 |
+
print(f"๊ฒ์ ๊ฒฐ๊ณผ ์์ ์๋ฃ: {search_results[:100]}...") # ๊ฒฐ๊ณผ ์๋ถ๋ถ๋ง ์ถ๋ ฅ
|
193 |
+
|
194 |
+
if not search_results.startswith("๊ฒ์ ์ค ์ค๋ฅ ๋ฐ์") and not search_results.startswith("SERPHOUSE_API_KEY"):
|
195 |
+
search_context = f"""
|
196 |
+
๋ค์์ ์ฌ์ฉ์ ์ง๋ฌธ๊ณผ ๊ด๋ จ๋ ์ต์ ๊ฒ์ ๊ฒฐ๊ณผ์
๋๋ค. ์ด ์ ๋ณด๋ฅผ ์ฐธ๊ณ ํ์ฌ ์ ํํ๊ณ ์ต์ ์ ๋ณด๊ฐ ๋ฐ์๋ ์๋ต์ ์ ๊ณตํ์ธ์:
|
197 |
+
{search_results}
|
198 |
+
์ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์์ ๋ค์ ์ง๋ฌธ์ ๋ต๋ณํ์ธ์. ๊ฒ์ ๊ฒฐ๊ณผ์์ ๋ช
ํํ ๋ต๋ณ์ ์ฐพ์ ์ ์๋ ๊ฒฝ์ฐ, ๋น์ ์ ์ง์์ ํ์ฉํ์ฌ ์ต์ ์ ๋ต๋ณ์ ์ ๊ณตํ์ธ์.
|
199 |
+
๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ธ์ฉํ ๋๋ ์ถ์ฒ๋ฅผ ๋ช
์ํ๊ณ , ๋ต๋ณ์ด ์ต์ ์ ๋ณด๋ฅผ ๋ฐ์ํ๋๋ก ํ์ธ์.
|
200 |
+
"""
|
201 |
+
search_info = f"๐ Deep Research ๊ธฐ๋ฅ ํ์ฑํ: ๊ด๋ จ ์น ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ต ์์ฑ ์ค..."
|
202 |
+
else:
|
203 |
+
print(f"๊ฒ์ ์คํจ ๋๋ ๊ฒฐ๊ณผ ์์: {search_results}")
|
204 |
+
except Exception as e:
|
205 |
+
print(f"Deep Research ์ฒ๋ฆฌ ์ค ์์ธ ๋ฐ์: {str(e)}")
|
206 |
+
search_info = f"๐ Deep Research ๊ธฐ๋ฅ ์ค๋ฅ: {str(e)}"
|
207 |
+
|
208 |
+
# API ์์ฒญ์ ์ํ ๋ํ ๊ธฐ๋ก ์ค๋น
|
209 |
+
messages = []
|
210 |
+
for user, assistant in history:
|
211 |
+
messages.append({"role": "user", "content": user})
|
212 |
+
messages.append({"role": "assistant", "content": assistant})
|
213 |
+
|
214 |
+
# ๊ฒ์ ์ปจํ
์คํธ๊ฐ ์์ผ๋ฉด ์์คํ
๋ฉ์์ง ์ถ๊ฐ
|
215 |
+
if search_context:
|
216 |
+
# DeepSeek ๋ชจ๋ธ์ ์์คํ
๋ฉ์์ง๋ฅผ ์ง์ํฉ๋๋ค
|
217 |
+
messages.insert(0, {"role": "system", "content": search_context})
|
218 |
+
|
219 |
+
# ์ ์ฌ์ฉ์ ๋ฉ์์ง ์ถ๊ฐ
|
220 |
+
messages.append({"role": "user", "content": message})
|
221 |
+
|
222 |
+
# API ์์ฒญ ์ค๋น
|
223 |
+
url = "https://api.fireworks.ai/inference/v1/chat/completions"
|
224 |
+
payload = {
|
225 |
+
"model": "accounts/fireworks/models/deepseek-v3-0324",
|
226 |
+
"max_tokens": 20480,
|
227 |
+
"top_p": 1,
|
228 |
+
"top_k": 40,
|
229 |
+
"presence_penalty": 0,
|
230 |
+
"frequency_penalty": 0,
|
231 |
+
"temperature": 0.6,
|
232 |
+
"messages": messages,
|
233 |
+
"stream": True # ์คํธ๋ฆฌ๋ฐ ํ์ฑํ
|
234 |
+
}
|
235 |
+
headers = {
|
236 |
+
"Accept": "application/json",
|
237 |
+
"Content-Type": "application/json",
|
238 |
+
"Authorization": f"Bearer {api_key}"
|
239 |
+
}
|
240 |
+
|
241 |
+
try:
|
242 |
+
# ์คํธ๋ฆฌ๋ฐ ์๋ต ์์ฒญ
|
243 |
+
response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
|
244 |
+
response.raise_for_status() # HTTP ์ค๋ฅ ๋ฐ์ ์ ์์ธ ๋ฐ์
|
245 |
+
|
246 |
+
# ๋ฉ์์ง๋ฅผ ์ถ๊ฐํ๊ณ ์ด๊ธฐ ์๋ต์ผ๋ก ์์
|
247 |
+
new_history = history.copy()
|
248 |
+
|
249 |
+
# search_info๊ฐ ์์ผ๋ฉด ์์ ๋ฉ์์ง์ ํฌํจ
|
250 |
+
start_msg = search_info if search_info else ""
|
251 |
+
new_history.append((message, start_msg))
|
252 |
+
|
253 |
+
# ์๋ต ์ ์ฒด ํ
์คํธ
|
254 |
+
full_response = start_msg
|
255 |
+
|
256 |
+
# ์คํธ๋ฆฌ๋ฐ ์๋ต ์ฒ๋ฆฌ
|
257 |
+
for line in response.iter_lines():
|
258 |
+
if line:
|
259 |
+
line_text = line.decode('utf-8')
|
260 |
+
|
261 |
+
# 'data: ' ์ ๋์ฌ ์ ๊ฑฐ
|
262 |
+
if line_text.startswith("data: "):
|
263 |
+
line_text = line_text[6:]
|
264 |
+
|
265 |
+
# ์คํธ๋ฆผ ์ข
๋ฃ ๋ฉ์์ง ํ์ธ
|
266 |
+
if line_text == "[DONE]":
|
267 |
+
break
|
268 |
+
|
269 |
+
try:
|
270 |
+
# JSON ํ์ฑ
|
271 |
+
chunk = json.loads(line_text)
|
272 |
+
chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
|
273 |
+
|
274 |
+
if chunk_content:
|
275 |
+
full_response += chunk_content
|
276 |
+
# ์ฑํ
๊ธฐ๋ก ์
๋ฐ์ดํธ
|
277 |
+
new_history[-1] = (message, full_response)
|
278 |
+
yield new_history, ""
|
279 |
+
except json.JSONDecodeError:
|
280 |
+
continue
|
281 |
+
|
282 |
+
# ์ต์ข
์๋ต ๋ฐํ
|
283 |
+
yield new_history, ""
|
284 |
+
|
285 |
+
except requests.exceptions.RequestException as e:
|
286 |
+
error_msg = f"API ์ค๋ฅ: {str(e)}"
|
287 |
+
if hasattr(e, 'response') and e.response and e.response.status_code == 401:
|
288 |
+
error_msg = "์ธ์ฆ ์คํจ. ํ๊ฒฝ ๋ณ์ FW_API_KEY๋ฅผ ํ์ธํด์ฃผ์ธ์."
|
289 |
+
yield history, error_msg
|
290 |
+
|
291 |
+
# Gradio ์ธํฐํ์ด์ค ์์ฑ
|
292 |
+
with gr.Blocks(theme="soft", fill_height=True) as demo:
|
293 |
+
# ํค๋ ์น์
|
294 |
+
gr.Markdown(
|
295 |
+
"""
|
296 |
+
# ๐ค DeepSeek V3 ์คํธ๋ฆฌ๋ฐ ์ธํฐํ์ด์ค
|
297 |
+
### Fireworks AI๊ฐ ์ ๊ณตํ๋ ๊ณ ๊ธ AI ๋ชจ๋ธ - ์ค์๊ฐ ์๋ต ์ง์
|
298 |
+
"""
|
299 |
+
)
|
300 |
+
|
301 |
+
# ๋ฉ์ธ ๋ ์ด์์
|
302 |
+
with gr.Row():
|
303 |
+
# ๋ฉ์ธ ์ฝํ
์ธ ์์ญ
|
304 |
+
with gr.Column():
|
305 |
+
# ์ฑํ
์ธํฐํ์ด์ค
|
306 |
+
chatbot = gr.Chatbot(
|
307 |
+
height=500,
|
308 |
+
show_label=False,
|
309 |
+
container=True
|
310 |
+
)
|
311 |
+
|
312 |
+
# Deep Research ํ ๊ธ ๋ฐ ์ํ ํ์ ์ถ๊ฐ
|
313 |
+
with gr.Row():
|
314 |
+
with gr.Column(scale=3):
|
315 |
+
use_deep_research = gr.Checkbox(
|
316 |
+
label="Deep Research ํ์ฑํ",
|
317 |
+
info="์ต์ ์ ํค์๋ ์ถ์ถ ๋ฐ ์น ๊ฒ์์ ํตํ ์ต์ ์ ๋ณด ํ์ฉ",
|
318 |
+
value=False
|
319 |
+
)
|
320 |
+
with gr.Column(scale=1):
|
321 |
+
api_status = gr.Markdown("API ์ํ: ์ค๋น๋จ")
|
322 |
+
|
323 |
+
# API ํค ์ํ ํ์ธ ๋ฐ ํ์
|
324 |
+
if not serphouse_api_key:
|
325 |
+
api_status.value = "โ ๏ธ SERPHOUSE_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค"
|
326 |
+
if not api_key:
|
327 |
+
api_status.value = "โ ๏ธ FW_API_KEY๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค"
|
328 |
+
if api_key and serphouse_api_key:
|
329 |
+
api_status.value = "โ
API ํค ์ค์ ์๋ฃ"
|
330 |
+
|
331 |
+
# ์
๏ฟฝ๏ฟฝ๏ฟฝ ์์ญ
|
332 |
+
with gr.Row():
|
333 |
+
msg = gr.Textbox(
|
334 |
+
label="๋ฉ์์ง",
|
335 |
+
placeholder="์ฌ๊ธฐ์ ํ๋กฌํํธ๋ฅผ ์
๋ ฅํ์ธ์...",
|
336 |
+
show_label=False,
|
337 |
+
scale=9
|
338 |
+
)
|
339 |
+
submit = gr.Button("์ ์ก", variant="primary", scale=1)
|
340 |
+
|
341 |
+
# ๋ํ ์ด๊ธฐํ ๋ฒํผ
|
342 |
+
with gr.Row():
|
343 |
+
clear = gr.ClearButton([msg, chatbot], value="๐งน ๋ํ ์ด๊ธฐํ")
|
344 |
+
|
345 |
+
# ์์ ์ฟผ๋ฆฌ
|
346 |
+
gr.Examples(
|
347 |
+
examples=[
|
348 |
+
"๋ฅ๋ฌ๋์์ ํธ๋์คํฌ๋จธ์ RNN์ ์ฐจ์ด์ ์ ์ค๋ช
ํด์ฃผ์ธ์.",
|
349 |
+
"ํน์ ๋ฒ์ ๋ด์ ์์๋ฅผ ์ฐพ๋ ํ์ด์ฌ ํจ์๋ฅผ ์์ฑํด์ฃผ์ธ์.",
|
350 |
+
"๊ฐํํ์ต์ ์ฃผ์ ๊ฐ๋
์ ์์ฝํด์ฃผ์ธ์."
|
351 |
+
],
|
352 |
+
inputs=msg
|
353 |
+
)
|
354 |
+
|
355 |
+
# ์ค๋ฅ ๋ฉ์์ง ํ์
|
356 |
+
error_box = gr.Markdown("")
|
357 |
+
|
358 |
+
# ๋ฒํผ๊ณผ ๊ธฐ๋ฅ ์ฐ๊ฒฐ
|
359 |
+
submit.click(
|
360 |
+
query_deepseek_streaming,
|
361 |
+
inputs=[msg, chatbot, use_deep_research],
|
362 |
+
outputs=[chatbot, error_box]
|
363 |
+
).then(
|
364 |
+
lambda: "",
|
365 |
+
None,
|
366 |
+
[msg]
|
367 |
+
)
|
368 |
+
|
369 |
+
# Enter ํค ์ ์ถ ํ์ฉ
|
370 |
+
msg.submit(
|
371 |
+
query_deepseek_streaming,
|
372 |
+
inputs=[msg, chatbot, use_deep_research],
|
373 |
+
outputs=[chatbot, error_box]
|
374 |
+
).then(
|
375 |
+
lambda: "",
|
376 |
+
None,
|
377 |
+
[msg]
|
378 |
+
)
|
379 |
+
|
380 |
+
return demo
|
381 |
+
|
382 |
+
# ์ธํฐํ์ด์ค ์คํ
|
383 |
+
if __name__ == "__main__":
|
384 |
+
demo = create_deepseek_interface()
|
385 |
+
demo.launch(debug=True)
|