임베딩
wippy/embeddings 모듈은 wippy/llm을 통해 임베딩을 생성하고 애플리케이션 데이터베이스에 저장한 뒤 벡터 유사도 검색을 수행합니다. PostgreSQL의 pgvector와 SQLite의 sqlite-vec를 지원합니다.
이 페이지는 독립 실행형 튜토리얼이 아니라 참조 스니펫을 포함한 API 입문서입니다. 스니펫은 기존 Wippy 프로젝트, 구성된 데이터베이스, 그리고 아래에서 설명하는 임베딩 모델·제공자·자격 증명을 전제로 합니다. 원격 임베딩 호출에는 제공자 요금이 발생할 수 있습니다. 콘텐츠를 인덱싱하고 검색하는 완전한 애플리케이션은 RAG 파이프라인 구축을 따르세요.
설정
프로젝트에 모듈을 추가합니다:
wippy add wippy/embeddings
wippy install
의존성을 선언하고, 의존성의 parameters를 통해 target_db 요구사항을 애플리케이션 데이터베이스에 연결합니다:
version: "1.0"
namespace: app
entries:
- name: app_db
kind: db.sql.sqlite
file: ./data/app.db
- name: dep.embeddings
kind: ns.dependency
component: wippy/embeddings
version: "*"
parameters:
- name: target_db
value: app:app_db
시작 시 wippy/migration이 01_create_embeddings_table 마이그레이션을 수행하여 데이터베이스 드라이버에 적합한 벡터 인덱스를 갖춘 embeddings_512 테이블을 생성합니다.
위와 같은 상대 SQLite 경로를 사용한다면 애플리케이션을 시작하기 전에 data 디렉터리를 만드세요.
현재 고정 상수
모듈은 현재 다음 비공개 상수를 정의합니다. 이 값들은 의존성 매개변수가 아닙니다:
| 상수 | 기본값 | 설명 |
|---|---|---|
EMBEDDING_MODEL |
text-embedding-3-small |
벡터 생성에 사용하는 LLM 모델 |
EMBEDDING_DIMENSIONS |
512 |
모델에 전달하는 벡터 크기 |
MAX_TOKENS_PER_REQUEST |
8000 |
호출별 토큰 예산. 큰 배치는 분할됨 |
DEFAULT_SEARCH_LIMIT |
10 |
search가 반환하는 기본 결과 수 |
토큰 수는 ceil(#text / 4)로 추정합니다. 제한을 넘는 배치는 항목 사이에서 분할됩니다. 단일 항목이 예산보다 크면 분할되지 않으며 해당 하위 배치는 LLM 호출 전에 실패합니다.
임포트
entries:
- name: my_app
kind: library.lua
source: file://my_app.lua
imports:
embeddings: wippy.embeddings:embeddings
local embeddings = require("embeddings")
고수준 API (wippy.embeddings:embeddings)
add
local result, err = embeddings.add(content, content_type, origin_id, context_id, meta)
content의 임베딩을 생성하고 저장합니다.
| 매개변수 | 타입 | 필수 | 설명 |
|---|---|---|---|
content |
string | 예 | 임베딩할 텍스트 |
content_type |
string | 예 | "document_chunk" 또는 "question" 같은 레이블. PostgreSQL에서는 32자로 제한됨 |
origin_id |
string | 예 | 원본 문서나 레코드 식별자. target_db가 PostgreSQL이면 UUID여야 함 |
context_id |
string | 아니요 | 추가 범위 키(섹션, 채팅, 테넌트) |
meta |
table | 아니요 | 임의의 JSON 직렬화 가능 메타데이터 |
{ entry_id, origin_id, content_type, context_id } 또는 nil, err를 반환합니다.
add_batch
다음 예시는 SQLite와 호환되는 애플리케이션 ID를 사용합니다. PostgreSQL 스키마는 origin_id를 UUID로 저장하므로 doc-1을 UUID로 바꾸세요.
local result, err = embeddings.add_batch({
{ content = "...", content_type = "chunk", origin_id = "doc-1" },
{ content = "...", content_type = "chunk", origin_id = "doc-1", context_id = "s1" },
})
여러 항목을 한 번의 호출로 임베딩하고 저장합니다. 전체 추정 토큰 수가 MAX_TOKENS_PER_REQUEST를 넘으면 메서드가 배치를 청크로 나눕니다. 각 리포지토리 청크는 트랜잭션이지만, 분할된 고수준 배치 전체는 원자적이지 않습니다. 뒤쪽 청크가 실패해도 앞쪽 청크는 저장된 채로 남습니다. { count, items = { ... } }를 반환합니다.
테스트 중 생성한 레코드를 제거하려면 각 샘플 origin에 대해 리포지토리 API의 delete_by_origin(origin_id) 메서드를 사용하세요.
search
local hits, err = embeddings.search("how do migrations work?", {
content_type = "document_chunk",
origin_id = "doc-1",
context_id = "section-2",
limit = 10,
})
쿼리 문자열을 임베딩하고 저장된 벡터에서 유사도 검색을 수행합니다. 모든 필터는 선택 사항이며 일치하는 레코드는 유사도순으로 정렬됩니다.
origin_id는 문자열 또는 비어 있지 않은 문자열 배열일 수 있습니다. 각 결과에는 entry_id, origin_id, content_type, context_id, content, 디코딩된 meta, 타임스탬프, similarity가 포함됩니다.
find_by_type
local hits, err = embeddings.find_by_type(
"how do migrations work?",
"document_chunk",
{ limit = 10 }
)
단일 content_type으로 search를 호출합니다. 기본 제한은 10입니다.
find_by_origin
local hits, err = embeddings.find_by_origin("how do migrations work?", "doc-1", {
content_type = "document_chunk",
context_id = "section-2",
limit = 5,
})
단일 origin_id와 선택적인 content_type, context_id 필터로 search를 호출합니다. 기본 제한은 5입니다.
리포지토리 API (wippy.embeddings:embedding_repo)
이미 벡터가 있어 임베딩 생성을 건너뛰려면 리포지토리를 직접 사용합니다. 원시 임베딩에는 정확히 512개의 숫자 값이 있어야 합니다:
| 함수 | 설명 |
|---|---|
embedding_repo.add(content, content_type, origin_id, context_id, meta, embedding) |
사전 계산한 벡터 삽입 |
embedding_repo.add_batch(batch) |
여러 사전 계산 벡터를 하나의 트랜잭션으로 삽입 |
embedding_repo.get_by_origin(origin_id) |
지정한 origin의 모든 레코드 나열 |
embedding_repo.delete_by_origin(origin_id) |
지정한 origin의 모든 레코드 제거 |
embedding_repo.delete_by_entry(entry_id) |
행 ID로 단일 레코드 제거 |
embedding_repo.search_by_embedding(vector, options) |
원시 벡터에 대한 유사도 검색 |
search_by_embedding은 { content_type, origin_id, context_id, limit }을 받습니다.
데이터베이스 지원
마이그레이션은 target_db의 데이터베이스 드라이버에 맞는 스키마를 생성합니다:
- PostgreSQL -
vector(512)컬럼과 IVFFlat 인덱스가 있는embeddings_512테이블.pgvector확장이 필요합니다. - SQLite - KNN 검색을 위해 메타데이터 및 콘텐츠 컬럼과 함께
embedding float[512]벡터 컬럼을 담는embeddings_512vec0가상 테이블.
벡터는 API 레이어에서 항상 일반 JSON 배열을 통해 왕복됩니다.