Python

[Python 프로젝트] 맛집 리뷰 자동화 만들기 #3 AI 연동하기

creato 2024. 12. 11. 23:17
728x90
반응형
SMALL
 

[Python 프로젝트] 맛집 리뷰 자동화 만들기 #2 GUI 만들기

[Python 프로젝트] 맛집 리뷰 자동화 만들기 #1 함수 맛보기예전에 내 맛집 포스팅을 보고는 내용이 비슷비슷하여사진만 넣으면 알아서 써주는 프로그램을 만들어보라고지나가던 말을 해주던 사

creatolog.tistory.com

아마 이번 프로젝트 마지막 시리즈 AI 연동하기.

지난 시간에 만든 GUI에 Ollama AI를 추가해 보겠다!

뤼튼이 알려주는 정보 다 받아쓰기.

 

 

1. 이전 버전 소개

- 1편 : 기본적인 리뷰 작성 기능 구현

- 2편 : tkinter로 GUI 환경 만들기

- 3편 : AI로 더 똑똑해진 리뷰 작성!

 

 

2. Ollama AI 소개

- 로컬에서 실행되는 오픈소스 AI

- API 키가 필요 없어 편리

- 한국어 지원도 가능

 

 

3. 우분투(Ubuntu)란?

- 리눅스 기반 무료 운영체제

- 개발자들이 가장 많이 쓰는 OS 중 하나!

- AI 개발 환경으로 딱

 

 

4. 왜 우분투가 필요할까?

- Ollama AI가 우분투에서 잘 돌아감

- 파이썬 개발 환경이 깔끔

- 무료라서 부담 없이 사용할 수 있음

 

 

5. WSL2 설치하기

- Windows 검색창에서 'Windows 기능'

- 'Linux용 Windows 하위 시스템' 체크

- 재부팅하기

 

 

6. Microsoft Store 실행

- 검색창에 'Ubuntu' 입력

 

 

7. 우분투 초기 설정
  • PowerShell 관리자 권한으로 실행
wsl --install

- 개발 환경 구성하는 거 너무 어렵습니다.

- 뭔가 이것저것 많이 했는데 필요한 건지 안 필요한 건지 모르겠음.

- 바이오스 어쩌고 저쩌고 나타나서 바이오스 설정 들어갑니다.

- SVM Mode 사용으로 바꿔줍니다. 진짜 별 걸 다 해봅니다.

- 뤼튼이 계속 사용자 설정부터 나온다 했는데 안 나와서 왜 그랬나 했는데 가상화 설정 때문이었고.

- 드디어 제대로 나타나니 해봅니다.

 

 

8. Ollama 설치

- 우분투 실행은 PowerShell 관리자 권한 실행 후 ubuntu 치면 됩니다.

sudo apt update
sudo apt upgrade
curl https://ollama.ai/install.sh | sh
ollama run mistral

 

 

9. Ollama API 연결
import requests
class ReviewMaker:
    def __init__(self):
        self.ollama_url = 'http://localhost:11434/api/generate'
def generate_review(self, prompt):
        payload = {
            "model": "mistral",
            "prompt": prompt,
            "stream": False
        }
        
        response = requests.post(self.ollama_url, json=payload)
        return response.json()['response']
def create_prompt_template(self, store_name, location, atmosphere, price_range, menu_items):
        menu_list = [f"{menu} ({price}원)" for menu, price in menu_items]
        
        template = f"""
        다음 정보로 맛집 리뷰를 작성해줘:
        가게 : {store_name}
        위치 : {location}
        분위기 : {atmosphere}
        가격대 : {price_range}
        메뉴 : {','.join(menu_list)}
        
        리뷰는 자연스럽고 솔직하게, 300자 내외로 작성해줘.
        """
        return template

- 뤼튼 씨, 우리 어제 만든 거 어떻게 만든 지 기억 못 해서 내가 계속 첨삭해줘야 함.

- 입력받기로 한 항목 기억 못 해서 소스 이상하게 만들어서 내가 계속 이건 이렇게 받기로 했어 수정함.

