偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RAG系列:系統(tǒng)評(píng)估 - 基于LLM-as-judge實(shí)現(xiàn)評(píng)估系統(tǒng)

人工智能
我們基于 LLM-as-judge 自己實(shí)現(xiàn)一套 RAG 系統(tǒng)評(píng)估系統(tǒng),用該評(píng)估系統(tǒng)評(píng)估了基礎(chǔ)版 RAG 系統(tǒng)(V1.0)的 5 個(gè)評(píng)估指標(biāo)的表現(xiàn),可以看到基礎(chǔ)版 RAG 系統(tǒng)(V1.0)這 5 個(gè)指標(biāo)的值都是偏低的。

引言

在 系統(tǒng)評(píng)估 - 五個(gè)主流評(píng)估指標(biāo)詳解 中,我們了解了 RAG 系統(tǒng)評(píng)估的 5 個(gè)主流指標(biāo),它們分別是 上下文召回率(Context Recall)、上下文相關(guān)性(Context Relevance)、答案忠實(shí)度(Faithfulness)、答案相關(guān)性(Answer Relevance)以及答案正確性(Answer Correctness),也簡(jiǎn)單了解了一些 RAG 系統(tǒng)的評(píng)估方法以及主流的評(píng)估系統(tǒng)。

今天我們將基于 LLM-as-judge 自己實(shí)現(xiàn)一套 RAG 系統(tǒng)評(píng)估系統(tǒng),然后通過該評(píng)估系統(tǒng)評(píng)估我們?cè)?nbsp;基于 DeepSeek + Chroma + LangChain 開發(fā)一個(gè)簡(jiǎn)單 RAG 系統(tǒng) 中搭建好的基礎(chǔ)版 RAG 系統(tǒng),以基礎(chǔ)版 RAG 系統(tǒng)這 5 個(gè)評(píng)估指標(biāo)值作為基準(zhǔn),通過學(xué)習(xí)不同的優(yōu)化方法來提升這 5 個(gè)指標(biāo)。

因?yàn)槭峭ㄟ^ LLM 來評(píng)估,所以評(píng)估 LLM 的能力越強(qiáng),理論上評(píng)估就會(huì)越準(zhǔn)確,因此在實(shí)際的業(yè)務(wù)場(chǎng)景中,盡可能選用能力更強(qiáng)的 LLM。

為了學(xué)習(xí)方便,本文采用的評(píng)估 LLM 是 Ollama 部署的 qwen2.5 14b。

本文完整代碼地址[1]:https://github.com/laixiangran/ai-learn/blob/main/src/app/rag/03_rag_evaluator/route.ts

下面具體講解下每個(gè)指標(biāo)評(píng)估器的代碼實(shí)現(xiàn):

上下文召回率評(píng)估器實(shí)現(xiàn)

衡量檢索到的上下文是否覆蓋參考答案所需的所有關(guān)鍵信息,避免遺漏關(guān)鍵信息。取值在 0 到 1 之間,數(shù)值越高表示檢索到的上下文覆蓋越全面。計(jì)算公式:上下文召回率 = 上下文覆蓋的關(guān)鍵信息數(shù)量 / 參考答案中關(guān)鍵信息總數(shù)量。例如,參考答案需要 5 個(gè)關(guān)鍵信息,若檢索到的上下文覆蓋其中 4 個(gè)關(guān)鍵信息,則上下文召回率為 0.8。

將參考答案(referenceAnswer)拆分成多個(gè)句子/關(guān)鍵信息(referenceAnswerStatements)。

舉個(gè)例子:

{
  "referenceAnswer": "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣,未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。",
  "referenceAnswerStatements": [
    "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。",
    "未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
  ]
}

代碼實(shí)現(xiàn)如下:

/**
 * 將文本拆分為多個(gè)句子(關(guān)鍵信息)
 * @param text 待拆分的文本
 * @param evaluateLLM 拆分的 LLM
 * @returns
 */
async function statementSplit(text, evaluateLLM) {
  const prompt = `
  你是一個(gè)語言專家,你的任務(wù)是將以下文本拆分為多個(gè)獨(dú)立的句子,每個(gè)句子獨(dú)立表達(dá)一個(gè)完整含義,同時(shí)保留原意的邏輯連貫性。

  說明:
  1. 嚴(yán)格按以下JSON格式返回:["句子1", "句子2", ...],不能輸出其他無關(guān)內(nèi)容。

  文本:
${text}

  回答:

  `;
  const res = await evaluateLLM.invoke(prompt);
  const data = formatToJson(res) || [];
  console.log('statements: ', data);
  return data;
}

