Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import torch | |
| from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig | |
| from peft import PeftModel | |
| # ๋ชจ๋ธ ์ค์ (์ฌ๊ธฐ๋ฅผ ์์ ํ์ธ์!) | |
| MODELS = { | |
| # ======================================== | |
| # 03๋ฒ: ํ๊ตญ์ด ์์ฝ (EXAONE-3.5) | |
| # ======================================== | |
| "ํ๊ตญ์ด ์์ฝ (03๋ฒ)": { | |
| "base_model": "LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct", | |
| "lora_path": "ryanu/exaone-summary-lora", # TODO: ๋ณธ์ธ ๊ฒฝ๋ก๋ก! | |
| "prompt_template": "{input}\n\n์์ฝ:", | |
| "max_new_tokens": 60, | |
| "placeholder": "๋ด์ค ๊ธฐ์ฌ๋ฅผ ์ ๋ ฅํ์ธ์...", | |
| "example": "์์ธ์๊ฐ ๋ด๋ ๋ถํฐ ์ ๊ธฐ์ฐจ ์ถฉ์ ์๋ฅผ ๋ํญ ํ๋ํ๋ค.", | |
| }, | |
| # ======================================== | |
| # 05๋ฒ: ๋ค์ค ๋ชจ๋ธ ๋น๊ต (์ ํ์ฌํญ) | |
| # ======================================== | |
| # "Granite ์์ฝ (05๋ฒ)": { | |
| # "base_model": "ibm-granite/granite-4.0-micro", | |
| # "lora_path": "your-username/granite-summary-lora", | |
| # "prompt_template": "<|user|>\n{input}\n\n์ ๊ธฐ์ฌ๋ฅผ ์์ฝํด์ฃผ์ธ์.<|assistant|>\n", | |
| # "max_new_tokens": 60, | |
| # "placeholder": "๋ด์ค ๊ธฐ์ฌ๋ฅผ ์ ๋ ฅํ์ธ์...", | |
| # "example": "์์ธ์๊ฐ ๋ด๋ ๋ถํฐ ์ ๊ธฐ์ฐจ ์ถฉ์ ์๋ฅผ ๋ํญ ํ๋ํ๋ค.", | |
| # }, | |
| # "Qwen3 ์์ฝ (05๋ฒ)": { | |
| # "base_model": "Qwen/Qwen3-4B-Instruct-2507", | |
| # "lora_path": "your-username/qwen3-summary-lora", | |
| # "prompt_template": "<|im_start|>user\n{input}\n\n์ ๊ธฐ์ฌ๋ฅผ ์์ฝํด์ฃผ์ธ์.<|im_end|>\n<|im_start|>assistant\n", | |
| # "max_new_tokens": 60, | |
| # "placeholder": "๋ด์ค ๊ธฐ์ฌ๋ฅผ ์ ๋ ฅํ์ธ์...", | |
| # "example": "์์ธ์๊ฐ ๋ด๋ ๋ถํฐ ์ ๊ธฐ์ฐจ ์ถฉ์ ์๋ฅผ ๋ํญ ํ๋ํ๋ค.", | |
| # }, | |
| # ======================================== | |
| # 06๋ฒ: ๊ฐ์ ๋ถ๋ฅ + ์์ด QA | |
| # ======================================== | |
| "๊ฐ์ ๋ถ๋ฅ (06๋ฒ)": { | |
| "base_model": "LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct", | |
| "lora_path": "your-username/lora-sentiment", | |
| "prompt_template": "๋ค์ ์ํ ๋ฆฌ๋ทฐ์ ๊ฐ์ ์ ๋ถ๋ฅํ์ธ์.\n\n๋ฆฌ๋ทฐ: {input}\n\n๊ฐ์ :", | |
| "max_new_tokens": 10, | |
| "placeholder": "์ํ ๋ฆฌ๋ทฐ๋ฅผ ์ ๋ ฅํ์ธ์...", | |
| "example": "This movie was amazing! Great story and excellent acting.", | |
| }, | |
| "์์ด QA (06๋ฒ)": { | |
| "base_model": "LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct", | |
| "lora_path": "your-username/lora-qa", | |
| "prompt_template": "Context: The Eiffel Tower is in Paris, France.\n\nQuestion: {input}\n\nAnswer:", | |
| "max_new_tokens": 30, | |
| "placeholder": "์ง๋ฌธ์ ์ ๋ ฅํ์ธ์...", | |
| "example": "Where is the Eiffel Tower located?", | |
| }, | |
| } | |
| loaded_models = {} | |
| def load_model(model_name): | |
| if model_name in loaded_models: | |
| return loaded_models[model_name] | |
| config = MODELS[model_name] | |
| tokenizer = AutoTokenizer.from_pretrained(config["base_model"], use_fast=False) | |
| if tokenizer.pad_token is None: | |
| tokenizer.pad_token = tokenizer.eos_token | |
| quant_config = BitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_use_double_quant=True, | |
| bnb_4bit_quant_type="nf4", | |
| bnb_4bit_compute_dtype=torch.bfloat16, | |
| ) | |
| base_model = AutoModelForCausalLM.from_pretrained( | |
| config["base_model"], | |
| device_map="auto", | |
| trust_remote_code=True, | |
| quantization_config=quant_config, | |
| ) | |
| model = PeftModel.from_pretrained(base_model, config["lora_path"]) | |
| loaded_models[model_name] = (model, tokenizer, config) | |
| return model, tokenizer, config | |
| def generate_response(model_name, user_input): | |
| try: | |
| model, tokenizer, config = load_model(model_name) | |
| prompt = config["prompt_template"].format(input=user_input) | |
| inputs = tokenizer(prompt, return_tensors="pt").to(model.device) | |
| with torch.no_grad(): | |
| outputs = model.generate( | |
| **inputs, | |
| max_new_tokens=config["max_new_tokens"], | |
| temperature=0.7, | |
| do_sample=True, | |
| pad_token_id=tokenizer.eos_token_id, | |
| ) | |
| result = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
| # ํ๋กฌํํธ ์ ๊ฑฐ | |
| if "์์ฝ:" in result: | |
| return result.split("์์ฝ:")[-1].strip() | |
| elif "๊ฐ์ :" in result: | |
| return result.split("๊ฐ์ :")[-1].strip() | |
| elif "Answer:" in result: | |
| return result.split("Answer:")[-1].strip() | |
| elif "<|assistant|>" in result: | |
| return result.split("<|assistant|>")[-1].strip() | |
| elif "<|im_start|>assistant" in result: | |
| return result.split("<|im_start|>assistant")[-1].replace("<|im_end|>", "").strip() | |
| else: | |
| return result[len(prompt):].strip() | |
| except Exception as e: | |
| return f"โ ์ค๋ฅ: {str(e)}" | |
| with gr.Blocks(title="LoRA ๋ชจ๋ธ ๋ฐ๋ชจ") as demo: | |
| gr.Markdown("# ๐ค LoRA ํ์ธํ๋ ๋ชจ๋ธ ๋ฐ๋ชจ") | |
| gr.Markdown("Day 1์์ ํ์ตํ ์ฌ๋ฌ LoRA ๋ชจ๋ธ์ ํ ์คํธํด๋ณด์ธ์!") | |
| with gr.Row(): | |
| with gr.Column(): | |
| model_dropdown = gr.Dropdown( | |
| choices=list(MODELS.keys()), | |
| value=list(MODELS.keys())[0], | |
| label="๐ ๋ชจ๋ธ ์ ํ" | |
| ) | |
| input_text = gr.Textbox(label="๐ฌ ์ ๋ ฅ", lines=5) | |
| submit_btn = gr.Button("๐ ์คํ", variant="primary") | |
| with gr.Column(): | |
| output_text = gr.Textbox(label="โจ ๊ฒฐ๊ณผ", lines=10) | |
| submit_btn.click( | |
| fn=generate_response, | |
| inputs=[model_dropdown, input_text], | |
| outputs=[output_text] | |
| ) | |
| demo.launch() | |