使用黄金圈原则来讲述我怎么使用扣子创建了一个公众号的BOT。
但是这是个讲述使用方法的文章,所以换一下顺序:Why、What、How
黄金圈原则:黄金圈原则是一个思考和解决问题的方法论,它包含三个层次:为什么(Why)、如何做(How)和做什么(What)。这个原则的核心在于从内在的价值观和目的出发,然后推导出实现目标的方法,最后确定具体的行动和结果。
Why
为什么要写这个BOT?
想用扣子解决点问题,当我拿起了锤子,看哪都是钉子。
所以砸下去的第一个钉子就是我的公众号。
我的公众号"刀笔法老猫"在去年的时候开始分享一些大模型的学习、使用心得。
这个公众号就是我自己的一个知识库。
但是,这些文章在发布之后就忘了,甚至在我使用的时候也不一定能想起来。
遇到问题费劲巴拉的找到解决方案,解决完成后想到这个问题我以前处理过啊。
What
这个BOT准备做什么?
- 查询写某个主题相关的所有文章
- 查询我之前解决某个问题的解决方案
How
这个BOT是为了练习用,所以会尽量用到COZE中各种能力:插件、工作流、知识库、数据库等。
首先整理思路:
如果想让BOT能够回答我写过的文章信息,那么需要他先了解我写的所有文章内容。
了解文章内容有两个方法:
- 全部复制出来
- 用爬虫工具全爬一边
方法一肯定不行,太麻烦了。
当然选择方法二。
在爬取完文章后需要BOT可以记忆我的文章,记忆的方式有两种:
- 向量知识库:这种方式最好,但是向量知识库只支持手动更新,有点麻烦
- 数据库:不太好用,关键问题是查询时比较死板,无法通过模糊的语义来分析,优点是可以动态更新
向量知识库的话操作没什么挑战性,既然是用锤子,选择方法二。
在记录完成后,BOT可以基于文章记录提供两个能力:
-
知识问答,基于我写的文章来回答问题
-
文章查找,查询包含某些关键词的文章
然后整理流程:
Step0:设计智能体
Step1:创建数据库
Step2:存储工作流
Step3:查询工作流
Step3:发布
最后实现:
Step0:设计智能体
shell
# 角色
你是一个公众号作家,能够根据公众号中已发布的文章内容回答用户的问题。用户的所有问题都将通过 mp_article_search_flows 工作流进行回答。当收到"采集"指令时,需按照要求采集公众号文章,并将文章链接作为 url 参数,调用 mp_collection_flows 工作流。
你的语气是:疯批、浓
性别:男
## 技能
### 技能 1: 回答用户问题
1. 能够理解用户的问题,并从公众号文章中提取相关信息进行回答。
2. 对于不明确的问题,通过调用 mp_article_search_flows 工作流获取答案。
### 技能 2: 采集公众号文章
1. 当接收到"采集"指令时,按照要求进行公众号文章的采集。
2. 将采集到的文章链接作为 url 参数,如果没有要求页码,则默认page=1,调用 mp_collection_flows 工作流。
## 限制
- 只回答与公众号相关的问题,拒绝回答其他问题。
- 所输出的内容必须按照给定的格式进行组织,不能偏离框架要求。
Step1:创建数据库
写字段名太麻烦,可以用AI来写。
Step2:存储工作流
先看个完整版,然后再一步一步介绍。
Step2.1:接收参数
工作流参数包含url和page。
Step2.2:使用GetArticlesList获取公众号文章列表
GetArticlesList是Coze的插件,可以通过发送任意一篇文章链接获取公众号最近及历史文章列表。由 Tweeze 提供 tweeze.app.
用法:
获取今日文章:获取任何微信公众号的最新文章列表。
获取过去的文章:获取任何微信公众号的历史文章列表。
然后你可以使用浏览器插件来获取文章的内容,并对其进行分析或重新创建。
传入URL和page参数就可以调用,page非必填,默认是1。
注意:公众号文章每页5篇。
另外这个服务不太稳定,以后有空了弄个插件,更稳定些。
比较神奇的是,这个插件可以获取到我已经删除的公众号文章,难道在很久以前就已经关注我了
Step2.3:使用LinkReaderPlugin插件读取文章
使用COZE官方提供的插件LinkReaderPlugin获取文章详情。
当你需要获取网页、pdf、抖音视频内容时,使用此工具。可以获取url链接下的标题和内容。
上一步查询结果是Array所以在读取文章内容时,使用批处理功能实现。
缺点是批处理功能只能循环10次,还不能嵌套循环,比如我有个List中有List就无法处理。
传入参数Prompt、type、url。
prompt没什么说的,type比较有意思,有三种类型,可以是"全文"或者"检索", enumerate value are ["全文","检索","总结"],文档写的一塌糊涂啊。
尝试了在限定URL后,其实没什么区别...
Step2.4:被逼无奈的一步
工作流中数据库插件没有批处理操作,我在前面两步的数组没办法批量插入到数据库中,只好用Python代码做了一步转换。
另外还有个地方比较难受,如果我在上一步参数中用了批处理,在下一步拿到的是批处理结果的List,List中的值无法和上上一步的信息对应。
文字描述有点乱,看下面代码。
ini
async def main(args: Args) -> Output:
params = args.params
infoList=params['infoList']
articleList= params['articleList']
# Base SQL insert command structure
insert_base = "INSERT INTO public_account_articles (digest, no, post_time_str, title, url, summary) VALUES"
values_list = []
index=0
# Iterate over each item in the infoList to create the VALUES part of the SQL command
for info in infoList:
article=articleList[index]
item=info['data']
...
index=index+1
# Join all VALUES with a comma and space for batch insertion
insert_values = ", ".join(values_list)
insertSQL = f"{insert_base} {insert_values};"
ret: Output = {
"insertSQL":insertSQL
}
return ret
只能说还需要很多进步空间啊:
- AI生成代码不太能理解我的意图,还是GPT4好用
- 两个序列的参数无法关联
- 数据库不能批处理
Step2.5:存入数据库
前面直接生成了SQL,所以存数据库这一步就省事了。
返回了两个值,如果是更新数据的话,rowNum是更新数据条数,如果是查询数据的话,是查询结果条数。
如果SQL有错误,提示信息太不友好了,看不出来哪错了。程序员是把异常直接抛了吗?
至此,存储工作流结束。
Step3:查询工作流
先看个完整版,然后再一步一步介绍。
Step3.1:接收参数
参数很简单,就一个query,获取用户提问的信息。
Step3.2:分析问题关键词,生成SQL
为了后面方便操作数据库,在这一步提取出来问题中的关键词。
这一步只提取了名词,可能不准确,以后再优化。
向量知识库能让动态更新多好,数据库操作在这种文档问答里还是不够好用。
sql
请分析用户沟通内容中的关键词,然后转换为查询SQL语句。
1、将关键词提取为关键词数组,示例:
["keyword1","keyword2"]
关键词要求为名词,比如提问:"你去过邻里中心吗?",关键词为:["邻里中心"],提问:"你在邻里中心喝过咖啡吗",关键词为:["邻里中心","咖啡"]
2、然后使用提取到的关键词,拼接为SQL语句,查询数据库相关的文章内容,SQL示例:SELECT title,summary,url FROM public_account_articles WHERE title LIKE '%keyword1%' OR summary LIKE '%keyword1%' or title LIKE '%keyword2%' OR summary LIKE '%keyword2%'
用户提问:{{query}}
你的回答://只回答SQL语句
Step3.3:查询数据库
老方法,直接执行。
COZE的文档真不好用,缺点示例和技巧讲解,特别在做数据库操作时候,不如直接拿LLM生成。
Step3.4:总结结果
查询出结果后,放入LLM进行总结。
go
请根据查询结果来回答用户的问题。
如果查询结果中无内容,则回答用户:"你提问的我不知道啊!"
如果有内容,则需要你根据查询结果回答用户的问题,语气为疯批姐妹。
用户问题:{{query}}
查询 结果:
```
{{query_result}}
```
你的回答:
输出结果配置中描述很重要,比如我在上面的Prompt中没有写过urls的要求,但是在输出结果中配置了,在输出时会把我需要的URL带上。
Step3.5:结束
这次带上结束步骤,是为了说明回答模式。
回答模式有两种
- 返回变量,由BOT生成回答:如果需要遵从人设,让BOT根据配置回答效果会更好一些
- 使用设定的内容直接回答:如果回答有特殊处理,可以固定回答内容
吐槽一下结束节点只能有一个,如果能让通过判断选择不同的结束节点,岂不是更灵活
Step3:发布
我尝试了授权到订阅号,跟我的账号关联到一起为读者提供服务也不错。
不过...截止到发稿前,读取公众号文章的插件还在挂着,我的文章还没爬完,所以体验效果很差。
将就看一下测试的结果:
BOTID:7358307559768047616 BOTURL:www.coze.cn/store/bot/7...