以rg为例:我们做文本搜索工具时,常直接优先调用rg这个外部工具,如果返回失败则使用自己写的搜索逻辑,我看了pi-agent的源码,也是这么做的。但我认为有一点是没有防护到的,那就是错误不是出在是否搜索成功!而是搜索成功了,但解码失败。这是我真正踩坑的地方:rg作为第三方工具,返回给python时传递的是原始的字节,这个时候千万不要将 text设置为True。因为你并不清楚,rg返回的字节码到底是UTF-8还是GBK,如果设置为True,默认是由python来解码,而python则是根据你的电脑环境来选择一个解码,那么就很容易出现,rg返回的字节码是UTF-8,但是是用GBK在解码的情况(我就是这种情况)。这里往往就会直接出错!
所以我认为要做四层防护:
第一层:将解码环节交给程序
如果是由python解码,存在一定随机性。所以我们先将text设置为False,这样python只负责接收rg返还回来的原始字节码。由我们自己的代码先检查这个原始字节码的编码类型,再使用相同的编码类型来解码!
第二层:判断外部工具的的返回
仔细查一下这些外部工具的返回码!根据返回码进行下一步判断。 rg一般会返回退出码:
0:搜索成功,并且找到了内容
1:搜索成功,但没有找到内容
2及其他:搜索执行失败
因此应该明确判断:
if result.returncode == 0:
return xxx
if result.returncode == 1:
return "(no matches)"
# 其他情况才认为 rg 失败,失败则使用我们自己定义的代码去搜索
第三层:工具失败时使用自己的程序
这里就不展开了,当外部工具明确失效时,我们需要切换成自己的代码来实现任务目标。
第四层:兜底方案,确保进程不会崩!
如果外部工具或自己的实现全部查询失败!此时不能伪装成 no matches.我目前个人想的最优解是:把错误信息封装成文本反馈给LLM。至于LLM是输出还是使用bash我无法确定,我也不知道这种兜底做法是否正确。希望各位大佬指教一下!