임베딩 모델을 사용한 재랭킹

RAG의 재정렬을 위한 파이썬 코드

Page content

Reranking은 검색 증강 생성 (RAG) 시스템에서 두 번째 단계로, 검색과 생성 사이에 위치합니다.

디지털 공간의 전기 큐브

위의 그림은 Flux-1 dev디지털 공간의 전기 큐브를 어떻게 상상하는지를 보여줍니다.

재검색과 재정렬

문서를 처음부터 벡터 DB에 임베딩 형태로 저장한다면, 검색 과정에서 유사한 문서 목록을 바로 얻을 수 있습니다.

독립적인 재정렬

하지만 먼저 인터넷에서 문서를 다운로드한 후, 검색 시스템의 응답은 검색 제공업체의 선호도/알고리즘, 스폰서 콘텐츠, SEO 최적화 등에 영향을 받을 수 있으므로, 검색 후 재정렬이 필요합니다.

저는 다음과 같은 작업을 수행했습니다:

  • 검색 쿼리에 대한 임베딩을 얻습니다.
  • 각 문서에 대한 임베딩을 얻습니다. 문서는 최대 8,000 토큰을 넘지 않기 때문에 예상되지 않았습니다.
  • 쿼리와 각 문서의 임베딩 간의 유사도를 계산합니다.
  • 문서를 이 유사도에 따라 정렬합니다.

벡터 DB는 여기서 사용하지 않겠습니다.

샘플 코드

Langchain을 사용하여 Ollama와 연결하고, Langchain의 cosine_similarity 함수를 사용합니다. 유사도 지표에 따라 필터링할 수 있지만, 다른 도메인과 임베딩 LLMs에 따라 임계값이 달라질 수 있음을 기억하세요.

이 코드가 여러분에게 도움이 되기를 바랍니다. Copy/Paste/UseAnyWayYouWant 라이선스. 감사합니다.

from langchain_core.documents import Document
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.utils.math import cosine_similarity
import numpy as np


def cosine_distance(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    return 1.0 - cosine_similarity(a, b)

def compute_score(vectors: np.ndarray) -> float:
    score = cosine_distance(vectors[0].reshape(1, -1), vectors[1].reshape(1, -1)).item()
    return score

def list_to_array(lst):
    return np.array(lst, dtype=float)   

def compute_scorel(lists) -> float:
    v1 = list_to_array(lists[0])
    v2 = list_to_array(lists[1])
    return compute_score([v1, v2])

def filter_docs(emb_model_name, docs, query, num_docs):
    content_arr = [doc.page_content for doc in docs]

    ollama_emb = OllamaEmbeddings(
        model=emb_model_name
    )

    docs_embs = ollama_emb.embed_documents(content_arr)
    query_embs = ollama_emb.embed_query(query)
    sims = []
    for i, emb in enumerate(docs_embs):
        idx = docs[i].id
        s = compute_scorel([query_embs, docs_embs[i]])
        simstr = str(round(s, 4))
        docs[i].metadata["sim"] = simstr
        sim = {
            "idx": idx,
            "i": i,
            "sim": s,
        }
        sims.append(sim)

    sims.sort(key=sortFn)

    sorted_docs = [docs[x["i"]] for x in sims]
    filtered_docs = sorted_docs[:num_docs]
    return filtered_docs

최고의 임베딩 모델

저의 작업에 있어 현재 최고의 임베딩 모델은 bge-large:335m-en-v1.5-fp16입니다.

두 번째로는 nomic-embed-text:137m-v1.5-fp16jina/jina-embeddings-v2-base-en:latest가 차지했습니다.

하지만 여러분의 도메인과 쿼리에 맞는 테스트를 수행하세요.

유용한 링크