소개
Qwen 언어 모델 시리즈는 다양한 자연어 처리 작업에 활용할 수 있는 강력한 오픈소스 LLM을 제공합니다.
이 글에서는 Qwen1.5-7B-Chat 모델을 기반으로 한 개인 비서 애플리케이션을 Python 환경에서 설정하고 실행하는 방법을 안내합니다.
이 모델은 70억 개 파라미터를 가진 비교적 가벼운 챗봇 특화 모델로, 대화형 용도에 최적화되어 있습니다.
예제 코드는 Google Colab과 같은 Python 노트북 환경에서 바로 실행할 수 있도록 구성되어 있으며,
원한다면 로컬 환경으로도 쉽게 이식하여 사용할 수 있습니다.
코딩 구현
Qwen 기반의 개인 비서를 구축하려면 여러 가지 의존성 패키지와 라이브러리 설치가 필요합니다.
따라서 가장 먼저 해야 할 일은 이들 라이브러리를 설치하고, 이미 설치되어 있을 수 있는 버전들과의 호환성을 최대한 확보하기 위해 버전 정보를 확인하는 것입니다.
pip install -q transformers accelerate bitsandbytes einops ipywidgets
초기 설정: GPU 활용 및 의존성 확인
모델 추론 속도를 높이기 위해, 사용 가능한 경우 GPU(CUDA) 를 자동으로 감지해 우선적으로 할당합니다.
이는 모델이 처음 호출되는 시점부터 적용되며, 특히 Colab이나 로컬 GPU 환경에서 성능 향상에 매우 효과적입니다.
또한, Qwen 모델을 실행하기 위해 필요한 필수 패키지 설치 및 버전 확인 과정도 함께 진행합니다.
# 기본 라이브러리 임포트
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import time
from IPython.display import display, HTML, clear_output
import ipywidgets as widgets
import sys
import os
# bitsandbytes 설치 확인 및 자동 설치
try:
import bitsandbytes as bnb
print("Successfully imported bitsandbytes")
except ImportError:
print("Error importing bitsandbytes. Attempting to install again...")
!pip install -q bitsandbytes --upgrade
import bitsandbytes as bnb
# (이미 설치되어 있다면 생략 가능) 필수 패키지 설치
!pip install -q transformers accelerate bitsandbytes einops ipywidgets
# 디바이스 설정: GPU(CUDA) 우선 적용, 없으면 CPU 사용
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
모델 불러오기 및 구성
이제 모델을 불러오고 설정할 차례입니다.
이번에 사용할 모델은 Qwen/Qwen1.5-7B-Chat 으로,
같은 계열의 고성능 모델인 Qwen2.5-Omni보다 가볍고 초기 추론 속도가 빠른 장점이 있습니다.
Omni 모델은 막강한 성능을 자랑하지만, 리소스 측면에서 조금 더 무거운 편입니다.
# Qwen1.5-7B-Chat 모델 로딩 - Colab T4 GPU에서 실행 가능
model_name = "Qwen/Qwen1.5-7B-Chat"
print(f"Loading {model_name}...")
start_time = time.time()
# 1. 토크나이저 로딩
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# 2. 모델 로딩 시도 - 4bit → 실패 시 8bit → 실패 시 일반 로딩
try:
print("Attempting to load model with 4-bit quantization...")
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16, # 성능 향상을 위한 bfloat16 사용
device_map="auto",
trust_remote_code=True,
quantization_config={"load_in_4bit": True} # 4-bit 양자화 시도
)
except Exception as e:
print(f"4-bit quantization failed with error: {str(e)}")
print("Falling back to 8-bit quantization...")
try:
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
trust_remote_code=True,
load_in_8bit=True # 8-bit로 대체 시도
)
except Exception as e2:
print(f"8-bit quantization failed with error: {str(e2)}")
print("Falling back to standard loading (will use more memory)...")
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
trust_remote_code=True
)
# 3. 로딩 시간 출력
load_time = time.time() - start_time
print(f"Model loaded in {load_time:.2f} seconds")
기본 프롬프트 설정하기
자신만의 대화형 어시스턴트를 만들 때는,
각 요청에 공통적으로 포함되는 기본 프롬프트(default prompt) 를 설정해
모델의 응답 스타일과 행동을 일관되게 조정하는 것이 좋은 관행입니다.
기본 프롬프트는 대화의 맥락을 잡아주고, 어시스턴트가 어떤 역할을 수행할지 명확히 지시하는 데 사용됩니다.
대화 흐름 관리: 응답 생성 함수 정의하기
다음으로 정의할 함수는 실행 흐름에서 가장 무거운 작업,
즉 모델이 사용자 입력을 받아 추론(inference)을 수행하고 응답을 생성하는 부분을 담당합니다.
특히 이 함수는 단발성 입력이 아닌, 연속적인 대화 세션(conversational session) 을 처리하기 위한 구조로 설계됩니다.
따라서 이전 대화 기록(chat history)을 함께 관리하고, 매 요청마다 이를 새 입력에 포함시키는 방식이 매우 중요합니다.
def generate_response(user_input, chat_history=None):
if chat_history is None:
chat_history = []
# 1. 시스템 프롬프트 포함하여 초기 메시지 구성
messages = [{"role": "system", "content": system_prompt}]
# 2. 기존 대화 기록(chat history)을 메시지에 추가
for message in chat_history:
messages.append(message)
# 3. 현재 사용자 입력 추가
messages.append({"role": "user", "content": user_input})
# 4. 메시지를 모델 입력 형식으로 변환 (토크나이징 전용 템플릿 사용)
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
inputs = tokenizer(prompt, return_tensors="pt").to(device)
# 5. 모델 추론 수행 (처음은 다소 시간이 걸릴 수 있음)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=512, # 생성할 최대 토큰 수
do_sample=True, # 샘플링 활성화 (더 자연스러운 응답 유도)
temperature=0.7, # 창의성 조절
top_p=0.9, # 상위 확률 누적 컷오프
pad_token_id=tokenizer.pad_token_id or tokenizer.eos_token_id
)
# 6. 토큰을 텍스트로 디코딩
full_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
# 7. 어시스턴트의 응답만 추출 (사용자 입력 이후 텍스트 기준)
assistant
인터랙티브 UI 구성하기: 사용자 입력과 응답을 실시간으로 주고받기
응답을 생성하는 핵심 함수 generate_response() 를 정의했다면,
이제는 이를 활용할 수 있는 간단한 사용자 인터페이스(UI) 를 구성해봅니다.
# 개인 어시스턴트용 간단한 UI 생성 함수
def create_assistant_ui():
output = widgets.Output() # 대화 내용 출력용 위젯
input_box = widgets.Text(
value='',
placeholder='Ask me anything...',
description='Question:',
layout=widgets.Layout(width='80%')
)
send_button = widgets.Button(description="Send")
clear_button = widgets.Button(description="Clear Chat")
chat_history = [] # 대화 기록 저장
# 전송 버튼 클릭 시 호출되는 함수
def on_send_button_clicked(b):
user_input = input_box.value
if not user_input.strip():
return
with output:
print(f"You: {user_input}")
print("Assistant: Thinking...", end="\r") # 응답 대기 표시
start_time = time.time()
try:
response = generate_response(user_input, chat_history)
end_time = time.time()
clear_output(wait=True) # 기존 출력 지우기
print(f"You: {user_input}")
print(f"Assistant: {response}")
print(f"\n(Response generated in {end_time - start_time:.2f} seconds)")
# 대화 기록 업데이트
chat_history.append({"role": "user", "content": user_input})
chat_history.append({"role": "assistant", "content": response})
except Exception as e:
clear_output(wait=True)
print(f"You: {user_input}")
print(f"Error generating response: {str(e)}")
import traceback
traceback.print_exc()
input_box.value = '' # 입력창 초기화
# 대화 초기화 버튼 클릭 시
def on_clear_button_clicked(b):
with output:
clear_output()
print("Chat cleared!")
chat_history.clear()
# 버튼 클릭 이벤트 연결
send_button.on_click(on_send_button_clicked)
clear_button.on_click(on_clear_button_clicked)
# Enter 키 입력 처리
def on_enter(sender):
on_send_button_clicked(None)
input_box.on_submit(on_enter)
# UI 구성 정렬
input_row = widgets.HBox([input_box, send_button, clear_button])
ui = widgets.VBox([output, input_row])
return ui
아래는 주어진 문장을 한국어 기술 블로그 스타일로 자연스럽게 번역한 내용입니다. 앞에서 다룬 ipywidgets 기반 인터페이스와 대비하여, CLI 대화 흐름을 추가로 소개하는 부분입니다:
# CLI 환경에서 Qwen 챗봇과 대화하는 간단한 루프 함수
def cli_chat():
print("\n=== Starting CLI Chat (type 'exit' to quit) ===")
chat_history = []
while True:
user_input = input("\nYou: ")
if user_input.lower() in ['exit', 'quit', 'q']:
print("Goodbye!")
break
print("Assistant: ", end="")
try:
start_time = time.time()
response = generate_response(user_input, chat_history)
end_time = time.time()
print(f"{response}")
print(f"(Generated in {end_time - start_time:.2f} seconds)")
# 대화 기록 업데이트
chat_history.append({"role": "user", "content": user_input})
chat_history.append({"role": "assistant", "content": response})
except Exception as e:
print(f"Error: {str(e)}")
import traceback
traceback.print_exc()
1. 모델 및 환경 점검용 빠른 테스트 함수
Qwen 모델이 제대로 로드되었는지, 필수 라이브러리들이 정상적으로 작동하는지를 확인하려면,
간단한 테스트용 함수를 작성해 초기 설정 상태를 빠르게 점검할 수 있습니다.
2. 전체 어시스턴트 실행 함수: UI 또는 CLI 선택 실행
어시스턴트 전체 애플리케이션을 실행할 수 있도록,
UI(위젯 기반) 또는 CLI(터미널 기반) 중 원하는 인터페이스를 선택적으로 실행할 수 있는 통합 함수도 정의해봅니다.
# 간단한 테스트 쿼리로 모델 상태 확인
def quick_test():
test_question = "What can you help me with?"
print(f"\nTest Question: {test_question}")
start_time = time.time()
try:
response = generate_response(test_question)
end_time = time.time()
print(f"Response: {response}")
print(f"Generation time: {end_time - start_time:.2f} seconds")
return True
except Exception as e:
print(f"Test failed with error: {str(e)}")
import traceback
traceback.print_exc()
return False
# 전체 어시스턴트 실행 함수: 인터페이스 선택 포함
def run_assistant():
print("\nRunning quick test...")
test_success = quick_test()
if test_success:
# 사용자에게 인터페이스 방식 선택 받기
interface_choice = input("\nChoose interface (1 for UI, 2 for CLI): ")
if interface_choice == "2":
cli_chat()
else:
print("\nStarting the personal assistant UI...")
assistant_ui = create_assistant_ui()
display(assistant_ui)
# UI 사용법 안내
print("\n--- 사용법 ---")
print("1. 텍스트 상자에 질문을 입력하세요")
print("2. Enter 키
직접 사용해보기: Qwen 어시스턴트와의 대화 시작!
이제 모든 준비가 잘 완료되었다면,
드디어 우리가 만든 개인 AI 어시스턴트와 직접 대화해볼 차례입니다.
설치, 설정, 모델 로딩까지 모두 문제없이 진행되었다면 이제부터는 즐기기만 하면 됩니다!