ginipick commited on
Commit
a958a41
·
verified ·
1 Parent(s): d81053d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -155
app.py CHANGED
@@ -3,80 +3,16 @@ from huggingface_hub import InferenceClient
3
  import os
4
  import pandas as pd
5
  from typing import List, Dict, Tuple
 
6
  import io
7
  import traceback
8
  import csv
9
- from functools import lru_cache
10
- from concurrent.futures import ThreadPoolExecutor
11
- import nltk
12
- from nltk.tokenize import sent_tokenize
13
- from transformers import AutoTokenizer
14
-
15
- # NLTK 데이터 다운로드
16
- nltk.download('punkt')
17
 
18
  # 추론 API 클라이언트 설정
19
  hf_client = InferenceClient(
20
  "CohereForAI/c4ai-command-r-plus-08-2024", token=os.getenv("HF_TOKEN")
21
  )
22
 
23
- def chunk_text(text: str, chunk_size: int = 500) -> List[str]:
24
- """텍스트를 더 작은 청크로 분할"""
25
- tokenizer = AutoTokenizer.from_pretrained("CohereForAI/c4ai-command-r-plus-08-2024")
26
- sentences = sent_tokenize(text)
27
- chunks = []
28
- current_chunk = []
29
- current_length = 0
30
-
31
- for sentence in sentences:
32
- sentence = sentence.strip()
33
- tokenized_sentence = tokenizer.encode(sentence, add_special_tokens=False)
34
- sentence_length = len(tokenized_sentence)
35
- if current_length + sentence_length > chunk_size:
36
- if current_chunk:
37
- chunks.append(' '.join(current_chunk))
38
- current_chunk = [sentence]
39
- current_length = sentence_length
40
- else:
41
- current_chunk.append(sentence)
42
- current_length += sentence_length
43
-
44
- if current_chunk:
45
- chunks.append(' '.join(current_chunk))
46
- return chunks
47
-
48
- # 나머지 코드는 이전과 동일하게 유지
49
-
50
-
51
-
52
-
53
-
54
- @lru_cache(maxsize=100)
55
- def cached_preprocess(text: str) -> str:
56
- """자주 사용되는 텍스트에 대한 전처리 결과를 캐싱"""
57
- return preprocess_single_chunk(text)
58
-
59
- def preprocess_single_chunk(chunk: str) -> str:
60
- """단일 청크에 대한 전처리 수행"""
61
- system_prompt = """당신은 데이터 전처리 전문가입니다. 입력된 텍스트를 CSV 데이터셋 형식으로 빠르게 변환하세요.
62
- [기존 규칙 동일]"""
63
-
64
- full_prompt = f"{system_prompt}\n\n입력텍스트:\n{chunk}\n\n출력:"
65
-
66
- try:
67
- # 스트리밍 비활성화 및 파라미터 최적화
68
- response = hf_client.text_generation(
69
- prompt=full_prompt,
70
- max_new_tokens=2000, # 토큰 수 제한
71
- temperature=0.1, # 더 결정적인 출력
72
- top_p=0.5, # 더 집중된 출력
73
- stream=False # 스트리밍 비활성화
74
- )
75
- return response.strip()
76
- except Exception as e:
77
- print(f"청크 처리 중 오류 발생: {str(e)}\n{traceback.format_exc()}")
78
- return "청크 처리 중 오류가 발생했습니다. 관리자에게 문의하세요."
79
-
80
  def load_code(filename: str) -> str:
81
  try:
82
  with open(filename, 'r', encoding='utf-8') as file:
@@ -84,8 +20,7 @@ def load_code(filename: str) -> str:
84
  except FileNotFoundError:
85
  return f"{filename} 파일을 찾을 수 없습니다."
86
  except Exception as e:
87
- print(f"파일 읽기 오류: {str(e)}\n{traceback.format_exc()}")
88
- return "파일을 읽는 중 오류가 발생했습니다. 관리자에게 문의하세요."
89
 
90
  def load_parquet(filename: str) -> str:
91
  try:
@@ -94,8 +29,7 @@ def load_parquet(filename: str) -> str:
94
  except FileNotFoundError:
95
  return f"{filename} 파일을 찾을 수 없습니다."
