idoubi
6个月前
idoubi
6个月前
idoubi
7个月前
MCP so 秒开优化经验总结👇 1. 底层框架升级 新版本升级到了 ShipAny v2,对应组件是 nextjs15 + react19 + tailwindcss4。底层框架升级带来了更好的 SSR 渲染性能,构建效率更高,构建产物体积更小,配合 cloudflare 的 CDN 分发,让静态资源加载速度更快了。 2. 部署方案升级 新版本使用 OpenNext 包裹,部署到了 cloudflare workers,跟之前部署在 cloudflare pages 的方案相比,支持 Node.js 运行时,可以使用更加完整的 nextjs 特性,配合 cloudflare 的 KV,R2 等组件,在动态读取数据时效率更高了。 3. 数据索引 之前的版本,数据库用的是 supabase, 用户每次访问都需要实时读取数据,数据量在增长、公网调用延时高,因为用的是 SSR(服务端渲染,需要读到数据再显示页面),最终表现就是用户打开页面很慢。 新版本优化,给数据表建索引,根据数据查询语句创建复合索引,比如 idx_featured_project (type,is_featured,created_at),让读取推荐的 server 或client 数据时速度更快。 4. 数据缓存 给数据表建索引只是让从数据库读数据更快了,但是导航站大部分情况是没必要实时读数据的,因此需要加一个数据缓存,减少对数据库的访问。 因为部署在 cloudflare,直接使用 cloudflare 的 KV 组件做缓存是最方便的,只需要在 worker 的配置绑定一下 KV,然后通过 set,get 方法存,取数据就行了。比如把从数据库读到的 featured servers 缓存到 KV,设置 1 小时后自动过期,这样 1 小时内这部分数据的读取就只会走 KV,速度更快了。 5. 增量静态再生 新版本使用 ISR(增量静态再生)代替原来的 SSR(服务端渲染),主要是在访问页面 page.tsx 里面加上这两行: export const dynamic = "force-static" export const revalidate = 600 dynamic = "force-static" 指示 nextjs 在构建阶段生成静态页面,cloudflare worker 自动把静态资源发到 CDN,用户访问页面走 CDN,速度飞快。 revalidate = 600 指示 nextjs 距离上一次生成静态页面超过 10 分钟就重新生成,这样新产生的数据最多等十分钟就能被用户访问到。 ISR 是秒开的关键。 6. 图片懒加载 新版本使用了 react-lazy-load-image-component 这个 npm 包来实现图片懒加载,让图片加载不影响页面渲染,用户打开页面更快。 因为没有部署在 vercel,next/image 的很多优化特性用不了,所以选择一个轻量的图片懒加载库,而不是用 next/image。 7. 链接页面预取 通过 next/link 替换带链接的 a 标签,自动预取页面,当用户点击链接时,目标页面已经加载好了,就会快速打开新的页面,体验很好。 总结: MCP so 通过升级底层框架,配合 ISR,充分利用了 cloudflare 上的 KV,R2 等组件实现数据和静态资源缓存,配合 cloudflare CDN 分发优势,从而实现了秒开。 经验可复制性: 1. 如果你的项目是基于 ShipAny 开发的,记得更新 cloudflare 分支的最新代码 2. 如果你的项目是基于 nextjs 的,可以参考 OpenNext 文档包一层,部署到 cloudflare workers 3. 如果你的项目需要频繁读取数据,记得合理添加数据库索引,同时设置数据缓存(Redis 或者 cloudflare KV 之类) 4. 如果你的项目不需要实时展示数据(比如导航站),记得设置 ISR,通过静态构建加速访问,配置 revalidate 时间,增量生成新内容 5. 如果你的项目涉及大量图片/视频等资源,记得压缩资源体积,上传文件存储,通过 CDN 做分发
idoubi
8个月前
关于 MCP 的几个理解误区: 1. 误区 1:MCP 协议需要大模型支持 MCP 全称模型上下文协议,是为了在用户与大模型对话过程中,补充上下文信息给大模型,让大模型更准确的回答用户提问而设计的。 在 MCP 出来之前,有多种方式可以实现上下文信息的补充,比如: - 记忆存储。把对话过程的历史消息存储下来,每次新提问,带上历史消息一起发送给大模型 - RAG。在让大模型回答问题之前,先从本地知识库或者互联网上检索信息,作为上下文补充给大模型 - Function Calling。传递一堆工具给大模型挑选,根据大模型的返回参数,调用工具,用工具返回的结果作为上下文补充给大模型 理解了给大模型补充上下文的原理,就可以知道,MCP 的本质,是指导应用层,如何更好的补充上下文信息给大模型。 模型收到回复提问请求时,MCP 工作已经完成了。 结论:MCP 协议不需要大模型支持,哪怕你使用古老的 gpt-2 作为问答模型,依然可以使用 MCP 协议补充上下文信息。 2. 误区 2:只有支持 Function Calling 的模型才支持 MCP 协议 聊 MCP 协议,必须要理解 Function Calling 机制。 - Function Calling 是一种交互范式。 基本流程是应用层传递一堆工具给大模型,大模型意图识别,做一次 Pick Tool 操作,返回应该调用的工具名称和调用参数,再由应用层发起 Call Tool 操作,拿到结果重新给到大模型回答。 Function Calling 这套机制下有三个角色:应用、资源方、大模型。 两个核心步骤:Pick Tool 和 Call Tool。 Pick Tool 需要大模型推理,Call Tool 需要应用与资源方交互。 - MCP 协议是一套交互标准。可以理解为 MCP 是对 Function Calling 机制的包装与升级。 MCP 协议定义了三个角色:主机、客户端、服务器。 跟 Function Calling 机制相比,MCP 协议相当于是把 客户端-服务器 作为一个黑盒。 整体视角看,MCP 协议有四个角色:主机应用、黑盒(客户端-服务器)、资源方、大模型 主机把请求给到客户端,客户端请求服务器,服务器对接资源方,主机最终得到黑盒返回的结果,作为补充上下文给到大模型回答。 Function Calling 是应用直接对接资源,MCP 是应用通过黑盒对接资源,对接更加标准化,资源接入成本更低。 Function Calling 是应用直接定义一堆工具,MCP 是应用从 MCP 服务器获取定义好的工具,应用无需重复编码。 涉及到工具调用的环节,MCP 与 Function Calling 的交互形式一致。都依赖大模型的 Pick Tool 能力。 所谓的大模型支持 Function Calling,是指大模型在 Pick Tool 环节,有更好的理解和推理能力,最终能返回更加准确的 Tool 和参数。 不支持 Function Calling 的模型,依然可以通过提示词工程实现 Pick Tool。只不过准确度不如支持 Function Calling 的模型。 结论:不支持 Function Calling 的模型,依然可以使用 MCP 协议补充上下文信息。 3. 误区 3:大模型原生支持 MCP 协议 所谓的大模型原生支持 MCP 协议,正确的理解应该是大模型内化了 MCP 协议的定义,并且内置集成了大量基于 MCP 协议定义的工具。 当接到用户提问时,应用即使不给大模型传递任何工具,大模型依然可以基于内化的工具列表进行推理,返回应该调用的工具名称和调用参数给应用。 事实上,互联网上的资源是千差万别的,意味着对接资源的 MCP 服务器及其内部的工具是海量的,不可枚举的。 另一个关键点是,某些资源是私有的,需要用户鉴权的,大模型训练时不可能内化用户的鉴权凭证。 从这个角度来讲,大模型内化 MCP 协议下的海量工具,不现实也不可能。 某些模型厂商,也许是为了蹭 MCP 的热度,某些自媒体,也许是对 MCP 协议理解不到位,宣称某大模型原生支持 MCP 协议。 其实要表达的意思,也许只是,在随大模型一起发布的某个 agent 框架里面,加上了对 MCP 协议的支持。 结论:大模型原生支持 MCP 协议,这种说法是不专业的。大模型现阶段不可能原生支持 MCP。 本人认知有限,也许会有理解偏颇之处。欢迎补充交流。🙂
idoubi
10个月前
以 manus 为例,拆解以 multi-agent 为基础的通用任务智能体的工作流程: 一. 意图识别 1. 获取用户输入内容,进行必要的意图识别和关键词提取,比如用户输入的是“想去日本旅游,需要一个旅行计划”,拆解之后得到的关键词是: japan-trip,任务类型为:travel 2. 如果用户输入的需求比较简单,不能识别用户的意图,此步骤可以引导用户继续对话,补充更多的信息,或者上传文档 / 图片等资料 二. 任务初始化 1. 用识别出来的任务关键词创建任务文件夹,启动 docker 容器,为后续的任务执行做环境隔离 2. 任务执行过程中的内容产物,写入到任务文件夹,任务结束之后清理 docker 容器 三. 步骤规划 1. 使用意图识别的结果 + 补充背景信息,请求一个推理模型,对任务进行步骤拆分 2. 将任务拆分的步骤信息,写入到任务文件夹的 四. 任务执行 1. 遍历任务文件夹中的 ,[ ] 表示待执行的任务,[x] 表示已执行的任务 2. 取出待执行的任务,带上任务上下文信息,做一次 function call,这里带上的 function tools 是系统内置的可以执行不同任务的 agent,比如 search agent / code agent / data-analysis agent 3. 根据 function call 的结果,调度指定的 agent 执行任务,把执行过程中产生的内容,写入到容器中的任务文件夹 4. 任务执行完,由主线程,更新 ,继续下一个任务 五. 归纳整理 1. 里面的任务全部执行完之后,主线程针对用户的初始需求,做一次整理输出 2. 把任务的内容产物,给到用户浏览或下载(文档 / 代码 / 图片 / 链接等) 3. 收集用户对任务的满意度 ---- 整个方案理下来,核心在于执行任务的 agent 设计,以及主线程的调度流程,以 search agent 为例,在处理“日本旅行计划”这个任务中,主要的执行步骤: 1. 拿到 japan-trip 等关键词信息,调用谷歌第三方 API,获取 10-20 条搜索结果 2. 模拟浏览器点开第一个网页,浏览网页内容,获取网页文本内容 + 浏览器截图拿到网页视觉信息 3. 调用支持多模态输入的模型,输入当前任务要求,从当前浏览的网页中提取有效信息(是否有符合要求的结果,如果不满足要求,返回下一个该点击的 button 元素) 4. 模拟浏览器点击 + 网页滚动行为,拿到更多的网页内容 + 视觉信息,重复几次,直到收集到的内容满足任务要求为止 5. 把收集到的内容保存到任务文件夹 这个 search agent 的核心在于模拟用户浏览网页行为,需要用到无头浏览器和多模态模型。 code agent 和 data-analysis agent 相对而言比较简单: 1. 根据任务需求,创建本地文件,写入代码(python 代码做数据分析,html 代码做视觉呈现) 2. 通过系统调用执行代码,把执行结果保存到任务文件夹 3. 通过 code-preview 服务,预览 html 文件的内容 --- 此类 multi-agent 产品,还有一些改进的空间: 1. 的多个任务,是线性依赖关系,可以使用 DAG(有向无环图)实现更加复杂的任务依赖 2. 需要引入自动化测试 agent,对任务结果进行判断和矫正,如果对某个步骤评分过低,需要回溯到之前的某个任务节点重新执行 3. 允许全自动 + 用户介入的混合模式,在某个步骤执行完,先寻求用户反馈,如果几秒内没收到反馈,则自动继续运行 --- 整体评价:manus 在工程层面做了很多工作,整体交互比其他产品好很多。技术层面,依然是没什么壁垒,对模型有比较深的依赖: 1. 也许有个小模型,做任务执行前的意图识别 2. 任务规划和推理,用 deepseek-r1 3. 图片识别 + 代码生成,用 claude-3.7-sonnet token 消耗会很高,能不能广泛用起来,取决于谁来负担这个成本。 最终的任务准确性和用户满意度,还需要更多的案例来说明。