
졸업 프로젝트에서 챗봇 파트가 있어 설계를 진행하였다.
1차로 문서가 들어왔을 때 챗봇의 제어를 통하여 부정문 선정을 진행하게 된다. (로직은 조금 더 자세하지만, 큰 틀로 볼 때)
-> 이 부분에서 멘토님께서 확장 기능으로 문서나 사용자의 요구, 인터넷 검색 등의 Rag 혹은 context 사용 시, AI가 인지하고 분석한 데이터에 대한 Client를 향한 피드백을 주고 이에 대한 의사소통이 있으면 좋겠다고 말씀해주셔서, 이에 대해서 확장 가능하게 설계를 해야한다. (요구 사항으로 분리)
-> 주제문 -> 부정문으로 가능 부분에서 조건 3 파트에서도 Ban_list에 문서 승인자의 개인적인 선호도 (청킹 단위 분석) 들어가기 위해서 저 부분에 대한 확장도 요구사항 가능성을 위하여 분리되어야 한다.
2차로 해당 부정문 선정과 관련한 피드백을 기반으로 2차 챗봇이 수정을 하게 된다. 이 과정에서 1차에서 받은 피드백을 기반으로 하고 Ban_list와 웹 크롤링, 검색 API, 기존 유지하는 Vector DB, RDB 등이 합산되어 최종 문서의 퀄리티에 대한 가이드를 제공한다.
사용 모델은 추천에서는 일단 4개이지만, OCR 모델과 임베딩 모델 같은 경우는 챗봇을 구성하는 여러 파트 중 하나라고 생각하여 일단 제외 시키고 가장 베이스 되는 모델은 2개가 된다. 경량화 LLM 모델과 전체 제어를 담당하게 되는 커다란 LLM 모델이다.
여기서 추가적으로 정하게 된 부분은,
대화의 내용을 기억하는 방식 -> Session key? 에 대한 문제이다.
챗봇 파트는 마이크로 웹 서비스를 가정하고 서버 자체를 분리하여 개발을 진행하고 있다.
고민 1:
챗봇 파트 뿐 아니라 전체 서비스(- 유저 및 문서 작성 및 편집)는 FastAPI 백엔드 기반에 JWT 인증 방식을 사용하고 있다.
기껏 JWT을 stateless를 기대하고 사용하였는데 대화 내용 기억을 위하여 Session 방식을 사용하는게 약간 좀 별로라는 생각이 들었다.
그래서 일단 AWS 기준으로 챗봇 자체의 서버 인스턴스 인바운드를 메인 백엔드 서버만 가능하게 하던지 아니면 API Gateway를 백엔드와 챗봇 서비스 사이에 추가하여 이 처리를 좀 다루는 파트를 나눌 지, 또한 대화 내용을 기억해야 하는지? 등 고민 중이다.
고민 2:
여러 모델을 함께 사용하는 AI agent 기반의 챗봇을 구현하기 위해서 Langchain을 사용하는데, 처음에는 Langchain을 라이브러리라고 생각했는데, 일부분 문법 강제와, Agent 자체가 가지고 있는 미들웨어, @tool 혹은 tool과 비슷한 구조와 같이 뭔가 프레임워크라 생각하게 되었다. 찾아보니 일종의 작은 MVC 구조를 가진다는 것을 알게 되어서 백엔드 프레임워크 기반으로 이를 어떻게 처리할 지에 대한 고민이 있다. -> FastAPI 기준으로 Service - Repository 등의 구조를 갖게 하고 Redis, VectorDB, MariaDB, 외부 검색 API 등의 의존성을 주입 시키는 형태로 구현을 하려 했으나 이것을 Agent단위로 진행을 해야할 지, Tool 단위로 진행해야 할 지 -> Tool단위로 한다면 tool을 클래스로 묶어서 사용해야 하는데 이게 Langchain에서 권장하는 문법으로 생각되지 않아 어떤 것이 맞는 방식인지에 대한 고민이 있었다.
고민 2.1:
Main App (FastAPI) -> Sub App (Main Model(llama-3-70B)) 의 형태로 이해하면 된다고 생각했다. 그러면 만약 경량화 모델을 사용한다면, Main -> Sub -> Sub2의 형태가 되는 것인가에 대한 궁금증이 있었는데 이 부분은 랭체인 오케트레이션을 학습하고 LangGraph를 알아야 한다고 한다. (아... ㅆ)
일단 기본적인 구조를 잡아두고 개발을 진행하려 했으나 리팩토링으로 관심사 분리가 생각보다 난이도가 좀 있다고 생각해서 구조에 대한 고민이 계속 된다.
현재 FastAPI 기준으로 본다면, 엔드포인트에서 -> LLM Service 코드에 접근하는 단 하나의 로직만이 존재한다.
물론 저 LLM Service는 Langchain agent에서 main model로 접근하는 로직이기 때문에 수많은 Depends가 엮일 예정이다.
그리고 그 하위에서 그 의존성 객체를 받아 경량화, main model 등에 각각 배분해 줄 예정이다.
그렇기 때문에 service 디렉토리 하위에 LLM 디렉토리를 생성하고 llm 디렉토리를 하나의 백엔드라 생각하고 내부에 새롭게 구조를 잡아주는 느낌으로 생각하고 있다.
고민 3:
Langchain에서 제공하는 agent는 middleware가 존재한다.
근데 지금 궁금한 부분은 멘토님께서 피드백 주신 부분 중, LLM의 순간의 생각을 가져와야 하는 부분이다.
그러면 두 가지 선택지가 있다고 생각하는데,
LLM의 중간 생각처럼 보이게 하는 것과
LLM의 실제 중간 생각을 가져오는 것이다.
여기서 LLM Langchain으로 중간 생각을 실시간 스트리밍해서 sse로 표현 가능하다고 하면,
하나 궁금한 게 단순히 보여주는 게 아니라, 중간에 사용자의 선택이 들어가야 한다면 보내놓고 대기를 해야한다.
그러면 서버가 계속 응답을 대기하는 상황이 되게 되는데 -> 자원을 계속 점유하거나, 응답 시간 초과 코드를 심어 놓고 응답 시간 초과를 걸어버려야 한다. (이 상황이 웃긴 상황이라고 생각한다) 이거를 해결하려면?
애초에 설계를 LangGraph로 바꿔야 한다. (아 ㅆ)
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
그냥 재밌네