发布于 2026-01-06 2 阅读
0

我为 OpenAI 和所有其他 LLM 制作了 MCP(模型上下文协议)替代解决方案,它比 Anthropic Claude DEV 的全球展示挑战赛更便宜,该挑战赛由 Mux 呈现:Pitch Your Projects!

我为 OpenAI 和所有其他 LLM 开发了一种比 Anthropico Claude 更便宜的 MCP(模型上下文协议)替代方案。

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

前言

我制作了 MCP(模型上下文协议)的替代方案。

我的替代方案是利用 Swagger/OpenAPI 和 TypeScript 类函数提供的 LLM 函数调用功能,并结合编译器和验证反馈策略进行增强。借助这些策略,您可以将 Anthropic Claude 的 MCP 完全替换为更小的模型gpt-4o-mini(例如,可以替换为本地 LLM)。

以下演示了我的替代方案,即在购物中心搜索和购买商品。其后端服务器包含 289 个 API 函数,我可以通过参数模型中的对话文本调用所有这些 APIgpt-4o-mini函数8b

import { Agentica } from "@agentica/core";
import { HttpLlm, OpenApi } from "@samchon/openapi";
import typia from "typia";

const agent = new Agentica({
  vendor: {
    api: new OpenAI({ apiKey: "*****" }),
    model: "gpt-4o-mini",
  },
  controllers: [
    HttpLlm.application({
      model: "chatgpt",
      document: OpenApi.convert(
        await fetch(
          "https://shopping-be.wrtn.ai/editor/swagger.json",
        ).then(r => r.json())
      )
    }),
    typia.llm.application<ShoppingCounselor, "chatgpt">(),
    typia.llm.application<ShoppingPolicy, "chatgpt">(),
    typia.llm.application<ShoppingSearchRag, "chatgpt">(),
  ],
});
await agent.conversate("I wanna buy MacBook Pro");
Enter fullscreen mode Exit fullscreen mode

脚本:

  • 你能做什么?
  • 能向我展示一下市场上的销售情况吗?
  • 我想查看MacBook的详细信息。选择(银色,16GB,1TB,英文)型号并加入购物车。将购物车添加到订单页面。我将用现金支付,我的地址是~

函数调用

图片描述

LLM 选择要调用的正确函数,并填充其参数。

LLM(大型语言模型)函数调用是指 LLM 通过分析与用户的对话上下文来选择合适的函数并填充参数。还有一个类似的概念叫做结构化输出,它指的是 LLM 自动将输出的对话转换为 JSON 等结构化数据格式。

我专注于LLM函数调用功能,并希望用户能够充分利用它。如果能够做到这一点,您就可以完全用它替换Anthropic Claude的MCP(模型上下文协议),使其适用于更小的模型gpt-4o-mini。以下是我希望通过我的解决方案实现的蓝图:

  • 用户列出候选函数
  • 用户无需设计复杂的代理图或工作流程。
  • 我已经在我的购物中心解决方案中实现了这一点。

OpenAPI战略

图片描述

OpenAPI规范到LLM函数调用方案的转换。

LLM(大型语言模型)函数调用需要基于 JSON 模式的函数模式。然而,不同的 LLM 服务供应商并没有使用相同的 JSON 模式。“OpenAI GPT”和“Anthropologie Claude”使用了不同的 LLM 函数调用 JSON 模式规范,Google Gemini 也与它们不同。

更糟糕的是,Swagger/OpenAPI 文档使用的 JSON 模式规范与 LLM 函数调用模式的规范不同,而且不同版本的 Swagger/OpenAPI 之间的规范差异很大。

为了解决这个问题,我做了如下处理@samchon/openapi。当 Swagger/OpenAPI 文档出现时,它会转换为 OpenAPI v3.1 修订版规范。然后,它会绕过迁移模式,将其转换为服务供应商特定的 LLM 函数调用模式。作为参考,迁移模式是另一种中间件模式,它将 OpenAPI 操作模式转换为类似函数的模式。

此外,在将 Swagger/OpenAPI 文档转换为 LLM 函数调用模式时,嵌入#Validation Feedback@samchon/openapi策略的参数运行时验证器

验证反馈

import { FunctionCall } from "pseudo";
import { ILlmFunction, IValidation } from "typia";

