成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡(jiǎn)述MCP的原理-AI時(shí)代的USB接口

人工智能
本文介紹了mcp的基本底層原理,mcp作為AI大模型時(shí)代的標(biāo)準(zhǔn)化交互協(xié)議,具備顯著的優(yōu)勢(shì)。對(duì)于開(kāi)發(fā)者來(lái)說(shuō)mcp的出現(xiàn)降低了功能集成的成本,有更大的發(fā)展前景。

1 簡(jiǎn)介

2 執(zhí)行流程

3 mcp架構(gòu)

3.1 mcp架構(gòu)設(shè)計(jì)

3.2 mcp基本功能

4 mcp通信原理

4.1 JSON-RPC

4.2 通信方式

5 生命周期

5.1 環(huán)境搭建

5.2 建立連接獲取可用工具列表

5.3 調(diào)用工具

6 總結(jié)

1.簡(jiǎn)介

隨著AI的不斷發(fā)展,RAG(檢索增強(qiáng)生成)和function calling等技術(shù)的出現(xiàn),使得大語(yǔ)言模型的對(duì)話生成能力得到了增強(qiáng)。然而,function calling的實(shí)現(xiàn)邏輯比較復(fù)雜,一個(gè)簡(jiǎn)單的工具調(diào)用和實(shí)現(xiàn)方式需要針對(duì)不同的系統(tǒng)和大模型單獨(dú)編寫適配接口,十分復(fù)雜。

在此背景下,mcp應(yīng)運(yùn)而生,為當(dāng)前業(yè)內(nèi)AI高效可靠地調(diào)用外部工具實(shí)現(xiàn)了標(biāo)準(zhǔn)化。下面,我將帶大家一起認(rèn)識(shí)下mcp的基本原理和實(shí)現(xiàn)方式。

2.執(zhí)行流程

在我們開(kāi)始今天的正題之前,需要先了解下通常用戶與大模型進(jìn)行一次交互的執(zhí)行流程:↓

圖片圖片

當(dāng)用戶問(wèn)“北京今天天氣怎么樣”時(shí),我們的程序會(huì)將用戶的問(wèn)題、以及預(yù)先識(shí)別到的工具列表包裝成提示詞發(fā)送給大模型。熟悉function calling原理的小伙伴們都知道,這時(shí)候大模型會(huì)基于預(yù)訓(xùn)練的function calling技術(shù)識(shí)別到想要調(diào)用的工具是什么,并將其結(jié)構(gòu)化輸出。我們的程序識(shí)別后再去調(diào)用對(duì)應(yīng)的工具,最后將得到的結(jié)果和之前的上下文再次發(fā)送給大模型,得到最終的結(jié)果返回給用戶。當(dāng)然,如何讓大模型選擇要調(diào)用的工具不是本期的重點(diǎn),這里不再贅述。

我們需要關(guān)注重點(diǎn)在于工具調(diào)用的這部分邏輯,在mcp沒(méi)有誕生之前是這樣子調(diào)用的:

圖片圖片

每次新增一個(gè)系統(tǒng),都需要開(kāi)發(fā)者單獨(dú)做適配,即使tool的功能很簡(jiǎn)單,也會(huì)有極大的重復(fù)開(kāi)發(fā)量。 在mcp出現(xiàn)后,調(diào)用方式發(fā)生了變化:

圖片圖片

系統(tǒng)與工具的調(diào)用方式實(shí)現(xiàn)了解耦,調(diào)用邏輯統(tǒng)一封裝到了mcp client和 mcp server之間,這一步的交互方式由官方提供了不同開(kāi)發(fā)語(yǔ)言的sdk,不再需要我們開(kāi)發(fā)者處理了。

3.mcp架構(gòu)

3.1 mcp架構(gòu)設(shè)計(jì)

接下來(lái)讓我們?cè)敿?xì)看下mcp的架構(gòu)設(shè)計(jì),mcp實(shí)現(xiàn)采用了標(biāo)準(zhǔn)的C/S架構(gòu)模式。

圖片圖片

host:用于承載接受用戶請(qǐng)求,與大模型交互,調(diào)用工具的一段程序。廣義上我們可以將其看作是一個(gè)AI Agent。

