ginipick commited on
Commit
9696775
ยท
verified ยท
1 Parent(s): 2a0f996

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +256 -324
app.py CHANGED
@@ -7,9 +7,6 @@ from huggingface_hub import HfApi
7
  import requests
8
  import re
9
  import traceback
10
- import time
11
- import threading
12
- import json
13
 
14
  # HuggingFace ๊ด€๋ จ API ํ‚ค (์ŠคํŽ˜์ด์Šค ๋ถ„์„ ์šฉ)
15
  HF_TOKEN = os.getenv("HF_TOKEN")
@@ -20,9 +17,6 @@ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
20
  genai.configure(api_key=GEMINI_API_KEY)
21
  model = genai.GenerativeModel("gemini-2.0-flash-thinking-exp-01-21")
22
 
23
- # --------------------------------------------------
24
- # ํŒŒ์ผ ๋ฐ ์ŠคํŽ˜์ด์Šค ๋ถ„์„ ๊ด€๋ จ ํ•จ์ˆ˜๋“ค (๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€)
25
- # --------------------------------------------------
26
  def get_headers():
27
  if not HF_TOKEN:
28
  raise ValueError("Hugging Face token not found in environment variables")
@@ -74,10 +68,6 @@ def format_tree_structure(tree_data: Dict, indent: str = "") -> str:
74
  formatted += format_tree_structure(child, indent + " ")
75
  return formatted
76
 
77
- def adjust_lines_for_code(code_content: str, min_lines: int = 10, max_lines: int = 100) -> int:
78
- num_lines = len(code_content.split('\n'))
79
- return min(max(num_lines, min_lines), max_lines)
80
-
81
  def analyze_space(url: str, progress=gr.Progress()):
82
  try:
83
  space_id = url.split('spaces/')[-1]
@@ -96,58 +86,82 @@ def analyze_space(url: str, progress=gr.Progress()):
96
  analysis = analyze_code(app_content)
97
  progress(0.9, desc="์‚ฌ์šฉ๋ฒ• ์„ค๋ช… ์ƒ์„ฑ ์ค‘...")
98
  usage = explain_usage(app_content)
99
- app_py_lines = adjust_lines_for_code(app_content)
 
100
  progress(1.0, desc="์™„๋ฃŒ")
101
- return app_content, tree_view, tree_structure, space_id, summary, analysis, usage, app_py_lines
102
  except Exception as e:
103
  print(f"Error in analyze_space: {str(e)}")
104
  print(traceback.format_exc())
105
  return f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}", "", None, "", "", "", "", 10
106
 
107
- # --------------------------------------------------
108
- # Gemini 2.0 Flash Thinking ๋ชจ๋ธ ๊ด€๋ จ ํ—ฌํผ ํ•จ์ˆ˜๋“ค
109
- # --------------------------------------------------
 
 
 
 
 
 
110
  def format_chat_history(messages: List[ChatMessage]) -> List[Dict]:
111
- formatted_history = []
112
- for message in messages:
113
- # thinking ๋ฉ”์‹œ์ง€(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์žˆ๋Š” ๋ฉ”์‹œ์ง€)๋Š” ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.
114
- if not (hasattr(message, "metadata") and message.metadata):
115
- formatted_history.append({
116
- "role": "user" if message.role == "user" else "assistant",
117
- "parts": [message.content or ""]
118
- })
119
- return formatted_history
120
-
121
- def gemini_chat_completion(system_message: str, user_message: str, max_tokens: int = 200, temperature: float = 0.7) -> str:
122
- initial_messages = [
 
 
 
 
 
 
 
 
 
 
 
123
  ChatMessage(role="system", content=system_message),
124
  ChatMessage(role="user", content=user_message)
125
  ]
126
- chat_history = format_chat_history(initial_messages)
127
  chat = model.start_chat(history=chat_history)
128
- final_response = ""
129
  try:
130
  for chunk in chat.send_message(user_message, stream=True):
131
  parts = chunk.candidates[0].content.parts
132
  if len(parts) == 2:
133
- final_response += parts[1].text
 
134
  else:
135
- final_response += parts[0].text
136
- return final_response.strip()
 
137
  except Exception as e:
138
  return f"LLM ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
139
 
140
- def summarize_code(app_content: str) -> str:
141
- system_message = "๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์š”์•ฝํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ 3์ค„ ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
142
- user_message = f"๋‹ค์Œ Python ์ฝ”๋“œ๋ฅผ 3์ค„ ์ด๋‚ด๋กœ ์š”์•ฝํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
143
  try:
144
- return gemini_chat_completion(system_message, user_message, max_tokens=200, temperature=0.7)
145
  except Exception as e:
146
  return f"์š”์•ฝ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
147
 
148
- def analyze_code(app_content: str) -> str:
149
- system_message = (
150
- "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. ๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์„œ๋น„์Šค์˜ ํšจ์šฉ์„ฑ๊ณผ ํ™œ์šฉ ์ธก๋ฉด์—์„œ ๋‹ค์Œ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\n"
 
 
 
 
151
  "A. ๋ฐฐ๊ฒฝ ๋ฐ ํ•„์š”์„ฑ\n"
152
  "B. ๊ธฐ๋Šฅ์  ํšจ์šฉ์„ฑ ๋ฐ ๊ฐ€์น˜\n"
153
  "C. ํŠน์žฅ์ \n"
@@ -155,328 +169,247 @@ def analyze_code(app_content: str) -> str:
155
  "E. ๊ธฐ๋Œ€ํšจ๊ณผ\n"
156
  "๊ธฐ์กด ๋ฐ ์œ ์‚ฌ ํ”„๋กœ์ ํŠธ์™€ ๋น„๊ตํ•˜์—ฌ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”. Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”."
157
  )
