LLM 애플리케이션 아키텍처란? (Korean)

Jonas Kim
9 min readJul 23, 2023

비즈니스 도메인 기반으로 대형 언어 모델 (LLM) 애플리케이션을 개발하고자 할 때 (예를 들어, 금융사 고객 응대 챗봇) 문제가 되는 점은 LLM의 정보 부족과 이로 인한 제한된 답변 능력입니다. 예를 들어, GPT 3.5는 2021년 9월 이후의 데이터가 없으므로 최신 뉴스에 대한 답변을 제공할 수 없습니다.

이 문제를 해결하기 위한 방안으로 LLM을 새로운 데이터로 파인튜닝하는 것이 있습니다. 그러나 이는 상당한 비용이 소요됩니다. 현재 기준으로 FLAN-T5-XXL (11B) 모델을 CNN 데일리 메일 데이터셋 1개에 대해 파인튜닝하면 약 77만 원이 들게 됩니다.

또 다른 대안으로는 우리가 원하는 정보가 담긴 문서를 직접 프롬프트 콘텍스트에 넣어주고 원하는 응답을 얻는 것입니다. 연구에 따르면 프롬프트의 가치는 데이터 샘플 약 100개에 준하는 정도라고 합니다.

하지만 모든 정보를 콘텍스트에 일일이 넣어주는 것은 현실적으로 불가능합니다. GPT-4가 처리 가능한 입력은 최대 50페이지 정도로 제한됩니다. 이러한 상황에서는 우리가 가진 정보를 데이터베이스에 저장해두고, 사용자의 질의가 들어올 때 (예를 들어, 챗봇을 통해 은행 계좌를 개설하는 방법을 물었을 때) 관련된 정보를 검색하여 해당 정보가 담긴 문서들을 프롬프트를 통해 LLM에 전달하는 방식이 더 효율적입니다. 이러한 서비스 아키텍처를 ‘검색 증강 생성’(Retrieval Augmented Generation, RAG)라고 합니다.

우리는 정보를 얻기 위해 LLM을 활용하는데, LLM에게 정보를 입력하는 방식이 다소 이상해 보일 수 있습니다. 그러나 정보의 입수와 정보의 처리(해석)는 완전히 다른 기능입니다. 제2차 세계 대전 때 영국 정보부는 독일군의 암호를 얻어와 앨런 튜링에게 전달했습니다. 그러면 튜링의 콜로서스 머신이 이 암호를 해석해 주었습니다. 이런 모습을 머릿속에 그려보면 이해가 빠를 것입니다. 이렇게 분업이 가능한 이유는 배우지 않은 정보를 일반화하여 해석하는 LLM의 능력이 매우 우수해진 결과입니다. (이를 제로샷 학습 또는 인-콘텍스트 학습이라고도 합니다.) 다시 말해, 어느 정도 일반화 성능이 있는 언어 모델이 아니라면 이러한 아키텍처를 사용하기 어려울 것입니다.

이전부터 언어 모델 성능을 향상시키기 위해 검색을 활용하는 시도가 많았으며, 대표적으로 RETROREARM이 있습니다. 하지만 현재는 RAG 아키텍처가 산업계에서 주목받고 있습니다. 이는 비약적으로 향상된 인-콘텍스트 학습 능력과 모델 학습이 따로 필요하지 않은 편리함 때문입니다.

RAG 아키텍처의 주된 작업흐름을 살펴보겠습니다. 첫 번째 작업 흐름은, 우리가 가진 정보를 검색하기 위해 DB에 정보를 저장하는 일입니다. 관계형 데이터베이스(RDB)에 정형화된 정보를 저장하고, LLM에게 SQL 문을 작성하여 검색하도록 하는 방법도 가능합니다. 그러나 우리가 가진 정보는 자연어로 작성된 문서 파일인 경우(예: PDF) 가 더 흔합니다.

