Community

항해 플러스 AI 후기 6주차 WIL

1. 이번 주 목표 * 커리큘럼 상의 목표는 챗봇의 형태의 서비스를 구현해보는것 이다. * 커리큘럼 자체보다는 LangChain에 관심이 많아 이를 더 잘 이해하기 위한 포석으로 삼는다. 2. 학습 내용 1. LangChain 기본적으로 챗봇 은 다음과 같은 방식으로 동작한다. 1. 유저의 메세지를 LLM에 입력으로 전달 2. LLM inference를 통해 출력으로 답변을 획득 3. 획득한 답변을 유저에게 반환 4. 그런데 LLM inference는 다음과 같은 문제들을 수반한다. * 다양한 LLM inference: 지금도 계속해서 새로운 LLM이 생겨나고 있고, 서로 다른 interface를 제공한다. 예를들어 HuggingFace 에서 LLM들과 API를 통해 사용할 수 있는 GPT-4는 아예 다른 방식으로 구현해야 한다. 따라서 LLM을 교체할 때마다 새로 구현을 해야하는 비용이 발생한다. * Prompt design: LLM inference의 성능은 prompting에 따라 좌우된다. 특정한 template이 주어졌을 때 유저의 메세지를 잘 수정해주는 코드를 구현하는 것은 많은 공수가 들어간다. * 높은 외부 data source 사용 난이도: RAG와 같은 방식은 외부 data source를 활용한다. 하지만 이렇게 외부 source를 활용하는 방식은 개인이 처음부터 구현하기에 난이도가 너무 높다. 이런 문제들을 해결하기 위한 도구 중 LangChain이 있다. * LangChain이란? 💡 LangChain은 대규모 언어 모델(LLM)을 사용하여 애플리케이션을 개발하기 위한 오픈 소스 오케스트레이션 프레임워크이다. 챗봇 같은 LLM 기반 애플리케이션을 구축하는 과정을 간소화시킬 수 있다. LangChain이 제공하는 기능들을 요약하면 다음과 같다. * LLM abstraction: 여러가지 LLM interface를 쉽게 대응할 수 있는 pipeline을 제공한다. HuggingFace, GPT-4, Gemini 등 다양한 LLM들을 최소한의 코드 수정으로 inference할 수 있게 해준다. * Prompt template: 유저의 메세지를 주어진 template에 맞춰 자동으로 수정하는 기능을 제공한다. * Indexes: 외부 data source를 사용한 LLM inference를 쉽게 진행할 수 있게 indexes를 제공한다. 2. LangGraph 커뮤니티에서 LangGraph에 대한 언급을 몇번 목격한 적이 있다. LangChain에 대해 정리하게 된 김에, LangGraph에 대해도 한번 정리해보면 좋을 것 같다는 생각이 들었다. LangChain으로 pipeline을 구성해서 상태 전달을 하고, 그 과정에서 출력을 만들어 낸다. 이 과정에서 발생할 수 있는 문제는 다음과 같다. 1. LLM pipeline 내에서 상태 전달을 할 때 특정 단계의 출력이 문제가 되어 전체 파이프라인에 문제가 발생 2. 이런 문제를 해결하기 위해 전후처리나 분기처리등을 추가하곤 하는데 LLM의 특성상 잘 제어되지 않음. LangGraph는 LangChain 생태계에서 발생하는 위와 같은 상태 전달 문제들을 보완하기 위해 만든 프레임워크이다. 심지어 LangChain 진영에서 직접 만들었다. 2.1 LangGraph의 특징 1. 상태 기반 그래프 구조: 애플리케이션의 로직을 노드와 엣지로 구성된 그래프로 표현한다. 2. 유연한 상태 관리: 복잡한 상태를 쉽게 정의하고 관리할 수 있다. 3. 조건부 라우팅: 동적인 의사결정 프로세스를 구현할 수 있다. 4. 체크포인팅: 그래프 실행 상태를 저장하고 복원할 수 있어 장기 실행 태스크와 오류 복구에 유용하다. 5. 서브그래프 지원: 복잡한 시스템을 모듈화하여 관리할 수 있다. 2.2 LangChain과의 비교 LangChain과 LangGraph는 둘 다 LLM 애플리케이션 개발을 위한 도구지만, 약간의 차이가 있다. | 특징 | LangGraph | LangChain | |--------------|------------------------------------------------|-----------------------------------------------| | 주요 목적 | 복잡한 워크플로우 및 의사결정 프로세스 구현 | LLM 통합 및 체인 구성 | | 구조 | 그래프 기반 | 체인 및 에이전트 기반 | | 상태 관리 | 명시적이고 세밀한 제어 | 암시적이고 자동화된 관리 | | 유연성 | 높음 (커스텀 로직 쉽게 구현) | 중간 (미리 정의된 컴포넌트 중심) | | 학습 곡선 | 상대적으로 가파름 | 상대적으로 완만함 | | 용도 | 복잡한 AI 시스템, 다중 에이전트 | 간단한 LLM 애플리케이션, RAG | 현재 LangChain만 사용해본 입장에서 이렇게 장단점을 테이블로 정리해도 크게 와닿지는 않는다. 다만 선택을 한다고 했을 때 프로덕트의 현재 단계나 목적에 따라 선택이 나뉠 수 있을 것 같다. * 빠른 프로토타이핑으로 검증하기 위해서라면: LangChain * 검증은 이미 되었고 사용성을 더 고도화 하기 위해서라면: LangGraph 프로덕트의 라이프 사이클에서도 자연스럽다고 느껴진다. LangChain으로 빠른 검증을 하고, LangGraph로 이주한다. 혹은 개념상으로 LangGraph상의 단일 노드가 이전 단계에서 LangChain으로 만들어놓은 결과물이 될 수도 있다. 만약 내가 멀티모달 형태의 서비스를 구현해야 한다면 애초에 입력부터 분기가 발생하기 때문에 주저하지 않고 LangGraph를 선택할 것 같다. 3. Streamlit 앞에서 LangChain에 대해서는 충분히 알아봤다. 그럼 Backend는 LangChain으로 구성한다고 치고, 챗봇은 Frontend도 필요하지 않은가? 처음부터 프론트엔드를 붙여서 개발하기에는, LangChain의 장점인 빠른 프로토타입을 통한 검증 이 상쇄되는 느낌이다. 그래서 이럴 때 사용하기 좋은 Streamlit 이라는 오픈소스 웹 프레임워크가 존재하고, 다음과 같은 특징이 있다. * Pure Python: 순수하게 Python으로 구성되어 있다. Python만 사용해서 UI를 구성할 수 있으므로, HuggingFace와 같은 AI Model을 쉽게 활용할 수 있는 장점이 있다. * 다양한 Widget: slider, 차트, 챗봇과 같은 직접 구현하기 복잡한데 활용도는 높은 widget들을 제공하고 있다. 3.1 예시 코드 다음은 Streamlit 으로 챗봇을 구성하는 예시 코드이다. import streamlit as st from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, AIMessage model = ChatOpenAI(model="gpt-4o-mini") st.title("GPT Bot") # Session state 초기화 if "messages" not in st.session_state: st.session_state.messages = [] # 만약 app이 rerun하면 message들을 다시 UI에 띄우기 for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("What is up?"): with st.chat_message("user"): st.markdown(prompt) st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("assistant"): messages = [] for m in st.session_state.messages: if m["role"] == "user": messages.append(HumanMessage(content=m["content"])) else: messages.append(AIMessage(content=m["content"])) result = model.invoke(messages) response = result.content st.markdown(response) st.session_state.messages.append({ "role": "assistant", "content": response }) 여기서 Gemma3 같은 오픈소스 LLM으로 변경하는 방법도 존재할 것 같다. 3. 느낀점 * 이제 드디어 LangChain과 LangGraph의 경계가 분명해졌다. * 챗봇을 구현하는건 재밌었다. Gemma3를 파인튜닝한 후 서빙해보면 좋을 것 같다.

알림

알림이 없습니다