158
- user_message = f"๋‹ค์Œ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
159
  try:
160
- return gemini_chat_completion(system_message, user_message, max_tokens=1000, temperature=0.7)
161
  except Exception as e:
162
  return f"๋ถ„์„ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
163
 
164
- def explain_usage(app_content: str) -> str:
165
- system_message = "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. ๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์‚ฌ์šฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งˆ์น˜ ํ™”๋ฉด์„ ๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋ฒ•์„ ์ƒ์„ธํžˆ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”."
166
- user_message = f"๋‹ค์Œ Python ์ฝ”๋“œ์˜ ์‚ฌ์šฉ๋ฒ•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
 
 
 
 
 
 
167
  try:
168
- return gemini_chat_completion(system_message, user_message, max_tokens=800, temperature=0.7)
169
  except Exception as e:
170
  return f"์‚ฌ์šฉ๋ฒ• ์„ค๋ช… ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
171
 
172
- def flatten_messages(messages: List[Any]) -> List[Any]:
 
 
 
173
  """
174
- ์ค‘์ฒฉ๋œ ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ‰ํƒ„ํ™”ํ•ฉ๋‹ˆ๋‹ค.
175
  """
176
- flat = []
177
- for item in messages:
178
- if isinstance(item, list):
179
- flat.extend(flatten_messages(item))
180
- else:
181
- flat.append(item)
182
- return flat
183
-
184
- def convert_chat_history(messages: List[Any]) -> List[Tuple[str, str]]:
185
- """
186
- ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก์˜ ๊ฐ ํ•ญ๋ชฉ์ด ChatMessage ๊ฐ์ฒด๋ผ๋ฉด (user, assistant) ํŠœํ”Œ๋กœ,
187
- ์ด๋ฏธ ํŠœํ”Œ์ธ ๊ฒฝ์šฐ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
188
- """
189
- flat_messages = flatten_messages(messages)
190
- conv = []
191
- i = 0
192
- while i < len(flat_messages):
193
- if isinstance(flat_messages[i], tuple):
194
- conv.append(flat_messages[i])
195
- i += 1
196
- elif hasattr(flat_messages[i], "role"):
197
- if flat_messages[i].role == "user":
198
- user_text = flat_messages[i].content
199
- bot_text = ""
200
- if i + 1 < len(flat_messages) and hasattr(flat_messages[i+1], "role") and flat_messages[i+1].role == "assistant":
201
- bot_text = flat_messages[i+1].content
202
- i += 2
203
- else:
204
- i += 1
205
- conv.append((user_text, bot_text))
206
- else:
207
- conv.append(("", flat_messages[i].content))
208
- i += 1
209
- else:
210
- i += 1
211
- return conv
212
-
213
- def convert_to_chatmessage(history: List[Tuple[str, str]]) -> List[ChatMessage]:
214
- """
215
- ํŠœํ”Œ ๋ชฉ๋ก์„ ChatMessage ๊ฐ์ฒด ๋ชฉ๋ก์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
216
- """
217
- new_history = []
218
- for tup in history:
219
- if tup[0]:
220
- new_history.append(ChatMessage(role="user", content=tup[0]))
221
- if tup[1]:
222
- new_history.append(ChatMessage(role="assistant", content=tup[1]))
223
- return new_history
224
-
225
- def stream_gemini_response(user_message: str, messages: List[ChatMessage]) -> Iterator[List[ChatMessage]]:
226
  if not user_message.strip():
227
- messages.append(ChatMessage(role="assistant", content="Please provide a non-empty text message. Empty input is not allowed."))
228
- yield messages
 
 
229
  return
230
 
231
- try:
232
- print(f"\n=== New Request (Text) ===")
233
- print(f"User message: {user_message}")
234
- chat_history = format_chat_history(messages)
235
- chat = model.start_chat(history=chat_history)
236
- response = chat.send_message(user_message, stream=True)
237
- thought_buffer = ""
238
- response_buffer = ""
239
- thinking_complete = False
240
-
241
- messages.append(
242
- ChatMessage(
243
- role="assistant",
244
- content="",
245
- metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
246
- )
 
247
  )
 
248
 
249
- for chunk in response:
250
- parts = chunk.candidates[0].content.parts
251
- current_chunk = parts[0].text
252
-
253
- if len(parts) == 2 and not thinking_complete:
254
- thought_buffer += current_chunk
255
- print(f"\n=== Complete Thought ===\n{thought_buffer}")
256
- messages[-1] = ChatMessage(
257
- role="assistant",
258
- content=thought_buffer,
259
- metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
260
- )
261
- yield messages
262
-
263
- response_buffer = parts[1].text
264
- print(f"\n=== Starting Response ===\n{response_buffer}")
265
- messages.append(
266
- ChatMessage(
267
- role="assistant",
268
- content=response_buffer
269
- )
270
- )
271
- thinking_complete = True
272
 
273
- elif thinking_complete:
274
- response_buffer += current_chunk
275
- print(f"\n=== Response Chunk ===\n{current_chunk}")
276
- messages[-1] = ChatMessage(
277
- role="assistant",
278
- content=response_buffer
279
- )
 
 
 
280
 
281
- else:
282
- thought_buffer += current_chunk
283
- print(f"\n=== Thinking Chunk ===\n{current_chunk}")
284
- messages[-1] = ChatMessage(
285
- role="assistant",
286
- content=thought_buffer,
287
- metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
288
- )
289
- yield messages
290
 
