(
query: string,
items: T[],
options: {
model: string
topN?: number
workspaceId?: string | null
/** User-supplied Cohere key from the Knowledge block field. Honored only on self-hosted. */
apiKey?: string
}
)
| 96 | * Returns the items in descending order of relevance, capped at `topN`. |
| 97 | */ |
| 98 | export async function rerank<T extends RerankItem>( |
| 99 | query: string, |
| 100 | items: T[], |
| 101 | options: { |
| 102 | model: string |
| 103 | topN?: number |
| 104 | workspaceId?: string | null |
| 105 | /** User-supplied Cohere key from the Knowledge block field. Honored only on self-hosted. */ |
| 106 | apiKey?: string |
| 107 | } |
| 108 | ): Promise<RerankResponse<T>> { |
| 109 | if (items.length === 0) return { results: [], isBYOK: false } |
| 110 | |
| 111 | if (!isSupportedRerankerModel(options.model)) { |
| 112 | throw new Error(`Unsupported reranker model: ${options.model}`) |
| 113 | } |
| 114 | |
| 115 | const { apiKey, isBYOK } = await resolveCohereKey(options.workspaceId, options.apiKey) |
| 116 | const cappedItems = |
| 117 | items.length > MAX_DOCUMENTS_PER_RERANK ? items.slice(0, MAX_DOCUMENTS_PER_RERANK) : items |
| 118 | if (items.length > MAX_DOCUMENTS_PER_RERANK) { |
| 119 | logger.warn(`Rerank input capped from ${items.length} to ${MAX_DOCUMENTS_PER_RERANK} documents`) |
| 120 | } |
| 121 | const documents = cappedItems.map((it) => it.text) |
| 122 | |
| 123 | const response = await retryWithExponentialBackoff( |
| 124 | async () => { |
| 125 | const controller = new AbortController() |
| 126 | const timeout = setTimeout(() => controller.abort(), RERANK_REQUEST_TIMEOUT_MS) |
| 127 | |
| 128 | const res = await fetch('https://api.cohere.com/v2/rerank', { |
| 129 | method: 'POST', |
| 130 | headers: { |
| 131 | Authorization: `Bearer ${apiKey}`, |
| 132 | 'Content-Type': 'application/json', |
| 133 | }, |
| 134 | body: JSON.stringify({ |
| 135 | model: options.model, |
| 136 | query, |
| 137 | documents, |
| 138 | top_n: options.topN ?? cappedItems.length, |
| 139 | }), |
| 140 | signal: controller.signal, |
| 141 | }).finally(() => clearTimeout(timeout)) |
| 142 | |
| 143 | if (!res.ok) { |
| 144 | const errorText = await res.text() |
| 145 | throw new RerankAPIError( |
| 146 | `Cohere rerank failed: ${res.status} ${res.statusText} - ${errorText}`, |
| 147 | res.status |
| 148 | ) |
| 149 | } |
| 150 | |
| 151 | return (await res.json()) as CohereRerankResponse |
| 152 | }, |
| 153 | { |
| 154 | maxRetries: 3, |
| 155 | initialDelayMs: 500, |
no test coverage detected