逐個(gè)分析每個(gè)句子/關(guān)鍵信息(referenceAnswerStatements)是否可歸因于給定的上下文(retrievedContext)并計(jì)算上下文召回率(contextRecall)。

舉個(gè)例子:

{
  "retrievedContext":[
    "2016 年,美國(guó)教育部撥款40億\n美元用以計(jì)算機(jī)科學(xué)教育普及\n五年計(jì)劃。\n英國(guó):滲透率9.3%\n2024 年,英國(guó)把編程納入5-12 歲\n少兒的必修課。\n芬蘭\n2016年,芬蘭將編程納入小學(xué)教學(xué)大綱",
    ...
],
"referenceAnswer":"2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣,未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。",
"referenceAnswerStatements":[
    "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。",
    "未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
]
"contextRecall":{
    "score":1,
    "data":[
      {"score":1,"statement":"2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。"},
      {
        "score":1,
        "statement":"未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
      }
    ]
}
}

代碼實(shí)現(xiàn)如下:

/**
 * 上下文召回率評(píng)估器。
 * 實(shí)現(xiàn)步驟:
 * 1. 將參考答案拆分成多個(gè)句子(關(guān)鍵信息);
 * 2. 逐個(gè)分析每個(gè)句子(關(guān)鍵信息)是否可歸因于給定的上下文;
 * 3. 根據(jù)每個(gè)句子(關(guān)鍵信息)的得分,計(jì)算上下文召回率。
 * @param evaluateData 評(píng)估數(shù)據(jù)
 * @param evaluateLLM 評(píng)估 LLM
 * @returns
 */
asyncfunctioncontextRecallEvaluator(evaluateData, evaluateLLM) {
// retrievedContext 檢索到的上下文
// referenceAnswer 參考答案
// referenceAnswerStatements 參考答案拆分出的多個(gè)句子(關(guān)鍵信息)
const { retrievedContext, referenceAnswer, referenceAnswerStatements } =
    evaluateData;
let newStatements = [];
if (!referenceAnswerStatements) {
    newStatements = awaitstatementSplit(referenceAnswer, evaluateLLM);
  } else {
    newStatements = [...referenceAnswerStatements];
  }
const allRes = [];
// 逐個(gè)分析每個(gè)句子(關(guān)鍵信息)是否可歸因于給定的上下文
while (newStatements.length > 0) {
    const statement = newStatements.shift();
    const prompt = `
你是一個(gè)語言專家,你的任務(wù)是分析句子是否可歸因于給定的上下文。

說明:
1. 如果句子不能歸因于上下文,則得分為0;
2. 如果句子能夠歸因于上下文,則得分為1;
3. 嚴(yán)格按以下JSON格式返回:{"score": "得分"},不能輸出其他無關(guān)內(nèi)容。

句子:
${statement}

上下文:
${retrievedContext.join('\n')}

回答:

`;
    const llmRes = await evaluateLLM.invoke(prompt);
    const data = formatToJson(llmRes);
    allRes.push({
      score: data?.score ? +data.score : 0,
      statement,
    });
    console.log('contextRecallEvaluator: ', allRes);
  }
// 根據(jù)每個(gè)句子(關(guān)鍵信息)的得分,計(jì)算上下文召回率
const score =
    allRes.reduce((score, cur) => {
      score += +cur.score;
      return score;
    }, 0) / allRes.length;
return {
    score,
    data: allRes,
  };
}

上下文相關(guān)性評(píng)估器實(shí)現(xiàn)

衡量檢索到的上下文與問題之間的相關(guān)性,避免包含無關(guān)冗余內(nèi)容。取值在 0 到 1 之間,數(shù)值越高表示檢索到的上下文相關(guān)性越高。計(jì)算公式:上下文相關(guān)性 = 上下文中與問題相關(guān)的片段數(shù)量 / 上下文中片段總數(shù)量。例如,檢索到的上下文總共有 5 個(gè)片段,與問題相關(guān)的片段有 4 個(gè),則上下文相關(guān)性為 0.8。

逐個(gè)分析每個(gè)上下文片段(retrievedContext)是否與問題(question)相關(guān)并計(jì)算上下文相關(guān)性(contextRelevance)。

舉個(gè)例子:

{
  "question":"預(yù)計(jì)2024年少兒編程教育市場(chǎng)規(guī)模是多少?未來潛力如何?",
"retrievedContext":[
    "2016 年,美國(guó)教育部撥款40億\n美元用以計(jì)算機(jī)科學(xué)教育普及\n五年計(jì)劃。\n英國(guó):滲透率9.3%\n2024 年,英國(guó)把編程納入5-12 歲\n少兒的必修課。\n芬蘭\n2016年,芬蘭將編程納入小學(xué)教學(xué)大綱",
    ...
],
"contextRelevance":{
    "score":0.7,
    "data":[
      {
        "score":0,
        "context":"2016 年,美國(guó)教育部撥款40億\n美元用以計(jì)算機(jī)科學(xué)教育普及\n五年計(jì)劃。\n英國(guó):滲透率9.3%\n2024 年,英國(guó)把編程納入5-12 歲\n少兒的必修課。\n芬蘭\n2016年,芬蘭將編程納入小學(xué)教學(xué)大綱"
      },
      ...
    ]
}
}

代碼實(shí)現(xiàn)如下:

/**
 * 上下文相關(guān)性評(píng)估器
 * 實(shí)現(xiàn)步驟:
 * 1. 逐個(gè)分析每個(gè)上下文片段是否與問題相關(guān);
 * 2. 根據(jù)每個(gè)上下文片段的得分,計(jì)算上下文相關(guān)性。
 * @param evaluateData 評(píng)估數(shù)據(jù)
 * @param evaluateLLM 評(píng)估 LLM
 * @returns
 */
asyncfunctioncontextRelevanceEvaluator(evaluateData, evaluateLLM) {
// question 問題
// retrievedContext 檢索到的上下文
const { question, retrievedContext } = evaluateData;
const newRetrievedContext = [...retrievedContext];
const allRes = [];
// 逐個(gè)分析每個(gè)上下文片段是否與問題相關(guān)
while (newRetrievedContext.length > 0) {
    const context = newRetrievedContext.shift();
    const prompt = `
你是一個(gè)語言專家,你的任務(wù)是確定上下文是否與問題有關(guān)。

說明:
1. 如果上下文與問題無關(guān),則得分為0;
2. 如果上下文與問題有關(guān),則得分為1;
3. 嚴(yán)格按以下JSON格式返回:{"score": "得分"},不能輸出其他無關(guān)內(nèi)容。

問題:
${question}

上下文:
${context}

回答:

`;
    const llmRes = await evaluateLLM.invoke(prompt);
    const data = formatToJson(llmRes);
    allRes.push({
      score: data?.score ? +data.score : 0,
      context,
    });
    console.log('contextRelevanceEvaluator: ', allRes);
  }
// 根據(jù)每個(gè)上下文片段的得分,計(jì)算上下文相關(guān)性
const score =
    allRes.reduce((score, cur) => {
      score += +cur.score;
      return score;
    }, 0) / allRes.length;
return {
    score,
    data: allRes,
  };
}

答案忠實(shí)度評(píng)估器實(shí)現(xiàn)

衡量實(shí)際答案是否嚴(yán)格基于檢索到的上下文,避免幻覺。取值在 0 到 1 之間,數(shù)值越高表示實(shí)際答案越嚴(yán)格基于檢索到的上下文。計(jì)算公式:答案忠實(shí)度 = 上下文能夠推斷出事實(shí)的數(shù)量 / 實(shí)際答案拆解出的事實(shí)總數(shù)量。例如,實(shí)際答案拆解出 5 個(gè)事實(shí),若檢索到的上下文覆蓋其中 4 個(gè)事實(shí),則答案忠實(shí)度為 0.8。

將實(shí)際答案(answer)拆分成多個(gè)句子(answerStatements)。

舉個(gè)例子:

{
  "answer": "根據(jù)提供的上下文信息,2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。",
  "answerStatements": [
    "2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。",
    "從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。",
    "這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。"
  ]
}

代碼實(shí)現(xiàn)如下:

/**
 * 將文本拆分為多個(gè)句子(關(guān)鍵信息)
 * @param text 待拆分的文本
 * @param evaluateLLM 拆分的 LLM
 * @returns
 */
async function statementSplit(text, evaluateLLM) {
  const prompt = `
  你是一個(gè)語言專家,你的任務(wù)是將以下文本拆分為多個(gè)獨(dú)立的句子,每個(gè)句子獨(dú)立表達(dá)一個(gè)完整含義,同時(shí)保留原意的邏輯連貫性。

  說明:
  1. 嚴(yán)格按以下JSON格式返回:["句子1", "句子2", ...],不能輸出其他無關(guān)內(nèi)容。

  文本:
${text}

  回答:

  `;
  const res = await evaluateLLM.invoke(prompt);
  const data = formatToJson(res) || [];
  console.log('statements: ', data);
  return data;
}

