合肥有多少做網(wǎng)站的優(yōu)化營商環(huán)境工作總結(jié)
文章目錄
- FastGPT 源碼:如何實現(xiàn) "問題優(yōu)化"
- 一、前言
- 二、源碼分析
- 2.1 queryExtension.ts 提示詞
- 2.2 queryExtension.ts 核心邏輯
- 2.3 queryExtension 引用位置
- 三、流程總結(jié)
FastGPT 源碼:如何實現(xiàn) “問題優(yōu)化”
一、前言
- 問題優(yōu)化的背景和目的
- 在 RAG (檢索增強(qiáng)生成) 系統(tǒng)中,用戶的問題需要去數(shù)據(jù)庫中執(zhí)行向量搜索來找到相關(guān)內(nèi)容
- 但在連續(xù)對話中,用戶的后續(xù)問題往往是不完整的,比如"第二點是什么"這樣的問題
- 如果直接用這樣的問題去搜索,由于缺乏上下文,很難找到相關(guān)內(nèi)容
- 因此需要問題優(yōu)化模塊來補全用戶的問題,使其變得完整和明確
- 核心實現(xiàn)方式
FastGPT 主要通過queryExtension
函數(shù)來實現(xiàn)問題優(yōu)化,核心代碼在packages/service/core/ai/functions/queryExtension.ts
中:
-
輸入?yún)?shù)包括:
- chatBg: 對話背景
- query: 用戶當(dāng)前問題
- histories: 歷史對話記錄
- model: 使用的模型
-
實現(xiàn)流程:
- 構(gòu)建提示詞模板,包含示例和要求
- 結(jié)合歷史記錄和當(dāng)前問題生成完整的提示詞
- 調(diào)用 AI 模型生成多個檢索詞
- 返回原始問題和擴(kuò)展后的問題列表
- 提示詞設(shè)計
FastGPT 使用了精心設(shè)計的提示詞模板來引導(dǎo) AI 模型生成高質(zhì)量的檢索詞:
const defaultPrompt = `作為一個向量檢索助手,你的任務(wù)是結(jié)合歷史記錄,從不同角度,為"原問題"生成個不同版本的"檢索詞",從而提高向量檢索的語義豐富度,提高向量檢索的精度。生成的問題要求指向?qū)ο笄逦鞔_,并與"原問題語言相同"。`;
- 實際效果
- 原問題:“第二點是什么”
- 歷史記錄中包含了 “FastGPT 的優(yōu)勢” 的上下文
- 優(yōu)化后的檢索詞會變成:
- “介紹下 FastGPT 簡便的優(yōu)勢”
- “FastGPT 為什么使用起來簡便?”
- “FastGPT的有哪些簡便的功能?”
- 搜索結(jié)果處理
優(yōu)化后的問題會用于知識庫搜索,搜索結(jié)果還會經(jīng)過重排序(ReRank)來進(jìn)一步提高相關(guān)性:
const reRankSearchResult = async ({data,query
}: {data: SearchDataResponseItemType[];query: string;
}) => {// 使用 rerank 模型對搜索結(jié)果重新排序const results = await reRankRecall({query,documents: data.map((item) => ({id: item.id,text: `${item.q}\n${item.a}`}))});
};
這樣的問題優(yōu)化機(jī)制確保了即使在用戶提出不完整或指代性問題時,系統(tǒng)也能準(zhǔn)確理解用戶意圖并找到相關(guān)的知識庫內(nèi)容。
二、源碼分析
2.1 queryExtension.ts 提示詞
作為一個向量檢索助手,你的任務(wù)是結(jié)合歷史記錄,從不同角度,為“原問題”生成個不同版本的“檢索詞”,從而提高向量檢索的語義豐富度,提高向量檢索的精度。生成的問題要求指向?qū)ο笄逦鞔_,并與“原問題語言相同”。例如:
歷史記錄:
"""
"""
原問題: 介紹下劇情。
檢索詞: ["介紹下故事的背景和主要人物。","故事的主題是什么?","劇情是是如何發(fā)展的?"]
----------------
歷史記錄:
"""
Q: 對話背景。
A: 當(dāng)前對話是關(guān)于 Nginx 的介紹和使用等。
"""
原問題: 怎么下載
檢索詞: ["Nginx 如何下載?","下載 Nginx 需要什么條件?","有哪些渠道可以下載 Nginx?"]
----------------
歷史記錄:
"""
Q: 對話背景。
A: 當(dāng)前對話是關(guān)于 Nginx 的介紹和使用等。
Q: 報錯 "no connection"
A: 報錯"no connection"可能是因為……
"""
原問題: 怎么解決
檢索詞: ["Nginx報錯"no connection"如何解決?","造成'no connection'報錯的原因。","Nginx提示'no connection',要怎么辦?"]
----------------
歷史記錄:
"""
Q: 護(hù)產(chǎn)假多少天?
A: 護(hù)產(chǎn)假的天數(shù)根據(jù)員工所在的城市而定。請?zhí)峁┠诘某鞘?#xff0c;以便我回答您的問題。
"""
原問題: 沈陽
檢索詞: ["沈陽的護(hù)產(chǎn)假多少天?"]
----------------
歷史記錄:
"""
Q: 作者是誰?
A: FastGPT 的作者是 labring。
"""
原問題: Tell me about him
檢索詞: ["Introduce labring, the author of FastGPT." ," Background information on author labring." "," Why does labring do FastGPT?"]
----------------
歷史記錄:
"""
Q: 對話背景。
A: 關(guān)于 FatGPT 的介紹和使用等問題。
"""
原問題: 你好。
檢索詞: ["你好"]
----------------
歷史記錄:
"""
Q: FastGPT 如何收費?
A: FastGPT 收費可以參考……
"""
原問題: 你知道 laf 么?
檢索詞: ["laf是什么?","如何使用laf?","laf的介紹。"]
----------------
歷史記錄:
"""
Q: FastGPT 的優(yōu)勢
A: 1. 開源2. 簡便3. 擴(kuò)展性強(qiáng)
"""
原問題: 介紹下第2點。
檢索詞: ["介紹下 FastGPT 簡便的優(yōu)勢", "FastGPT 為什么使用起來簡便?","FastGPT的有哪些簡便的功能?"]。
----------------
歷史記錄:
"""
Q: 什么是 FastGPT?
A: FastGPT 是一個 RAG 平臺。
Q: 什么是 Laf?
A: Laf 是一個云函數(shù)開發(fā)平臺。
"""
原問題: 它們有什么關(guān)系?
檢索詞: ["FastGPT和Laf有什么關(guān)系?","FastGPT的RAG是用Laf實現(xiàn)的么?"]
----------------
歷史記錄:
"""
{{histories}}
"""
原問題: {{query}}
檢索詞: `
2.2 queryExtension.ts 核心邏輯
好的,我來幫您逐行分析 queryExtension.ts
的代碼實現(xiàn):
- 導(dǎo)入依賴
import { replaceVariable } from '@fastgpt/global/common/string/tools'; // 用于替換字符串中的變量
import { getAIApi } from '../config'; // 獲取 AI API 配置
import { ChatItemType } from '@fastgpt/global/core/chat/type'; // 聊天項類型定義
import { countGptMessagesTokens } from '@fastgpt/global/common/string/tiktoken'; // 計算 token 數(shù)量
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type'; // OpenAI 聊天參數(shù)類型
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt'; // 聊天內(nèi)容轉(zhuǎn)換為運行時提示詞
- 提示詞模板定義
const defaultPrompt = `作為一個向量檢索助手...`;
這是一個很長的提示詞模板,包含了多個示例。每個示例都遵循相同的格式:
- 歷史記錄: 展示對話上下文
- 原問題: 用戶當(dāng)前的問題
- 檢索詞: 生成的擴(kuò)展問題數(shù)組
- 主函數(shù)定義
export const queryExtension = async ({chatBg, // 對話背景query, // 用戶當(dāng)前問題histories = [], // 歷史對話記錄model // 使用的模型
}) => {
- 構(gòu)建系統(tǒng)提示詞
const systemFewShot = chatBg? `Q: 對話背景。
A: ${chatBg}
`: '';
如果有對話背景,則添加到提示詞中
- 構(gòu)建歷史對話
const historyFewShot = histories.map((item) => {const role = item.obj === 'Human' ? 'Q' : 'A';return `${role}: ${chatValue2RuntimePrompt(item.value).text}`;}).join('\n');
將歷史對話記錄轉(zhuǎn)換為 Q/A 格式的文本
- 合并提示詞
const concatFewShot = `${systemFewShot}${historyFewShot}`.trim();
- 初始化 AI API
const ai = getAIApi({timeout: 480000 // 8分鐘超時
});
- 構(gòu)建請求消息
const messages = [{role: 'user',content: replaceVariable(defaultPrompt, {query: `${query}`,histories: concatFewShot})}
] as ChatCompletionMessageParam[];
將用戶問題和歷史記錄替換到提示詞模板中
- 調(diào)用 AI 接口
const result = await ai.chat.completions.create({model: model,temperature: 0.01, // 溫度很低,保證輸出穩(wěn)定性messages,stream: false
});
- 處理返回結(jié)果
let answer = result.choices?.[0]?.message?.content || '';
if (!answer) {return {rawQuery: query,extensionQueries: [],model,tokens: 0};
}
- 解析結(jié)果
answer = answer.replace(/\\"/g, '"'); // 處理轉(zhuǎn)義字符
try {const queries = JSON.parse(answer) as string[]; // 解析為字符串?dāng)?shù)組return {rawQuery: query, // 原始問題extensionQueries: Array.isArray(queries) ? queries : [], // 擴(kuò)展后的問題列表model, // 使用的模型tokens: countGptMessagesTokens(messages) // token 數(shù)量};
} catch (error) {// 解析失敗時返回空結(jié)果console.log(error);return {rawQuery: query,extensionQueries: [],model,tokens: 0};
}
這個函數(shù)的主要作用是:
- 接收用戶問題和歷史對話
- 使用精心設(shè)計的提示詞引導(dǎo) AI 生成多個檢索詞
- 返回原始問題和擴(kuò)展后的問題列表
- 通過低溫度參數(shù)(0.01)確保輸出的穩(wěn)定性
- 完整的錯誤處理確保函數(shù)的健壯性
這樣的設(shè)計使得即使用戶提出不完整的問題,系統(tǒng)也能通過上下文理解用戶意圖并生成合適的檢索詞。
2.3 queryExtension 引用位置
- 知識庫搜索中的使用
// packages/service/core/dataset/search/utils.ts
export const datasetSearchQueryExtension = async ({model,query,histories,chatBg
}) => {const result = await queryExtension({model,query,histories,chatBg});
}
這是最主要的使用場景,在知識庫搜索前對用戶問題進(jìn)行優(yōu)化。
- 工作流節(jié)點中的使用
// packages/service/core/workflow/dispatch/tools/queryExternsion.ts
export const dispatchQueryExtension = async ({model,params,histories,chatBg
}) => {const queryExtensionModel = getLLMModel(model);const { extensionQueries, tokens } = await queryExtension({chatBg,query: params.userChatInput,histories,model: queryExtensionModel.model});
}
作為工作流中的一個獨立節(jié)點使用,可以在對話流程中進(jìn)行問題優(yōu)化。
- 搜索測試中的使用
// projects/app/src/pages/api/core/dataset/searchTest.ts
const { concatQueries, rewriteQuery, aiExtensionResult } = await datasetSearchQueryExtension({model: body.model,query: body.searchParams.query,histories: body.searchParams.histories || [],chatBg: body.searchParams.chatBg
});
在知識庫的搜索測試功能中使用,用于測試問題優(yōu)化的效果。
- 配置相關(guān)
在多個配置文件中,我們可以看到usedInQueryExtension
的配置:
{"usedInQueryExtension": true // 標(biāo)記模型是否可用于問題優(yōu)化
}
- UI 組件中的使用
// projects/app/src/components/core/module/DatasetParamsModal.tsx
const queryExtensionModel = watch('datasetSearchExtensionModel');
在界面上提供問題優(yōu)化相關(guān)的配置選項。
三、流程總結(jié)
- 用戶發(fā)起問題
- 如果啟用了問題優(yōu)化功能:
- 系統(tǒng)會調(diào)用
queryExtension
生成多個檢索詞 - 這些檢索詞會與原始問題一起用于知識庫搜索
- 搜索結(jié)果會經(jīng)過重排序和合并
- 系統(tǒng)會調(diào)用
- 最終返回最相關(guān)的知識庫內(nèi)容
這種設(shè)計讓系統(tǒng)能夠:
- 更好地理解用戶的意圖
- 處理不完整或指代性的問題
- 提高知識庫搜索的準(zhǔn)確性
- 支持連續(xù)對話中的上下文理解