langchain 프레임워크

개요

랭체인만 사용하는 경우는 거의 없지만 이 프레임워크에 대해서 이해한 것을 기반으로 다른 프레임워크를 능숙하게 사용할 수 있도록 하는게 중요하다.

패키지 그룹 소개

  1. core : 추상화와 LCEL을 제공한다.
  2. partners: 언어 모델 통합 클래스를 제공함.
  3. community: partners에서 제공하지 않는 모델을 제공. langchain-text-splitters, langchain-experimental 청킹 등 다양한 실험 기능을 제공함

설치

!pip install langchain-core langchain-openai pydantic

사용방법

1. 싱글턴 질의 보내기

from langchain_openai import OpenAI

model = OpenAI(model = "gpt-3.5-turbo-instruct", temperature = 0.0, api_key = "api_key")
output = model.invoke("Hello, world!")
print(output)
  • 랭체인 프레임워크를 쓰면, 사용할 언어 모델 패키지가 제공하는 api 호출 방법에 구속되지 않고 싱글턴 질의를 보낼 수 있다.
  • 사용하고 싶은 언어 모델의 프레임워크 또는 패키지에 대한 공부 없이도 모델을 사용할 수 있게 된다.

2. 대화내용을 컨텍스트로 함께 보내기

ChatOpenAI를 사용하면 이렇게 구성할 수 있다.

from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI

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

messages = [
    SystemMessage(content = "당신은 사용자에게 음식의 레시피를 알려주는 요리사입니다. 조리 순서와 방법을 알려주세요."),
    HumanMessage(content = "치즈 요리를 먹고 싶습니다."),
    AIMessage(content = "어떤 치즈 요리를 좋아하시나요?"),
    HumanMessage(content = "치즈 퐁듀 레시피를 알려주세요.")
]

ai_message = model.invoke(messages)
print(ai_message.content)

ChatOpenAI vs OpenAI

컨텍스트를 함께 포함하는 방식에 관해서 openai 는 두개의 방법을 사용할 수 있다.

  • OpenAI는 단순 텍스트 입력만 가능하지만, ChatOpenAI는 대화 내용을 함께 보낼 수 있음
  • OpenAI는 단일 질의에 적합하고, ChatOpenAI는 대화형 상호작용에 적합함
  • OpenAI는 gpt-3.5-turbo-instruct 같은 명령어 기반 모델을, ChatOpenAI는 gpt-4 같은 채팅 기반 모델을 사용
  • ChatOpenAI는 SystemMessage로 AI의 역할을 지정할 수 있음

3. prompt template 사용하기

시스템 템플릿을 주는 방법이 표준화 된다. 랭체인 없이 사용할 모델의 별도 프레임워크를 사용하는 경우에는 시스템 프롬프트를 주는 방식이 각양 각색이다. 이런 위험을 회피하고 쓰는 사람도, 읽는 사람도 알기 쉽게 코드를 작성할 수 있다.

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant that can answer questions."),
    ("human", "{input}")
])

4. message holder : 메시지가 들어가는 플레이스 홀더 넣기

from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant that can answer questions."),
    MessagesPlaceholder("chat_history", optional=True),
    ("human", "{input}")
])

prompt_value = prompt.invoke({
    "chat_history": [
        HumanMessage(content = "What is the capital of France?"),
        AIMessage(content = "The capital of France is Paris.")
    ],
    "input": "What is the capital of Germany?"
})

print(prompt_value)

기초적인 수준이지만, 이런 기능을 제공하는 것도 편의성에 많은 영향을 준다. llm으로 가장 많이 만들어야하는 기능이 사용자와 상호작용하는 front 부분인데, 여기에는 필연적으로 사용자의 메시지와 ai의 메시지가 표출되어야한다. 랭체인 프레임워크에서 이런 기능을 제공해줌으로써 개발자가 이 메시지들을 따로 태깅하고 관리할 필요가 줄어든다.

5. 멀티 모달 기능

대부분 멀티미디어(사진, 음성, 영상 등)을 컨텍스트로 사용해서 응답을 받기 위해서는 모델에 종속적으로 작업해야한다. 어떤 모델은 되고, 어떤 모델은 안되는 경우가 많기 때문이다. 또 같은 이미지더라도 확장자에 따라서 읽을 수 없는 경우도 있고 .. 다양하다. 이런 상황에서 발생하는 에러를 회피하기 위해서는 사용하고 있는 모델의 사용 범위를 잘 알고 있어야 한다.

랭체인에서도 이런 방식으로 멀티 모달 기능을 제공하고 있다.

근데 아마도 모델마다 되는게 있을테니 확인은 필요하다. 그럼에도 불구하고 표준화된 방식으로 미디어를 태울 수 있다는 점은 큰 장점이다.

from langchain_core.prompts import ChatPromptTemplate
import base64

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

prompt = ChatPromptTemplate.from_messages([
    (
        "user",
        [
            {"type": "text", "text": "{input}"},
            {"type": "image_url", "image_url": {"url": "{url_input}"}},
            {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,{local_image}"}}
        ]
    )
])

# URL 이미지 사용
url_prompt_value = prompt.invoke({
    "input": "What is the capital of France?", 
    "url_input": "https://i.imgur.com/ZcQmbtY.jpg",
    "local_image": ""
})
print("URL 이미지 결과:")
print(url_prompt_value)

# 로컬 이미지 사용
local_image_path = "path/to/your/local/image.jpg"
base64_image = encode_image_to_base64(local_image_path)
local_prompt_value = prompt.invoke({
    "input": "What is the capital of France?",
    "url_input": "",
    "local_image": base64_image
})
print("\n로컬 이미지 결과:")
print(local_prompt_value)