大語言模型的應用探索AI Agent初探!

前言

大語言模型的應用之一是與大語言模型進行聊天也就是一個ChatBot,這個應用已經很廣泛了。

接下來的一個應用就是AI Agent。

AI Agent是人工智能代理(Artificial Intelligence Agent)的概念,它是一種能夠感知環境、進行決策和執行動作的智能實體,通常基于機器學習和人工智能技術,具備自主性和自適應性,在特定任務或領域中能夠自主地進行學習和改進。一個更完整的Agent,一定是與環境充分交互的,它包括兩部分——一是Agent的部分,二是環境的部分。此刻的Agent就如同物理世界中的「人類」,物理世界就是人類的「外部環境」。

image-20240708160424399

效果

今天就基于開源的大語言模型Qwen2-7B-Instruct與開源的LLM應用框架SenmanticKernel實現我們的第一個AI Agent!

入門先從一個簡單的例子入手,比如叫大語言模型將字符串打印至控制臺。

在ChatBox應用中,我們叫大語言模型將字符串打印至控制臺,它的回答可能是這樣子的:

image-20240708161150957

而在簡易的AI Agent應用中,大語言模型會幫我們完成這項簡單的任務。

image-20240708161449438

image-20240708161514177

又比如,我們需要從數據庫中檢索信息,假設需要檢索的信息如下所示:

 List<Order> Orders = new List<Order>(){new Order(){Id=1,Name="iPhone15",Address="武漢"},new Order(){Id=2,Name="iPad",Address="北京"},new Order(){Id=3,Name="MacBook",Address="上海"},new Order(){Id=4,Name = "HuaWei Mate60 ",Address = "深圳"},new Order(){Id = 5,Name = "小米14",Address = "廣州"}};

在ChatBox應用中,我們如果問Id為1的訂單信息是什么?大語言模型是不會知道我們想干什么的,回答可能如下所示:

image-20240708162121671

而在簡易的AI Agent應用中,AI回答如下:

image-20240708162335212

image-20240708162418992

實踐

上一篇文章講過,在SemanticKernel中OpenAI支持Function Call的模型與月之暗面支持Function Call的模型,只需進行簡單的設置即可實現自動函數調用,但我嘗試了其他開源的模型,發現做不到。

通過github了解到,其他的模型可以通過提示工程來實現本地函數調用。

什么是提示工程?

提示工程(Prompt Engineering)是一種自然語言處理(NLP)技術,主要應用于生成式AI模型,如GPT-3等。它通過精心設計輸入提示(prompt),引導模型生成特定類型的輸出。在提示工程中,用戶可以控制模型的輸出內容、風格和格式,以滿足不同的應用場景需求。

提示工程的關鍵在于設計有效的提示,這通常需要對模型的能力和限制有深入的了解。通過調整提示的結構、語言和上下文,可以顯著提高模型生成結果的質量和相關性。在實際應用中,提示工程可以用于文本生成、問答、翻譯、摘要、對話系統等多個領域。

上面兩個簡單的AI Agent應用實現的原理是一樣的,選擇第二個獲取訂單的引用進行講解。

實現的方法來自上一篇博客提到的項目:

Jenscaasen/UniversalLLMFunctionCaller: A planner that integrates into Semantic Kernel to enable function calling on all Chat based LLMs (Mistral, Bard, Claude, LLama etc) (github.com)

在kernel中導入插件:

public sealed class OrderPlugin
{List<Order> Orders = new List<Order>(){new Order(){Id=1,Name="iPhone15",Address="武漢"},new Order(){Id=2,Name="iPad",Address="北京"},new Order(){Id=3,Name="MacBook",Address="上海"},new Order(){Id=4,Name = "HuaWei Mate60 ",Address = "深圳"},new Order(){Id = 5,Name = "小米14",Address = "廣州"}};[KernelFunction, Description("根據Id獲取訂單")][return: Description("獲取到的訂單")]public string GetOrderById([Description("訂單的Id")] int id){var order = Orders.Where(x => x.Id == id).FirstOrDefault();if(order != null){return order.ToString();}else{return "找不到該Id的訂單";}}
}
_kernel.ImportPluginFromType<OrderPlugin>("Order");
 UniversalLLMFunctionCaller planner = new(_kernel);string result = await planner.RunAsync(AskText);

