iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
生成式 AI

練習AI系列 第 25

查詢重寫(Query Rewriting,多路召回 + 去重)

  • 分享至 

  • xImage
  •  

🆕 程式碼

  1. src/day24_qrewrite.js
    // src/day24_qrewrite.js
    import { openai } from "./aiClient.js";
    import { answerWithRAG } from "./day16_rag_store.js";

/**

  • 查詢重寫:給定原始問題,產生 3–5 個等價或相關問法
    */
    export async function rewriteQueries(originalQ) {
    const res = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    temperature: 0.3,
    messages: [
    { role: "system", content: "你是查詢重寫器,請將問題改寫成多個等價問法,維持原意。" },
    { role: "user", content: 問題:${originalQ}\n請輸出一個 JSON 陣列,例如 ["問法1","問法2",...],不要多餘說明。 }
    ]
    });
    try {
    return JSON.parse(res.choices[0].message.content);
    } catch {
    return [originalQ];
    }
    }

/**

  • Query Rewrite 檢索:多路召回 + 去重
    */
    export async function retrieveWithQRewrite({ tenant, ns, query, topK = 6 }) {
    const queries = await rewriteQueries(query);
    const seen = new Map();
    const results = [];

for (const q of queries) {
const { sources } = await answerWithRAG({ tenant, ns, query: q, topK });
for (const s of sources) {
if (!seen.has(s.id)) {
seen.set(s.id, s);
results.push(s);
}
}
}

// 按 score 排序,取前 topK
results.sort((a, b) => (b.score || 0) - (a.score || 0));
return results.slice(0, topK);
}

  1. app/api/kb/[tenant]/[ns]/ask/route.js(新增策略)

只貼新增的分支,保留 Day 19 / 23 的 default & section 分支:

import { retrieveWithQRewrite } from "../../../../../src/day24_qrewrite.js";

...

if (strategy === "qrewrite") {
const chunks = await retrieveWithQRewrite({ tenant, ns, query: q, topK: 6 });
const ctxText = chunks.map((h,i)=># 片段${i+1}(${h.docId}|${h.id.split("#")[1]})\n${h.text}).join("\n\n");

const res = await openai.chat.completions.create({
  model:"gpt-4o-mini", temperature:0.2,
  messages:[
    { role:"system", content:"你是嚴謹的客服知識庫助理,僅依據提供片段回答;不足請說明。" },
    { role:"user", content:`問題:${q}\n\n片段:\n${ctxText}\n\n請用繁體中文回答。` }
  ]
});
const answer = res.choices?.[0]?.message?.content?.trim() || "沒有找到足夠資訊。";

return NextResponse.json({ ok:true, strategy:"qrewrite", answer, sources: chunks });

}

  1. app/studio/page.tsx(新增策略選項)
    <select className="select select-bordered select-sm" value={strategy} onChange={e=>setStrategy(e.target.value as any)}>

上一篇
章節錨點 + 章節優先檢索(Section-first Retrieval)
下一篇
Hybrid Retrieval(向量 + 關鍵字 BM25)
系列文
練習AI29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言