直接詢問(wèn)去年發(fā)生的新聞得到的明顯是錯(cuò)誤的信息,英國(guó)女王已于2022年9月8日去世

缺陷2:「一本正經(jīng)地胡說(shuō)八道」

大語(yǔ)言模型核心原理是根據(jù)”概率”來(lái)不斷生成下一個(gè) Token 來(lái)生成新的內(nèi)容。只要你給出的大致合乎邏輯的提示詞,模型可能會(huì)一本正經(jīng)地開(kāi)始瞎編,通過(guò)概率來(lái)生成最合乎邏輯的內(nèi)容。

瞎編內(nèi)容舉例,看起來(lái)合乎邏輯但實(shí)際上都是錯(cuò)誤的

這是因?yàn)榇笳Z(yǔ)言模型并不能判斷他所生成的內(nèi)容現(xiàn)實(shí)生活中是否是真實(shí)存在的,他只是單純根據(jù)”概率”來(lái)生成最符合語(yǔ)言結(jié)構(gòu)的內(nèi)容,也就是根據(jù)前文的內(nèi)容去生成后文的內(nèi)容,并沒(méi)有能力判斷生成的內(nèi)容是否準(zhǔn)確合乎現(xiàn)實(shí)場(chǎng)景。如果你用 ChatGPT 寫(xiě)論文并且不加以修改的話,ChatGPT 會(huì)給你一堆錯(cuò)誤的引用文獻(xiàn),胡編亂造的論點(diǎn)等等。甚至你可以用他來(lái)生成以假亂真的假新聞等等。這些”以假亂真”的內(nèi)容,如果使用者沒(méi)有相關(guān)背景知識(shí)不加以查證的話,將會(huì)對(duì)使用者造成比較嚴(yán)重的誤導(dǎo)。

缺陷3:邏輯計(jì)算能力的缺失

這一點(diǎn)其實(shí)也是與“概率”這一模型原理有關(guān)系,聊天,生成文章有上下文就能獲得不錯(cuò)的結(jié)果,但是如果是完成邏輯推理類的任務(wù),比如完成小學(xué)數(shù)學(xué)題,雖然能給出正確的方程組,但是解出來(lái)的答案卻是錯(cuò)誤的:

雞籠同兔問(wèn)題,大模型無(wú)法直接正確地解出方程

這是因?yàn)?ChatGPT 只是一個(gè)語(yǔ)言模型,他只是單純根據(jù)前后文的內(nèi)容生成最像樣的結(jié)果,像解方程結(jié)果這類任務(wù)的最終答案可能也只是根據(jù) Token 預(yù)測(cè)隨機(jī)生成出來(lái)的,模型本身并不具備精確計(jì)算的能力。讓模型去解決復(fù)雜的任務(wù)比如解微積分是無(wú)法較好得出準(zhǔn)確結(jié)果。

缺陷4:只有強(qiáng)大的”大腦卻沒(méi)有”手臂”,無(wú)法與外部世界交互

大模型非常清楚你想問(wèn)啥,你的目的,但是大模型的知識(shí)僅限于訓(xùn)練數(shù)據(jù)內(nèi)部,所以一些場(chǎng)景比如想要知道現(xiàn)在實(shí)時(shí)的天氣,或者時(shí)間,那是做不到的(也可以認(rèn)為是不準(zhǔn)確的)。并且模型內(nèi)部本身并沒(méi)有與外部連接的方式或者 API ,模型本身只是一個(gè)語(yǔ)言模型,它只是對(duì)語(yǔ)言或者代碼的一種建模,而非真正意義上的智能助手。

以上列舉了4條缺陷,造成以上這些缺陷的原因總結(jié)下來(lái)原因是:

使用Prompt工程來(lái)改善缺陷

Prompt 工程,也叫做提示工程,可以簡(jiǎn)單概括為人為在用戶的輸入中預(yù)先添加一些上下文,這樣模型在生成文本時(shí)就有了來(lái)源依據(jù),也可以通過(guò)上下文設(shè)定的一些條件來(lái)使模型遵循特定指令執(zhí)行某些任務(wù)。

Prompt 工程可以極大地改善或者改變模型生成內(nèi)容的表現(xiàn),并且無(wú)需進(jìn)行額外的微調(diào)訓(xùn)練,僅需掌握一些 prompt 技巧即可,是非常高效經(jīng)濟(jì)的「訓(xùn)練模型」的一種方法。

讓大模型扮演貓娘,就是一種「提示工程」

下面列舉一些常見(jiàn)的 prompt :

