当前位置: 首页 > news >正文

9.2 入门案例:简单函数调用机器人

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

❌ 常见误区

  • ❌ 工具描述写得越详细越好 — 太长的描述反而干扰 LLM 决策,简洁精准最好
  • ❌ 所有工具一次性注册 — 按场景分组加载,减少选择困难
  • ❌ 忽略工具的错误处理 — 工具可能失败,必须有 fallback 和异常捕获
http://www.jsqmd.com/news/1070589/

相关文章:

  • 高效窗口管理神器:AlwaysOnTop让多任务处理变得简单
  • 【从0到1构建一个ClaudeAgent】规划与协调-技能
  • AI写论文新选择!4款AI论文写作工具,提升论文质量有妙招!
  • NS-USBLoader完整指南:轻松管理Switch游戏文件的终极工具
  • 舰艇(VR)虚拟仿真训练系统
  • Consul:服务发现与服务网格的一站式方案
  • 告别“脏数据”:深入解析 VoxCPM 如何让 PDF 真正为 AI 所用
  • Laravel:PHP 开发者用了就回不去的框架
  • 2026年长沙画册设计公司怎么选?业内人士的实话
  • ComfyUI Reactor Node完整指南:如何快速实现高质量AI换脸
  • Hermes Agent 一周暴涨五万 Star,但我劝你别急着追
  • 【学习笔记】大模型时代全景图:从 GPT 到 Claude/DeepSeek,一文看懂 LLM 演进史
  • 从数据标注到自研模型:
  • 高校建设人工智能实验室,到底该如何选择服务商?
  • Java + EasyExcel 实现单个接口导出多个Excel
  • 管理驾驶舱如何帮助老板快速了解企业经营状态
  • 三位24岁博士团队创办映界科技,补齐具身智能感知短板,2026年订单有望超千万!
  • AI写专著必备攻略:4款工具助力,快速生成20万字专业专著!
  • UVa 571 Jugs
  • NS-USBLoader终极指南:快速搞定Switch游戏安装与系统注入的4个关键步骤
  • Claude Code + Kimi Code 配置指南
  • SMUDebugTool终极指南:免费开源AMD Ryzen处理器调试工具完全教程
  • Kimi LeetCode 3348. 最小可整除数位乘积 II Rust实现
  • 开源版Figma:Penpot,设计协同+代码生成,全栈设计平台
  • 4.5 呈现AI分析结果、报告与用户反馈接口
  • 【从0到1构建一个ClaudeAgent】并
  • 2026年版牙科修复材料行业投资分析及前景趋势预测报告
  • LangChain框架在高炉炼铁智能化领域的应用~系列文章15:性能优化与部署 — 把AI模型“搬进“炼铁车间
  • 互联网大厂 Java 求职面试中的技术探讨
  • GEO 服务商横向测评:森辰 GEO、剪流 GEO、增长超人怎么选|中小企避坑选型指南