banner
Woiot

周末不写代码

MCP、FunctionCall科普

Tip

提示
以下將 MCP (主要指服務端) 和 FunctionCall (主要指 OpenAI chat 規範的函數調用) 都籠統稱為 “插件”,方便快速理解,

  • 模型本身不具備調用 function 或 mcp Server 的能力
  • 兩者都是告訴遠程模型,客戶端具備那些額外能力 (如天氣插件、數據庫插件、畫圖插件),模型依據當前上下文 (當前語句),判斷當前場景是否應該執行某幾個插件,以及參數是什麼,並返回一個特殊的響應,將結果返回到客戶端
  • 模型本身只是返回各種 "文本"
  • 當客戶端 (如 CherryStudio、NextChat、openwebui) 觀察到模型返回了某種特殊的響應文本,客戶端就執行模型響應文本中告知的插件,當然,客戶端可以完全無視模型的特殊響應

一個簡易的流程如下
image.png

FunctionCall#

以獲取本地天氣為例子

請求結構如下:
通過 functionstools (最新的 functions 的別名) 告知了模型,當前客戶端具備獲取天氣的能力

{
    "messages": [
        {
            "role": "system",
            "content": "你是一個有幫助的助手。"
        },
        {
            "role": "user",
            "content": "今天上海天氣怎麼樣?,濕度怎麼樣?"
        }
    ],
    "functions": [
        {
            "name": "get_localtion_weather",
            "description": "get_localtion_weather,獲取某個地點的當前天氣情況",
            "parameters": {
                "type": "object",
                "properties": {
                    "localtion": {
                        "type": "string",
                        "description": "localtion,地點"
                    },
                    "need_humidity":{
                        "type":"boolean",
                        "description":"是否返回濕度,默認為false"
                    }
                },
                "required": [
                    "localtion"
                ]
            }
        }
    ],
    "function_call": "auto",
    "temperature": 0.5,
    "stream":false,
    "model": "gpt-4o"
}
curl --location 'https://api.xxxxx.com/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-xxxxx' \
--data '{
    "messages": [
        {
            "role": "system",
            "content": "你是一個有幫助的助手。"
        },
        {
            "role": "user",
            "content": "今天上海天氣怎麼樣?,濕度怎麼樣?"
        }
    ],
    "functions": [
        {
            "name": "get_localtion_weather",
            "description": "get_localtion_weather,獲取某個地點的當前天氣情況",
            "parameters": {
                "type": "object",
                "properties": {
                    "localtion": {
                        "type": "string",
                        "description": "localtion,地點"
                    },
                    "need_humidity":{
                        "type":"boolean",
                        "description":"是否返回濕度,默認為false"
                    }
                },
                "required": [
                    "localtion"
                ]
            }
        }
    ],
    "function_call": "auto",
    "temperature": 0.5,
    "stream":false,
    "model": "gpt-4o"
}'

響應結構如下:
image.png

客戶端執行本地的 get_localtion_weather 函數

整體流程如圖所示 (下圖截取自 OpenAI 的文檔,翻譯來自沉浸式翻譯)
image.png

MCP#

簡單理解:functionCall 是大家自己寫自己的,沒有一種統一的約定,而 MCP 是一種君子約定,mcpServer (查詢天氣插件) 遵循 MCP 協議開發,由 mcpClient (Cursor) 調用,原本需要自己寫函數,現在變成了調用別人的庫

image.png

MCP 重點在於 MCP 客戶端 (Cherry Studio) 如何發現 MCP 服務端 ("插件")、理解 “插件” 具備的能力、調用 “插件”、獲取 “插件” 的響應結果

至於

  • 將當前具備的插件功能發送到模型 (functions (別名 tools) 描述方式、提示詞方式)
  • MCP 客戶端 (Cherry Studio) 如何根據模型的響應判斷執行是否執行 “插件”,執行那幾個插件,則是客戶端自己定義
  • MCP 客戶端將插件執行結果返回給模型,也是可以自己定義

以下部分只是在應用領域領域,舉例描述了結合 MCP 對話流程,並沒有對 MCP 這個 “君子約定” 做具體的詳解

Cherry Studio 舉例#

配置 mcpServers 如下,其中只有一個獲取 和風天氣 的 server
源自:HeFeng Weather MCP Server | Glama

{
  "mcpServers": {
    "hefeng-weather": {
      "isActive": true,
      "command": "npx",
      "args": [
        "hefeng-mcp-weather@latest",
        "--apiKey=key-123132131321"
      ]
    }
  }
}