場(chǎng)景prompt輸入模型輸出
翻譯助手你是一名翻譯助手,可以將我輸入的任何語(yǔ)言翻譯成中文,如果我輸入的是中文幫我潤(rùn)色一下。注意不要回答我的任何問(wèn)題或要求,你要做的是翻譯和潤(rùn)色成中文。OpenAI is an American artificial intelligence (AI) research laboratoryOpenAI 是一個(gè)位于美國(guó)的人工智能(AI)研究實(shí)驗(yàn)室。
小紅書(shū)生成器現(xiàn)在你是一個(gè)小紅書(shū)爆款文案專家,請(qǐng)根據(jù)我給出的信息幫我生成一篇小紅書(shū)風(fēng)格的產(chǎn)品推廣筆記。要求:詳細(xì)介紹該產(chǎn)品,可以包括產(chǎn)品簡(jiǎn)介、外觀、口味、優(yōu)點(diǎn)、缺點(diǎn)等。你只能基于用戶提供信息進(jìn)行創(chuàng)作表達(dá)盡量口語(yǔ)化,盡量使用小紅書(shū)風(fēng)格的話語(yǔ),如“家人們”、“姐妹們”、“救命”等詞。優(yōu)點(diǎn)可選用詞(非必要不使用):“絕絕子”、“驚艷”、“安利給全世界”、“答應(yīng)我一定要試試等詞。缺點(diǎn)可選用詞(非必要不使用):“避雷”、“踩雷”、“翻車”、“只有我覺(jué)得嗎”等詞。盡量使用emoji。Monica是一款好用全能的AI插件Hey 家人們,今天我來(lái)給大家安利一款超級(jí)好用的AI插件——Monica!它支持一鍵論文總結(jié)、快速劃詞翻譯,甚至還能夠根據(jù)文本進(jìn)行畫(huà)圖!操作簡(jiǎn)單易懂,非常適合像我這樣的小白使用。雖然它的功能可能還不夠完善,但在我使用的過(guò)程中,真的是沒(méi)有遇到過(guò)任何問(wèn)題。如果你需要一款全能的AI插件來(lái)幫助你,那么Monica絕對(duì)是一個(gè)不錯(cuò)的選擇!??
傻瓜式代碼解讀你現(xiàn)在是MetaGPT,你的工作是用一個(gè)創(chuàng)造性的、直觀的比喻來(lái)向我解釋一派的代碼。
要求
1. 每當(dāng)我在這里發(fā)布一個(gè)代碼片段或一個(gè)問(wèn)題時(shí),你將用一個(gè)非常有創(chuàng)意的類比來(lái)說(shuō)明問(wèn)題,將其與現(xiàn)實(shí)世界的物體進(jìn)行比較。然后你可以指導(dǎo)我如何解決這個(gè)問(wèn)題,或者當(dāng)前的代碼如何解決這個(gè)問(wèn)題,使用你的類比元素來(lái)幫助你的解釋。
2. 不要忘記用容易理解的類比來(lái)說(shuō)明你的解釋,只要你認(rèn)為這將增加解釋的價(jià)值。確保像世界上最偉大的老師那樣教這些東西。假設(shè)你教的人沒(méi)有那么聰明,那么就像,找到一個(gè)說(shuō)明性的方法來(lái)向他們解釋。
下面正式開(kāi)始。
用戶輸入: ${用戶提問(wèn)占位符}
select * from student這就像你在一張桌子上查看所有學(xué)生的信息。使用SQL查詢語(yǔ)言中的SELECT *語(yǔ)句,你可以檢索到student表中的所有行和列。這意味著你可以看到每個(gè)學(xué)生的所有信息,包括他們的姓名、年齡、性別、成績(jī)等等。
遵循特定格式執(zhí)行命令并輸出你是一名翻譯助手,始終可以將用戶的提問(wèn)翻譯成英文,并輸出為一段JSON。對(duì)象中需包含兩個(gè)key,分別是origin,對(duì)應(yīng)原文,以及translated,對(duì)應(yīng)譯文。你應(yīng)該始終輸出合法的JSON對(duì)象。
下面正式開(kāi)始。
用戶輸入: ${用戶提問(wèn)占位符}
Monica是一款好用全能的AI插件
{
 “origin”: “Monica是一款好用全能的AI插件”,
 “translated”: “Monica is a versatile and easy-to-use AI plugin.”
}
問(wèn)答助手基于以下已知信息,簡(jiǎn)潔和專業(yè)的來(lái)回答用戶的問(wèn)題,不要隨意回答不存在的內(nèi)容。答案請(qǐng)使用中文。
問(wèn)題:LangChain是一個(gè)旨在簡(jiǎn)化使用大型語(yǔ)言模型創(chuàng)建應(yīng)用程序的框架。作為語(yǔ)言模型集成框架,LangChain的用例與一般語(yǔ)言模型的用例有很大的重疊,包括文檔分析和摘要,聊天機(jī)器人和代碼分析。LangChain同時(shí)支持Python與Nodejs
用戶的問(wèn)題:
${用戶提問(wèn)占位符}
你的回答:
Langchain是什么框架,支持用什么語(yǔ)言開(kāi)發(fā)?LangChain是一個(gè)旨在簡(jiǎn)化使用大型語(yǔ)言模型創(chuàng)建應(yīng)用程序的框架。它支持Python和Node.js兩種編程語(yǔ)言。

編寫(xiě)prompt的幾個(gè)要點(diǎn):

除了讓模型遵循特定指令,扮演特定功能的助手的助手外,甚至可以讓模型”思考”他應(yīng)該做什么,去決策是否要去做某些事情,在下一節(jié)Langchain的介紹中將會(huì)詳細(xì)介紹。

使用LangChain增強(qiáng)大模型能力

通過(guò)上面一節(jié)我們知道了通過(guò)prompt可以改變模型輸出的結(jié)果,使其遵循特定指令或者扮演特定功能的助手。而langchain這個(gè)框架正是利用這個(gè)特性,通過(guò)prompt的形式給予模型上下文或執(zhí)行特定的指令,通過(guò)指令使得模型可以調(diào)用模型外部接口,并從外部獲取輸入,為應(yīng)用程序賦予智能化。甚至通過(guò)agent prompt讓模型去拆解復(fù)雜任務(wù),通過(guò)選擇工具賦能連接外部接口,給予模型每一步工具分解的結(jié)果,根據(jù)結(jié)果去思考或決策解決當(dāng)前問(wèn)題每一步要做的事情,最終得出答案。

Langchain 中主要關(guān)鍵的實(shí)體:

Agents:Chains 只能采取固定的行動(dòng)(實(shí)現(xiàn)調(diào)用接口、查SQL、查文檔等等)而 Agent 可以自己決定采用什么樣的行動(dòng)、使用哪些工具,這些工具可以是搜索引擎、各類數(shù)據(jù)庫(kù)、任意的輸入或輸出的字符串,甚至是另一個(gè) LLM、Chain 和 Agent。

Langchain 內(nèi)置了非常豐富的工具,能夠使模型能夠快速地外部工具進(jìn)行對(duì)接:

在 Nodejs 上使用 LangChain

是的,LangChain 除了對(duì) python 的支持,官方也提供了 Nodejs 版本的框架,只需要 Nodejs 版本大于18即可使用。對(duì)于前端技術(shù)棧開(kāi)發(fā)人員而言,Nodejs?是再熟悉不過(guò)了,配合?Express,NestJS,全棧的?NextJS?等框架,使得我們可以很方便快捷地讓我們應(yīng)用智能起來(lái)。

安裝 LangChain

yarn add langchain
# 或者
npm i langchain

創(chuàng)建一個(gè) LLM:

import { PromptTemplate, OpenAI } from 'langchain'; 

const model = new OpenAI(); // 記得在環(huán)境變量中配置你的OpenAI Key
const resA = await model.call('為一個(gè)披薩餅餐廳起一個(gè)好的名字。');
// resA餐廳起名的結(jié)果: 維羅納披薩館
res.status(200).json({ result: resA });

創(chuàng)建一個(gè)Prompt Template:

import { PromptTemplate, OpenAI } from 'langchain'; 

const template = '為{restaurantType}餐廳起一個(gè)好的名字。';
const promptA = new PromptTemplate({ template, inputVariables: ['restaurantType'] });
const formattedPrompt = await promptA.format({
restaurantType: '四川菜',
});
// formattedPrompt: 為四川菜餐廳起一個(gè)好的名字。
// 繼續(xù)將處理好的prompt傳給模型生成結(jié)果
const resA = await model.call(formattedPrompt);
// resA: 川香居

后續(xù)僅需要改變 restaurantType ,就可以為不同類型餐館通過(guò)大模型快速起名。

使用Chains:

上面的例子還是比較簡(jiǎn)單的,下面讓我們?cè)囋噺?fù)雜的,如何通過(guò) Chain 實(shí)現(xiàn)調(diào)用外部接口,文檔的調(diào)用,并交給模型來(lái)處理。

import { OpenAI } from "langchain/llms/openai";
import { APIChain } from "langchain/chains";

// Open-Meteo是一個(gè)免費(fèi)開(kāi)源的天氣接口,OPEN_METEO_DOCS為它的接口文檔詳細(xì)描述
const OPEN_METEO_DOCS = `BASE URL: https://api.open-meteo.com/

API Documentation
The API endpoint /v1/forecast accepts a geographical coordinate, a list of weather variables and responds with a JSON hourly weather forecast for 7 days. Time always starts at 0:00 today and contains 168 hours. All URL parameters are listed below:

Parameter Format Required Default Description
latitude, longitude Floating point Yes Geographical WGS84 coordinate of the location
hourly String array No A list of weather variables which should be returned. Values can be comma separated, or multiple &hourly= parameter in the URL can be used.
daily String array No A list of daily weather variable aggregations which should be returned. Values can be comma separated, or multiple &daily= parameter in the URL can be used. If daily weather variables are specified, parameter timezone is required.
current_weather Bool No false Include current weather conditions in the JSON output.
temperature_unit String No celsius If fahrenheit is set, all temperature values are converted to Fahrenheit.
windspeed_unit String No kmh Other wind speed speed units: ms, mph and kn
precipitation_unit String No mm Other precipitation amount units: inch
timeformat String No iso8601 If format unixtime is selected, all time values are returned in UNIX epoch time in seconds. Please note that all timestamp are in GMT+0! For daily values with unix timestamps, please apply utc_offset_seconds again to get the correct date.
timezone String No GMT If timezone is set, all timestamps are returned as local-time and data is returned starting at 00:00 local-time. Any time zone name from the time zone database is supported. If auto is set as a time zone, the coordinates will be automatically resolved to the local time zone.
past_days Integer (0-2) No 0 If past_days is set, yesterday or the day before yesterday data are also returned.
start_date
end_date String (yyyy-mm-dd) No The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30).
models String array No auto Manually select one or more weather models. Per default, the best suitable weather models will be combined.

Variable Valid time Unit Description
temperature_2m Instant °C (°F) Air temperature at 2 meters above ground
snowfall Preceding hour sum cm (inch) Snowfall amount of the preceding hour in centimeters. For the water equivalent in millimeter, divide by 7. E.g. 7 cm snow = 10 mm precipitation water equivalent
rain Preceding hour sum mm (inch) Rain from large scale weather systems of the preceding hour in millimeter
showers Preceding hour sum mm (inch) Showers from convective precipitation in millimeters from the preceding hour
weathercode Instant WMO code Weather condition as a numeric code. Follow WMO weather interpretation codes. See table below for details.
snow_depth Instant meters Snow depth on the ground
freezinglevel_height Instant meters Altitude above sea level of the 0°C level
visibility Instant meters Viewing distance in meters. Influenced by low clouds, humidity and aerosols. Maximum visibility is approximately 24 km.`;

export async function run() {
const model = new OpenAI();
// 使用APIChain,
const chain = APIChain.fromLLMAndAPIDocs(model, OPEN_METEO_DOCS, {
headers: {
// These headers will be used for API requests made by the chain.
},
});

const res = await chain.call({
question:
"上海今天天氣怎么樣",
});
// The weather in Shanghai today is 33.2°C with a weather code of 1.
// 成功通過(guò)調(diào)用外部接口取得了完全真實(shí)的天氣信息
console.log({ res });
}

