@@ -180,6 +180,143 @@ if __name__ == '__main__':
180180
181181```
182182
183+ #### 工程化调用工具
184+
185+ 其实以上的调用方式都是换汤不换药,就是将可调用的工具(函数)作为提示词的一部分,传入给大模型。让大模型做选择填空,并返回特定格式。
186+
187+ - 选择:是否调用以及调用哪些
188+ - 填空:调用函数的参数填什么
189+
190+ <Highlight >Agent中的大模型,第一核心能力是指令遵循能力</Highlight >。
191+
192+ ``` python showLineNumbers
193+ import json
194+ from dataclasses import dataclass
195+ from typing import Any, Callable
196+
197+ @dataclass
198+ class Tool :
199+ """ 极简工具对象,仅保留名称、描述和同步调用入口。"""
200+
201+ name: str
202+ description: str
203+ func: Callable[... , Any]
204+
205+ def invoke (self , ** kwargs : Any) -> Any:
206+ """ 同步调用底层函数。"""
207+ return self .func(** kwargs)
208+
209+
210+ def tool (
211+ func : Callable[... , Any] | None = None ,
212+ * ,
213+ name : str | None = None ,
214+ description : str = " " ,
215+ ) -> Tool | Callable[[Callable[... , Any]], Tool]:
216+ """ 把被装饰的同步函数封装成 `Tool`,支持可选参数。"""
217+
218+ def decorator (fn : Callable[... , Any]) -> Tool:
219+ tool_name = name or fn.__name__
220+ tool_description = (description or fn.__doc__ or " " ).strip()
221+ """
222+ 装饰器可以收集工具函数信息作为大模型的上下文。其实这里也可以让大模型自己将工具的描述信息二次加工或者直接通过源代码生成,即让大模型自己生成工具的描述信息。
223+
224+ import inspect
225+ tool_description = 大模型推理("请根据以下函数源码,生成工具的描述信息:"+inspect.getsource(func))
226+ """
227+ return Tool(name = tool_name, description = tool_description, func = fn)
228+
229+ if func is None :
230+ return decorator
231+ return decorator(func)
232+
233+
234+ @tool
235+ def get_weather (city : str ) -> str :
236+ """
237+ 描述:根据城市名称返回天气。
238+
239+ 参数:
240+ - city: 城市名称 str
241+
242+ 返回:
243+ - 天气信息 str
244+
245+ """
246+ fake_db = {
247+ " 北京" : " 晴天,12℃" ,
248+ " 上海" : " 多云,15℃" ,
249+ " 深圳" : " 小雨,24℃" ,
250+ }
251+ return fake_db.get(city, " 暂无天气数据" )
252+
253+
254+ class FakeChatModel :
255+ """ 模拟选择工具的 LLM,如果检测到“天气”则调用 weather 工具。"""
256+
257+ def __init__ (self , tools : list[Tool] = None ) -> None :
258+ if tools is not None :
259+ self .bind_tools(tools)
260+
261+ def bind_tools (self , tools : list[Tool]) -> None :
262+ self .tools = {tool.name: tool for tool in tools}
263+
264+ def run (self , user_input : str ) -> str :
265+ """ 模拟 LLM 的推理、构造工具调用 JSON,再执行工具。"""
266+ prompt_template = """
267+ 你是一个乐于助人的助手,根据用户输入的提示词,完成任务。
268+
269+ 你也许有一些工具可以选择,如果需要使用工具,请选择一个工具,并填入工具的参数。
270+
271+ 这是用户输入的提示词:
272+
273+ {user_input}
274+
275+ 这是工具列表:
276+
277+ {tools}
278+
279+ 如果你需要使用工具,请按照以下格式返回:
280+ [
281+ {{ "Tool": "工具名称", "ToolArgs": {{ "工具参数1": "参数值1", "工具参数2": "参数值2"}}}}
282+ ]
283+
284+ 如果你不需要使用工具,请直接返回:
285+ [
286+ {{ "Message": "回答内容"}}
287+ ]
288+ """
289+
290+ prompt = prompt_template.format(user_input = user_input, tools = self .tools)
291+ print (prompt)
292+
293+ # 大模型做 选择填空题,选择一个工具,并填入工具的参数(示例)
294+ result = """ [
295+ {"Tool":"get_weather","ToolArgs":{"city":"上海"}}
296+ ]"""
297+ result_json = json.loads(result)
298+ if result_json[0 ].get(" Tool" , None ):
299+ tool_name = result_json[0 ][" Tool" ]
300+ tool_args = result_json[0 ][" ToolArgs" ]
301+ tools_result = self .tools[tool_name].invoke(** tool_args)
302+ # self.run(tools_result) 可以将工具的结果作为用户输入,继续推理
303+ return [{" Message" : tools_result}]
304+ else :
305+ return [{" Message" : result_json[0 ][" Message" ]}]
306+
307+
308+ if __name__ == " __main__" :
309+ tools = [get_weather] # 装饰器已经把函数变成 Tool
310+ model = FakeChatModel()
311+ model.bind_tools(tools)
312+
313+ question = " 上海 天气"
314+ print (f " 用户: { question} " )
315+ result = model.run(question)
316+ print (f " 模型: { result} " )
317+ ```
318+
319+
183320#### Mcp
184321
185322一种专为大模型设计的API接口,简单易用,岗位要求基本与传统API开发一致,但需要对大模型特性有所了解。
@@ -233,15 +370,6 @@ A2A 是 Agent 到 Agent 的通信,是多智能体系统中的一种通信方
233370
234371参考文章: https://www.aimodels.fyi/papers/arxiv/why-do-multi-agent-llm-systems-fail
235372
236- ## 框架分析
237-
238- langchain
239-
240- langgraph、langgraph-swarm
241-
242- AutoGen
243-
244- MG
245373
246374## 案例分析
247375
0 commit comments