export const correctFunctionCall = (p: {
  call: FunctionCall;
  functions: Array<ILlmFunction<"chatgpt">>;
  retry: (reason: string, errors?: IValidation.IError[]) => Promise<unknown>;
}): Promise<unknown> => {
  // FIND FUNCTION
  const func: ILlmFunction<"chatgpt"> | undefined =
    p.functions.find((f) => f.name === p.call.name);
  if (func === undefined) {
    // never happened in my experience
    return p.retry(
      "Unable to find the matched function name. Try it again.",
    );
  }

  // VALIDATE
  const result: IValidation<unknown> = func.validate(p.call.arguments);
  if (result.success === false) {
    // 1st trial: 30% (gpt-4o-mini in shopping mall chatbot)
    // 2nd trial with validation feedback: 99%
    // 3nd trial with validation feedback again: never have failed
    return p.retry(
      "Type errors are detected. Correct it through validation errors",
      {
        errors: result.errors,
      },
    );
  }
  return result.data;
}
Enter fullscreen mode Exit fullscreen mode

LLM 函数调用完美吗?不,绝对不完美。

像 OpenAI 这样的 LLM(大型语言模型)服务供应商在组合函数调用或结构化输出的参数时,经常会出现类型级别的错误。即使目标模式非常简单(例如Array<string>类型),LLM 也常常直接使用类型化的值来填充它string

根据我的经验,OpenAI gpt-4o-mini8b参数方面)在向购物中心服务调用函数时,大约 70% 的参数类型错误。为了克服 LLM 函数调用的缺陷,许多 LLM 用户使用大型模型llama-3.2-405b并尝试使用简单的结构化模式。然而,我尝试了另一种方法:验证反馈策略,而不是使用大型模型或简化模式。结果非常成功。

验证反馈策略的关键概念是,先让 LLM 函数调用构造无效的类型化参数,并将详细的类型错误告知 LLM,以便 LLM 在下一轮调用中修正错误的类型化参数。

而且,我已经采用了typia.validate<T>()一些typia.llm.application<Class, Model>()功能来替代 MCP。它们通过在编译级别分析 TypeScript 源代码和类型来构建验证逻辑,因此比任何其他验证器(例如下面的验证器)都更加详细和准确。

通过这种验证反馈策略并结合typia运行时验证器,我实现了最理想的LLM函数调用,可以完全替代MCP(模型上下文协议),从而应用于更小的模型gpt-4o-mini。采用这种策略后,第一次函数调用尝试的成功率从30%提升到第二次函数调用尝试的成功率99%,并且从第三次尝试开始从未失败。

成分 typia TypeBox ajv io-ts zod C.V.
便于使用
简单对象
对象(层级式)
对象(递归)
对象(联合体,隐式)
对象(联合体,显式)
对象(附加标签)
对象(模板字面量类型)
对象(动态属性)
数组(剩余元组)
数组(分层)
数组(递归)
数组(递归,并集)
数组(R+U,隐式)
数组(重复)
数组(重复,并集)
终极联盟类型

编译器技能

图片描述

编译器技术能够完美生成模式。

我认为最重要的是,无论是 Anthropic Claude 的 MCP(模型上下文协议)还是我提倡用来取代 MCP 的 LLM(LLM 函数调用)函数调用策略,都要安全地创建 JSON 模式。

顺便一提,我观察了很多其他人工智能开发者,他们都在手动编写 JSON 模式。即使借助一些工具构建器,也常常会造成模式定义重复,这似乎很危险。在传统的开发生态系统中,即使人犯了模式编写错误,其他人也可以通过其所在机构来纠正。然而,人工智能却不会原谅错误

为了确保模式组合的安全性,我开发了一个基于 TypeScript 编译器的 JSON 模式生成器typia,并且@nestia已经运行了很长时间。如果您编写一条typia.llm.application<MyClass, "chatgpt">()语句,它将被转换为 OpenAI 函数调用模式的集合。这种模式转换是通过在编译级别分析 TypeScript 源代码来完成的typia

此外,在开发用于生成 OpenAPI 文档的后端服务器时,@nestia也会进行同样的操作typia。它会分析后端服务器的 TypeScript 源代码,以便安全地生成 OpenAPI 文档而不会出现任何错误。

编译器技术能够生成如此完美的模式,我认为我的替代方案比 Anthropic Claude 的 MCP(模型上下文协议)更好。

