RangChain

강의 Ch4.03~07, 파일 03-LCEL : 멀티모달 모델, 프롬프트 템플릿, 변형

유방울 2025. 1. 17. 17:12

멀티모달 모델

텍스트 외적인 출력 입력이 되는 모델

ex. 이미지, 오디오, 비디오

gpt-4o, gpt-4-turbo 모델은 이미지 인식 기능 

but 이미지 생성하는 기능은 없음

-> 근데 이거 바뀌지 않았나????????? 생성해주던데..

 

테디노트가 멀티모달 클래스 만들었음

 

definition 들어가면 어떻게 구현됐는지 볼 수 있음

이 class 없으면 하나씩 다 구현해야 함.. 복잡데스

from langchain_teddynote.models import MultiModal
from langchain_teddynote.messages import stream_response

# 객체 생성
llm = ChatOpenAI(
    temperature=0.1,  # 창의성 (0.0 ~ 2.0)
    model_name="gpt-4o",  # 모델명 무조건 이걸 써야 함함
)

# 멀티모달 객체 생성
multimodal_llm = MultiModal(llm)

 

이미지 -> 우클릭 -> 이미지 주소 복사

# url 넣을 때 "" 넣기
# 이미지 해상도가 좋으면 훨씬 성능이 좋음
# 얘가 출력해준 내용으로 또 다시 요청을 할 수도 있음
IMAGE_URL = "https://t3.ftcdn.net/jpg/03/77/33/96/360_F_377339633_Rtv9I77sSmSNcev8bEcnVxTHrXB4nRJ5.jpg"

print(multimodal_llm.invoke(IMAGE_URL))

로컬에 있는 파일

IMAGE_PATH_FROM_FILE = "./images/sample-image.png"  # . 현재 있는 곳에서 라는 의미

print(multimodal_llm.invoke(IMAGE_PATH_FROM_FILE))

프롬프트 템플릿의 활용

기본예시: 프롬프트 + 모델 + 출력 파서

 

LCEL을 배울 건데 이 전에 구성요소를 알아야 함

1. 프롬프트 만들고 -> LLM 전달함

프럼프트란?

LLM한테 질문 만들어서 던지는데 이를 의미함

이는 질문이 아니라 지시사항임

종합적인 의미임, 답변 어떻게 해야할지도 포함됨

 

문자열도 만들 수 있는데 템플릿을 사용할 것임

 

1. PromptTemplate

지시사항을 주고 세부내용을 주는 것임

이 전체가 llm한테 전달되는 것이고 이를 바탕으로 답변을 줌

langchain안에 있는 prompt template을 이용할 것임

- template: 템플릿 문자열, 중괄호{}는 변수를 나타냄

- input_variables: 중괄호 안에 들어갈 변수의 이름을 리스트로 정의 

 

2. input_variables 변수

: 변수의 이름을 정의하는 리스트

 

모든 문장을 작성함

API 서비스를 만들때는 구조화된 내용이 있고

사용자가 지시하는 일부만 바뀌는 게 좋음

문자열로 정의하는데 country는 입력 변수

 

프롬프트 템플릿 객체 생성 

country가 variable

from langchain_teddynote.messages import stream_response  # 스트리밍 출력
from langchain_core.prompts import PromptTemplate

# template 정의
template = "{country}의 수도는 어디인가요?"

# from_teDmplate 메소드를 이용하여 PromptTemplate 객체 생성
prompt_template = PromptTemplate.from_template(template)
prompt_template

PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}의 수도는 어디인가요?')

예시의 country를 다른 것으로 치환해서 알 수 있음

처음부터 끝까지 다 작성하려면 피곤함

나라만 넣으면 자동으로 수도가 나오면 편함

# prompt 생성
prompt = prompt_template.format(country="대한민국")
prompt

'대한민국의 수도는 어디인가요?'

# prompt 생성
prompt = prompt_template.format(country="미국")
prompt

