openfree commited on
Commit
434dc20
ยท
verified ยท
1 Parent(s): 1d68b76

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -121
app.py CHANGED
@@ -5,34 +5,34 @@ 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",
@@ -51,41 +51,41 @@ def create_deepseek_interface():
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
  }
@@ -94,138 +94,138 @@ def create_deepseek_interface():
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
- # ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํŒŒ์‹ฑ ๋ฐ ํฌ๋งทํŒ… (Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ)
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 i, result in enumerate(organic_results[:5], 1): # ์ƒ์œ„ 5๊ฐœ ๊ฒฐ๊ณผ๋งŒ ํ‘œ์‹œ
137
- title = result.get("title", "์ œ๋ชฉ ์—†์Œ")
138
- snippet = result.get("snippet", "๋‚ด์šฉ ์—†์Œ")
139
  link = result.get("link", "#")
140
  displayed_link = result.get("displayed_link", link)
141
 
142
- # Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ (๋ฒˆํ˜ธ ๋ฐ ๋งํฌ ํฌํ•จ)
143
  formatted_results.append(
144
  f"### {i}. [{title}]({link})\n\n"
145
  f"{snippet}\n\n"
146
- f"**์ถœ์ฒ˜**: [{displayed_link}]({link})\n\n"
147
  f"---\n\n"
148
  )
149
 
150
- print(f"๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ {len(organic_results)}๊ฐœ ์ฐพ์Œ")
151
  return "".join(formatted_results)
152
 
153
- # ๊ฒฐ๊ณผ๊ฐ€ ์—†๊ฑฐ๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ตฌ์กฐ์ธ ๊ฒฝ์šฐ
154
- print("๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์—†์Œ ๋˜๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์‘๋‹ต ๊ตฌ์กฐ")
155
- print(f"์‘๋‹ต ๊ตฌ์กฐ ์ƒ์„ธ: {search_results.keys() if hasattr(search_results, 'keys') else '๋ถˆ๋ช…ํ™•ํ•œ ๊ตฌ์กฐ'}")
156
 
157
- # ์‘๋‹ต ๋‚ด์šฉ์—์„œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ฐพ๊ธฐ
158
- error_msg = "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†๊ฑฐ๋‚˜ ์‘๋‹ต ํ˜•์‹์ด ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค"
159
  if "error" in search_results:
160
  error_msg = search_results["error"]
161
  elif "message" in search_results:
162
  error_msg = search_results["message"]
163
 
164
- return f"## ๊ฒ€์ƒ‰์–ด '{search_query}'์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ\n\n{error_msg}"
165
 
166
  except Exception as e:
167
- error_msg = f"๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
168
  print(error_msg)
169
  import traceback
170
  print(traceback.format_exc())
171
 
172
- # ๋””๋ฒ„๊น… ๋ชฉ์ ์œผ๋กœ API ์š”์ฒญ ์ƒ์„ธ ์ •๋ณด ์ถ”๊ฐ€ (Markdown ํ˜•์‹)
173
- return f"## ์˜ค๋ฅ˜ ๋ฐœ์ƒ\n\n" + \
174
- f"๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: **{str(e)}**\n\n" + \
175
- f"### API ์š”์ฒญ ์ƒ์„ธ ์ •๋ณด:\n" + \
176
  f"- **URL**: {url}\n" + \
177
- f"- **๊ฒ€์ƒ‰์–ด**: {search_query}\n" + \
178
- f"- **ํŒŒ๋ผ๋ฏธํ„ฐ**: {params}\n"
179
 
180
- # ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ DeepSeek API ํ˜ธ์ถœ ํ•จ์ˆ˜
181
  def query_deepseek_streaming(message, history, use_deep_research):
182
  if not api_key:
183
- yield history, "ํ™˜๊ฒฝ ๋ณ€์ˆ˜ FW_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
184
  return
185
 
186
  search_context = ""
187
  search_info = ""
188
  if use_deep_research:
189
  try:
