feat: pluggable embedding backends (OpenAI-compatible / local-gguf + resilient fallback)#9
Closed
epruseal wants to merge 1 commit into
Closed
feat: pluggable embedding backends (OpenAI-compatible / local-gguf + resilient fallback)#9epruseal wants to merge 1 commit into
epruseal wants to merge 1 commit into
Conversation
…resilient fallback) 기존 ChromaDB 기본 EF(all-MiniLM-L6-v2, 384d)는 영어 특화라 한국어 검색 품질이 낮다(실측 top-1 0/5, MRR 0.285). EMBEDDING_BACKEND 환경변수로 임베딩 함수를 교체할 수 있게 하여 KURE-v1(1024d) 등 OpenAI 호환 서버 모델로 품질을 개선한다 (실측 top-1 5/5, MRR 1.000). - EMBEDDING_BACKEND=local(기본): 기존 ChromaDB EF 그대로 → 100% 하위호환. - EMBEDDING_BACKEND=openai: OpenAI 호환 /v1/embeddings 서버(LM Studio·vLLM· Ollama·실제 OpenAI) + 로컬 GGUF 폴백. - OpenAIEmbeddingFunction: httpx 직접 호출, OPENAI_API_KEY 설정 시 Bearer 인증. - LlamaCppEmbeddingFunction: 로컬 GGUF 폴백(lazy load, 자동 다운로드). - ResilientEmbeddingFunction: primary 장애 시 폴백 자동 전환(health TTL). 환경변수: EMBEDDING_BACKEND, OPENAI_API_BASE, OPENAI_EMBED_MODEL, OPENAI_API_KEY, OPENAI_TIMEOUT, EMBED_DIM, EMBED_COLLECTION, LOCAL_GGUF_PATH.
Owner
Author
|
검토 완료 — upstream(AlexAI-MCP#7)으로 제출. 머지 없이 닫음. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: pluggable embedding backends (OpenAI-compatible / local-gguf + resilient fallback)
배경 / 문제
ChromaDB 기본 임베딩 함수(all-MiniLM-L6-v2, ONNX, 384d)는 영어 특화라 한국어 검색
품질이 낮다. 동일 코퍼스에서 실측 결과:
변경 요약
EMBEDDING_BACKEND환경변수로 임베딩 함수를 교체할 수 있게 한다. 기본값은local이라기존 동작 100% 보존(아무 설정도 안 하면 지금과 똑같이 minilm 사용).
EMBEDDING_BACKEND=local(기본): ChromaDB 기본 EF. 기존 컬렉션opencrab_vectors그대로.EMBEDDING_BACKEND=openai: OpenAI 호환/v1/embeddingsAPI를 쓰는 범용 경로. 임베딩모델은 자유롭게 선택 — 실제 OpenAI 클라우드 모델(
text-embedding-3-small/-large등)도,로컬·자체호스팅 서버(LM Studio·Ollama·vLLM·HF TEI)에 올린 모델도 모두 가능하다. 모델은
OPENAI_EMBED_MODEL, 차원은EMBED_DIM, 컬렉션은EMBED_COLLECTION으로 지정한다.추천한다. 번들된 로컬 GGUF 폴백도 KURE-v1이라, KURE primary면 추가 설정 없이 폴백까지
바로 동작한다.
EMBED_DIM을 해당 모델 차원에 맞추고(예:-3-small=1536),로컬 GGUF 폴백은 차원이 달라 부적합하므로
LOCAL_GGUF_PATH로 동일 차원 GGUF를 지정하거나폴백에 의존하지 않는다(원격만 사용). → 자세한 제약은 아래 "임베딩 모델 혼용 금지" 참고.
신규 컴포넌트
stores/openai_embedding.pyOpenAIEmbeddingFunction— httpx로/v1/embeddings직접 호출.OPENAI_API_KEY설정 시Authorization: Bearer, 미설정 시 무인증(LM Studio 등). L2 재정규화.stores/llamacpp_embedding.pyLlamaCppEmbeddingFunction— 로컬 GGUF 폴백. lazy load, 미존재 시 HuggingFace 자동 다운로드(KURE-v1-Q4_K_M).stores/resilient_embedding.pyResilientEmbeddingFunction— primary 장애 시 fallback 자동 전환. health TTL 캐시로 불필요한 타임아웃 재시도 방지.기존 파일 변경
config.py: 임베딩 관련 Settings 필드 추가(아래 환경변수). 기존 필드/동작 불변.stores/chroma_store.py:embedding_function: Any = None파라미터 추가.None이면 기존기본 EF 사용 → 하위호환. 주입 시 해당 EF로 add/query.
stores/factory.py:make_vector_store()에embedding_backend=="openai"분기만 추가.make_graph_store/make_doc_store/make_sql_store는 변경 없음.호환성 / 롤백
local이라 설정 안 하면 기존과 동일. 새 의존성도 openai 경로에서만 로드(lazy import).EMBEDDING_BACKEND미설정 또는local로 되돌리면 즉시 롤백, 기존 컬렉션 보존.name()="kure_v1"고정 → 컬렉션 메타데이터 일관 → 재시작/폴백 전환 시 동일 컬렉션 재사용.하나의 Chroma 컬렉션은 하나의 임베딩 모델·차원으로만 채워야 한다. 색인(add)과
질의(query)는 반드시 같은 모델로 수행되어야 하며, 서로 다른 모델의 벡터를 한 컬렉션에
섞으면 검색이 무의미해진다(차원 불일치 또는 의미공간 불일치). 한 컬렉션 = 한 모델이
원칙이다. (
openai는 모델이 아니라 *백엔드(전송 방식)*임에 유의 — 실제 OpenAI 모델, KURE,KoSimCSE 등 어떤 모델이든 이 백엔드로 쓸 수 있고, 그중 무엇을 골랐든 컬렉션 안에서 섞지 말 것.)
local(minilm 384d)과openai백엔드의 컬렉션은 분리되어 있어(
opencrab_vectors↔EMBED_COLLECTION, 기본opencrab_vectors_kure) 자동으로 충돌하지 않는다.EMBED_COLLECTION을 쓰고 전량 재색인해야 한다. 기존 컬렉션에 다른 모델로 덧쓰면 안 된다.같은 KURE-v1임을 전제로
name()="kure_v1"하나로 컬렉션을 공유한다. 서로 다른 모델을primary/fallback으로 두면 안 된다.
환경변수
EMBEDDING_BACKENDlocallocal또는openaiOPENAI_API_BASEhttp://localhost:1234/v1OPENAI_EMBED_MODELtext-embedding-kure-v1text-embedding-3-small, KURE 서빙 모델명 등)OPENAI_API_KEYOPENAI_TIMEOUT8.0EMBED_DIM1024text-embedding-3-small=1536)EMBED_COLLECTIONopencrab_vectors_kureLOCAL_GGUF_PATH~/.cache/opencrab/models에 자동 다운로드테스트 / 검증
py_compile6파일 통과.OpenAIEmbeddingFunction.name()=="kure_v1", Bearer 헤더 분기,_l2_normalize,빈입력 패스스루, ResilientEF 체인 생성 모두 정상(네트워크 없이).
_DEFAULT_GGUF_DIR가~/.cache/opencrab/models로 해석되고XDG_CACHE_HOME존중 확인.ontology_query3건 정상(감리 제1조 1.0235 / FP 대가산정 0.9963 / CBD 표준산출물 1.0054).
비고
LM Studio언급은호환 서버의 예시로만 남김.
mykor/KURE-v1-gguf(Q4_K_M, ~438MB)는 한국어 임베딩용 공개 모델. 다른 모델은LOCAL_GGUF_PATH로 지정 가능.CPU 자원이 부족하면 한국어 경량 임베딩
BM-K/KoSimCSE-roberta(RoBERTa-base, 약 110M, 768d)를 추천한다. KURE보다 가볍고 빠르지만 한국어 전용이며 검색
품질은 다소 낮을 수 있다.
Text-Embeddings-Inference)에 KoSimCSE를 서빙하고
OPENAI_EMBED_MODEL,EMBED_DIM=768, 별도EMBED_COLLECTION만 지정하면 된다(전량 재색인 필요).(GGUF가 없으면
EMBEDDING_BACKEND=openai의 primary만 사용).