模型輸出結(jié)果:The weather in Shanghai today is 33.2°C with a weather code of ,成功通過(guò)調(diào)用外部接口取得了完全真實(shí)的天氣信息

如果模型不知道一件事情的上下文可能會(huì)胡編亂造,沒(méi)關(guān)系,我們把上下文喂給模型再讓他回答就可以了。只需要使用以下類似的 prompt 格式:

基于以下已知信息,簡(jiǎn)潔和專業(yè)的來(lái)回答用戶的問(wèn)題,不要隨意回答不存在的內(nèi)容。答案請(qǐng)使用中文。
截至今日(6月20日),已有多地公布了高考成績(jī)查詢時(shí)間。
快來(lái)看看你所在地區(qū)何時(shí)放榜——

貴州:成績(jī)發(fā)布時(shí)間為6月24日00:00左右。志愿填報(bào)時(shí)間為6月27日00:00到6月30日18:00。錄取時(shí)間為7月7日到8月20日。

內(nèi)蒙古:高考成績(jī)將于6月23日公布,考生可登錄內(nèi)蒙古招生考試信息網(wǎng)免費(fèi)查分。6月23日至26日,考生可申請(qǐng)復(fù)查卷面分?jǐn)?shù)。

上海:考試成績(jī)將于6月23日開(kāi)通查詢。6月24日起,考生成績(jī)通知單將按照考生高考報(bào)名表上填寫(xiě)的通信地址投遞到考生家中。

江西:考生可于6月23日查詢高考成績(jī),6月25日中午12時(shí)前可申請(qǐng)成績(jī)復(fù)核。

四川:預(yù)計(jì)6月23日公布各批次錄取控制分?jǐn)?shù)線和考生成績(jī)。

云南:預(yù)計(jì)6月23日左右擬定2023年高考錄取最低控制分?jǐn)?shù)線,提請(qǐng)?jiān)颇鲜≌猩荚囄瘑T會(huì)審定后,及時(shí)向社會(huì)公布。
// 省略很多很長(zhǎng)文本內(nèi)容...
用戶的問(wèn)題:
${用戶輸入占位符}
你的回答:
// 這里讓模型自動(dòng)填充即可

這里將一篇2023年高考剛結(jié)束的信息輸入給模型作為上下文(模型訓(xùn)練數(shù)據(jù)肯定有沒(méi)有2023年高考的信息)。當(dāng)把這篇新聞放入模型上下文之后,你咨詢它各地高考信息一定可以獲取準(zhǔn)確的信息

未接入上下文時(shí),模型給出了錯(cuò)誤的信息

接入上下文后,模型根據(jù)上下文給出了準(zhǔn)確的信息

使用向量來(lái)實(shí)現(xiàn)文本內(nèi)容召回

如果你熟悉大模型,此時(shí)的你一定發(fā)現(xiàn)這樣做其實(shí)有個(gè)很明顯的問(wèn)題,模型能接受的上下文大小是有限的。對(duì)于 ChatGPT 來(lái)說(shuō),能接受的上下文大小一般只有 4k 個(gè) token 左右( GPT4 可以做到更大,40k,但仍然需要考慮這個(gè)問(wèn)題),對(duì)于中文文本你最多只可以在 prompt 中放 2000 字左右的上下文。可以采取一個(gè)策略,那就是只將用戶提問(wèn)中最相關(guān)的內(nèi)容作為模型上下文prompt。

這個(gè)要如何實(shí)現(xiàn)?方法有很多,包括傳統(tǒng)的關(guān)鍵詞匹配,或者用 Elasticsearch 等引擎做模糊匹配都可以。下面介紹一個(gè)更AI更智能的方式:向量搜索。

什么是向量搜索?

來(lái)回憶一下NLP基礎(chǔ)知識(shí),要處理自然語(yǔ)言文本,第一件事情就是將它分詞后轉(zhuǎn)為一個(gè)個(gè)token。token的編碼實(shí)際上是代表著一種one-hot向量,維度太大了,所以要對(duì)它進(jìn)行 embedding(詞嵌入)降維,轉(zhuǎn)換為一個(gè)n維的向量。

將一段文本向量化之后每個(gè)向量可以理解為是 n 維空間中的一個(gè)點(diǎn),兩個(gè)越相似的文本它們?cè)谶@個(gè)n維空間中的距離就越近。找出距離最近的點(diǎn)的過(guò)程就可以理解為是一個(gè)向量搜索的過(guò)程。最常見(jiàn)的算法是歐氏距離計(jì)算:

歐式距離

聽(tīng)起來(lái)有些復(fù)雜是不是,其實(shí)許多已經(jīng)事先封裝好的向量搜索工具,比如來(lái)自 Facebook 的 Faiss ,開(kāi)源的Chroma等等,我們僅需了解基本概念即可,并且使用起來(lái)非常方便,僅需若干行代碼就可以實(shí)現(xiàn)向量搜索的過(guò)程。下面介紹一下使用Faiss配合Chains實(shí)現(xiàn)文本匹配召回實(shí)現(xiàn)智能問(wèn)答:

第一步:將文本分為一個(gè)個(gè)【塊】

// MarkdownTextSplitter是一個(gè)Text Splitters的實(shí)現(xiàn),用來(lái)快速對(duì)markdown或者純文本分段。
const splitter = new MarkdownTextSplitter({
chunkSize: 100, // 一個(gè)塊中最大的token數(shù)量
chunkOverlap: 50, // 相鄰塊之間重疊字符的數(shù)量。默認(rèn)值為200個(gè)Token。塊和塊之間添加重疊的文本有助于模型獲取更多上下文信息
});
// 將上下文向量化
const output = await splitter.splitText(docText);