逐個(gè)分析每個(gè)句子(answerStatements)是否可歸因于給定的上下文(retrievedContext)并計(jì)算答案忠實(shí)度(faithfulness)。

舉個(gè)例子:

{
  "retrievedContext":[
    "2016 年,美國(guó)教育部撥款40億\n美元用以計(jì)算機(jī)科學(xué)教育普及\n五年計(jì)劃。\n英國(guó):滲透率9.3%\n2024 年,英國(guó)把編程納入5-12 歲\n少兒的必修課。\n芬蘭\n2016年,芬蘭將編程納入小學(xué)教學(xué)大綱",
    ...
],
"answer":"根據(jù)提供的上下文信息,2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。",
"answerStatements":[
    "2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。",
    "從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。",
    "這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。"
],
"faithfulness":{
    "score":1,
    "data":[
      {
        "score":1,
        "statement":"2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。"
      },
      {
        "score":1,
        "statement":"從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。"
      },
      {
        "score":1,
        "statement":"這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。"
      }
    ]
}
}

代碼實(shí)現(xiàn)如下:

/**
 * 答案忠實(shí)度評(píng)估器
 * 實(shí)現(xiàn)步驟:
 * 1. 將實(shí)際答案拆分成多個(gè)句子(事實(shí));
 * 2. 逐個(gè)分析每個(gè)句子(事實(shí))是否可歸因于給定的上下文;
 * 3. 根據(jù)每個(gè)句子(事實(shí))的得分,計(jì)算答案忠實(shí)度。
 * @param evaluateData 評(píng)估數(shù)據(jù)
 * @param evaluateLLM 評(píng)估 LLM
 * @returns
 */
asyncfunctionfaithfulnessEvaluator(evaluateData, evaluateLLM) {
// retrievedContext 檢索到的上下文
// answer 實(shí)際答案
// answerStatements 實(shí)際答案拆分出的多個(gè)句子(事實(shí))
const { retrievedContext, answer, answerStatements } = evaluateData;
let newStatements = [];
if (!answerStatements) {
    newStatements = awaitstatementSplit(answer, evaluateLLM);
  } else {
    newStatements = [...answerStatements];
  }
const allRes = [];
// 逐個(gè)分析每個(gè)句子(事實(shí))是否可歸因于給定的上下文
while (newStatements.length > 0) {
    const statement = newStatements.shift();
    const prompt = `
你是一個(gè)語言專家,你的任務(wù)是分析句子是否可歸因于給定的上下文。

說明:
1. 如果句子不能歸因于上下文,則得分為0;
2. 如果句子能夠歸因于上下文,則得分為1;
3. 嚴(yán)格按以下JSON格式返回:{"score": "得分"},不能輸出其他無關(guān)內(nèi)容。

句子:
${statement}

上下文:
${retrievedContext.join('\n')}

回答:

`;
    const llmRes = await evaluateLLM.invoke(prompt);
    const data = formatToJson(llmRes);
    allRes.push({
      score: data?.score ? +data.score : 0,
      statement,
    });
    console.log('faithfulnessEvaluator: ', allRes);
  }
// 根據(jù)每個(gè)句子(事實(shí))的得分,計(jì)算答案忠實(shí)度
const score =
    allRes.reduce((score, cur) => {
      score += +cur.score;
      return score;
    }, 0) / allRes.length;
return {
    score,
    data: allRes,
  };
}

答案相關(guān)性評(píng)估器實(shí)現(xiàn)

衡量實(shí)際答案是否直接完整回答用戶問題,排除冗余或跑題。取值在 0 到 1 之間,數(shù)值越高表示實(shí)際答案更直接完整回答用戶問題。計(jì)算公式:答案相關(guān)性 = 與實(shí)際問題相關(guān)的模擬問題數(shù)量 / 實(shí)際答案推導(dǎo)出的模擬問題總數(shù)量。例如,實(shí)際答案推導(dǎo)出 5 個(gè)模擬問題,若其中 4 個(gè)與實(shí)際問題相關(guān),則答案相關(guān)性為 0.8。

根據(jù)實(shí)際答案(answer)推導(dǎo)出多個(gè)模擬問題(simulationQuestions)。