자연어를 DB에 저장하려면, 일반적으로 숫자 형태로 변환해야 합니다. 특정 단어나 문장들이 존재하는지 여부를 나타내는 이진값 벡터로 변환할 수 있지만, 보다 현대적인 기술은 의미가 유사한 문장들이 유사한 벡터 값을 갖도록 변환하는 것입니다. 이렇게 함으로써 더 응축된 길이의 벡터 형태로 정보를 표현할 수 있게 됩니다.

‘의미가 유사하다’라는 표현이 나왔는데, 이는 ‘정보의 해석’ 과정이 필요함을 뜻합니다. 이를 위해서도 언어 모델의 개입이 필요합니다. (반드시 LLM이 아니어도 됩니다.) 수집한 문서들을 작은 조각들로 분할하고(청킹), 언어 모델의 해석을 통해 벡터 형태(임베딩)로 변환한 후, 이를 벡터 DB에 저장합니다. 이 과정은 검색 엔진의 오랜 기술이지만, 최근에 다시 각광받고 있습니다.

문서를 정제하는 데이터 전처리 작업(ETL)은 주로 Databricks, Apache Airflow와 같은 기존 도구를 사용하며, LangChain 또는 LlamaIndex의 문서 로더 기능을 추가로 활용할 수도 있습니다.

임베딩 작업은 전처리에 포함되며, OpenAI의 API(text-embedding-ada-002), Cohere, 허깅페이스의 BERT, Sentence Transformer, GPT-J 등을 사용할 수 있습니다. 임베딩은 LLM 앱의 성능에 직접적인 영향을 미치므로, 매우 신중하게 선택해야 합니다. 또한, 우수한 임베딩이더라도 우리가 원하는 언어를 지원하지 않는다면 사용할 수 없습니다.

데이터베이스는 RDB가 아닌 벡터 DB를 사용해야 합니다. 클레이폿 AI 창립자인 칩 후옌이 ‘그래프 DB의 해가 2021년이라면, 벡터 DB의 해는 2023년’이라고 말한 것처럼 이 분야에 대한 관심이 높습니다. Pinecone은 안정적인 클라우드 호스팅 기반으로 서비스되며, Weaviate, Vespa, Qdrant는 단일 노드 기반의 오픈소스 DB입니다. Chroma, Faiss는 로컬 벡터 관리 라이브러리로, 엄밀히 DB는 아니지만 (샤딩 및 복제를 통한 성능 보장, 내결함성 향상, 모니터링, 접근 제어, 백업과 컬렉션 등 DB의 주된 기능을 제공하지 않기 때문에) 임베딩 검색 용도로 가볍게 사용할 수 있습니다. pgvector와 같이 PostgreSQL OLTP 확장판도 드물지만 사용되는 예시가 있습니다.

작업 흐름으로 돌아가, 두 번째 흐름은 LLM 앱에 질의가 들어오면 (예를 들어, “은행 계좌를 개설하려면 어떻게 해야 하나요?”) 이 문장을 임베딩 벡터로 만들고, 벡터 DB에서 수치적으로 거리가 가장 가까운 문서들을 검색하여 가져옵니다.

그러나 계산학적으로 ‘가장 가까운’ 문서 벡터를 찾는 것은 벡터의 크기 (차원)이 커질수록 어려워집니다. 따라서 ‘근사적으로 가까운’ (Approximate Nearest Neighbor, ANN) 벡터를 빠르게 찾는 방법이 주로 사용됩니다. 빠른 검색을 위해 벡터는 미리 인덱싱되며, 이를 위해 무작위 투영, PQ (Product Quantization), LSH (Locality Sensitive Hashing), HNSW (Hierarchical Navigable Small World) 등의 기법들이 적용됩니다. 이러한 기법들의 유무와 구현은 벡터 DB마다 다르며, 이는 LLM 앱의 성능에 영향을 미치므로 주의가 필요합니다. 또한, 벡터 인덱싱 대신에 트리나 지식 그래프 구조 또는 이들의 조합을 활용한 인덱싱을 고려하기도 합니다.