- 나 그래도 소스 작성할 줄은 몰라도 의미는 알아서 수정해달하고 할 줄은 안다고?

def generate_button_click(self):
        menu_items = [(menu.get().strip(), price.get().strip())
                      for menu, price in self.menu_rows
                      if menu.get().strip() and price.get().strip()]
        
        prompt = self.create_prompt_template(
            self.entries['가게명:'].get().strip(),
            self.entries['위치:'].get().strip(),
            self.entries['분위기:'].get().strip(),
            self.entries['가격대:'].get().strip(),
            menu_items
        )
        
        review = self.generate_review(prompt)
        self.review_text.delete(1.0, END)
        self.review_text.insert(END, review)

- 결국 어제 만들었던 함수 복붙해서 먹여서 정확도를 높였다^^

- 어제와 같은 모습인 것 같지만 3.0으로 버전을 올렸다.

- 열심히 빈칸을 채운 후 리뷰 생성을 눌러보겠습니다.

ollama puu llama2

- PowerShell 실행 후 ollama 켜주시고

- 네이버 지도 켜고 아무 가게나 눌러서 입력해 봅니다.

- 컴퓨터가 좋은 컴퓨터가 아니라 시간이 엄청 걸립니다.

- 토큰으로 와서 토큰 조합하는 작업도 해줬습니다.

- 이제 텍스트 박스 크기도 키우고 스크롤바도 넣어줄 예정.

- 근데 이 친구 영어밖에 할 줄 모르나 봄.

import json
import requests

import tkinter as tk
from tkinter import ttk