'대한민국의 미국는 어디인가요?'

 

 

ex 회의록

미리 작성된 다양한 형식을 다 가지고 옴

변하는 부분만 치환가능

 

프롬프트 완성해서 llm한테 넣어주는 게 아니라

이 템플릿 + llm 연결할 것임

이 문법은 chain으로 할 것임


Chain 생성

LCEL(LangChain Expression Language)

chain의 형태가 다양함 

아래는 가장 기본적임

(파이프 연산자 : 시프트 \)

chain = prompt | model | output_praser

 

prompt = PromptTemplate

 

프롬프트에 정의한 변수가 있으면

invoke시 꼭 변수를 줘야 함

 

# prompt 를 PromptTemplate 객체로 생성합니다.
prompt = PromptTemplate.from_template("{topic} 에 대해 쉽게 설명해주세요.")

model = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)

# 체인으로 엮음
chain = prompt | model

 invoke() 호출

python 딕셔너리 형태로 입력값을 전달 (키:값)

invoke() 호출 시 입력값을 전달함

# input 딕셔너리에 주제를 '인공지능 모델의 학습 원리'으로 설정합니다.
input = {"topic": "인공지능 모델의 학습 원리"}

# prompt 객체와 model 객체를 파이프(|) 연산자로 연결하고 invoke 메서드를 사용하여 input을 전달합니다.
# 이를 통해 AI 모델이 생성한 메시지를 반환합니다.
chain.invoke(input)

AIMessage(content='인공지능 모델의 학습 원리를 쉽게 설명하자면, 다음과 같은 단계로 이해할 수 있습니다.\n\n1. **데이터 수집**: 인공지능 모델은 학습하기 위해 많은 데이터를 필요로 합니다. 이 데이터는 이미지, 텍스트, 소리 등 다양한 형태일 수 있습니다.\n\n2. **데이터 전처리**: 수집한 데이터는 모델이 이해할 수 있는 형태로 변환해야 합니다. 예를 들어, 이미지의 크기를 조정하거나, 텍스트를 숫자로 변환하는 과정이 필요합니다.\n\n3. **모델 선택**: 학습할 모델을 선택합니다. 이는 신경망, 결정 트리, 서포트 벡터 머신 등 여러 가지 방법이 있습니다. 각 모델은 특정한 문제에 더 적합할 수 있습니다.\n\n4. **학습**: 모델은 주어진 데이터를 바탕으로 패턴을 찾습니다. 이 과정에서 모델은 입력 데이터와 정답(라벨) 간의 관계를 학습합니다. 예를 들어, 고양이와 개의 이미지를 구분하는 모델은 각각의 특징을 학습하게 됩니다.\n\n5. **손실 함수**: 모델의 예측이 실제 정답과 얼마나 차이가 나는지를 측정하는 방법입니다. 이 차이를 줄이기 위해 모델의 파라미터(가중치)를 조정합니다.\n\n6. **최적화**: 손실 함수를 최소화하기 위해 경량화된 알고리즘(예: 경사 하강법)을 사용하여 모델의 파라미터를 업데이트합니다. 이 과정을 반복하면서 모델은 점점 더 정확한 예측을 하게 됩니다.\n\n7. **검증**: 학습이 끝난 후, 모델의 성능을 평가하기 위해 새로운 데이터(검증 데이터)를 사용합니다. 이 데이터는 모델이 학습할 때 사용하지 않은 데이터로, 모델의 일반화 능력을 확인하는 데 도움을 줍니다.\n\n8. **배포**: 모델이 충분히 학습하고 검증되면 실제 환경에 배포되어 사용됩니다. 이후에도 새로운 데이터로 모델을 업데이트하거나 개선할 수 있습니다.\n\n이러한 과정을 통해 인공지능 모델은 주어진 문제를 해결할 수 있는 능력을 갖추게 됩니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 485, 'prompt_tokens': 22, 'total_tokens': 507, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_72ed7ab54c', 'finish_reason': 'stop', 'logprobs': None}, id='run-57aaaa12-1a5c-4aff-8c58-0182c3a90ad5-0', usage_metadata={'input_tokens': 22, 'output_tokens': 485, 'total_tokens': 507, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

but input variable이 한 개인 경우는 딕셔너리 형태 안 써도 됨

chain.invoke("인공지능 모델의 학습원리")

input variable이 두 개인 경우

# prompt 바꾸면 chain도 다시 실행해야 함

prompt = PromptTemplate.from_template("{topic}에 대해 {how} 설명해주세요.")

model = ChatOpenAI()

chain = prompt | model
# variables 2개 확인
chain 

PromptTemplate(input_variables=['how', 'topic'], input_types={}, partial_variables={}, template='{topic}에 대해 {how} 설명해주세요.')
| ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x000001E3EF9BAA10>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x000001E3EF982310>, root_client=<openai.OpenAI object at 0x000001E3EF89B150>, root_async_client=<openai.AsyncOpenAI object at 0x000001E3EF9BABD0>, model_kwargs={}, openai_api_key=SecretStr('**********'))
# how 예시로는 영어로, 5살짜리 어린아이에게도 이해할 수 있게
input ={"topic" : "인공지능 모델의 학습 원리", "how": "간단하게"}

 

