官方 Python 实现的 UTCP 1.0.1 正式发布

通用工具调用协议(UTCP)是一种现代、灵活且可扩展的标准,用于定义和与各种通信协议中的工具进行交互。UTCP 1.0.0 引入了基于插件架构的模块化核心,使其更具可扩展性、可测试性,并更易于打包。

与其他协议相比,UTCP 特别强调以下几点:

  • 可扩展性:UTCP 设计上能够处理大量工具和提供商,同时不牺牲性能。
  • 可扩展性:可插拔架构使开发人员能够轻松添加新的通信协议、工具存储机制和搜索策略,而无需修改核心库。
  • 互操作性:随着协议插件生态系统的不断扩展(包括 HTTP、SSE、CLI 等),UTCP 可与几乎任何现有服务或基础设施集成。
  • 易用性: 该协议基于简单、定义明确的 Pydantic 模型构建,使开发人员能够轻松实现和使用。

1.0.0 版本的新架构

UTCP 已重构为一个核心库和一组可选插件。

核心包(utcp)

utcp 包提供核心组件和接口:

  • 数据模型:用于 ToolCallTemplateUtcpManualAuth 的 Pydantic 模型。
  • 可插拔接口:
  • CommunicationProtocol:定义协议特定通信的契约(例如 HTTP、CLI)。
  • ConcurrentToolRepository:用于存储和检索工具的线程安全访问接口。
    • ToolSearchStrategy:用于实现工具搜索算法的接口。
  • VariableSubstitutor:处理配置中的变量替换。
  • ToolPostProcessor:允许在返回工具结果前对其进行修改。
  • 默认实现:
  • UtcpClient:与 UTCP 生态系统交互的主要客户端。
    • InMemToolRepository:一个内存工具库,支持异步读写锁。
    • TagAndDescriptionWordMatchStrategy:一种改进的搜索策略,支持基于标签和描述关键词的匹配。
元素周期表

协议插件

通信协议现已作为独立的可安装包。这使核心保持精简,并允许用户仅安装所需的协议。

  • utcp-http:支持 HTTP、SSE 和可流式传输的 HTTP,以及 OpenAPI 转换器。
  • utcp-cli:用于封装本地命令行工具。
  • utcp-mcp:用于与模型上下文协议(MCP)的互操作性。
  • utcp-text:用于读取文本文件。
  • utcp-socket:TCP 和 UDP 协议的框架。(正在开发中,需要更新)
  • utcp-gql:GraphQL 的框架。(正在开发中,需要更新)

安装

安装核心库及所需协议插件。

# Install the core client and the HTTP plugin
pip install utcp utcp-http

# Install the CLI plugin as well
pip install utcp-cli

开发时,可从克隆的仓库以可编辑模式安装包:

# Clone the repository
git clone https://github.com/universal-tool-calling-protocol/python-utcp.git
cd python-utcp

# Install the core package in editable mode with dev dependencies
pip install -e core[dev]

# Install a specific protocol plugin in editable mode
pip install -e plugins/communication_protocols/http

从 0.x 到 1.0.0 的迁移指南

版本 1.0.0 引入了多个兼容性更改。请按照以下步骤迁移您的项目。

  1. 更新依赖项:安装新的 utcp 核心包以及您使用的特定协议插件(例如 utcp-httputcp-cli)。
  2. 配置:
  • 配置对象:UtcpClient 通过 UtcpClientConfig 对象、字典或指向包含配置的 JSON 文件的路径进行初始化。
    • 手动调用模板:providers_file_path 选项已被移除。现在,您需要直接在 UtcpClientConfig 中提供 manual_call_templates 的列表,而非文件路径。
  • 术语:术语 provider 已被替换为 call_template,而 provider_type 现为 call_template_type
    • 可流式 HTTP:call_template_type 中的 http_stream 已重命名为 streamable_http
  1. 更新导入:将导入语句修改为反映新的模块化结构。例如,from utcp.client.transport_interfaces.http_transport import HttpProvider 改为 from utcp_http.http_call_template import HttpCallTemplate
  2. 工具搜索:如果您之前使用的是默认搜索策略,新的策略为 TagAndDescriptionWordMatchStrategy。这是新的默认策略,除非您之前实现了自定义策略,否则无需进行任何更改。
  3. 工具命名:工具名称现在以 manual_name.tool_name 的形式进行命名空间划分。客户端会自动处理此操作。6. 变量替换命名空间:在不同 call_templates 中替换的变量,首先会使用手册名称并重复 _ 进行命名空间划分。例如,来自手册 manual_1 的工具调用模板中的 API_KEY 键将转换为 manual__1_API_KEY

