Qdrant에서 Superlinked 사용하기

Qdrant에서 Superlinked 사용하기 (superlinked)

Superlinked는 셀프 호스팅 추론 엔진(SIE, Self-hosted Inference Engine) 이에요. 85개 이상의 임베딩 모델(dense, sparse, multivector / ColBERT)을 단일 엔드포인트로 제공해요. sie-qdrant 패키지를 쓰면 SIE를 Qdrant 컬렉션의 임베딩 프로바이더로 사용할 수 있고, SIE가 텍스트를 벡터로 인코딩하면 그 벡터를 Qdrant에 저장하고 검색하게 돼요.

출처: Qdrant 공식 문서 — superlinked

sie-qdrant는 현재 Python 전용이에요. TypeScript 지원은 아직 없어요.

설치

pip install sie-qdrant

이 설치로 sie-sdkqdrant-client (v1.7 이상)가 의존성으로 함께 설치돼요. 그리고 실행 중인 SIE 인스턴스도 필요해요. 배포 옵션(Docker, GPU)은 Superlinked 퀵스타트를 참고해요.

Vectorizer

SIEVectorizer는 SIE를 호출해서 dense 벡터를 list[float]로 돌려줘요. 그대로 Qdrant의 PointStruct(vector=...)query_points()에 넘길 수 있어요.

from sie_qdrant import SIEVectorizer

vectorizer = SIEVectorizer(
    base_url="http://localhost:8080",
    model="NovaSearch/stella_en_400M_v5",
)

SIE가 dense 임베딩으로 지원하는 모델이라면 아무 모델이나 model 파라미터만 바꿔서 쓸 수 있어요.

# Nomic MoE (768-dim, multilingual)
vectorizer = SIEVectorizer(model="nomic-ai/nomic-embed-text-v2-moe")

# E5 (1024-dim, instruction-tuned - SIE handles query vs document encoding automatically)
vectorizer = SIEVectorizer(model="intfloat/e5-large-v2")

# BGE-M3 (1024-dim, also supports sparse output for hybrid search)
vectorizer = SIEVectorizer(model="BAAI/bge-m3")

지원하는 모든 모델은 Model Catalog에서 확인할 수 있어요.

전체 예제

Qdrant 컬렉션을 만들고, SIE로 문서를 임베딩하고, 검색하는 흐름을 볼게요.

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
from sie_qdrant import SIEVectorizer

vectorizer = SIEVectorizer(
    base_url="http://localhost:8080",
    model="NovaSearch/stella_en_400M_v5",
)

client = QdrantClient("http://localhost:6333")

client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(size=1024, distance=Distance.COSINE),
)

texts = [
    "Machine learning is a subset of artificial intelligence.",
    "Neural networks are inspired by biological neurons.",
    "Deep learning uses multiple layers of neural networks.",
    "Python is popular for machine learning development.",
]

vectors = vectorizer.embed_documents(texts)

client.upsert(
    collection_name="documents",
    points=[
        PointStruct(id=i, vector=v, payload={"text": t})
        for i, (t, v) in enumerate(zip(texts, vectors))
    ],
)

query_vec = vectorizer.embed_query("What is deep learning?")

results = client.query_points(
    collection_name="documents",
    query=query_vec,
    limit=2,
)

for point in results.points:
    print(point.payload["text"])

중요한 지점이 하나 있어요. 문서는 embed_documents(...)로, 검색 쿼리는 embed_query(...)로 따로 만든다는 점이에요. SIE는 이 둘을 구분해서 인코딩해 줘요.

named vectors (dense + sparse)

하이브리드 검색을 위해서는 SIENamedVectorizer를 쓰면 한 번의 SIE 호출로 여러 벡터 타입을 만들 수 있어요. 이때 모델이 요청한 모든 출력 타입을 지원해야 해요. BAAI/bge-m3는 dense와 sparse를 모두 지원하고, jinaai/jina-... 계열은 다른 조합을 지원해요.

더 알아보기 (Learn more)