190
- # ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ (์ฒซ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ)
191
- yield history + [(message, "๐Ÿ” ์ตœ์ ์˜ ํ‚ค์›Œ๋“œ ์ถ”์ถœ ๋ฐ ์›น ๊ฒ€์ƒ‰ ์ค‘...")], ""
192
 
193
- # ๊ฒ€์ƒ‰ ์‹คํ–‰ - ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ๋กœ๊ทธ ์ถ”๊ฐ€
194
- print(f"Deep Research ํ™œ์„ฑํ™”๋จ: ๋ฉ”์‹œ์ง€ '{message}'์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰ ์‹œ์ž‘")
195
  search_results = search_with_serphouse(message)
196
- print(f"๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ˆ˜์‹  ์™„๋ฃŒ: {search_results[:100]}...") # ๊ฒฐ๊ณผ ์•ž๋ถ€๋ถ„๋งŒ ์ถœ๋ ฅ
197
 
198
- if not search_results.startswith("๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ") and not search_results.startswith("SERPHOUSE_API_KEY"):
199
  search_context = f"""
200
- ๋‹ค์Œ์€ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ์ตœ์‹  ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ •ํ™•ํ•˜๊ณ  ์ตœ์‹  ์ •๋ณด๊ฐ€ ๋ฐ˜์˜๋œ ์‘๋‹ต์„ ์ œ๊ณตํ•˜์„ธ์š”:
201
 
202
  {search_results}
203
 
204
- ์œ„ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ๋‹ค์Œ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•˜์„ธ์š”. ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์—์„œ ๋ช…ํ™•ํ•œ ๋‹ต๋ณ€์„ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ๋‹น์‹ ์˜ ์ง€์‹์„ ํ™œ์šฉํ•˜์—ฌ ์ตœ์„ ์˜ ๋‹ต๋ณ€์„ ์ œ๊ณตํ•˜์„ธ์š”.
205
- ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ธ์šฉํ•  ๋•Œ๋Š” ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•˜๊ณ , ๋‹ต๋ณ€์ด ์ตœ์‹  ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•˜๋„๋ก ํ•˜์„ธ์š”.
206
  """
207
- search_info = f"๐Ÿ” Deep Research ๊ธฐ๋Šฅ ํ™œ์„ฑํ™”: ๊ด€๋ จ ์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‘๋‹ต ์ƒ์„ฑ ์ค‘..."
208
  else:
209
- print(f"๊ฒ€์ƒ‰ ์‹คํŒจ ๋˜๋Š” ๊ฒฐ๊ณผ ์—†์Œ: {search_results}")
210
  except Exception as e:
211
- print(f"Deep Research ์ฒ˜๋ฆฌ ์ค‘ ์˜ˆ์™ธ ๋ฐœ์ƒ: {str(e)}")
212
- search_info = f"๐Ÿ” Deep Research ๊ธฐ๋Šฅ ์˜ค๋ฅ˜: {str(e)}"
213
 
214
- # API ์š”์ฒญ์„ ์œ„ํ•œ ๋Œ€ํ™” ๊ธฐ๋ก ์ค€๋น„
215
  messages = []
216
  for user, assistant in history:
217
  messages.append({"role": "user", "content": user})
218
  messages.append({"role": "assistant", "content": assistant})
219
 
220
- # ๊ฒ€์ƒ‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
221
  if search_context:
222
- # DeepSeek ๋ชจ๋ธ์€ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค
223
  messages.insert(0, {"role": "system", "content": search_context})
224
 
225
- # ์ƒˆ ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
226
  messages.append({"role": "user", "content": message})
227
 
228
- # API ์š”์ฒญ ์ค€๋น„
229
  url = "https://api.fireworks.ai/inference/v1/chat/completions"
230
  payload = {
231
  "model": "accounts/fireworks/models/deepseek-v3-0324",
@@ -236,7 +236,7 @@ def create_deepseek_interface():
236
  "frequency_penalty": 0,
237
  "temperature": 0.6,
238
  "messages": messages,
239
- "stream": True # ์ŠคํŠธ๋ฆฌ๋ฐ ํ™œ์„ฑํ™”
240
  }
