近期LLM的一些趋势之二——MCP

书接上回,文末提到一个点:

当然也有不变的点:工具的建设依然很重要。只不过,今年需要更多的思考如何将这些基建工具与上述的flowgraph结合起来。

当时没有展开写,而最近随着MCP(Managed Context Protocol)的逐步普及和应用,今天来补一下当时挖的坑。

什么是MCP

参考MCP的官方文档,MCP是一个用于管理和使用上下文的协议,旨在帮助开发者更好地与大型语言模型(LLM)进行交互。它提供了一种结构化的方法来处理上下文信息,使得在与LLM进行对话时,可以更有效地传递和管理信息。

它的工作流程也很简单(LLM以Claude为例):

When you submit a query:

  • The client gets the list of available tools from the server
  • Your query is sent to Claude along with tool descriptions
  • Claude decides which tools (if any) to use
  • The client executes any requested tool calls through the server
  • Results are sent back to Claude
  • Claude provides a natural language response
  • The response is displayed to you

从工作流程来看,是不是感觉跟我们熟悉的Function Calling有些类似?

MCP vs function calling

MCP和Function Calling的区别在于:

  1. 功能范围:MCP不仅仅是一个函数调用的接口,它还包括了上下文管理、工具描述和结果处理等多个方面的功能。而Function Calling主要集中在函数调用本身。
  2. 上下文管理:MCP提供了更为全面的上下文管理功能,可以在多个工具之间共享和传递上下文信息。而Function Calling通常是针对单个函数的调用,缺乏跨函数的上下文管理能力。
  3. 工具描述:MCP允许开发者为每个工具提供详细的描述信息,以便LLM更好地理解如何使用这些工具。而Function Calling通常只提供函数名和参数,缺乏详细的描述信息。
  4. 结果处理:MCP在结果处理上也提供了更多的灵活性,可以根据不同的工具和上下文信息进行定制化的结果处理。而Function Calling通常是固定的结果处理方式,缺乏灵活性。
  5. 适用场景:MCP更适合于复杂的应用场景,尤其是需要多个工具协同工作的场景。而Function Calling更适合于简单的函数调用场景。
  6. 扩展性:MCP的设计考虑了未来的扩展性,可以方便地添加新的工具和功能。而Function Calling在扩展性上相对较弱,添加新功能可能需要较大的改动。
  7. 社区支持:MCP是一个开放的协议,得到了广泛的社区支持和参与。而Function Calling通常是由特定的公司或组织维护,缺乏广泛的社区支持。
  8. 文档和示例:MCP提供了详细的文档和示例,帮助开发者快速上手。而Function Calling的文档和示例相对较少,可能需要开发者自行摸索。
  9. 学习曲线:由于MCP的功能更为全面和复杂,学习曲线相对较陡。而Function Calling相对简单,学习曲线较平缓。
  10. 性能:在性能方面,MCP可能会因为其复杂性而引入一定的性能开销。而Function Calling通常是直接调用函数,性能较高。
  11. 安全性:MCP在设计上考虑了安全性,提供了一些安全机制来保护上下文信息。而Function Calling通常缺乏这样的安全机制,可能存在一定的安全隐患。
  12. 兼容性:MCP是一个开放的协议,可以与多种语言和平台兼容。而Function Calling通常是针对特定语言或平台的,兼容性较差。

此外,可以参考《MCP 与 Function Call 区别》。其中提到一个比喻非常形象:

  • MCP:通用协议层面的标准约定,就像给 LLM 使用的“USB-C规范”。
  • Function Call:特定大模型厂商提供的独特特性,就像某品牌手机的专属充电协议。

如何使用?

回到我们最开始的观点:不变的点:工具的建设依然很重要。对于MCP来说,主要是指MCP Server。作为一个gopher,推荐者以下两个项目:

两个项目都是golang传统的开箱即用。

要让LLM能够把提供工具、资源、prompt驱动起来,需要借助 MCP client 这个桥梁。而目前从官方推荐的Clients来看,MCP client 主要以两种形式出现:①面向普通用户的application应用,如Claude Desktop App;②面向开发者的agent框架库,如mcp-agent。这里推荐fast-agent.

MCP 的意义

MCP的意义在于它为开发者提供了一种结构化的方法来管理和使用上下文信息,使得与LLM的交互更加高效和灵活。通过MCP,开发者可以更好地利用LLM的能力,构建出更为复杂和智能的应用程序。

还是有点抽象,对不对?从过去技术发展历史来看,MCP跟当年的微服务架构有点类似。不同的是,微服务架构下更多的还是工程、业务逻辑驱动数据流和控制流,而MCP则是将LLM作为决策中枢。也就是说,MCP是一个面向LLM的微服务架构。

太阳底下没有新鲜事,以前微服务架构下的经验在MCP架构下会有一定的借鉴意义。另一方面,MCP的出现也意味着我们需要重新审视和设计我们的应用架构,以更好地适应LLM的特点和需求。

MacBook M1配置ESP32开发环境

兴趣使然,斥巨资25元淘宝了一块ESP32的开发版,也就是最“昂贵”的ESP32 DEVKIT V1。

已经有将近10年没有做嵌入式开发,正琢磨着要不要搞一个Windows环境做ESP32开发,搜索一圈以后发现,esp-idf对各个平台的支持居然都不错。因此尝试在M1上面配置了一下ESP32的开发环境。

