Nacho

[냉부] 👨‍🍳 레시피 AI 만드는 여정 (4) 본문

Toys

[냉부] 👨‍🍳 레시피 AI 만드는 여정 (4)

Nacho_13 2024. 11. 14. 16:11
반응형

일해라 AI!

 

본문에서는...

  • 끝까지 해결하지 못한 오류
  • OpenAi 한테 호구당한 이야기
  • Flask 서버
  • EC2
  • LLama3.1 파인튜닝
  • 웹 크롤링 (완료)

과 같은 내용을 다룹니다..

 

8. Flask 서버 구축

Flask 는 대표적인 파이썬 프레임워크로 작은 프로젝트를 할 때 주로 사용한다고 알려져 있습니다.

레시피 api 또한 굉장히 작은 프로젝트이기 때문에 Flask를 사용 했습니다. 

FLASK_APP/
    ├── public/
    │   └── index.html
    ├── static/
    │   ├── script.js
    │   └── styles.css
    └── app.py

 

우선 필요한 라이브러리를 import 합니다.

from flask import Flask, request, jsonify, render_template
from pydantic import BaseModel
from openai import OpenAI
import re
import json

 

http://localhost:5000 에 접속했을 때 index.html를 reder 한다는 의미입니다.

@app.route('/') # http://localhost:5000 + / 과 같다
def main_page():
   return render_template('index.html')

 

8.1 POST 요청 OpenAI API 답변 내보내기

우선 Post 답변을 보내려선 요청이 먼저 와야 한다. 

다음은 javascript로 작성한 간단한 submit으로 post를 보내는 코드이다.

document.getElementById('ingredient-form').addEventListener('submit', function(event) {
  event.preventDefault();
  const ingredientInput = document.getElementById('ingredient-input').value;

  const requestData = {
    chat: ingredientInput  // 재료 input 을 Key:Value 형태로 변환
  };

  const url = "http://localhost:5000" // 사용할 url 입력
  const loadingSpinner = document.getElementById('loading-spinner');
  loadingSpinner.style.display = 'block';
  fetch(url+'/generate', { // "http://localhost:5000/generate 로 Post요청
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestData) // Post로 {chat : 재료 input} 를 보낸다.
  })

 

"http://localhost:5000/generate 로 보냈다면 다시 Flask로 돌아와서

 

@app.route('/generate', methods=['POST']) # Post
def generate_response():
  data = request.json  # POST로 보낸 데이터를 JSON 형식으로 받음
  user_chat = data.get("chat")
  print(user_chat)
  if not user_chat:
    return jsonify({"error": "No chat provided"}), 400

 

이런식으로 요청을 받아오면 된다.

이제 이전 포스트에서 작성했던 OpenAI API 코드를 합쳐주면 된다.

 

from flask import Flask, request, jsonify, render_template
from pydantic import BaseModel
from openai import OpenAI
import re
import json

client = OpenAI()

app = Flask(__name__, template_folder='public')

@app.route('/')
def main_page():
   return render_template('index.html')

@app.route('/generate', methods=['POST'])
def generate_response():
  data = request.json  # POST로 보낸 데이터를 JSON 형식으로 받음
  user_chat = data.get("chat")
  print(user_chat)
  if not user_chat:
    return jsonify({"error": "No chat provided"}), 400
    
  completion = client.chat.completions.create(
    model="gpt-4o-2024-08-06",
    messages=[
      {
          "role": "system", 
          "content": '''당신은 주어진 재료를 이용하며 맛있는 요리 레시피를 작성하는 AI입니다.
              주어진 역할에 충실하게 단계적으로 음식을 만드는 과정을 쉽고 자세히 설명합니다.
              요리를 처음 하는 사람도 따라 할 수 있는 친절한 설명이 필요합니다.
              한국어로 단계에 맞춰 설명해주세요.
            '''
          },
      {"role": "user", "content": f"{user_chat}"}
    ],
    response_format={
      "type": "json_schema",
      "json_schema": {
        "name": "recipes",
        "schema": {
          "type": "object",
          "properties": {
            "title" : {"type": "string"},
            "summary" : {"type": "string"},
            "ingredients" : {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "name": {"type": "string"},
                  "ea": {"type": "string"}
                },
                "required": ["name", "ea"],
                "additionalProperties": False
              }
            },
            "steps": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "step": {"type": "string"},
                },
                "required": ["step"],
                "additionalProperties": False
              }
            },
            "tips": {"type": "string"}
          },
          "required": ["title","summary","ingredients","steps", "tips"],
          "additionalProperties": False
        },
        "strict": True
      }
    }
  )

  generated_text = completion.choices[0].message.content

  print(generated_text)
  response_data = json.loads(generated_text)

  return jsonify(response_data) # json 형태로 return

 

9. dall-e-3 모델도 사용해보기

Openai API에는 dall-e 모델도 사용해 볼 수 있는데 이를 이용해서 음식 사진도 동일한 방법으로 생성하고자 한다.

음식 사진은 generate_respose 함수에서 생성한 답변을 사용하면 좋을 것 같았다.

 

사진 생성을 위해서는 prompt가 필요한데 generate_respose 의 titile 과 summary 부분을 prompt로 입력하여 생성토록 했다.

 

대충 이런 느낌

 

generate 함수에서 한번에 이미지까지 생성해도 좋지만 공부의 일환으로 generate_img 함수도 작성하였다.

 

@app.route('/generate_img', methods=['POST'])
def generate_img():
  data = request.json
  user_img = data.get("img")
  if not user_img:
    return jsonify({"error": "No chat provided"}), 400

  image = client.images.generate(
    model="dall-e-3",
    prompt=f"{user_img}",
    n=1,
    size="1024x1024",
    response_format='url'
  )
  generated_img = image.data[0].url

  return  jsonify({'image' : generated_img})

 

간단하게 작성되는 것을 볼 수 있다.

반응형