舉個(gè)例子:

{
  "answer": "根據(jù)提供的上下文信息,2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。",
  "simulationQuestions": [
    "2024年少兒編程教育市場(chǎng)的規(guī)模是多少?",
    "未來五年到十年,少兒編程教育市場(chǎng)規(guī)模預(yù)計(jì)能達(dá)到多少?",
    "為什么說少兒編程教育有巨大的發(fā)展空間?"
  ]
}

代碼實(shí)現(xiàn)如下:

/**
 * 根據(jù)答案推導(dǎo)出多個(gè)模擬問題
 * @param text 
 * @param evaluateLLM 
 * @returns 
 */
async function simulationQuestion(text, evaluateLLM) {
  const prompt = `
  你是一個(gè)語言專家,你的任務(wù)是根據(jù)以下答案的核心內(nèi)容來生成3個(gè)用戶可能問的問題。

  說明:
  1. 嚴(yán)格按以下JSON格式返回:["問題1", "問題2", ...],不能輸出其他無關(guān)內(nèi)容。

  答案:
${text}

  回答:

  `;
  const res = await evaluateLLM.invoke(prompt);
  const data = formatToJson(res) || [];
  console.log('questions: ', data);
  return data;
}

逐個(gè)分析每個(gè)模擬問題(simulationQuestions)是否與原問題(question)相似并計(jì)算答案相關(guān)性(answerRelevance)。

舉個(gè)例子:

{
  "question":"預(yù)計(jì)2024年少兒編程教育市場(chǎng)規(guī)模是多少?未來潛力如何?",
"answer":"根據(jù)提供的上下文信息,2024年少兒編程教育市場(chǎng)的規(guī)模約為488億元人民幣。從長(zhǎng)遠(yuǎn)來看,隨著越來越多家長(zhǎng)認(rèn)同編程教育的重要性以及其逐漸滲透進(jìn)入教學(xué)體系內(nèi),該市場(chǎng)有望在未來5到10年內(nèi)發(fā)展成為一個(gè)千億級(jí)別的大市場(chǎng)。這表明少兒編程教育具有巨大的發(fā)展?jié)摿涂臻g。",
"simulationQuestions":[
    "2024年少兒編程教育市場(chǎng)的規(guī)模是多少?",
    "未來五年到十年,少兒編程教育市場(chǎng)規(guī)模預(yù)計(jì)能達(dá)到多少?",
    "為什么說少兒編程教育有巨大的發(fā)展空間?"
],
"answerRelevance":{
    "score":1,
    "data":[
      {
        "score":1,
        "simulationQuestion":"2024年少兒編程教育市場(chǎng)的規(guī)模是多少?"
      },
      {
        "score":1,
        "simulationQuestion":"未來五年到十年,少兒編程教育市場(chǎng)規(guī)模預(yù)計(jì)能達(dá)到多少?"
      },
      {
        "score":1,
        "simulationQuestion":"為什么說少兒編程教育有巨大的發(fā)展空間?"
      }
    ]
}
}

代碼實(shí)現(xiàn)如下:

/**
 * 答案相關(guān)性評(píng)估器
 * 實(shí)現(xiàn)步驟:
 * 1. 根據(jù)實(shí)際答案推導(dǎo)出多個(gè)模擬問題;
 * 2. 逐個(gè)分析每個(gè)模擬問題是否與原問題相似;
 * 3. 根據(jù)每個(gè)模擬問題的得分,計(jì)算答案相關(guān)性。
 * @param evaluateData 評(píng)估數(shù)據(jù)
 * @param evaluateLLM 評(píng)估 LLM
 * @returns
 */
