大内密探零零发之 iOS 密探神器 AI 大模型 MCP 服务开发记(下)

引子

上回说到,零零发的 "密探发明聊天棚" 虽已初具雏形,却卡在了最关键的一步 ------ 工具调用结果没法传给军师。

在本篇京城八卦中,您将学到如下内容:

  • 引子
  • 🔄 第五回:打通任督二脉!工具结果传给军师
  • 🧪 第六回:实战演练!看看神器好不好使
    • 第一步:密探发问
    • 第二步:军师接招
    • 第三步:调用工具
    • 第四步:结果回传
    • 第五步:军师总结
  • 🚀 第七回:查漏补缺!这些坑可别踩
  • 🎭 终章:神器大成,零零发的 "发明哲学"

就像他那 "要你命三千" 明明装好了十八般兵器,却忘了装发射按钮,急得零零发抓耳挠腮:"岂有此理!这就好比跟无相皇打架,都掏出刀了却发现没开刃,岂不是贻笑大方?:("


🔄 第五回:打通任督二脉!工具结果传给军师

零零发蹲在地上画了三个圈:"第一步,军师让调用工具;第二步,咱们调用工具拿结果;第三步,把结果塞回给军师。这三步环环相扣,少一步都成不了事!" 说着就在sendMessage里补全了逻辑,活像给断了的经脉接上线。

看看这补全的代码,每一步都透着零零发的 "发明智慧":

swift 复制代码
// 完善后的发送消息方法(新增处理工具调用的逻辑)
func sendMessage() {
    // 上集已有代码:添加用户消息、清空输入框、开始加载
    let userMessage = Request.Message(role: .user, content: [.text(text: inputText)])
    messages.append(ChatMessage(message: userMessage))
    inputText = ""
    isLoading = true
    let allMessages = messages.map(\.message)
    
    Task {
        do {
            let advisorResponse = try await advisorService.send(messages: allMessages)
            let assistantMessage = ChatMessage(
                message: Request.Message(role: .assistant, content: advisorResponse.content)
            )
            self.messages.append(assistantMessage)
            
            // 新增:遍历军师的回复,看看有没有让调用工具
            for content in advisorResponse.content {
                switch content {
                case .toolUse(let toolId, let toolName, let input):
                    // 调用工具,并把结果回传给军师(这步是关键!)
                    try await useTool(toolId: toolId, toolName: toolName, input: input)
                case .text, .toolResult:
                    continue // 其他类型的消息不用处理
                }
            }
        } catch {
            print("出错啦!零零发:'哎呀,零件掉了!' 错误:\(error)")
        }
        isLoading = false
    }
}

// 新增:调用工具并回传结果给军师的方法
private func useTool(toolId: String, toolName: String, input: [String: String]) async throws {
    // 1. 找对应的工具(总不能张冠李戴,拿查发明的工具去测暗器吧)
    guard let tool = inventionServer.tools.first(where: { $0.name == toolName }) else {
        print("没找到工具:\(toolName),零零发:'这零件我好像没见过啊?'")
        return
    }
    
    // 2. 调用工具拿结果(相当于按动"要你命三千"的发射按钮)
    let toolResult = try await inventionServer.call(tool)
    print("工具返回结果:\(toolResult),零零发:'成了!'")
    
    // 3. 把结果包装成"工具结果消息",加到聊天记录里
    let toolResultMessage = Request.Message(
        role: .user, // 注意:工具结果也得算用户这边的消息,不然军师不认
        content: [.toolResult(toolUseId: toolId, content: toolResult)]
    )
    self.messages.append(ChatMessage(message: toolResultMessage))
    
    // 4. 把包含工具结果的所有消息再发给军师,让他接着分析
    let allMessages = self.messages.map(\.message)
    let finalResponse = try await advisorService.send(messages: allMessages)
    let finalMessage = ChatMessage(
        message: Request.Message(role: .assistant, content: finalResponse.content)
    )
    self.messages.append(finalMessage)
}

零零发拍着胸脯说:"瞧见没?这useTool方法就是打通任督二脉的关键!工具结果必须带toolUseId,跟军师发的 ID 对上,不然他老人家哪知道这结果是哪个请求的?就像给皇上递奏折,得标上编号,不然皇上哪记得你上次说的是啥!"

🧪 第六回:实战演练!看看神器好不好使

代码写完了,零零发搓着手说:"是骡子是马拉出来遛遛!咱们模拟个场景 ------ 我问军师'我的天外飞仙破解器状态如何?',看看它能不能自动查、自动答。"

第一步:密探发问

输入框敲上:"军师,我那天外飞仙破解器咋样了?能对付无相皇不?" 点发送。此时 APP 把消息发给 Claude,附带可用工具列表。

第二步:军师接招

