# 기본 Kivy 및 Ollama 관련 모듈 import
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.clock import Clock
from kivy.core.clipboard import Clipboard
from kivy.config import Config
from kivy.core.window import Window
import threading
import ollama
import os
# ✅ 초기 윈도우 크기 설정 (시작 전 설정 필요)
Config.set('graphics', 'width', '800')
Config.set('graphics', 'height', '1024')
# ✅ 폰트 경로 설정
FONT_PATH = os.path.join(os.path.dirname(__file__), 'fonts', 'NotoSansKR-Regular.ttf')
# ✅ 출력 텍스트 정리 함수 (줄바꿈 허용, 이모지/비표준 제거)
def clean_text(text):
return ''.join(c for c in text if c.isprintable() or c == '\n')
# ✅ 메인 레이아웃 클래스 정의
class ChatLayout(BoxLayout):
def __init__(self, **kwargs):
super().__init__(orientation='vertical', **kwargs)
# ✅ 실행 중 윈도우 사이즈 설정 (보완용)
Window.size = (800, 1024)
# ✅ 질문 입력 필드
self.input = TextInput(
hint_text='질문을 입력하세요',
size_hint=(1, 0.11),
multiline=False,
font_name=FONT_PATH
)
# ✅ 질문하기 버튼
self.button = Button(
text='질문하기',
size_hint=(1, 0.1),
font_name=FONT_PATH
)
self.button.bind(on_press=self.ask_model)
# ✅ 복사 버튼
self.copy_button = Button(
text='답변 복사하기',
size_hint=(1, 0.08),
font_name=FONT_PATH
)
self.copy_button.bind(on_press=self.copy_answer)
# ✅ 스크롤 가능한 답변 영역
self.scroll = ScrollView(size_hint=(1, 0.68))
self.output = Label(
text='답변이 여기에 표시됩니다',
font_name=FONT_PATH,
size_hint_y=None, # height를 직접 제어 가능하게 설정
halign='left',
valign='top',
markup=True # 줄바꿈 등 마크업 반영
)
self.output.bind(texture_size=self.update_height)
self.scroll.add_widget(self.output)
# ✅ 전체 UI 구성
self.add_widget(self.input)
self.add_widget(self.button)
self.add_widget(self.copy_button)
self.add_widget(self.scroll)
# ✅ 텍스트 영역 크기 자동 조정 설정
Clock.schedule_once(self.set_text_width, 0)
self.scroll.bind(width=self.set_text_width)
# ✅ 텍스트 너비 설정
def set_text_width(self, *args):
self.output.text_size = (self.scroll.width - 20, None)
self.output.texture_update()
# ✅ 텍스트 높이 자동 반영 (스크롤뷰 내에서 줄 수에 따라 높이 조절)
def update_height(self, *args):
self.output.height = self.output.texture_size[1]
self.output.canvas.ask_update()
# ✅ 질문 버튼 클릭 시 호출
def ask_model(self, instance):
question = self.input.text.strip()
if question:
self.output.text = '답변을 생성 중입니다...\n\n'
App.get_running_app().root_window.set_title("질문 처리 중...")
# ✅ 백그라운드 스레드로 처리 (UI 멈춤 방지)
threading.Thread(target=self.query_ollama, args=(question,)).start()
# ✅ Ollama API를 통한 응답 처리
def query_ollama(self, question):
try:
response = ollama.generate(
model='rabbit-ko',
prompt=question + "\n\n자세히 설명해줘. 줄바꿈 포함해서 길게 써줘.",
stream=False,
options={'num_predict': 12000} # ✅ 최대 토큰 수 설정 (응답 길이 제한 완화)
)
# 응답 텍스트 정리
answer = clean_text(response['response'])
# ✅ 메인 UI 스레드에서 Label 업데이트
def update_ui(dt):
self.output.text = answer
App.get_running_app().root_window.set_title("Llama")
Clock.schedule_once(update_ui, 0)
except Exception as e:
# ✅ 오류 발생 시 UI에 표시
def show_error(dt):
self.output.text = f"[오류 발생]\n{str(e)}"
App.get_running_app().root_window.set_title("Llama")
Clock.schedule_once(show_error, 0)
# ✅ 복사 버튼 클릭 시 클립보드에 저장
def copy_answer(self, instance):
Clipboard.copy(self.output.text)
self.copy_button.text = '복사 완료!'
# ✅ 앱 실행 클래스
class LlamaApp(App):
def build(self):
return ChatLayout()
# ✅ 앱 실행 시작
if __name__ == '__main__':
LlamaApp().run()
'PYTHON(파이썬) > TKINTER & KIVY' 카테고리의 다른 글
Google Sheet 사용 (credentials.json) (0) | 2024.10.30 |
---|---|
kivy & opencv (camera & cctv) (2) | 2024.10.29 |
kivy로 윈도우용 GUI 구현하기 (1) | 2024.10.29 |
GUI 툴 kivy란? (크로스 플랫폼) (9) | 2024.10.29 |
tkinter를 APP로 전환은? (1) | 2024.10.29 |