以上面高考新聞的例子舉例,分割好的文本結(jié)果是類似以下的內(nèi)容。

const docs = [
"高考報(bào)名人數(shù)近年一直呈現(xiàn)明顯的上漲趨勢(shì),那么2023年各省高考人數(shù)是多少?2023年全國(guó)高考人數(shù)能達(dá)到多少人?2023全國(guó)參加高考人數(shù)有多少?2023年高考人數(shù)比2023年多嗎?各省市高考人數(shù)排名如何",
"到多少人?2023全國(guó)參加高考人數(shù)有多少?2023年高考人數(shù)比2023年多嗎?各省市高考人數(shù)排名如何?在本文小編整理了全國(guó)各地歷年高考人數(shù)統(tǒng)計(jì)一覽表,并附上2023年全國(guó)各地高考人數(shù)排行榜,可供同學(xué)們",
"?在本文小編整理了全國(guó)各地歷年高考人數(shù)統(tǒng)計(jì)一覽表,并附上2023年全國(guó)各地高考人數(shù)排行榜,可供同學(xué)們參考。",
// ...
]

第二步:建立向量數(shù)據(jù)庫(kù)

import { FaissStore } from 'langchain/vectorstores/faiss';
import { OpenAIEmbeddings } from 'langchain/embeddings';

const embedding = new OpenAIEmbeddings() // 使用OpenAI的embedding模型
const vectorStore = await FaissStore.fromTexts(output, metadata, embedding);

第三步:搜索匹配文本

const prompt = "湖南高考報(bào)名人數(shù)"
const topK = 3;
// 搜索最相關(guān)的topK個(gè)塊
const searchRes = await vectorStore.similaritySearchWithScore(prompt, topK);
// 匹配前3的結(jié)果:
// 2023年湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人。其中普通高考報(bào)名人數(shù)50.97萬(wàn)人,比上年增加1.27萬(wàn)人(首選物理的考生有30.93萬(wàn)人,占比60.68%;首選歷史的考生有20.04萬(wàn)人,占比39.3
// 2023年高考中,河南省的高考人數(shù)達(dá)到了125萬(wàn),成為全國(guó)高考人數(shù)最多的省份,2023四川省的高考報(bào)名人數(shù)超過(guò)77萬(wàn)人,對(duì)比去年(69.8萬(wàn))漲了7.2萬(wàn)。
// 海南三亞市參加高考報(bào)名人數(shù)共5946人,比去年增加了436人。其中普通類5170人,藝術(shù)類496人,體育類280人;應(yīng)屆生5518人(含中職生111人),往屆生428人;外省籍務(wù)工人員隨遷子女(異地

接入問(wèn)答Chain,實(shí)現(xiàn)知識(shí)庫(kù)問(wèn)答:

Langchain中內(nèi)置了StuffDocumentsChain,MapReduceDocumentsChain,這些Chain里面內(nèi)置了向量搜索以及拼接為prompt的過(guò)程。

使用下面的上下文來(lái)回答最后的問(wèn)題。如果您不知道答案,請(qǐng)直接說(shuō)不知道,不要試圖編造答案。

2023年湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人。其中普通高考報(bào)名人數(shù)50.97萬(wàn)人,比上年增加1.27萬(wàn)人(首選物理的考生有30.93萬(wàn)人,占比60.68%;首選歷史的考生有20.04萬(wàn)人,占比39.32%);對(duì)口升學(xué)考試報(bào)名人數(shù)16.69萬(wàn)人,比上年增加1.49萬(wàn)人;少年班等其他考生約0.74萬(wàn)人,與上年基本持平。

Question: 湖南高考人數(shù)是多少?
Helpful Answer:

MapReduceDocumentsChain?這種方法涉及對(duì)每個(gè)數(shù)據(jù)塊運(yùn)行初始提示(對(duì)于摘要任務(wù),這可能是該塊的摘要;對(duì)于問(wèn)答任務(wù),這可能是僅基于該塊的答案)。然后,運(yùn)行一個(gè)不同的提示來(lái)組合所有初始輸出。簡(jiǎn)單來(lái)說(shuō)就是多塊內(nèi)容總結(jié)成n塊后將這n塊內(nèi)容拼起來(lái)再總結(jié)一次。一般適用于ChatPDF等大段文本的場(chǎng)景。

使用StuffDocumentsChain實(shí)現(xiàn)問(wèn)答代碼示例:

const llmA = new OpenAI({});
const chainA = loadQAStuffChain(llmA);
const splitter = new MarkdownTextSplitter({
chunkSize: 100,
chunkOverlap: 50,
});
// 建立向量數(shù)據(jù)庫(kù)
const docs = await splitter.createDocuments([text]);

const question = '湖南高考人數(shù)是多少?';
// 調(diào)用chain,進(jìn)行向量匹配并回答用戶的提問(wèn)
const resA = await chainA.call({
input_documents: docs, // 文檔塊列表
question, // 用戶提問(wèn)
});
// resA問(wèn)答結(jié)果:上海的考生將于6月24日起收到成績(jī)通知單投遞到考生家中。

實(shí)現(xiàn)一個(gè)自己的Chains:

Langchain內(nèi)置了一些如文檔問(wèn)答Chain,數(shù)據(jù)庫(kù)Chain,APIChain一些常用的Chain。如果這些Chain不能滿足你的需求,可以自己實(shí)現(xiàn)一個(gè)Chain,繼承BaseChain實(shí)現(xiàn)其中的接口方法即可,核心就兩點(diǎn):

import { BaseChain } from "langchain/chains";