client: 基于mcp規(guī)則實(shí)現(xiàn)的客戶端,負(fù)責(zé)與mcp服務(wù)端進(jìn)行通信。

server: 基于mcp規(guī)則實(shí)現(xiàn)的服務(wù)端,實(shí)現(xiàn)了工具內(nèi)部的邏輯操作,并將執(zhí)行結(jié)果返回給mcp客戶端。

3.2 mcp基本功能

當(dāng)下主流的與大模型交互的三要素?zé)o非是:工具、資源、提示詞,而mcp針對(duì)這三類均做了標(biāo)準(zhǔn)化處理。 以下是幾個(gè)重要的功能:

  • Resource:類似文件的數(shù)據(jù),可以被客戶端讀取,如數(shù)據(jù)庫(kù)數(shù)據(jù)或文件內(nèi)容。
  • Tools:可以被大模型調(diào)用的函數(shù)。
  • prompt:預(yù)先編寫的模板,幫助用戶完成特定任務(wù)。
  • sampling:允許server主動(dòng)通過(guò)client調(diào)用大模型獲取數(shù)據(jù)進(jìn)行采樣。

4.mcp通信原理

4.1 JSON-RPC

MCP采用JSON-RPC作為底層的通信協(xié)議。JSON-RPC是一種基于JSON的輕量級(jí)遠(yuǎn)程調(diào)用協(xié)議,相較于HTTP來(lái)說(shuō)它更加簡(jiǎn)潔、高效、容易處理。

請(qǐng)求結(jié)構(gòu)體

{
  jsonrpc: "2.0",
  id: number | string,
  method: string,
  params?: object
}

響應(yīng)結(jié)構(gòu)體

{
  jsonrpc: "2.0",
  id: number | string,
  result?: object,
  error?: {
    code: number,
    message: string,
    data?: unknown
  }
}

在發(fā)起通信的源碼中我們也可以看到確實(shí)使用到了json-rpc

@Override
public <T> Mono<T> sendRequest(String method, Object requestParams, TypeReference<T> typeRef) {
  String requestId = this.generateRequestId();

return Mono.<McpSchema.JSONRPCResponse>create(sink -> {
   this.pendingResponses.put(requestId, sink);
   // 構(gòu)建json-rpc請(qǐng)求
   McpSchema.JSONRPCRequest jsonrpcRequest = new McpSchema.JSONRPCRequest(McpSchema.JSONRPC_VERSION, method,requestId, requestParams);
            // 發(fā)送請(qǐng)求
   this.transport.sendMessage(jsonrpcRequest)
    .subscribe(v -> {}, error -> {
     this.pendingResponses.remove(requestId);
     sink.error(error);
    });
  }).timeout(this.requestTimeout).handle((jsonRpcResponse, sink) -> {
            // 省略異常處理
  });
 }

json-rpc與http的對(duì)比

屬性

HTTP

JSON-RPC

本質(zhì)

應(yīng)用層協(xié)議(Web核心協(xié)議)

輕量級(jí)RPC協(xié)議(基于JSON格式)

數(shù)據(jù)格式

支持JSON/XML/二進(jìn)制等多種格式

強(qiáng)制JSON格式,結(jié)構(gòu)更簡(jiǎn)潔

協(xié)議功能

包含緩存/認(rèn)證/狀態(tài)碼等完整功能

僅定義RPC調(diào)用規(guī)范(無(wú)底層邏輯)

通信模式

無(wú)狀態(tài),支持GET/POST等多方法

無(wú)狀態(tài),基于method字段調(diào)用

適用場(chǎng)景

Web API、瀏覽器交互、復(fù)雜業(yè)務(wù)

微服務(wù)內(nèi)部調(diào)用、物聯(lián)網(wǎng)等輕量場(chǎng)景

典型應(yīng)用

RESTful接口、網(wǎng)頁(yè)加載

服務(wù)間函數(shù)調(diào)用、嵌入式設(shè)備通信

4.2 通信方式

mcp基于以上通信協(xié)議,實(shí)現(xiàn)了以下通信方式:

STDIO

采用STDIO的方式,server端會(huì)在client端啟動(dòng)時(shí),作為client端的子進(jìn)程一起啟動(dòng)。這種方式適用于client和server在同一臺(tái)機(jī)器上通信的場(chǎng)景,通常用于工具調(diào)試。 它的實(shí)現(xiàn)原理是client和server兩個(gè)進(jìn)程間通過(guò)stdin和stdout進(jìn)行雙向通信。