esp-idf本质上是一个VS Code插件。因此,所谓的安装配置过程就是ESP-IDF VS Code 插件的安装过程。整体流程基本做到了一路下一步。如果你跟我一样是苹果M1的环境,有几个点需要在注意一下:

  • idf插件依赖python 3环境。macOS Monterey自带的python3会在一些路径识别上出现头文件无法找到的问题,导致安装失败。诸如:

clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -iwithsysroot/System/Library/Frameworks/System.framework/PrivateHeaders -iwithsysroot/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/Headers -arch arm64 -arch x86_64 -Werror=implicit-function-declaration -DCYTHON_CLINE_IN_TRACEBACK=0 -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -Isrc -Isrc/lxml/includes -I/Users/liudanking/.espressif/python_env/idf4.4_py3.8_env/include -I/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/Headers -c src/lxml/etree.c -o build/temp.macosx-10.14-arm64-cpython-38/src/lxml/etree.o -w -flat_namespace

解决方式其实也很简单,从python官网下载一个python3版本手动安装一下即可。

  • 安装完成以后,直接使用USB线连接,电脑可能无法识别设备,需要安装CP2102芯片的usb-to-uart驱动
  • 根据范例,手动尝试点亮板载的蓝色LED,可能会出现无法点亮的问题。这是因为自己购买的开发版并不是官方版本,GPIO引脚并不是实例源码中的8,可以通过查看商家给的电路图的方式,确定正确的蓝色LED GPIO具体是多少。具体到我的情况,修改为GPIO 2即可。

初步体验下来,ESP32的示例代码挺齐全的,环境配置门槛也不够,开发版整体也足够便宜,再加上当前“万物互联”的概念,这几年能够拿下相当一部分市场也的确是软硬实力兼具的。接下来会用一些业余时间做一些有意思的玩具,不定期更新在博客。

升级MacBook Pro M1 Pro啦

因为上海疫情原因,定制的21款MacBook Pro 16 inch足足等待了两个月才到手。

这是自己的第三台MacBook Pro,具有基本一样的功能和外观设计理念,尤其是那个电饭锅magsafe充电口。所不同的是,这是一台搭载苹果M1 Pro CPU的机器。机器到手后,前后断断续续花了半个月把应用、数据和环境都配置好了。简单记录一下自己的这次迁移记录。

系统迁移及兼容性

自己现在在用的是2015款MacBook Pro 15 inch. 考虑到M1架构与Intel架构的差异性,以及看了一些power user的反馈,这次迁移没有使用Time Machine。而是直接 one by one 配置安装配置的方式。最开始以为工作量会比较大,但实际迁移过程中发现,自己常用的应用也就那么几个。而自己最开始比较畏惧的环境配置,因为之前很早就做了云同步,所以也是比预期快很多的就完成了配置。

在M1上运行Intel架构的应用,会经过 Rosetta 2 转换,有大概20%的性能损失。在活动监视器上面,也可以通过 kind 查到到。目前常用的软件基本都能兼容,这块目前没有遇到什么问题。

开发环境

golang的环境可以一路next配置完,目前还没有发现任何兼容性问题,而且编译速度极快。

自己是重度 alfred 用户,从10年前开始切换到mac, 就购买了mega授权。但是切换到新机器后,发现很多workflow依赖的python都没法工作了(macOS 12.3以后移除了python)。恢复的话主要两步:1、自己下载安装python; 2、因为python路径发生了变化,还需要更新workflow到兼容m1的版本 或者 手动修改workflow中写错的路径。

java 8 环境,如果追求m1原生和性能,可以考虑 azul jdk,但是可能存在一些兼容性问题。主要是一些依赖的lib可能没有m1原生版本。因此,我的选择是同时安装了一个 oracle 版本备用。

使用感受

关于M1 Pro/Max的性能,我推荐极客湾的苹果M1 Pro/M1 Max评测. 这里聊一下自己作为一个典型的开发者的使用感受:

  • magsafe回归了,140w快充太赞了。magsafe充电口也是为什么我的上一台macbook一直坚守在2015款的重要原因。而140w的快充基本上稍微补点电就可以用半天,对于有时候动辄一天的会来说,基本没有了续航焦虑。
  • 整机功耗非常低,日常开发非常安静,风扇基本不转。从系统监控看,95%情况下,功耗在15w以下。不得不感慨苹果的精准刀法,这个功耗你用ipad原装20w充电头其实也能勉强用,但是就是会时而触发从电池借电。而根据我之前的经验,这会非常容易造成电池鼓包。因此,我现在随身携带的是一个 type-c PD的应急充电头是30w的,同时满足手机电脑充电,我推荐你也这样做。
  • 刘海摄像头还算能接受,基本不影响日常使用。这么大的挖孔当前只有一个1080p的摄像头肯定是战未来的,毕竟库克是库存管理大师。这也就意味着,这代的MacBook Pro模具应该会有相当长的一段时间。颇有点iPhone 12回滚iPhone 4的味道。
  • 指纹识别比较方便,在这个基本都标配的时代,只能说是中规中矩。
  • 键盘也随着magsafe的恢复,基本重新回到了2015款的手感。但是键程显然还是比2015款短,能有80%的舒适度吧。

新的笔记本到手半个月了,即使加上之前2个多月的等待,这段时间用来下来也是挺开心的。苹果在这个产品线上重新找到了当年 Pro 的那个味道,自己也很久没用到能让自己如此满意的电子产品。配上好鞍,重新出发!