LangChain: 대규모 언어모델 애플리케이션 개발 프레임워크
LangChain은 대규모 언어모델(LLM)을 활용한 애플리케이션 개발을 위한 강력한 프레임워크로, 데이터 연결과 환경 상호작용을 지원합니다.
시작하기
LangChain이란?
LangChain은 언어모델, 특히 대규모 언어모델(LLM)을 활용하여 구동하는 애플리케이션을 개발하기 위한 프레임워크입니다. 이 프레임워크는 두 가지 주요 기능을 제공합니다:
  • Data-aware: 언어 모델을 다른 데이터 소스와 연결
  • Agentic: 언어 모델이 환경과 상호작용할 수 있도록 지원
최근의 Large Language Model(LLM)은 뛰어난 맥락 이해 능력을 보이며, 일반적인 상황에서 인간과 자연스럽게 상호작용하는 것과 같이 행동합니다. 하지만 도메인 지식이나 전문성이 필요한 태스크에 대해서는 구체적이고 유효한 답변을 제공하지 않을 수 있습니다.
LangChain은 검색을 통해 언어모델에 지식을 보완하는 방법을 사용합니다. 관련 코퍼스를 적절한 단위(Chunk, 청크)로 쪼개두고 임베딩해둔 다음, 질문에 대해 유사한 청크를 검색하여 활용하는 방식입니다. 이러한 개념을 "프롬프트 파이프라인"이라고 합니다.
LangChain 모듈 구성
LangChain은 이름 그대로 여러 구성 요소를 결합하여 애플리케이션을 만들 수 있는 체인을 제공합니다. 최소한의 모듈부터 시작해서 복잡한 모듈까지, 확장 가능한 인터페이스 및 외부 소스와의 통합을 제공합니다.
Model I/O
언어모델과 인터페이스하는 모듈로, LLM과의 통신을 관리합니다.
Data connection
애플리케이션 특화된 데이터와 인터페이스하여 LLM에 외부 정보를 제공합니다.
Chains
호출(Call) 시퀀스를 구성하여 복잡한 작업 흐름을 만듭니다.
Agents
체인이 high-level의 지침에 따라 사용할 도구를 선택하도록 합니다.
Memory
체인의 실행 사이에 애플리케이션의 상태를 유지합니다.
Callbacks
체인의 중간 단계를 기록하거나 스트리밍합니다.
LangChain 설치 및 환경 설정하기
pip 설치를 통해 파이썬에서 LangChain을 활용할 수 있습니다. 쏘이지˚◡˚
pip install langchain
LangChain에서 OpenAI API 연결하기
OpenAI API key를 발급 받은 후, 다음 두 가지 방법 중 하나로 연결할 수 있습니다:
  1. 환경변수를 export하는 방법:
export OPENAI_API_KEY="..."
  1. OpenAI 객체를 호출할 때 openai api key를 전달하는 방법:
from langchain.llms import OpenAI llm = OpenAI(openai_api_key="...")

LangChain을 설치한 후에는 OpenAI API 키를 설정해야 합니다. API 키는 보안을 위해 환경 변수로 설정하는 것이 좋습니다. 개발 환경에서는 직접 코드에 입력할 수도 있지만, 프로덕션 환경에서는 반드시 환경 변수나 보안 저장소를 사용하세요.
LLM Chain 컴포넌트 이해하기
LangChain 어플리케이션에서 가장 핵심이 되는 블록은 LLMChain입니다. 체인에서는 아래의 3가지를 조합합니다:
LLM
언어모델은 핵심적인 추론 엔진으로, 성공적으로 LangChain을 활용하기 위해서는 각각 다른 언어모델의 유형과 사용방법을 이해하는 것이 중요합니다.
Prompt Templates
프롬프트 템플릿에서는 언어모델에 전달하는 지시사항(instruction)을 관리합니다. 이는 언어모델의 출력 결과와 직결되기 때문에, 프롬프트를 작성하는 방법과 전략이 매우 중요합니다.
Output Parsers
출력 파서는 LLM이 리턴하는 결과를 사용 가능한 형식으로 전환하여 아웃풋 다운스트림에서 사용할 수 있도록 합니다.
LLM 호출하기
언어모델에는 두 가지 종류가 있는데, LangChain에서는 이를 아래와 같이 구분합니다:
LLMs
string(문자열)을 인풋으로 받아 string을 아웃풋으로 리턴하는 언어모델입니다. TextDavinci와 같은 일반적인 언어모델이 여기에 해당합니다.
from langchain.llms import OpenAI llm = OpenAI(openai_api_key=api_key) llm.predict("안녕하세요?")
ChatModels
메시지(ChatMessage 객체)의 리스트를 인풋으로 받아 메시지를 리턴하는 언어모델입니다. ChatGPT 등이 여기에 해당합니다.
from langchain.chat_models import ChatOpenAI from langchain.schema import HumanMessage chat_model = ChatOpenAI(openai_api_key=api_key) messages = [HumanMessage(content="안녕하세요?")] chat_model.predict_messages(messages)
ChatMessage 구성 요소
ChatModel에서 사용하는 ChatMessage는 두 개의 컴포넌트로 이루어져 있습니다:
content
메시지의 내용을 담고 있는 부분입니다. 사용자의 질문이나 AI의 응답 등 실제 텍스트가 여기에 포함됩니다.
role
해당 메시지의 발신원이 되는 개체의 역할을 정의합니다. 다음과 같은 역할이 있습니다:
  • HumanMessage: 사람 혹은 사용자의 메시지
  • AIMessage: AI 혹은 assistant의 메시지
  • SystemMessage: 시스템의 메시지
  • FunctionMessage: 함수 호출에 따른 메시지