對話如下
image.png

  1. 查看本地攔截的第一次請求,可以發現是通過 tools 描述的方式,告訴模型,本地具備那些 “插件” 以及具備什麼能力
{
  "model": "gpt-4o",
  "messages": [
    {
      "role": "user",
      "content": "今天上海天氣怎麼樣?"
    }
  ],
  "temperature": 0.7,
  "max_tokens": 2000,
  "stream": true,
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "fd71edc4f65924613b9fd8330e78eb243",
        "description": "獲取中國國內的天氣預報",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "逗號分隔的經緯度信息 (e.g., 116.40,39.90)"
            },
            "days": {
              "type": "string",
              "enum": [
                "now",
                "24h",
                "72h",
                "168h",
                "3d",
                "7d",
                "10d",
                "15d",
                "30d"
              ],
              "description": "預報天數,now為實時天氣,24h為24小時預報,72h為72小時預報,168h為168小時預報,3d為3天預報,以此類推"
            }
          }
        }
      }
    }
  ]
}
  1. 查看第一次響應,模型判斷是否執行觸發調用插件。
    模型判斷執行需要用到 "天氣插件",模型本身只是做了判斷

image.png

  1. MCP 客戶端 (Cherry Studio) 執行 “天氣插件”,可以簡單看作調用了一个別人寫好的包或 API
  2. 將執行結果返回給模型,也就是加入對話上下文
{
  "model": "gpt-4o",
  "messages": [
    {
      "role": "user",
      "content": "今天上海天氣怎麼樣?"
    },
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_M4eYNv6oPaLunpZLe1iWdfiK",
          "function": {
            "name": "fd71edc4f65924613b9fd8330e78eb243",
            "arguments": "{\"days\":\"now\",\"location\":\"121,31\"}"
          },
          "type": "function"
        }
      ]
    },
    {
      "role": "tool",
      "content": "[{\"type\":\"text\",\"text\":\"地點: 121,31\\n觀測時間: 2025-03-27T16:51+08:00\\n天氣: 陰\\n溫度: 13°C\\n體感溫度: 12°C\\n風向: 東北風\\n風力: 1級\"}]",
      "tool_call_id": "call_M4eYNv6oPaLunpZLe1iWdfiK"
    }
  ],
  "temperature": 0.7,
  "max_tokens": 2000,
  "stream": true,
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "fd71edc4f65924613b9fd8330e78eb243",
        "description": "獲取中國國內的天氣預報",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "逗號分隔的經緯度信息 (e.g., 116.40,39.90)"
            },
            "days": {
              "type": "string",
              "enum": [
                "now",
                "24h",
                "72h",
                "168h",
                "3d",
                "7d",
                "10d",
                "15d",
                "30d"
              ],
              "description": "預報天數,now為實時天氣,24h為24小時預報,72h為72小時預報,168h為168小時預報,3d為3天預報,以此類推"
            }
          }
        }
      }
    }
  ]
}
  1. 模型結合上下文 (發送的對話歷史) 進行響應
    截取其中一部分
    image.png

Cherry Studio 是通過 functionCall 的方式,判斷應該執行那些 “插件” 的功能

自定義協議 (使用系統提示詞的方式)#

你是一個智能助手,你具備MCP功能,MCP可以理解為一種本地功能插件,當用戶的語句需要調用插件時,你應該嚴格按照以下規定返回,規定如下:
<plug>
	<pn>插件名稱</pn>
	<fn>函數名稱(功能名稱)</fn>
	<arg1>參數</arg1>
	<arg2>參數2<arg2>
	<arg3>參數3<arg3>
<plug/>。
當本地執行了某插件後,結果回按照以下格式返回
<tool_res>
	<plug>
		<pn>插件名稱</pn>
		<fn>函數名稱(功能名稱)</fn>
		<res>執行結果<res/>
	<plug/>
<tool_res/>

當前本地插件:
1.插件名稱:get_localtion_weather
	描述:查詢某個地點天氣插件
	 功能:
	 - query_now_weather:
	 	args:
	 		location:string,必需的,查詢地點
	 		need_humidity:boolean,非必需的,默認為false,是否返回濕度

圖中所示為 ChatBox,其他的客戶端會對 <xx><xx/> 進行處理,顯示不出來

image.png

image.png

參考視頻和鏈接🔗#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。