291
- print(f"\n=== Final Response ===\n{response_buffer}")
 
 
 
 
 
 
 
292
 
293
- except Exception as e:
294
- print(f"\n=== Error ===\n{str(e)}")
295
- messages.append(
296
- ChatMessage(
 
297
  role="assistant",
298
- content=f"I apologize, but I encountered an error: {str(e)}"
 
299
  )
300
- )
301
- yield messages
 
302
 
303
- def respond(message: str, history: List[ChatMessage]) -> Iterator[List[Tuple[str, str]]]:
304
  """
305
- stream_gemini_response()๋ฅผ ํ˜ธ์ถœํ•œ ํ›„, ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํŠœํ”Œ ๋ชฉ๋ก์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
306
  """
307
- for updated_messages in stream_gemini_response(message, history):
308
- yield convert_chat_history(updated_messages)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
 
310
- def user_message(msg: str, history: List[ChatMessage]) -> Tuple[str, List[ChatMessage]]:
311
- history.append(ChatMessage(role="user", content=msg))
312
- return "", history
 
 
 
 
313
 
314
- def respond_wrapper(message, chat_history, max_tokens, temperature, top_p):
315
- # chat_history๊ฐ€ ํŠœํ”Œ ๋ชฉ๋ก์ด๋ผ๋ฉด ChatMessage ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜
316
- if chat_history and isinstance(chat_history[0], tuple):
317
- chat_history = convert_to_chatmessage(chat_history)
318
- for updated in stream_gemini_response(message, chat_history):
319
- yield "", convert_chat_history(updated)
 
 
 
320
 
321
  # --------------------------------------------------
322
- # Gradio UI ๊ตฌ์„ฑ
323
  # --------------------------------------------------
324
  def create_ui():
325
  try:
326
  css = """
327
- /* ์ „์ฒด ๋ฐฐ๊ฒฝ ๋ฐ ๊ธฐ๋ณธ ๊ธ€๊ผด ์„ค์ • */
328
- body {
329
- background-color: #f9f9f9;
330
- font-family: 'Helvetica Neue', Arial, sans-serif;
331
- color: #333;
332
- }
333
- /* ํ•˜๋‹จ ํ‘ธํ„ฐ ์ˆจ๊น€ */
334
- footer { visibility: hidden; }
335
-
336
- /* ์ถœ๋ ฅ ๊ทธ๋ฃน ์Šคํƒ€์ผ: ๋ฐ์€ ๋ฐฐ๊ฒฝ, ๋ถ€๋“œ๋Ÿฌ์šด ํ…Œ๋‘๋ฆฌ์™€ ๊ทธ๋ฆผ์ž */
337
- .output-group {
338
- border: 1px solid #ccc;
339
- border-radius: 8px;
340
- padding: 15px;
341
- margin-bottom: 20px;
342
- background-color: #ffffff;
343
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
344
- }
345
- /* ์Šคํฌ๋กค ์˜์—ญ ์„ค์ • */
346
- .scroll-lock {
347
- overflow-y: auto !important;
348
- max-height: 300px !important;
349
- }
350
- .tree-view-scroll {
351
- overflow-y: auto !important;
352
- max-height: 400px !important;
353
- }
354
- .full-height {
355
- height: 80vh !important;
356
- overflow-y: auto !important;
357
- }
358
- /* ์ฝ”๋“œ ๋ฐ•์Šค ์Šคํƒ€์ผ: ๋ชจ๋…ธ์ŠคํŽ˜์ด์Šค ํฐํŠธ์™€ ๋ฐ์€ ๋ฐฐ๊ฒฝ */
359
- .code-box {
360
- overflow-x: auto !important;
361
- overflow-y: auto !important;
362
- white-space: pre !important;
363
- background-color: #f5f5f5;
364
- border-radius: 4px;
365
- padding: 10px;
366
- font-family: 'Courier New', Courier, monospace;
367
- }
368
- .code-box > div { min-width: 100% !important; }
369
- .code-box > div > textarea {
370
- word-break: normal !important;
371
- overflow-wrap: normal !important;
372
- }
373
- /* ํƒญ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์Šคํƒ€์ผ: ๋‹จ์ˆœํ•˜๊ณ  ๊น”๋”ํ•œ ๋””์ž์ธ */
374
- .tab-nav {
375
- background-color: #ffffff;
376
- border-bottom: 1px solid #ccc;
377
- display: flex;
378
- }
379
- .tab-nav button {
380
- background: none;
381
- border: none;
382
- padding: 10px 20px;
383
- margin: 0;
384
- cursor: pointer;
385
- font-size: 16px;
386
- color: #555;
387
- transition: color 0.3s, border-bottom 0.3s;
388
- }
389
- .tab-nav button:hover,
390
- .tab-nav button.selected {
391
- color: #000;
392
- border-bottom: 2px solid #007BFF;
393
- }
394
- /* ์ž…๋ ฅ์ฐฝ ๋ฐ ํ…์ŠคํŠธ ์˜์—ญ ์Šคํƒ€์ผ */
395
- input[type="text"], textarea {
396
- color: #333;
397
- background-color: #fff;
398
- border: 1px solid #ccc;
399
- border-radius: 4px;
400
- padding: 8px;
401
- }
402
  """
403
 
404
- with gr.Blocks(theme="default", css=css) as demo:
405
- gr.Markdown("# MOUSE: Space Research Thinking", elem_classes="header-markdown")
406
-
407
- with gr.Tabs() as tabs:
408
  with gr.TabItem("๋ถ„์„"):
