Rerank API
질의와 후보 문서들을 받아 관련도 순으로 다시 정렬합니다. 모델은 질의와 문서를 함께 읽고 점수를 내는 cross-encoder(KURE-Reranker-nano)라, 임베딩 유사도보다 정답과 비슷한 함정 문서를 더 잘 구분합니다. 보통 1차 검색(KURE-v3, KURE-Sparse, BM25 등)으로 찾은 상위 수십 개를 다시 정렬하는 데 씁니다.
인증과 한도는 Embeddings API와 같습니다.
재정렬하기
POST https://kure.kullm.ai/api/v1/rerank요청 본문
| 파라미터 | 타입 | 구분 | 설명 |
|---|---|---|---|
model | string | 필수 | kure-reranker-nano 또는 스냅샷 kure-reranker-nano-20261016 (모델 ID와 버전) |
query | string | 필수 | 검색 질의. 빈 문자열은 안 됩니다. |
documents | string[] | 필수 | 정렬할 문서. 최대 100개이며 빈 문자열은 안 됩니다. |
top_n | integer | 선택 | 상위 N개만 돌려줍니다. 기본값은 문서 전체입니다. |
return_documents | boolean | 선택 | 결과에 문서 원문을 넣습니다. 기본값 false. |
질의와 문서 한 쌍은 합쳐서 최대 8,192 토큰입니다. 넘으면 에러 없이 긴 쪽부터 잘라서 채점합니다.
응답
{
"id": "rerank-59b5073b…",
"model": "kure-reranker-nano-20261016",
"results": [
{ "index": 1, "relevance_score": 0.9996, "document": { "text": "고려대학교는 서울특별시 성북구 안암로 145에 있다." } },
{ "index": 2, "relevance_score": 0.0073, "document": { "text": "연세대학교는 서울특별시 서대문구 연세로 50에 있다." } }
],
"usage": { "total_tokens": 73 }
}results는relevance_score가 높은 순입니다.index는documents에서의 위치입니다.relevance_score는 0~1 사이의 관련 확률입니다(모델 점수의 sigmoid). 질의가 달라도 같은 기준이라, 예를 들어 0.5 미만을 버리는 식으로 임계값을 둘 수 있습니다.document는return_documents가true일 때만 들어갑니다.usage.total_tokens는 질의·문서 쌍마다 센 토큰의 합입니다. 질의는 문서 수만큼 반복해서 셉니다(질의 20토큰, 문서 100개면 질의 몫만 2,000토큰). 이 값이 rate limit에서 차감됩니다.
예시
# pip install requests
import os
import requests
res = requests.post(
"https://kure.kullm.ai/api/v1/rerank",
headers={"Authorization": f"Bearer {os.environ['KURE_API_KEY']}"},
json={
"model": "kure-reranker-nano",
"query": "고려대학교는 어디에 있나요?",
"documents": [
"김치찌개는 김치와 돼지고기를 넣어 끓인다.",
"고려대학교는 서울특별시 성북구 안암로 145에 있다.",
"연세대학교는 서울특별시 서대문구 연세로 50에 있다.",
],
"top_n": 2,
"return_documents": True,
},
)
res.raise_for_status()
for r in res.json()["results"]:
print(f"{r['relevance_score']:.4f} {r['document']['text']}")검색 파이프라인에 넣기
1차 검색으로 넓게 찾고(상위 20~100개), 리랭커로 다시 정렬해 상위 몇 개만 씁니다. 1차 검색은 KURE-v3 임베딩, KURE-Sparse, 또는 둘을 합친 하이브리드 검색이면 됩니다.
import os
import numpy as np
import requests
from openai import OpenAI
API = "https://kure.kullm.ai/api/v1"
KEY = os.environ["KURE_API_KEY"]
client = OpenAI(base_url=API, api_key=KEY)
def embed(texts, input_type):
vecs = []
for i in range(0, len(texts), 8): # 한 요청에 최대 8개
res = client.embeddings.create(
model="kure-v3", input=texts[i : i + 8], dimensions=1024, extra_body={"input_type": input_type}
)
vecs += [d.embedding for d in res.data]
return np.array(vecs)
docs = [...] # 검색 대상 문서
doc_vecs = embed(docs, "document") # 미리 계산해 벡터 DB에 저장해 두는 부분
def search(query, k=50, n=5):
scores = doc_vecs @ embed([query], "query")[0]
candidates = [docs[i] for i in np.argsort(-scores)[:k]] # 1차 검색 상위 k개
res = requests.post(
f"{API}/rerank",
headers={"Authorization": f"Bearer {KEY}"},
json={"model": "kure-reranker-nano", "query": query, "documents": candidates, "top_n": n},
)
res.raise_for_status()
return [(r["relevance_score"], candidates[r["index"]]) for r in res.json()["results"]]- 후보가 많을수록 정답을 놓칠 가능성은 줄지만 토큰과 시간이 늘어납니다. 20~50개로 시작해 조정하세요.
- 후보가 100개를 넘으면 여러 요청으로 나눠 보낸 뒤
relevance_score로 합쳐 정렬하면 됩니다. 점수는 요청이 달라도 같은 기준입니다. - 결과를 플레이그라운드에서 KURE-v3 유사도와 나란히 비교해 볼 수 있습니다.
