中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

油金地 做網(wǎng)站品牌推廣營銷平臺

油金地 做網(wǎng)站,品牌推廣營銷平臺,代辦網(wǎng)站備案,坪山網(wǎng)站建設(shè)設(shè)計(jì)大模型能理解自然語言,從而能解決問題,但是就像人類大腦一樣,大腦只能發(fā)送指令,實(shí)際行動得靠四肢,所以LangChain4j提供的Tools機(jī)制就是大模型的四肢。 大模型的不足 大模型在解決問題時(shí),是基于互聯(lián)網(wǎng)上很…

大模型能理解自然語言,從而能解決問題,但是就像人類大腦一樣,大腦只能發(fā)送指令,實(shí)際行動得靠四肢,所以LangChain4j提供的Tools機(jī)制就是大模型的四肢。

大模型的不足

大模型在解決問題時(shí),是基于互聯(lián)網(wǎng)上很多歷史資料進(jìn)行預(yù)測的,而且答案具有一定的隨機(jī)性,那如果我問"今天是幾月幾號?",大模型是大概率答錯(cuò)的,因?yàn)榇竽P涂隙ㄟ€沒有來得及學(xué)習(xí)今天所產(chǎn)生的最新資料。

比如:

package com.timi;import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;public class _04_Toos {public static void main(String[] args) {ChatLanguageModel model = OpenAiChatModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();System.out.println(model.generate("今天是幾月幾號?"));}
}

代碼執(zhí)行結(jié)果為:

今天是十二月十九號。

多執(zhí)行幾次,每次執(zhí)行結(jié)果很有可能不一樣,所以如果要求大模型處理時(shí)間相關(guān)的問題,它就無能為力了。

因此,我們擴(kuò)展一下,出現(xiàn)這種情況的原因是ChatGPT是基于歷史數(shù)據(jù)來進(jìn)行預(yù)測的,它沒辦法拿到當(dāng)前最新的數(shù)據(jù),比如說時(shí)間,從而限制了它的進(jìn)一步使用,那么LangChain4j的Tools機(jī)制就能夠幫助大模型來獲取當(dāng)前最新的數(shù)據(jù),從而解決上述時(shí)間相關(guān)的問題。

由于LangChain4j提供的"demo"不支持Tools機(jī)制,需要大家自行獲取OpenAI的ApiKey,或者找一些OpenAI的代理來間接的調(diào)用OpenAI的API。

ToolSpecification

首先需要定義一個(gè)工具,其實(shí)就是一個(gè)方法,用來返回當(dāng)前日期,并且通過@Tool注解來描述該工具,從而使得大模型在需要獲取當(dāng)前時(shí)間時(shí)能夠調(diào)用該工具方法得到當(dāng)前時(shí)間:

@Tool("獲取當(dāng)前日期")
public static String dateUtil(){return LocalDateTime.now().toString();
}

然后將工具方法轉(zhuǎn)成ToolSpecification對象,并傳遞給大模型:

package com.timi;import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.agent.tool.ToolSpecifications;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.Response;import java.time.LocalDateTime;
import java.util.Collections;public class _04_Tools {@Tool("獲取當(dāng)前日期")public static String dateUtil(){return LocalDateTime.now().toString();}public static void main(String[] args) throws NoSuchMethodException {ChatLanguageModel model = OpenAiChatModel.builder().baseUrl("http://localhost:3000/v1").apiKey("sk-peszVtFXoLnWK45bB15370Df6f344cAa9a088eF50f9c7302").build();ToolSpecification toolSpecification = ToolSpecifications.toolSpecificationFrom(_04_Tools.class.getMethod("dateUtil"));UserMessage userMessage = UserMessage.from("今天是幾月幾號?");Response<AiMessage> response = model.generate(Collections.singletonList(userMessage), toolSpecification);System.out.println(response.content());}
}

所以,一個(gè)ToolSpecification對象就代表一個(gè)工具,當(dāng)用戶把要問題UserMessage和工具ToolSpecification一起傳遞給大模型,大模型就知道要結(jié)合工具描述來解決用戶的問題,此時(shí)大模型響應(yīng)的AiMessage不再是一串文本,而是:

AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_IPiiRjIM5PmVdDWjpXcUN5c7", name = "dateUtil", arguments = "{}" }] }

一個(gè)ToolExecutionRequest,表示一個(gè)工具執(zhí)行請求,表示大模型在解決問題時(shí),需要調(diào)用工具來解決用戶的問題,由于我們可能傳了多個(gè)工具給大模型,所以toolExecutionRequests是一個(gè)List,表示為了解決用戶的問題需要調(diào)用哪些工具。

所以,我們在得到了ToolExecutionRequest后,就需要取執(zhí)行對應(yīng)的工具方法了,其中ToolExecutionRequest的name屬性就是方法名,arguments就表示要傳遞給方法的參數(shù)值:

Response<AiMessage> response = model.generate(Collections.singletonList(userMessage), toolSpecification);AiMessage aiMessage = response.content();
if (aiMessage.hasToolExecutionRequests()) {for (ToolExecutionRequest toolExecutionRequest : aiMessage.toolExecutionRequests()) {String methodName = toolExecutionRequest.name();Method method = _04_Tools.class.getMethod(methodName);// result就是當(dāng)前時(shí)間String result = (String) method.invoke(null);System.out.println(result);}
}

此時(shí)的輸出結(jié)果為:

2024-03-24T11:37:02.618942

這就是大模型想要的當(dāng)前時(shí)間,相當(dāng)于是ToolExecutionRequest的響應(yīng)結(jié)果,那我們該如何把這個(gè)響應(yīng)結(jié)果告訴給大模型,從而讓大模型告訴我“今天是幾月幾號?”呢?

前面在介紹ChatMessage類型時(shí),除開有UserMessage、AiMessage、SystemMessage之外,還有一種類型就是ToolExecutionResultMessage,因此ToolExecutionResultMessage就表示工具執(zhí)行結(jié)果,所以我們把工具的執(zhí)行結(jié)果封裝為ToolExecutionResultMessage即可:

ToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from(toolExecutionRequest.id(), toolExecutionRequest.name(), result);

然后使用歷史對話的思想,把以上用戶和大模型之間涉及到的ChatMessage按順序添加到List中發(fā)送給大模型即可:

ToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from(toolExecutionRequest.id(), toolExecutionRequest.name(), result);AiMessage message = model.generate(Lists.newArrayList(userMessage, aiMessage, toolExecutionResultMessage)).content();
System.out.println(message.text());

這樣大模型就能正確的告訴當(dāng)前時(shí)間了:

今天是2024324日。

AiServices整合Tools

以上使用Tools的方式有點(diǎn)復(fù)雜,如果大模型要解決一個(gè)復(fù)雜問題需要調(diào)用多個(gè)工具或多輪工具調(diào)用,以上代碼就更不合適了,而AiServices能簡化這個(gè)過程。

假如有這么一個(gè)需求:獲取今天注冊的所有新用戶信息,對于這個(gè)需求我們可以這么來實(shí)現(xiàn)。

首先定義一個(gè)User對象:

static class User {private String username;private Integer age;public User(String username, Integer age) {this.username = username;this.age = age;}
}

然后定義兩個(gè)Tools:

static class MyTools {@Tool("獲取當(dāng)前日期")public static String dateUtil(String onUse) {return LocalDateTime.now().toString();}@Tool("獲取指定日期注冊的用戶信息")public static List<User> getUserInfo(String date) {System.out.println("接收到的date參數(shù)的值:" + date);User user1 = new User("司馬懿", 18);User user2 = new User("曹操", 18);return Lists.newArrayList(user1, user2);}
}

一個(gè)用來獲取當(dāng)前時(shí)間,一個(gè)接收當(dāng)前時(shí)間并返回用戶信息。

再定義一個(gè)UserService接口:

interface UserService {@SystemMessage("先獲取具體日期,然后再解決用戶問題")String getUserInfo(String desc);
}

然后利用AiServices創(chuàng)建UserService接口的代理對象:

public static void main(String[] args) {ChatLanguageModel model = ZhipuAiChatModel.builder().apiKey("0f4d2b0e8d95f48e6e1f138b881d0a53.UkIov25cJBSvjFDo").build();UserService userService = AiServices.builder(UserService.class).chatLanguageModel(model).tools(new MyTools()).chatMemory(MessageWindowChatMemory.withMaxMessages(10)).build();String userInfo = userService.getUserInfo("獲取今天的注冊的新用戶信息");System.out.println(userInfo);}

并執(zhí)行g(shù)etUserInfo()方法,傳入你的描述信息就可以獲取到User信息了。比如以上代碼的執(zhí)行結(jié)果為:

接收到的date參數(shù)的值:2024-04-21
2024420日注冊的用戶有司馬懿和曹操,他們的年齡都是18歲。

源碼分析

在代理對象的invoke()方法中,以下代碼會去調(diào)用大模型的底層API:

Response<AiMessage> response = context.toolSpecifications == null? context.chatModel.generate(messages): context.chatModel.generate(messages, context.toolSpecifications);

當(dāng)指定了Tools時(shí),就會調(diào)用context.chatModel.generate(messages, context.toolSpecifications),我們debug來看下返回結(jié)果:
image.png
第一次響應(yīng)是一個(gè)ToolExecutionRequest工具執(zhí)行請求,name為"now",表示要執(zhí)行now()方法,也就是獲取當(dāng)前時(shí)間,然后會執(zhí)行如下代碼:

for (ToolExecutionRequest toolExecutionRequest : aiMessage.toolExecutionRequests()) {// 執(zhí)行工具ToolExecutor toolExecutor = context.toolExecutors.get(toolExecutionRequest.name());// 工具執(zhí)行結(jié)果String toolExecutionResult = toolExecutor.execute(toolExecutionRequest, memoryId);// 把工具執(zhí)行請求和結(jié)果封裝為ToolExecutionResultMessageToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from(toolExecutionRequest,toolExecutionResult);// 添加到ChatMemory中chatMemory.add(toolExecutionResultMessage);
}

然后執(zhí)行以下代碼,再次請求大模型,此時(shí)ChatMemory中包含了第一次工具請求的結(jié)果:

response = context.chatModel.generate(chatMemory.messages(), context.toolSpecifications);

這一次得到的響應(yīng)是:
image.png
仍然是一個(gè)工具執(zhí)行請求,只不過方法時(shí)getUserInfo()方法,并且入?yún)樯弦徊焦ぞ哒{(diào)用的結(jié)果,然后和上面類似,處理該工具執(zhí)行請求,也就是執(zhí)行g(shù)etUserInfo()方法得到工具執(zhí)行結(jié)果,同樣再次把第二次的工具執(zhí)行請求和結(jié)果封裝為ToolExecutionResultMessage,并添加到ChatMemory中,此時(shí)ChatMemory中的內(nèi)容為:
image.png
依次為:用戶的問題、第一次工具執(zhí)行請求和結(jié)果、第二次工具執(zhí)行請求和結(jié)果。

把最終的ChatMemory發(fā)送給大模型之后,大模型就知道了今天注冊的新用戶信息有哪些了,就會把結(jié)果返回給你:
image.png
基于此,我們其實(shí)打通了大模型和我們系統(tǒng)內(nèi)部數(shù)據(jù)之間的橋梁,使得大模型能夠調(diào)用我們提供的工具來獲取系統(tǒng)內(nèi)部的最新數(shù)據(jù),而我們可以更進(jìn)一步讓大模型基于這些數(shù)據(jù)來做更智能的事情,比如:

需求改為:“獲取今天注冊的新用戶信息,然后基于這些用戶發(fā)送一份郵件”,我們只需要再定義一個(gè)發(fā)送郵件Tool就可以了:

@Tool("給指定用戶發(fā)送郵件")
public void email(String user) {System.out.println("發(fā)送郵件:" + user);
}

然后:

List<User> users = userService.getUserInfo("獲取今天注冊的新用戶信息,然后基于這些用戶發(fā)送一份郵件");

代碼執(zhí)行結(jié)果為:

接收到的date參數(shù)的值:2024-04-21
發(fā)送郵件:司馬懿,曹操
今天注冊的用戶有司馬懿和曹操,已經(jīng)給他們發(fā)送了一份郵件。

通過這個(gè)Demo,我們發(fā)現(xiàn),我們可以利用自然語言來整合各項(xiàng)系統(tǒng)功能,這將是一種新的編程模式:自然語言編程。

本節(jié)總結(jié)

本節(jié)我們學(xué)習(xí)了LangChain4j中的Tools機(jī)制,通過Tools機(jī)制可以通過自然語言整合大模型和系統(tǒng)內(nèi)部功能,使得大模型這個(gè)智能大腦擁有了靈活的四肢,從而可以處理更復(fù)雜的場景,同時(shí)也感受到了自然語言編程離我們越來越近了,下一節(jié)我們將學(xué)習(xí)文本向量化以及向量模型、向量數(shù)據(jù)庫,這是檢索增強(qiáng)生成(RAG)的基礎(chǔ)。

http://m.risenshineclean.com/news/65604.html

相關(guān)文章:

  • 音樂盒的網(wǎng)站怎么做代寫稿子的平臺
  • 深圳建站公司模板網(wǎng)絡(luò)營銷公司排行
  • 怎么制作app網(wǎng)站千萬不要去電商公司上班
  • 制作網(wǎng)站公司年收入多少百度指數(shù)關(guān)鍵詞未收錄怎么辦
  • 平安做計(jì)劃書的網(wǎng)站人力資源培訓(xùn)
  • 網(wǎng)站建設(shè)公司專業(yè)的建站優(yōu)化公司百度seo怎么優(yōu)化
  • 每月網(wǎng)站流量網(wǎng)絡(luò)營銷常用的工具
  • 加關(guān)鍵詞的網(wǎng)站石家莊網(wǎng)站seo外包
  • 上海網(wǎng)站企業(yè)軟文推廣是什么
  • 網(wǎng)站后期維護(hù)收費(fèi)熱門網(wǎng)站排名
  • 貿(mào)易網(wǎng)站建設(shè)sem投放是什么意思
  • 網(wǎng)頁制作工具的選擇與網(wǎng)站整體風(fēng)格網(wǎng)絡(luò)廣告推廣服務(wù)
  • 老司機(jī)做爰網(wǎng)站老師影音百度托管運(yùn)營哪家好
  • 家裝設(shè)計(jì)師培訓(xùn)學(xué)校湖南企業(yè)seo優(yōu)化推薦
  • 新手做網(wǎng)站做什么樣的網(wǎng)站建設(shè)公司哪個(gè)好呀
  • 怎么在微信做企業(yè)網(wǎng)站app開發(fā)費(fèi)用標(biāo)準(zhǔn)
  • 有哪些設(shè)計(jì)的很優(yōu)秀的網(wǎng)站企業(yè)培訓(xùn)內(nèi)容
  • 沈陽智能模板建站軟文營銷范文100字
  • 武漢軟件100強(qiáng)企業(yè)名單北京官方seo搜索引擎優(yōu)化推薦
  • 資陽網(wǎng)站設(shè)計(jì)搜狗搜索網(wǎng)
  • 互聯(lián)網(wǎng)行業(yè) 英文郴州seo網(wǎng)絡(luò)優(yōu)化
  • 濟(jì)南做網(wǎng)站多少錢站長工具pr值查詢
  • 全免費(fèi)云游戲網(wǎng)頁在線玩seo快速排名軟件價(jià)格
  • 東莞seo網(wǎng)站推廣個(gè)人怎么做免費(fèi)百度推廣
  • 重慶網(wǎng)站建設(shè)有限公司拼多多運(yùn)營
  • 網(wǎng)站運(yùn)營模式有哪些短網(wǎng)址鏈接生成
  • 現(xiàn)在最靠譜的購物網(wǎng)站有哪些天津seo實(shí)戰(zhàn)培訓(xùn)
  • 網(wǎng)站開發(fā)師培訓(xùn)網(wǎng)絡(luò)營銷手段有哪四種
  • 深圳網(wǎng)站開發(fā)優(yōu)化營商環(huán)境 助推高質(zhì)量發(fā)展
  • 建設(shè)一個(gè)網(wǎng)站需要提供什么手續(xù)seo網(wǎng)絡(luò)推廣專員