使用示例

1. 使用 UTCP 客户端

config.json(可选)

您可以通过 JSON 文件定义完整的客户端配置。所有字段均为可选。

{
  "variables": {
    "openlibrary_URL": "https://openlibrary.org/static/openapi.json"
  },
  "load_variables_from": [
    {
      "variable_loader_type": "dotenv",
      "env_file_path": ".env"
    }
  ],
  "tool_repository": {
    "tool_repository_type": "in_memory"
  },
  "tool_search_strategy": {
    "tool_search_strategy_type": "tag_and_description_word_match"
  },
  "manual_call_templates": [
    {
        "name": "openlibrary",
        "call_template_type": "http",
        "http_method": "GET",
        "url": "${URL}",
        "content_type": "application/json"
    },
  ],
  "post_processing": [
    {
        "tool_post_processor_type": "filter_dict",
        "only_include_keys": ["name", "key"],
        "only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
    }
  ]
}

client.py

import asyncio
from utcp.utcp_client import UtcpClient
from utcp.data.utcp_client_config import UtcpClientConfig

async def main():
    # The UtcpClient can be created with a config file path, a dict, or a UtcpClientConfig object.

    # Option 1: Initialize from a config file path
    # client_from_file = await UtcpClient.create(config="./config.json")

    # Option 2: Initialize from a dictionary
    client_from_dict = await UtcpClient.create(config={
        "variables": {
            "openlibrary_URL": "https://openlibrary.org/static/openapi.json"
        },
        "load_variables_from": [
            {
                "variable_loader_type": "dotenv",
                "env_file_path": ".env"
            }
        ],
        "tool_repository": {
            "tool_repository_type": "in_memory"
        },
        "tool_search_strategy": {
            "tool_search_strategy_type": "tag_and_description_word_match"
        },
        "manual_call_templates": [
            {
                "name": "openlibrary",
                "call_template_type": "http",
                "http_method": "GET",
                "url": "${URL}",
                "content_type": "application/json"
            }
        ],
        "post_processing": [
            {
                "tool_post_processor_type": "filter_dict",
                "only_include_keys": ["name", "key"],
                "only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
            }
        ]
    })

    # Option 3: Initialize with a full-featured UtcpClientConfig object
    from utcp_http.http_call_template import HttpCallTemplate
    from utcp.data.variable_loader import VariableLoaderSerializer
    from utcp.interfaces.tool_post_processor import ToolPostProcessorConfigSerializer

    config_obj = UtcpClientConfig(
        variables={"openlibrary_URL": "https://openlibrary.org/static/openapi.json"},
        load_variables_from=[
            VariableLoaderSerializer().validate_dict({
                "variable_loader_type": "dotenv", "env_file_path": ".env"
            })
        ],
        manual_call_templates=[
            HttpCallTemplate(
                name="openlibrary",
                call_template_type="http",
                http_method="GET",
                url="${URL}",
                content_type="application/json"
            )
        ],
        post_processing=[
            ToolPostProcessorConfigSerializer().validate_dict({
                "tool_post_processor_type": "filter_dict",
                "only_include_keys": ["name", "key"],
                "only_include_tools": ["openlibrary.read_search_authors_json_search_authors_json_get"]
            })
        ]
    )
    client = await UtcpClient.create(config=config_obj)

    # Call a tool. The name is namespaced: `manual_name.tool_name`
    result = await client.call_tool(
        tool_name="openlibrary.read_search_authors_json_search_authors_json_get",
        tool_args={"q": "J. K. Rowling"}
    )

    print(result)

