基于JSON的Ollama和LangChain agent

到目前为止,我们都可能意识到,通过为LLMs提供额外的工具,我们可以显著增强它们的功能。

例如,即使是ChatGPT在付费版本中也可以直接使用Bing搜索和Python解释器。OpenAI更进一步,为工具使用提供了经过优化的LLM模型,您可以将可用的工具和提示一起传递给API端点。

然后LLM决定是否可以直接提供回答,或者是否应该首先使用任何可用的工具。

请注意,这些工具不仅仅用于获取额外的信息;它们可以是任何东西,甚至可以让LLMs预订晚餐。我之前实施过一个项目,允许LLM通过一组预定义的工具与图数据库进行交互,我称之为语义层。

一个与图数据库交互的代理LLM。图片由作者提供。

本质上,这些工具通过提供动态、实时的信息访问、通过记忆进行个性化以及通过知识图谱对关系进行复杂的理解,来增强像GPT-4这样的LLM。

它们共同使LLM能够提供更准确的推荐,随着时间的推移了解用户的偏好,并获得更广泛的最新信息,从而实现更具互动性和适应性的用户体验。

正如提到的那样,除了在查询时能够检索到额外的信息外,它们还给LLM提供了一种影响他们环境的选择,例如在日历中预订会议。

虽然OpenAI为我们提供了精细调整的模型来进行工具使用,但事实是,大多数其他LLMs在函数调用和工具使用方面都不及OpenAI水平。

我已经尝试了Ollama中大部分可用的模型,大多数都难以始终生成可用于驱动代理的预定义结构化输出。另一方面,有一些模型是针对函数调用进行了优化的。

然而,这些模型采用了一种自定义的提示工程模式来进行函数调用,但这种模式并没有很好地记录,或者它们不能用于除了函数调用之外的任何其他用途。

最终,我决定遵循现有的LangChain实现,使用基于JSON的代理,使用Mixtral 8x7b LLM。我将Mixtral 8x7b用作电影代理,通过语义层与Neo4j进行交互,Neo4j是一种本地图数据库。代码可作为Langchain模板和Jupyter笔记本提供。如果你对工具的实现方式感兴趣,可以查看我之前的博客文章。在这里,我们将讨论如何实现基于JSON的LLM代理。

语义层中的工具

LangChain文档中的示例(JSON代理,HuggingFace示例)使用的是只有一个字符串输入的工具。由于语义层中的工具使用稍微复杂一些的输入,我不得不深入研究一下。这是一个推荐工具的示例输入。

all_genres = ["Action","Adventure","Animation","Children","Comedy","Crime","Documentary","Drama","Fantasy","Film-Noir","Horror","IMAX","Musical","Mystery","Romance","Sci-Fi","Thriller","War","Western",
]class RecommenderInput(BaseModel):movie: Optional[str] = Field(description="movie used for recommendation")genre: Optional[str] = Field(description=("genre used for recommendation. Available options are:" f"{all_genres}"))

推荐工具有两个可选输入:电影和类型。此外,我们使用一个可用值的枚举来表示类型参数。

虽然输入并不是非常复杂,但仍比单个字符串输入更先进,因此实现方式必须稍有不同。

基于JSON的LLM代理的提示

在我的实现中,我从LangChain hub中现有的 hwchase17/react-json 提示中获得了很大的灵感。该提示使用以下系统消息。

Answer the following questions as best you can. You have access to the following tools:{tools}The way you use the tools is by specifying a json blob.
Specifically, this json should have a `action` key (with the name of the tool to use) and a `action_input` key (with the input to the tool going here).The only values that should be in the "action" field are: {tool_names}The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB:```
{{"action": $TOOL_NAME,"action_input": $INPUT
}}
```ALWAYS use the following format:Question: the input question you must answer
Thought: you should always think about what to do
Action:
```
$JSON_BLOB
```
Observation: the result of the action
... (this Thought/Action/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input questionBegin! Reminder to always use the exact characters `Final Answer` when responding.

提示从定义可用工具开始,稍后我们将介绍。提示的最重要部分是指示LLM输出应该是什么样子的。当LLM需要调用一个函数时,应该使用以下JSON结构:

{{"action": $TOOL_NAME,"action_input": $INPUT
}}

这就是为什么它被称为基于JSON的代理:当LLM想要使用任何可用工具时,我们指示它生成一个JSON。然而,这只是输出定义的一部分。完整的输出应该具有以下结构:

Thought: you should always think about what to do
Action:
```
$JSON_BLOB
```
Observation: the result of the action
... (this Thought/Action/Observation can repeat N times)
Final Answer: the final answer to the original input question

LLM应该在输出的思考部分解释它正在做什么。当它想要使用任何可用的工具时,应该将动作输入提供为JSON blob。

观察部分保留给工具输出,当代理决定可以向用户返回答案时,应使用最终答案键。以下是使用此结构的电影代理的示例。

在这个例子中,我们要求代理人推荐一部好的喜剧片。由于代理人可用的工具之一是推荐工具,它决定利用推荐工具,通过提供JSON语法来定义其输入。幸运的是,LangChain具有内置的JSON代理输出解析器,所以我们不必担心实现它。接下来,LLM从工具中获得一个响应,并将其作为提示中的观察。

由于工具提供了所有所需的信息,LLM决定它已经有足够的信息来构建最终答案,并将其返回给用户。

我注意到很难促使工程师Mixtral只在需要使用工具时使用JSON语法。在我的实验中,当它不想使用任何工具时,有时会使用以下JSON动作输入。

{{"action": Null,"action_input": ""
}}

LangChain中的输出解析函数不会忽略空或类似的操作,而是返回一个错误,指出未定义空工具。我试图向工程师提供解决这个问题的提示,但无法以一致的方式做到。

因此,我决定添加一个虚拟的闲聊工具,当用户想要闲聊时,代理可以调用它。

response = ("Create a final answer that says if they ""have any questions about movies or actors"
)class SmalltalkInput(BaseModel):query: Optional[str] = Field(description="user query")class SmalltalkTool(BaseTool):name = "Smalltalk"description = "useful for when user greets you or wants to smalltalk"args_schema: Type[BaseModel] = SmalltalkInputdef _run(self,query: Optional[str] = None,run_manager: Optional[CallbackManagerForToolRun] = None,) -> str:"""Use the tool."""return response

这样,代理可以在用户打招呼时决定使用一个虚拟的Smalltalk工具,我们不再遇到解析空或缺失工具名称的问题。

这个解决方法非常有效,所以我决定保留它。正如提到的,大多数模型没有经过训练来产生行动输入或文本,如果不需要行动,我们必须使用当前可用的内容。

然而,有时候模型在第一次迭代时成功地不调用任何工具,这取决于情况。但是给它一个像smalltalk工具这样的逃逸选项似乎可以防止异常。

在系统提示中定义工具输入

如前所述,我必须弄清楚如何定义稍微复杂的工具输入,以便LLM能够正确解释它们。

有趣的是,在实施自定义函数之后,我发现了一个现有的LangChain函数,它将自定义的Pydantic工具输入定义转换为Mixtral可以识别的JSON对象。

from langchain.tools.render import render_text_description_and_argstools = [RecommenderTool(), InformationTool(), Smalltalk()]tool_input = render_text_description_and_args(tools)
print(tool_input)

生成以下字符串描述:

"Recommender":"useful for when you need to recommend a movie",
"args":{{"movie":{{"title":"Movie","description":"movie used for recommendation","type":"string"}},"genre":{{"title":"Genre","description":"genre used for recommendation. Available options are:['Action', 'Adventure', 'Animation', 'Children', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'IMAX', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western']","type":"string"}}}
},
"Information":"useful for when you need to answer questions about various actors or movies",
"args":{{"entity":{{"title":"Entity","description":"movie or a person mentioned in the question","type":"string"}},"entity_type":{{"title":"Entity Type","description":"type of the entity. Available options are 'movie' or 'person'","type":"string"}}}
},
"Smalltalk":"useful for when user greets you or wants to smalltalk",
"args":{{"query":{{"title":"Query","description":"user query","type":"string"}}}
}

我们可以简单地将这个工具描述复制到系统提示中,Mixtral就能够使用定义好的工具,这非常酷。

 结论

JSON-based agent的大部分工作是由Harrison Chase和LangChain团队完成的,我对此表示感谢。我所要做的就是找到拼图的碎片并将它们组合起来。正如前面提到的,不要期望与GPT-4一样的代理性能水平。然而,我认为像Mixtral这样更强大的OSSLLMs可以作为代理使用(比GPT-4需要更多的异常处理)。

我期待更多的开源LLMs被调整得更好作为代理。

代码可作为Langchain模板和Jupyter笔记本提供。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/268293.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GIT 卸载干净(图文详解)

一、控制面板卸载 右击卸载 等待卸载过程 二、在环境变量,把相关信息删除干净

巧妙解决接口测试产生脏数据问题

测试数据创建后需要对其删除,不然可能产生脏数据,对开发和测试、生产环境造成一定影响。 其接口框架是基于Python,API规范基于REST。 产生原因 改进前:清除资源的操作放在每个正向测试用例里,没有在setUp和tearDown…

使用 MongoDB Atlas 无服务器实例更高效地开发应用程序

使用 MongoDB Atlas无服务器实例更高效地开发应用程序 身为开发者,数据库并不一定需要您来操心。您可不想耗费时间来预配置集群或调整集群大小。同样地,您也不想操心因未能正确扩展而导致经费超标。 MongoDB Atlas 可为您提供多个数据库部署选项。虽然…

Vue路由(黑马程序员)

路由介绍 将资代码/vue-project(路由)/vue-project/src/views/tlias/DeptView.vue拷贝到我们当前EmpView.vue同级,其结构如下: 此时我们希望,实现点击侧边栏的部门管理,显示部门管理的信息,点击员工管理,显…

Vision Pro开发者学习路线

官方给到的Vision Pro开发者学习路线: 1. 学习基础知识: - 学习 Xcode、Swift 和 SwiftUI 的基础知识,包括语法、UI 设计等。 - 掌握 ARKit 和 SwiftUI 的使用,了解如何创建沉浸式增强现实体验。 2. 学习 3D 建模&#xf…

【latex】\IEEEpubid版权声明与正文内容重叠

问题描述 撰写IEEE Trans论文时,出现版权声明文字\IEEEpubid与正文内容重叠的问题: 原因分析: 在使用模板时,不小心将以下命令删除了: \IEEEpubidadjcol 解决方案: 在需要换页的位置附近添加以上命令&…

Appium自动化测试环境搭建

1、Appium简介 Appium是一个开源的,适用于原生或混合移动应用( hybrid mobile apps )的自动化测试平台,Appium应用WebDriver: JSON wire protocol驱动安卓和iOS移动应用。 2、环境配置 (1) 配置java环境 首先安装jdk。安装完成后新建用户…

【算法大家庭】动态规划算法

目录 🧂1.动态规划思想 🌭2.背包问题思路分析 🍿3.代码实现 1.动态规划思想 将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的 2.背包问题思路分…

德人合科技 | 天锐绿盾终端安全管理系统

德人合科技提到的“天锐绿盾终端安全管理系统”是一款专业的信息安全防泄密软件。这款软件基于核心驱动层,为企业提供信息化防泄密一体化方案。 www.drhchina.com 其主要特点包括: 数据防泄密管理:天锐绿盾终端安全管理系统能够确保数据在创…

10.轮廓系数-机器学习模型性能的常用的评估指标

轮廓系数(Silhouette Coefficient)是评估聚类算法效果的常用指标之一。它结合了聚类的凝聚度(Cohesion)和分离度(Separation),能够量化聚类结果的紧密度和分离度。 背景 1.聚类分析的背景 在…

蓝桥杯算法题汇总

一.线性表:链式 例题:旋转链表 二.栈: 例题:行星碰撞问题 三.队列 三.数组和矩阵 例题: 四.哈希表 五.二叉树 主要方法是递归 主要考察点是遍历:前序,中序,后序遍历,层…

C习题002:澡堂洗澡

问题 输入样例 在这里给出一组输入。例如&#xff1a; 2 5 1 3 3 2 3 3 输出样例 在这里给出相应的输出。例如&#xff1a; No代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int N,W,s,t,p;int arr_s[…

解决:Information:java: javacTask: 源发行版 8 需要目标发行版 1.8

解决&#xff1a;Information:java: javacTask: 源发行版 8 需要目标发行版 1.8 先点击 Project Structure 查看jdk是否为1.8版本 我这jdk版本为1.8版本的&#xff0c;但还是运行还是报错 据以上错误显示以及上述配置&#xff0c;我选择的编译器是jdk1.8的&#xff0c;但是在i…

2.模拟问题——3.叠筐

【原题链接】 分析 题目含义 根据题目要求&#xff0c;即要将中心值放在正方形框正中心&#xff0c;然后依次轮换在外层围上另一个边缘值&#xff0c;围的时候边框要保证中心值和边缘值交替&#xff0c;所围图形保持为一个正方形&#xff0c;围完最后一圈后&#xff0c;需要…

【leetcode】用队列实现栈

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 点击查看题目 思路: 在做此题之前&#xff0c;我们先要实现队列&#xff0c;这在上个博客中已经写过&#…

武器大师——操作符详解(下)

目录 六、单目操作符 七、逗号表达式 八、下标引用以及函数调用 8.1.下标引用 8.2.函数调用 九、结构体 9.1.结构体 9.1.1结构的声明 9.1.2结构体的定义和初始化 9.2.结构成员访问操作符 9.2.1直接访问 9.2.2间接访问 十、操作符的属性 10.1.优先性 10.2.结合性 …

JVM相关问题

JVM相关问题 一、Java继承时父子类的初始化顺序是怎样的&#xff1f;二、JVM类加载的双亲委派模型&#xff1f;三、JDK为什么要设计双亲委派模型&#xff0c;有什么好处&#xff1f;四、可以打破JVM双亲委派模型吗&#xff1f;如何打破JVM双亲委派模型&#xff1f;五、什么是内…

Day03:Web架构OSS存储负载均衡CDN加速反向代理WAF防护

目录 WAF CDN OSS 反向代理 负载均衡 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服务/负载均衡等 安全产品&#xff1a;CDN/WAF/IDS/IPS/蜜罐/防火墙/杀毒等 渗透命令&#xff1a;文件上传下载/端口服务/Shell反弹等 抓包技术&#xff1a…

随机生成验证码

随机生成验证码 需求&#xff1a;随机生成一个任意位的验证码包含数字、大写字母和小写字母 1.代码实现 package com.ham;import java.util.Random;public class case2 {public static void main(String[] args) {System.out.println(code(4));}public static String code(i…

Jvm之内存泄漏

1 内存溢出 1.1 概念 java.lang.OutOfMemoryError&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现OutOfMemoryError。产生该错误的原因主要包括&#xff1a;JVM内存过小。程序不严密&#xff0c;产生了过多的垃圾。 程序体现: 内…