빅웨이브에이아이 기술블로그

LangChain: LLM 서비스를 어떻게 개발할 수 있을까? 본문

기술 블로그

LangChain: LLM 서비스를 어떻게 개발할 수 있을까?

빅웨이브 이현상 2024. 1. 24. 15:39

Introduction

 

안녕하세요! 빅웨이브에이아이 이현상입니다!

 

요즘 들어 블로그 포스트를 거의 올리지 못해 저도 참 아쉬웠는데요,

 

사실 저도 직장 근무를 하면서 회사 블로그 운영하기가 쉽지는 않더라구요 ㅜㅜ

 

그래서 아에 블로그를 지금처럼.. 방치하기 보다는, 저희 회사의 월간 세미나로 정리되는 내용을 하나씩 공유드리고자 합니다!

 

최근 저희 회사에서는 최신 트렌드에 발맞춰서 LLM(Large Language Model) 및 생성형 AI 관련 내용들을 연구하고 있는데요,

 

이 밖에도 추후 AI 관련 트렌드에 맞춰 정리된 내용들을 지속적으로 전달해드리려고 해요.

 

오늘은 LangChain이라는 LLM 어플리케이션 개발을 위한 프레임워크를 소개해드리겠습니다!

 

빅웨이브에이아이 이현상 님의 리뷰입니다.

1. LangChain이란?

  • LLM 기반 어플리케이션 개발을 위한 프레임워크, 다양한 LLM관련 기능들을 결합(체인)하여 손쉽게 사용하도록 지원
  • Harrison Chase라는 사람이 2022년 Robust Intelligence 근무 시절 시작한 오픈소스 프로젝트, JavaScript와 파이썬에서 패키지 형식으로 지원
  • 핵심 기능 2가지
    1. 상황 인식 - LLM을 소스(지침, 예시, 콘텐츠 등)와 연결
    2. 추론(Reasoning) - LLM 기반 특정 추론 유도
  • 프레임워크 구성
    • LangChain 라이브러리: Python 및 JS 라이브러리, 어플리케이션 개발을 위한 LLM Chain(다양한 기능 결합) 지원
    • LangSmith: LLM Chain을 디버깅, 테스트, 평가 및 모니터링할 수 있는 개발자 플랫폼
    • LangServe: LLM Chain을 REST API로 배포하기 위한 라이브러리
    • LangChain 템플릿: 다양한 작업을 위한 기본 아키텍처 제공

LangChain 구성도!

 

  • LangChain 개발 생애 주기
    • 개발: LangChain 탬플릿 가지고 어플리케이션 기능 개발
    • 생산화: LangSmith로 LLM 체인 검사, 테스트, 모니터링
    • 배포: LangServe로 모든 LLM 체인 API 개발
  • 패키지 주요 구성
    • LangChain: LLM의 아키텍처를 구성하는 상황 인지, 기능 체인, 에이전트 및 검색(Retrieval) 전략
    • Langchain-Core: 기본 추상화 및 언어
    • LangChain-Community: 서드 파티(타 프레임워크) 통합
  • 패키지 주요 모듈
    1. Chains: LLM 관련 도구, 전처리 등 기능 제공, LCEL(LangChain Expression Language) 활용
    2. Agents: 에이전트(작업 주체)가 LLM을 활용하여 어떤 작업을 수행할 지 선택
    3. Retrieval: 언어 생성에 문서 참고, 문서를 텍스트 벡터 형식으로 저장하여 최적화
    4. Model I/O(Input/Output): 모델의 입출력 관리 모듈, 전세계 언어 관련 모델과 상호작용할 수 있는 블록 방식 기능 제공
    5. Memory: 언어 생성에서 과거의 상호작용 기록이 필요한 경우 이를 메모리 형태로 관리
    6. Callbacks: 로깅, 모니터링, 스트리밍(ChatGPT와 같이 실시간 답변 생성) 등 LLM 어플리케이션의 다양한 단계와 연결하는 기능

2. Python LangChain 환경 세팅 (Local)

  • pip install로 간단하게 설치 가능, Anaconda 가상 환경이나 Dev Container 활용 권장
  • VS code Anaconda Dev Container + pip install
    1. Anaconda 설치
    2. VS code 설치
    3. Docker Desktop 설치
    4. Dev Container 세팅
    5. pip install 실행
    6. LangChain 버전 확인

VsCode Dev Container

  • Requirements.txt