asyncfunctionanswerRelevanceEvaluator(evaluateData, evaluateLLM) {
// question 問題
// answer 實(shí)際答案
// simulationQuestions 根據(jù)實(shí)際答案推導(dǎo)出的多個(gè)模擬問題
const { question, answer, simulationQuestions } = evaluateData;
let newSimulationQuestions = [];
if (!simulationQuestions) {
    newSimulationQuestions = awaitsimulationQuestion(answer, evaluateLLM);
  } else {
    newSimulationQuestions = [...simulationQuestions];
  }
const allRes = [];
// 逐個(gè)分析每個(gè)模擬問題是否與原問題相似
while (newSimulationQuestions.length > 0) {
    const simulationQuestion = newSimulationQuestions.shift();
    const prompt = `
你是一個(gè)語言專家,你的任務(wù)是分析模擬問題和實(shí)際問題是否相似。

說明:
1. 如果模擬問題與實(shí)際問題不相似,則得分為0;
2. 如果模擬問題與實(shí)際問題相似,則得分為1;
3. 嚴(yán)格按以下JSON格式返回:{"score": "相似度"},不能輸出其他無關(guān)內(nèi)容。

模擬問題:
${simulationQuestion}

實(shí)際問題:
${question}

回答:

`;
    const llmRes = await evaluateLLM.invoke(prompt);
    const data = formatToJson(llmRes);
    allRes.push({
      score: data?.score ? +data.score : 0,
      simulationQuestion,
    });
    console.log('answerRelevanceEvaluator: ', allRes);
  }
// 根據(jù)每個(gè)模擬問題的得分,計(jì)算答案相關(guān)性
const score =
    allRes.reduce((score, cur) => {
      score += +cur.score;
      return score;
    }, 0) / allRes.length;
return {
    score,
    data: allRes,
  };
}

答案正確性評(píng)估器實(shí)現(xiàn)

衡量實(shí)際答案的準(zhǔn)確性,需與參考答案對(duì)比。取值在 0 到 1 之間,數(shù)值越高表示實(shí)際答案與參考答案匹配度越高,準(zhǔn)確性也就越高。計(jì)算公式:答案準(zhǔn)確性 = 實(shí)際答案覆蓋的關(guān)鍵信息數(shù)量 / 參考答案中關(guān)鍵信息總數(shù)量。例如,參考答案需要 5 個(gè)關(guān)鍵信息,若實(shí)際答案覆蓋其中 4 個(gè)關(guān)鍵信息,則答案正確性為 0.8。

將參考答案(referenceAnswer)拆分成多個(gè)句子/關(guān)鍵信息(referenceAnswerStatements)。

舉個(gè)例子:

{
  "referenceAnswer": "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣,未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。",
  "referenceAnswerStatements": [
    "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。",
    "未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
  ]
}

代碼實(shí)現(xiàn)如下:

/**
 * 將文本拆分為多個(gè)句子(關(guān)鍵信息)
 * @param text 待拆分的文本
 * @param evaluateLLM 拆分的 LLM
 * @returns
 */
async function statementSplit(text, evaluateLLM) {
  const prompt = `
  你是一個(gè)語言專家,你的任務(wù)是將以下文本拆分為多個(gè)獨(dú)立的句子,每個(gè)句子獨(dú)立表達(dá)一個(gè)完整含義,同時(shí)保留原意的邏輯連貫性。

  說明:
  1. 嚴(yán)格按以下JSON格式返回:["句子1", "句子2", ...],不能輸出其他無關(guān)內(nèi)容。

  文本:
${text}

  回答:

  `;
  const res = await evaluateLLM.invoke(prompt);
  const data = formatToJson(res) || [];
  console.log('statements: ', data);
  return data;
}

逐個(gè)分析每個(gè)句子/關(guān)鍵信息(referenceAnswerStatements)是否可歸因于給定的實(shí)際答案(question)并計(jì)算答案正確性(answerCorrectness)。

舉個(gè)例子:

{
  "question":"預(yù)計(jì)2024年少兒編程教育市場(chǎng)規(guī)模是多少?未來潛力如何?",
"referenceAnswer":"2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣,未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。",
"referenceAnswerStatements":[
    "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。",
    "未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
]
"answerCorrectness":{
    "score":1,
    "data":[
      {"score":1,"statement":"2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣。"},
      {
        "score":1,
        "statement":"未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
      }
    ]
}
}

代碼實(shí)現(xiàn)如下:

/**
 * 答案正確性評(píng)估器
 * 實(shí)現(xiàn)步驟:
 * 1. 將參考答案拆分成多個(gè)句子(關(guān)鍵信息);
 * 2. 逐個(gè)分析每個(gè)句子(關(guān)鍵信息)是否可歸因于給定的實(shí)際答案;
 * 3. 根據(jù)每個(gè)句子(關(guān)鍵信息)的得分,計(jì)算答案正確性。
 * @param evaluateData 評(píng)估數(shù)據(jù)
 * @param evaluateLLM 評(píng)估 LLM
 * @returns
 */