stream 예시

# 스트리밍 출력을 위한 요청
answer = chain.stream(input)

# 스트리밍 출력
stream_response(answer)

 

템플릿 변경

format 설정도 가능

template = """
당신은 영어를 가르치는 10년차 영어 선생님입니다. 주어진 상황에 맞는 영어 회화를 작성해 주세요.
양식은 [FORMAT]을 참고하여 작성해 주세요.

#상황:
{question}

#FORMAT:
- 영어 회화:
- 한글 해석:
"""

# 프롬프트 템플릿을 이용하여 프롬프트를 생성합니다.
prompt = PromptTemplate.from_template(template)

# ChatOpenAI 챗모델을 초기화합니다.
model = ChatOpenAI(model_name="gpt-4o-mini")

# 문자열 출력 파서를 초기화합니다.
output_parser = StrOutputParser()
# 체인을 구성합니다.
chain = prompt | model | output_parser

# 완성된 Chain을 실행하여 답변을 얻습니다.
print(chain.invoke({"question": "저는 식당에 가서 음식을 주문하고 싶어요"}))

아래는 스트리밍 예시

answer = chain.stream({"question":"저는 식당에서 가서 음식을 주문하고 싶어요"})

stream_response(answer)

- 영어 회화:
  A: Hi there! Can I take your order?
  B: Yes, I'd like to have the grilled chicken with rice, please.
  A: Would you like anything to drink?
  B: Yes, I'll have a glass of water, please.
  A: Great choice! Anything else?
  B: No, that's all for now. Thank you!

- 한글 해석:
  A: 안녕하세요! 주문 도와드릴까요?
  B: 네, 구운 치킨과 밥을 주세요.
  A: 음료수는 필요하신가요?
  B: 네, 물 한 잔 주세요.
  A: 좋은 선택이에요! 다른 것은 없으신가요?
  B: 아니요, 지금은 그게 다입니다. 감사합니다!

 

내가 만든 예시 ㅋㅋ

prompt = PromptTemplate.from_template("{people}들 중 한 명을 랜덤하게 선택해주세요.")

model = ChatOpenAI(
    temperature=0.8,
    tiktoken_model_name="gpt-4o-mini"
)

chain = prompt | model

input = {"people": "유정은, 오다경, 손민기, 신재우, 배승훈"}

answer = chain.invoke(input)

answer.content

 

틀렸던 오류

stream은 model!

invoke는 chain !

중괄호 자체를 넣고 싶으면 (( 두개 넣으면 됨

 

Langsmith 해석

prompt token : input token

completion toeken : output token

꽤 비쌈