import gradio as gr import torch from transformers import ( AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer, LlamaTokenizer, ) import os from threading import Thread import spaces import subprocess # flash-attn 라이브러리 설치. CUDA 빌드는 건너뜀. subprocess.run( "pip install flash-attn --no-build-isolation", env={"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"}, shell=True, ) # Hugging Face 토큰 가져오기 token = os.environ["HF_TOKEN"] # apple/OpenELM-270M 모델과 토크나이저 로드 # 토크나이저가 오류나는 문제가 있어서 NousResearch/Llama-2-7b-hf를 씀 # 한국어 모델 토크나이저로 바꿔봄 beomi/llama-2-ko-7b # apple/OpenELM-1.1B 토크나이저만 크게 해봄 <- 안됨 # OpenELM-3B-Instruct로 둘다 변경경 model = AutoModelForCausalLM.from_pretrained( "apple/OpenELM-3B-Instruct", token=token, trust_remote_code=True, ) tok = AutoTokenizer.from_pretrained( "apple/OpenELM-3B-Instruct", token=token, trust_remote_code=True, tokenizer_class=LlamaTokenizer, ) # 종료 토큰 ID 설정 terminators = [ tok.eos_token_id, ] # GPU가 사용 가능한 경우 GPU로, 아니면 CPU로 모델 로드 if torch.cuda.is_available(): device = torch.device("cuda") print(f"Using GPU: {torch.cuda.get_device_name(device)}") else: device = torch.device("cpu") print("Using CPU") model = model.to(device) # Spaces의 GPU 자원을 사용하여 chat 함수 실행. 최대 60초 동안 GPU 자원 사용 가능. @spaces.GPU(duration=60) def chat(message, history, temperature, do_sample, max_tokens): # 채팅 기록을 적절한 형식으로 변환 chat = [] for item in history: chat.append({"role": "user", "content": item[0]}) if item[1] is not None: chat.append({"role": "assistant", "content": item[1]}) chat.append({"role": "user", "content": message}) # 토크나이저를 사용하여 입력 처리 messages = tok.apply_chat_template(chat, tokenize=False, add_generation_prompt=True) model_inputs = tok([messages], return_tensors="pt").to(device) # TextIteratorStreamer를 사용하여 모델 출력 스트리밍 streamer = TextIteratorStreamer( tok, timeout=20.0, skip_prompt=True, skip_special_tokens=True ) # 생성 관련 매개변수 설정 generate_kwargs = dict( model_inputs, streamer=streamer, max_new_tokens=max_tokens, # 생성할 최대 새 토큰 수 do_sample=True, # 샘플링 여부 temperature=temperature, # 온도 매개변수. 높을수록 다양성 증가 eos_token_id=terminators, # 종료 토큰 ID ) # 온도가 0이면 샘플링하지 않음 if temperature == 0: generate_kwargs["do_sample"] = False # 별도 스레드에서 모델 생성 시작 t = Thread(target=model.generate, kwargs=generate_kwargs) t.start() # 생성된 텍스트를 반복적으로 yield partial_text = "" for new_text in streamer: partial_text += new_text yield partial_text yield partial_text # Gradio의 ChatInterface를 사용하여 대화형 인터페이스 생성 demo = gr.ChatInterface( fn=chat, examples=[["let's talk about korea"]], additional_inputs_accordion=gr.Accordion( label="⚙️ Parameters", open=False, render=False ), additional_inputs=[ gr.Slider( minimum=0, maximum=1, step=0.1, value=0.7, label="Temperature", render=False ), gr.Checkbox(label="Sampling", value=True), gr.Slider( minimum=128, maximum=4096, step=1, value=512, label="Max new tokens", render=False, ), ], stop_btn="Stop Generation", title="Chat With LLMs", description="Now Running [apple/OpenELM-270M](https://huggingface.co/apple/OpenELM-270M)", ) # Gradio 인터페이스 실행 demo.launch()