241
  headers = {
242
  "Accept": "application/json",
@@ -245,123 +245,123 @@ def create_deepseek_interface():
245
  }
246
 
247
  try:
248
- # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์š”์ฒญ
249
  response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
250
- response.raise_for_status() # HTTP ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์˜ˆ์™ธ ๋ฐœ์ƒ
251
 
252
- # ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ดˆ๊ธฐ ์‘๋‹ต์œผ๋กœ ์‹œ์ž‘
253
  new_history = history.copy()
254
 
255
- # search_info๊ฐ€ ์žˆ์œผ๋ฉด ์‹œ์ž‘ ๋ฉ”์‹œ์ง€์— ํฌํ•จ
256
  start_msg = search_info if search_info else ""
257
  new_history.append((message, start_msg))
258
 
259
- # ์‘๋‹ต ์ „์ฒด ํ…์ŠคํŠธ
260
  full_response = start_msg
261
 
262
- # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
263
  for line in response.iter_lines():
264
  if line:
265
  line_text = line.decode('utf-8')
266
 
267
- # 'data: ' ์ ‘๋‘์‚ฌ ์ œ๊ฑฐ
268
  if line_text.startswith("data: "):
269
  line_text = line_text[6:]
270
 
271
- # ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ๋ฉ”์‹œ์ง€ ํ™•์ธ
272
  if line_text == "[DONE]":
273
  break
274
 
275
  try:
276
- # JSON ํŒŒ์‹ฑ
277
  chunk = json.loads(line_text)
278
  chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
279
 
280
  if chunk_content:
281
  full_response += chunk_content
282
- # ์ฑ„ํŒ… ๊ธฐ๋ก ์—…๋ฐ์ดํŠธ
283
  new_history[-1] = (message, full_response)
284
  yield new_history, ""
285
  except json.JSONDecodeError:
286
  continue
287
 
288
- # ์ตœ์ข… ์‘๋‹ต ๋ฐ˜ํ™˜
289
  yield new_history, ""
290
 
291
  except requests.exceptions.RequestException as e:
292
- error_msg = f"API ์˜ค๋ฅ˜: {str(e)}"
293
  if hasattr(e, 'response') and e.response and e.response.status_code == 401:
294
- error_msg = "์ธ์ฆ ์‹คํŒจ. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ FW_API_KEY๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
295
  yield history, error_msg
296
 
297
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
298
  with gr.Blocks(theme="soft", fill_height=True) as demo:
299
- # ํ—ค๋” ์„น์…˜
300
  gr.Markdown(
301
  """
302
- # ๐Ÿค– DeepSeek V3-0324 + Reserach
303
- ### DeepSeek V3-0324 ์ตœ์‹  ๋ชจ๋ธ + ์‹ค์‹œ๊ฐ„ 'Deep Research' Agentic AI ์‹œ์Šคํ…œ @ https://discord.gg/openfreeai
304
  """
305
  )
306
 
307
- # ๋ฉ”์ธ ๋ ˆ์ด์•„์›ƒ
308
  with gr.Row():
309
- # ๋ฉ”์ธ ์ฝ˜ํ…์ธ  ์˜์—ญ
310
  with gr.Column():
311
- # ์ฑ„ํŒ… ์ธํ„ฐํŽ˜์ด์Šค
312
  chatbot = gr.Chatbot(
313
  height=500,
314
  show_label=False,
315
  container=True
316
  )
317
 
318
- # Deep Research ํ† ๊ธ€ ๋ฐ ์ƒํƒœ ํ‘œ์‹œ ์ถ”๊ฐ€
319
  with gr.Row():
320
  with gr.Column(scale=3):
321
  use_deep_research = gr.Checkbox(
322
- label="Deep Research ํ™œ์„ฑํ™”",
323
- info="์ตœ์ ์˜ ํ‚ค์›Œ๋“œ ์ถ”์ถœ ๋ฐ ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ์ตœ์‹  ์ •๋ณด ํ™œ์šฉ",
324
  value=False
325
  )
