시스템을 흐르는 핵심 객체들의 구조와 관계. Document → Chunk → Embedding → VectorIndex, Query → Prompt → Response.
💡 핵심 개념: LLM 앱의 객체 모델은 일반 웹 앱과 거의 같음. 차이는 Embedding(float 배열)이라는 비정형 객체와 VectorIndex(검색 인터페이스) 정도. 나머지는 평범한 도메인 모델.
classDiagram
class Document {
+String id
+String title
+String source
+DateTime createdAt
+Metadata metadata
}
class Chunk {
+String id
+String docId
+String text
+Int position
+Int tokenCount
}
class Embedding {
+String chunkId
+String model
+Float[] vector
+Int dimensions
}
class VectorIndex {
+String id
+String name
+Int dimensions
+DistanceMetric metric
+upsert(Embedding)
+query(Float[]) Chunk[]
}
class Query {
+String text
+Float[] embedding
+Int topK
}
class RetrievedChunk {
+String chunkId
+Float score
+String text
}
class Prompt {
+String systemMsg
+String userMsg
+Chunk[] context
}
class Response {
+String answer
+RetrievedChunk[] sources
+DateTime generatedAt
}
Document "1" --> "*" Chunk : splits into
Chunk "1" --> "1" Embedding : has
Embedding "*" --> "1" VectorIndex : stored in
Query --> VectorIndex : searches
VectorIndex --> RetrievedChunk : returns
RetrievedChunk --> Prompt : context for
Prompt --> Response : input to
Response --> Query : answers
🔧 필드별 의미
- Document.id — UUID 또는 hash. 멱등성 보장 키.
- Chunk.position — 문서 내 순서. 인접 청크 추가 시 사용.
- Embedding.dimensions — 384 / 768 / 1024 / 1536 / 3072. 모델 의존적.
- VectorIndex.metric — cosine / dot / euclidean. 임베딩 정규화 여부 결정.
- RetrievedChunk.score — 거리 점수. 낮을수록 유사(cosine distance).
- Prompt.context — 시스템 메시지에 들어갈 chunk 배열. 토큰 한도 주의.
📋 Pydantic 구현 예시:
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Literal
class Document(BaseModel):
id: str
title: str
source: str # 'notion://page/123' or 's3://bucket/key'
created_at: datetime
metadata: dict = Field(default_factory=dict)
class Chunk(BaseModel):
id: str
doc_id: str
text: str
position: int
token_count: int
class Embedding(BaseModel):
chunk_id: str
model: str # 'text-embedding-3-small'
vector: list[float]
dimensions: int
⚠️ 흔한 함정:
- Float[] 그대로 DB 저장 — 메모리 폭발. pickle/jsonb로 압축 저장 권장
- dimensions 안 저장 — 나중에 모델 바꿨는데 옛날 벡터 섞이면 검색 망가짐
- Chunk.id 안 unique — 같은 doc에서 같은 chunk 두 번 생성되면 벡터 중복.
hash(doc_id + position + text)
🛠️ 구현: Python Pydantic, TypeScript Zod, Go struct + validator. LangChain은 자체 Document 클래스 제공하지만 커스텀 권장.