96
  except Exception as e:
97
- print(f"Parquet 파일 로드 오류: {str(e)}\n{traceback.format_exc()}")
98
- return "파일을 읽는 중 오류가 발생했습니다. 관리자에게 문의하세요."
99
 
100
  def respond(
101
  message: str,
@@ -144,9 +78,9 @@ def respond(
144
  response += msg
145
  yield response
146
  except Exception as e:
147
- error_message = f"추론 중 오류가 발생했습니다: {str(e)}"
148
  print(error_message)
149
- yield "추론 중 오류가 발생했습니다. 관리자에게 문의하세요."
150
 
151
  def upload_csv(file_path: str) -> Tuple[str, str]:
152
  try:
@@ -168,8 +102,7 @@ def upload_csv(file_path: str) -> Tuple[str, str]:
168
  df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
169
  return f"{parquet_filename} 파일이 성공적으로 업로드되고 변환되었습니다.", parquet_filename
170
  except Exception as e:
171
- print(f"CSV 파일 업로드 및 변환 중 오류 발생: {str(e)}\n{traceback.format_exc()}")
172
- return "CSV 파일 업로드 및 변환 중 오류가 발생했습니다. 관리자에게 문의하세요.", ""
173
 
174
  def upload_parquet(file_path: str) -> Tuple[str, str, str]:
175
  try:
@@ -181,26 +114,25 @@ def upload_parquet(file_path: str) -> Tuple[str, str, str]:
181
  parquet_json = df.to_json(orient='records', force_ascii=False)
182
  return "Parquet 파일이 성공적으로 업로드되었습니다.", parquet_content, parquet_json
183
  except Exception as e:
184
- print(f"Parquet 파일 업로드 중 오류 발생: {str(e)}\n{traceback.format_exc()}")
185
- return "Parquet 파일 업로드 중 오류가 발생했습니다. 관리자에게 문의하세요.", "", ""
186
 
187
  def text_to_parquet(text: str) -> Tuple[str, str, str]:
188
  try:
189
  from io import StringIO
190
  import csv
191
-
192
  # 입력 텍스트 정제
193
  lines = text.strip().split('\n')
194
  cleaned_lines = []
195
-
196
  for line in lines:
197
  # 빈 줄 건너뛰기
198
  if not line.strip():
199
  continue
200
-
201
  # 쌍따옴표 정규화
202
  line = line.replace('""', '"') # 중복 쌍따옴표 처리
203
-
204
  # CSV 파싱을 위한 임시 StringIO 객체 생성
205
  temp_buffer = StringIO(line)
206
  try:
@@ -211,14 +143,14 @@ def text_to_parquet(text: str) -> Tuple[str, str, str]:
211
  # 각 필드를 적절히 포맷팅
212
  formatted_line = f'{parsed_line[0]},"{parsed_line[1]}","{parsed_line[2]}","{parsed_line[3]}"'
213
  cleaned_lines.append(formatted_line)
214
- except Exception as e:
215
  continue
216
  finally:
217
  temp_buffer.close()
218
-
219
  # 정제된 CSV 데이터 생성
220
  cleaned_csv = '\n'.join(cleaned_lines)
221
-
222
  # DataFrame 생성
223
  df = pd.read_csv(
224
  StringIO(cleaned_csv),
@@ -227,28 +159,28 @@ def text_to_parquet(text: str) -> Tuple[str, str, str]:
227
  escapechar='\\',
228
  names=['id', 'text', 'label', 'metadata']
229
  )
230
-
231
  # 데이터 유형 최적화
232
  df = df.astype({'id': 'int32', 'text': 'string', 'label': 'string', 'metadata': 'string'})
233
-
234
  # Parquet 파일로 변환
235
  parquet_filename = 'text_to_parquet.parquet'
236
  df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
237
-
238
  # Parquet 파일 내용 미리보기
239
  parquet_content = load_parquet(parquet_filename)
240
-
241
  return f"{parquet_filename} 파일이 성공적으로 변환되었습니다.", parquet_content, parquet_filename
242
-
243
  except Exception as e:
244
  error_message = f"텍스트 변환 중 오류가 발생했습니다: {str(e)}"
245
  print(f"{error_message}\n{traceback.format_exc()}")
246
- return "텍스트 변환 중 오류가 발생했습니다. 관리자에게 문의하세요.", "", ""
247
 
248
  def preprocess_text_with_llm(input_text: str) -> str:
249
  if not input_text.strip():
250
- return "입력 텍스트가 없습니다."
251
-
252
  system_prompt = """당신은 데이터 전처리 전문가입니다. 입력된 텍스트를 CSV 데이터셋 형식으로 변환하세요.
253
 
254
  규칙:
@@ -277,53 +209,41 @@ def preprocess_text_with_llm(input_text: str) -> str:
277
  - 각 행은 새로운 줄로 구분
278
  - 불필요한 반복 출력 금지"""
279
 
280
- try:
281
- # 텍스트를 청크로 분할
282
- chunks = chunk_text(input_text)
283
-
284
- # 병렬 처리로 청크들을 처리
285
- with ThreadPoolExecutor(max_workers=3) as executor:
286
- futures = []
287
- for chunk in chunks:
288
- # 각 청크에 대한 프롬프트 생성
289
- chunk_prompt = f"{system_prompt}\n\n입력텍스트:\n{chunk}\n\n출력:"
290
- future = executor.submit(
291
- hf_client.text_generation,
292
- prompt=chunk_prompt,
293
- max_new_tokens=2000,
294
- temperature=0.1,
295
- top_p=0.5,
296
- stream=False
297
- )
298
- futures.append(future)
299
 
300
- processed_chunks = [future.result() for future in futures]
301
-
302
- # 결과 병합 및 중복 제거
303
- all_lines = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  seen_texts = set()
305
- current_id = 1
306
-
307
- for chunk_result in processed_chunks:
308
- # EOS_TOKEN 처리
309
- if "<EOS_TOKEN>" in chunk_result:
310
- chunk_result = chunk_result.split("<EOS_TOKEN>")[0]
311
-
312
- lines = chunk_result.strip().split('\n')
313
- for line in lines:
314
- line = line.strip()
315
- if line and '출력:' not in line and line not in seen_texts:
316
- # ID 재할당
317
- parts = line.split(',', 1)
318
- if len(parts) > 1:
319
- new_line = f"{current_id},{parts[1]}"
320
- if new_line not in seen_texts: # 추가적인 중복 검사
321
- all_lines.append(new_line)
322
- seen_texts.add(new_line)
323
- current_id += 1
324
-
325
- processed_text = '\n'.join(all_lines)
326
-
327
  # CSV 형식 검증
328
  try:
329
  from io import StringIO
@@ -332,11 +252,11 @@ def preprocess_text_with_llm(input_text: str) -> str:
332
  return processed_text
333
  except csv.Error:
334
  return "LLM이 올바른 CSV 형식을 생성하지 못했습니다. 다시 시도해주세요."
335
-
336
  except Exception as e:
337
  error_message = f"전처리 중 오류가 발생했습니다: {str(e)}"
338
  print(error_message)
339
- return "전처리 중 오류가 발생했습니다. 관리자에게 문의하세요."
340
 
341
  # CSS 설정
342
  css = """
@@ -375,6 +295,8 @@ with gr.Blocks(css=css) as demo:
375
  elem_id="initial-description"
376
  )
377
 
 
 
378
  # 첫 번째 탭: 챗봇 데이터 업로드 (탭 이름 변경: "My 데이터셋+LLM")
379
  with gr.Tab("My 데이터셋+LLM"):
380
  gr.Markdown("### LLM과 대화하기")
@@ -418,8 +340,7 @@ with gr.Blocks(css=css) as demo:
418
  # 어시스턴트의 응답을 히스토리에 추가
419
  history.append({"role": "assistant", "content": partial_response})
420
  except Exception as e:
421
- print(f"메시지 처리 오류 발생: {str(e)}\n{traceback.format_exc()}")
422
- response = "메시지 처리 중 오류가 발생했습니다. 관리자에게 문의하세요."
423
  history.append({"role": "assistant", "content": response})
424
  yield history, ""
425
 
@@ -540,48 +461,49 @@ with gr.Blocks(css=css) as demo:
540
  lines=15,
541
  placeholder="여기에 전처리할 텍스트를 입력하세요..."
542
  )
543
-
544
  with gr.Row():
545
  preprocess_button = gr.Button("전처리 실행", variant="primary")
546
  clear_button = gr.Button("초기화")
547
-
548
  preprocess_status = gr.Textbox(
549
  label="전처리 상태",
550
  interactive=False,
551
  value="대기 중..."
552
  )
553
-
554
  processed_text_output = gr.Textbox(
555
  label="전처리된 데이터셋 출력",
556
  lines=15,
557
  interactive=False
558
  )
559
-
560
  # Parquet 변환 및 다운로드 섹션
561
  convert_to_parquet_button = gr.Button("Parquet으로 변환")
562
  download_parquet = gr.File(label="변환된 Parquet 파일 다운로드")
563
 
 
 
 
564
  def handle_text_preprocessing(input_text: str):
565
  if not input_text.strip():
566
- yield "입력 텍스트가 없습니다.", ""
567
- return
568
-
569
  try:
570
  preprocess_status_msg = "전처리를 시작합니다..."
571
  yield preprocess_status_msg, ""
572
-
573
  processed_text = preprocess_text_with_llm(input_text)
574
-
575
  if processed_text:
576
  preprocess_status_msg = "전처리가 완료되었습니다."
577
  yield preprocess_status_msg, processed_text
578
  else:
579
  preprocess_status_msg = "전처리 결과가 없습니다."
580
  yield preprocess_status_msg, ""
581
-
582
  except Exception as e:
583
- error_msg = "전처리 중 오류가 발생했습니다. 관���자에게 문의하세요."
584
- print(f"전처리 중 오류 발생: {str(e)}\n{traceback.format_exc()}")
585
  yield error_msg, ""
586
 
587
  def clear_inputs():
@@ -590,15 +512,14 @@ with gr.Blocks(css=css) as demo:
590
  def convert_to_parquet_file(processed_text: str):
591
  if not processed_text.strip():
592
  return "변환할 텍스트가 없습니다.", None
593
-
594
  try:
595
  message, parquet_content, parquet_filename = text_to_parquet(processed_text)
596
  if parquet_filename:
597
  return message, parquet_filename
598
  return message, None
599
  except Exception as e:
600
- print(f"Parquet 변환 중 오류 발생: {str(e)}\n{traceback.format_exc()}")
601
- return "Parquet 변환 중 오류가 발생했습니다. 관리자에게 문의하세요.", None
602
 
603
  # 이벤트 핸들러 연결
604
  preprocess_button.click(
@@ -633,5 +554,5 @@ with gr.Blocks(css=css) as demo:
633
  gr.Markdown("### [email protected]", elem_id="initial-description")
634
 
635
  if __name__ == "__main__":
636
- demo.launch(share=True) # 코드상의 오류나 개선이 필요한 사항을 추론하여 보고하라
637
 
 
3
  import os
4
  import pandas as pd
5
  from typing import List, Dict, Tuple
6
+ import json
7
  import io
8
  import traceback
9
  import csv
 
 
 
 
 
 
 
 
10
 
11
  # 추론 API 클라이언트 설정
12
  hf_client = InferenceClient(
13
  "CohereForAI/c4ai-command-r-plus-08-2024", token=os.getenv("HF_TOKEN")
14
  )
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def load_code(filename: str) -> str:
17
  try:
18
  with open(filename, 'r', encoding='utf-8') as file:
 
20
  except FileNotFoundError:
21
  return f"{filename} 파일을 찾을 수 없습니다."
22
  except Exception as e:
23
+ return f"파일을 읽는 오류가 발생했습니다: {str(e)}"
 
24
 
25
  def load_parquet(filename: str) -> str:
26
  try:
 
29
  except FileNotFoundError:
30
  return f"{filename} 파일을 찾을 수 없습니다."
31
  except Exception as e:
32
+ return f"파일을 읽는 오류가 발생했습니다: {str(e)}"
 
33
 
34
  def respond(
35
  message: str,
 
78
  response += msg
79
  yield response
80
  except Exception as e:
81
+ error_message = f"추론 중 오류가 발생했습니다: {str(e)}\n{traceback.format_exc()}"
82
  print(error_message)
83
+ yield error_message
84
 
85
  def upload_csv(file_path: str) -> Tuple[str, str]:
86
  try:
 
102
  df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
103
  return f"{parquet_filename} 파일이 성공적으로 업로드되고 변환되었습니다.", parquet_filename
104
  except Exception as e:
105
+ return f"CSV 파일 업로드 및 변환 중 오류가 발생했습니다: {str(e)}", ""
 
106
 
107
  def upload_parquet(file_path: str) -> Tuple[str, str, str]:
108
  try:
 
114
  parquet_json = df.to_json(orient='records', force_ascii=False)
115
  return "Parquet 파일이 성공적으로 업로드되었습니다.", parquet_content, parquet_json
116
  except Exception as e:
117
+ return f"Parquet 파일 업로드 중 오류가 발생했습니다: {str(e)}", "", ""
 
118
 
119
  def text_to_parquet(text: str) -> Tuple[str, str, str]:
120
  try:
121
  from io import StringIO
122
  import csv
123
+
124
  # 입력 텍스트 정제
125
  lines = text.strip().split('\n')
126
  cleaned_lines = []
127
+
128
  for line in lines:
129
  # 빈 줄 건너뛰기
130
  if not line.strip():
131
  continue
132
+
133
  # 쌍따옴표 정규화
134
  line = line.replace('""', '"') # 중복 쌍따옴표 처리
135
+
136
  # CSV 파싱을 위한 임시 StringIO 객체 생성
137
  temp_buffer = StringIO(line)
138
  try:
 
143
  # 각 필드를 적절히 포맷팅
144
  formatted_line = f'{parsed_line[0]},"{parsed_line[1]}","{parsed_line[2]}","{parsed_line[3]}"'
145
  cleaned_lines.append(formatted_line)
146
+ except:
147
  continue
148
  finally:
149
  temp_buffer.close()
150
+
151
  # 정제된 CSV 데이터 생성
152
  cleaned_csv = '\n'.join(cleaned_lines)
153
+
154
  # DataFrame 생성
155
  df = pd.read_csv(
156
  StringIO(cleaned_csv),
 
159
  escapechar='\\',
160
  names=['id', 'text', 'label', 'metadata']
161
  )
162
+
163
  # 데이터 유형 최적화
164
  df = df.astype({'id': 'int32', 'text': 'string', 'label': 'string', 'metadata': 'string'})
165
+
166
  # Parquet 파일로 변환
167
  parquet_filename = 'text_to_parquet.parquet'
168
  df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
169
+
170
  # Parquet 파일 내용 미리보기
171
  parquet_content = load_parquet(parquet_filename)
172
+
173
  return f"{parquet_filename} 파일이 성공적으로 변환되었습니다.", parquet_content, parquet_filename
174
+
175
  except Exception as e:
176
  error_message = f"텍스트 변환 중 오류가 발생했습니다: {str(e)}"
177
  print(f"{error_message}\n{traceback.format_exc()}")
178
+ return error_message, "", ""
179
 
180
  def preprocess_text_with_llm(input_text: str) -> str:
181
  if not input_text.strip():
182
+ return "입력 텍스트가 비어있습니다."
183
+
184
  system_prompt = """당신은 데이터 전처리 전문가입니다. 입력된 텍스트를 CSV 데이터셋 형식으로 변환하세요.
185
 
186
  규칙:
 
209
  - 각 행은 새로운 줄로 구분
210
  - 불필요한 반복 출력 금지"""
211
 
212
+ full_prompt = f"{system_prompt}\n\n입력텍스트:\n{input_text}\n\n출력:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
+ try:
215
+ response = ""
216
+ stream = hf_client.text_generation(
217
+ prompt=full_prompt,
218
+ max_new_tokens=4000,
219
+ temperature=0.1, # 더 결정적인 출력을 위해 낮춤
220
+ top_p=0.9,
221
+ stream=True,
222
+ )
223
+
224
+ for msg in stream:
225
+ if msg:
226
+ response += msg
227
+
228
+ # <EOS_TOKEN> 이전까지만 추출하고 정제
229
+ if "<EOS_TOKEN>" in response:
230
+ processed_text = response.split("<EOS_TOKEN>")[0].strip()
231
+ else:
232
+ processed_text = response.strip()
233
+
234
+ # 중복 출력 제거
235
+ lines = processed_text.split('\n')
236
+ unique_lines = []
237
  seen_texts = set()
238
+
239
+ for line in lines:
240
+ line = line.strip()
241
+ if line and '출력:' not in line and line not in seen_texts:
242
+ unique_lines.append(line)
243
+ seen_texts.add(line)
244
+
245
+ processed_text = '\n'.join(unique_lines)
246
+
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  # CSV 형식 검증
248
  try:
249
  from io import StringIO
 
252
  return processed_text
253
  except csv.Error:
254
  return "LLM이 올바른 CSV 형식을 생성하지 못했습니다. 다시 시도해주세요."
255
+
256
  except Exception as e:
257
  error_message = f"전처리 중 오류가 발생했습니다: {str(e)}"
258
  print(error_message)
259
+ return error_message
260
 
261
  # CSS 설정
262
  css = """
 
295
  elem_id="initial-description"
296
  )
297
 
298
+
299
+
300
  # 첫 번째 탭: 챗봇 데이터 업로드 (탭 이름 변경: "My 데이터셋+LLM")
301
  with gr.Tab("My 데이터셋+LLM"):
302
  gr.Markdown("### LLM과 대화하기")
 
340
  # 어시스턴트의 응답을 히스토리에 추가
341
  history.append({"role": "assistant", "content": partial_response})
342
  except Exception as e:
343
+ response = f"추론오류가 발생했습니다: {str(e)}"
 
344
  history.append({"role": "assistant", "content": response})
345
  yield history, ""
346
 
 
461
  lines=15,
462
  placeholder="여기에 전처리할 텍스트를 입력하세요..."
463
  )
