Qdrant에서 Superlinked 사용하기
Qdrant에서 Superlinked 사용하기 (superlinked)
Superlinked는 셀프 호스팅 추론 엔진(SIE, Self-hosted Inference Engine) 이에요. 85개 이상의 임베딩 모델(dense, sparse, multivector / ColBERT)을 단일 엔드포인트로 제공해요. sie-qdrant 패키지를 쓰면 SIE를 Qdrant 컬렉션의 임베딩 프로바이더로 사용할 수 있고, SIE가 텍스트를 벡터로 인코딩하면 그 벡터를 Qdrant에 저장하고 검색하게 돼요.
sie-qdrant는 현재 Python 전용이에요. TypeScript 지원은 아직 없어요.
설치
pip install sie-qdrant
이 설치로 sie-sdk와 qdrant-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-... 계열은 다른 조합을 지원해요.