미국/유럽 지역 Ask-Your-Docs 아키텍처: OpenAI, Cohere, Voyage 및 선택적 재순위화 (Selective
요약
효율적인 Ask-Your-Docs 시스템 구축을 위해 임베딩을 통한 광범위한 검색과 선택적 재순위화(Reranking) 아키텍처를 제안합니다. 데이터 무결성 유지, 쿼리 작업 제한, 소스 문서의 영구 보존을 핵심 설계 원칙으로 강조합니다.
핵심 포인트
- 임베딩으로 검색(Recall)을 수행하고 상위 후보군에 대해서만 재순위화 실시
- 벡터 데이터와 소스 문서 간의 식별자 및 버전 연결을 통한 데이터 무결성 확보
- 벡터 인덱스는 파생된 상태일 뿐이므로 원본 문서를 시스템의 기록(System of Record)으로 유지
- 지역 적격성, 데이터 보존 및 삭제 정책을 모델 비용보다 우선적으로 고려
짧은 답변: 미국/유럽(US/EU)의 Ask-Your-Docs 시스템을 구축하려면, 광범위한 검색(Recall)을 위해 임베딩(Embeddings)을 사용하고, 제한된 후보군(Candidate set)에 대해서만 재순위화(Reranking)를 수행하십시오. 그리고 OpenAI, Cohere, Voyage 중 무엇을 선택할지는 귀하의 자체 코퍼스(Corpus)에서 성공적인 쿼리당 전체 비용을 측정한 후에 결정하십시오.
이것이 아키텍처 결정 사항입니다. 낮은 임베딩 비율은 빈번한 재색인(Re-indexing)으로 상쇄될 수 있는 반면, 인상적인 재순위화 모델(Reranker)이라도 모든 문서를 처리하게 되면 비용이 많이 드는 습관이 될 수 있습니다. 따라서 결정적인 제약 조건은 가격표가 아니라, 문서 작성부터 수락된 답변에 이르기까지 시스템이 수행하는 작업량입니다.
각 단계를 교체 가능하게 유지하십시오.
결정 기록: 벤더 선택 전 불변 사항 (Invariants)
첫 번째 불변 사항은 출처(Provenance)입니다. 저장된 모든 벡터는 소스 문서의 식별자, 청크(Chunk) 식별자, 임베딩 모델 ID, 그리고 이를 생성한 색인 버전(Indexing version)과 연결된 상태를 유지해야 합니다. 이러한 연관 관계가 없다면, 부분적인 마이그레이션 과정에서 벡터 공간(Vector spaces)이 뒤섞일 수 있으며, 색인은 그럴듯해 보이는 결과를 계속 반환할 수 있습니다. 저는 이를 데이터 무결성(Data-integrity) 실패로 간주합니다. 시스템이 파생된 상태를 설명하거나 재구축하는 데 필요한 정보를 잃어버렸기 때문입니다.
두 번째 불변 사항은 제한된 쿼리 작업(Bounded query work)입니다. 임베딩 검색(Embedding retrieval)은 검색(Recall)을 제공하며, 선택적 재순위화(Optional reranking)는 상위 결과만을 대상으로 합니다. 후보 제한(Candidate limit)은 보편적인 상수가 아니라 평가된 작업 부하 파라미터(Workload parameter)입니다. 짧은 제품 지원 질문과 광범위한 정책 질문은 서로 다른 제한치를 정당화할 수 있지만, 두 제한치 모두 관찰 가능해야 하며 상한선(Capped)이 있어야 합니다. 만약 재순위화가 건너뛰어진다면, 애플리케이션은 두 경로가 동일하다고 조용히 설명하는 대신, 현재 임베딩 순서대로 결과를 제공하고 있다는 사실을 인지하고 있어야 합니다.
셋째, 소스 문서(source documents)는 영구적인 기록 시스템(system of record)으로 남아야 합니다. 벡터 인덱스(vector index)는 파생된 상태(derived state)입니다. 이를 재구성하는 데 비용이 많이 들 수 있지만, 삭제, 수정 워크플로우(correction workflows), 그리고 모델 마이그레이션(model migration)은 인덱스가 유일하게 살아남은 복사본이라는 사실에 절대 의존해서는 안 됩니다. 미국/유럽(US/EU) SaaS 배포의 경우, 모델 비용을 논의하기 전에 지역 적격성(region eligibility), 보존(retention), 그리고 삭제 동작(deletion behavior)이 선행 확인 사항입니다. 비용 측면에서 매력적인 요청 경로라 할지라도, 워크로드의 데이터 경계(data boundary)를 위반한다면 여전히 유효하지 않습니다.
실패 경계(failure boundaries)는 명확합니다: 혼합 모델 인덱스(mixed-model indexes), 오래된 삭제 정보(stale deletions), 중복 수집(duplicate ingestion), 통제되지 않은 재임베딩(uncontrolled re-embedding), 무제한적인 재순위화 팬아웃(unbounded rerank fan-out), 그리고 HTTP 429 에러 이후의 재시도 증폭(retry amplification)입니다. 이러한 실패들은 관련성 차트(relevance chart)만큼 보기 좋지는 않습니다. 하지만 설계 검토(design review)를 지배하는 요소들입니다.
가상의 야간 문서 동기화(nightly document sync)를 가정해 봅시다. 서식 변경(formatting change)이 발생하여 사람이 읽을 수 있는 내용은 동일하지만 새로운 상위 리비전(upstream revision)이 도착합니다. 수집 경로(ingestion path)가 의미론적 콘텐츠(semantic content)와 표현 방식(presentation)을 구분하지 못하면, 새로운 청크 식별자(chunk identities)를 생성하고 문서 전체를 임베딩 대상으로 예약합니다. 한편, 쿼리 트래픽이 속도 제한(rate limit)에 도달하고, 클라이언트가 Retry-After를 준수하지 않은 채 429 응답을 재시도합니다. 이 시퀀스의 어떤 단계도 잘못된 모델 응답을 요구하지는 않지만, 인덱싱 작업은 늘어나고, 중복된 파생 레코드(duplicate derived records)가 축적되며, 쿼리 재시도는 겉으로 보이는 검색 비용을 부풀립니다. 제어 장치는 각각의 경계에 위치해야 합니다. 쓰기 경로(write path)에는 콘텐츠 해시(content hashes)와 멱등적 수집(idempotent ingestion)을, 저장소에는 버전 관리된 벡터 네임스페이스(versioned vector namespaces)를, 재순위화(reranking) 전에는 제한된 후보군(bounded candidates)을, 그리고 클라이언트에는 제한된 지수 백오프(capped exponential backoff)를 적용해야 합니다. 이러한 작업을 계산하지 않는 속도 비교는 아키텍처가 아닌 송장 금액(invoice label)만을 측정하는 것입니다.
미국/유럽 팀은 Ask-Your-Docs 재순위화(reranking)를 위해 OpenAI, Cohere, Voyage를 어떻게 비교해야 하는가?
고정된 대표 코퍼스(corpus)와 판정된 쿼리 세트(query set)로 시작하십시오. 간결한 질문, 어휘 불일치(vocabulary mismatches), 거의 중복된 구절(near-duplicate passages), 그리고 작은 수식어 하나로 정답 출처가 바뀌는 질문들을 포함해야 합니다. 모든 후보군에 대해 동일한 문서와 쿼리를 실행하고, 선택된 모델의 정확한 식별자(identifier)를 고정하며, 카탈로그 날짜를 기록하십시오. 공개 벤치마크(benchmark)가 프라이빗 지식 베이스(private knowledge base)를 위한 이 선택을 확정 지어줄 수 있을지는 확신할 수 없습니다. 부족한 증거는 시스템이 실제로 서비스하게 될 문서와 질문에 대한 성능입니다.
재순위화(reranking) 전의 재현율(recall), 재순위화 후의 순위 품질(ranking quality), 2단계로 전달된 후보군(candidates), 처리된 총 입력량, 꼬리 지연 시간(tail latency), 그리고 재시도(retries)를 측정하십시오. 그다음 인덱싱 경제성(indexing economics)과 쿼리 경제성(query economics)을 분리하십시오. 인덱싱에는 초기 청크(chunks)와 문서 변동(document churn) 또는 모델 변경으로 인해 발생하는 재임베딩(re-embedding)이 포함됩니다. 쿼리 작업에는 쿼리 임베딩(query embeddings)과 선택된 후보군에 대한 재순위화 작업만 포함됩니다. 마이그레이션 당일의 인덱싱 비용을 해당 날짜의 쿼리 수로 나누면 극단적인 수치가 나오며, 이는 잘못된 의사결정으로 이어집니다.
청킹(chunking) 방식과 반복되는 상용구(boilerplate)에 따라 결과는 크게 달라질 수 있습니다.
아래의 비교는 보편적인 순위라기보다는 의도적으로 의사결정 테이블(decision table) 형태로 작성되었습니다. 제공된 증거는 품질 측면의 승자나 현재 단위 가격 측면의 승자를 확정 짓지 않으므로, 그러한 주장은 아키텍처로 포장된 마케팅에 불과할 것입니다.
| 옵션 | 선호하는 경우 | 수집해야 할 증거 | 다른 경로를 선택해야 하는 이유 |
|---|---|---|---|
| OpenAI 직접 연결 (OpenAI direct) | 기존 애플리케이션이 이미 해당 API를 사용 중이며, 평가된 모델이 코퍼스(corpus) 품질 임계값을 통과하는 경우 | 정확한 모델 ID, 현재 비용 기준, 미국/유럽(US/EU) 적격성, 유지 조건, 재현율(recall), 그리고 엔드-투-엔드(end-to-end) 쿼리 작업량 | 다른 후보 모델이 동일한 품질 및 거버넌스 제약 조건을 충족하면서 전체 작업량이 더 적은 경우 |
| ... |
Infrai의 관련 이점은 약속된 벤치마크 결과가 아니라 가독성(legibility)에 있습니다. 임베딩(embeddings)과 선택적 재순위화(optional reranking)는 단순한 HTTP 기능 뒤에 위치하며, 이를 발견하기 위한 자료에는 호출 방법이 설명되어 있습니다. 또한 동일한 런타임(runtime)에서 추후 다른 벤더 통합 없이도 채팅 답변을 지원할 수 있습니다. 이는 SDK 전용 애플리케이션 코드를 원하지 않는 팀들에게 신뢰할 수 있는 어댑터 경계(adapter boundary)가 됩니다. 다만, 이것이 모델을 평가하거나, 식별자(identifiers)를 고정하거나, 미국/유럽(US/EU) 제약 조건을 검증해야 할 필요성을 없애주는 것은 아닙니다.
제공업체 네이티브 제어, 조달 관계 또는 계약이 불변의 조건(invariant)인 경우에는 OpenAI, Cohere, Voyage, Gemini 또는 Together를 직접 통합하는 것이 더 깔끔한 선택으로 남습니다. 그러한 요구사항을 일반적인 인터페이스 아래에 묻어버리지 마십시오.
코퍼스를 인덱싱하기 전에 핵심 경로를 모델링하십시오
100만 토큰당 비용은 유용한 입력값이지만, 답변당 비용은 아닙니다. 2단계 시스템에는 최소 세 가지의 별도 항목이 있습니다: 코퍼스 임베딩(corpus embedding), 쿼리 임베딩(query embedding), 그리고 선택적 재순위화(optional reranking)입니다. 코퍼스 임베딩은 계획 기간(planning horizon) 동안 분할 상환(amortized)됩니다. 재순위화는 이를 호출하는 쿼리 및 해당 쿼리에 전송되는 입력값에 따라 규모가 결정됩니다. 재시도(retries) 비용은 각주가 아닌 관찰된 총계에 포함되어야 합니다.
이 Python 프로그램은 특정 벤더의 속도 제한(rate)을 포함하거나 문서화되지 않은 API 페이로드(payload)를 가정하지 않고 이러한 항목들을 명시적으로 보여줍니다. 동일한 평가 실행에서 얻은 현재 견적 요율과 작업량 측정값을 전달하십시오. 이 프로그램은 비교를 위해 두 가지 총계, 즉 계획된 인덱싱 지출과 선택된 기간 동안의 시맨틱 검색(semantic-search) 지출을 출력합니다.
import argparse
from decimal import Decimal
...
입력값은 막연한 평균치가 아니라 트레이스(traces)로부터 도출되어야 합니다. 임베딩 (embeddings)을 트리거하는 서식 전용 문서 업데이트를 카운트하세요. 후보군 선택 후의 재순위화 (rerank) 입력값을 카운트하세요. 재시도 트래픽을 카운트하세요. 그런 다음 모든 옵션에 대해 동일한 품질 임계값 (quality threshold)으로 모델을 다시 실행하세요. 관련성이 무너질 때까지 후보군을 줄이는 것은 최적화가 아닙니다.
스토리지 아키텍트 (storage architect)라면 마이그레이션이 어떻게 동작하는지도 물어야 합니다. 임베딩 모델을 변경하는 것은 일반적으로 컷오버 (cutover) 전까지 기존 인덱스를 읽을 수 있는 상태로 유지하면서, 새로운 버전 아래에서 파생된 벡터들을 재구축해야 함을 의미합니다. 애플리케이션은 단순히 두 벡터의 차원 (dimension)이 같다는 이유만으로 오래된 네임스페이스 (namespace)에 새로운 벡터를 써서는 안 됩니다. 차원의 동일성은 의미론적 호환성 (semantic compatibility)에 대해 아무것도 말해주지 않습니다.
거부된 설계와 그것이 승리하는 좁은 사례
저는 성장하는 SaaS 지식 베이스를 위해 저장된 모든 청크 (chunk)를 재순위화 (reranking)하는 방식을 거부합니다. 이는 쿼리 시점의 더 무거운 프로세싱을 코퍼스 (corpus) 크기에 결합시키고, 검색 (retrieval) 단계의 경계 함수 (bounding function)를 제거하며, 벤더 비교를 불필요하게 거대한 워크로드 간의 경쟁으로 변질시킵니다. 문서의 양이 쿼리 관련성과 무관하게 증가하는 경우에는 적합하지 않습니다. 임베딩을 통해 광범위하게 검색하고, 후보군 세트를 제한하며, 판단된 품질 향상이 정당화되는 경우에만 재순위화를 활성화하십시오.
타당한 예외는 있습니다. 트래픽이 낮고 안정적인 아주 작은 코퍼스이면서, 모든 적격 항목을 정렬해야 한다는 엄격한 요구 사항이 있는 경우에는 전체 후보군 세트로 간주하여 추론하는 것이 더 쉬울 수 있습니다. 최대 세트가 입증 가능하게 제한되어 있고, 측정된 지연 시간 (latency), 거버넌스 (governance), 그리고 처리 비용이 모두 적절할 때는 해당 접근 방식을 유지하십시오. 문제는 코퍼스가 변하더라도 이 조건이 계속 유지되어야 한다는 점입니다.
공유 런타임 (shared-runtime) 선택 방식에도 한계는 있습니다. 제공업체별 특화 기능 (provider-specific features)이 핵심적이거나 직접적인 벤더 계약 (vendor agreement)이 필수적인 경우에는 적합하지 않습니다. 또한 전용 모더레이션 엔드포인트 (moderation endpoint)가 없다는 단점도 있습니다. 텍스트나 이미지 검토가 필요한 애플리케이션은 JSON 스키마 (JSON schema)를 사용하는 채팅 모델 (chat model)을 통해 해당 제어 로직을 설계해야 하는데, 이는 보안 경계 (security boundary) 측면에서 잘못된 선택일 수 있습니다. 그러한 경우에는 직접적인 제공업체를 선택하거나 요구 사항을 충족하는 전문 모더레이션 서비스 (specialized moderation service)를 선택하십시오.
벤더 라벨이 없다고 해서 취약한 회계 (accounting) 문제가 해결되는 것은 아닙니다. 방어 가능한 결정은 소스 데이터의 내구성을 유지하고 두 가지 검색 단계 (retrieval stages)를 교체 가능하게 유지하면서, 측정된 전체 경로 작업 (complete-path work)이 가장 적고 동일한 관련성 (relevance) 및 거버넌스 (governance) 하한선을 충족하는 옵션을 선택하는 것입니다.
참고 문헌 (References)
- OpenAI, "Function calling": https://platform.openai.com/docs/guides/function-calling
- ElevenLabs documentation: https://elevenlabs.io/docs
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기