優(yōu)點(diǎn):

  • 無(wú)外部依賴
  • 進(jìn)程間通信極快
  • 脫機(jī)可用

缺點(diǎn)

  • 并發(fā)能力差,是同步阻塞模型
  • 不支持多進(jìn)程通信

SSE

全名是server send event,是一種基于服務(wù)端到客戶端的流式傳輸方式,同時(shí)客戶端向服務(wù)端通信采用http的方式進(jìn)行傳輸。一般用于client在本地,server在遠(yuǎn)程服務(wù)器的場(chǎng)景。

圖片圖片

具體執(zhí)行流程如下:

  • 客戶端會(huì)向服務(wù)端的/sse端點(diǎn)發(fā)送http請(qǐng)求,服務(wù)端會(huì)返回sessionID等信息建立sse連接。
  • 初始化連接完成后,客戶端會(huì)向服務(wù)端請(qǐng)求tools/list接口獲取所有的tool列表,用于之后發(fā)送給大模型。
  • 在工具調(diào)用時(shí),客戶端會(huì)將調(diào)用信息如method,args通過(guò)post請(qǐng)求調(diào)用tools/call接口發(fā)送給服務(wù)端處理,服務(wù)端通過(guò)sse連接通知客戶端結(jié)果。

從本質(zhì)上看,sse是一種異步非阻塞的通信模型,極大的提高了agent的吞吐能力,但其服務(wù)器和客戶端需要做長(zhǎng)連接容易連接中斷,會(huì)丟失上下文。而官方在今年又推出了一項(xiàng)通信方式的更新,使用streamable http替代sse解決了以上的問(wèn)題。

5.生命周期

以下是mcp的生命周期:

圖片圖片

在mcp client和mcp server建立連接后,client會(huì)立即向server請(qǐng)求獲取可用的工具列表,這里也體現(xiàn)了mcp工具的動(dòng)態(tài)可插拔性。 接下來(lái)我將用Spring AI帶大家一起了解下mcp client的調(diào)用流程。

我們需要引入Spring AI的maven依賴,以及對(duì)spring AI對(duì)Mcp的依賴。

5.1 環(huán)境搭建

我們需要在server端向外暴露一個(gè)工具。

/** 構(gòu)建根據(jù)城市獲取天氣的tool
     * @param city 城市名稱
     * @return 天氣信息
     */
    @Tool(name = "getWeather", description = "根據(jù)城市獲取天氣")
    public String getWeather(String city) {
        return new String((city).getBytes(), StandardCharsets.UTF_8) + " 天氣為晴天 25℃";
    }

SpringAi會(huì)將標(biāo)有@Tool注解的方法自動(dòng)注入到ToolCallbackProvider中。 在client端,我們需要配置下mcp server的地址。

spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            server1: # sse服務(wù)端
              url: http://127.0.0.1:8080

寫一個(gè)demo來(lái)模擬用戶詢問(wèn)大模型的流程。

@Bean
    public CommandLineRunner callToolByLLM(ChatClient.Builder chatClientBuilder,
                                                 ToolCallbackProvider toolCallbackProvider,
                                                 ConfigurableApplicationContext context) {

        return args -> {
            System.out.println("基于spring-ai,llm調(diào)用方法------");
            Gson gson = new Gson();
            // 模擬用戶輸入的信息,并把工具列表傳給LLM
            String userInput = "獲取北京的天氣";
            System.out.println("用戶問(wèn): " + userInput);
            var chatClient = chatClientBuilder
                    .defaultUser("獲取北京的天氣")
                    .defaultTools(toolCallbackProvider)
                    .build();
            // 包裝請(qǐng)求LLM
            String content = chatClient.prompt(userInput).call().content();
            System.out.println("AI回答: " + gson.toJson(content));
            // 結(jié)束會(huì)話
            context.close();
        };
    }

5.2 建立連接獲取可用工具列表

當(dāng)程序啟動(dòng)后,spring會(huì)自動(dòng)注入McpClient和ToolCallbackProvider,此時(shí)會(huì)向server端發(fā)送請(qǐng)求獲取所有可用的工具列表。

