myezrag / app.py
ginipick's picture
Update app.py
0fbbd89 verified
raw
history blame
18.3 kB
import gradio as gr
from huggingface_hub import InferenceClient
import os
import pandas as pd
from typing import List, Dict, Tuple
# μΆ”λ‘  API ν΄λΌμ΄μ–ΈνŠΈ μ„€μ •
hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus-08-2024", token=os.getenv("HF_TOKEN"))
def load_code(filename: str) -> str:
try:
with open(filename, 'r', encoding='utf-8') as file:
return file.read()
except FileNotFoundError:
return f"{filename} νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
except Exception as e:
return f"νŒŒμΌμ„ μ½λŠ” 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
def load_parquet(filename: str) -> str:
try:
df = pd.read_parquet(filename, engine='pyarrow')
return df.head(10).to_markdown(index=False)
except FileNotFoundError:
return f"{filename} νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
except Exception as e:
return f"νŒŒμΌμ„ μ½λŠ” 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
# μ½”λ“œ 파일 λ‘œλ“œ
fashion_code = load_code('fashion.cod')
uhdimage_code = load_code('uhdimage.cod')
MixGEN_code = load_code('mgen.cod')
# 초기 Parquet 파일 λ‘œλ“œ (κΈ°μ‘΄ test.parquet)
test_parquet_content = load_parquet('test.parquet')
def respond(
message: str,
history: List[Dict[str, str]],
system_message: str = "",
max_tokens: int = 4000,
temperature: float = 0.7,
top_p: float = 0.9,
) -> str:
# μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ μ„€μ •
system_prefix = """λ°˜λ“œμ‹œ ν•œκΈ€λ‘œ 닡변할것. λ„ˆλŠ” 주어진 μ†ŒμŠ€μ½”λ“œλ₯Ό 기반으둜 "μ„œλΉ„μŠ€ μ‚¬μš© μ„€λͺ… 및 μ•ˆλ‚΄, Q&Aλ₯Ό ν•˜λŠ” 역할이닀". μ•„μ£Ό μΉœμ ˆν•˜κ³  μžμ„Έν•˜κ²Œ 4000토큰 이상 Markdown ν˜•μ‹μœΌλ‘œ μž‘μ„±ν•˜λΌ. λ„ˆλŠ” μ½”λ“œλ₯Ό 기반으둜 μ‚¬μš© μ„€λͺ… 및 질의 응닡을 μ§„ν–‰ν•˜λ©°, μ΄μš©μžμ—κ²Œ 도움을 μ£Όμ–΄μ•Ό ν•œλ‹€. μ΄μš©μžκ°€ κΆκΈˆν•΄ ν•  λ§Œν•œ λ‚΄μš©μ— μΉœμ ˆν•˜κ²Œ μ•Œλ €μ£Όλ„λ‘ ν•˜λΌ. μ½”λ“œ 전체 λ‚΄μš©μ— λŒ€ν•΄μ„œλŠ” λ³΄μ•ˆμ„ μœ μ§€ν•˜κ³ , ν‚€ κ°’ 및 μ—”λ“œν¬μΈνŠΈμ™€ ꡬ체적인 λͺ¨λΈμ€ κ³΅κ°œν•˜μ§€ 마라."""
# νŠΉμ • λͺ…λ Ήμ–΄ 처리
if message.lower() == "νŒ¨μ…˜ μ½”λ“œ μ‹€ν–‰":
system_prefix += f"\n\nνŒ¨μ…˜ μ½”λ“œ λ‚΄μš©:\n```python\n{fashion_code}\n```"
message = "νŒ¨μ…˜ κ°€μƒν”ΌνŒ…μ— λŒ€ν•œ λ‚΄μš©μ„ ν•™μŠ΅ν•˜μ˜€κ³ , μ„€λͺ…ν•  μ€€λΉ„κ°€ λ˜μ–΄μžˆλ‹€κ³  μ•Œλ¦¬κ³  μ„œλΉ„μŠ€ URL(https://aiqcamp-fash.hf.space)을 톡해 ν…ŒμŠ€νŠΈ 해보라고 좜λ ₯ν•˜λΌ."
elif message.lower() == "uhd 이미지 μ½”λ“œ μ‹€ν–‰":
system_prefix += f"\n\nUHD 이미지 μ½”λ“œ λ‚΄μš©:\n```python\n{uhdimage_code}\n```"
message = "UHD 이미지 생성에 λŒ€ν•œ λ‚΄μš©μ„ ν•™μŠ΅ν•˜μ˜€κ³ , μ„€λͺ…ν•  μ€€λΉ„κ°€ λ˜μ–΄μžˆλ‹€κ³  μ•Œλ¦¬κ³  μ„œλΉ„μŠ€ URL(https://openfree-ultpixgen.hf.space)을 톡해 ν…ŒμŠ€νŠΈ 해보라고 좜λ ₯ν•˜λΌ."
elif message.lower() == "mixgen μ½”λ“œ μ‹€ν–‰":
system_prefix += f"\n\nMixGEN μ½”λ“œ λ‚΄μš©:\n```python\n{MixGEN_code}\n```"
message = "MixGEN3 이미지 생성에 λŒ€ν•œ λ‚΄μš©μ„ ν•™μŠ΅ν•˜μ˜€κ³ , μ„€λͺ…ν•  μ€€λΉ„κ°€ λ˜μ–΄μžˆλ‹€κ³  μ•Œλ¦¬κ³  μ„œλΉ„μŠ€ URL(https://openfree-mixgen3.hf.space)을 톡해 ν…ŒμŠ€νŠΈ 해보라고 좜λ ₯ν•˜λΌ."
elif message.lower() == "test.parquet μ‹€ν–‰":
# historyμ—μ„œ parquet_content μ°ΎκΈ°
parquet_content = ""
for item in history:
if item['role'] == 'assistant' and 'test.parquet 파일 λ‚΄μš©' in item['content']:
try:
parquet_content = item['content'].split("```markdown\n")[1].split("\n```")[0]
except IndexError:
parquet_content = ""
break
system_prefix += f"\n\ntest.parquet 파일 λ‚΄μš©:\n```markdown\n{parquet_content}\n```"
message = "test.parquet νŒŒμΌμ— λŒ€ν•œ λ‚΄μš©μ„ ν•™μŠ΅ν•˜μ˜€κ³ , κ΄€λ ¨ μ„€λͺ… 및 Q&Aλ₯Ό 진행할 μ€€λΉ„κ°€ λ˜μ–΄μžˆλ‹€. κΆκΈˆν•œ 점이 있으면 물어보라."
elif message.lower() == "csv μ—…λ‘œλ“œ":
message = "CSV νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λ €λ©΄ 두 번째 탭을 μ‚¬μš©ν•˜μ„Έμš”."
# μ‹œμŠ€ν…œ λ©”μ‹œμ§€μ™€ λŒ€ν™” 기둝 κ²°ν•©
messages = [{"role": "system", "content": system_prefix}]
for chat in history:
messages.append({"role": chat['role'], "content": chat['content']})
messages.append({"role": "user", "content": message})
response = ""
try:
# λͺ¨λΈμ— λ©”μ‹œμ§€ 전솑 및 응닡 λ°›κΈ°
for msg in hf_client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
token = msg.choices[0].delta.get('content', None)
if token:
response += token
yield response
except Exception as e:
yield f"μΆ”λ‘  쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
def upload_csv(file_path: str) -> Tuple[str, str]:
try:
# CSV 파일 읽기
df = pd.read_csv(file_path, sep=',')
# ν•„μˆ˜ 컬럼 확인
required_columns = {'id', 'text', 'label', 'metadata'}
available_columns = set(df.columns)
missing_columns = required_columns - available_columns
if missing_columns:
return f"CSV νŒŒμΌμ— λ‹€μŒ ν•„μˆ˜ 컬럼이 λˆ„λ½λ˜μ—ˆμŠ΅λ‹ˆλ‹€: {', '.join(missing_columns)}", ""
# 데이터 ν΄λ Œμ§•
df.drop_duplicates(inplace=True)
df.fillna('', inplace=True)
# 데이터 μœ ν˜• μ΅œμ ν™”
df = df.astype({'id': 'int32', 'text': 'string', 'label': 'category', 'metadata': 'string'})
# Parquet 파일둜 λ³€ν™˜
parquet_filename = os.path.splitext(os.path.basename(file_path))[0] + '.parquet'
df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
# Parquet 파일 λ‚΄μš© 미리보기
parquet_content = load_parquet(parquet_filename)
return f"{parquet_filename} 파일이 μ„±κ³΅μ μœΌλ‘œ μ—…λ‘œλ“œλ˜κ³  λ³€ν™˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", parquet_content
except Exception as e:
return f"CSV 파일 μ—…λ‘œλ“œ 및 λ³€ν™˜ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}", ""
def upload_parquet(file_path: str) -> Tuple[str, str, Dict]:
try:
# Parquet 파일 읽기
df = pd.read_parquet(file_path, engine='pyarrow')
# Markdown으둜 λ³€ν™˜ν•˜μ—¬ 미리보기
parquet_content = df.to_markdown(index=False)
return "Parquet 파일이 μ„±κ³΅μ μœΌλ‘œ μ—…λ‘œλ“œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.", parquet_content, df.to_json()
except Exception as e:
return f"Parquet 파일 μ—…λ‘œλ“œ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}", "", {}
def text_to_parquet(text: str) -> Tuple[str, str, bytes]:
try:
# ν…μŠ€νŠΈλ₯Ό DataFrame으둜 λ³€ν™˜ (각 행은 콀마둜 ꡬ뢄)
data = [line.split(',') for line in text.strip().split('\n')]
df = pd.DataFrame(data, columns=['id', 'text', 'label', 'metadata'])
# 데이터 μœ ν˜• μ΅œμ ν™”
df = df.astype({'id': 'int32', 'text': 'string', 'label': 'category', 'metadata': 'string'})
# Parquet 파일둜 λ³€ν™˜
parquet_filename = 'text_to_parquet.parquet'
df.to_parquet(parquet_filename, engine='pyarrow', compression='snappy')
# Parquet 파일 λ‚΄μš© 미리보기
parquet_content = load_parquet(parquet_filename)
# 파일 데이터λ₯Ό λ°”μ΄λ„ˆλ¦¬λ‘œ 읽기
with open(parquet_filename, "rb") as f:
data = f.read()
return f"{parquet_filename} 파일이 μ„±κ³΅μ μœΌλ‘œ λ³€ν™˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", parquet_content, data
except Exception as e:
return f"ν…μŠ€νŠΈ λ³€ν™˜ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}", "", b""
# CSS μ„€μ •
css = """
footer {
visibility: hidden;
}
#chatbot-container, #chatbot-data-upload {
height: 600px;
overflow-y: scroll;
}
#chatbot-container .message, #chatbot-data-upload .message {
font-size: 14px;
}
"""
# Gradio Blocks μΈν„°νŽ˜μ΄μŠ€ μ„€μ •
with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css) as demo:
gr.Markdown("# LLM μ„œλΉ„μŠ€ μΈν„°νŽ˜μ΄μŠ€")
# 첫 번째 νƒ­: 챗봇
with gr.Tab("챗봇"):
gr.Markdown("### LLMκ³Ό λŒ€ν™”ν•˜κΈ°")
chatbot = gr.Chatbot(label="챗봇", type="messages", elem_id="chatbot-container")
msg = gr.Textbox(label="λ©”μ‹œμ§€ μž…λ ₯", placeholder="여기에 λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš”...")
send = gr.Button("전솑")
with gr.Accordion("μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ 및 μ˜΅μ…˜ μ„€μ •", open=False):
system_message = gr.Textbox(label="System Message", value="λ„ˆλŠ” AI μ‘°μ–Έμž 역할이닀.")
max_tokens = gr.Slider(minimum=1, maximum=8000, value=4000, label="Max Tokens")
temperature = gr.Slider(minimum=0, maximum=1, value=0.7, label="Temperature")
top_p = gr.Slider(minimum=0, maximum=1, value=0.9, label="Top P")
# 챗봇 λ©”μ‹œμ§€ 처리 ν•¨μˆ˜
def handle_message(message, history, system_message, max_tokens, temperature, top_p):
history = history or []
history.append({"role": "user", "content": message})
try:
# 응닡 생성
response_gen = respond(message, history, system_message, max_tokens, temperature, top_p)
response = ""
for partial in response_gen:
response = partial # μ΅œμ’… 응닡
history.append({"role": "assistant", "content": response})
except Exception as e:
response = f"μΆ”λ‘  쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
history.append({"role": "assistant", "content": response})
return history, ""
send.click(
handle_message,
inputs=[msg, chatbot, system_message, max_tokens, temperature, top_p],
outputs=[chatbot, msg]
)
# 예제 볡원
with gr.Accordion("예제", open=False):
gr.Examples(
examples=[
["νŒ¨μ…˜ μ½”λ“œ μ‹€ν–‰"],
["UHD 이미지 μ½”λ“œ μ‹€ν–‰"],
["MixGEN μ½”λ“œ μ‹€ν–‰"],
["test.parquet μ‹€ν–‰"],
["μƒμ„Έν•œ μ‚¬μš© 방법을 마치 화면을 λ³΄λ©΄μ„œ μ„€λͺ…ν•˜λ“―이 4000 토큰 이상 μžμ„Ένžˆ μ„€λͺ…ν•˜λΌ"],
["FAQ 20건을 μƒμ„Έν•˜κ²Œ μž‘μ„±ν•˜λΌ. 4000토큰 이상 μ‚¬μš©ν•˜λΌ."],
["μ‚¬μš© 방법과 차별점, νŠΉμ§•, 강점을 μ€‘μ‹¬μœΌλ‘œ 4000 토큰 이상 유튜브 μ˜μƒ 슀크립트 ν˜•νƒœλ‘œ μž‘μ„±ν•˜λΌ"],
["λ³Έ μ„œλΉ„μŠ€λ₯Ό SEO μ΅œμ ν™”ν•˜μ—¬ λΈ”λ‘œκ·Έ 포슀트(λ°°κ²½ 및 ν•„μš”μ„±, κΈ°μ‘΄ μœ μ‚¬ μ„œλΉ„μŠ€μ™€ λΉ„κ΅ν•˜μ—¬ 특μž₯점, ν™œμš©μ²˜, κ°€μΉ˜, κΈ°λŒ€νš¨κ³Ό, 결둠을 포함)둜 4000 토큰 이상 μž‘μ„±ν•˜λΌ"],
["νŠΉν—ˆ μΆœμ›μ— ν™œμš©ν•  기술 및 λΉ„μ¦ˆλ‹ˆμŠ€λͺ¨λΈ 츑면을 ν¬ν•¨ν•˜μ—¬ νŠΉν—ˆ μΆœμ›μ„œ ꡬ성에 맞게 ν˜μ‹ μ μΈ 창의 발λͺ… λ‚΄μš©μ„ μ€‘μ‹¬μœΌλ‘œ 4000 토큰 이상 μž‘μ„±ν•˜λΌ."],
["계속 μ΄μ–΄μ„œ λ‹΅λ³€ν•˜λΌ"],
],
inputs=msg,
label="예제 선택",
)
# 두 번째 νƒ­: 데이터 λ³€ν™˜
with gr.Tab("데이터 λ³€ν™˜"):
gr.Markdown("### CSV 파일 μ—…λ‘œλ“œ 및 Parquet λ³€ν™˜")
with gr.Row():
with gr.Column():
csv_file = gr.File(label="CSV 파일 μ—…λ‘œλ“œ", type="filepath")
upload_button = gr.Button("μ—…λ‘œλ“œ 및 λ³€ν™˜")
upload_status = gr.Textbox(label="μ—…λ‘œλ“œ μƒνƒœ", interactive=False)
parquet_preview = gr.Markdown(label="Parquet 파일 미리보기")
download_button = gr.Download(label="Parquet 파일 λ‹€μš΄λ‘œλ“œ")
def handle_csv_upload(file_path: str) -> Tuple[str, str, Tuple[bytes, str]]:
message, parquet_filename = upload_csv(file_path)
if parquet_filename:
# Parquet 파일 읽기
with open(parquet_filename, "rb") as f:
data = f.read()
filename = os.path.basename(parquet_filename)
return message, parquet_filename, (data, filename)
else:
return message, "", None
upload_button.click(
handle_csv_upload,
inputs=csv_file,
outputs=[upload_status, parquet_preview, download_button]
)
gr.Markdown("### 기쑴 Parquet 파일")
gr.Markdown(f"**test.parquet 파일 λ‚΄μš©:**\n```markdown\n{test_parquet_content}\n```")
# μ„Έ 번째 νƒ­: 챗봇 데이터 μ—…λ‘œλ“œ
with gr.Tab("챗봇 데이터 μ—…λ‘œλ“œ"):
gr.Markdown("### Parquet 파일 μ—…λ‘œλ“œ 및 μ§ˆλ¬Έν•˜κΈ°")
with gr.Row():
with gr.Column():
parquet_upload = gr.File(label="Parquet 파일 μ—…λ‘œλ“œ", type="filepath")
parquet_upload_button = gr.Button("μ—…λ‘œλ“œ")
parquet_upload_status = gr.Textbox(label="μ—…λ‘œλ“œ μƒνƒœ", interactive=False)
parquet_preview_chat = gr.Markdown(label="Parquet 파일 미리보기")
parquet_data_state = gr.State()
def handle_parquet_upload(file_path: str) -> Tuple[str, str, Dict]:
message, parquet_content, parquet_json = upload_parquet(file_path)
if parquet_json:
return message, parquet_content, parquet_json
else:
return message, "", {}
parquet_upload_button.click(
handle_parquet_upload,
inputs=parquet_upload,
outputs=[parquet_upload_status, parquet_preview_chat, parquet_data_state]
)
gr.Markdown("### LLMκ³Ό λŒ€ν™”ν•˜κΈ°")
chatbot_data_upload = gr.Chatbot(label="챗봇 데이터 μ—…λ‘œλ“œ", type="messages", elem_id="chatbot-data-upload")
msg_data_upload = gr.Textbox(label="λ©”μ‹œμ§€ μž…λ ₯", placeholder="여기에 λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš”...")
send_data_upload = gr.Button("전솑")
def handle_message_data_upload(message: str, history: List[Dict[str, str]], system_message: str, max_tokens: int, temperature: float, top_p: float, parquet_data: Dict) -> Tuple[List[Dict[str, str]], str]:
history = history or []
history.append({"role": "user", "content": message})
try:
# Parquet 데이터λ₯Ό ν™œμš©ν•  수 μžˆλŠ” 둜직 μΆ”κ°€ κ°€λŠ₯
response_gen = respond(message, history, system_message, max_tokens, temperature, top_p)
response = ""
for partial in response_gen:
response = partial
history.append({"role": "assistant", "content": response})
except Exception as e:
response = f"μΆ”λ‘  쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
history.append({"role": "assistant", "content": response})
return history, ""
send_data_upload.click(
handle_message_data_upload,
inputs=[msg_data_upload, chatbot_data_upload, system_message, max_tokens, temperature, top_p, parquet_data_state],
outputs=[chatbot_data_upload, msg_data_upload]
)
# λ„€ 번째 νƒ­: ν…μŠ€νŠΈ to csv to parquet λ³€ν™”
with gr.Tab("ν…μŠ€νŠΈ to csv to parquet λ³€ν™”"):
gr.Markdown("### ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜λ©΄ CSV둜 λ³€ν™˜ ν›„ Parquet으둜 μžλ™ μ „ν™˜λ©λ‹ˆλ‹€.")
with gr.Row():
with gr.Column():
text_input = gr.Textbox(
label="ν…μŠ€νŠΈ μž…λ ₯ (각 행은 `id,text,label,metadata` ν˜•μ‹μœΌλ‘œ μž…λ ₯)",
lines=10,
placeholder="예: 1,Sample Text,Label1,Metadata1\n2,Another Text,Label2,Metadata2"
)
convert_button = gr.Button("λ³€ν™˜ 및 λ‹€μš΄λ‘œλ“œ")
convert_status = gr.Textbox(label="λ³€ν™˜ μƒνƒœ", interactive=False)
parquet_preview_convert = gr.Markdown(label="Parquet 파일 미리보기")
download_parquet_convert = gr.Download(label="Parquet 파일 λ‹€μš΄λ‘œλ“œ")
def handle_text_to_parquet(text: str) -> Tuple[str, str, Tuple[bytes, str]]:
message, parquet_content, file_data = text_to_parquet(text)
if file_data:
filename = 'text_to_parquet.parquet'
return message, parquet_content, (file_data, filename)
else:
return message, "", None
convert_button.click(
handle_text_to_parquet,
inputs=text_input,
outputs=[convert_status, parquet_preview_convert, download_parquet_convert]
)
# 주의 사항
gr.Markdown("## 주의 사항")
gr.Markdown("""
- **CSV μ—…λ‘œλ“œ**: CSV νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λ©΄ μžλ™μœΌλ‘œ Parquet 파일둜 λ³€ν™˜λ©λ‹ˆλ‹€. CSV νŒŒμΌμ€ λ°˜λ“œμ‹œ **콀마(`,`)**둜 κ΅¬λΆ„λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
- **Parquet 미리보기**: μ—…λ‘œλ“œλœ Parquet 파일의 첫 10개 행이 미리보기둜 ν‘œμ‹œλ©λ‹ˆλ‹€.
- **LLM과의 λŒ€ν™”**: λ³€ν™˜λœ Parquet 파일 λ‚΄μš©μ„ 기반으둜 LLM이 응닡을 μƒμ„±ν•©λ‹ˆλ‹€.
- **Parquet λ‹€μš΄λ‘œλ“œ**: λ³€ν™˜λœ Parquet νŒŒμΌμ„ λ‹€μš΄λ‘œλ“œν•˜λ €λ©΄ λ³€ν™˜λœ 파일 μ˜†μ˜ λ‹€μš΄λ‘œλ“œ 링크λ₯Ό ν΄λ¦­ν•˜μ„Έμš”.
- **챗봇 데이터 μ—…λ‘œλ“œ**: 챗봇 데이터 μ—…λ‘œλ“œ νƒ­μ—μ„œ Parquet νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λ©΄ ν•΄λ‹Ή 데이터λ₯Ό 기반으둜 질문과 닡변을 진행할 수 μžˆμŠ΅λ‹ˆλ‹€.
- **ν…μŠ€νŠΈ to csv to parquet**: λ„€ 번째 νƒ­μ—μ„œ ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜λ©΄ μžλ™μœΌλ‘œ CSV둜 λ³€ν™˜λ˜κ³ , λ‹€μ‹œ Parquet 파일둜 μ „ν™˜λ˜μ–΄ λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.
""")
gr.Markdown("### Gradio μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ LLM λͺ¨λΈκ³Ό μƒν˜Έμž‘μš©ν•˜μ„Έμš”!")
if __name__ == "__main__":
# share=TrueλŠ” Hugging Face Spacesμ—μ„œ μ§€μ›λ˜μ§€ μ•ŠμœΌλ―€λ‘œ 제거
demo.launch()