23 lines
1.3 KiB
JavaScript
23 lines
1.3 KiB
JavaScript
'use strict';
|
|
|
|
// LLM rerank:对 RAG 候选做二次排序(旧 bridge rag/reranker.js 的移植)。
|
|
function createReranker(llm) {
|
|
async function rerank(query, candidates, topK = 3) {
|
|
if (!candidates || candidates.length <= topK) return candidates || [];
|
|
const docs = candidates.map((c, i) => `[${i}] (category: ${c.category || ''}) Q: ${c.question}\nA: ${String(c.answer || '').slice(0, 200)}`).join('\n\n');
|
|
const prompt = `Rank these knowledge base entries by relevance to the query. Output ONLY the indices of the ${topK} most relevant entries, in order, comma-separated. Example: 3,0,7\n\nQuery: "${query}"\n\nEntries:\n${docs}`;
|
|
try {
|
|
const res = await llm.chat({ messages: [{ role: 'user', content: prompt }], temperature: 0, maxTokens: 50 });
|
|
const indices = String(res.content || '').trim().split(',').map((s) => parseInt(s.trim(), 10)).filter((i) => Number.isInteger(i) && i >= 0 && i < candidates.length);
|
|
if (!indices.length) return candidates.slice(0, topK);
|
|
return indices.slice(0, topK).map((i) => candidates[i]);
|
|
} catch (err) {
|
|
console.error(JSON.stringify({ ts: new Date().toISOString(), warn: `rerank failed: ${err.message}` }));
|
|
return candidates.slice(0, topK);
|
|
}
|
|
}
|
|
return { rerank };
|
|
}
|
|
|
|
module.exports = { createReranker };
|