langchain==0.1.0
langchain-openai==0.0.2
beautifulsoup4==4.12.2
faiss-cpu==1.7.4
langchainhub==0.1.14
langserve[all]==0.0.39
tavily-python==0.1.9
fastapi==0.109.0
uvicorn==0.23.2
urllib3==2.1.0

3. Python LangChain 예제

  • OpenAI Playground API 키 발급(유료 주의, 그래도 GPT 3.5의 경우 매우 저렴)
  • pip install -r requirements.txt로 패키지 세팅
  • 코드 시작!

1) Simple 예제

# 패키지 세팅
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "..."
llm = ChatOpenAI()
# 간단하게 API 텍스트 호출
llm.invoke("LangSmith로 Testing과 Evaluation을 어떻게 할 수 있어?")

  • 패키지 불러와서 변수 설정하고 invoke로 텍스트 호출할 수 있음
# OpenAI Chat API 프롬프트 세팅
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
    ("system", "너는 월드 클래스 급의 문서 작성 전문가야. 한번 잘 써봐"),
    ("user", "{input}")
])

# 백 슬래쉬로 변수 객체에 대해 chain 걸 수 있음
chain = prompt | llm

# prompt 포함 생성
chain.invoke({"input": "LangSmith로 Testing과 Evaluation을 어떻게 할 수 있어?"})

  • 프롬프트를 양식대로 코드 작성하여 체인(|)을 설정할 수 있음, chain.invoke로 텍스트 생성 가능
# 출력되는 text 후처리로 string만 추출
from langchain_core.output_parsers import StrOutputParser

output_parser = StrOutputParser()

chain = prompt | llm | output_parser

# prompt, parser 포함 생성
chain.invoke({"input": "LangSmith로 Testing과 Evaluation을 어떻게 할 수 있어?"})

  • string만 추출하는 등 전처리 및 후처리 과정도 chain에 결합할 수 있음

2) Retrieval(검색 기능) 붙이기

  • Retrieval 이란 LangChain의 주요 기능 중 하나로, 학습된 생성 모델이 알기 어려운 정보라도 문서 형태로 주어지면 이를 참고하여 보다 정확한 텍스트를 생성할 수 있음
  • 문서를 임베딩 벡터 형태로 저장해두고 이를 chain하여 답변 생성에서 활용할 수 있음
# 웹 사이트 URL로 문서 등록
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("<https://docs.smith.langchain.com/overview>")

docs = loader.load()

# 임베딩 임포트
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()

# FAISS(Facebook AI Similarity Search)로 문서를 벡터화
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter()
documents = text_splitter.split_documents(docs)
vector = FAISS.from_documents(documents, embeddings)
  • 웹사이트를 로드하여 문서화, OpenAI 임베딩 방식으로 FAISS 활용하여 벡터 추출
# 프롬프트 탬플릿 만들기
# 입력값으로 context(문서), input(질문) 설정
from langchain.chains.combine_documents import create_stuff_documents_chain

prompt = ChatPromptTemplate.from_template("""해당 질문에 대해서 오직 주어진 context만을 기반하여 답변을 작성해줘:

<context>
{context}
</context>

Question: {input}""")

document_chain = create_stuff_documents_chain(llm, prompt)

# 바로 prompt에 문서 내용 넣는 방식으로도 가능하긴 함
from langchain_core.documents import Document

document_chain.invoke({
    "input": "LangSmith로 Testing과 Evaluation을 어떻게 할 수 있어?",
    "context": [Document(page_content="LangSmith 개요와 사용자 가이드라인")]
})
  • 프롬프트에 LangChain Document 양식으로 텍스트를 직접 넣을 수도 있음
# 만들어놓은 벡터 retriever와 document_chain 연동
from langchain.chains import create_retrieval_chain

retriever = vector.as_retriever()
retrieval_chain = create_retrieval_chain(retriever, document_chain)

# retrieval chain에 질문 넣어서 답변 생성
response = retrieval_chain.invoke({"input": "LangSmith로 Testing과 Evaluation을 어떻게 할 수 있어?"})
print(response["answer"])
  • 만들어놓은 벡터를 chain으로 연동하여 답변 생성
  • Retrieval 적용 전 vs 후 비교, 확실히 적용 후 적합한 텍스트를 생성하는 듯!