class MyCustomChain extends BaseChain {
inputKeys = ["input"];
outputKeys = ["output"];

/**
* 實(shí)現(xiàn)_call方法調(diào)用外部的接口并返回結(jié)果
*/
async _call(inputs: Record<string, any>) {
const { input } = inputs;

// 獲取輸入,并調(diào)用外部接口
const output = await someAsyncFunction(input);
return { output };
}
}

使用Agents:

Chains的流程相對(duì)較為固定,我們用一個(gè)實(shí)例來(lái)看一下Agents的能力。

要使用一個(gè)agent,需要定義一個(gè)agent,以及agent所需的tools

langchain內(nèi)部封裝了LLMChain和agent實(shí)例的創(chuàng)建為一個(gè)工作函數(shù)方法,僅需要定義所需的tools傳入到工廠函數(shù)即可獲得一個(gè)agentExecutor。

Tool Prompts:

一個(gè)Tools需要包含三個(gè)屬性:name,description_call。其中 name 和 description 共同作為 prompt 的一部分,_call 方法則是具體接受從工具 prompt 解析出來(lái)的輸入并異步返回調(diào)用外部接口的輸出。

(Langchain默認(rèn)使用的prompt都為英文,為了方便大家理解,下面展示時(shí)把 prompt 都翻譯成了中文)

一個(gè)典型的”計(jì)算器”Tool類實(shí)現(xiàn)如下

import { Parser } from "expr-eval";
import { Tool } from "./base.js";

export class Calculator extends Tool {

name = "calculator";
description = `用于計(jì)算數(shù)學(xué)表達(dá)式的工具。該工具的輸入應(yīng)該是一個(gè)可以被簡(jiǎn)單計(jì)算器執(zhí)行的有效數(shù)學(xué)表達(dá)式。
`;

/** @ignore */
async _call(input: string) {
try {
return Parser.evaluate(input).toString();
} catch (error) {
return "I don't know how to do that.";
}
}

}

這個(gè) Tool 類的 descritption 大致描述了這個(gè)工具是一個(gè)”計(jì)算器”,能夠接受表達(dá)式的輸入并且返回計(jì)算結(jié)果。在使用agents時(shí),模型會(huì)根據(jù)情況智能地選擇需要執(zhí)行的工具。

agents 會(huì)遍歷所有注冊(cè)的 tools,拼接成下面這種格式的 prompt:

請(qǐng)盡力回答用戶的問(wèn)題,你可以使用以下工具:

vector-search:一個(gè)知識(shí)搜索工具,當(dāng)需要從信息中提取你需要的信息時(shí),使用這個(gè)工具。若不能直接獲取到有用的信息,請(qǐng)嘗試進(jìn)行分解。
calculator:用于計(jì)算數(shù)學(xué)表達(dá)式的工具。該工具的輸入應(yīng)該是一個(gè)可以被簡(jiǎn)單計(jì)算器執(zhí)行的有效數(shù)學(xué)表達(dá)式。

Agent prompts:

有了Tools,該用何種Prompt去提示模型執(zhí)行何種任務(wù)?在上面的工具prompt基礎(chǔ)上我們繼續(xù)拼接以下格式的prompt:

請(qǐng)盡力回答用戶的問(wèn)題,你可以使用以下工具:

vector-search:一個(gè)知識(shí)搜索工具,當(dāng)需要從信息中提取你需要的信息時(shí),使用這個(gè)工具。若不能直接獲取到有用的信息,請(qǐng)嘗試進(jìn)行分解。
calculator:用于計(jì)算數(shù)學(xué)表達(dá)式的工具。該工具的輸入應(yīng)該是一個(gè)可以被簡(jiǎn)單計(jì)算器執(zhí)行的有效數(shù)學(xué)表達(dá)式。

請(qǐng)使用以下格式回答問(wèn)題:
Question: 用戶的提問(wèn)
Thought: 你應(yīng)該思考如何回答這個(gè)問(wèn)題
Action: 選擇一個(gè)適當(dāng)?shù)墓ぞ邅?lái)回答問(wèn)題,應(yīng)該是以下其中一個(gè):[vector-search, calculator]
Action Input: 輸入到工具中的內(nèi)容
Observation: 工具返回的結(jié)果
... (Thought/Action/Action Input/Observation可以重復(fù)N次)
Thought: 我現(xiàn)在知道最終答案了
Final Answer: 原始問(wèn)題的最終答案是什么

通過(guò)這一段神奇的 prompt ,模型就能夠進(jìn)行思考并選擇該用什么工具去解決,并將它的中間思考過(guò)程添加到 prompt 當(dāng)中去。模型會(huì)不斷地思考–選擇工具–觀察運(yùn)行結(jié)果,直到可以得出最后的答案。

Agents 實(shí)際例子:

下面讓我們用一個(gè)實(shí)例來(lái)展示一下 Agents 拆解任務(wù),逐步獲取結(jié)果的過(guò)程。假設(shè)我們的任務(wù)是從一篇新聞中求出甘肅省加湖南省高考人數(shù)數(shù)量是多少。

獲取數(shù)據(jù)并進(jìn)行向量化:

新聞的原始文本使用這篇新聞:https://www.sohu.com/a/681224993_99946287,將這篇新聞的文本下載下來(lái)并保存為文本,之后通過(guò)VectorStoreQATool進(jìn)行向量化。

定義兩個(gè) Tools :

vector-search: 一個(gè)知識(shí)搜索工具,當(dāng)需要從信息中提取你需要的信息時(shí),使用這個(gè)工具。若不能直接獲取到有用的信息,請(qǐng)嘗試進(jìn)行分解。