asyncfunctionanswerCorrectnessEvaluator(evaluateData, evaluateLLM) {
// answer 實(shí)際答案
// referenceAnswer 參考答案
// referenceAnswerStatements 參考答案拆分出的多個(gè)句子(關(guān)鍵信息)
const { answer, referenceAnswer, referenceAnswerStatements } = evaluateData;
let newStatements = [];
if (!referenceAnswerStatements) {
    newStatements = awaitstatementSplit(referenceAnswer, evaluateLLM);
  } else {
    newStatements = [...referenceAnswerStatements];
  }
const allRes = [];
// 逐個(gè)分析每個(gè)句子(關(guān)鍵信息)是否可歸因于給定的實(shí)際答案
while (newStatements.length > 0) {
    const statement = newStatements.shift();
    const prompt = `
你是一個(gè)語言專家,你的任務(wù)是分析句子是否可歸因于給定的實(shí)際答案。

說明:
1. 如果句子不能歸因于實(shí)際答案,則得分為0;
2. 如果句子能夠歸因于實(shí)際答案,則得分為1;
3. 嚴(yán)格按以下JSON格式返回:{"score": "得分"},不能輸出其他無關(guān)內(nèi)容。

句子:
${statement}

實(shí)際答案:
${answer}

回答:

`;
    const llmRes = await evaluateLLM.invoke(prompt);
    const data = formatToJson(llmRes);
    allRes.push({
      score: data?.score ? +data.score : 0,
      statement,
    });
    console.log('answerCorrectnessEvaluator: ', allRes);
  }
// 根據(jù)每個(gè)句子(關(guān)鍵信息)的得分,計(jì)算答案正確性
const score =
    allRes.reduce((score, cur) => {
      score += +cur.score;
      return score;
    }, 0) / allRes.length;
return {
    score,
    data: allRes,
  };
}

基礎(chǔ)版 RAG 系統(tǒng)評(píng)估

至此,我們基于 LLM-as-judge 自己實(shí)現(xiàn)了一套 RAG 系統(tǒng)評(píng)估系統(tǒng),下面我們通過該評(píng)估系統(tǒng)來評(píng)估基礎(chǔ)版 RAG 系統(tǒng)。

以下每一步的詳細(xì)代碼就不貼了,評(píng)估詳細(xì)代碼地址[2]:https://github.com/laixiangran/ai-learn/blob/main/src/app/rag/03_rag_evaluator/route.ts

準(zhǔn)備 QA 測(cè)試數(shù)據(jù)

這里我準(zhǔn)備了 20 個(gè) 測(cè)試 QA(含參考答案),QA 測(cè)試數(shù)據(jù)文件地址[3]:https://github.com/laixiangran/ai-learn/blob/main/src/app/data/qa_test_20.json

[
  ...
  {
    "question": "預(yù)計(jì)2024年少兒編程教育市場(chǎng)規(guī)模是多少?未來潛力如何?",
    "referenceAnswer": "2024年市場(chǎng)規(guī)模預(yù)計(jì)約488億人民幣,未來有望達(dá)到千億級(jí)別,顯示行業(yè)持續(xù)增長(zhǎng)的潛力。"
  },
  ...
]

知識(shí)庫(kù)構(gòu)建

文檔切分配置:

  • 用于分割文本的字符或字符串(separator):["\n\n", "\n", " ", ""];
  • 每個(gè)文本塊的最大字符數(shù)(chunk_size):500;
  • 文本塊之間的重疊字符數(shù)(chunk_overlap):50。

Embedding 模型:

  • nomic-embed-text。

代碼實(shí)現(xiàn)如下:

// 1. 文件解析
const docs = awaitloadPdf(
    'src/app/data/2024少兒編程教育行業(yè)發(fā)展趨勢(shì)報(bào)告.pdf'
  );

// 2. 文件切分
const texts = awaitsplitDocuments(docs);

// 3. 初始化向量模型和向量數(shù)據(jù)庫(kù),并將文檔存儲(chǔ)到向量數(shù)據(jù)庫(kù)
awaitaddDocuments(texts);

指標(biāo)評(píng)估

檢索上下文 TopK: 3;

評(píng)估 LLM: qwen2.5:14b(Ollama 部署)。

代碼實(shí)現(xiàn)如下:

// 單個(gè)指標(biāo)評(píng)估
asyncfunctionbathEvaluator(indexName: string) {
const evaluatorMap = {
    contextRecall: contextRecallEvaluator,
    contextRelevance: contextRelevanceEvaluator,
    faithfulness: faithfulnessEvaluator,
    answerRelevance: answerRelevanceEvaluator,
    answerCorrectness: answerCorrectnessEvaluator,
  };
const evaluator = evaluatorMap[indexName];
const inputPath = 'src/app/data/qa_test_20.json';
const outputPath = 'src/app/data/qa_test_20_base_evaluate.json';
const qaDatas = awaitreadJsonFile(inputPath);
const llm = initOllamaLLM('qwen2.5:14b');

const res = [];
while (qaDatas.length > 0) {
    const data = qaDatas.shift();
    if (!data.answer) {
      const { retrievedContext, answer } = awaitllmAnswerByQaData(
        data.question
      );
      data.retrievedContext = retrievedContext;
      data.answer = answer;
    }
    const evaluateRes = awaitevaluator(data, llm);
    res.push({
      ...data,
      [indexName]: evaluateRes,
    });
  }

// 將 LLM 回答結(jié)果保存到文件中
awaitsaveJsonFile(JSON.stringify(res), outputPath);

// 計(jì)算最終指標(biāo)數(shù)據(jù)
const score =
    res.reduce((score, cur) => {
      score += cur[indexName].score;
      return score;
    }, 0) / res.length;

return { [indexName]: +score.toFixed(1) };
}

// 指標(biāo)評(píng)估
const indexs = [
'contextRecall',
'contextRelevance',
'faithfulness',
'answerRelevance',
'answerCorrectness',
];
constdata: any = {};
while (indexs.length > 0) {
const indexName = indexs.shift() || '';
const indexRes = awaitbathEvaluator(indexName);
  data[indexName] = indexRes[indexName];
}

基礎(chǔ)版 RAG 系統(tǒng)(V1.0)各指標(biāo)的評(píng)估結(jié)果如下:

圖片

版本

優(yōu)化描述

上下文召回率(contextRecall

上下文相關(guān)性(contextRelevance

答案忠實(shí)度(faithfulness

答案相關(guān)性(answerRelevance

答案正確性(answerCorrectness

基礎(chǔ) RAG 系統(tǒng)(V1.0)

0.6

0.5

0.8

0.5

0.6

結(jié)語

至此,我們基于 LLM-as-judge 自己實(shí)現(xiàn)一套 RAG 系統(tǒng)評(píng)估系統(tǒng),用該評(píng)估系統(tǒng)評(píng)估了基礎(chǔ)版 RAG 系統(tǒng)(V1.0)的 5 個(gè)評(píng)估指標(biāo)的表現(xiàn),可以看到基礎(chǔ)版 RAG 系統(tǒng)(V1.0)這 5 個(gè)指標(biāo)的值都是偏低的,所以后面我將通過講解不同的優(yōu)化方法來提升基礎(chǔ)版 RAG 系統(tǒng)(V1.0)這 5 個(gè)指標(biāo),敬請(qǐng)期待。

引用鏈接

[1] 本文完整代碼地址: https://github.com/laixiangran/ai-learn/blob/main/src/app/rag/03_rag_evaluator/route.ts

[2] 評(píng)估詳細(xì)代碼地址: https://github.com/laixiangran/ai-learn/blob/main/src/app/rag/03_rag_evaluator/route.ts

[3] QA 測(cè)試數(shù)據(jù)文件地址: https://github.com/laixiangran/ai-learn/blob/main/src/app/data/qa_test_20.json

責(zé)任編輯:龐桂玉 來源: 燃哥講AI
相關(guān)推薦

2025-05-23 06:00:00

RAGAI人工智能

2025-05-23 02:00:00

RAGAI人工智能

2024-09-10 08:26:40

2024-03-04 00:05:00

人工智能LLM 評(píng)估

2011-02-22 10:01:13

2024-06-18 14:01:17

2011-03-22 16:45:00

2025-05-22 06:48:50

RAGAI應(yīng)用開發(fā)框架DeepSeek

2022-09-01 16:58:52

DTW算法鴻蒙

2009-06-20 09:14:48

2024-05-10 14:35:56

人工智能大型語言模型

2024-05-27 00:45:00

2016-10-07 21:56:28

2013-06-18 19:23:16

身份認(rèn)證管理身份認(rèn)證管理系統(tǒng)身份認(rèn)證

2013-06-19 09:46:57

身份認(rèn)證管理云應(yīng)用

2011-01-13 16:59:12

2024-09-11 16:36:39

2021-12-02 06:40:43

SSPMSaaS應(yīng)用風(fēng)險(xiǎn)

2024-01-11 16:24:12

人工智能RAG

2015-05-04 13:13:39

ONOS網(wǎng)絡(luò)操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)