Retrieval 적용 전 Retrieval 적용 후
'LangSmith를 테스트하고 평가하기 위해 다음과 같은 단계를 따를 수 있습니다.\n\n1. 데이터 준비: 테스트 및 평가를 위해 사용할 데이터를 수집하고 준비합니다. 이 데이터는 가능한 한 다양한 유형과 주제를 포함해야 합니다.\n\n2. 테스트 데이터 설정: 수집한 데이터에서 테스트에 사용할 부분을 선택합니다. 일반적으로 데이터 세트의 일부를 테스트 데이터로 분리하여 모델의 성능을 평가합니다.\n\n3. 모델 학습: LangSmith 모델을 학습시킵니다. 이 단계에서는 모델의 파라미터를 조정하고 최적화 알고리즘을 사용하여 모델을 학습시킵니다. 모델을 학습시킬 때는 훈련 데이터를 사용합니다.\n\n4. 모델 테스트: 학습된 모델을 사용하여 테스트 데이터를 예측합니다. 예측 결과를 테스트 데이터의 실제 결과와 비교하여 모델의 성능을 평가합니다. 이를 통해 모델이 새로운 입력에 대해 얼마나 정확하게 예측하는지 알 수 있습니다.\n\n5. 모델 평가: 모델의 성능을 평가하기 위해 다양한 지표를 사용할 수 있습니다. 일반적으로 분류 문제의 경우 정확도, 정밀도, 재현율, F1 점수 등을 사용합니다. 회귀 문제의 경우 평균 제곱 오차(MSE)나 평균 절대 오차(MAE) 등을 사용할 수 있습니다.\n\n6. 모델 개선: 모델의 성능을 향상시키기 위해 다양한 방법을 시도할 수 있습니다. 예를 들어, 모델의 구조를 변경하거나 하이퍼파라미터를 조정하여 최적의 모델을 찾을 수 있습니다.\n\n7. 추가 테스트 및 평가: 모델을 개선한 후에는 다시 테스트 데이터를 사용하여 성능을 평가합니다. 이를 통해 모델의 개선 여부를 확인할 수 있습니다.\n\n8. 반복: 필요한 경우 위 단계를 반복하여 모델을 계속 개선할 수 있습니다. 데이터의 다양성을 높이거나 모델 구조를 변경하여 더 나은 성능을 얻을 수 있습니다.\n\nLangSmith의 테스트와 평가는 이러한 단계를 따라 진행될 수 있으며, 이를 통해 모델의 성능을 정량적으로 평가하고 개선할 수 있습니다.') LangSmith를 사용하여 Testing과 Evaluation을 수행하는 방법에 대해 알려드리겠습니다. LangSmith를 사용하여 프롬프트 또는 체인에 대한 변경 사항을 테스트하는 가장 기본적인 방법은 데이터 포인트를 사용하여 체인을 실행하고 출력을 시각화하는 것입니다. 여전히 기술적인 발전이 있지만, 출력물을 눈으로 확인하는 것에는 대체불가능한 것은 없습니다. 현재, 데이터 포인트 위에서 체인을 실행하는 작업은 클라이언트 측에서 수행되어야 합니다. LangSmith 클라이언트를 사용하면 데이터셋을 가져와서 체인을 실행하고 결과를 로깅하여 데이터셋과 관련된 새 프로젝트에 결과를 기록하는 것이 쉽습니다. 그런 다음 결과를 검토할 수 있습니다. 또한, 웹 앱에서 직접 피드백을 할당하고 테스트 프로젝트마다 집계 통계를 표시하여 실행에 대한 피드백을 기록하는 것도 쉽게 만들었습니다. 또한, 이러한 실행 결과를 평가하는 것도 더욱 쉽게 만들었습니다. 이를 위해 오픈 소스인 LangChain 라이브러리에 일련의 평가자를 추가했습니다. 이러한 평가자는 테스트 실행을 시작할 때 지정할 수 있으며, 테스트 실행이 완료되면 결과를 평가합니다. 솔직히 말하면, 이러한 평가자 중 대부분은 완벽하지 않습니다. 맹신해서는 안 되는 것들이라고 권장하지는 않습니다. 그러나 이러한 평가자는 살펴봐야 할 예제를 안내하는 데 유용하다고 생각합니다. 데이터 포인트의 수가 증가하고 각각을 수동으로 확인하기가 불가능해지는 경우 특히 가치가 있습니다. 인간 평가는 모델 동작에 대한 일관된 및 확장 가능한 정보를 얻는 데 도움이 되는 자동 평가 메트릭에 대한 완전한 대체물은 아직 없습니다. LangSmith는 주석 큐를 통해 실행을 수동으로 검토하고 주석을 추가하는 것을 쉽게 만들어줍니다. 이러한 큐를 사용하면 모델 유형이나 자동 평가 점수와 같은 기준에 따라 실행을 선택하고 사람에 의한 검토를 위해 큐에 추가할 수 있습니다. 리뷰어로서는 입력, 출력 및 기존 태그를 빠르게 확인한 후 자신의 피드백을 추가할 수 있습니다. 이를 통해 주관적인 품질을 평가하거나, 자동 평가된 실행의 일부를 샘플링하고 유효성을 검증하여 자동 메트릭이 여전히 신뢰할 수 있고 올바른 정보를 캡처하는지 확인하는 데 사용할 수 있습니다. 이렇게 큐를 사용하여 작성된 주석은 소스 실행에 "피드백"으로 할당되므로 나중에 필터링하고 분석하기 쉽습니다.

 