409
  with gr.Row():
410
- with gr.Column(scale=6):
411
- url_input = gr.Textbox(label="HuggingFace Space URL", placeholder="์˜ˆ: https://huggingface.co/spaces/username/space_name")
412
- analyze_button = gr.Button("๋ถ„์„", variant="primary")
413
-
414
- with gr.Group(elem_classes="output-group scroll-lock"):
415
- summary_output = gr.Markdown(label="์š”์•ฝ (3์ค„ ์ด๋‚ด)")
416
-
417
- with gr.Group(elem_classes="output-group scroll-lock"):
418
- analysis_output = gr.Markdown(label="๋ถ„์„")
419
-
420
- with gr.Group(elem_classes="output-group scroll-lock"):
421
- usage_output = gr.Markdown(label="์‚ฌ์šฉ๋ฒ•")
422
-
423
- with gr.Group(elem_classes="output-group tree-view-scroll"):
424
- tree_view_output = gr.Textbox(label="ํŒŒ์ผ ๊ตฌ์กฐ (Tree View)", lines=30)
425
-
426
- with gr.Column(scale=4):
427
- with gr.Group(elem_classes="output-group full-height"):
428
- code_tabs = gr.Tabs()
429
- with code_tabs:
430
- with gr.TabItem("app.py"):
431
- app_py_content = gr.Code(
432
- language="python",
433
- label="app.py",
434
- lines=200,
435
- elem_classes="full-height code-box"
436
- )
437
- with gr.TabItem("requirements.txt"):
438
- requirements_content = gr.Textbox(
439
- label="requirements.txt",
440
- lines=200,
441
- elem_classes="full-height code-box"
442
- )
443
 
444
  with gr.TabItem("AI ์ฝ”๋“œ์ฑ—"):
445
- gr.Markdown("## : ์˜ˆ์ œ๋ฅผ ์ž…๋ ฅ/์„ ํƒํ•˜๊ณ , ์ด์–ด์„œ ๋ณต์‚ฌํ•œ app.py ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ถ™์—ฌ ๋„ฃ์œผ์„ธ์š”", elem_classes="header-markdown")
446
- # ์ฑ„ํŒ… ๋ฐ•์Šค ๋†’์ด๋ฅผ 400px๋กœ ์ง€์ •ํ•˜์—ฌ ํ™”๋ฉด ๋†’์ด์— ๋งž๊ฒŒ ์ค„์ž„.
 
447
  chatbot = gr.Chatbot(
448
  label="๋Œ€ํ™”",
449
- elem_classes="output-group",
450
  height=400
451
  )
452
 
