참고문서: https://python.langchain.com/docs/get_started/quickstart.html
실습파일:
LangChain이란?
LangChain은 언어모델, 특히 대규모 언어모델(LLM)을 활용하여 구동하는 애플리케이션을 개발하기 위한 프레임워크로,
● Data-aware: 언어 모델을 다른 데이터 소스와 연결하거나
● Agentic: 언어 모델이 환경과 상호작용할 수 있도록 하는 애플리케이션 개발을 지원한다.
최근의 Large Language Model(LLM)은 뛰어난 맥락 이해 능력을 보이며,
일반적인 상황에서 인간과 자연스럽게 상호작용하는 것과 같이 행동한다.
하지만 도메인 지식이나 전문성이 필요한 태스크에 대해서는 구체적이고 유효한 답변을 제공하지 않을 수 있다.
예를 들어 의학, 법률 자문에 언어모델을 사용한다면, 일반적인 수준의 답변을 받을 수는 있어도 상세한 정보를 얻을 수는 없다.
이러한 한계를 극복하기 위해 LangChain에서는 검색을 통해 언어모델에 지식을 보완하는 방법을 사용한다.
관련 코퍼스를 적절한 단위(Chunk, 청크)로 쪼개두고 임베딩해둔 다음, 질문에 대해 유사한 청크를 검색하여 활용하는 방식이다.
이러한 개념을 "프롬프트 파이프라인"이라고 한다.
LangChain 모듈
LangChain은 이름 그대로 여러 구성 요소를 결합하여 애플리케이션을 만들 수 있는 체인을 제공한다.
아래와 같이 최소한의 모듈부터 시작해서 복잡한 모듈까지, 확장 가능한 인터페이스 및 외부 소스와의 통합을 제공한다.
● Model I/O - 언어모델과 인터페이스
● Data connection - 애플리케이션 특화된 데이터와 인터페이스
● Chains - 호출(Call) 시퀀스를 구성함
● Agents - 체인이 high-lebel의 지침에 따라 사용할 도구를 선택하도록 함
● Memory - 체인의 실행 사이에 애플리케이션의 상태를 유지함
● Callbacks - 체인의 중간 단계를 기록하거나 스트리밍함
LangChain 설치 및 환경 설정하기
pip 설치를 통해 파이썬에서 LangChain을 활용할 수 있다. 쏘이지˚◡˚
pip install langchain
LangChain에서 OpenAI API 연결하기
OpenAI API key를 발급받은 후, a) 환경변수를 export하거나
export OPENAI_API_KEY="..."
b) OpenAI 객체를 호출할 때 openai api key를 전달하는 방식으로 Langchain에서 OpenAI 언어모델을 사용할 수 있다.
from langchain.llms import OpenAI
llm = OpenAI(openai_api_key="...")
LLM Chain 컴포넌트 이해하기
LangChain 어플리케이션에서 가장 핵심이 되는 블록은 LLMChain이다.
체인에서는 아래의 3가지를 조합한다:
1) LLM - 언어모델은 핵심적인 추론 엔진으로, 성공적으로 LangChain을 활용하기 위해서는 각각 다른 언어모델의 유형과 사용방법을 이해하는 것이 중요하다.
2) Prompt Templates - 프롬프트 템플릿에서는 언어모델에 전달하는 지시사항(instruction)을 관리한다. 이는 언어모델의 출력 결과와 직결되기 때문에, 프롬프트를 작성하는 방법과 전략이 매우 중요하다.
3) Output Parsers - 출력 파서는 LLM이 리턴하는 결과를 사용 가능한 형식으로 전환하여 아웃풋 다운스트림에서 사용할 수 있도록 한다.
❶ LLM 호출하기
언어모델에는 두 가지 종류가 있는데, LangChain에서는 이를 아래와 같이 구분한다:
a) LLMs: string(문자열)을 인풋으로 받아 string을 아웃풋으로 리턴하는 언어모델 (TextDavinci와 같은 일반적은 언어모델)
b) ChatModels: 메시지( ChatMessage
객체)의 리스트를 인풋으로 받아 메시지를 리턴하는 언어모델 (ChatGPT 등)
여기서 ChatModel에서 사용하는 ChatMessage
는 두 개의 컴포넌트로 이루어져 있다:
content
: 메시지의 내용role
: 해당 메시지의 발신원이 되는 개체의 역할을 정의HumanMessage
: 사람 혹은 사용자의 메시지AIMessage
: AI 혹은 assistant의 메시지SystemMessage
: 시스템의 메시지FunctionMessage
: 함수 호출에 따른 메시지- 위의 객체에 딱 맞는 역할이 없다면, 직접 클래스를 상속하여 role을 정의할 수 있다.
LangChain은 두 가지 방법으로 LLM과 ChatModel이라는 표준 인터페이스를 활용하도록 한다:
predict
: string을 인풋으로 받아 string을 아웃풋으로 리턴predict_messages
: 메시지의 리스트를 인풋으로 받아 메시지를 리턴
아래의 예시는 LangChain에서 OpenAI의 ChatGPT 모델을 활용하여 결과를 받아보는 예시 코드이다 :
from langchain.chat_models import ChatOpenAI
api_key = "your-api-key"
chat_model = ChatOpenAI(openai_api_key=api_key)
chat_model.predict("잠이 안 올 때는 어떻게 하면 좋을지 대답해줘")
이때 질문 부분을 사용자 메시지(HumanMessage
)로 처리해서 추론을 할 수 있으며,
temperature 등 언어모델 사용에 필요한 인자들을 함께 파라미터로 넘길 수도 있다.
from langchain.schema import HumanMessage
text = "잠이 안 올 때는 어떻게 하면 좋을지 대답해줘"
messages = [HumanMessage(content=text)]
chat_model.predict_messages(messages, temperature = 0.1)
❷ Prompt templates 작성하기
대부분 언어모델을 사용할 때에는 사용자의 입력을 그대로 LLM에 전달하는 지시, 혹은 맥락과 함께 전달한다.
특정 작업에 대해 이렇게 추가적인 컨텍스트를 제공할 때 prompt template를 활용할 수 있다.
예를 들어, 위의 질문에 대해 ChatGPT가 너무 장황하게 답변하는 것을 막기 위해 아래와 같은 프롬프팅이 가능하다:
from langchain.prompts import PromptTemplate
my_template = """아래의 질문에 대해 한 줄로 간결하고 친절하게 답변하세요.
질문: {question}"""
prompt = PromptTemplate.from_template(my_template)
prompt.format(question="잠이 안 올 때는 어떻게 하면 좋을지 대답해줘")
chat_model.predict(prompt.format(question="잠이 안 올 때는 어떻게 하면 좋을지 대답해줘"))
"간결하고 친절하게 답변하라"라는 지시사항에 맞게, ChatGPT는 짧고 간결한 답변을 리턴한 것을 확인할 수 있다.
PromptTemplate를 활용하면 이러한 formatting을 통해 다양한 부분 변수들을 통합하여 템플릿화하는 것이 가능하다.
더 나아가 ChatMessage
를 다루는 데에도 유용한데, 이 경우 내용뿐만 아니라 각 메시지의 역할이나 리스트에서의 위치와 같은 정보들을 활용할 수가 있다.
ChatMessageTemplate
는 ChatMessage
를 어떻게 템플릿화할지, 즉 그 역할과 내용을 어떻게 다룰지 가이드한다.
아래는 시스템 메시지를 통해 어떤 언어로 대답할지 지시하는 예시이다.
지시사항은 영어로 작성하며, 강조하고 싶은 부분은 대문자로 쓰는 것이 효과적이기 때문에 아래와 같이 작성하였다.
from langchain.prompts.chat import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
#시스템 역할 지정하기
template = """
You are a helpful assistant to help teenagers learn {output_language}.
Answer the question in <{output_language}> within 1~2 sentences.
YOU MUST USE <{output_language}> TO ANSWER THE QUESTION.
Question:"""
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
chat_prompt.format_messages(output_language="English",
text="잠이 안 올 때는 어떻게 하면 좋을지 대답해줘")
실행 예시:
❸ Output Parsers 활용하기
LLM 아웃풋을 받아왔다면, OutputParsers를 통해 LLM의 아웃풋을 원하는 다운스트림 모양으로 변환할 수 있다.
OutputParser에서는 아래와 같은 몇 가지 기본 타입이 있다:
- LLM의 텍스트 아웃풋을 JSON과 같은 구조화된 형태로 변환하기
- ChatMessage를 일반 문자열로 변환하기
- message(OpenAI의 fucntion 호출)등으로부터 나온 정보를 문자열로 변환하기
from langchain.schema import BaseOutputParser
class CommaSeparatedListOutputParser(BaseOutputParser):
"""LLM 아웃풋에 있는 ','를 분리해서 리턴하는 파서."""
def parse(self, text: str):
return text.strip().split(", ")
CommaSeparatedListOutputParser().parse("아기, 여우")
❹ LLMChain으로 조합하기
이제 LLMChain
을 사용하여 위의 세 가지 조합을 모두 조합하자!
- PromptTemplate를 활용하여 시스템 프롬프트(지시사항)를 작성하고,
- ChatOpenAI호출을 통해 이를 LLM에 전달한 다음,
- OutputParser을 통해 결과물을 파싱할 것이다.
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.schema import BaseOutputParser
class CommaSeparatedListOutputParser(BaseOutputParser):
"""LLM 아웃풋에 있는 ','를 분리해서 리턴하는 파서."""
def parse(self, text: str):
return text.strip().split(", ")
template = """
너는 5세 아이의 낱말놀이를 도와주는 AI야.
아이가 어떤 카테고리에 해당하는 개체들을 말해달라고 <질문>을 하면
해당 카테고리에 해당하는 단어들을 5개 나열해야 해.
이때 각 단어는 반드시 comma(,)로 분리해서 대답해주고, 이외의 말은 하지 마.
질문:"""
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
chain = LLMChain(
llm=ChatOpenAI(openai_api_key = api_key),
prompt=chat_prompt,
output_parser=CommaSeparatedListOutputParser()
)
chain.run("동물에 대해 공부하고 싶어")