if __name__ == "__main__":
    asyncio.run(main())

2. 提供 UTCP 手册

UTCPManual 描述您提供的工具。关键变化是将 tool_provider 替换为 call_template

server.py

UTCP装饰器版本:

from fastapi import FastAPI
from utcp_http.http_call_template import HttpCallTemplate
from utcp.data.utcp_manual import UtcpManual
from utcp.python_specific_tooling.tool_decorator import utcp_tool

app = FastAPI()

# The discovery endpoint returns the tool manual
@app.get("/utcp")
def utcp_discovery():
    return UtcpManual.create_from_decorators(manual_version="1.0.0")

# The actual tool endpoint
@utcp_tool(tool_call_template=HttpCallTemplate(
    name="get_weather",
    url=f"https://example.com/api/weather",
    http_method="GET"
), tags=["weather"])
@app.get("/api/weather")
def get_weather(location: str):
    return {"temperature": 22.5, "conditions": "Sunny"}

无UTCP依赖的服务器版本:

from fastapi import FastAPI

app = FastAPI()

# The discovery endpoint returns the tool manual
@app.get("/utcp")
def utcp_discovery():
    return {
        "manual_version": "1.0.0",
        "utcp_version": "1.0.1",
        "tools": [
            {
                "name": "get_weather",
                "description": "Get current weather for a location",
                "tags": ["weather"],
                "inputs": {
                    "type": "object",
                    "properties": {
                        "location": {"type": "string"}
                    }
                },
                "outputs": {
                    "type": "object",
                    "properties": {
                        "temperature": {"type": "number"},
                        "conditions": {"type": "string"}
                    }
                },
                "call_template": {
                    "call_template_type": "http",
                    "url": "https://example.com/api/weather",
                    "http_method": "GET"
                }
            }
        ]
    }

# The actual tool endpoint
@app.get("/api/weather")
def get_weather(location: str):
    return {"temperature": 22.5, "conditions": "Sunny"}

3. 完整示例

您可以在 示例仓库 中找到完整示例。

协议规范

UtcpManualTool 模型

Tool 中的 tool_provider 对象已被 call_template 取代。

{
  "manual_version": "string",
  "utcp_version": "string",
  "tools": [
    {
      "name": "string",
      "description": "string",
      "inputs": { ... },
      "outputs": { ... },
      "tags": ["string"],
      "call_template": {
        "call_template_type": "http",
        "url": "https://...",
        "http_method": "GET"
      }
    }
  ]
}

调用模板配置示例

各协议的配置示例。请记得将 provider_type 替换为 call_template_type

HTTP 调用模板

{
  "name": "my_rest_api",
  "call_template_type": "http", // Required
  "url": "https://api.example.com/users/{user_id}", // Required
  "http_method": "POST", // Required, default: "GET"
  "content_type": "application/json", // Optional, default: "application/json"
  "auth": { // Optional, example using ApiKeyAuth for a Bearer token. The client must prepend "Bearer " to the token.
    "auth_type": "api_key",
    "api_key": "Bearer $API_KEY", // Required
    "var_name": "Authorization", // Optional, default: "X-Api-Key"
    "location": "header" // Optional, default: "header"
  },
  "headers": { // Optional
    "X-Custom-Header": "value"
  },
  "body_field": "body", // Optional, default: "body"
  "header_fields": ["user_id"] // Optional
}

SSE(服务器发送事件)调用模板

{
  "name": "my_sse_stream",
  "call_template_type": "sse", // Required
  "url": "https://api.example.com/events", // Required
  "event_type": "message", // Optional
  "reconnect": true, // Optional, default: true
  "retry_timeout": 30000, // Optional, default: 30000 (ms)
  "auth": { // Optional, example using BasicAuth
    "auth_type": "basic",
    "username": "${USERNAME}", // Required
    "password": "${PASSWORD}" // Required
  },
  "headers": { // Optional
    "X-Client-ID": "12345"
  },
  "body_field": null, // Optional
  "header_fields": [] // Optional
}