重點在planner.RunAsync中。

導入為了實現目的內置的插件:

 // Initialize pluginsvar plugins = _kernel.Plugins;var internalPlugin = _kernel.Plugins.AddFromType<UniversalLLMFunctionCallerInternalFunctions>();

UniversalLLMFunctionCallerInternalFunctions插件如下:

    internal class UniversalLLMFunctionCallerInternalFunctions{//   [KernelFunction, Description("Call this when the workflow is done and there are no more functions to call")]//   public string Finished(//  [Description("Wrap up what was done and what the result is, be concise")] string finalmessage//)//   {//       return string.Empty;//       //no actual implementation, for internal routing only//   }[KernelFunction, Description("當工作流程完成,沒有更多的函數需要調用時,調用這個函數")]public string Finished([Description("總結已完成的工作和結果,盡量簡潔明了。")] string finalmessage){return string.Empty;//no actual implementation, for internal routing only}//[KernelFunction, Description("Gets the name of the spaceship of the user")]//public string GetMySpaceshipName()//{//    return "MSS3000";//}[KernelFunction, Description("獲取用戶飛船的名稱")]public string GetMySpaceshipName(){return "嫦娥一號";}//   [KernelFunction, Description("Starts a Spaceship")]//   public void StartSpaceship(//  [Description("The name of the spaceship to start")] string ship_name//)//   {//       //no actual implementation, for internal routing only//   }[KernelFunction, Description("啟動飛船")]public void StartSpaceship([Description("啟動的飛船的名字")] string ship_name){//no actual implementation, for internal routing only}}
}

我將英文原版注釋掉并增加了一個中文的版本。

將插件轉化為文本:

// Convert plugins to text
string pluginsAsText = GetTemplatesAsTextPrompt3000(plugins);

image-20240708163921817

獲取到了插件中所有本地函數的信息。

nextFunctionCall = await GetNextFunctionCallAsync(chatHistory, pluginsAsText);

讓大語言模型獲取下一次需要調用的函數。

在對話示例中加入一個提示,這個提示是關鍵!

image-20240708164508312

英文原版如下:

        private string GetLoopSystemMessage(string pluginsAsTextPrompt3000){string systemPrompt = $@"You are a computer system. You can only speak TextPrompt3000 to make the user call functions, and the user will behaveas a different computer system that answers those functions.Below, you are provided a goal that needs to be reached, as well as a list of functions that the user could use.You need to find out what the next step for the user is to reach the goal and recommend a TextPrompt3000 function call. You are also provided a list of functions that are in TextPrompt3000 Schema Format.The TextPrompt3000 Format is defined like this:{GetTextPrompt300Explanation()}##available functions##{pluginsAsTextPrompt3000}##end functions##The following rules are very important:1) you can only recommend one function and the parameters, not multiple functions2) You can only recommend a function that is in the list of available functions3) You need to give all parameters for the function. Do NOT escape special characters in the name of functions or the names of parameters (dont do aaa\_bbb, just stick to aaa_bbb)!4) Given the history, the function you recommend needs to be important to get closer towards the goal5) Do not wrap functions into each other. Stick to the list of functions, this is not a math problem. Do not use placeholders.We only need one function, the next one needed. For example, if function A() needs to be used as parameter in function B(), do NOT do B(A()). Instead,if A wasnt called allready, call A() first. The result will be used in B in a later iteration.6) Do not recommend a function that was recently called. Use the output instead. Do not use Placeholders or Functions as parameters for other functions7) Only write a Function Call, do not explain why, do not provide a reasoning. You are limited to writing a function call only!8) When all  necessary functions are called and the result was presented by the computer system, call the Finished function and present the resultIf you break any of those rules, a kitten dies. ";return systemPrompt;}

