[8기 랭체인] 멀티모달로 고든램지가 되어보기

안녕하세요 미남홀란드입니다.

제가 이번에 참고한건 멀티모달관련 Task 였습니다. 저는 원래 회사에서 한달에 하나씩 컨텐츠를 만들고 있는 업무도 하고 있습니다. 안그래도 최근에 멀티모달로 GPT-vision docs를 보면서 한땀한땀 ‘OO스테이크’ 라는 프로젝트를 했는데요. 위 프로젝트에서 처음 써보는 코드들이다보니 리팩토링이 잘 안되고, 조금 가독성이 좋지 않아서 랭체인 관련 독스를 찾아보다가 멀티모달 Task cookbook 이 있어서 이걸로 시도를 해보았습니다.


보다시피 랭체인의 기초적인 모듈만 import 해서 구현했습니다. 기존코드보다 2배정도는 감소한것 같습니다. 근데 써보니깐 속도는 기존것이 더 빠른것 같기도한게 아무래도 랭체인의 단점인 속도 때문인것 같습니다.

  import base64
import io
import os

import numpy as np
from IPython.display import HTML, display
from PIL import Image


def encode_image(image_path):
    """Getting the base64 string"""

    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")


def plt_img_base64(img_base64):
    """Display the base64 image"""

    # Create an HTML img tag with the base64 string as the source
    image_html = f'<img src="data:image/jpeg;base64,{img_base64}" />'

    # Display the image by rendering the HTML
    display(HTML(image_html))


# Image for QA
path = "/Users/kdb/RAG_langchain/meet.jpeg"
img_base64 = encode_image(path)
plt_img_base64(img_base64)

예시 이미지)

구글에서 스테이크 익힘정도를 검색해서 나온 사진을 주피터환경에 로드해서 출력한 모습입니다.

스테이크의 익음정도와 문자로 등급이 나와있는데요 GPT-vision 이 이미지 캡셔닝 성능도 좋지만 OCR 성능 또한 매우 좋다고 합니다😀

물론 GPT가 이해를 높게 하겠지만 그냥 사진을 입력해도 최소한의 Context 를 만들어서 fewshot 텍스트를 조금이라도 주면 성능이 개선되지 않을까 생각을 했습니다.

→ 이건 장담을 못하겠습니다 Test 를 안해봐서

하여튼 첫번째 루프가 돌아서 컨텍스트를 생산하고 그걸 기반으로 instruction 을 만들어야겠다 생각했습니다.

# 랭체인으로 Context를 저장해서 다시 한번 사용하기 위한 함수
def invoke_chat_with_image(text_message, img_base64):
    chat = ChatOpenAI(model="gpt-4-vision-preview", temperature=0, max_tokens=1024, api_key="your api key")

    msg = chat.invoke(
        [
            HumanMessage(
                content=[
                    {
                        "type": "text",
                        "text": text_message,
                    },
                    {
                        "type": "image_url",
                        "image_url": {"url": f"data:image/jpeg;base64,{img_base64}"},
                    },
                ]
            )
        ]
    )
    return msg
context = invoke_chat_with_image(meet_question, img_base64)

출력결과 : [content = “이 이미지는 스테이크의 다양한 익힘 정도를 보여주고 있습니다. 각 단계별로 스테이크의 색깔과 질감이 어떻게 변하는지 설명하겠습니다.\n\n1. Rare (레어): 스테이크의 중심부가 대부분 붉은색을 유지하며, 가장자리는 약간 갈색으로 익혀져 있습니다. 중심부의 온도는 매우 낮으며, 고기의 질감은 매우 부드럽고 촉촉합니다.\n\n2. Medium Rare (미디엄 레어): 중심부는 여전히 붉은색이지만, 레어보다는 조금 더 익혀져 있으며, 가장자리는 더욱 갈색으로 변합니다. 중심부의 온도가 조금 더 올라가고, 고기는 여전히 부드럽지만 레어보다는 조금 더 탄력이 있습니다.\n\n3. Medium (미디엄): 중심부가 분홍색을 띠며, 가장자리는 잘 익은 갈색을 보입니다. 고기의 질감은 탄력 있고 촉촉하며, 중심부의 온도가 더 올라가서 고기의 주스가 적당히 유지됩니다.\n\n4. Medium Well (미디엄 웰): 중심부에 약간의 분홍색이 남아 있지만, 대부분 갈색으로 변합니다. 고기는 더욱 탄력 있고, 주스는 적어지며, 질감은 미디엄보다는 조금 더 단단합니다.\n\n5. Well Done (웰던): 고기 전체가 완전히 갈색으로 익혀져 있으며, 중심부에 분홍색이 전혀 남아 있지 않습니다. 고기의 질감은 가장 단단하고, 주스가 거의 없어져서 건조할 수 있습니다.\n\n각각의 익힘 정도는 개인의 취향에 따라 선택되며, 고기의 종류나 부위에 따라서도 적합한 익힘 정도가 달라질 수 있습니다.'“]


보다시피 매우 잘 출력을 해주고 저는 이걸로 컨텍스트를 생성하는 프롬프트를 만듭니다.

sub_question = """
- 너는 미국의 최고의 레스토랑 chief이다. 마치 Gorden ramsay같아.
- 너는 고기의 익힘을 판단해서 손님에게 설명을 해주어야 한다.
-{0} \n 를 참고해서 고기의 익힘을 설명해주면된다.
- 잘 설명하면 너에게 팁으로 200달러를 줄것이다.
[output]
- 고기의 익힘을 설명해준다.
- 곁들임 음료: ex) 맥주, 와인
- 곁들임 음료는 너가 어울릴만한걸 추천해주세요.
""".format(context.content)

그리고 물론 웹으로 구현 해야겠지만 user_input 을 받아옵니다.

path = "/Users/kdb/RAG_langchain/user_input.jpeg"
user_img_base64 = encode_image(path)
result = invoke_chat_with_image(sub_question,user_img_base64)


최종결과를 보겠습니다.

매우 묘사를 잘 해주고, 음료까지 추천해주는 모습입니다. 비교적 코드 몇줄에 멀티모달이 가능했습니다.

저는 이 프로젝트를 이제 embedded 단에서 구현을 하려고 합니다.

https://github.com/jh941213/LLM_GPT-4_Vision_steak_classfier_bot

깃허브에 소스코드 업로드 해두었습니다. 기존방식은 웹 Streamlit 으로 구현을 해놨는데 Langchain 을 썼을때와 차이점을 보셔도 재밌을것 같습니다.

긴글 읽어주셔서 감사합니다.

GitHub - jh941213/LLM_GPT-4_Vision_steak_classfier_bot: LLM 과 GPT-4 Vision 을 활용하여 고기의 익음정도를 측정하는 봇
10
1개의 답글

👉 이 게시글도 읽어보세요

모집 중인 AI 스터디