public class SyncMcpToolCallbackProvider implements ToolCallbackProvider {
    @Override
    public ToolCallback[] getToolCallbacks() {

        var toolCallbacks = new ArrayList<>();

        this.mcpClients.stream().forEach(mcpClient -> {
            // mcpClient.listTools()
            toolCallbacks.addAll(mcpClient.listTools()
                    .tools()
                    .stream()
                    .filter(tool -> toolFilter.test(mcpClient, tool))
                    .map(tool -> new SyncMcpToolCallback(mcpClient, tool))
                    .toList());
        });
        var array = toolCallbacks.toArray(new ToolCallback[0]);
        validateToolCallbacks(array);
        return array;
    }
}

mcpClient會(huì)用json-rpc的格式調(diào)用tools/list方法,獲取當(dāng)前server下所有可用的工具列表。

public Mono<McpSchema.ListToolsResult> listTools(String cursor) {
    return this.withInitializationCheck("listing tools", initializedResult -> {
        if (this.serverCapabilities.tools() == null) {
            return Mono.error(new McpError("Server does not provide tools capability"));
        }
        return this.mcpSession.sendRequest(McpSchema.METHOD_TOOLS_LIST, new McpSchema.PaginatedRequest(cursor),
                LIST_TOOLS_RESULT_TYPE_REF);
    });
}

5.3 調(diào)用工具

當(dāng)用戶詢問(wèn)"北京今天天氣怎么樣"時(shí),程序會(huì)將上述獲取到的所有工具和用戶的信息生成提示詞告訴大模型,大模型選擇一個(gè)合適的工具告訴程序去調(diào)用工具。

public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatResponse) {

        // 構(gòu)建提示詞、工具
        ChatCompletionRequest request = createRequest(prompt, false);
        // 構(gòu)建要調(diào)用的大模型信息
        ChatModelObservationContext observationContext = ChatModelObservationContext.builder()
                .prompt(prompt)
                .provider(OpenAiApiConstants.PROVIDER_NAME)
                .requestOptions(prompt.getOptions())
                .build();

        ChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
                .observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
                        this.observationRegistry)
                .observe(() -> {
                    // post請(qǐng)求大模型Api
                    ResponseEntity<ChatCompletion> completionEntity = this.retryTemplate
                            .execute(ctx -> this.openAiApi.chatCompletionEntity(request, getAdditionalHttpHeaders(prompt)));
                    // 解析結(jié)果省略步驟 ...
                    return chatResponse;
                });

        // 判斷是否是工具調(diào)用
        if (toolExecutionEligibilityPredicate.isToolExecutionRequired(prompt.getOptions(), response)) {
            var toolExecutionResult = this.toolCallingManager.executeToolCalls(prompt, response);
            // 判斷是否返回結(jié)果
            if (toolExecutionResult.returnDirect()) {
                // Return tool execution result directly to the client.
                return ChatResponse.builder()
                        .from(response)
                        .generations(ToolExecutionResult.buildGenerations(toolExecutionResult))
                        .build();
            }
            else {
                // 帶著工具結(jié)果直接調(diào)用
                returnthis.internalCall(new Prompt(toolExecutionResult.conversationHistory(), prompt.getOptions()),response);
            }
        }
        return response;
    }

這里我們對(duì)大模型返回的結(jié)果進(jìn)行抓包,可以看到大模型想要調(diào)用的方法信息