calculator: 用于計(jì)算數(shù)學(xué)表達(dá)式的工具。該工具的輸入應(yīng)該是一個(gè)可以被簡(jiǎn)單計(jì)算器執(zhí)行的有效數(shù)學(xué)表達(dá)式。

創(chuàng)建一個(gè) agents ,并執(zhí)行:

// 創(chuàng)建向量數(shù)據(jù)庫(kù)
const vectorStore = await FaissStore.fromTexts(output, output, embedding);

// langchain內(nèi)置的VectorStoreQATool沒(méi)有提供prompt,這里手動(dòng)提供
const vecToolName = 'vector-search';
const vecToolDescription = '一種知識(shí)搜索工具,用于從大量信息中提取所需信息。如果無(wú)法直接獲得有用信息,請(qǐng)嘗試將其分解。';
const tools = [
// 向量搜索工具
new VectorStoreQATool(vecToolName, vecToolDescription, {
llm: llmA,
vectorStore,
}),
// 計(jì)算器工具
new Calculator(),
];
// 創(chuàng)建agent執(zhí)行器
const executor = await initializeAgentExecutorWithOptions(tools, llmA, {
agentType: 'zero-shot-react-description',
verbose: true,
});

// 用戶提問(wèn)
const input = '湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)的結(jié)果';
// 結(jié)果: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)結(jié)果為931848
const result = await executor.call({ input });

經(jīng)過(guò)約十幾秒的執(zhí)行,最后成功獲取了正確的結(jié)果:湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)結(jié)果為931848

這十幾秒當(dāng)中發(fā)生了什么?來(lái)拆解一下發(fā)送給模型的 prompt :

第一步初始狀態(tài),Agent 使用了以下 prompt:

請(qǐng)盡力回答以下問(wèn)題,你可以使用以下工具:

vector-search:一個(gè)知識(shí)搜索工具,當(dāng)需要從信息中提取你需要的信息時(shí),使用這個(gè)工具。若不能直接獲取到有用的信息,請(qǐng)嘗試進(jìn)行分解。
calculator:用于計(jì)算數(shù)學(xué)表達(dá)式的工具。該工具的輸入應(yīng)該是一個(gè)可以被簡(jiǎn)單計(jì)算器執(zhí)行的有效數(shù)學(xué)表達(dá)式。

請(qǐng)使用以下格式回答問(wèn)題:
Question: 用戶的提問(wèn)
Thought: 你應(yīng)該思考如何回答這個(gè)問(wèn)題
Action: 選擇一個(gè)適當(dāng)?shù)墓ぞ邅?lái)回答問(wèn)題,應(yīng)該是以下其中一個(gè):[vector-search, calculator]
Action Input: 輸入到工具中的內(nèi)容
Observation: 工具返回的結(jié)果
... (Thought/Action/Action Input/Observation可以重復(fù)N次)
Thought: 我現(xiàn)在知道最終答案了
Final Answer: 原始問(wèn)題的最終答案是什么

開(kāi)始!
Question: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)的結(jié)果,用中文回答
Thought:

上面的 prompt 讓模型思考第一個(gè)所需要的工具,并將思考過(guò)程放置在 Thought 之后,隨后選擇合適的工具和解析所需的工具輸入 Action Input ,在這里模型的選擇是知識(shí)庫(kù)搜索工具,并且工具的輸入應(yīng)該為湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù):

Thought: 我需要找到湖南和甘肅的高考報(bào)名人數(shù)
Action: vector-search
Action Input: 湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù)

第二步:提取關(guān)聯(lián)文本:

使用 vector-search 配合向量搜索,提取關(guān)聯(lián)的文本并讓模型提取總結(jié)信息:

使用下面的上下文來(lái)回答最后的問(wèn)題。如果你不知道答案,只需說(shuō)你不知道,不要試圖編造答案。

高考報(bào)名人數(shù)近年一直呈現(xiàn)明顯的上漲趨勢(shì),那么2023年各省高考人數(shù)是多少?2023年全國(guó)高考人數(shù)能達(dá)到多少人?2023全國(guó)參加高考人數(shù)有多少?2023年高考人數(shù)比2023年多嗎?各省市高考人數(shù)排名如何?在本文小編整理了全國(guó)各地歷年高考人數(shù)統(tǒng)計(jì)一覽表,并附上2023年全國(guó)各地高考人數(shù)排行榜,可供同學(xué)們參考。
2023年湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人。其中普通高考報(bào)名人數(shù)50.97萬(wàn)人,比上年增加1.27萬(wàn)人(首選物理的考生有30.93萬(wàn)人,占比60.68%;首選歷史的考生有20.04萬(wàn)人,占比39.32%);對(duì)口升學(xué)考試報(bào)名人數(shù)16.69萬(wàn)人,比上年增加1.49萬(wàn)人;少年班等其他考生約0.74萬(wàn)人,與上年基本持平。
2023年甘肅省高考報(bào)名人數(shù)共計(jì)247848人,比去年增加4600人。其中,參與普通高考考場(chǎng)編排考生196678人,共設(shè)置15個(gè)考區(qū),195個(gè)考點(diǎn),6967個(gè)考場(chǎng)。不參與統(tǒng)一高考考場(chǎng)編排考生51170人,包括高等職業(yè)教育分類考試招生綜合評(píng)價(jià)錄取23068人,中職升學(xué)考試 27965人、消防單招68人,殘障生(不參加全國(guó)統(tǒng)考)44人,單設(shè)考場(chǎng)25人。
廣東省汕頭市公布了2023年高考報(bào)名人數(shù),2023年高考報(bào)名人數(shù)為:5.4萬(wàn)人,相比2023年增加了5000人+,報(bào)名人數(shù)上漲10%。
海南三亞市參加高考報(bào)名人數(shù)共5946人,比去年增加了436人。其中普通類5170人,藝術(shù)類496人,體育類280人;應(yīng)屆生5518人(含中職生111人),往屆生428人;外省籍務(wù)工人員隨遷子女(異地高考)645人,占報(bào)考人數(shù)的10.8%。
今年江西省近54萬(wàn)名考生報(bào)名高考。

