RAGOndevice / app.py
cutechicken's picture
Update app.py
c53bcba verified
raw
history blame
23.7 kB
import torch
import gradio as gr
import spaces
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
import os
from threading import Thread
import random
from datasets import load_dataset
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
from typing import List, Tuple
import json
from datetime import datetime
# GPU ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ
torch.cuda.empty_cache()
# ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •
HF_TOKEN = os.environ.get("HF_TOKEN", None)
MODEL_ID = "CohereForAI/c4ai-command-r7b-12-2024"
MODELS = os.environ.get("MODELS")
MODEL_NAME = MODEL_ID.split("/")[-1]
# ๋ชจ๋ธ๊ณผ ํ† ํฌ๋‚˜์ด์ € ๋กœ๋“œ
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.bfloat16,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
# ์œ„ํ‚คํ”ผ๋””์•„ ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋“œ
wiki_dataset = load_dataset("lcw99/wikipedia-korean-20240501-1million-qna")
print("Wikipedia dataset loaded:", wiki_dataset)
# TF-IDF ๋ฒกํ„ฐ๋ผ์ด์ € ์ดˆ๊ธฐํ™” ๋ฐ ํ•™์Šต
print("TF-IDF ๋ฒกํ„ฐํ™” ์‹œ์ž‘...")
questions = wiki_dataset['train']['question'][:10000] # ์ฒ˜์Œ 10000๊ฐœ๋งŒ ์‚ฌ์šฉ
vectorizer = TfidfVectorizer(max_features=1000)
question_vectors = vectorizer.fit_transform(questions)
print("TF-IDF ๋ฒกํ„ฐํ™” ์™„๋ฃŒ")
class ChatHistory:
def __init__(self):
self.history = []
self.history_file = "/tmp/chat_history.json"
self.load_history()
def add_conversation(self, user_msg: str, assistant_msg: str):
conversation = {
"timestamp": datetime.now().isoformat(),
"messages": [
{"role": "user", "content": user_msg},
{"role": "assistant", "content": assistant_msg}
]
}
self.history.append(conversation)
self.save_history()
def format_for_display(self):
formatted = []
for conv in self.history:
formatted.append([
conv["messages"][0]["content"],
conv["messages"][1]["content"]
])
return formatted
def get_messages_for_api(self):
messages = []
for conv in self.history:
messages.extend([
{"role": "user", "content": conv["messages"][0]["content"]},
{"role": "assistant", "content": conv["messages"][1]["content"]}
])
return messages
def clear_history(self):
self.history = []
self.save_history()
def save_history(self):
try:
with open(self.history_file, 'w', encoding='utf-8') as f:
json.dump(self.history, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"ํžˆ์Šคํ† ๋ฆฌ ์ €์žฅ ์‹คํŒจ: {e}")
def load_history(self):
try:
if os.path.exists(self.history_file):
with open(self.history_file, 'r', encoding='utf-8') as f:
self.history = json.load(f)
except Exception as e:
print(f"ํžˆ์Šคํ† ๋ฆฌ ๋กœ๋“œ ์‹คํŒจ: {e}")
self.history = []
# ์ „์—ญ ChatHistory ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
chat_history = ChatHistory()
def find_relevant_context(query, top_k=3):
# ์ฟผ๋ฆฌ ๋ฒกํ„ฐํ™”
query_vector = vectorizer.transform([query])
# ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ
similarities = (query_vector * question_vectors.T).toarray()[0]
# ๊ฐ€์žฅ ์œ ์‚ฌํ•œ ์งˆ๋ฌธ๋“ค์˜ ์ธ๋ฑ์Šค
top_indices = np.argsort(similarities)[-top_k:][::-1]
# ๊ด€๋ จ ์ปจํ…์ŠคํŠธ ์ถ”์ถœ
relevant_contexts = []
for idx in top_indices:
if similarities[idx] > 0:
relevant_contexts.append({
'question': questions[idx],
'answer': wiki_dataset['train']['answer'][idx],
'similarity': similarities[idx]
})
return relevant_contexts
def analyze_file_content(content, file_type):
"""Analyze file content and return structural summary"""
if file_type in ['parquet', 'csv']:
try:
lines = content.split('\n')
header = lines[0]
columns = header.count('|') - 1
rows = len(lines) - 3
return f"๐Ÿ“Š ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์กฐ: {columns}๊ฐœ ์ปฌ๋Ÿผ, {rows}๊ฐœ ๋ฐ์ดํ„ฐ"
except:
return "โŒ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์กฐ ๋ถ„์„ ์‹คํŒจ"
lines = content.split('\n')
total_lines = len(lines)
non_empty_lines = len([line for line in lines if line.strip()])
if any(keyword in content.lower() for keyword in ['def ', 'class ', 'import ', 'function']):
functions = len([line for line in lines if 'def ' in line])
classes = len([line for line in lines if 'class ' in line])
imports = len([line for line in lines if 'import ' in line or 'from ' in line])
return f"๐Ÿ’ป ์ฝ”๋“œ ๊ตฌ์กฐ: {total_lines}์ค„ (ํ•จ์ˆ˜: {functions}, ํด๋ž˜์Šค: {classes}, ์ž„ํฌํŠธ: {imports})"
paragraphs = content.count('\n\n') + 1
words = len(content.split())
return f"๐Ÿ“ ๋ฌธ์„œ ๊ตฌ์กฐ: {total_lines}์ค„, {paragraphs}๋‹จ๋ฝ, ์•ฝ {words}๋‹จ์–ด"
def read_uploaded_file(file):
if file is None:
return "", ""
try:
file_ext = os.path.splitext(file.name)[1].lower()
if file_ext == '.parquet':
df = pd.read_parquet(file.name, engine='pyarrow')
content = df.head(10).to_markdown(index=False)
return content, "parquet"
elif file_ext == '.csv':
encodings = ['utf-8', 'cp949', 'euc-kr', 'latin1']
for encoding in encodings:
try:
df = pd.read_csv(file.name, encoding=encoding)
content = f"๐Ÿ“Š ๋ฐ์ดํ„ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:\n{df.head(10).to_markdown(index=False)}\n\n"
content += f"\n๐Ÿ“ˆ ๋ฐ์ดํ„ฐ ์ •๋ณด:\n"
content += f"- ์ „์ฒด ํ–‰ ์ˆ˜: {len(df)}\n"
content += f"- ์ „์ฒด ์—ด ์ˆ˜: {len(df.columns)}\n"
content += f"- ์ปฌ๋Ÿผ ๋ชฉ๋ก: {', '.join(df.columns)}\n"
content += f"\n๐Ÿ“‹ ์ปฌ๋Ÿผ ๋ฐ์ดํ„ฐ ํƒ€์ž…:\n"
for col, dtype in df.dtypes.items():
content += f"- {col}: {dtype}\n"
null_counts = df.isnull().sum()
if null_counts.any():
content += f"\nโš ๏ธ ๊ฒฐ์ธก์น˜:\n"
for col, null_count in null_counts[null_counts > 0].items():
content += f"- {col}: {null_count}๊ฐœ ๋ˆ„๋ฝ\n"
return content, "csv"
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"โŒ ์ง€์›๋˜๋Š” ์ธ์ฝ”๋”ฉ์œผ๋กœ ํŒŒ์ผ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ({', '.join(encodings)})")
else:
encodings = ['utf-8', 'cp949', 'euc-kr', 'latin1']
for encoding in encodings:
try:
with open(file.name, 'r', encoding=encoding) as f:
content = f.read()
return content, "text"
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"โŒ ์ง€์›๋˜๋Š” ์ธ์ฝ”๋”ฉ์œผ๋กœ ํŒŒ์ผ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ({', '.join(encodings)})")
except Exception as e:
return f"โŒ ํŒŒ์ผ ์ฝ๊ธฐ ์˜ค๋ฅ˜: {str(e)}", "error"
def read_uploaded_file(file):
if file is None:
return "", ""
try:
file_ext = os.path.splitext(file.name)[1].lower()
if file_ext == '.parquet':
df = pd.read_parquet(file.name)
content = f"๐Ÿ“Š ๋ฐ์ดํ„ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:\n{df.head(10).to_markdown(index=False)}\n\n"
content += f"\n๐Ÿ“ˆ ๋ฐ์ดํ„ฐ ์ •๋ณด:\n"
content += f"- ์ „์ฒด ํ–‰ ์ˆ˜: {len(df)}\n"
content += f"- ์ „์ฒด ์—ด ์ˆ˜: {len(df.columns)}\n"
content += f"- ์ปฌ๋Ÿผ ๋ชฉ๋ก: {', '.join(df.columns)}\n"
return content, "parquet"
elif file_ext == '.csv':
encodings = ['utf-8', 'cp949', 'euc-kr', 'latin1']
for encoding in encodings:
try:
df = pd.read_csv(file.name, encoding=encoding)
content = f"๐Ÿ“Š ๋ฐ์ดํ„ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:\n{df.head(10).to_markdown(index=False)}\n\n"
content += f"\n๐Ÿ“ˆ ๋ฐ์ดํ„ฐ ์ •๋ณด:\n"
content += f"- ์ „์ฒด ํ–‰ ์ˆ˜: {len(df)}\n"
content += f"- ์ „์ฒด ์—ด ์ˆ˜: {len(df.columns)}\n"
content += f"- ์ปฌ๋Ÿผ ๋ชฉ๋ก: {', '.join(df.columns)}\n"
content += f"\n๐Ÿ“‹ ์ปฌ๋Ÿผ ๋ฐ์ดํ„ฐ ํƒ€์ž…:\n"
for col, dtype in df.dtypes.items():
content += f"- {col}: {dtype}\n"
null_counts = df.isnull().sum()
if null_counts.any():
content += f"\nโš ๏ธ ๊ฒฐ์ธก์น˜:\n"
for col, null_count in null_counts[null_counts > 0].items():
content += f"- {col}: {null_count}๊ฐœ ๋ˆ„๋ฝ\n"
return content, "csv"
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"์ง€์›๋˜๋Š” ์ธ์ฝ”๋”ฉ์œผ๋กœ ํŒŒ์ผ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ({', '.join(encodings)})")
else: # ํ…์ŠคํŠธ ํŒŒ์ผ
encodings = ['utf-8', 'cp949', 'euc-kr', 'latin1']
for encoding in encodings:
try:
with open(file.name, 'r', encoding=encoding) as f:
content = f.read()
# ํŒŒ์ผ ๋‚ด์šฉ ๋ถ„์„
lines = content.split('\n')
total_lines = len(lines)
non_empty_lines = len([line for line in lines if line.strip()])
# ์ฝ”๋“œ ํŒŒ์ผ ์—ฌ๋ถ€ ํ™•์ธ
is_code = any(keyword in content.lower() for keyword in ['def ', 'class ', 'import ', 'function'])
if is_code:
# ์ฝ”๋“œ ํŒŒ์ผ ๋ถ„์„
functions = len([line for line in lines if 'def ' in line])
classes = len([line for line in lines if 'class ' in line])
imports = len([line for line in lines if 'import ' in line or 'from ' in line])
analysis = f"\n๐Ÿ“ ์ฝ”๋“œ ๋ถ„์„:\n"
analysis += f"- ์ „์ฒด ๋ผ์ธ ์ˆ˜: {total_lines}\n"
analysis += f"- ํ•จ์ˆ˜ ์ˆ˜: {functions}\n"
analysis += f"- ํด๋ž˜์Šค ์ˆ˜: {classes}\n"
analysis += f"- import ๋ฌธ ์ˆ˜: {imports}\n"
else:
# ์ผ๋ฐ˜ ํ…์ŠคํŠธ ํŒŒ์ผ ๋ถ„์„
words = len(content.split())
chars = len(content)
analysis = f"\n๐Ÿ“ ํ…์ŠคํŠธ ๋ถ„์„:\n"
analysis += f"- ์ „์ฒด ๋ผ์ธ ์ˆ˜: {total_lines}\n"
analysis += f"- ์‹ค์ œ ๋‚ด์šฉ์ด ์žˆ๋Š” ๋ผ์ธ ์ˆ˜: {non_empty_lines}\n"
analysis += f"- ๋‹จ์–ด ์ˆ˜: {words}\n"
analysis += f"- ๋ฌธ์ž ์ˆ˜: {chars}\n"
return content + analysis, "text"
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"์ง€์›๋˜๋Š” ์ธ์ฝ”๋”ฉ์œผ๋กœ ํŒŒ์ผ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ({', '.join(encodings)})")
except Exception as e:
return f"ํŒŒ์ผ ์ฝ๊ธฐ ์˜ค๋ฅ˜: {str(e)}", "error"
# ํŒŒ์ผ ์—…๋กœ๋“œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง ์ˆ˜์ •
def init_msg():
return "ํŒŒ์ผ์„ ๋ถ„์„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."
CSS = """
/* 3D ์Šคํƒ€์ผ CSS */
:root {
--primary-color: #2196f3;
--secondary-color: #1976d2;
--background-color: #f0f2f5;
--card-background: #ffffff;
--text-color: #333333;
--shadow-color: rgba(0, 0, 0, 0.1);
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.container {
transform-style: preserve-3d;
perspective: 1000px;
}
.chatbot {
background: var(--card-background);
border-radius: 20px;
box-shadow:
0 10px 20px var(--shadow-color),
0 6px 6px var(--shadow-color);
transform: translateZ(0);
transition: transform 0.3s ease;
backdrop-filter: blur(10px);
}
.chatbot:hover {
transform: translateZ(10px);
}
/* ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ ์˜์—ญ */
.input-area {
background: var(--card-background);
border-radius: 15px;
padding: 15px;
margin-top: 20px;
box-shadow:
0 5px 15px var(--shadow-color),
0 3px 3px var(--shadow-color);
transform: translateZ(0);
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 10px;
}
.input-area:hover {
transform: translateZ(5px);
}
/* ๋ฒ„ํŠผ ์Šคํƒ€์ผ */
.custom-button {
background: linear-gradient(145deg, var(--primary-color), var(--secondary-color));
color: white;
border: none;
border-radius: 10px;
padding: 10px 20px;
font-weight: 600;
cursor: pointer;
transform: translateZ(0);
transition: all 0.3s ease;
box-shadow:
0 4px 6px var(--shadow-color),
0 1px 3px var(--shadow-color);
}
.custom-button:hover {
transform: translateZ(5px) translateY(-2px);
box-shadow:
0 7px 14px var(--shadow-color),
0 3px 6px var(--shadow-color);
}
/* ํŒŒ์ผ ์—…๋กœ๋“œ ๋ฒ„ํŠผ */
.file-upload-icon {
background: linear-gradient(145deg, #64b5f6, #42a5f5);
color: white;
border-radius: 8px;
font-size: 2em;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 70px;
width: 70px;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.file-upload-icon:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
/* ํŒŒ์ผ ์—…๋กœ๋“œ ๋ฒ„ํŠผ ๋‚ด๋ถ€ ์š”์†Œ ์Šคํƒ€์ผ๋ง */
.file-upload-icon > .wrap {
display: flex !important;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.file-upload-icon > .wrap > p {
display: none !important;
}
.file-upload-icon > .wrap::before {
content: "๐Ÿ“";
font-size: 2em;
display: block;
}
/* ๋ฉ”์‹œ์ง€ ์Šคํƒ€์ผ */
.message {
background: var(--card-background);
border-radius: 15px;
padding: 15px;
margin: 10px 0;
box-shadow:
0 4px 6px var(--shadow-color),
0 1px 3px var(--shadow-color);
transform: translateZ(0);
transition: all 0.3s ease;
}
.message:hover {
transform: translateZ(5px);
}
.chat-container {
height: 600px !important;
margin-bottom: 10px;
}
.input-container {
height: 70px !important;
display: flex;
align-items: center;
gap: 10px;
margin-top: 5px;
}
.input-textbox {
height: 70px !important;
border-radius: 8px !important;
font-size: 1.1em !important;
padding: 10px 15px !important;
display: flex !important;
align-items: flex-start !important; /* ํ…์ŠคํŠธ ์ž…๋ ฅ ์œ„์น˜๋ฅผ ์œ„๋กœ ์กฐ์ • */
}
.input-textbox textarea {
padding-top: 5px !important; /* ํ…์ŠคํŠธ ์ƒ๋‹จ ์—ฌ๋ฐฑ ์กฐ์ • */
}
.send-button {
height: 70px !important;
min-width: 70px !important;
font-size: 1.1em !important;
}
/* ์„ค์ • ํŒจ๋„ ๊ธฐ๋ณธ ์Šคํƒ€์ผ */
.settings-panel {
padding: 20px;
margin-top: 20px;
}
"""
@spaces.GPU
def stream_chat(message: str, history: list, uploaded_file, temperature: float, max_new_tokens: int, top_p: float, top_k: int, penalty: float):
try:
print(f'message is - {message}')
print(f'history is - {history}')
# ํŒŒ์ผ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ
file_context = ""
if uploaded_file and message == "ํŒŒ์ผ์„ ๋ถ„์„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค...":
try:
content, file_type = read_uploaded_file(uploaded_file)
if content:
file_analysis = analyze_file_content(content, file_type)
file_context = f"\n\n๐Ÿ“„ ํŒŒ์ผ ๋ถ„์„ ๊ฒฐ๊ณผ:\n{file_analysis}\n\nํŒŒ์ผ ๋‚ด์šฉ:\n```\n{content}\n```"
message = "์—…๋กœ๋“œ๋œ ํŒŒ์ผ์„ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”."
except Exception as e:
print(f"ํŒŒ์ผ ๋ถ„์„ ์˜ค๋ฅ˜: {str(e)}")
file_context = f"\n\nโŒ ํŒŒ์ผ ๋ถ„์„ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
# ๊ด€๋ จ ์ปจํ…์ŠคํŠธ ์ฐพ๊ธฐ
try:
relevant_contexts = find_relevant_context(message)
wiki_context = "\n\n๊ด€๋ จ ์œ„ํ‚คํ”ผ๋””์•„ ์ •๋ณด:\n"
for ctx in relevant_contexts:
wiki_context += f"Q: {ctx['question']}\nA: {ctx['answer']}\n์œ ์‚ฌ๋„: {ctx['similarity']:.3f}\n\n"
except Exception as e:
print(f"์ปจํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ์˜ค๋ฅ˜: {str(e)}")
wiki_context = ""
# ๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ ๊ตฌ์„ฑ
conversation = []
for prompt, answer in history:
conversation.extend([
{"role": "user", "content": prompt},
{"role": "assistant", "content": answer}
])
# ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ ๊ตฌ์„ฑ
final_message = file_context + wiki_context + "\nํ˜„์žฌ ์งˆ๋ฌธ: " + message
conversation.append({"role": "user", "content": final_message})
# ํ† ํฌ๋‚˜์ด์ € ์„ค์ •
input_ids = tokenizer.apply_chat_template(conversation, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(input_ids, return_tensors="pt").to(0)
streamer = TextIteratorStreamer(tokenizer, timeout=10., skip_prompt=True, skip_special_tokens=True)
generate_kwargs = dict(
inputs,
streamer=streamer,
top_k=top_k,
top_p=top_p,
repetition_penalty=penalty,
max_new_tokens=max_new_tokens,
do_sample=True,
temperature=temperature,
eos_token_id=[255001],
)
thread = Thread(target=model.generate, kwargs=generate_kwargs)
thread.start()
buffer = ""
for new_text in streamer:
buffer += new_text
yield "", history + [[message, buffer]]
except Exception as e:
error_message = f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
print(f"Stream chat ์˜ค๋ฅ˜: {error_message}")
yield "", history + [[message, error_message]]
def create_demo():
with gr.Blocks(css=CSS) as demo:
chatbot = gr.Chatbot(
value=[],
height=600,
label="GiniGEN AI Assistant",
elem_classes="chat-container"
)
with gr.Row(elem_classes="input-container"):
with gr.Column(scale=1, min_width=70):
file_upload = gr.File(
type="filepath",
elem_classes="file-upload-icon",
scale=1,
container=True,
interactive=True,
show_label=False
)
with gr.Column(scale=4):
msg = gr.Textbox(
show_label=False,
placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”... ๐Ÿ’ญ",
container=False,
elem_classes="input-textbox",
scale=1
)
with gr.Column(scale=1, min_width=70):
send = gr.Button(
"์ „์†ก",
elem_classes="send-button custom-button",
scale=1
)
with gr.Accordion("๐ŸŽฎ ๊ณ ๊ธ‰ ์„ค์ •", open=False):
with gr.Row():
with gr.Column(scale=1):
temperature = gr.Slider(
minimum=0, maximum=1, step=0.1, value=0.8,
label="์ฐฝ์˜์„ฑ ์ˆ˜์ค€ ๐ŸŽจ"
)
max_new_tokens = gr.Slider(
minimum=128, maximum=8000, step=1, value=4000,
label="์ตœ๋Œ€ ํ† ํฐ ์ˆ˜ ๐Ÿ“"
)
with gr.Column(scale=1):
top_p = gr.Slider(
minimum=0.0, maximum=1.0, step=0.1, value=0.8,
label="๋‹ค์–‘์„ฑ ์กฐ์ ˆ ๐ŸŽฏ"
)
top_k = gr.Slider(
minimum=1, maximum=20, step=1, value=20,
label="์„ ํƒ ๋ฒ”์œ„ ๐Ÿ“Š"
)
penalty = gr.Slider(
minimum=0.0, maximum=2.0, step=0.1, value=1.0,
label="๋ฐ˜๋ณต ์–ต์ œ ๐Ÿ”„"
)
gr.Examples(
examples=[
["๋‹ค์Œ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ ์„ ์ฐพ์•„๋‚ด๊ณ  ๊ฐœ์„ ๋œ ๋ฒ„์ „์„ ์ œ์‹œํ•ด์ฃผ์„ธ์š”:\ndef fibonacci(n):\n if n <= 1: return n\n return fibonacci(n-1) + fibonacci(n-2)"],
["๋‹ค์Œ ์˜์–ด ๋ฌธ์žฅ์„ ํ•œ๊ตญ์–ด๋กœ ๋ฒˆ์—ญํ•˜๊ณ , ์–ดํœ˜์™€ ๋ฌธ๋ฒ•์  ํŠน์ง•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”: 'The implementation of artificial intelligence in healthcare has revolutionized patient care, yet it raises ethical concerns regarding privacy and decision-making autonomy.'"],
["์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์ธ์‚ฌ์ดํŠธ๋ฅผ ๋„์ถœํ•ด์ฃผ์„ธ์š”:\n์—ฐ๋„๋ณ„ ๋งค์ถœ์•ก(์–ต์›)\n2019: 1200\n2020: 980\n2021: 1450\n2022: 2100\n2023: 1890"],
["๋‹ค์Œ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ SWOT ๋ถ„์„์„ ํ•ด์ฃผ์„ธ์š”: '์ „ํ†ต์ ์ธ ์˜คํ”„๋ผ์ธ ์„œ์ ์ด ์˜จ๋ผ์ธ ํ”Œ๋žซํผ์œผ๋กœ์˜ ์ „ํ™˜์„ ๊ณ ๋ ค์ค‘์ž…๋‹ˆ๋‹ค. ๋…์ž๋“ค์˜ ๋””์ง€ํ„ธ ์ฝ˜ํ…์ธ  ์†Œ๋น„๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ๊ฒฝ์Ÿ๋ ฅ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ธฐ์กด ๊ณ ๊ฐ์ธต๋„ ์ง€ํ‚ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.'"],
["๋‹ค์Œ ์ˆ˜ํ•™ ๋ฌธ์ œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ์ž์„ธํžˆ ํ’€์ดํ•ด์ฃผ์„ธ์š”: 'ํ•œ ์›์˜ ๋„“์ด๊ฐ€ ๊ทธ ์›์— ๋‚ด์ ‘ํ•˜๋Š” ์ •์‚ฌ๊ฐํ˜• ๋„“์ด์˜ 2๋ฐฐ์ผ ๋•Œ, ์›์˜ ๋ฐ˜์ง€๋ฆ„๊ณผ ์ •์‚ฌ๊ฐํ˜•์˜ ํ•œ ๋ณ€์˜ ๊ธธ์ด์˜ ๊ด€๊ณ„๋ฅผ ๊ตฌํ•˜์‹œ์˜ค.'"],
["๋‹ค์Œ SQL ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๊ณ  ๊ฐœ์„ ์ ์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\nSELECT * FROM orders o\nLEFT JOIN customers c ON o.customer_id = c.id\nWHERE YEAR(o.order_date) = 2023\nAND c.country = 'Korea'\nORDER BY o.order_date DESC;"],
["๋‹ค์Œ ๋งˆ์ผ€ํŒ… ์บ ํŽ˜์ธ์˜ ROI๋ฅผ ๋ถ„์„ํ•˜๊ณ  ๊ฐœ์„ ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•ด์ฃผ์„ธ์š”:\n์ด ๋น„์šฉ: 5000๋งŒ์›\n๋„๋‹ฌ์ž ์ˆ˜: 100๋งŒ๋ช…\nํด๋ฆญ๋ฅ : 2.3%\n์ „ํ™˜์œจ: 0.8%\nํ‰๊ท  ๊ตฌ๋งค์•ก: 35,000์›"],
],
inputs=msg
)
# ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ
msg.submit(
stream_chat,
inputs=[msg, chatbot, file_upload, temperature, max_new_tokens, top_p, top_k, penalty],
outputs=[msg, chatbot]
)
send.click(
stream_chat,
inputs=[msg, chatbot, file_upload, temperature, max_new_tokens, top_p, top_k, penalty],
outputs=[msg, chatbot]
)
file_upload.change(
fn=init_msg,
outputs=msg,
queue=False
).then(
fn=stream_chat,
inputs=[msg, chatbot, file_upload, temperature, max_new_tokens, top_p, top_k, penalty],
outputs=[msg, chatbot],
queue=True
)
return demo
if __name__ == "__main__":
demo = create_demo()
demo.launch()