3) 대화형 LangChain 만들기

  • Chat History를 생성하여 대화형 LangChain을 만들 수 있음
# 프롬프트 양식 정의
from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
    ("user", "Given the above conversation, generate a search query to look up in order to get information relevant to the conversation")
])
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)

# Retrieval을 위한 문서 관련 추가 출력값 생성
from langchain_core.messages import HumanMessage, AIMessage

chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
retriever_chain.invoke({
    "chat_history": chat_history,
    "input": "Tell me how"
})

  • 4번째 Document가 ChatGPT로 추가 생성된 Document, 이걸 또 chain으로 활용할 수 있음
# 위에서 만든 추가 생성 텍스트도 같이 묶어서 chain 수행
prompt = ChatPromptTemplate.from_messages([
    ("system", "아래의 문맥을 바탕으로 사용자의 질문에 답변:\\n\\n{context}"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("user", "{input}"),
])
document_chain = create_stuff_documents_chain(llm, prompt)

retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)

# 대화형으로 답변 생성
chat_history = [HumanMessage(content="내 어플리케이션을 테스트하는 것에 LangSmith를 활용할 수 있어?"), AIMessage(content="네!")]
retrieval_chain.invoke({
    "chat_history": chat_history,
    "input": "어떻게 도움이 될 수 있는지 한국어로 얘기해줘."
})

  • LangSmith 문서 및 앞에서 생성한 텍스트까지 연계하여 최종 답변 생성

4) Agent 활용 웹 서칭 기능 붙이기

  • Tavily API를 활용하여 LangChain Hub에서 Agent 불러와서 기능 연동, 검색 내용을 기반으로 답변을 생성할 수 있음
# retriever 도구 세팅
from langchain.tools.retriever import create_retriever_tool
import os

retriever_tool = create_retriever_tool(
    retriever,
    "langsmith_search",
    "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
)

# TAVILY API 세팅
os.environ["TAVILY_API_KEY"] = "..."

from langchain_community.tools.tavily_search import TavilySearchResults
search = TavilySearchResults()

tools = [retriever_tool, search]
from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import create_openai_functions_agent
from langchain.agents import AgentExecutor

# 에이전트 및 프롬프트, LLM 세팅
prompt = hub.pull("hwchase17/openai-functions-agent")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 에이전트 작업 실행(답변 생성)
agent_executor.invoke({"input": "어떻게 LangSmith를 활용하여 LLM 어플리케이션을 테스트할 수 있지?"})

  • 검색 기능을 연동하는 것은 효과적일 수 있으나, 검색된 URL이 제대로 된 정보를 가지고 있지 않은 경우의 위험성이 존재, 그리고 한국어로 질문 및 답변 유도 시 제대로 돌아가지 않는 경우도 있음

5) LangChain 서빙

  • 서빙도 FastAPI + Uvicorn 활용해서 간단하게 수행 가능
  • 터미널에서 python serve.py 실행
#serve.py
from typing import List
import os

from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.tools.retriever import create_retriever_tool
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import create_openai_functions_agent
from langchain.agents import AgentExecutor
from langchain.pydantic_v1 import BaseModel, Field
from langchain_core.messages import BaseMessage
from langserve import add_routes

# 환경 변수 설정
os.environ["OPENAI_API_KEY"] = "..."
os.environ["TAVILY_API_KEY"] = "..."

# 1. Retriever 생성, 웹사이트 문서로 만들고 임베딩 벡터로 변환
loader = WebBaseLoader("<https://docs.smith.langchain.com/overview>")
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter()
documents = text_splitter.split_documents(docs)
embeddings = OpenAIEmbeddings()
vector = FAISS.from_documents(documents, embeddings)
retriever = vector.as_retriever()

# 2. Retriever 툴 만들기
retriever_tool = create_retriever_tool(
    retriever,
    "langsmith_search",
    "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
)

search = TavilySearchResults()
tools = [retriever_tool, search]