326
  with gr.Column(scale=1):
327
- api_status = gr.Markdown("API ์ƒํƒœ: ์ค€๋น„๋จ")
328
 
329
- # API ํ‚ค ์ƒํƒœ ํ™•์ธ ๋ฐ ํ‘œ์‹œ
330
  if not serphouse_api_key:
331
- api_status.value = "โš ๏ธ SERPHOUSE_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค"
332
  if not api_key:
333
- api_status.value = "โš ๏ธ FW_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค"
334
  if api_key and serphouse_api_key:
335
- api_status.value = "โœ… API ํ‚ค ์„ค์ • ์™„๋ฃŒ"
336
 
337
- # ์ž…๋ ฅ ์˜์—ญ
338
  with gr.Row():
339
  msg = gr.Textbox(
340
- label="๋ฉ”์‹œ์ง€",
341
- placeholder="์—ฌ๊ธฐ์— ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”...",
342
  show_label=False,
343
  scale=9
344
  )
345
- submit = gr.Button("์ „์†ก", variant="primary", scale=1)
346
 
347
- # ๋Œ€ํ™” ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ
348
  with gr.Row():
349
- clear = gr.ClearButton([msg, chatbot], value="๐Ÿงน ๋Œ€ํ™” ์ดˆ๊ธฐํ™”")
350
 
351
- # ์˜ˆ์ œ ์ฟผ๋ฆฌ
352
  gr.Examples(
353
  examples=[
354
- "๋”ฅ๋Ÿฌ๋‹์—์„œ ํŠธ๋žœ์Šคํฌ๋จธ์™€ RNN์˜ ์ฐจ์ด์ ์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.",
355
- "ํŠน์ • ๋ฒ”์œ„ ๋‚ด์˜ ์†Œ์ˆ˜๋ฅผ ์ฐพ๋Š” ํŒŒ์ด์ฌ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.",
356
- "๊ฐ•ํ™”ํ•™์Šต์˜ ์ฃผ์š” ๊ฐœ๋…์„ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
357
  ],
358
  inputs=msg
359
  )
360
 
361
- # ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
362
  error_box = gr.Markdown("")
363
 
364
- # ๋ฒ„ํŠผ๊ณผ ๊ธฐ๋Šฅ ์—ฐ๊ฒฐ
365
  submit.click(
366
  query_deepseek_streaming,
367
  inputs=[msg, chatbot, use_deep_research],
@@ -372,7 +372,7 @@ def create_deepseek_interface():
372
  [msg]
373
  )
374
 