可流式 HTTP 调用模板

注意名称已从 http_stream 更改为 streamable_http

{
  "name": "streaming_data_source",
  "call_template_type": "streamable_http", // Required
  "url": "https://api.example.com/stream", // Required
  "http_method": "POST", // Optional, default: "GET"
  "content_type": "application/octet-stream", // Optional, default: "application/octet-stream"
  "chunk_size": 4096, // Optional, default: 4096
  "timeout": 60000, // Optional, default: 60000 (ms)
  "auth": null, // Optional
  "headers": {}, // Optional
  "body_field": "data", // Optional
  "header_fields": [] // Optional
}

CLI 调用模板

{
  "name": "my_cli_tool",
  "call_template_type": "cli", // Required
  "command_name": "my-command --utcp", // Required
  "env_vars": { // Optional
    "MY_VAR": "my_value"
  },
  "working_dir": "/path/to/working/directory", // Optional
  "auth": null // Optional (always null for CLI)
}

文本调用模板

{
  "name": "my_text_manual",
  "call_template_type": "text", // Required
  "file_path": "./manuals/my_manual.json", // Required
  "auth": null // Optional (always null for Text)
}

MCP(模型上下文协议)调用模板

{
  "name": "my_mcp_server",
  "call_template_type": "mcp", // Required
  "config": { // Required
    "mcpServers": {
      "server_name": {
        "transport": "stdio",
        "command": ["python", "-m", "my_mcp_server"]
      }
    }
  },
  "auth": { // Optional, example using OAuth2
    "auth_type": "oauth2",
    "token_url": "https://auth.example.com/token", // Required
    "client_id": "${CLIENT_ID}", // Required
    "client_secret": "${CLIENT_SECRET}", // Required
    "scope": "read:tools" // Optional
  }
}

测试

测试结构已更新以反映新的核心/插件分离。

运行测试

要运行核心库和所有插件的所有测试:

# Ensure you have installed all dev dependencies
python -m pytest

要运行特定包(例如核心库)的测试:

python -m pytest core/tests/

要运行特定插件(例如 HTTP)的测试:

python -m pytest plugins/communication_protocols/http/tests/ -v

要运行带覆盖率的测试:

python -m pytest --cov=utcp --cov-report=xml

构建

构建过程现在涉及根据需要分别构建每个包(coreplugins),尽管它们独立发布到 PyPI。

  1. 创建并激活虚拟环境。
  2. 安装构建依赖项:pip install build
  3. 导航至包目录(例如:cd core)。
  4. 运行构建:python -m build
  5. 可分发文件(.whl.tar.gz)将位于 dist/ 目录中。