class ReviewMaker:
    def __init__(self):
        self.ollama_url = 'http://localhost:11434/api/generate'
        
        self.window = tk.Tk()
        self.window.title("리뷰 메이커 v3.0")
        self.basic_info()
        self.menu_info()
        self.create_review() # 여기 추가
        self.window.mainloop()
    
    def generate_button_click(self):
        try:
            
            menu_items = [(menu.get().strip(), price.get().strip())
                        for menu, price in self.menu_rows
                        if menu.get().strip() and price.get().strip()]
            
            prompt = self.create_prompt_template(
                self.entries['가게명:'].get().strip(),
                self.entries['위치:'].get().strip(),
                self.entries['분위기:'].get().strip(),
                self.entries['가격대:'].get().strip(),
                menu_items
            )
            
            review = self.generate_review(prompt)
            self.review_text.delete(1.0, tk.END)
            self.review_text.insert(tk.END, review)
            self.review_text.update()
        except Exception as e:
            self.review_text.insert("1.0", f"에러: {str(e)}")
    
    def generate_review(self, prompt):
        payload = {
            "model": "llama2",
            "prompt": prompt
        }
        
        response = requests.post(self.ollama_url, json=payload)
        print("응답내용:", response.text)
        
        response_text = ""
        for line in response.text.split('\n'):
            if line:
                try:
                    data = json.loads(line)
                    response_text += data.get("response","")
                except:
                    continue
        print("완성된 텍스트:", response_text)
        return response_text
    
    def create_prompt_template(self, store_name, location, atmosphere, price_range, menu_items):
        menu_list = [f"{menu} ({price}원)" for menu, price in menu_items]
        
        template = f"""
        다음 정보로 맛집 리뷰를 작성해줘:
        가게 : {store_name}
        위치 : {location}
        분위기 : {atmosphere}
        가격대 : {price_range}
        메뉴 : {','.join(menu_list)}
        
        리뷰는 자연스럽고 솔직하게, 300자 내외로 작성해줘.
        리뷰는 반드시 한국어로 작성바람.
        """
        return template

    def basic_info(self):
        frame = tk.Frame(self.window)
        frame.pack(pady=5)
        
        self.entries = {}
        labels = ['가게명:', '위치:', '분위기:', '가격대:']
        
        for label in labels:
            row = tk.Frame(frame)
            row.pack(fill='x', padx=5, pady=2)
            
            tk.Label(row, text=label, width=8).pack(side='left')
            entry = tk.Entry(row)
            entry.pack(side='left', expand=True, fill='x')
            self.entries[label] = entry

    def menu_info(self):
        self.menu_frame = tk.LabelFrame(self.window, text="메뉴 입력")
        self.menu_frame.pack(padx=5, pady=5, fill='x')
        
        btn = tk.Button(self.menu_frame, text="메뉴 추가", command=self.add_row)
        btn.pack(pady=5)
        
        self.menu_rows = []
        self.add_row()

    def add_row(self):
        row = tk.Frame(self.menu_frame)
        row.pack(fill='x', padx=5, pady=2)
        
        row.grid_columnconfigure(1, weight=1)
        row.grid_columnconfigure(3, weight=1)
        
        tk.Label(row, text="메뉴:").grid(row=0, column=0)
        menu = tk.Entry(row, width=20)
        menu.grid(row=0, column=1, padx=5, sticky='ew')
        
        tk.Label(row, text="가격:").grid(row=0, column=2)
        price = tk.Entry(row, width=10)
        price.grid(row=0, column=3, padx=5, sticky='ew')
        
        self.menu_rows.append((menu, price))
        
    def create_review(self):
        frame = tk.Frame(self.window)
        frame.pack(pady=5)
                
        self.review_text = tk.Text(frame, height=20, width=60)
        scrollbar = tk.Scrollbar(frame)
        self.review_text.pack(side=tk.LEFT)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        scrollbar.config(command=self.review_text.yview)
        self.review_text.config(yscrollcommand=scrollbar.set)
        
        btn_frame = tk.Frame(self.window)
        btn_frame.pack(pady=5)
        
        tk.Button(btn_frame, text="리뷰 생성", command=self.generate_button_click).pack(side='left', padx=2)
        tk.Button(btn_frame, text="복사하기", command=self.copy_review).pack(side='left', padx=2)
    
    def generate(self):
        store = self.entries['가게명:'].get().strip()
        location = self.entries['위치:'].get().strip()
        mood = self.entries['분위기:'].get().strip()
        price_range = self.entries['가격대:'].get().strip()
        
        review = f"[{store}]\n"
        review += f"위치: {location}\n"
        review += f"분위기: {mood}\n"
        review += f"가격대: {price_range}\n\n"
        review += "메뉴:\n"
        
        for menu, price in self.menu_rows:
            menu_text = menu.get().strip()
            price_text = price.get().strip()
            if menu_text and price_text:
                review += f"{menu_text} ({price_text}원)\n"
        
        self.review_text.delete(1.0, tk.END)
        self.review_text.insert(tk.END, review)
        
    def copy_review(self):
        self.window.clipboard_clear()
        self.window.clipboard_append(self.review_text.get(1.0, tk.END))

app = ReviewMaker()

- 한국어로 작성해 달라니까 영어로 작성해 주는 바보 같은 친구.

 

 

개발환경 세팅하면서 느낀 건데 예전이었으면 막히는 부분 있으면

구글에 똑같이 검색해서 어떻게 해결하는지 찾았을 텐데

AI한테 사진 띡 찍어 보내면서 해결해 '줘' 하고 있는 모습 너무 웃겼음.

세상이 진짜 많이 변한 거 같기도 하고.

 

그래서 이거 나한테 도움 되는 거 맞기는 한 거냐고.

요즘은 프로그램 그냥 말로 만들면 될 거 같음.

버튼을 누르면 이렇게 동작되게 하고 싶어 만들어 '줘'

달력에서 날짜에 마우스를 올리면 이런 동작이 되었으면 좋겠어 만들어 '줘'

 

뤼튼이랑 프로그램 만들면서 느낀 거

회사 프로그램도 소스코드 AI한테 다 먹인 후에

말로만 코딩하면 프로그램 다 만들어 주겠다. 우리 다 잘리겠다.

 

프로젝트 하나 재미있게 만들고 왔으니

이제 다시 챗지피티한테 돌아가서 기초부터 공부하고 오겠습니다.

 

 

728x90
반응형
LIST