Jina Embeddings 연동
Jina Embeddings 연동 (jina-embeddings)
Qdrant는 Jina AI의 임베딩과 호환돼요. Jina Embeddings에서 무료 체험 키를 받아 임베딩을 얻을 수 있습니다.
Qdrant 사용자는 코드 QDRANT를 사용하면 Jina AI API에서 10% 할인을 받을 수 있어요.
기술 요약 (Technical Summary)
| 모델 | 차원(Dimension) | 언어(Language) | MRL (matryoshka) | 컨텍스트(Context) |
|---|---|---|---|---|
| jina-embeddings-v4 | 2048 (single-vector), 128 (multi-vector) | 다국어 (30+) | 예 | 32768 + Text/Image |
| jina-clip-v2 | 1024 | 다국어 (100+, 30에 집중) | 예 | Text/Image |
| jina-embeddings-v3 | 1024 | 다국어 (89개 언어) | 예 | 8192 |
| jina-embeddings-v2-base-en | 768 | 영어 | 아니요 | 8192 |
| jina-embeddings-v2-base-de | 768 | 독일어 & 영어 | 아니요 | 8192 |
| jina-embeddings-v2-base-es | 768 | 스페인어 & 영어 | 아니요 | 8192 |
| jina-embeddings-v2-base-zh | 768 | 중국어 & 영어 | 아니요 | 8192 |
Jina는 모든 작업에
jina-embeddings-v4를 사용할 것을 권장해요.
백본(backbone) 위에 jina-embeddings-v4는 서로 다른 임베딩 용도를 위한 5개의 task-specific 어댑터로 학습되었어요. 요청에 task를 포함하면 다운스트림 애플리케이션을 최적화할 수 있습니다.
- retrieval.query: 검색(retrieval) 작업에서 사용자 쿼리나 질문을 인코딩할 때 사용.
- retrieval.passage: 검색 작업에서 indexing 시점에 큰 문서를 인코딩할 때 사용.
- code.query: 코드 관련 검색 작업에서 사용자 쿼리나 질문을 인코딩할 때 사용.
- code.passage: 코드 관련 검색 작업에서 indexing 시점에 큰 문서를 인코딩할 때 사용.
- text-matching: 두 문장 사이의 유사도 측정처럼 텍스트 유사도 매칭을 위해 인코딩할 때 사용.
비슷하게 jina-embeddings-v3도 서로 다른 임베딩 용도를 위한 5개의 task-specific 어댑터로 학습되었어요. 요청에 task를 포함하면 최적화할 수 있습니다.
- retrieval.query: 검색 작업에서 사용자 쿼리나 질문을 인코딩할 때 사용.
- retrieval.passage: 검색 작업에서 indexing 시점에 큰 문서를 인코딩할 때 사용.
- classification: 텍스트 분류 작업을 위해 텍스트를 인코딩할 때 사용.
- text-matching: 두 문장 사이의 유사도 측정처럼 텍스트 유사도 매칭을 위해 인코딩할 때 사용.
- separation: 클러스터링 또는 reranking 작업에 사용.
jina-embeddings-v4, jina-embeddings-v3, jina-clip-v2는 Matryoshka Representation Learning을 지원해요. 이를 통해 최소한의 성능 손실로 임베딩 차원을 제어할 수 있죠. 요청에 dimensions를 포함해 원하는 차원을 선택하면 됩니다. 기본적으로 dimensions는 2048(jina-embeddings-v4) 또는 1024(jina-embeddings-v3, jina-clip-v2)로 설정되고, 256~2048 사이의 값이 권장돼요. 아래 표는 jina-embeddings-v3 모델의 차원별 성능을 참고하기 위한 힌트예요. 다른 모델도 비슷한 결과를 보여줘요.
| 차원 | 32 | 64 | 128 | 256 | 512 | 768 | 1024 |
|---|---|---|---|---|---|---|---|
| 평균 검색 성능 (nDCG@10) | 52.54 | 58.54 | 61.64 | 62.72 | 63.16 | 63.3 | 63.35 |
jina-embeddings-v4와 jina-embeddings-v3는 Late Chunking을 지원해요. 이는 모델의 긴 컨텍스트 능력을 활용해 컨텍스트 기반 청크 임베딩을 생성하는 기법이에요. 요청에 late_chunking=True를 포함하면 컨텍스트 기반 청크 표현을 활성화할 수 있습니다. true로 설정하면 Jina AI API가 input 필드의 모든 문장을 연결해 하나의 문자열로 모델에 입력해요. 내부적으로 모델은 이 길게 연결된 문자열을 임베딩한 뒤 late chunking을 수행해, 입력 리스트의 크기와 일치하는 임베딩 리스트를 반환해요.
예제 (Example)
텍스트-텍스트 검색 (Text-to-Text Retrieval)
아래 코드는 Qdrant와 함께 jina-embeddings-v4를 사용하는 방법을 보여줘요.
import requests
import qdrant_client
from qdrant_client.models import Distance, VectorParams, Batch
# Jina API 키를 제공하고 사용 가능한 모델 중 하나를 선택해요.
JINA_API_KEY = "jina_xxxxxxxxxxx"
MODEL = "jina-embeddings-v4"
DIMENSIONS = 2048 # 또는 원하는 출력 벡터 차원을 선택하세요.
TASK = 'retrieval.passage' # indexing용. 쿼리용이라면 retrieval.query로 설정하세요.
# API에서 임베딩 가져오기
url = "https://api.jina.ai/v1/embeddings"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {JINA_API_KEY}",
}
data = {
"input": ["Your text string goes here", "You can send multiple texts"],
"model": MODEL,
"dimensions": DIMENSIONS,
"task": TASK,
"late_chunking": True,
}
response = requests.post(url, headers=headers, json=data)
embeddings = [d["embedding"] for d in response.json()["data"]]
# 임베딩을 Qdrant에 인덱싱
client = qdrant_client.QdrantClient(":memory:")
client.create_collection(
collection_name="MyCollection",
vectors_config=VectorParams(
size=DIMENSIONS,
distance=Distance.DOT,
),
)
qdrant_client.upsert(
collection_name="MyCollection",
points=Batch(
ids=list(range(len(embeddings))),
vectors=embeddings,
),
)
텍스트-이미지 검색 (Text-to-Image Retrieval)
아래 코드는 Qdrant와 함께 jina-embeddings-v4를 사용해 텍스트-이미지 검색을 하는 방법을 보여줘요.
import requests
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
# Jina API 키를 제공하고 모델을 선택하세요.
JINA_API_KEY = "jina_xxxxxxxxxxx"
MODEL = "jina-embeddings-v4"
DIMENSIONS = 2048 # 원하는 출력 벡터 차원을 설정하세요.
# 입력 정의
text_input = "A blue cat"
image_url = "https://i.pinimg.com/600x315/21/48/7e/21487e8e0970dd366dafaed6ab25d8d8.jpg"
# Jina API에서 임베딩 가져오기
url = "https://api.jina.ai/v1/embeddings"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {JINA_API_KEY}",
}
data = {
"input": [
{"text": text_input},
{"image": image_url},
],
"model": MODEL,
"dimensions": DIMENSIONS,
}
response = requests.post(url, headers=headers, json=data)
response_data = response.json()["data"]
# 모델은 이미지와 텍스트를 구분하지 않으므로, 입력 순서에 따라 출력을 추출해요.
text_embedding = response_data[0]["embedding"]
image_embedding = response_data[1]["embedding"]
# Qdrant 클라이언트 초기화
client = QdrantClient(url="http://localhost:6333/")
# named 벡터로 컬렉션 생성
collection_name = "MyCollection"
client.recreate_collection(
collection_name=collection_name,
vectors_config={
"text_vector": VectorParams(size=DIMENSIONS, distance=Distance.DOT),
"image_vector": VectorParams(size=DIMENSIONS, distance=Distance.DOT),
},
)
client.upsert(
collection_name=collection_name,
points=[
PointStruct(
id=0,
vector={
"text_vector": text_embedding,
"image_vector": image_embedding,
},
)
],
)
# 이제 컬렉션을 쿼리해 볼게요.
search_query = "A purple cat"
# Jina API에서 검색 쿼리 임베딩 가져오기
url = "https://api.jina.ai/v1/embeddings"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {JINA_API_KEY}",
}
data = {
"input": [{"text": search_query}],
"model": MODEL,
"dimensions": DIMENSIONS,
# "task": "retrieval.query" # 텍스트-텍스트 검색 작업이라면 이 줄의 주석을 해제하세요.
}
response = requests.post(url, headers=headers, json=data)
query_embedding = response.json()["data"][0]["embedding"]
search_results = client.query_points(
collection_name=collection_name,
query=query_embedding,
using="image_vector",
limit=5,
).points
for result in search_results:
print(f"ID: {result.id}, Score: {result.score}")