453
- msg = gr.Textbox(label="๋ฉ”์‹œ์ง€", placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”...")
454
-
 
 
 
455
  # ์ˆจ๊ฒจ์ง„ ํŒŒ๋ผ๋ฏธํ„ฐ
456
- max_tokens = gr.Slider(minimum=1, maximum=8000, value=4000, label="Max Tokens", visible=False)
457
- temperature = gr.Slider(minimum=0, maximum=1, value=0.7, label="Temperature", visible=False)
458
- top_p = gr.Slider(minimum=0, maximum=1, value=0.9, label="Top P", visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
459
 
460
  examples = [
461
- ["์ƒ์„ธํ•œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋งˆ์น˜ ํ™”๋ฉด์„ ๋ณด๋ฉด์„œ ์„ค๋ช…ํ•˜๋“ฏ์ด 4000 ํ† ํฐ ์ด์ƒ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๋ผ"],
462
- ["FAQ 20๊ฑด์„ ์ƒ์„ธํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๋ผ. 4000ํ† ํฐ ์ด์ƒ ์‚ฌ์šฉํ•˜๋ผ."],
463
- ["์‚ฌ์šฉ ๋ฐฉ๋ฒ•๊ณผ ์ฐจ๋ณ„์ , ํŠน์ง•, ๊ฐ•์ ์„ ์ค‘์‹ฌ์œผ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์œ ํŠœ๋ธŒ ์˜์ƒ ์Šคํฌ๋ฆฝํŠธ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ผ"],
464
- ["๋ณธ ์„œ๋น„์Šค๋ฅผ SEO ์ตœ์ ํ™”ํ•˜์—ฌ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑํ•˜๋ผ"],
465
- ["ํŠนํ—ˆ ์ถœ์›์— ํ™œ์šฉํ•  ํ˜์‹ ์ ์ธ ์ฐฝ์˜ ๋ฐœ๋ช… ๋‚ด์šฉ์„ ์ค‘์‹ฌ์œผ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑํ•˜๋ผ."],
466
- ["ํ˜์‹ ์ ์ด๊ณ  ๋…ผ๋ฆฌ์ ์ธ ์ „๋ฌธ ๋…ผ๋ฌธ์˜ ํ˜•์‹์œผ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑํ•˜๋ผ."],
467
- ["๊ณ„์† ์ด์–ด์„œ ๋‹ต๋ณ€ํ•˜๋ผ"],
468
  ]
469
  gr.Examples(examples, inputs=msg)
470
 
471
- msg.submit(respond_wrapper, [msg, chatbot, max_tokens, temperature, top_p], [msg, chatbot])
472
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  with gr.TabItem("Recommended Best"):
474
  gr.Markdown(
475
- "Discover the best recommended HuggingFace Spaces [here](https://huggingface.co/spaces/openfree/Korean-Leaderboard).",
476
- elem_id="recommended-best"
477
  )
478
 
479
- # ์ƒํƒœ ์ €์žฅ์šฉ ๋ณ€์ˆ˜
480
  space_id_state = gr.State()
481
  tree_structure_state = gr.State()
482
  app_py_content_lines = gr.State()
@@ -484,15 +417,26 @@ def create_ui():
484
  analyze_button.click(
485
  analyze_space,
486
  inputs=[url_input],
487
- outputs=[app_py_content, tree_view_output, tree_structure_state, space_id_state, summary_output, analysis_output, usage_output, app_py_content_lines]
 
 
 
 
 
 
 
 
 
488
  ).then(
489
  lambda space_id: get_file_content(space_id, "requirements.txt"),
490
  inputs=[space_id_state],
491
  outputs=[requirements_content]
 
 
 
 
492
  )
493
 
494
- app_py_content.change(lambda lines: gr.update(lines=lines), inputs=[app_py_content_lines], outputs=[app_py_content])
495
-
496
  return demo
497
 
498
  except Exception as e:
@@ -504,21 +448,9 @@ if __name__ == "__main__":
504
  try:
505
  print("Starting HuggingFace Space Analyzer...")
506
  demo = create_ui()
507
- print("UI created successfully.")
508
- print("Configuring Gradio queue...")
509
  demo.queue()
510
- print("Gradio queue configured.")
511
- print("Launching Gradio app...")
512
- demo.launch(
513
- server_name="0.0.0.0",
514
- server_port=7860,
515
- share=False,
516
- debug=True,
517
- show_api=False
518
- )
519
- print("Gradio app launched successfully.")
520
  except Exception as e:
521
  print(f"Error in main: {str(e)}")
522
- print("Detailed error information:")
523
  print(traceback.format_exc())
524
  raise
 
7
  import requests
8
  import re
9
  import traceback
 
 
 
10
 
11
  # HuggingFace ๊ด€๋ จ API ํ‚ค (์ŠคํŽ˜์ด์Šค ๋ถ„์„ ์šฉ)
12
  HF_TOKEN = os.getenv("HF_TOKEN")
 
17
  genai.configure(api_key=GEMINI_API_KEY)
18
  model = genai.GenerativeModel("gemini-2.0-flash-thinking-exp-01-21")
19
 
 
 
 
20
  def get_headers():
21
  if not HF_TOKEN:
22
  raise ValueError("Hugging Face token not found in environment variables")
 
68
  formatted += format_tree_structure(child, indent + " ")
69
  return formatted
70
 
 
 
 
 
71
  def analyze_space(url: str, progress=gr.Progress()):
72
  try:
73
  space_id = url.split('spaces/')[-1]
 
86
  analysis = analyze_code(app_content)
87
  progress(0.9, desc="์‚ฌ์šฉ๋ฒ• ์„ค๋ช… ์ƒ์„ฑ ์ค‘...")
88
  usage = explain_usage(app_content)
89
+ # lines ์ˆ˜ ์กฐ์ •
90
+ lines_for_app_py = adjust_lines_for_code(app_content)
91
  progress(1.0, desc="์™„๋ฃŒ")
92
+ return app_content, tree_view, tree_structure, space_id, summary, analysis, usage, lines_for_app_py
93
  except Exception as e:
94
  print(f"Error in analyze_space: {str(e)}")
95
  print(traceback.format_exc())
96
  return f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}", "", None, "", "", "", "", 10
97
 
98
+ def adjust_lines_for_code(code_content: str, min_lines: int = 10, max_lines: int = 100) -> int:
99
+ num_lines = len(code_content.split('\n'))
100
+ return min(max(num_lines, min_lines), max_lines)
101
+
102
+ # -----------------------------
103
+ # LLM (Gemini) ๊ด€๋ จ ํ•จ์ˆ˜
104
+ # -----------------------------
105
+ from gradio import ChatMessage
106
+
107
  def format_chat_history(messages: List[ChatMessage]) -> List[Dict]:
108
+ """
109
+ ChatMessage ๋ชฉ๋ก์„ Gemini ๋ชจ๋ธ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
110
+ (Thinking ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํฌํ•จ ๋ฉ”์‹œ์ง€๋Š” ์ œ์™ธ)
111
+ """
112
+ formatted = []
113
+ for m in messages:
114
+ # 'Thinking' metadata๊ฐ€ ์žˆ์œผ๋ฉด ๋ฌด์‹œ
115
+ if hasattr(m, "metadata") and m.metadata:
116
+ continue
117
+ role = "assistant" if m.role == "assistant" else "user"
118
+ formatted.append({"role": role, "parts": [m.content or ""]})
119
+ return formatted
120
+
121
+ import google.generativeai as genai
122
+
123
+ def gemini_chat_completion(
124
+ system_message: str,
125
+ user_message: str,
126
+ max_tokens: int = 200,
127
+ temperature: float = 0.7
128
+ ) -> str:
129
+ # ChatMessage ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜
130
+ init_msgs = [
131
  ChatMessage(role="system", content=system_message),
132
  ChatMessage(role="user", content=user_message)
133
  ]
134
+ chat_history = format_chat_history(init_msgs)
135
  chat = model.start_chat(history=chat_history)
136
+ final = ""
137
  try:
138
  for chunk in chat.send_message(user_message, stream=True):
139
  parts = chunk.candidates[0].content.parts
140
  if len(parts) == 2:
141
+ # Thinking + ์ตœ์ข…์‘๋‹ต ํ˜•ํƒœ๋กœ ๋“ค์–ด์˜จ ๊ฒฝ์šฐ
142
+ final += parts[1].text
143
  else:
144
+ # ๊ทธ๋ƒฅ ์‘๋‹ต
145
+ final += parts[0].text
146
+ return final.strip()
147
  except Exception as e:
148
  return f"LLM ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
149
 
150
+ def summarize_code(app_content: str):
151
+ system_msg = "๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์š”์•ฝํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ 3์ค„ ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
152
+ user_msg = f"๋‹ค์Œ Python ์ฝ”๋“œ๋ฅผ 3์ค„ ์ด๋‚ด๋กœ ์š”์•ฝํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
153
  try:
154
+ return gemini_chat_completion(system_msg, user_msg, max_tokens=200, temperature=0.7)
155
  except Exception as e:
156
  return f"์š”์•ฝ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
157
 
158
+ def analyze_code(app_content: str):
159
+ # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— '๋”ฅ์”ฝํ‚น' ์•ˆ๋‚ด๋ฌธ ์ถ”๊ฐ€
160
+ system_msg = (
161
+ "You are a deep thinking AI. You may use extremely long chains of thought to deeply consider the problem "
162
+ "and deliberate with yourself via systematic reasoning processes to help come to a correct solution prior to answering. "
163
+ "You should enclose your thoughts and internal monologue inside tags, and then provide your solution or response to the problem. "
164
+ "๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์„œ๋น„์Šค์˜ ํšจ์šฉ์„ฑ๊ณผ ํ™œ์šฉ ์ธก๋ฉด์—์„œ ๋‹ค์Œ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\n"
165
  "A. ๋ฐฐ๊ฒฝ ๋ฐ ํ•„์š”์„ฑ\n"
166
  "B. ๊ธฐ๋Šฅ์  ํšจ์šฉ์„ฑ ๋ฐ ๊ฐ€์น˜\n"
167
  "C. ํŠน์žฅ์ \n"
 
169
  "E. ๊ธฐ๋Œ€ํšจ๊ณผ\n"
170
  "๊ธฐ์กด ๋ฐ ์œ ์‚ฌ ํ”„๋กœ์ ํŠธ์™€ ๋น„๊ตํ•˜์—ฌ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”. Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”."
171
  )
172
+ user_msg = f"๋‹ค์Œ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
173
  try:
174
+ return gemini_chat_completion(system_msg, user_msg, max_tokens=1000, temperature=0.7)
175
  except Exception as e:
176
  return f"๋ถ„์„ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
177
 
178
+ def explain_usage(app_content: str):
179
+ # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— '๋”ฅ์”ฝํ‚น' ์•ˆ๋‚ด๋ฌธ ์ถ”๊ฐ€
180
+ system_msg = (
181
+ "You are a deep thinking AI. You may use extremely long chains of thought to deeply consider the problem "
182
+ "and deliberate with yourself via systematic reasoning processes to help come to a correct solution prior to answering. "
183
+ "You should enclose your thoughts and internal monologue inside tags, and then provide your solution or response to the problem. "
184
+ "๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์‚ฌ์šฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ฝ”๋“œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งˆ์น˜ ํ™”๋ฉด์„ ๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋ฒ•์„ ์ƒ์„ธํžˆ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. Markdown ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•˜์„ธ์š”."
185
+ )
186
+ user_msg = f"๋‹ค์Œ Python ์ฝ”๋“œ์˜ ์‚ฌ์šฉ๋ฒ•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
187
  try:
188
+ return gemini_chat_completion(system_msg, user_msg, max_tokens=800, temperature=0.7)
189
  except Exception as e:
190
  return f"์‚ฌ์šฉ๋ฒ• ์„ค๋ช… ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
191
 
192
+ # -----------------------------
193
+ # ์‹ค์ œ ๋Œ€ํ™” ์ŠคํŠธ๋ฆฌ๋ฐ
194
+ # -----------------------------
195
+ def stream_gemini_response(user_message: str, conversation_state: List[ChatMessage]) -> Iterator[List[ChatMessage]]:
196
  """
197
+ conversation_state: ChatMessage ๊ฐ์ฒด๋กœ๋งŒ ์ด๋ฃจ์–ด์ง„ '๋Œ€ํ™” ์ด๋ ฅ' (Gradio State).
198
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  if not user_message.strip():
200
+ conversation_state.append(
201
+ ChatMessage(role="assistant", content="Please provide a non-empty text message. Empty input is not allowed.")
202
+ )
203
+ yield conversation_state
204
  return
205
 
206
+ print(f"\n=== New Request ===\nUser message: {user_message}")
207
+
208
+ # ๊ธฐ์กด ๋Œ€ํ™”๋ฅผ Gemini ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
209
+ chat_history = format_chat_history(conversation_state)
210
+ chat = model.start_chat(history=chat_history)
211
+
212
+ response = chat.send_message(user_message, stream=True)
213
+ thought_buffer = ""
214
+ response_buffer = ""
215
+ thinking_complete = False
216
+
217
+ # 'Thinking' ํ‘œ์‹œ์šฉ
218
+ conversation_state.append(
219
+ ChatMessage(
220
+ role="assistant",
221
+ content="",
222
+ metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
223
  )
224
+ )
225
 
226
+ for chunk in response:
227
+ parts = chunk.candidates[0].content.parts
228
+ current_chunk = parts[0].text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
+ if len(parts) == 2 and not thinking_complete:
231
+ # ์ฒซ ๋ฒˆ์งธ๊ฐ€ '์ƒ๊ฐ', ๋‘ ๋ฒˆ์งธ๊ฐ€ ์ตœ์ข… ์‘๋‹ต
232
+ thought_buffer += current_chunk
233
+ print(f"\n=== Complete Thought ===\n{thought_buffer}")
234
+ conversation_state[-1] = ChatMessage(
235
+ role="assistant",
236
+ content=thought_buffer,
237
+ metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
238
+ )
239
+ yield conversation_state
240
 
241
+ response_buffer = parts[1].text
242
+ print(f"\n=== Starting Response ===\n{response_buffer}")
243
+ conversation_state.append(
244
+ ChatMessage(role="assistant", content=response_buffer)
245
+ )
246
+ thinking_complete = True
 
 
 
247
 
248
+ elif thinking_complete:
249
+ # ์ด๋ฏธ ์ƒ๊ฐ์ด ๋๋‚ฌ์œผ๋ฏ€๋กœ ์ตœ์ข… ์‘๋‹ต ๋ˆ„์ 
250
+ response_buffer += current_chunk
251
+ print(f"\n=== Response Chunk ===\n{current_chunk}")
252
+ conversation_state[-1] = ChatMessage(
253
+ role="assistant",
254
+ content=response_buffer
255
+ )
256
 
257
+ else:
258
+ # ์•„์ง ์ƒ๊ฐ ์ค‘
259
+ thought_buffer += current_chunk
260
+ print(f"\n=== Thinking Chunk ===\n{current_chunk}")
261
+ conversation_state[-1] = ChatMessage(
262
  role="assistant",
263
+ content=thought_buffer,
264
+ metadata={"title": "โš™๏ธ Thinking: *The thoughts produced by the model are experimental"}
265
  )
266
+ yield conversation_state
267
+
268
+ print(f"\n=== Final Response ===\n{response_buffer}")
269
 
270
+ def convert_to_display_tuples(messages: List[ChatMessage]) -> List[Tuple[str, str]]:
271
  """
272
+ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด (user, assistant) ํŠœํ”Œ ๋ชฉ๋ก์œผ๋กœ ๋ณ€ํ™˜
273
  """
274
+ result = []
275
+ i = 0
276
+ while i < len(messages):
277
+ if messages[i].role == "user":
278
+ user_text = messages[i].content
279
+ assistant_text = ""
280
+ if i + 1 < len(messages) and messages[i+1].role == "assistant":
281
+ assistant_text = messages[i+1].content
282
+ i += 2
283
+ else:
284
+ i += 1
285
+ result.append((user_text, assistant_text))
286
+ else:
287
+ # assistant ๋‹จ๋…
288
+ result.append(("", messages[i].content))
289
+ i += 1
290
+ return result
291
 
292
+ def user_submit_message(msg: str, conversation_state: List[ChatMessage]):
293
+ """
294
+ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ํ˜ธ์ถœ.
295
+ ChatMessage ๋ฆฌ์ŠคํŠธ(conversation_state)์— user ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค ๋ฐ˜ํ™˜.
296
+ """
297
+ conversation_state.append(ChatMessage(role="user", content=msg))
298
+ return "", conversation_state
299
 
300
+ def respond_wrapper(message: str, conversation_state: List[ChatMessage], max_tokens, temperature, top_p):
301
+ """
302
+ ์œ ์ € ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„ Gemini์—๊ฒŒ ์š”์ฒญ(์ŠคํŠธ๋ฆฌ๋ฐ)ํ•˜๊ณ , ๋Œ€ํ™” ์ด๋ ฅ์„ ์—…๋ฐ์ดํŠธ ํ›„
303
+ ํ™”๋ฉด์—๋Š” (user, assistant) ํŠœํ”Œ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
304
+ """
305
+ # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต
306
+ for updated_messages in stream_gemini_response(message, conversation_state):
307
+ # ํ™”๋ฉด ํ‘œ์‹œ์šฉ (user, assistant) ํŠœํ”Œ๋กœ ๋ณ€ํ™˜
308
+ yield "", convert_to_display_tuples(updated_messages)
309
 
310
  # --------------------------------------------------
311
+ # Gradio UI
312
  # --------------------------------------------------
313
  def create_ui():
314
  try:
315
  css = """
316
+ footer {visibility: hidden;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  """
318
 
319
+ with gr.Blocks(css=css) as demo:
320
+ gr.Markdown("# MOUSE: Space Research Thinking")
321
+
322
+ with gr.Tabs():
323
  with gr.TabItem("๋ถ„์„"):
324
  with gr.Row():
325
+ with gr.Column():
326
+ url_input = gr.Textbox(label="HuggingFace Space URL")
327
+ analyze_button = gr.Button("๋ถ„์„")
328
+
329
+ summary_output = gr.Markdown(label="์š”์•ฝ")
330
+ analysis_output = gr.Markdown(label="๋ถ„์„")
331
+ usage_output = gr.Markdown(label="์‚ฌ์šฉ๋ฒ•")
332
+ tree_view_output = gr.Textbox(label="ํŒŒ์ผ ๊ตฌ์กฐ", lines=20)
333
+
334
+ with gr.Column():
335
+ code_tabs = gr.Tabs()
336
+ with code_tabs:
337
+ with gr.TabItem("app.py"):
338
+ app_py_content = gr.Code(
339
+ language="python",
340
+ label="app.py",
341
+ lines=50
342
+ )
343
+ with gr.TabItem("requirements.txt"):
344
+ requirements_content = gr.Textbox(
345
+ label="requirements.txt",
346
+ lines=50
347
+ )
 
 
 
 
 
 
 
 
 
 
348
 
349
  with gr.TabItem("AI ์ฝ”๋“œ์ฑ—"):
350
+ gr.Markdown("## ์˜ˆ์ œ๋ฅผ ์ž…๋ ฅ ๋˜๋Š” ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ถ™์—ฌ๋„ฃ๊ณ  ์งˆ๋ฌธํ•˜์„ธ์š”")
351
+
352
+ # Chatbot์€ ๋‹จ์ง€ ์ถœ๋ ฅ๋งŒ ๋‹ด๋‹น(ํŠœํ”Œ์„ ๋ฐ›์•„ ํ‘œ์‹œ)
353
  chatbot = gr.Chatbot(
354
  label="๋Œ€ํ™”",
 
355
  height=400
356
  )
357
 
358
+ msg = gr.Textbox(
359
+ label="๋ฉ”์‹œ์ง€",
360
+ placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”..."
361
+ )
362
+
363
  # ์ˆจ๊ฒจ์ง„ ํŒŒ๋ผ๋ฏธํ„ฐ
364
+ max_tokens = gr.Slider(
365
+ minimum=1, maximum=8000,
366
+ value=4000, label="Max Tokens",
367
+ visible=False
368
+ )
369
+ temperature = gr.Slider(
370
+ minimum=0, maximum=1,
371
+ value=0.7, label="Temperature",
372
+ visible=False
373
+ )
374
+ top_p = gr.Slider(
375
+ minimum=0, maximum=1,
376
+ value=0.9, label="Top P",
377
+ visible=False
378
+ )
379
 
380
  examples = [
381
+ ["์ƒ์„ธํ•œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ 4000 ํ† ํฐ ์ด์ƒ ์ƒ์„ธํžˆ ์„ค๋ช…"],
382
+ ["FAQ 20๊ฑด์„ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑ"],
383
+ ["๊ธฐ์ˆ  ์ฐจ๋ณ„์ , ๊ฐ•์ ์„ ์ค‘์‹ฌ์œผ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์„ค๋ช…"],
384
+ ["ํŠนํ—ˆ ์ถœ์›์— ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ํ˜์‹  ์•„์ด๋””์–ด๋ฅผ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑ"],
385
+ ["๋…ผ๋ฌธ ํ˜•์‹์œผ๋กœ 4000 ํ† ํฐ ์ด์ƒ ์ž‘์„ฑ"],
386
+ ["๊ณ„์† ์ด์–ด์„œ ๋‹ต๋ณ€ํ•˜๋ผ"]
 
387
  ]
388
  gr.Examples(examples, inputs=msg)
389
 
390
+ # ๋Œ€ํ™” ์ƒํƒœ(์ฑ„ํŒ… ๊ธฐ๋ก)๋Š” ChatMessage ๊ฐ์ฒด๋กœ๋งŒ ์œ ์ง€
391
+ conversation_state = gr.State([])
392
+
393
+ # ์ด๋ฒคํŠธ ์ฒด์ธ
394
+ # 1) ์œ ์ € ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ -> user_submit_message -> (์ž…๋ ฅ์ฐฝ ๋น„์šฐ๊ณ , ChatMessage์ถ”๊ฐ€)
395
+ # 2) respond_wrapper ํ˜ธ์ถœ -> Gemini ์ŠคํŠธ๋ฆฌ๋ฐ -> ChatMessage ๊ฐฑ์‹  -> ํŠœํ”Œ ๋ณ€ํ™˜ํ•˜์—ฌ chatbot์— ํ‘œ์‹œ
396
+ msg.submit(
397
+ user_submit_message,
398
+ inputs=[msg, conversation_state],
399
+ outputs=[msg, conversation_state],
400
+ queue=False
401
+ ).then(
402
+ respond_wrapper,
403
+ inputs=[msg, conversation_state, max_tokens, temperature, top_p],
404
+ outputs=[msg, chatbot], # msg๋Š” ๋น„์›Œ์ฃผ๊ณ , chatbot์—๋Š” (user,assistant) ํŠœํ”Œ ๋ฆฌ์ŠคํŠธ
405
+ )
406
+
407
  with gr.TabItem("Recommended Best"):
408
  gr.Markdown(
409
+ "Discover recommended HuggingFace Spaces [here](https://huggingface.co/spaces/openfree/Korean-Leaderboard)."
 
410
  )
411
 
412
+ # ๋ถ„์„ ๋ฒ„ํŠผ ๋กœ์ง
413
  space_id_state = gr.State()
414
  tree_structure_state = gr.State()
415
  app_py_content_lines = gr.State()
 
417
  analyze_button.click(
418
  analyze_space,
419
  inputs=[url_input],
420
+ outputs=[
421
+ app_py_content,
422
+ tree_view_output,
423
+ tree_structure_state,
424
+ space_id_state,
425
+ summary_output,
426
+ analysis_output,
427
+ usage_output,
428
+ app_py_content_lines
429
+ ]
430
  ).then(
431
  lambda space_id: get_file_content(space_id, "requirements.txt"),
432
  inputs=[space_id_state],
433
  outputs=[requirements_content]
434
+ ).then(
435
+ lambda lines: gr.update(lines=lines),
436
+ inputs=[app_py_content_lines],
437
+ outputs=[app_py_content]
438
  )
439
 
 
 
440
  return demo
441
 
442
  except Exception as e:
 
448
  try:
449
  print("Starting HuggingFace Space Analyzer...")
450
  demo = create_ui()
 
 
451
  demo.queue()
452
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False, debug=True, show_api=False)
 
 
 
 
 
 
 
 
 
453
  except Exception as e:
454
  print(f"Error in main: {str(e)}")
 
455
  print(traceback.format_exc())
456
  raise