회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
IT 지식이 무엇보다 중요해진 요즘, 여러분은 어떻게 공부하고 있나요? 가장 먼저 눈길이 가는 건 다양한 IT 강의 영상일 겁니다. 강의를 제공하는 교육 기업들과 함께, 요즘IT에서 ‘IT 강의 시리즈’를 준비했습니다. 엄선한 교육 영상을 텍스트로 읽고 필요한 정보를 빠르게 가져가세요.
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
IT 지식이 무엇보다 중요해진 요즘, 여러분은 어떻게 공부하고 있나요? 가장 먼저 눈길이 가는 건 다양한 IT 강의 영상일 겁니다. 강의를 제공하는 교육 기업들과 함께, 요즘IT에서 ‘IT 강의 시리즈’를 준비했습니다. 엄선한 교육 영상을 텍스트로 읽고 필요한 정보를 빠르게 가져가세요.
이번 강의는 ‘랭체인으로 LLM 기반 애플리케이션 설계하기’입니다. 구글 클라우드의 고객 엔지니어이자 이스라엘 라이히만 대학에서 컴퓨터 과학을 가르치는 에덴 마르코(Eden Marco) 님이 강의를 맡았습니다. 랭체인의 기본 개념부터 LLM 애플리케이션 개발에 도움을 주는 도구 정보까지, 텍스트 환경에 적합한 내용들만 간추려 소개합니다. 영어로 진행한 강의의 번역본을 기초로 글을 구성했습니다. 전체 영상은 유데미에서 확인할 수 있습니다.
안녕하세요, 에덴 마르코입니다. 이번에는 메모리에 관한 모든 것을 소개합니다. 정확히 말하면 ‘랭체인’에서의 메모리에 관한 것이죠.
상호참조해결(Coreference Resolution), 랭체인에서 메모리를 다루는 전략, 메시지를 영구적으로 저장하기 위한 LangGraph, 효율적인 메시지 활용을 위한 처리와 요약 방법을 다룹니다.
LLM에서 사용자 상호작용은 ‘무상태(stateless)’로 일어납니다. 기본적으로는 LLM이 이전에 발생한 대화에서 아무 정보도 저장하지 않는다는 뜻이죠. 그래서 state, less, 무상태인 겁니다.
예시를 살펴볼까요? 랭체인 공식문서를 학습한 대형 언어 모델에 누가 랭체인을 만들었는지 물으면, “해리슨 체이스가 만들었다”라는 올바른 답변을 받습니다.
하지만 이어서 그와 연관된 유튜브 비디오가 있는지 물으면 “죄송하지만 누구를 말씀하시는지 모르겠다”는 답변을 받습니다. 맥락을 더 제공하거나 그(him)가 누구인지 명확히 해달라고 하네요.
이런 문제는 어떻게 해결할까요? 이러한 문제를 해결하는 개념, 이제부터 알아볼 개념은 공식 용어로 ‘상호참조해결(Coreference Resolution)’이라 불립니다.
텍스트 안에서 동일한 개체나 개념을 참조하는 모든 표현이나 단어, 문구를 식별하는 작업이죠. 다시 말해 하나의 텍스트 안에서 어떠한 단어나 문구와 동일한 것을 지칭하는 모든 인스턴스를 식별하는 과정입니다.
앞서 질문에서도 ‘그(Him)’는 해리슨 체이스(Harisson Chase)를 가리키지만 LLM은 상태가 없기 때문에, 상호참조해결을 할 수 없었습니다.
그러나 만약 LLM이 프롬프트에서 상태와 채팅 히스토리를 받는다면 상호참조해결을 할 수 있을 겁니다.
이것이 현재 랭체인이 메모리를 위해 지원하는 모든 솔루션의 기본적인 토대입니다. 프롬프트에 데이터와 정보를 전달해 LLM이 상호참조해결을 할 수 있을 정교한 방법을 찾는 거죠.
자, 이런 사람과 봇의 대화 예시가 있습니다. 여기, 이전 대화에 기반해 질문에 답하라는 프롬프트를 제공하겠습니다.
이전 대화로 주는 내용은 사용자와 봇 사이의 일어난 소통이죠. 사용자는 “콜드브루 커피를 좋아하는데, 어디에서 구할 수 있냐”고 묻습니다. 봇이 ‘스타벅스’를 알려 주지만, 사용자는 스타벅스가 싫다며 다른 곳은 없는 지 묻죠. 이번에 봇은 ‘커피빈’을 추천합니다. 사용자의 마지막 질문은 “그걸 또 어디에서 찾을 수 있냐?”는 거고요.
여기서 ‘그것(that)’은 콜드브루 커피를 말합니다. 또한 사용자가 스타벅스나 커피빈에서 마시고 싶지 않다는 것(else)을 LLM이 알고 있다면 이 정보를 쉽게 처리해 상호참조해결을 할 수 있습니다.
랭체인에서 메모리를 다루는 전략은 여러 차례 수정을 거쳤습니다. 지금부터는 챗봇에 메모리를 설정하는 작업의 최신 모범 사례를 소개하려고 합니다.
여기서 ‘메모리’라고 하면, 모든 메모리, 일반적으로 메시지를 LLM 코드에 채우는 거라고 생각하면 됩니다.
다만 어떤 경우에는 토큰 제한을 초과해 메모리가 충분하지 않을 수 있습니다. 돈이 많이 들기도 하고요. 그래서 매번 모든 메모리를 LLM에 보낼 필요는 없습니다. 컨텍스트 윈도우가 큰 LLM을 사용하더라도 말입니다.
예를 들어, Gemini 1.5 Pro를 쓰면서 몇백만 개의 토큰을 보낸다면, 비용도 많이 들고, 속도도 느려질 것입니다. 오히려 더 나쁜 결과를 얻기도 합니다. LLM이 처리할 필요가 없는 쓸데없는 것들도 보내게 되니까요. “쓰레기를 넣으면 쓰레기가 나온다는 말”을 기억해야 합니다.
현재 랭체인에는 이를 처리하는 주요 전략이 세 가지 있습니다.
첫 번째 전략은 단순히 문제를 무시하고, 아무것도 하지 않은 상태로 모든 걸 LLM 코드에 넣는 겁니다. 이 방법도 사용자와 봇 사이에 짧은 대화만 오갔을 때는 유용할 수 있습니다. 또, 시작하기에 가장 쉬운 방법이죠.
두 번째 방법은 오래된 메시지를 삭제하는 겁니다. 챗봇과 관련 없을 법한 메시지를 맨 처음 단계에서 제거하는 겁니다. 바로 이게 휴리스틱입니다. 물론 항상 좋은 건 아니지만요.
마지막, 또 다른 전략은 메시지를 쓰기 좋은 형태로 처리하는 겁니다. 예를 들어, 모든 메시지를 요약한 다음, 그 요악본과 마지막 메시지 몇 개만 저장하는 방식이죠.
지금까지 우리가 나눈 전략은 모두 어떤 메시지를 저장할지에 관한 이야기입니다.
모두 저장할지, 오래된 메시지를 필터링할지, 요약본을 저장할지 같이 말이죠. 하지만 메시지를 어디에 저장할지, 어떻게 관리할지는 논의하지 않았습니다.
랭체인 생태계에서 이를 수행하는 가장 새로운 방법은 LangGraph를 사용하는 겁니다. 핵심 개념은 체크포인터입니다. 이 체크포인터가 메시지를 영속(persistence)하는 데 도움을 주죠. 사용하기도 아주 쉽습니다.
예시를 보겠습니다. 모든 과거의 메시지를 LLM에 전달하는 방법입니다.
여기 보이는 채팅 프롬프트 템플릿에는 from_messages 함수를 사용하고 있습니다. 이로써 시스템 지침에 대한 시스템 메시지를 볼 수 있습니다. 여기에는 변수 이름이 messages인 메시지 플레이스홀더 객체가 있어요.
이렇게 랭체인에 이 변수를 활용해 사용자의 모든 과거 기록을 동적으로 삽입할 것임을 알리는 겁니다. 그리고는 바로 그 객체에 여러 메시지를 삽입하는 거죠.
형식은 사전과 같습니다. 아래 코드처럼 체인을 호출하며 메시지를 가진 사전을 보내는데요, 이 사전에는 사용자의 모든 과거 메시지 목록이 들어 있습니다. 인간이 보낸 메시지에 AI가 응답한 메시지가 있고, 또다시 인간이 보낸 메시지가 있네요.
이렇게 보류 중인 메시지 히스토리를 LLM에 보냅니다. 어떻게 보낼까요? Arena 애플리케이션에서는 영속성 DB를 사용해 모든 메시지를 저장하고, 검색하며, 가져와 보냅니다. 이게 메시지를 보내는 부분입니다.
이제 랭체인, 정확히 말해 LangGraph가 메시지를 영속하는 데 어떤 도움을 주는지 보겠습니다. LangGraph의 핵심인 체크포인터 또는, 체크포인팅이라는 개념도 함께요.
간단히 말하면, 반복해서 보내는 모든 사용자 메시지나 AI 봇의 메시지에서, LangGraph가 정보를 가져와 DB에 영속성으로 저장하는 겁니다.
이때 메모리에는 저장으로 지속되지 않는 메모리 세이버 체크포인트가 있습니다. PostgreSQL, MySQL, Redis, MongoDB 등 체크포인트가 있죠. 그 외에도 LangGraph에는 다른 통합이 많이 이루어질 것이며, 영구 보관되는 데이터베이스에 메시지를 저장하는 데 도움을 줄 겁니다.
우리는 체크포인트 객체를 생성해서 LangGraph에 전달하기만 하면 됩니다.
여기서는, 체크포인트가 모든 영속성 작업을 수행하며 DB에 영구적으로 보관한게 돕는다는 걸 이해하는 것이 가장 중요합니다.
그럼 다시 메시지를 어떻게 처리하는지 이야기해 봅시다.
오래 지나 필요 없는 메시지를 무시하려면 어떻게 해야 할까요? 토큰, 지연 시간, 비용을 절약할 수 있도록 랭체인은 트리머(trimmer)라는 개념을 도입합니다. 메시지를 다듬을 객체죠. trim_messages 함수로 트리머를 생성할 수 있습니다.
이제 트리머의 전략을 정해야 합니다. 랭체인은 다양한 트리밍을 처리하는 법, 즉, 무엇을 제거할지 여러 방법을 제공합니다. 아래 예시에서는 최대 토큰을 설정하고, 토큰 카운터를 len으로 설정하는 방법을 썼습니다. 이처럼 토큰 수나 메시지 수에 따라 트리밍할 수 있습니다. 그 외에도 많은 옵션이 있죠. 트리머를 호출하려면 invoke 메서드를 사용하고 처리할 모든 메시지를 입력해야 합니다. 그 후 트리밍된 메시지만 남았을 때, LLM에 보내면 되는 것이죠.
요약 또한 토큰을 절약하고 LLM에 정확한 컨텍스트를 보낼 수 있는 다른 기술입니다.
여기 요약 프롬프트가 작업을 수행합니다. 이 프롬프트는 우리가 가진 모든 기록을 받아서 하나의 요약본으로 정리합니다. 이걸 영속성 스토리지에 저장하는 거예요. 이처럼 메시지를 요약할 때마다, 미가공 메시지는 필요 없어지니 나중에 가서 간단히 삭제하면 토큰을 절약할 수 있습니다.
여기까지가 데이터를 체크포인팅하기 전에 필요한 몇 가지 작업입니다.
다시 한번 강조할게요. 메모리에 무엇을 저장하는지, 이를 이해해야 합니다. 모든 미가공 메시지를 저장하거나, 다듬어진 일부 메시지를 저장하거나, 메시지의 요약본을 저장할 수 있습니다. 물론 저장하고 싶은 메모리에 대한 처리 과정을 추가할 수도 있습니다. 또, 이 기능을 애플리케이션에 더 적합한 로직으로 확장할 수도 있죠. 기록과 메시지를 저장하는 것, 그걸 영속하는 것은 LangGraph 체크포인터에 의해 이루어집니다. 최근 선호되는 방법이죠. 이때 체크포인터 객체는 데이터를 가져가 DB 쿼리를 만들어 타깃 DB에 보내는 역할을 합니다.
이 작업을 우리가 직접 처리하지 않고 모두 랭체인에 맡기는 이유는 뭘까요? 이미 구현된, 편리한 함수이기 때문입니다. 이미 프레임워크가 모든 사용 사례를 알아 해결책을 제공하는데, 새로 만들 이유가 없는 거죠. 적어도 제 생각에는 그렇습니다.
원본 영상 바로가기 https://bit.ly/udemy_langchain3
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.