Claude 收到消息,一看是查发明状态,立马回复:"稍等,我这就调用工具查查您的天外飞仙破解器状态。" 同时偷偷发了个工具调用指令(藏在 JSON 里,用户看不见):

json 复制代码
{
  "content": [
    {
      "type": "text",
      "text": "我这就帮您查查天外飞仙破解器的状态..."
    },
    {
      "type": "tool_use",
      "id": "toolu_007", // 工具调用ID,等会儿结果要用
      "name": "check_latest_invention",
      "input": {}
    }
  ]
}

第三步:调用工具

APP 检测到tool_use指令,立马调用check_latest_invention工具,从 "密探发明库" 拿到结果:"天外飞仙破解器:电量80%,状态:已校准"

第四步:结果回传

APP 把结果包装成tool_result消息,发给军师:

json 复制代码
{
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_007", // 必须跟之前的ID对上
      "content": "天外飞仙破解器:电量80%,状态:已校准"
    }
  ],
  "role": "user"
}

第五步:军师总结

Claude 收到结果,整理成人话回复:"回禀密探,您的天外飞仙破解器目前电量 80%,已校准完毕,对付无相皇绰绰有余!不过记得打完架充个电,免得下次急用。"

零零发看着完整的聊天记录,笑得合不拢嘴:"完美!这流程比我给琴操姑娘修胭脂盒还顺!从发问、调用工具到拿到答案,一气呵成,简直是'居家旅行、杀人灭口'之必备神器啊!"

🚀 第七回:查漏补缺!这些坑可别踩

零零发毕竟是老江湖,知道新发明总有小毛病,特意列了几个 "避坑指南":

  1. 权限问题

    "调用'密探发明库'得先申请权限,不然就像没带腰牌想进皇宫 ------ 门儿都没有!" 务必在 Info.plist 里加好描述,不然 APP 会闪退。

  2. 角色别搞反

    "用户发的消息角色是user,军师是assistant,工具结果也算user这边的。搞错了角色,军师就会像被点了穴 ------ 一动不动,还报错给你看!"

  3. tool_use_id 要对应

    "工具结果的 ID 必须跟军师发的对上,就像暗器上的标记,错了就会乱开枪!" 要是 ID 对不上,Claude 会一脸懵:"这结果是啥玩意儿?我没问过啊!"

  4. 异常处理不能少

    "万一工具调用失败,比如没数据,得告诉用户'查不到哦',别让 APP 直接崩溃。就像我那发明偶尔卡壳,总得有个'重启按钮'吧?"

🎭 终章:神器大成,零零发的 "发明哲学"

零零发把 "密探神器" 往桌上一放,对着镜头感慨道:"你看这 MCP 协议,不就是给 APP 装了个'会思考的脑子'吗?以前的 APP 是'你问一句,它答一句',现在倒好,它会自己找工具、查数据,跟个小密探似的!"

他拿起 "天外飞仙破解器" 比划着:"这就像我当年发明武器,不光要能打,还得会'思考'------ 敌人来了,它自动选刀还是选枪。做 APP 也一样,光有界面不够,得让它懂用户、会办事,这才是'智能'的真谛啊!"

最后,零零发凑近屏幕,挤眉弄眼道:"记住了啊,搞开发就像追姑娘 ------ 得懂她心思,还得有手段。MCP 就是你的'泡妞秘籍',用好了,你的 APP 能跟用户聊得眉来眼去,比我跟琴操姑娘还投缘呢!"

要知零零发与琴操姑娘后事如何?我们下次再叙喽。

感谢宝子们的观赏,再会啦!8-)

相关推荐
大熊猫侯佩3 小时前
大内密探零零发之 iOS 密探神器 AI 大模型 MCP 服务开发记(上)
llm·ai编程·mcp
下位子3 小时前
『AI 编程』用 Claude Code 从零到一开发全栈减脂追踪应用
前端·ai编程·claude
子昕3 小时前
Claude Code插件系统上线!AI编程的“App Store”时代来了
ai编程
Java中文社群4 小时前
n8n和在线免费体验蚂蚁万亿开源大模型Ling-1T!
aigc·ai编程
302AI4 小时前
体验升级而非颠覆,API成本直降75%:DeepSeek-V3.2-Exp评测
人工智能·llm·deepseek
聚客AI6 小时前
🥺单智能体总是翻车?可能是你缺了这份LangGraph多Agent架构指南
人工智能·llm·agent
yaocheng的ai分身6 小时前
氛围编码革命进入下一阶段: Bolt v2
ai编程
爱可生开源社区6 小时前
2025 年 9 月《大模型 SQL 能力排行榜》发布,新增 Kimi K2 最新版测评!
sql·llm
大模型教程6 小时前
半小时部署企业智能问答系统!MaxKB让知识管理效率翻倍
程序员·llm·agent