Question: 湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù)
Helpful Answer:

此處 Helpful Answer 由模型總結(jié)的內(nèi)容:湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人,甘肅高考報(bào)名人數(shù)共計(jì)247848人。

第三步:獲取了人數(shù)相關(guān)必要信息之后,模型會(huì)智能地選擇調(diào)用計(jì)算器工具:

Question: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)的結(jié)果,用中文回答
Thought: 我需要找到湖南和甘肅的高考報(bào)名人數(shù)
Action: vector-search
Action Input: 湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù)
Observation: 湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人,甘肅高考報(bào)名人數(shù)共計(jì)247848人。
Thought: 我現(xiàn)在知道了湖南和甘肅的高考報(bào)名人數(shù),可以使用計(jì)算器計(jì)算出最終結(jié)果
Action: calculator
Action Input: 68.4萬(wàn)人 + 247848

此處會(huì)調(diào)用 Caculator 實(shí)例中的 _call 方法,將68.4萬(wàn)人 + 247848傳入到計(jì)算器工具中并執(zhí)行Parser.evaluate(input);代碼,由此獲取表達(dá)式準(zhǔn)確的計(jì)算結(jié)果。

很明顯,68.4萬(wàn)人 + 247848不是一個(gè)合法的表達(dá)式,在代碼捕獲異常之后返回模型 I don’t know how to do that,讓模型嘗試糾錯(cuò)

Question: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)的結(jié)果,用中文回答
Thought: 我需要找到湖南和甘肅的高考報(bào)名人數(shù)
Action: vector-search
Action Input: 湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù)
Observation: 湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人,甘肅高考報(bào)名人數(shù)共計(jì)247848人。
Thought: 我現(xiàn)在知道了湖南和甘肅的高考報(bào)名人數(shù),可以使用計(jì)算器計(jì)算出最終結(jié)果
Action: calculator
Action Input: 68.4萬(wàn)人 + 247848
Observation: I don't know how to do that.
Thought:我需要將數(shù)字轉(zhuǎn)換為計(jì)算器可以理解的格式。
Action: calculator
Action Input: 684000 + 247848

在這一輪思考中,模型添加了思考內(nèi)容并嘗試糾正表達(dá)式:我需要將數(shù)字轉(zhuǎn)換為計(jì)算器可以理解的格式。并把剛才錯(cuò)誤的表達(dá)式成功糾正為正確的表達(dá)式 684000 + 247848。

第四步:模型認(rèn)為所有必要信息都獲取到了,總結(jié)輸出答案:

Question: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)的結(jié)果,用中文回答
Thought: 我需要找到湖南和甘肅的高考報(bào)名人數(shù)
Action: vector-search
Action Input: 湖南高考報(bào)名人數(shù), 甘肅高考報(bào)名人數(shù)
Observation: 湖南高考報(bào)名人數(shù)共有68.4萬(wàn)人,甘肅高考報(bào)名人數(shù)共計(jì)247848人。
Thought: 我現(xiàn)在知道了湖南和甘肅的高考報(bào)名人數(shù),可以使用計(jì)算器計(jì)算出最終結(jié)果
Action: calculator
Action Input: 68.4萬(wàn)人 + 247848
Observation: I don't know how to do that.
Thought: 我需要將數(shù)字轉(zhuǎn)換為計(jì)算器可以理解的格式。
Action: calculator
Action Input: 684000 + 247848
Observation: 931848.
Thought: 我現(xiàn)在知道了最終結(jié)果
Final Answer: 湖南高考報(bào)名人數(shù)加上甘肅高考報(bào)名人數(shù)結(jié)果為931848

以上模型拆解任務(wù),選擇工具的步驟總結(jié)如下:

至此,以上通過(guò)大模型+多輪 agent prompt,在經(jīng)過(guò)了工具的選擇,生成工具輸入,執(zhí)行外部工具,智能糾錯(cuò)等步驟之后,讓模型有依有據(jù)地進(jìn)行多步思考調(diào)用外部工具并解決問(wèn)題,并得出準(zhǔn)確的答案。

總結(jié):

通過(guò)上面章節(jié),介紹了大模型的缺陷、prompt 的能力、Langchain 框架核心概念,以及在 Nodejs 中 LLM 、Prompt Template、Chains、Agent 等方法的實(shí)踐,使得模型有連接外部世界的能力。

Langchain看似很強(qiáng)大,但實(shí)際上開(kāi)發(fā)過(guò)程中,還是會(huì)有以下幾點(diǎn)挑戰(zhàn):

但總體來(lái)說(shuō) Langchain 可以以較低的成本快速地讓模型實(shí)現(xiàn)真正的多模態(tài)執(zhí)行多種外部任務(wù),并且非常易于接入使用,無(wú)需太多的AI相關(guān)知識(shí)就可使實(shí)現(xiàn)應(yīng)用的智能化。

本文章轉(zhuǎn)載微信公眾號(hào)@稀土掘金技術(shù)社區(qū)

上一篇:

掌握如何搭建高效的大模型任務(wù)流(一):LangChain任務(wù)流構(gòu)建

下一篇:

5分鐘掃盲chatGPT與OpenAI編程(for 開(kāi)發(fā)者)
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)