시스템 설계 GenAI: 생산 애플리케이션을 위한 기반 및 아키텍처
LLM을 응용 프로그램에 통합하려고 하며 RAG, 미세 조정 또는 일반 작업을 수행할지 궁금합니다. 프롬프트를 개선하시겠습니까? 당신은 혼자가 아닙니다. 2024년까지의 분석에 따르면 GenAI 배포의 73%가 기업이 실패하다 6개월 이내(주로 단계에서 잘못된 아키텍처 선택으로 인해) 디자인 이니셜. 문제는 모델이 아닙니다. 많은 팀이 기술을 먼저 선택한다는 것입니다. 문제를 이해합니다.
이 가이드는 프로덕션 환경에서 GenAI 시스템을 설계하기 위한 실용적인 의사결정 프레임워크를 제공합니다. 기본 아키텍처(RAG, 미세 조정, 신속한 엔지니어링) 및 접근 방식 선택 기준 특정 사용 사례에 적합합니다.
무엇을 배울 것인가
- 세 가지 기본 아키텍처: RAG, 미세 조정 및 신속한 엔지니어링
- 의사결정 프레임워크: 각 접근 방식을 언제 사용할지
- 생산 중인 GenAI 애플리케이션을 위한 시스템 아키텍처
- 기술 스택 2026: LangChain, LlamaIndex, vLLM
- 피해야 할 일반적인 패턴과 안티패턴
- RAG 시스템 평가를 위한 품질 지표
73% 문제: GenAI 배포가 실패하는 이유
건축에 들어가기 전에 왜 그렇게 많은 프로젝트가 실패하는지 이해하는 것이 중요합니다. 원인 엔터프라이즈 배포 사후 분석에서 확인된 주요 항목은 다음과 같습니다.
- 관리되지 않는 환각: 모델은 그럴듯하지만 잘못된 답변을 생성하며, 없음 검증 시스템이 구현되었습니다
- 허용할 수 없는 지연 시간:p99 사용자가 기대하는 쿼리에서 3~5초 초과 빨리
- 폭발적인 비용: 실행 전 쿼리당 비용 계산은 없습니다. 몇 주 안에 예산이 소진됩니다
- 관리되지 않는 지식 차단: 모델이 최근 데이터나 비공개 데이터를 알지 못합니다. 회사의
- 추적성 부족: 문서가 어떤 문서를 기반으로 하는지 알 수 없음 대응(규제된 상황에서 중요)
우리가 살펴볼 각 아키텍처는 이러한 문제 중 일부를 다른 아키텍처보다 더 잘 해결합니다. 아는 것 절충을 통해 처음부터 강력한 시스템을 설계할 수 있습니다.
세 가지 기본 아키텍처
1. 신속한 엔지니어링
모든 GenAI 시스템의 출발점: 모델을 다음 방향으로 안내하는 프롬프트를 구성합니다. 원하는 출력. 2026년의 주요 기술:
- 퓨샷 프롬프트: 프롬프트에 입출력 예시 제공
- CoT(사고 사슬): 모델에게 단계별로 먼저 생각하도록 요청합니다. 대답하다
- 시스템 프롬프트: 모델의 동작과 컨텍스트를 정의합니다.
- 구조화된 출력: 안정적인 구문 분석을 위해 강제로 JSON 또는 XML 형식으로 출력합니다.
# Esempio: prompt engineering con structured output
import json
from openai import OpenAI
client = OpenAI()
def analyze_ticket(ticket_text: str) -> dict:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": """Sei un sistema di triage per ticket di supporto.
Analizza il ticket e restituisci JSON con:
- priority: "high" | "medium" | "low"
- category: "bug" | "feature" | "question"
- sentiment: "frustrated" | "neutral" | "positive"
- estimated_resolution_hours: numero intero"""
},
{
"role": "user",
"content": f"Ticket: {ticket_text}"
}
],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
# Uso
result = analyze_ticket("Il mio account e bloccato da ieri, non riesco ad accedere!")
# {"priority": "high", "category": "bug", "sentiment": "frustrated", ...}
언제 사용하는가: 간단하고 잘 정의된 사례, 신속한 프로토타이핑, 여유가 없을 때 개인 데이터를 통합해야 하며 기본 모델은 이미 도메인을 알고 있습니다.
제한: 최근 또는 독점 데이터, 사실에 대한 환각에는 작동하지 않습니다. 구체적인 비용은 컨텍스트의 길이에 비례합니다.
2. RAG — 검색-증강 생성
RAG는 지식 단절과 개인 데이터 문제를 해결합니다. 모델에 대한 지식을 바탕으로 데이터베이스에서 관련 문서를 검색하여 컨텍스트에 배치합니다. 세대 이전.
RAG 시스템의 기본 아키텍처는 4단계로 구성됩니다.
- 인덱싱: 문서를 청크로 분할하고 임베딩 벡터로 변환합니다. 벡터 데이터베이스에 저장되었습니다.
- 검색: 사용자의 쿼리를 동일한 임베딩 공간으로 변환합니다. 가장 유사한 청크가 복구됩니다.
- 증가: 검색된 청크는 프롬프트에 컨텍스트로 삽입됩니다.
- 세대: LLM은 제공된 컨텍스트를 기반으로 응답을 생성합니다.
# RAG minimo funzionante con LangChain e Qdrant
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_qdrant import QdrantVectorStore
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 1. Carica e chunka i documenti
loader = PyPDFLoader("manuale_prodotto.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=64
)
chunks = splitter.split_documents(docs)
# 2. Crea il vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = QdrantVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
url="http://localhost:6333",
collection_name="manuale_prodotto"
)
# 3. Crea la chain RAG
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
# 4. Query
result = rag_chain.invoke({"query": "Come configuro le notifiche email?"})
print(result["result"])
# La risposta cita i documenti recuperati, non inventa
언제 사용하는가: 회사 지식 기반, 기술 문서, FAQ 등 응답은 구체적이고 추적 가능한 문서를 기반으로 해야 하는 경우입니다.
제한: 검색 품질에 따라 달라지는 품질, 추가 대기 시간, 인프라 오버헤드.
3. 미세 조정
미세 조정은 데이터에 대한 추가 교육을 통해 모델의 동작을 조정합니다. 도메인 특정. 2026년의 지배적인 패러다임은 매개변수 효율적인 미세 조정 (PEFT) 소비자 하드웨어에 대한 교육을 가능하게 하는 LoRA 및 QLoRA와 같은 기술을 사용합니다.
# Fine-tuning con LoRA usando transformers e PEFT
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType
import torch
model_name = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto"
)
# Configurazione LoRA: adatta solo il 0.1% dei parametri
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16, # rank della matrice di adattamento
lora_alpha=32, # scaling factor
lora_dropout=0.1,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"]
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 6,815,744 || all params: 8,037,191,680
# trainable%: 0.0848%
언제 사용하는가: 수천 개의 학습 예제가 있는 경우 다음 형식이 필요합니다. 매우 구체적이고 일관된 출력을 원하거나 예제를 제거하여 프롬프트의 길이를 줄이려는 경우 소수.
중요한 안티패턴: 사실적 지식을 주입하기 위해 세밀하게 조정하지 마세요. (날짜, 숫자, 특정 사실). 모델은 이해와 환각 없이 "기억"합니다. 어쨌든. 지식을 얻으려면 RAG를 사용하십시오.
의사결정 프레임워크
가장 중요한 질문은 "어떤 기술을 사용할 것인가"가 아니라 "나의 진짜 문제는 무엇인가"이다. 이 의사결정 트리는 사용 사례의 90%를 다룹니다.
Hai dati privati o recenti che il modello non conosce?
SI --> Considera RAG come base
NO --> Prompt engineering puo essere sufficiente
Il tuo knowledge base e aggiornato frequentemente?
SI --> RAG (indicizza i nuovi documenti, non ri-addestra)
NO --> Fine-tuning puo essere considerato
Hai 1000+ esempi di coppie input-output di alta qualita?
SI --> Fine-tuning e un'opzione valida
NO --> Stai nei limiti di RAG + few-shot
Hai bisogno di tracciabilita (citare le fonti)?
SI --> RAG obbligatorio
NO --> Piu flessibilita
Latenza critica (sotto 500ms)?
SI --> Fine-tuning (elimina retrieval overhead) o caching aggressivo
NO --> RAG funziona bene
Conclusione tipica 2026:
Start with RAG + prompt engineering
Add fine-tuning solo se RAG non raggiunge qualita richiesta
생산을 위한 시스템 아키텍처
프로덕션급 GenAI 시스템은 단순한 "LLM + 벡터 데이터베이스" 그 이상입니다. 구성 요소 심각한 배포에 필요한:
# Stack minimo per RAG in produzione (Docker Compose)
services:
api:
image: your-genai-api:latest
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY}
QDRANT_URL: http://qdrant:6333
REDIS_URL: redis://redis:6379
depends_on:
- qdrant
- redis
qdrant:
image: qdrant/qdrant:v1.9.0
volumes:
- qdrant_storage:/qdrant/storage
ports:
- "6333:6333"
redis:
image: redis:7-alpine
# Semantic cache: evita LLM calls per query simili
volumes:
- redis_data:/data
prometheus:
image: prom/prometheus:latest
# Monitora: latency p50/p95/p99, costo per query, quality score
grafana:
image: grafana/grafana:latest
# Dashboard: LLM performance, retrieval quality, cost tracking
프로토타입을 생산 시스템에서 분리하는 중요한 구성요소:
- 의미론적 캐싱 (Redis + GPTCache 같은 라이브러리): 비용을 30~60% 절감합니다. 유사하게 반복되는 쿼리가 있는 애플리케이션의 경우
- 관찰 가능성: 각 LLM 호출을 대기 시간, 사용된 토큰, 비용 및 품질 점수 — 이 데이터가 없으면 최적화할 수 없습니다
- 대체 전략: OpenAI가 다운되면 어떻게 되나요? 국내 모델이 있어요 백업하는 방법?
- 비율 제한 및 할당량 관리: 쿼리로부터 예산을 보호하세요 변칙적인
- PII 감지: LLM으로 데이터를 보내기 전 개인 데이터를 탐지하고 모호하게 합니다. 민감한
2026년의 기술 스택
GenAI 생태계는 몇몇 지배적인 플레이어를 중심으로 안정화되었습니다.
권장 스택 2026
- 관현악법: 복잡한 RAG 파이프라인을 위한 LangChain v0.3+ 또는 LlamaIndex v0.10+; 에이전트 워크플로우를 위한 LangGraph
- 벡터 데이터베이스: Qdrant(자체 호스팅, 우수한 성능), pgVector(이미 PostgreSQL, 1M 벡터 미만), Pinecone(관리형, 보장된 대기 시간)
- 추론: 자체 호스팅 오픈 소스 모델을 위한 vLLM 또는 TensorRT-LLM OpenAI/인류 클라우드 API용
- 임베딩: OpenAI의 text-embedding-3-small(1536 희미, $0.02/1M 토큰) 또는 무료 셀프 호스팅을 위한 all-MiniLM-L6-v2
- 관찰 가능성: 추적을 위한 LangSmith, Weights & Biases Weave 또는 Phoenix 체인의
- 평가: 자동화된 RAG 지표(충실성, 답변 관련성, 맥락 기억)
RAG 시스템의 품질 측정 기준
RAG 시스템이 제대로 작동하는지 어떻게 알 수 있나요? RAGAS 프레임워크는 측정 가능한 측정항목을 정의합니다.
# Valutazione automatica con RAGAS
from ragas import evaluate
from ragas.metrics import (
faithfulness, # la risposta e supportata dai documenti recuperati?
answer_relevancy, # la risposta risponde alla domanda?
context_recall, # i documenti recuperati contengono le info necessarie?
context_precision # i documenti recuperati sono tutti rilevanti?
)
from datasets import Dataset
# Dataset di test (ground truth necessario)
test_data = {
"question": ["Come configuro l'autenticazione 2FA?"],
"answer": ["Per configurare 2FA, vai in Impostazioni > Sicurezza..."],
"contexts": [["Documentazione 2FA: ...", "Guida sicurezza: ..."]],
"ground_truth": ["La 2FA si configura tramite l'app mobile nelle impostazioni sicurezza"]
}
dataset = Dataset.from_dict(test_data)
result = evaluate(dataset, metrics=[
faithfulness,
answer_relevancy,
context_recall,
context_precision
])
print(result)
# faithfulness: 0.95 (la risposta non inventa)
# answer_relevancy: 0.88 (la risposta e pertinente)
# context_recall: 0.82 (i doc recuperati coprono la risposta)
# context_precision: 0.91 (i doc recuperati sono rilevanti)
생산 시스템의 현실적인 목표: 충실도 > 0.85(중요: 이 이하 역치 환각이 빈번함), Answer_relevancy > 0.80, context_recall > 0.75.
피해야 할 안티패턴
- 모든 문서의 고정 청크 크기: 구조화된 문서(FAQ, API 문서) 서술형 텍스트 이외의 청크가 필요함
- 의미 검색만: 정확한 기술 용어로는 실패합니다. 하이브리드 검색 사용 (BM25 + 의미)
- 재순위 없음: top-k 벡터가 반드시 가장 유용한 것은 아닙니다. 에 크로스 인코더로 정밀도가 15~20% 향상됩니다.
- 지속적인 평가가 없는 RAG: 문서를 인쇄하면 품질이 저하됩니다. 그들은 변한다; 생산의 충실도를 모니터링합니다.
- 첫 번째 선택으로 미세 조정: 그리고 비싸고 느리다; RAG는 거의 항상 존재합니다. 오른쪽으로 움직여 시작하세요
결론 및 다음 단계
GenAI 애플리케이션을 위한 시스템 설계에는 훨씬 더 뛰어난 아키텍처 선택이 필요합니다. 모델 선택. 2026년 경험 법칙: 항상 RAG + 프롬프트로 시작 공학, RAGAS로 품질을 측정하고 차이가 있는 경우에만 미세 조정을 추가합니다. 검색 최적화 후에도 품질이 유지됩니다.
이 시리즈의 다음 기사에서는 각 구성 요소를 자세히 살펴보겠습니다. 오른쪽 벡터 데이터베이스, 청킹 전략, 하이브리드 검색 및 에이전트 아키텍처 랭그래프.







