ASTRA框架:多主体图像生成中的身份与姿态解耦技术
2026/6/24 5:19:22
RAG 让 LLM 能「读」,Function Calling 让 LLM 能「做」。这篇带你从零实现一个带工具调用能力的聊天机器人——它能查天气、搜新闻、做算术,还能把结果整理成漂亮的格式返回。
最终效果: 用户:「北京今天天气怎么样?顺便帮我算下 23 * 47」 机器人: 🌤 北京今天:晴,气温 12~22°C,适合出行 🧮 23 × 47 = 1081 用户:「搜一下最新的 AI 新闻」 机器人:[调用搜索工具] 🔍 找到以下最新资讯: 1. OpenAI 发布 GPT-5 ... 2. Google DeepMind 宣布 ... 关键能力: ✅ 自动判断是否需要调用工具 ✅ 正确提取函数参数 ✅ 执行工具并将结果整合进回答 ✅ 多轮工具调用(一个问题可能需要调多个工具)# bot/tools.pyimportjsonimportrandomfromdatetimeimportdatetimefromtypingimportCallable# 工具注册表:名称 → (函数, 描述, 参数Schema)TOOLS_REGISTRY:dict[str,dict]={}deftool(name:str,description:str,params_schema:dict):"""装饰器:注册一个工具函数"""defdecorator(func:Callable):TOOLS_REGISTRY[name]={"function":func,"description":description,"parameters":params_schema,}returnfuncreturndecorator@tool(name="get_weather",description="获取指定城市的当前天气",params_schema={"type":"object","properties":{"city":{"type":"string","description":"城市名"},},"required":["city"]})defget_weather(city:str)->str:"""模拟天气 API(实际替换为真实 API)"""weathers=["晴","多云","阴","小雨"]temp_low=random.randint(-5,20)temp_high=random.randint(temp_low+5,temp_low+18)returnjson.dumps({"city":city,"weather":random.choice(weathers),"temp_low":temp_low,"temp_high":temp_high,"updated_at":datetime.now().isoformat()},ensure_ascii=False)@tool(name="calculate",description="执行数学计算表达式",params_schema={"type":"object","properties":{"expression":{"type":"string","description":"数学表达式,如 '23*47'"},},"required":["expression"]})defcalculate(expression:str)->str:try:# 安全起见只允许数字和基本运算符allowed=set("0123456789+-*/().% ")ifnotall(cinallowedforcinexpression):returnjson.dumps({"error":"不允许的表达式字符"})result=eval(expression)# 生产环境用 ast.literal_eval 更安全returnjson.dumps({"expression":expression,"result":result})exceptExceptionase:returnjson.dumps({"error":str(e)})@tool(name="search_news",description="搜索最新新闻(按关键词)",params_schema={"type":"object","properties":{"keyword":{"type":"string","description":"搜索关键词"},"limit":{"type":"integer","description":"返回条数(默认5)"},},"required":["keyword"]})defsearch_news(keyword:str,limit:int=5)->str:"""模拟搜索(实际接入搜索 API 或 Tavily)"""fake_news=[f"{keyword}相关重大进展报道",f"专家解读{keyword}领域新趋势",f"{month}月{keyword}行业数据发布",]returnjson.dumps([{"title":n,"source":"模拟源"}forninfake_news[:limit]],ensure_ascii=False)print(f"已注册{len(TOOLS_REGISTRY)}个工具:{list(TOOLS_REGISTRY.keys())}")# bot/main.pyfromopenaiimportOpenAIimportjsonfromtoolsimportTOOLS_REGISTRY client=OpenAI()defbuild_tools_definition():"""转换为 OpenAI Function Calling 格式"""return[{"type":"function","function":{"name":name,"description":info["description"],"parameters":info["parameters"]}}forname,infoinTOOLS_REGISTRY.items()]defexecute_tool(name:str,args:dict):"""安全执行工具并返回结果"""ifnamenotinTOOLS_REGISTRY:returnjson.dumps({"error":f"未知工具:{name}"})try:func=TOOLS_REGISTRY[name]["function"]result=func(**args)returnresultexceptExceptionase:returnjson.dumps({"error":f"工具执行错误:{e}"})defchat_with_tools(user_message:str,max_turns=5):"""带 Function Calling 的多轮对话循环"""messages=[{"role":"system","content":"你是一个有帮助的助手。使用可用工具来获取实时信息和执行操作。"}]messages.append({"role":"user","content":user_message})tools_def=build_tools_definition()forturninrange(max_turns):response=client.chat.completions.create(model="gpt-4o-mini",messages=messages,tools=tools_def,temperature=0.2,)msg=response.choices[0].message# 情况A:直接回答ifnotmsg.tool_calls:returnmsg.content# 情况B:调用工具messages.append(msg)# 记录 LLM 的决策fortcinmsg.tool_calls:func_name=tc.function.name func_args=json.loads(tc.function.arguments)print(f" 🔧 调用工具:{func_name}({func_args})")tool_result=execute_tool(func_name,func_args)print(f" 📋 结果:{tool_result[:100]}...")# 结果喂回 LLMmessages.append({"role":"tool","tool_call_id":tc.id,"content":tool_result})return"达到最大轮次限制"# CLI 交互if__name__=="__main__":print("🤖 函数调用机器人已启动!(输入 quit 退出)\n")whileTrue:query=input("你: ")ifquery.lower()=="quit":breakanswer=chat_with_tools(query)print(f"🤖:{answer}\n")# 运行python-mbot.main❌ 常见误区