또한 질의문이 너무 간결하다면 관련성 있는 문서를 찾아오기 어려울 수 있고 이를 보완하기 위한 연구들이 있습니다. 예컨대, 가상의 문서를 임베딩하여 질의를 보강한다거나 콘텍스트 문서 생성에 클러스터링 알고리즘을 적용한 ‘생성 후 읽기’ (GenRead) 기법 등이 있습니다.

세 번째 작업흐름으로 진행될 내용을 설명하겠습니다. 질의와 관련 있는 문서(예를 들어, 비대면 은행 계좌 개설 안내 문서)를 가져왔다면, 이를 프롬프트 콘텍스트에 입력하고 LLM에게 답변을 요청해야 합니다. 이를 위해서는 질의에 대한 임베딩 처리, 검색 요청, 검색 결과를 활용한 프롬프트 엔지니어링 작업이 필요합니다. 이러한 작업을 특정 주체가 중앙에서 제어해주는데, 이를 오케스트레이션 프레임워크라고 합니다.

오케스트레이션 프레임워크 중 대표적인 것이 Langchain이며, LlamaIndex (최초 명칭은 GPT Index)도 주목받고 있습니다. Langchain은 장황한 인터페이스와 느린 구현으로 인해 파이썬으로 직접 개발하는 경우도 있습니다. 그러나 Langchain은 아직 0.0.239 버전으로 개발이 진행 중이므로 기다려봐야 할 필요가 있습니다. 재밌게도 ChatGPT에 플러그인을 사용하여 오케스트레이션을 시험해볼 수도 있습니다.

LLM의 챔피언은 당연히 OpenAI의 gpt-4, gpt-4–32k이며, 50배 저렴하고 빠른 gpt-3.5-turbo를 사용해볼 수도 있습니다. 또한, Anthropic의 Claude는 GPT-3.5 수준의 정확도와 신속한 추론 속도를 가지고 있으며, 특히 Claude 2는 100k 길이의 콘텍스트 창을 지원한다고 합니다. 일부 단순한 요청은 오픈소스 모델로 분기하여 대응하면서 비용을 낮출 수도 있습니다. 이런 경우를 대비하여 Databricks, AnyScale, Mosaic, Modal, RunPod 플랫폼은 모델 파인튜닝 도구를, Hugging FaceReplicate는 API 인터페이스를 제공하고 있습니다.

시중에는 다양한 상업용 오픈소스 LLM 모델이 존재하며(Together, Mosaic, Falcon, Mistral 등) 이들이 GPT-3.5의 정확도 수준에 다다른다면 산업계에서는 오픈소스 사용도 고려할 가능성이 보입니다. 최근 Meta에서 Llama2를 릴리즈하면서 LLM 씬에도 개성있고 우수한 모델이 쏟아져 나오는 스테이블 디퓨전 모먼트가 발생하지 않을까 그 귀추가 주목되고 있습니다.

주된 작업흐름에 대한 이야기는 끝났습니다. 요약하자면, 어떤 임베딩, 벡터 DB, 그리고 LLM을 사용할지가 애플리케이션의 성능을 좌우하는 핵심 요소입니다. MLOps와 비슷하게 RAG 주위로는 수많은 LLMOps 도구들의 생태계가 형성되고 있습니다. LLM 응답 캐싱을 위해 Redis, GPTCache가, LLM 출력 모니터링, 추적, 평가를 위해 W&B, MLflow, PromptLayer, Helicone이, 출력의 유해성 검증을 위해 Guardrails가, 그리고 프롬프트 주입 공격 방어를 위해 Rebuff가 제공되고 있습니다.

전체적인 RAG 아키텍처 호스팅은 주로 클라우드 공급자 서비스 내에서 이루어지겠지만, 흥미로운 두 가지 시도가 있습니다. Streamship은 LLM 앱을 엔드-투-엔드로 호스팅하면서 다양한 기능을 제공하려고 하고, 독자적인 LLM 모델을 갖추고 있는 AnyScale, Mosaic은 모델과 파이썬 코드를 한 곳에서 호스팅 가능하도록 지원하고 있습니다.

--

--