464
+
465
  with gr.Row():
466
  preprocess_button = gr.Button("전처리 실행", variant="primary")
467
  clear_button = gr.Button("초기화")
468
+
469
  preprocess_status = gr.Textbox(
470
  label="전처리 상태",
471
  interactive=False,
472
  value="대기 중..."
473
  )
474
+
475
  processed_text_output = gr.Textbox(
476
  label="전처리된 데이터셋 출력",
477
  lines=15,
478
  interactive=False
479
  )
480
+
481
  # Parquet 변환 및 다운로드 섹션
482
  convert_to_parquet_button = gr.Button("Parquet으로 변환")
483
  download_parquet = gr.File(label="변환된 Parquet 파일 다운로드")
484
 
485
+
486
+
487
+
488
  def handle_text_preprocessing(input_text: str):
489
  if not input_text.strip():
490
+ return "입력 텍스트가 없습니다.", ""
491
+
 
492
  try:
493
  preprocess_status_msg = "전처리를 시작합니다..."
494
  yield preprocess_status_msg, ""
495
+
496
  processed_text = preprocess_text_with_llm(input_text)
497
+
498
  if processed_text:
499
  preprocess_status_msg = "전처리가 완료되었습니다."
500
  yield preprocess_status_msg, processed_text
501
  else:
502
  preprocess_status_msg = "전처리 결과가 없습니다."
503
  yield preprocess_status_msg, ""
504
+
505
  except Exception as e:
506
+ error_msg = f"처리 중 오류가 발생했습니다: {str(e)}"
 
507
  yield error_msg, ""
508
 
509
  def clear_inputs():
 
512
  def convert_to_parquet_file(processed_text: str):
513
  if not processed_text.strip():
514
  return "변환할 텍스트가 없습니다.", None
515
+
516
  try:
517
  message, parquet_content, parquet_filename = text_to_parquet(processed_text)
518
  if parquet_filename:
519
  return message, parquet_filename
520
  return message, None
521
  except Exception as e:
522
+ return f"Parquet 변환 중 오류 발생: {str(e)}", None
 
523
 
524
  # 이벤트 핸들러 연결
525
  preprocess_button.click(
 
554
  gr.Markdown("### [email protected]", elem_id="initial-description")
555
 
556
  if __name__ == "__main__":
557
+ demo.launch(share=True)
558