以下是一个关于实现简单的 function calling agents 的指导,以便小白能够理解:
实现原理: 提示词工程主要由提示词注入和工具结果回传两部分代码组成。提示词注入用于将工具信息及使用工具的提示词添加到系统提示中,它包含 TOOL_EAXMPLE、tools_instructions 和 REUTRN_FORMAT 三个部分。TOOL_EAXMPLE 用于提示 LLM 如何理解和使用工具,编写时应注意用无关紧要的工具作示例避免混淆。tools_instructions 是将通用工具字典转换成 LLM 可读的工具列表,实际使用时可动态调整。REUTRN_FORMAT 定义了调用 API 的格式。工具结果回传阶段利用正则表达式抓取输出中的“tool”和“parameters”参数,对于 interpreter 工具使用另一种正则表达式提取 LLM 输出的代码,通过识别 LLM 返回的调用工具的字典提取对应值传入工具函数,将工具返回结果以 observation 角色返回给 LLM,对于不接受相关角色的 LLM 接口可改为回传给 user 角色。
实现方式的比较与建议:
此外,在初级菜鸟学习 Langchain 做简单 RAG 方面:
相关代码和示例可参考相应的链接。
本文采用的提示词工程主要有两部分代码组成:提示词注入和工具结果回传。提示词注入用于将工具信息以及使用工具的提示词添加到系统提示中。工具结果回传则是解析tool calling的输出,并将工具返回的内容再次嵌入LLM。[heading2]1、提示词注入阶段[content]INSTRUCTION为最后注入到系统提示中的字符串,他又包含了TOOL_EAXMPLE、tools_instructions、REUTRN_FORMAT三个部分。TOOL_EAXMPLE用于提示LLM如何理解tool以及如何使用tool。在编写TOOL_EAXMPLE时,请注意用一些无关紧要的工具作为示例,例如本文使用的将数字加一和数字减一的工具,从而避免LLM混淆真正可以使用的工具与示例工具。tools_instructions是由目前通用的工具字典转换成LLM可读的工具列表。实际使用LLM时,可以通过输入不同的工具来动态调整tools_instructions,让LLM得知目前可用的工具有哪些以及如何使用。REUTRN_FORMAT定义了调用API的格式。[heading2]2、工具结果回传阶段[content]利用正则表达式抓取输出中的"tool"和"parameters"参数。对于interpreter工具,使用了另一种正则表达式来提取LLM输出的代码,提高LLM使用interpreter工具的成功率。本文使用代码如下:通过识别LLM返回的调用工具的字典,提取出对应的值,再传入相应的工具函数,最后将工具返回的结果以observation的角色返回给LLM。对于一些不接受observation、tool、function角色的LLM接口,可以改为回传给user角色,例如:通过以上提示词工程,可以避免微调,让完全没有tool calling能力的LLM获得稳定的tool calling能力。
这里就讲简单的retrieve的过程。[heading4]Table表格[heading5]方法1:读入表格markdown格式,嵌入template。[content]这里举例为GLM的例子,Azure openai同理。[heading5]方法2:直接使用function call。[content]绕过langchain定义数据库读取的方式。这里我只尝试了GLM的官方方法。这里的parse_function_call是GLM的SDK开放的工具。我的理解是大模型从用户输入的语言提炼出函数所需的参数变量然后进行传参完成数据库查询。[heading4]Text文字[heading5]文字相似度检索过程[content]读入文字,进行文字清洗-->文本句子切分-->文本向量化->计算相似度-->取前几的答案为输入详情见https://github.com/yuanzhoulvpi2017/DocumentSearch脚本简单易懂,不再赘述。Part1不用学习框架,快速实现。氮素过于简单,写得太死,不利于后期持续开发,如果有好的方法尝试基本重开【正常人开发都不会这样的。。除非很紧急没空看文档】[heading3]Part2用Langchain做table和text的RAG[heading4]Table表格[heading5]法1:运用Agent:[heading5]法2:运用Chain:[heading4]Text文字[content]RetrievalQA.from_chain_type[heading3]Part3使用Agent把文本多种文档组合起来![content]这里只示范文本和数据库表格等等,别的我觉得就是差不多类似的写法!主要用chain。Agent套来套去也可以,就是容易眼花。。[heading3]最后[content]https://gitee.com/cyz6668/langchain-simple-rag整理好了,欢迎踩踩
上面讲到了4种实现Function Calling的方式:Json Output:通过Prompt的方式让模型输出JSON格式内容优劣势:Prompt麻烦,输出不稳定,串业务成本高Json Mode:官方Josn Output,1106与Tools同期推出优劣势:JSON格式稳定,但实际上它与Tools的适用场景是不同的,JSON mode是为了输出JSON存在的,而Tools是为了Call API存在的Function Calling和Tools就不再赘述但是从可控的角度来说,还是会推荐Function Calling和Tools来实现。1、放弃JSON mode:随着模型能力提升,模型能够准确地输出JSON,但是它还是会出错,不能保证100%正确;模型厂家对Function Calling是有微调优化的,也有说法是专门的MOE专家,但是无从验证;2、降低System prompt依赖,化繁为简S yste m prompt里面写的东西太多了,你不能保证模型能很好地遵循它;能在Tools里面去写的东西,尽量写在Tools里面3、API Response增强Prompt:其实所有输入给模型的内容,都可以算作是Pormpt。同理,Tools调用的结果也就是API Response也会被返回给到模型。可以在这一步增加一些给大模型的约束和提示,这里的准确率非常高,毛估估95%以上。4、尽量让模型做选择,而不是填空把确定的答案做成选项给到模型,比如用Enum的方式。一方面减少token的输出,提高速度;另一方面,准确率高5、利用Tools来做Route,构建Multi Agent一个不行就上两,两个不行就上四。术业有专攻,Agent的世界也一样。