@Controller("shoppings/customers/sales")
export class ShoppingCustomerSaleController {
  /**
   * Get a sale with detailed information.
   *
   * Get a {@link IShoppingSale sale} with detailed information including
   * the SKU (Stock Keeping Unit) information represented by the
   * {@link IShoppingSaleUnitOption} and {@link IShoppingSaleUnitStock} 
   * types.
   *
   * > If you're an A.I. chatbot, and the user wants to buy or compose a
   * > {@link IShoppingCartCommodity shopping cart} from a sale, please
   * > call this operation at least once to the target sale to get 
   * > detailed SKU information about the sale.
   * >
   * > It needs to be run at least once for the next steps. In other 
   * > words, if you A.I. agent has called this operation to a specific
   * > sale, you don't need to call this operation again for the same 
   * > sale.
   * >
   * > Additionally, please do not summarize the SKU information. 
   * > Just show the every options and stocks in the sale with detailed
   * > information.
   *
   * @param id Target sale's {@link IShoppingSale.id}
   * @returns Detailed sale information
   * @tag Sale
   */
  @TypedRoute.Get(":id")
  public async at(
    @TypedParam("id") id: string & tags.Format<"uuid">,
  ): Promise<IShoppingSale>;
}
Enter fullscreen mode Exit fullscreen mode

传统的OpenAPI组合方式。

由韩国大型IT公司之一的Toss Corporation编写。

@ExtendWith(RestDocumentationExtension::class, SpringExtension::class)
@SpringBootTest
class SampleControllerTest {
  private lateinit var mockMvc: MockMvc

  @BeforeEach
  internal fun setUp(context: WebApplicationContext, restDocumentation: RestDocumentationContextProvider) {
    mockMvc = MockMvcBuilders.webAppContextSetup(context)
      .apply<DefaultMockMvcBuilder>(MockMvcRestDocumentation.documentationConfiguration(restDocumentation))
      .build()
  }

  @Test
  fun getSampleByIdTest() {
    val sampleId = "aaa"
    mockMvc.perform(
      get("/api/v1/samples/{sampleId}", sampleId)
    )
      .andExpect(status().isOk)
      .andExpect(jsonPath("sampleId", `is`(sampleId)))
      .andExpect(jsonPath("name", `is`("sample-$sampleId")))
      .andDo(
        MockMvcRestDocumentationWrapper.document(
          identifier = "sample",
          resourceDetails = ResourceSnippetParametersBuilder()
            .tag("Sample")
            .description("Get a sample by id")
            .pathParameters(
              parameterWithName("sampleId")
                .description("the sample id"),
            )
            .responseFields(
              fieldWithPath("sampleId")
                .type(JsonFieldType.STRING)
                .description("The sample identifier."),
              fieldWithPath("name")
                .type(JsonFieldType.STRING)
                .description("The name of sample."),
            ),
        ),
      )
  }
}

Agentica,一款取代 MCP 的智能人工智能框架

图片描述

@nestia/agent为了增强功能并将其拆分为多个扩展包,该功能已被迁移@agentica/*。由于它将由组织层面进行开发,因此您可能会更快地遇到它。

利用上述 OpenAPI、验证反馈和编译器策略,我和我的伙伴们正在开发一个智能体 AI 框架。它可以完全替代 MCP(模型上下文协议),并且模型成本远低于 Anthropic Claude。在我们的案例中,我们尝试使用本地 LLM(局部逻辑层模型)。

新框架的名称是[@agentica此处应填写框架名称],预计将在1到2周后发布。功能已基本完成,只剩下命令行包和文档需要编写。

@agentica采用了以下多代理编排策略。借助此代理编排策略,用户无需编写复杂的代理图或工作流,只需将 Swagger/OpenAPI 文档或 TypeScript 类类型线性地传递给它即可@agentica@agentica它将通过函数调用完成所有操作。


图片描述

当用户发出指令时,@agentica系统会将对话文本传递给selector代理,并让selector代理从上下文中查找(或取消)候选函数。如果代理selector找不到任何可调用的候选函数,且之前也没有选择过任何候选函数,则selector代理将像普通的 ChatGPT 一样运行。

然后@agentica进入循环语句,直到候选函数为空。在循环语句中,caller智能体尝试通过分析用户的对话文本来调用 LLM 函数。如果上下文足以构成候选函数的参数,caller智能体则实际调用目标函数,并decriber解释函数调用结果。否则,上下文不足以构成参数,caller智能体会向用户请求更多信息。

这种 LLM(大型语言模型)函数调用策略将selectorcaller和 分开,describer是其关键逻辑@agentica

文章来源:https://dev.to/samchon/i-made-mcp-model-context-protocol-alternative-solution-for-openai-and-all-other-llms-that-is-i7f