微信扫码
添加专属顾问
我要投稿
重要: 阅读该文章之前,一定要先阅读:LLM之Agent初探
1、当业务中有大量的tool时,比如有上千个,这些tool的描述加起来,总长度已经大大超过了LLM的最大输入长度,即使能接受这么长的token,从attention机制来看,效果也好不到哪里去。
2、在LLM完成指令时,这几千个tool也不是都会被用上,那些没被用上的tool,且没被使用的tool占了绝大部分,大量的没被使用的tool占着大部分输入的token,造成资源的浪费,且推理性能也会有所下降。
基于以上两点考虑,尽量将与实际指令相关的tool加载进agent,丢弃那些不太可能会用到的tool是十分有必要的。
我们是不是可以将每次输入进来的instruction去和所有 tool 的 description进行语义匹配,将最相关的部分tool加载进agent,以便agent调用,这样,我们既可以将agent执行instruction过程中可能会用到的tool加载进来,又可以过滤掉那些不太可能会用到的tool,既能不损失效果,又达到了减少token消耗的目的。比如:当instruction是please calculator 735456*32时,我们最有可能用得到的tool肯定是和calculator相关的,不太可能用到的是获取实时新闻、获取当前时间之类的毫不相干的tool。
基于以往的经验,以上思考确实站得住脚,我们可以利用外挂知识库的思想,去完成这件事情。
首先,我们需要构建一个tool知识库,跟我们业务所有的相关的tool应该都在该知识库中维护,格式如下:
| tool_name | tool_description |
| calculator | Useful for when you need to answer questions about math. |
| wikipedia | A wrapper around Wikipedia. Useful for when you need to answer general questions about people, places, companies, facts, historical events, or other subjects. Input should be a search query. |
| terminal | Run shell commands on this Linux machine. |
| requests_delete | A portal to the internet. Use this when you need to make a DELETE request to a URL. Input should be a specific url, and the output will be the text response of the DELETE request. |
| duckduckgo_search | A wrapper around DuckDuckGo Search. Useful for when you need to answer questions about current events. Input should be a search query. |
| ... |
以上这些tool,都是langchain里面内置的,源码路径:langchain/agents/load_tools.py我把这些内置的tool都给存到了本地,用作tool知识库。
对以上tool知识库向量化,这里我的向量化模型是bge-large-zh,将tool_description向量化,使用HNSW方法构建索引,存于本地
注: ToolLLM 团队训练了一个 tool retriever模型,大家可以试下效果如何
def search(self, query, topk=3):
query_text_embedding = self.model.encode([query])
distances, indexs = self.faiss_index.search(query_text_embedding, topk)
tool_names = []
for idx in indexs[0]:
logger.info(self.data["name"][idx], "----" , self.data["description"][idx])
tool_names.append(self.data["name"][idx])
return tool_names
这里我们召回的是最有可能的 tool names,有了这些tool names后,我们就可以去加载对应的tool进agent了。
因为实际的tool name和使用load_tools方法加载tool时名字并非一样的,所以我这里加了个map。去映射对应的load_tools时使用的name
tool_name_map = {
"Calculator": "llm-math",
"Text-Message": "twilio",
"sleep": "sleep",
"Open-Meteo-API": "open-meteo-api",
"requests_get": "requests_get"
}
这里偷懒了,总共五十个,我只映射了五个,我们使用一个instruction试试
question = "please calculator 735456*32"
召回的top3 tool
Calculator ---- Useful for when you need to answer questions about math.
Text-Message ---- Useful for when you need to send a text message to a provided phone number.
sleep ---- Make agent sleep for a specified number of seconds.
agent回答:
Thought: I need to use the calculator tool to solve this math problem.
Action:
```
{
"action": "Calculator",
"action_input": "735456*32"
}
```
Observation: Answer: 23534592
I know what to respond
Action:
```
{
"action": "Final Answer",
"action_input": "23534592"
}
```
可以看出,agent成功调用了Calculator,说明该方法确实有效。
当你使用的是自定义的tool时,原理也是一样的,可以参考langchain/agents/load_tools.py中的源码,将tool组织成dict格式,如:
{
"tool1_name": "tool1的实现函数",
"tool2_name": "tool2的实现函数",
"tool3_name": "tool3的实现函数"
}
1、向量化模型效果决定该agent效果,若是连相关的tool都无法召回出来,那就无法将会被使用到的tool加载到agent中,agent在执行instruction时,无法调用正确的tool
2、当召回的数量较多时(如50以上),我们可以再加一个重排模块,对召回的tool重新排序。
3、当召回效果还是不好时,我们可以通过对tool的description优化,观察效果
4、当以上方法都尝试之后,可以使用LLM对query进行扩充,让LLM分析该instruction可能会用到哪些tool,最后将LLM扩充后的instruction和原始instruction都作为query来召回,将结果拼接
总之,这一套下来,可以做的事情又变多了
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-08-21
2025-08-20
2025-09-07
2025-08-21
2025-08-19
2025-08-05
2025-09-16
2025-08-20
2025-10-02
2025-09-08
2025-10-29
2025-10-29
2025-10-29
2025-10-28
2025-10-28
2025-10-28
2025-10-27
2025-10-27