위의 객체에 딱 맞는 역할이 없다면, 직접 클래스를 상속하여 role을 정의할 수 있습니다.
ChatGPT 모델 활용 예시
아래의 예시는 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)

temperature 값을 낮게 설정하면(0.1 등) 더 일관되고 예측 가능한 응답을 얻을 수 있습니다. 반면, 높은 값(0.7 이상)은 더 창의적이고 다양한 응답을 생성합니다.
Prompt Templates 작성하기
대부분 언어모델을 사용할 때에는 사용자의 입력을 그대로 LLM에 전달하는 대신, 맥락과 함께 전달합니다. 특정 작업에 대해 이렇게 추가적인 컨텍스트를 제공할 때 prompt template를 활용할 수 있습니다.
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을 통해 다양한 부분 변수들을 통합하여 템플릿화하는 것이 가능합니다.

프롬프트 템플릿을 사용하면 동일한 형식의 질문에 대해 일관된 응답 형식을 유지할 수 있습니다. 이는 특히 여러 사용자 입력을 처리하는 애플리케이션에서 유용합니다.
ChatMessageTemplate 활용하기
ChatMessage를 다루는 데에도 템플릿이 유용한데, 이 경우 내용뿐만 아니라 각 메시지의 역할이나 리스트에서의 위치와 같은 정보들을 활용할 수가 있습니다. ChatMessageTemplateChatMessage를 어떻게 템플릿화할지, 즉 그 역할과 내용을 어떻게 다룰지 가이드합니다.
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("아기, 여우")

OutputParser를 구현할 때는 LLM의 응답이 항상 예상한 형식으로 오지 않을 수 있다는 점을 고려해야 합니다. 오류 처리 로직을 추가하여 예상치 못한 형식의 응답도 적절히 처리할 수 있도록 하세요.
LLMChain으로 조합하기
이제 LLMChain을 사용하여 위의 세 가지 조합을 모두 조합해 보겠습니다!
PromptTemplate 작성
시스템 프롬프트(지시사항)를 작성하여 LLM에게 어떤 작업을 수행할지 명확히 지시합니다.
ChatOpenAI 호출
작성한 프롬프트를 LLM에 전달하여 응답을 받아옵니다.
OutputParser 적용
LLM의 응답을 원하는 형식으로 파싱하여 활용합니다.
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("동물에 대해 공부하고 싶어")
LangChain의 실제 활용 사례
고객 서비스 챗봇
기업 FAQ 데이터베이스와 연결하여 고객 질문에 정확한 답변을 제공하는 챗봇을 구현할 수 있습니다. LangChain의 RAG(Retrieval Augmented Generation) 기능을 활용하면 최신 정보로 응답할 수 있습니다.
문서 분석 및 요약
대량의 문서를 처리하여 핵심 정보를 추출하고 요약하는 시스템을 구축할 수 있습니다. LangChain의 문서 로더와 체인을 활용하면 PDF, 웹페이지 등 다양한 형식의 문서를 처리할 수 있습니다.
개인 비서 AI
이메일, 캘린더, 메모 등 개인 데이터와 연결하여 일정 관리, 이메일 작성 등을 도와주는 개인 비서 AI를 개발할 수 있습니다. LangChain의 Agent 기능을 활용하면 여러 도구를 조합하여 복잡한 작업을 수행할 수 있습니다.
LangChain과 RAG(Retrieval Augmented Generation)
LangChain의 가장 강력한 기능 중 하나는 RAG(Retrieval Augmented Generation)입니다. RAG는 언어 모델의 한계를 극복하기 위해 외부 데이터 소스에서 관련 정보를 검색하여 모델의 응답을 보강하는 기술입니다.
RAG의 작동 방식:
  1. 문서를 청크(chunk)로 분할하여 벡터 데이터베이스에 저장
  1. 사용자 질문을 벡터화하여 관련 청크 검색
  1. 검색된 정보를 프롬프트에 포함하여 LLM에 전달
  1. LLM이 검색된 정보를 바탕으로 정확한 응답 생성
이 방식을 통해 LLM은 학습 데이터에 없는 최신 정보나 특정 도메인 지식에 대해서도 정확한 응답을 제공할 수 있습니다.

RAG는 특히 의료, 법률, 금융 등 전문 지식이 필요한 분야에서 유용합니다. 또한 자주 업데이트되는 정보를 다루는 애플리케이션에서도 큰 가치를 제공합니다.
LangChain 학습 및 참고 자료
공식 문서
LangChain의 공식 문서는 가장 신뢰할 수 있는 학습 자료입니다. 기본 개념부터 고급 기능까지 상세히 설명되어 있습니다.
예제 코드
다양한 예제 코드를 통해 실제 구현 방법을 배울 수 있습니다.
  • GitHub 저장소의 examples 디렉토리
  • Colab 노트북 튜토리얼
  • 커뮤니티에서 공유하는 프로젝트 사례
커뮤니티 자원
활발한 커뮤니티를 통해 질문하고 배울 수 있습니다.
  • Discord 채널
  • GitHub Discussions
  • Stack Overflow 태그
  • Medium 블로그 포스트
LangChain은 빠르게 발전하는 프레임워크이므로, 최신 기능과 모범 사례를 계속 학습하는 것이 중요합니다. 공식 문서와 커뮤니티 자원을 통해 최신 정보를 얻고, 실제 프로젝트에 적용해보면서 경험을 쌓아가는 것이 좋습니다.