안녕하세요 미남홀란드입니다.
제가 이번에 참고한건 멀티모달관련 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 을 활용하여 고기의 익음정도를 측정하는 봇