共有 60 条讨论

  1. 我甚至参加过一场会议,其中一位演讲者坚称在Langchain出现之前,你无法“链式模型响应”。一次又一次,我们构建这些抽象层,使我们与底层技术和核心技术脱节,导致人们对技术存在巨大的知识差距和误解。

    而对于大语言模型(LLM)而言,这一循环变得异常迅速,其最终影响也极为明显——这些工具除了污染你的上下文外,别无他用,它们让你对响应的控制权更少,并把你绑在它们的生态系统中。

    它比用一堆工具定义污染上下文更能提供更好、更高效的结果,因为“哦,工具调用就是这样工作的”。

    创建一个简单的单子接口比使用LangChain更胜一筹,而且你可以保留对实现和设计的控制权,而不是被迫使用一个不理解模式的人设计的方案。

    对提示内容的控制能让你对输出结果有更好的掌控。保持简单能让你对流程和架构有更好的掌控。

    我不在乎你喜欢的博主怎么说。如果你亲自去实现,你就会直接体验到这一点。

    1. 如何提取调用?解析响应?处理无效调用?将结果编码并关联到原始调用?处理错误状态?是为每个新 API 进行定制开发,还是有通用组件处理 REST API 或外壳调用等?

      你建议的更好方法中,很多内容并非项目特定。

      如果你的设置一直运行良好,那么它可能有很多可以重用的通用组件,对吧?还是每次都从头开始编写解析逻辑?

      如果可以重用,那与创建抽象层有什么不同?

      顺便说一句,模型正在被明确训练以使用工具调用而非自定义功能。

      1. 你解析它。对于无效调用,你可以使用你选择的模型进行重新验证。解析并不是一个难以解决的问题,它很简单,你可以解析任何你想要的内容。我从Ada和DaVinci时代就开始解析大语言模型(LLM)的响应,当时它们只是完成文本,这真的并不难。引入每个新API是定制工作,还是有通用组件处理如REST API或外壳调用等?

        为什么任何大语言模型(LLM)框架要处理这些?这是基础架构101。我不想在现有架构上叠加另一层架构。

        >如果被复用,那与创建抽象有什么不同?

        因为你对抽象有控制权。你对上下文中的内容有控制权。你可以根据上下文更新这些抽象和提示。你可以选择自己的模型,而不是依赖于库或工具支持的模型。

        >顺便说一下,模型正在被明确训练来使用工具调用,而不是自定义内容。

        这很好,但它们也擅长生成代码,而代码做什么?调用函数。

        1. 我不是说它们很难,我是说它们是_常见问题_,不需要每次都解决。我不会每次需要时都重新解决标题大小写问题。

          >因为你可以控制抽象层。

          而且根据你使用的工具,你也可以在其他库/等中实现这一点。

          > 这很好,但它们也擅长生成代码,猜猜代码在做什么?调用函数。

          没错,而且还有更多,所以这取决于你如何沙箱化,我猜。

    2. 这种方法在将大语言模型(LLMs)直接集成到应用程序时很有意义。

      避免自定义大语言模型(LLM)集成有显著优势:用户可利用现有大语言模型(LLM)订阅,您需维护的代码更少,且产品可专注于核心用例而非开发大语言模型(LLM)接口。

      虽然我可能同意你的观点,但这与“影响”有何不同?

      我见过很多博主建议“100%组装”、“仅使用JavaScript”、“不使用SQL”,这些似乎都非常相似。

      1. 从技术上讲是的,我发现自己陷入了一种矛盾的困境 🙂

        我认为在倡导此类观点时,尤其是涉及技术和抽象概念时,需要遵循一定的“合理性曲线”。

        因为通常向下游发展会变得更难(例如,完全使用汇编语言或完全使用 JavaScript 是一件更难的事情),但完全使用纯大语言模型(LLM)则更容易——你不需要学习新的框架,不需要学习新的抽象概念,它可以共享,易于管理,并且所有人都可以阅读。

        在这种情况下,向上游迁移反而会增加难度,将其转化为代码管理问题,使代码更难理解,并不可避免地增加复杂性。

        如果你在团队中添加新成员,而他们看到你使用100%汇编语言,他们需要适应它,学习其工作原理,理解为何要这样设计等等。

        但如果你只使用核心技术,他们可以立即理解正在发生的事情。没有包装的提示、魔法符号、奇怪的抽象——“哦,这是一个代理,这是一个链,而这是一个检索器,它也是一个代理,但它只能与不使用UTCP调用的非检索器链式连接”。

        所以,一如既往,这是主观的,任何倡导都需要应用于一个合理的曲线——最终,这有意义吗?

      2. 但现在你受限于模型、提供商以及模型对输出的遵守程度。

        虽然使用结构化输出很棒,但它会造成较大的性能影响,且你失去对它的控制——例如,通过groq使用较小的模型修复无效响应往往比让大型模型生成结构化响应更快。

        拥有50个工具?直接堆叠2个小型模型或进行搜索,并为每个工具提供基本定义,然后输出函数调用,比将所有50个工具定义为JSON并喂给模型更快且更精准。

        虽然结构化响应本身没问题,但这真的取决于用例和提供商。如果你能承受计算时间的损失,那当然很好。如果你不能,那么没有什么能比对提供商、模型和输出选择的绝对控制更好了。

  2. 很快,他们将发现API(应用程序接口)。程序之间通过给定的合同/协议/原型进行交互。

    /pun

    1. 有趣的是,这正是UTCP的本质。它只是让AI利用现有API而非为工具调用创建封装协议(如MCP)的一种方式。

      该协议仅用于发现。在实际调用时它会自动退居幕后

    2. 从未听说过。API是为MCP与其他系统交互而开发的工具吗?

      1. 是的,但我们需要大量SOAP和XML。很快。/s 🙂

      1. 没问题。等_AI兄弟_发现COM(上下文编排机制)再说。

    3. 听起来很复杂。我们需要一个具备AI能力的谷歌或微软来帮我们搞清楚这些东西,并作为云订阅服务出售。

    4. 这是一个常见但懒惰的笑话。这关乎连接具有特定API调用要求的代理与现有API。

  3. 我有一种2010-2015年JS生态系统疯狂时期的感觉。这些半成品的想法。请停止吧,我们不需要额外的抽象层和工具,这些工具并没有真正解决任何问题,只是为了满足虚荣心去创建东西并获得GitHub星标。

    1. 我不同意。我认为尝试这些事情是有价值的,看看什么有效,什么无效。我们可以坐下来思考和讨论,但有时你需要构建一些东西并尝试。

      1. 不,我太老了,我已经知道这没有用,而且会在短期内引发安全问题。

        1. 哇,成为第一个全知全能的人类一定很棒!

          1. 这叫经验。别说你什么都懂。我只是知道这是炒作垃圾而已。以后再感谢我吧。

      2. 我认为,绝大多数组织都过于僵化,无法仅仅通过引入大型语言模型(LLM)访问权限、退一步观察,就能判断这是否是一种改进。

        如果你能某种程度上捕捉到独立创始人需要招聘第二名员工之前所能达到的阶段,你更有可能看到效果。因为LLM在我的工作中并不比我更出色,但在许多我可以容忍做得不好的工作中,它们比我更出色。

        如果出现重大的技术变革,那将是当那些在初创阶段没有大语言模型(LLMs)支持的初创企业开始被那些在初创阶段就拥有大语言模型(LLMs)支持的初创企业超越的时候。

        目前,创建代理的用户只有一个可用选项,即通过工具为代理添加功能。这就是MCP。坦白说,它并不理想,因为它非常主观,并且需要重建整个互联网基础设施。UTCP是唯一的其他替代方案。它采用轻量级方法,不强加额外的抽象层,而是利用现有协议。

    2. 你对“半成品想法”有什么意见?你是否希望我们回到80年代,那时每个人都在车库里开发,只发布完全成熟的代码?我记得那时候情况并不比现在好。

      至于JS生态系统的混乱;虽然我同意我们经历了很多混乱,但我认为这是必要的,才能达到目前围绕React和其他几个框架的相对稳定状态。React特别是在2013年首次发布,此后在阳光下“烘焙”确实受益匪浅。

    3. 也许我们可以发布一个名为“工具调用协议”的流行术语。它就是TCP。

      或上下文共享变量

      或执行模型语言

      或..

      1. 上下文共享系统和启发式变换器机器学习也颇具潜力。

      2. 该死的这些与工具相关的语言扩展。

      3. 请资助我的可扩展专家增强功能

  4. 依我之见,这里有很多不必要的批评。整个人工智能领域正处于探索阶段,新想法、新方法和新模型在多个层面不断涌现,包括模型和API。目前,我们甚至没有一个统一的模型响应API(OpenAI的Chat Completions API是事实上的标准,但它并未正式标准化,缺乏推理响应,缓存机制也不明确等)。因此,像这样的项目中的一些想法可能会被采纳并带来新的贡献。

    1. 同意!目前工具调用只有一种方式,即MCP。我对MCP不满意,因此希望有替代方案,最终大家能选择或创建最佳选项。我们现在讨论的是未来的基础设施,我不希望仅仅因为MCP要求,就重建所有已正常运行的系统。

  5. 有些开发者喜欢用鲁布·戈德堡机器来实现工具。

    每当他们需要执行两三个手动步骤或配置时,他们宁愿开发一个抽象层,只需按一个按钮就能完成这些操作。

    直到这个按钮需要另一个手动操作来配合。然后他们会再次开发一个抽象层,将按下按钮与补充操作封装在一起,并由上级按钮的按下触发。

    示例:Docker->Kubernetes->Helm 或任何其他使用 YAML 编写 YAML 的工具。

    1. 抽象层的增加正是我们不再用汇编语言编程的原因。

      1. 同意,但我的观点是,抽象层应提供可辨别的价值提升,而非仅仅将同级别的一系列操作合并为一个。

        1. 或者,用父评论的话来说,这就是为什么我们不再编写输出更多汇编语言的汇编语言程序。

    2. 假设许多十年前的工具会采用一年前的协议,仅仅是为了改善与代理的交互。

      这是乐观主义

      888/0/sethaurus

      我不喜欢将模型本身逐渐重新定义为控制工具的中心,并借助一个执行模型输出内容的框架。将文本生成器与程序实际的易失性输入输出之间的联系抽象化是不好的。

  6. 初始提交:2025年6月24日。已提供从0.x到1.x的迁移路径。

    为什么我现在感觉自己这么老了?

    说句认真的,有没有模型支持这个?

    1. > 初始提交:2025年6月24日。已提供从0.x到1.x的迁移路径。

      因为这对撰写该读我文件的LLM来说完全合理

      1. 我们在HN发帖时应进行年龄验证

  7. 通过不使用服务器作为接口,UTCP使调用者与工具的耦合度更高。例如,一个搜索MCP服务器可以将搜索提供商作为可选参数,动态选择而不破坏合同。使用UTCP无法做到这一点。接口是好事。

    1. 这不是关于延迟。这是关于安全性和重建现有基础设施。互联网上有足够的通信协议可以实现任何你能想象的功能。我们应该使用这些协议,并用它们来编写我们的接口和封装,而不是 MCP。这就是 UTCP 所做的。它允许代理使用现有基础设施、通信协议和安全机制。

    1. 你好,我认为这是非常有价值的反馈,我们会认真研究,感谢分享!

  8. Cmd+F “现代”

    “通用工具调用协议(UTCP)是一种现代、灵活且可扩展的标准,用于定义和与各种通信协议中的工具进行交互。”

    直接扔进垃圾桶。

    1. 嘿,兄弟,我明白,我们用的是专业术语

      但我们是真实的人,正在开发一个我们认为能改进现状的真实协议,仅仅因为它不符合你的用词习惯就称其为“垃圾”,这既没有必要,甚至可以说伤人

      所以,如果你有反馈,我很乐意改进,但请不要轻易否定它

      1. 但他们的评论中有一丝真理。“现代”这个词很快就会过时,它可能不应该被使用,就像“新”不应该被用于项目/库名称一样。

        依我之见,去除“现代、灵活和可扩展”会改善那句话。

        我快速浏览了README,以我的口味来看,其中过度使用了“软性”形容词(简单、易用等),这让我(作为一名工程师)将其视为营销驱动的。

  9. 名字里有“通用”这个词,所以这一定就是它了,对吧?

  10. 我真的不明白。我一定漏掉了什么显而易见的东西。

    任何“工具协议”本质上只是一个类型化的函数接口。

    几十年来,我们已经有了数十种(数百种?数千种?)不同的格式/语言来描述这些。

    为什么我们还要继续创造更多?

    调用函数的对象和目的真的重要吗?是由服务器还是命令行可执行文件实现的?数据传输协议重要吗?“模型”重要吗?

      interface HelloSayer {
        /** 说你好 **/
        String sayHello();
      }
    

    这是你的工具协议,兄弟

    1. 干得漂亮!给你3000个GitHub星标!!!

    2. 如果你尝试实现你描述的内容,你会很快发现你遗漏了什么。具体来说,你需要将接口与文本接口进行对接。

      1. 我不想说废话,但终端和像MUD这样的东西及其前身已经通过文本与人类交互了40年。

  11. 所以这基本上意味着要么让工具实现这个接口,要么编写一个封装层(这相当于编写一个MCP服务器),对吧?所以这比MCP稍微通用一些,还是我漏掉了什么?

  12. 为什么大家都抱怨,这很好,是比MCP更需要的改进。MCP还不是“最终答案”,也许有时间用更好的东西取代它。

  13. 你好HN,

    我是UTCP贡献者。

    我理解大家对在现有基础设施上无缘无故添加抽象层的 frustrations,但UTCP实际上正在努力避免 exactly that。

    想象以下场景。你创建了一个用户在日常生活中使用的代理。现在你希望用户能够做更多事情,而不仅仅是生成文本。也就是调用工具。

    如何实现这一点?

    选项1:你实现自己的基础设施,允许用户调用你自定义基础设施支持的任何工具。-> 用户在选择工具时灵活性较低

    选项 2:您使用 MCP 客户端。现在,您的用户可以添加任何支持 MCP 的工具。不过,这会增加一层额外的基础设施。代理 -> MCP 服务器 -> 原生工具(可能是 REST API、CLI 命令等)

    选项 3:您使用 UTCP 客户端。现在您的用户可以添加任何使用任何通信协议的工具。代理 -> 原生工具(可能是 REST API、CLI 命令、MCP 服务器等)

    简而言之,UTCP 注重安全性,而非重建现有基础设施。互联网上有大量通信协议可实现您能想象到的任何功能。我们应该利用这些协议,并使用它们编写接口和封装层,而非 MCP。这就是 UTCP 的作用。它允许代理利用现有基础设施、通信协议和安全机制。

    我们是一个完全由社区驱动的开源项目,目标是创建一个对用户有用的协议

    希望这能说清楚,祝大家开发愉快 <3

  14. 按照惯例,年轻一代的开发者将被炒作和 vaporware 烧伤,并创建一个充满孤儿协议和工具的生态系统

    这让我想起了 2000 年代初的所有 NoSQL 垃圾

  15. 这太疯狂了!我们一直在训练模型来编写和编辑代码,现在又来了这个?这些人应该读读这篇论文(CodeAct)https://arxiv.org/abs/2402.01030

    > 大语言模型(LLM)代理通常通过生成预定义格式的 JSON 或文本被提示执行操作,这通常受限于有限的操作空间(例如预定义工具的范围)和受限的灵活性(例如无法组合多个工具)。本研究提出使用可执行的 Python 代码将 LLM 代理的操作整合到统一的操作空间(CodeAct)中。通过与 Python 解释器集成,CodeAct 可执行代码动作,并在多轮交互中根据新观察结果动态修订先前动作或生成新动作。我们对 17 个大语言模型(LLMs) 在 API-Bank 及新整理的基准数据集上的广泛分析表明,CodeAct 的性能优于广泛使用的替代方案(成功率最高可提升 20%)。CodeAct的优异表现促使我们构建一个开源大语言模型(LLM)代理,该代理通过执行可解释代码与环境交互,并使用自然语言与用户协作。为此,我们收集了包含7000个多轮交互的指令微调数据集CodeActInstruct。我们证明该数据集可与现有数据结合,在不牺牲模型通用能力的前提下提升代理导向任务中的模型性能。基于 Llama2 和 Mistral 进行微调的 CodeActAgent 集成 Python 解释器,并通过现有库自主执行复杂任务(如模型训练)及进行自我调试。

  16. UTCP能否与OpenAI模型配合使用,尽管这些模型缺乏对MCP的通用支持?

    1. 通常模型本身不支持MCP,而是围绕模型构建的封装层支持。

  17. 也许我们可以实现一个 UTCP->REST 桥接,以添加另一个不必要的抽象层。

    /s

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你也许感兴趣的: