|
之前展示过我自己搞的智能助手【奥特曼】,他可以打开本机的软件工具,可以联网查询天气,可以控制我的小米电视,还可以调用外部接口完成写论文存储到固定位置等任务,那这部分具体是怎么做的,哈哈其实核心就是大模型+agent tool,本次就给大家分享一下这个部分,还没有看过我的智能助手的可以看一下如下视频
背景介绍
起初只是想搞一个语音助手,就是根据用户的语音输入,给出反馈,后来逐步完善成可以调用各种工具的智能体了,后续还在不断完善,过段时间会开源,^_^ 工具使用
很多大模型都有调用工具函数的能力,但是确实效果差距有点大,我测试了多个大模型,最后发现,llama3.1,gemma2效果是最好的,本次实验,大模型就是使用的llama3.1,工具封装使用的langchain_experimental这个包,这个包可以基于大模型封装各种tool,以供大模型去识别调用,执行你设定的任务,还可以传递参数。 具体流程
首先构造工具函数和确定参数,这里以打开 浏览器的function为例: 首先需要找到浏览器exe的路径如下:

在浏览器的图标上右击,点击【打开文件所在位置】,然后,如下 
在打开的位置中,右击浏览器图标,点击【复制文件地址】,这样你就得到了exe的地址
"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe" 这个在构造函数时使用。 定义从ollama的接口获取大模型,这里使用的langchain_experimental包中的OllamaFunctions函数,这个是使用大模型调用工具的函数
model_tool=OllamaFunctions(model='llama3.1:8b',base_url='http://localhost:11434',format='json')
构造调用函数:这里要构造一个可以调用exe文件的函数,我们使用os的调用系统命令的方式去运行exe
os.startfile(r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe") 这个地方很简答,当然你也可以 使用其他python内置方式去调用exe,这里为了更具通用性,也就是当你调用工具时都走这个函数,我们需要给函数传递一个参数,用来识别我们是对什么工具进行操作,具体函数如下: defopen_tool(name):
if name == "音乐播放器":os.startfile(r"C:\Program Files\NetEase\CloudMusic\cloudmusic.exe")elif name == "录屏程序":# 需要启动的 Python 脚本路径script_path = r'F:/alloy-voice-assistant-main/luping_tool_2.py >> lp.log 2>&1 &'python_p="D:/anaconda3/python.exe"# 使用 os.system 在后台启动进程os.system(f'start /B {python_p} {script_path}')return name+"已打开,并缩小到任务栏中了"elif name == "微软浏览器":os.startfile(r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe")else:os.startfile(r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe")
return name+"已打开"
我这里只集成了四个工具,你也可以集成更多进来。 业务处理函数映射,方便后续调用
fn_map={'open_tool' pen_tool}这里是为了后边调用时更方便使用string类型确定fun。 通过业务处理函数描述,把业务函数绑定到大模型上
llm_with_tool=model_tool.bind_tools(tools=[{'name':'open_tool','description':'根据用户的命令打开音乐播放器、录屏程序、微软浏览器或谷歌浏览器','parameters':{'type':'object','properties':{'name':{'type':'string','description':'支持录屏程序,音乐播放器目前仅支持网易音乐播放器,浏览器的名字,目前仅支持微软浏览器、谷歌浏览器',}},'required':['name'],},}])讲解一下这个绑定方式,这个主要是OllamaFunctions的绑定工具到大模型的方式,首先tools中可以定义多个工具,每个工具以自定格式进行书写;具体到工具参数 name:这里填写工具的名称,和映射中的一直,不可以和其他重复 description:这里是一段自然语言描述,描述本工具的作用 parameters:这个是参数定义,就是你调用工具函数时传递的参数,这里可以是多个参数,每个参数是一个字典形式,放在properties中,其中 required 是参数名字,多个参数时,就罗列多个在一个list中。
好了这样一个agent tool的定义就完成了,下面进行调用
调用代码如下
defchat_handler(chat_str):print("====================")print(f"user:{chat_str}")print("--------------------")ai_msg=llm_with_tool.invoke(chat_str)print(ai_msg.tool_calls)ifai_msg.tool_calls:fn_name=ai_msg.tool_calls[0]['name']fn_param=ai_msg.tool_calls[0]['args']print("ai:......")print(f"调用函数:{fn_name},参数:{fn_param}")res=fn_map[fn_name](**fn_param)returnreselse:returnai_msg.content 大模型处理输入并确定需要调用的业务函数,并实际调用业务函数 这里讲解一下调用原理,大模型结合工具的描述和用户的输入进行匹配,如果有参数,会解析参数出来,然后去调用对应tool,如果没有匹配上任何tool,就会按照用户直接和llm对话的方式去返回结果,这样不至于硬性匹配所谓最相似的工具。 |