我翻譯了一個中文版本并添加了使用中文回答如下:

        private string GetLoopSystemMessage(string pluginsAsTextPrompt3000){string systemPrompt = $@"你是一個計算機系統。
你只能使用TextPrompt3000指令,讓用戶調用對應的函數,而用戶將作為另一個回答這些函數的計算機系統。
以下是您所需實現的目標,以及用戶可以使用的函數列表。
您需要找出用戶到達目標的下一步,并推薦一個TextPrompt3000函數調用。 
您還會得到一個TextPrompt3000 Schema格式的函數列表。
TextPrompt3000格式的定義如下所示:
{GetTextPrompt300Explanation()}
##可用函數列表開始##
{pluginsAsTextPrompt3000}
##可用函數列表結束##以下規則非常重要:
1) 你只能推薦一個函數及其參數,而不是多個函數
2) 你可以推薦的函數只存在于可用函數列表中
3) 你需要為該函數提供所有參數。不要在函數名或參數名中轉義特殊字符,直接使用(如只寫aaa_bbb,不要寫成aaa\_bbb)
4) 你推薦的歷史記錄與函數需要對更接近目標有重要作用
5) 不要將函數相互嵌套。 遵循列表中的函數,這不是一個數學問題。 不要使用占位符。
我們只需要一個函數,下一個所需的函數。舉個例子, 如果 function A() 需要在 function B()中當參數使用, 不要使用 B(A())。 而是,
如果A還沒有被調用, 先調用 A()。返回的結果將在下一次迭代中在B中使用。
6) 不要推薦一個最近已經調用過的函數。 使用輸出代替。 不要將占位符或函數作為其他函數的參數使用。
7) 只寫出一個函數調用,不解釋原因,不提供理由。您只能寫出一個函數調用!
8) 當所有必需的函數都被調用,且計算機系統呈現了結果,調用Finished函數并展示結果。
9) 請使用中文回答。如果你違反了任何這些規定,那么會有一只小貓死去。
";return systemPrompt;}

第一次直觀感受到了提示工程的魔法。

根據這個模板與對話歷史詢問大語言模型下一步需要執行的函數名稱與參數是什么:

image-20240708164957393

大語言模型回答需要調用的函數名為GetOrderById,參數id為3,接下來驗證是否可以轉化為一個Function Call:

image-20240708165204124

在plugins中查找是否有同名的函數,如果有KernelArguments,進行本地函數調用:

