返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

使用coze扣子搭建智能bot「程序员的工具箱」的思考和总结

[复制链接]
链载Ai 显示全部楼层 发表于 3 小时前 |阅读模式 打印 上一主题 下一主题

前记

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">大模型已经火了快 2 年的时间了,从简单的文字处理的单一场景到到现在的企业迫切需要 LLM 在更多的场景赋能的时代。大众也从简单问答、RAG 知识库、到智能 Agent 的构建有了自己的认识和想法。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">如果要构建一个 Agent 就会涉及到一些架构模式:

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">路由分发架构模式

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">当用户输入一个 Prompt 查询时,该查询会被发送到路由转发模块,而路由转发模块则扮演着对输入 Prompt 进行分类的角色。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">大模型代理架构模式

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">在任何一个生态系统中,都会有多个针对特定任务领域的专家,并行工作以处理特定类型的查询,然后将这些响应整合在一起,形成一个全面的答案。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">基于缓存的微调架构模式

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">我们将缓存和微调引入到大模型应用架构中,可以解决成本高、推理速度慢以及幻觉等组合问题。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">面向目标的 Agent 架构模式

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.1em;color: rgb(63, 63, 63);">对于用户的 Prompt 提示词,Agent 会基于大模型先做规划(Planning),拆解成若干子任务,然后对每个子任务分别执行(Action),同时对每一步的执行结果进行观测(Observation),如果观测结果合格,就直接返回给用户最终答案,如果观测结果不合格或者执行出错,会重新进行规划(Replanning)。

Agent 智能体组合架构模式

从上述几种架构中我们不难看出还是非常复杂的,也不是一般企业能够做的了的。(费钱?)

好在扣子已经把很多工作都做了。我们只需要在他上面去搭建想要的 agent 即可,大大减少了普通人的使用成本。

下面就结合自己的搭建一个 agent 的过程详细了解各个功能的构建过程。

工具集成

在扣子 bot 的编辑页面的中间区块插件区域我们可以选用扣子商店里面上架的工具。同时也可以自己去编写插件。插件的实现目前提供了两种语言:JavaScriptpython。可以根据自己的能力选用对应的语言编写即可。具体的编写插件的教程可以去官网文档查看。

那一个插件具体要实现什么样子的功能需要看我们构建的 bot 需要提供什么的能力。比如我是工具类的 bot,就需要集成各种常用的功能的工具。

目前我的bot程序员的工具箱[1]里面集成了挺多的工具:红框住的都是自研插件,具体如何做一个插件可以参考官网文档:

先分享一个自己实现工具json2sql将json数据转换为sql:(此插件目前已经上架到官方插件商店)

import{Args}from'@/runtime';
import{Input,Output}from"@/typings/json2sql/json2sql";

/**
*Eachfileneedstoexportafunctionnamed`handler`.ThisfunctionistheentrancetotheTool.
*@param{Object}args.input-inputparameters,youcangettestinputvaluebyinput.xxx.
*@param{Object}args.logger-loggerinstanceusedtoprintlogs,injectedbyruntime
*@returns{*}Thereturndataofthefunction,whichshouldmatchthedeclaredoutputparameters.
*
*Remembertofillininput/outputinMetadata,ithelpsLLMtorecognizeandusetool.
*/
exportasyncfunctionhandler({input,logger}:Args<Input>)romise<Output>{
varjson_str=input.jsonStr.replaceAll('\n','')
json_str=json_str.replaceAll("'",'"')
vardata=JSON.parse(json_str);
varsql="";
sql+="CREATETABLE{table_name}(\n";
varfflag=1;
varfield=[];
for(constkeyindata){
if(key=="id"){
fflag=0;
continue
}
letval=data[key];
if(typeofval=="string"){
field=field.concat("`"+key+"`VARCHAR(255)NOTNULLdefault''");
}
if(typeofval=="number"){
if((val+"").indexOf(".")>-1){
field=field.concat("`"+key+"`FLOAT");
}else{
field=field.concat("`"+key+"`INTNOTNULLdefault0");
}
}
if(typeofval=="boolean"){
field=field.concat("`"+key+"`BOOLEANNOTNULLdefaultfalse");
}
}

if(!fflag){
field=field.concat("`id`int(11)NOTNULLAUTO_INCREMENT");
field=field.concat("PRIMARYKEY(id)")
}
logger.info(field);
sql+=field.join(",\n");
sql+="\n);";
return{
result:sql,
};
};

输出:

CREATETABLE{table_name}(
`name`VARCHAR(255)NOTNULLdefault'',
`age`INTNOTNULLdefault0,
`sex`VARCHAR(255)NOTNULLdefault'',
`phone`VARCHAR(255)NOTNULLdefault'',
`address`VARCHAR(255)NOTNULLdefault'',
`money`FLOAT,
`deleted`BOOLEANNOTNULLdefaultfalse,
`id`int(11)NOTNULLAUTO_INCREMENT,
PRIMARYKEY(id)
);

让模型调用工具

不管工具的能力多好,能让大模型调用到才是真的好?。

如何才能让大模型调用到呢?那就是prompt的编写。

扣子官方提供的案例里面是使用markdown格式写的,那我们也参考官方的格式:

###技能3:json数据转sql
1. 如果用户需要将 json 数据转换为 sql 语句,运用 json2sql 工具进行转换。
2. 不要对输出的 sql 做改写,输出 markdown 格式。

这里主要是对模型说明当遇到什么样子的数据时候需要调用哪个工具来处理数据。所以我们调用一个工具需要注意两点:

  • •prompt 中需要以简单直接的语句说明工具调用的方式

  • •在工具的说明里面也需要说明工具的能力

这些内容都会提交给大模型去理解,观察、执行。也就是React的执行能力。如果想要构建一个比较智能的Agent就需要React的思考执行模型。感兴趣的可以去了解下大模型应用中的React

查询Linux命令的能力:知识库

我们还是先看使用效果:

示例 1:查询sed命令

示例2:查询grep命令

解析:

linux命令的查询以及使用能力大模型已经具备了一些能力,不过我这里还是使用了知识库的能力作为 LLM 的内容补充。总共有 600+的命令作为知识库的内容。

LLM 会存在一些痛点,比如知识老旧、幻觉、高成本。所以很多情况下需要使用 RAG 的技术来解决 LLM 的问题。当然这里也不例外,也是利用了 RAG 的技术。

RAG有三方面的好处:

  • •确保LLM可以回答最新、最准确的内容。并且用户可以访问模型内容的来源,确保可以检查其声明的准确性并最终可信。

  • •通过将LLM建立在一组外部的、可验证的事实数据之上,该模型将信息提取到其参数中的机会更少。这减少了LLM泄露敏感数据或“幻觉”不正确或误导性信息的机会。

  • RAG还减少了用户根据新数据不断训练模型并随着数据的变化更新训练参数的需要。通过这种方式企业可以减低相关财务成本。

关于 LLM 与 RAG 的详细内容这里不再赘述,大家可以参考我前面的文章RAG实操教程: langchain+Milvus向量数据库创建你的本地知识库[2]

自己干

我这里的 600+的 linux 命令对应的都是采集的网页数据。扣子提供了网页自动采集的能力。但是他只能一条条采集。对于600+的网页数据在没有 API 的基础上去搞估计的废了?。文件上传可以一次导入 10 个文本,这个效率感觉比上面的那个靠谱多了。

于是就动手自己去采集 600+的网页数据。采集数据需要注意几点:

  • •限制采集的频率

  • •添加必要的 header 参数

  • •如果有用户认证的需要对应的 cookie 或者 token。

  • •提取网页上面自己关心的数据内容。

所以奔着一切动手实践的初衷手写爬取网页的代码,并按照每 10 个文件保存到一个目录中。

下面是 python 代码,需要的同学可以参考:

fromlangchain_community.document_loadersimportWebBaseLoader
frombs4importSoupStrainer
frombs4importBeautifulSoup
importos,time

deflinux_shell():
total=1
foridxinurls:
url=idx
url_arr=url.split('/')
name=url_arr[-1].replace('html','txt')
#定位网页上面需要爬取的数据块
only_a_tags=SoupStrainer(class_="markdown-style")
loader=WebBaseLoader(
web_path=url,
encoding='utf-8',
bs_kwargs={'parse_only'nly_a_tags}
)
#这里为了简单就直接使用langchain的文本加载器
data=loader.load()
dir_name=f'/Users/oo7/Developer/langchain/coze/cmds/{int(total/10)+1}'
ifos.path.exists(dir_name)isFalse:
os.makedirs(dir_name)
file_name=f"{os.path.join(dir_name,name)}"
#简单处理文件的格式
page_content=data[0].page_content.replace('\n\n\n\n','\n')
#保存内容到文件中
withopen(file_name,'w')asf:
f.writelines(f"Linux{name.split('.')[0]}命令详解\n")
f.write(page_content)

print(f"{total}:{idx}isdownloaded")
time.sleep(0.5)
total+=1

知识库配置:

对于知识库的配置,个人感觉还是比较重要的。知识库的配置有几项下面分别说一下:

  • •搜索策略:从知识库中获取知识的检索方式,不同的检索策略可以更有效地找到正确的信息,提高其生成的答案的准确性和可用性。

  • •最大召回数量:从知识库中返回给大模型的最大段落数,数值越大返回的内容越多。

    • •这个配置需要根据自己的实际情况去做调整。

    • •值越大返回的内容越多,某种情况下会导致返回的无用的信息多。

    • •值越小返回的内容越少,某种啥情况下会导致内容缺乏核心点。

  • •最小匹配度:根据设置的匹配度选取段落返回给大模型,低于设定匹配度的内容不会被召回。

    • •这个就通常所说的向量数据库的得分。得分越大匹配度越高,返回的条数越少。

    • •这个配置也是需要根据自己内容来做调整。

  • •调用方式

    • •自动调用:LLM 会根据用户内容做匹配。

    • •按需调用:这种情况需要在角色设定里面配置使用知识库的场景和匹配情况。

下面是我的提示词以及配置:

###技能10:linux命令查询
1、如果用户查询linux 命令时,运用 recallKnowledge 来获取内容。
2、如果内容比较少,尽可能的给出一些使用示例和场景。
3、如果找到的内容匹配度较低,需要运用 bingWebSearch 搜索内容。

从图中看到这个效果还是比较好的。很多人添加完知识库就不管了,我的建议是最好还是做下配置,多使用看效果。

获取新闻能力

这里主要是使用了获取新闻的插件:ithome_news这个插件是自己做的(现已上架到扣子官方的插件商店中,有需要的可以自行下载),数据来源是爬取某科技网站的日榜周榜月榜的新闻。

工作流构建:

构建工作流需要的节点:

  • •开始节点

  • •LLM 节点

  • •选择器节点 (好像没必要了?)

  • •插件节点(调用获取新闻)

  • •结束节点

这里流程图里面两个节点很关键:

  • •大模型节点:这个节点让大模型去理解用户输入内容,并分析需要获取新闻的分类是哪一个。

    ##返回
    新闻类型:日榜、周榜、月榜。
    从用户输入内容"{{input}}。默认类型为日榜"中提取新闻类型.返回的内容只能是新闻类型中的内容。
    -类型参数:{{category}}

    这一步很关键,目的就是让大模型能准确获取用户内容的意图从而提取里面的分类。这个分类会传递到后面的新闻节点,然后输出对应的类型。

  • •新闻工具节点:节点从LLM获取到的输入分类参数,输出对应分类下面的新闻。如果没有大模型提取出的新闻分类,这一步就很鸡肋。

    从上面的测试结果看,已经很完美的输出了数据。

  • •看下使用效果

使用工作流

bot 中使用工作流news_flow

想让 bot 展现的时候是卡片的效果,只需要将工作流输出的内容数据以卡片的形式展现即可。

对于卡片输出的注意点:

  • •输出的内容必须是固定的,绑定卡片的数据才能固定显示。一般使用API等程序输出固定格式内容

  • •多字段的数据,比如具有标题字段、内容字段、图片字段、url字段的数据会让效果更好。

定时任务能力

这次意外发现,官方提供了一个触发器的能力。那就是设置定时任务,到时间自动执行。有了这个功能是不是突然感觉发挥的空间就很大了呢?

prompt 的重要性

prompt的重要性相信好多人都认识到了。扣子的prompt使用markdown格式编写。主要分为三个部分。

  • LLM的角色设定以及所具备的能力。

  • •详细说明每一个能力,以及能力触发的场景和对数据的处理能力。

  • •约束:限制bot不能做什么。

如果效果不是很理想需要不断的调整 prompt,目的是让 LLM 里面我们的意图。

除此之外工具、工作流等的名称以及描述也是整个botprompt的一部分。到最后 bot 去执行的时候都会将相关工具的描述拼接到prompt里面。最后让 LLM 去思考、执行、观察一直不断的循环这个过程,直到 LLM 认为需要停止的时候输出最终内容。下面的图是 React 的整个过程。

整体的prompt分享给大家作为参考,实际效果还需要根据自己的bot做调整:

#角色
你是一位全能的数据处理专家,擅长处理各种数据格式,能对 JSON 字符串进行格式转换、转义与去除转义操作,还能获取网页内容并加以总结,能用通俗易懂的语言阐释数据特性与复杂的分析结果。

##技能
###技能1:格式化JSON字符串
1.能使用json_formater 工具将用户提供的需转换数据格式化为 JSON 对象。
2.可运用JSON_unescaping 工具对用户输入的需转义数据进行去除转义操作。

###技能2:获取网页内容并总结
1.若用户输入包含 URL 链接,提取该URL 链接,并通过 LinkReaderPlugin 工具获取网页内容。

###技能3:json数据转sql
1.如果用户需要将 json 数据转换为 sql 语句,运用 json2sql 工具进行转换。
2.不要对输出的 sql 做改写,输出 markdown 格式。

###技能4:识别图片中的文字
1.当用户输入图片内容时,可运用 ocr 工具识别图片中的文字。

###技能5:具备强大的思考及自执行能力
能根据用户输入,不断思考要提取的数据、调用的工具及提取工具的输入参数,直至获得可使用的数据为止。

###技能 6:固定markdown 格式回复
1、如果回复用户的内容是代码,使用markdown格式的内容回复用户

###技能7:搜索引擎
1、如果用户希望通过网络查找内容,运用bingWebSearch工具获取内容
2、对搜索引擎的结果内容不要过度总结和优化

###技能8:域名DNS解析记录
1、如果用户要获取域名的DNS解析记录,运用功能dns_tool工具获取内容

###技能 9:获取新闻
1、当用户要获取新闻时,运用news_flow 工具获取内容。

##限制
-不要对输出的 sql 做改写,输出 markdown 格式。
-需依据用户输入,持续思考要提取的信息、调用的工具及工具的输入参数,直至获取到可用数据。
-如需进行总结,只能依据现有内容,不能自行创造。
-输出的内容必须按照给定的格式进行组织,不能偏离框架要求。
-对于分析结果,需详细解释其含义,不能仅提供数字或图表。
-在使用特定编程语言提取数据时,必须阐释所使用的逻辑和方法,不能仅提供代码。
-你只能回答与编程有关的话题。
-不要总结新闻内容

其他功能:

主要的功能讲完后剩余的就是其他功能了,下面的这些都是辅助功能,让你的 bot 更加的完美。

  • •开场白文案:也就是自我介绍?。

  • •开场白预置问题:引导用户提问,使用户能够快速掌握相关的能力。

  • •用户问题建议:

  • •语音:个性化,依据场景以及个人爱好设定就行。

具体如何使用请查询官方文档。

总结:

上面带大家熟悉了构建一个bot的整体过程包括:

  • • LLM agent 架构模式。

  • •插件的编写功能实现,以及插件 prompt 的重要性。

  • •知识库构建,知识库与 bot 的结合。RAG 相关知识。

  • •流程 flow 的使用。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