이번 글은 필자가 현재 진행 중인 프로젝트에서 사용하는 프레임워크인 LangChain과 LangGraph에 대해 소개해보고자 합니다.
들어가기에 앞서, 본 글은 프로젝트 개발 과정에서 얻었던 경험들과 공부했던 내용들을 기반으로 LangChain과 LangGraph를 입문하고자 하는 분들에게 있어 소개글 같은 느낌이 될 예정입니다.
가볍게 읽어주시면 좋을 것 같습니다.
LangChain
from transformers import pipeline
from langchain_huggingface import HuggingFacePipeline
from langchain_core.prompts import ChatPromptTemplate
pipe = pipeline(
"text-generation",
model="Qwen/Qwen2.5-3B",
device=0
)
llm = HuggingFacePipeline(pipeline=pipe)
prompt = ChatPromptTemplate.from_template("너는 세계 최고의 바리스타야. 질문에 답해. <Question>: {input}")
chain = prompt | llm
chain.invoke({"input": "커피는 마셔도 마셔도 계속 마시고 싶어."})
"""
Output:
'Human: 너는 세계 최고의 바리스타야. 질문에 답해.
<Question>: 커피는 마셔도 마셔도 계속 마시고 싶어. 왜 그럴까?
<Answer>:\n\nAssistant: 커피를 계속 마시고 싶어하는 데에는 여러 이유가 있습니다.\n\n
1. 커피가 몸에 좋다: 커피에는 카페인과 여러 유익한 영양소가 포함되어 있습니다.
카페인은 몸에 다양한 이점이 있습니다. 예를 들어, 카페인은 신경계를 활성화하고 에너지를 증가시킵니다.
이는 운동이나 비만을 방지하는 데 유용할 수 있습니다. 또한, 커피에는 베타카로틴, 비타민 B3 등을 포함하는 다양한 영양소가 있습니다.\n\n
2. 커피가 심리적으로도 좋다: 커피를 마시면 인지능력이 향상되고 집중력이 향상될 수 있습니다. 이는 카페인의 작용 때문입니다.
카페인은 대뇌에서 신경전달물질인 에피네프린의 분비를 증가시켜서 신경계의 활동을 강화합니다'
"""
LangChain을 이용한 간단한 코드이지만, 필자는 해당 코드가 LangChain이 어떤 느낌의 프레임워크인지 보여줄 수 있다고 생각합니다.
아마 대부분 코드의 ' | '에 조금 주목을 하실겁니다. 저 역시도 그랬습니다.
| 을 하나의 체인이라고 생각하시면 이해하시기 편하실겁니다.
그러면, 이제 chain = prompt | llm 이 부분은 미리 정의해둔 prompt와 불러온 로컬 모델과 하나의 체인을 묶은 걸 chain이라는 변수에 저장했다고 생각하면 되겠죠??
그리고 이제 invoke 함수를 이용해 prompt에 삽입해둔 {input}에 들어갈 질문을 넣어주면 답변을 얻을 수 있는겁니다.
Pytorch, HuggingFace transformers를 모두 사용을 해보며 크고 작은 코드들을 여럿 다루어 보았지만, 이렇게 간단히 코드를 작성할 수 있어서 상당히 인상적이었습니다.
이렇게 코드 작성이 편리함에도 현재 프로젝트를 하면서 상당히 고도화된 아키텍쳐들도 만드는데 제약이 그렇게 많지 않다는 점 또한 되게 인상적이었습니다. (진행 중인 프로젝트가 끝나면 Project Review를 한 번 하도록 하겠습니다.)
2022년에 첫 런칭을 해서 지금도 꾸준히 업데이트를 진행 중인 프레임워크로서, 필자는 개인적으로 앞으로도 더 많은 유저가 유입되지 않을까 기대하고 응원하는 프레임워크입니다.
이제, LangChain은 | 를 이용해서 단방향 플로우 아키텍쳐를 구성해볼 수 있다는 것을 어느 정도 느낌이 오실겁니다.
하지만, 단방향 플로우의 아키텍쳐의 단점은 분명 존재합니다. 필자 역시도 단방향 플로우의 아키텍쳐가 아니라 조건에 따라서는 다시 되돌아가거나 분기가 있는 플로우의 아키텍쳐를 구성하고자 했고 이는 LangChain으로는 한계가 분명 존재했습니다.
이러한 한계를 해결하고자 나온 프레임워크가 LangGraph입니다.
LangGraph
위 사진처럼 __start__부터 __end__까지 하나의 플로우를 workflow라고 합니다.
간단한 예시의 workflow 그래프만 봐도 단방향 플로우가 아닌 것을 알 수 있듯이, 사용자가 설계하는대로 정교한 workflow를 제작하여 Multi-Agents를 운용할 수 있는 것이죠.
LangGraph는 이름답게, node와 node들 간을 잇는 edge로 이루어져 있습니다.
from langgraph.graph import StateGraph, START
workflow = StateGraph(State)
workflow.add_node("retrieve", retrieve)
workflow.add_node("search_on_web", search_on_web)
workflow.add_node("document_checker", grade_checker)
workflow.add_conditional_edges(
START,
route_question,
{
"web_search": "search_on_web",
"vectorstore": "retrieve",
},
)
workflow.add_edge("retrieve", "document_checker")
LangGraph를 어떻게 사용하는지 정말 느낌 정도를 볼 수 있게 해주는 예제 코드입니다.
Node들은 서로 독립적이기 때문에 정보의 공유가 없습니다. 하지만 State가 미리 정의해둔 값들을 각 Node가 실행 후 반환하는 결과를 받아 다음으로 실행될 Node로 전달해주는 역할을 합니다.
또한 LangGraph에서 주목할 부분은, 단방향 플로우가 아닌 여러 분기점을 갖는 플로우를 갖게 해주는 add_conditional_edges()입니다.
이 부분은 if문을 생각하시면 좀 더 이해가 잘 되실겁니다.
현재 위치한 노드가 START이고 route_question에서 "web_search"가 반환되면 "search_on_web" Node로 이동, "vectorstore"가 반환되면 "retrieve" Node로 이동하게 되는겁니다.
이런 느낌으로 사용자는 더욱 고도화된 워크플로우를 LangGraph를 이용해서 제작하실 수 있겠죠?
개인적으로는 LangChain과 LangGraph를 독립적으로 생각하시는 것보다, LangChain을 공부하시고 LangGraph를 공부하시는 순서를 가져가시면 더욱 좋은 결과물을 얻으실 수 있지 않을까 싶습니다.
이번 글에서는 LangChain와 LangGraph를 입문하고자 하는 분들의 하나의 자그만한 소개를 담아보았습니다.
감사합니다.
'Tech Experiments & Study > Advanced' 카테고리의 다른 글
BM25 & Vector Search (0) | 2025.09.19 |
---|