GenAI 스택의 실체 파헤치기

전통적인 소프트웨어 설계는 결정론(determinism)에 의존합니다. 입력을 보내고, 스키마에 따라 이를 검증하며, 예측 가능한 출력을 기대합니다.

생성형 AI는 이를 변화시킵니다. 거대 언어 모델(LLM)은 확률적 엔진입니다. 확률을 기반으로 텍스트를 예측합니다.

LLM을 마법 상자처럼 다룬다면, 여러분의 프로덕션 앱은 실패할 것입니다. 하지만 LLM을 변동성이 있고 비결정론적인(non-deterministic) 서드파티 API로 다룬다면, 신뢰할 수 있는 시스템을 구축할 수 있습니다.

LLM에는 반드시 관리해야 할 특정 제약 사항이 있습니다:

  • 페이로드 크기(Payload Size): 모델에는 컨텍스트 윈도우(context window)라고 불리는 엄격한 제한이 있습니다. 무제한의 데이터를 보낼 수는 없습니다.
  • 지연 시간(Latency): 데이터베이스 읽기는 밀리초(ms) 단위로 이루어지지만, LLM 추론(inference)은 초 단위로 걸립니다. 이를 처리하기 위해서는 비동기 큐(asynchronous queues)나 스트리밍(streaming)이 필요합니다.
  • 환각(Hallucinations): 모델에 특정 데이터가 부족하면, 그럴듯해 보이지만 틀린 답을 만들어냅니다.

비용이 많이 드는 재학습 없이 데이터 문제를 해결하기 위해, 우리는 검색 증강 생성(Retrieval-Augmented Generation, RAG)을 사용합니다.

RAG는 API에 자신만의 데이터베이스를 가져오는 것과 같습니다. 모델이 여러분의 데이터를 알고 있기를 기대하는 대신, 백엔드에서 관련 컨텍스트를 가져와 프롬프트에 주입합니다.

RAG 워크플로우:

  1. 사용자가 프롬프트를 보냅니다.
  2. 시스템이 벡터 데이터베이스(Vector Database)에 쿼리를 보냅니다.
  3. 시스템이 의미적으로 유사한 텍스트 청크(chunks)를 찾습니다.
  4. 시스템이 이 청크들을 프롬프트에 주입합니다.
  5. LLM이 근거 기반의 컨텍스트를 처리합니다.

이를 통해 LLM은 지식 생성기에서 컨텍스트 처리기로 변모합니다. 이는 오류를 크게 줄여줍니다.

LLM 출력을 자동화된 서비스에 유용하게 사용하려면 구조화된 출력(Structured Outputs)이 필요합니다. 마이크로서비스를 위해 대화형 텍스트를 파싱할 때 정규 표현식(regex)을 사용할 수는 없습니다. JSON과 같이 정확한 스키마 정의를 전달해야 합니다. 이를 통해 모델이 코드가 읽을 수 있는 엄격한 레이아웃을 따르도록 보장할 수 있습니다.

프로덕션 수준의 AI를 구축하려면 선형적인 프롬프트에서 벗어나 견고한 시스템 설계로 나아가야 합니다.

출처: https://dev.to/ingit_bhatnagar/de-mystifying-the-genai-stack-from-llms-to-rag-a-systems-perspective-4jp8

선택 사항 학습 커뮤니티: https://t.me/GyaanSetuAi