# 3. 웹 검색 기능이 포함된 
prompt = hub.pull("hwchase17/openai-functions-agent")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 4. 앱 정의
app = FastAPI(
  title="LangChain Server",
  version="1.0",
  description="A simple API server using LangChain's Runnable interfaces",
)

# 5. chain 라우팅 RestAPI URL 추가

# Pydantic Schema 정의 (API 입력값)
class Input(BaseModel):
    input: str
    chat_history: List[BaseMessage] = Field(
        ...,
        extra={"widget": {"type": "chat", "input": "location"}},
    )

# Pydantic Schema 정의 (API 출력값)
class Output(BaseModel):
    output: str

# 라우팅 실제로 추가하기
add_routes(
    app,
    agent_executor.with_types(input_type=Input, output_type=Output),
    path="/agent",
)

# .py 파일 실행 (uvicorn)
if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)
  • FASTAPI docs 바로 발행해 줌

  • Playground 형태의 테스트 UI도 만들어줌

4. LangChain Template 예제

  • 간단한 paper 리스트 추출 template, npm으로 app 추가하는 것처럼 쉽게 할 수 있음, 구조화된 형식의 텍스트 생성 필요할 때 활용할 수 있을 것
  • 단, Templates 서빙하기 전에 필요한 API key를 잘 정리해둘 것
// LangChain Templates 생성(도커 서빙)
pip install -U langchain-cli
langchain app new sum_app --package extraction-openai-functions
langchain serve
  • 따로 프론트엔드 template을 제공하지 않음. 백엔드 서빙 아키텍처 형태로 제공됨. test는 playground에서 가능

 

  • 따로 프론트엔드 template을 제공하지 않음. 백엔드 서빙 아키텍처 형태로 제공됨. test는 playground에서 가능
  • LangChain 보유 Template 리스트
    1. mongo-parent-document-retrieval: ****문서를 청크 단위 분할 기법으로 Retrieval 고도화
    2. Semi-Structured RAG: 텍스트와 테이블 포함 데이터 Retrieval 기능
    3. Temporal RAG: 시간 요소가 중요한 문서(SNS 게시물, 뉴스 등) Retrieval
    4. RAG-Fusion: 다중 쿼리를 생성한 다음 Fusion을 활용하여 Retrieval 문서 순위를 다시 지정
    5. Multi-Query Retriever: LLM으로 여러 쿼리를 생성하고 모든 쿼리에 대한 문서를 Retrieval
    6. Guardrails Output Parser: Guardrails-ai를 사용하여 LLM 출력을 검증
    7. ChatBot Feedback: LangSmith를 사용하여 챗봇 응답을 평가할 수 있는 기능
    • 그 외는 Reference의 LangChain Template 참고하시길..

5. 결론

  • 실제 배포 환경에서는 Template 예제처럼 langchain CLI로 도커 서빙하는 것이 정석으로 보임
  • 기본적으로 ChatGPT 등의 SaaS 외의 LLM 모델을 활용할 경우 웹/앱 개발 시 LangChain 프레임워크 필수
  • 온프레미스 환경에서의 LangChain 구축
    • 데이터 보안이나 외부망 활용이 제한되는 경우, 필수적으로 LangChain 프레임워크를 활용해야할 것으로 판단됨
  • 클라우드 환경에서의 LangChain 구축
  • 멀티모달 LangChain 적용 가능성
    • LangChain은 ChatGPT4의 Vision 기술과 결합될 수 있음
    • 이미지 생성 및 해석의 영역에서 Retreival, Agent 기능이 결합될 수 있을 것
    • 예시: 뉴스, 교재, 소설 등 삽화 생성, AI 기반 갤러리 도슨트 서비스 등..
  • GPT Assistants API: Playground와 API에서 LangChain의 기능들을 손쉽게 활용할 수 있도록 서비스 제공 중, ChatGPT의 기능과 최적화된 형태로 제공됨
  • 향후 ChatGPT 기반 웹/앱 개발 시에는 OpenAI의 API를 사용할 것인지, LangChain 프레임워크를 활용할 것인지 결정해야 하는 부분이 존재할 것

Reference

https://python.langchain.com/docs/get_started/introduction, Official Documentation

https://python.langchain.com/docs/templates/, LangChain Templates

https://en.wikipedia.org/wiki/LangChain, Wikipedia

https://www.samsungsds.com/kr/insights/what-is-langchain.html, Samsung SDS Post

https://www.youtube.com/watch?v=IZGBshGqB3g, GPT4 Vision + LangChain

 

Comments