375
- # Enter ํ‚ค ์ œ์ถœ ํ—ˆ์šฉ
376
  msg.submit(
377
  query_deepseek_streaming,
378
  inputs=[msg, chatbot, use_deep_research],
@@ -385,7 +385,7 @@ def create_deepseek_interface():
385
 
386
  return demo
387
 
388
- # ์ธํ„ฐํŽ˜์ด์Šค ์‹คํ–‰
389
  if __name__ == "__main__":
390
  demo = create_deepseek_interface()
391
  demo.launch(debug=True)
 
5
  import time
6
  from dotenv import load_dotenv
7
 
8
+ # Load .env file (if it exists)
9
  load_dotenv()
10
 
11
  def create_deepseek_interface():
12
+ # Get API keys from environment variables
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("Warning: FW_API_KEY environment variable is not set.")
18
  if not serphouse_api_key:
19
+ print("Warning: SERPHOUSE_API_KEY environment variable is not set.")
20
 
21
+ # Keyword extraction function (LLM-based)
22
  def extract_keywords_with_llm(query):
23
  if not api_key:
24
+ return "FW_API_KEY not set for LLM keyword extraction.", query
25
 
26
+ # Extract keywords using LLM (DeepSeek model)
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, # Low temperature for consistent results
32
  "messages": [
33
  {
34
  "role": "system",
35
+ "content": "Extract key search terms from the user's question that would be effective for web searches. Provide these as a search query with words separated by spaces only, without commas. For example: 'Prime Minister Han Duck-soo impeachment results'"
36
  },
37
  {
38
  "role": "user",
 
51
  response.raise_for_status()
52
  result = response.json()
53
 
54
+ # Extract keywords from response
55
  keywords = result["choices"][0]["message"]["content"].strip()
56
 
57
+ # Use original query if keywords are too long or improperly formatted
58
  if len(keywords) > 100:
59
+ return f"Extracted keywords: {keywords}", query
60
 
61
+ return f"Extracted keywords: {keywords}", keywords
62
 
63
  except Exception as e:
64
+ print(f"Error during keyword extraction: {str(e)}")
65
+ return f"Error during keyword extraction: {str(e)}", query
66
 
67
+ # Search function using SerpHouse API
68
  def search_with_serphouse(query):
69
  if not serphouse_api_key:
70
+ return "SERPHOUSE_API_KEY is not set."
71
 
72
  try:
73
+ # Extract keywords
74
  extraction_result, search_query = extract_keywords_with_llm(query)
75
+ print(f"Original query: {query}")
76
  print(extraction_result)
77
 
78
+ # Basic GET method seems best after analyzing documentation
79
  url = "https://api.serphouse.com/serp/live"
80
 
81
+ # Check if query is in Korean
82
  is_korean = any('\uAC00' <= c <= '\uD7A3' for c in search_query)
83
 
84
+ # Simplified parameters
85
  params = {
86
  "q": search_query,
87
  "domain": "google.com",
88
+ "serp_type": "web", # Changed to basic web search
89
  "device": "desktop",
90
  "lang": "ko" if is_korean else "en"
91
  }
 
94
  "Authorization": f"Bearer {serphouse_api_key}"
95
  }
96
 
97
+ print(f"Calling SerpHouse API with basic GET method...")
98
+ print(f"Search term: {search_query}")
99
+ print(f"Request URL: {url} - Parameters: {params}")
100
 
101
+ # Execute GET request
102
  response = requests.get(url, headers=headers, params=params)
103
  response.raise_for_status()
104
 
105
+ print(f"SerpHouse API response status code: {response.status_code}")
106
  search_results = response.json()
107
 
108
+ # Check response structure
109
+ print(f"Response structure: {list(search_results.keys()) if isinstance(search_results, dict) else 'Not a dictionary'}")
110
 
111
+ # Parse and format search results (in Markdown)
112
  formatted_results = []
113
+ formatted_results.append(f"## Search term: {search_query}\n\n")
114
 
115
+ # Handle various possible response structures
116
  organic_results = None
117
 
118
+ # Possible response structure 1
119
  if "results" in search_results and "organic" in search_results["results"]:
120
  organic_results = search_results["results"]["organic"]
121
 
122
+ # Possible response structure 2
123
  elif "organic" in search_results:
124
  organic_results = search_results["organic"]
125
 
126
+ # Possible response structure 3 (nested 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
+ # Process organic results if available
132
  if organic_results and len(organic_results) > 0:
133
+ # Output response structure
134
+ print(f"First organic result structure: {organic_results[0].keys() if len(organic_results) > 0 else 'empty'}")
135
 
136
+ for i, result in enumerate(organic_results[:5], 1): # Show only top 5 results
137
+ title = result.get("title", "No title")
138
+ snippet = result.get("snippet", "No content")
139
  link = result.get("link", "#")
140
  displayed_link = result.get("displayed_link", link)
141
 
142
+ # Format in Markdown (including number and link)
143
  formatted_results.append(
144
  f"### {i}. [{title}]({link})\n\n"
145
  f"{snippet}\n\n"
146
+ f"**Source**: [{displayed_link}]({link})\n\n"
147
  f"---\n\n"
148
  )
149
 
150
+ print(f"Found {len(organic_results)} search results")
151
  return "".join(formatted_results)
152
 
153
+ # Handle case with no results or unexpected structure
154
+ print("No search results or unexpected response structure")
155
+ print(f"Detailed response structure: {search_results.keys() if hasattr(search_results, 'keys') else 'Unclear structure'}")
156
 
157
+ # Find error messages in response
158
+ error_msg = "No search results found or response format is different than expected"
159
  if "error" in search_results:
160
  error_msg = search_results["error"]
161
  elif "message" in search_results:
162
  error_msg = search_results["message"]
163
 
164
+ return f"## Results for '{search_query}'\n\n{error_msg}"
165
 
166
  except Exception as e:
167
+ error_msg = f"Error during search: {str(e)}"
168
  print(error_msg)
169
  import traceback
170
  print(traceback.format_exc())
171
 
172
+ # Add API request details for debugging (in Markdown)
173
+ return f"## Error Occurred\n\n" + \
174
+ f"An error occurred during search: **{str(e)}**\n\n" + \
175
+ f"### API Request Details:\n" + \
176
  f"- **URL**: {url}\n" + \
177
+ f"- **Search Term**: {search_query}\n" + \
178
+ f"- **Parameters**: {params}\n"
179
 
180
+ # Function to call DeepSeek API with streaming
181
  def query_deepseek_streaming(message, history, use_deep_research):
182
  if not api_key:
183
+ yield history, "Environment variable FW_API_KEY is not set. Please check the environment variables on the server."
184
  return
185
 
186
  search_context = ""
187
  search_info = ""
188
  if use_deep_research:
189
  try:
190
+ # Start search (first message)
191
+ yield history + [(message, "๐Ÿ” Extracting optimal keywords and searching the web...")], ""
192
 
193
+ # Execute search - add logs for debugging
194
+ print(f"Deep Research activated: Starting search for '{message}'")
195
  search_results = search_with_serphouse(message)
196
+ print(f"Search results received: {search_results[:100]}...") # Output first part of results
197
 
198
+ if not search_results.startswith("Error during search") and not search_results.startswith("SERPHOUSE_API_KEY"):
199
  search_context = f"""
200
+ Here are recent search results related to the user's question. Use this information to provide an accurate response with the latest information:
201
 
202
  {search_results}
203
 
204
+ Based on the above search results, answer the user's question. If you cannot find a clear answer in the search results, use your knowledge to provide the best answer.
205
+ When citing search results, mention the source, and ensure your answer reflects the latest information.
206
  """
207
+ search_info = f"๐Ÿ” Deep Research feature activated: Generating response based on relevant web search results..."
208
  else:
209
+ print(f"Search failed or no results: {search_results}")
210
  except Exception as e:
211
+ print(f"Exception occurred during Deep Research: {str(e)}")
212
+ search_info = f"๐Ÿ” Deep Research feature error: {str(e)}"
213
 
214
+ # Prepare conversation history for API request
215
  messages = []
216
  for user, assistant in history:
217
  messages.append({"role": "user", "content": user})
218
  messages.append({"role": "assistant", "content": assistant})
219
 
220
+ # Add system message with search context if available
221
  if search_context:
222
+ # DeepSeek model supports system messages
223
  messages.insert(0, {"role": "system", "content": search_context})
224
 
225
+ # Add new user message
226
  messages.append({"role": "user", "content": message})
227
 
228
+ # Prepare API request
229
  url = "https://api.fireworks.ai/inference/v1/chat/completions"
230
  payload = {
231
  "model": "accounts/fireworks/models/deepseek-v3-0324",
 
236
  "frequency_penalty": 0,
237
  "temperature": 0.6,
238
  "messages": messages,
239
+ "stream": True # Enable streaming
240
  }
241
  headers = {
242
  "Accept": "application/json",
 
245
  }
246
 
247
  try:
248
+ # Request streaming response
249
  response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True)
250
+ response.raise_for_status() # Raise exception for HTTP errors
251
 
252
+ # Add message and start with initial response
253
  new_history = history.copy()
254
 
255
+ # Include search_info in starting message if available
256
  start_msg = search_info if search_info else ""
257
  new_history.append((message, start_msg))
258
 
259
+ # Full response text
260
  full_response = start_msg
261
 
262
+ # Process streaming response
263
  for line in response.iter_lines():
264
  if line:
265
  line_text = line.decode('utf-8')
266
 
267
+ # Remove 'data: ' prefix
268
  if line_text.startswith("data: "):
269
  line_text = line_text[6:]
270
 
271
+ # Check for stream end message
272
  if line_text == "[DONE]":
273
  break
274
 
275
  try:
276
+ # Parse JSON
277
  chunk = json.loads(line_text)
278
  chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
279
 
280
  if chunk_content:
281
  full_response += chunk_content
282
+ # Update chat history
283
  new_history[-1] = (message, full_response)
284
  yield new_history, ""
285
  except json.JSONDecodeError:
286
  continue
287
 
288
+ # Return final response
289
  yield new_history, ""
290
 
291
  except requests.exceptions.RequestException as e:
292
+ error_msg = f"API error: {str(e)}"
293
  if hasattr(e, 'response') and e.response and e.response.status_code == 401:
294
+ error_msg = "Authentication failed. Please check your FW_API_KEY environment variable."
295
  yield history, error_msg
296
 
297
+ # Create Gradio interface
298
  with gr.Blocks(theme="soft", fill_height=True) as demo:
299
+ # Header section
300
  gr.Markdown(
301
  """
302
+ # ๐Ÿค– DeepSeek V3-0324 + Research
303
+ ### DeepSeek V3-0324 Latest Model + Real-time 'Deep Research' Agentic AI System @ https://discord.gg/openfreeai
304
  """
305
  )
306
 
307
+ # Main layout
308
  with gr.Row():
309
+ # Main content area
310
  with gr.Column():
311
+ # Chat interface
312
  chatbot = gr.Chatbot(
313
  height=500,
314
  show_label=False,
315
  container=True
316
  )
317
 
318
+ # Add Deep Research toggle and status display
319
  with gr.Row():
320
  with gr.Column(scale=3):
321
  use_deep_research = gr.Checkbox(
322
+ label="Enable Deep Research",
323
+ info="Utilize optimal keyword extraction and web search for latest information",
324
  value=False
325
  )
326
  with gr.Column(scale=1):
327
+ api_status = gr.Markdown("API Status: Ready")
328
 
329
+ # Check and display API key status
330
  if not serphouse_api_key:
331
+ api_status.value = "โš ๏ธ SERPHOUSE_API_KEY is not set"
332
  if not api_key:
333
+ api_status.value = "โš ๏ธ FW_API_KEY is not set"
334
  if api_key and serphouse_api_key:
335
+ api_status.value = "โœ… API keys configured"
336
 
337
+ # Input area
338
  with gr.Row():
339
  msg = gr.Textbox(
340
+ label="Message",
341
+ placeholder="Enter your prompt here...",
342
  show_label=False,
343
  scale=9
344
  )
345
+ submit = gr.Button("Send", variant="primary", scale=1)
346
 
347
+ # Clear conversation button
348
  with gr.Row():
349
+ clear = gr.ClearButton([msg, chatbot], value="๐Ÿงน Clear Conversation")
350
 
351
+ # Example queries
352
  gr.Examples(
353
  examples=[
354
+ "Explain the difference between Transformers and RNNs in deep learning.",
355
+ "Write a Python function to find prime numbers within a specific range.",
356
+ "Summarize the key concepts of reinforcement learning."
357
  ],
358
  inputs=msg
359
  )
360
 
361
+ # Error message display
362
  error_box = gr.Markdown("")
363
 
364
+ # Connect buttons to functions
365
  submit.click(
366
  query_deepseek_streaming,
367
  inputs=[msg, chatbot, use_deep_research],
 
372
  [msg]
373
  )
374
 
375
+ # Allow Enter key submission
376
  msg.submit(
377
  query_deepseek_streaming,
378
  inputs=[msg, chatbot, use_deep_research],
 
385
 
386
  return demo
387
 
388
+ # Run interface
389
  if __name__ == "__main__":
390
  demo = create_deepseek_interface()
391
  demo.launch(debug=True)