[
    {
        "assistantMessage": {
            "toolCalls": [
                {
                    "id": "call_b4a9cb0f04a3495d941b71",
                    "type": "function",
                    "name": "spring_ai_mcp_client_server1_getWeather",
                    "arguments": "{\"city\": \"北京\"}"
                }
            ],
        // 中間內(nèi)容省略...
        "chatGenerationMetadata": {
            "metadata": {},
            "finishReason": "TOOL_CALLS",
            "contentFilters": []
        }
    }
]

mcpClient執(zhí)行調(diào)用邏輯。

public Mono<McpSchema.CallToolResult> callTool(McpSchema.CallToolRequest callToolRequest) {
  return this.withInitializationCheck("calling tools", initializedResult -> {
   if (this.serverCapabilities.tools() == null) {
    return Mono.error(new McpError("Server does not provide tools capability"));
   }
   return this.mcpSession.sendRequest(McpSchema.METHOD_TOOLS_CALL, callToolRequest, CALL_TOOL_RESULT_TYPE_REF);
  });
 }

執(zhí)行完成后,程序會(huì)攜帶結(jié)果和上下文再次請(qǐng)求大模型獲取結(jié)果,直到大模型認(rèn)為可以結(jié)束了,會(huì)將最終的結(jié)果返回給用戶。 此次請(qǐng)求的執(zhí)行結(jié)果如下:

圖片圖片

6.總結(jié)

本文介紹了mcp的基本底層原理,mcp作為AI大模型時(shí)代的標(biāo)準(zhǔn)化交互協(xié)議,具備顯著的優(yōu)勢(shì)。對(duì)于開(kāi)發(fā)者來(lái)說(shuō)mcp的出現(xiàn)降低了功能集成的成本,有更大的發(fā)展前景。但mcp當(dāng)下也有很多不可回避的缺點(diǎn),比如頻繁與大模型交互,為了保證消息連貫上下文內(nèi)容劇增,token消耗大,使用成本變高。另外在安全性方面不夠健全,對(duì)于提示詞注入等手段沒(méi)有成熟的解決方案。

盡管mcp當(dāng)前不是那么的完美無(wú)缺,但他的出現(xiàn)給AI的發(fā)展提供了一種全新的交互模式和更多的可能。

關(guān)于作者

張皓昱,轉(zhuǎn)轉(zhuǎn)門店后端開(kāi)發(fā)工程師

責(zé)任編輯:武曉燕 來(lái)源: 轉(zhuǎn)轉(zhuǎn)技術(shù)
相關(guān)推薦

2016-11-09 17:19:22

1

2009-05-25 10:25:12

1

2022-08-16 08:13:08

數(shù)據(jù)安全數(shù)據(jù)安全治理管理能力

2011-03-10 13:18:54

SQLwhere

2017-11-23 14:25:25

系統(tǒng)設(shè)計(jì)消息隊(duì)列以用戶為中心的系統(tǒng)設(shè)計(jì)

2018-02-01 21:18:40

戴爾

2010-09-07 17:02:39

家庭布線

2010-09-08 15:51:53

SQL語(yǔ)句where

2024-07-10 10:54:44

2016-12-22 09:31:35

UbuntuSHA-1資源

2018-01-21 23:14:09

戴爾

2013-05-16 10:07:42

固態(tài)硬盤RAID 0三星840 Pro

2024-05-31 13:04:09

2024-02-20 22:13:49

SQL語(yǔ)句編程

2010-01-19 10:02:03

Windows 7 S下載

2011-04-01 15:53:20

T-SQLDateTime

2021-11-15 06:56:45

MyBatis開(kāi)發(fā)項(xiàng)目

2022-03-01 07:37:30

MySQL場(chǎng)景框架

2017-11-23 17:23:23

2011-04-02 15:36:47

OSPF
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久综合| 一区二区成人在线 | 亚洲性免费| 免费视频一区二区 | 天天天天操 | 欧美一级精品片在线看 | av色噜噜 | 久久精品伊人 | 91精品国产一区二区三区香蕉 | 色资源在线观看 | 高清人人天天夜夜曰狠狠狠狠 | 国产午夜精品一区二区三区 | 一区二区三区中文字幕 | 欧美极品在线观看 | 国产成人精品一区二 | 在线看片福利 | 久久伊人青青草 | 91精品国产麻豆 | 欧美一a | 欧美一区二区三区视频 | 中文字幕在线网 | 精品久久久久香蕉网 | 狠狠的干 | 毛片免费观看视频 | 99精品欧美一区二区三区 | 日韩视频在线免费观看 | 国产精品国色综合久久 | 欧美天堂在线 | 观看av| 国产精品视频在线免费观看 | 99视频在线免费观看 | 欧美成人一区二免费视频软件 | 中文字幕视频在线 | 我想看一级黄色毛片 | 久热m3u8 | 精品国产乱码久久久久久丨区2区 | 精品1区2区3区4区 | 亚洲国产黄 | 亚洲福利网站 | 欧美日韩中文在线 | 波多野结衣一二三区 |