LLM에 RAG를 결합하여 내 블로그를 안내해주는 개인 사서
Description: RAG를 통해 저의 블로그를 설명해주는 LLM을 만들어보고자 시작한 프로젝트입니다. 당시 개발지식이 부족하여 주먹구구식인 부분이 많지만, 실제로 동작했던 서비스를 처음부터 만들어본 점에서 뜻 깊은 프로젝트였습니다.
현재 노트: KR-110.10 LLM에 RAG를 결합하여 내 블로그를 안내해주는 개인 사서
하위 분류
- KR-110.10 a Langchain ,Streamlit , Milvus 등의 LLM을 위한 툴
프로젝트 개요
보유하고 있는 데이터를 이용하여 LLM과 결합하여 개인 사서 RAG시스템을 목표로 시작한 프로젝트입니다. 나중에 스스로에게 물어볼때나 블로그 글을 전부 읽지 않더라고 나에대해 궁금한 사람들을 대신 대답해주기 위한 목적
설명을 덧 붙이자면 Chatgpt와 같은 LLM은 기존의 학습된 내용이외에 대답을 못하고 웹서치나, 파인튜닝등과 같은 여러 기술을 요구하는데 그중에서도 RAG라는 기술은 구현하기 쉬우면서도 개인의 정보를 바탕으로 개인화된 기능을 제공해주는 방식입니다.
예를들어 Chatgpt와 같은 LLM에 블로그주인의 정보를 묻는다면 모른다 라고하겠지만, RAG를 통해 정보를 주어지면 제 블로그 글을 바탕으로 대답이 가능하게 됩니다.
코드
https://github.com/murphybread/Librarian
아키텍쳐
프로젝트 하면서 느꼈던 점들
기능 구현을 위해서 덜 완벽한 애플리케이션 만들기
기능 구현식 부족한 개발지식과 앞으로의 운영을 위해 포기할 것을 선정하는 경험을하였습니다. 한 번도 아니고 여러번 있었긴 했지만 그 중에서 인상 깊었던것은 메모리 기능
이였습니다.
왜냐하면 이 기능을 구현하면서 항상 100점짜리를 만들려고했던 마인드에서 85점정도도 괜찮지않나를 생각했기 때문입니다.
처음에는 회원기능 즉 로그인과 비밀번호를 통해 자신이 이야기했던 대화를 기록하고자하였습니다. 하지만 개발을 막 시작한당시라 로그인과 비밀번호가 얼마나 어려운지 잘몰랐고, Streamlit이라는 프레임워크에 종속되다보니 지원하지 않는 기능이 불가능하다는 것을 깨닫기까지 시간이 오래걸렸습니다.
이후 비슷한 고민들을 구현한 레퍼런스들을 찾아보았고, Streamlit에서 페이지 렌더링의 경우 세밀하게 조절이 가능해 if문의 분기처리 를 통해 password라는 프로퍼티값의 일치여부로 페이지 렌더링으로 유사한 기능이 가능하다는 것을 깨달았습니다. 하지만 이 방법도 결국 로그인하기위한 키와 같은 것을 어떻게 저장해서 어떻게 전달할지가 해결되지 않았기에 구현되지 못하였습니다.
다른 방법을 찾던 중 일단 무엇을이라는 문제는 고유키값을 이용해보자라는 아이디어를 얻었습니ㅏ. 개인화된 방식이 아닌 uuid를 이용하여 고유화된 값을 이용해 마치 로그인 로그아웃해서 정보를 얻는것과 같은 효과를 낼 수 있다고 생각했기 떄문입니다.
마지막으로 남는 것은 이걸 어떻게였습니다. 그 때 당시에는 어플리케이션이 완벽히 기능을 제공하고 사용자는 무조건 편의성을 고려한 방식이 어플리케이션을 갖춰야할 조건이라고 생각하였습니다. 그래서 해당 uuid값을 앱내에서 쉽게 저장,관리,불러오기 기능을 구현해야한다고 생각했습니다. 하지만 구현난이도가 너무어려웠고 결국 유저에게 제공해서 유저가 기록하는 방법을 선택하였습니다. 즉 프로그램실행되는동안 메모리 uuid값을 노출하고, 나중에 메모리기능을 쓰고 싶으면 해당 값을 사용하는 방식으로 제공하기로하였습니다.
이 과정에서 정말 필요한 기능을 위해선 포기하고 수정해야할 것들을 적절히 선택하며 모든것이 완벽한 100점짜리 애플리케이션을 만드는 것보다 적절히 부족하지만 원하는 기능이 돌아가는 애플리케이션을 만드는 것도 중요하다는것을 깨달았습니다.
라이브러리와 프레임워크를 주의해야할 때
라이브러리나 패키지의 추상화에의한 의존성문제에서 많은 것을 배웠습니다. 여러 라이브러리나 프레임워크를 사용하다보면 결국 어디서 왜 문제가 생겼는지를 파악하기 어렵다는 것을 꺠달았습니다.
기본적으로 Langchain이라는 프레임워크가 LLM을 쉽게 사용하기 위해 추상화를 하게됩니다.
그리고 Mlivus라는 벡터 DB의 경우도 official docs에서 어떤 의미로 추상화 돼있습니다.
그리고 이 Milvus를 서비스하는 Zilliz Cloud에서 자체 api를 통해 한번 더 추상화가 이루어집니다.
마지막으로 웹 프론트엔드인 Streamlit도 기능이 추상화 돼있기때문에 해당 official docs를 보고 , 부족한부분은 코드를 뜯어봐야했습니다.
이렇게 복잡한 추상화다보니 처음 Streamlit에서 문제가 생기면 일일히 다 확인을 해보아야했습니다. 이후에는 그나마 구간 구간 나누어서 테스트를하였습니다.
여기서 제일 힘들었던 부분이 버전이 바뀌면서 벡터DB를 지원하는 기능에 변경점이 생
긴 부분이었습니다. 업데이트가 잦은 Milvus에서 1.24
버전이 되고 이에 맞춰 Zilliz Cloud가 업데이트를 안하는점이었습니다. API의 경우 입력 출력 양식과 파라미터등이 민감하게 반응하다보니 이런부분에서 큰 어려움이 있었습니다. 결국패키지의 버전을 고정하는 방법으로 해당 문제를 수정하였습니다.
이 과정에서 사용하기 편리하게 만든 것을 많이 사용 하다보면 결국 문제가 생길 때 해결하기 어렵다는 점을 배웠습니다. 흔히 라이브러리나 프레임워크에 의지하지 말라라는 말이 어떤 말인지를 몸으로 배웠던 경험이었습니다.