private async Task<string> InvokePluginAsync(FunctionCall functionCall)
{List<string> args = new List<string>();foreach (var paraam in functionCall.Parameters){args.Add($"{paraam.Name} : {paraam.Value}");}Debug.WriteLine($">>invoking {functionCall.Name} with parameters {string.Join(",", args)}");// Iterate over each plugin in the kernelforeach (var plugin in _kernel.Plugins){// Check if the plugin has a function with the same name as the function callvar function = plugin.FirstOrDefault(f => f.Name == functionCall.Name);if (function != null){// Create a new context for the function callKernelArguments context = new KernelArguments();// Add the function parameters to the contextforeach (var parameter in functionCall.Parameters){context[parameter.Name] = parameter.Value;}// Invoke the functionvar result = await function.InvokeAsync(_kernel, context);Debug.WriteLine($">>Result: {result.ToString()}");return result.ToString();}}
 // Invoke the functionvar result = await function.InvokeAsync(_kernel, context);

在本例中會執行:

[KernelFunction, Description("根據Id獲取訂單")]
[return: Description("獲取到的訂單")]
public string GetOrderById(
[Description("訂單的Id")] int id)
{var order = Orders.Where(x => x.Id == id).FirstOrDefault();if(order != null){return order.ToString();}else{return "找不到該Id的訂單";}
}

這個函數,得到如下結果:

image-20240708165812387

大語言模型判斷已經完成了任務,下一步執行

   [KernelFunction, Description("當工作流程完成,沒有更多的函數需要調用時,調用這個函數")]public string Finished([Description("總結已完成的工作和結果,盡量簡潔明了。")] string finalmessage
){return string.Empty;//no actual implementation, for internal routing only}

這個函數,如下所示:

image-20240708170028013

下一個調用的函數是Finished的,會跳出循環:

image-20240708170231464

返回最后的信息:

image-20240708170316368

最終的效果如下所示:

image-20240708170356146

以上就是本次分享的全部內容,嘗試使用開源的大語言模型與SenmanticKernel框架結合,構建自己的簡易的AI Agent,不過AI Agent的效果還不是很好,任務變復雜有可能會出錯,具體學習可以看推薦的項目的源代碼,作者寫的還是比較清晰的。感謝硅基流動提供的平臺,讓我等沒有硬件資源的人,也可以流暢的使用開源的大語言模型,進行大語言模型的應用探索。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43135.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43135.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43135.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

消防認證-防火窗

一、消防認證 消防認證是指消防產品符合國家相關技術要求和標準&#xff0c;且通過了國家認證認可監督管理委員會審批&#xff0c;獲得消防認證資質的認證機構頒發的證書&#xff0c;消防產品具有完好的防火功能&#xff0c;是住房和城鄉建設領域驗收的重要指標。 二、認證依據…

GEE代碼實例教程詳解:NDVI時間序列趨勢分析

簡介 在本篇博客中&#xff0c;我們將使用Google Earth Engine (GEE) 對MODIS NDVI數據進行時間序列趨勢分析。通過分析2001年至2021年的NDVI數據&#xff0c;我們可以了解植被覆蓋度隨時間的變化趨勢。 背景知識 MODIS數據集 MODIS&#xff08;Moderate Resolution Imagin…

Websocket在Java中的實踐——整合Rabbitmq和STOMP

大綱 Rabbitmq開啟STOMP支持 服務端依賴參數參數映射類配置類邏輯處理類 測試測試頁面Controller測試案例 在《Websocket在Java中的實踐——STOMP通信的最小Demo》一文中&#xff0c;我們使用enableSimpleBroker啟用一個內置的內存級消息代理。本文我們將使用Rabbitmq作為消息代…

【Unity2D 2022:Particle System】添加拾取粒子特效

一、創建粒子特效游戲物體 二、修改粒子系統屬性 1. 基礎屬性 &#xff08;1&#xff09;修改發射粒子持續時間&#xff08;Duration&#xff09;為3s &#xff08;2&#xff09;取消勾選循環&#xff08;Looping&#xff09; &#xff08;2&#xff09;修改粒子存在時間&…

SQL性能優化策略

發現問題 通過業務監控發現慢SQL或接口響應延遲。利用性能分析工具定位問題。 定位SQL語句 使用監控工具確定影響性能的SQL語句和表。 SQL查詢變慢原因 索引失效&#xff1a;查詢未使用索引或索引效率低。多表連接&#xff1a;JOIN操作導致性能下降。查詢字段過多&#xf…

Monitor結構解讀之EntryQ和WaitSet的區別

EntryQ&#xff08;或_EntryList&#xff09;和WaitSet&#xff08;或_WaitSet&#xff09;在Java的monitor機制中扮演著不同的角色&#xff0c;它們之間的主要區別體現在以下幾個方面&#xff1a; 1. 等待原因和機制 EntryQ&#xff08;或_EntryList&#xff09;&#xff1a…

面試常考題---128陷阱(詳細)

1.問題引入 分別引入了int和Integer變量&#xff0c;并進行比較 int b 128; int b1 128;Integer d 127; Integer d1 127;Integer e 128; Integer e1 128;System.out.println(bb1); System.out.println(dd1); System.out.println(ee1); System.out.println(e.equals(e1)…

刷題(day01)

1、leetcode485.最大連續1的個數 給定一個二進制數組 nums &#xff0c; 計算其中最大連續 1 的個數。 示例 1&#xff1a; 輸入&#xff1a;nums [1,1,0,1,1,1] 輸出&#xff1a;3 解釋&#xff1a;開頭的兩位和最后的三位都是連續 1 &#xff0c;所以最大連續 1 的個數是 3.…

Nginx 高效加速策略:動靜分離與緩存詳解

在現代Web開發中&#xff0c;網站性能是衡量用戶體驗的關鍵指標之一。Nginx&#xff0c;以其出色的性能和靈活性&#xff0c;成為眾多網站架構中不可或缺的一部分。本文將深度解析如何利用Nginx實現動靜分離與緩存&#xff0c;從而大幅提升網站加載速度和響應效率。 理解動靜分…

昇思第18天打卡|ShuffleNet圖像分類

ShuffleNet網絡介紹 ShuffleNetV1是曠視科技提出的一種計算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一樣主要應用在移動端&#xff0c;所以模型的設計目標就是利用有限的計算資源來達到最好的模型精度。ShuffleNetV1的設計核心是引入了兩種操作&#xff1a;Pointw…

張大哥筆記:你一旦開竅,就會發現遍地都是錢

大家有沒有發現&#xff0c;窮人總是追逐眼前的利益&#xff0c;總是在追著錢跑&#xff0c;卻總是賺不到錢。而富人有著長遠的見識&#xff0c;追著問題跑&#xff0c;最后卻賺的盆滿缽滿。 我們聽過這樣一句話&#xff0c;錢不是賺來的&#xff0c;而是幫助別人解決問題后給你…

【計算機】同步/異步

同步/異步 在計算機科學和編程中&#xff0c;“同步”&#xff08;Synchronization&#xff09;是一種機制&#xff0c;用于協調不同進程或線程之間的操作&#xff0c;以避免競態條件&#xff08;race conditions&#xff09;、死鎖&#xff08;deadlocks&#xff09;和其他并…

Qt/C++編寫地圖應用/離線地圖下載/路徑規劃/軌跡回放/海量點/坐標轉換

一、前言說明 這個地圖組件寫了很多年了&#xff0c;最初設計的比較粗糙&#xff0c;最開始只是為了滿足項目需要&#xff0c;并沒有考慮太多拓展性&#xff0c;比如最初都是按照百度地圖寫死在代碼中&#xff0c;經過這幾年大量的現場實際應用&#xff0c;以及大量的用戶提出…

Django 新增數據 save()方法

1&#xff0c;添加模型 Test/app11/models.py from django.db import modelsclass Book(models.Model):title models.CharField(max_length100)author models.CharField(max_length100)publication_date models.DateField()price models.DecimalField(max_digits5, decim…

BFC 是什么?

BFC 是塊級格式化上下文&#xff08;Block Formatting Context&#xff09;的縮寫&#xff0c;是 CSS 中一個重要的概念&#xff0c;用于控制塊級盒子的布局及浮動元素的交互。BFC 是一個獨立的渲染區域&#xff0c;內部的塊級盒子會按照特定的規則進行布局&#xff0c;不會影響…

軟件工程(上)

目錄 軟件過程模型&#xff08;軟件開發模型&#xff09; 瀑布模型 原型模型 V模型 構件組裝模型 螺旋模型&#xff08;原型瀑布&#xff09; 基于構件的軟件工程&#xff08;CBSE&#xff09; 快速應用開發模型&#xff08;RAD&#xff09; 統一過程&#xff08;UP&a…

Linux學習看這一篇就夠了,超超超牛的Linux基礎入門

引言 小伙伴們&#xff0c;不管是學習c還是學習其他語言在我們學的路上都繞不過操作系統&#xff0c;而且&#xff0c;老生常談的Linux更是每個計算機人的必修&#xff0c;那么我們對Linux的了解可能只是從別人那聽到的簡單的這個系統很牛&#xff0c;巴拉巴拉的&#xff0c;但…

大模型日報 2024-07-08

大模型日報 2024-07-08 大模型資訊 Anthropic CEO&#xff1a;大模型訓練成本暴漲&#xff0c;2027年將達1000億美元&#xff01; Anthropic首席執行官表示&#xff0c;當前AI模型訓練成本是10億美元&#xff0c;未來三年&#xff0c;這個數字可能會上升到100億美元甚至1000億美…