使用 AceDataCloud AI Chat v2 构建智能体应用

聊天端点可以返回文本。一个智能体端点可以检查文件、搜索网页、调用已授权工具、询问缺失信息,并将每一步流式传回你的界面。

这就是 AceDataCloud AI Chat v2 背后的实际差异。端点 POST https://api.acedata.cloud/aichat2/conversations 保留了原始对话 API 的简洁请求风格,同时增加了多模态内容块、自主多轮工具使用、MCP 连接、结构化流式事件、可恢复的对话以及对话 CRUD 操作。

AI Chat v2 架构:多模态输入、智能体工具和结构化事件

本指南重点介绍从基础聊天机器人迁移到生产级智能体体验时重要的集成决策。

AI Chat v2 有哪些变化?

AI Chat v2 是对原始 /aichat/conversations 接口的全面升级。其主要能力包括:

  • 多模态输入: 在一个 message 数组中发送有序的 text、image_url 和 file_url 块。
  • 自主工具使用: 模型可以跨多个轮次调用内置工具和用户授权的 MCP 服务器。
  • 类型化流式传输: 将文本、工具活动、引用、卡片、产物、错误和完成数据渲染为独立事件。
  • 暂停和恢复: 处理 ask_user_question 事件,并使用工具结果继续同一对话。
  • 对话管理: 通过同一端点上的操作进行检索、批量检索、更新和删除。
  • 向后兼容的请求: 现有的 model + question 客户端可以通过更改端点路径完成迁移。

重要的架构转变是,你的前端不再必须将响应视为一个不透明的字符串。它可以成为一个事件驱动的工作区。

从向后兼容的路径开始

风险最低的迁移方式有意保持很小的改动。保留现有请求体,只更改端点:

curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer YOUR_API_TOKEN' \
  -H 'content-type: application/json' \
  -d '{
    "model": "YOUR_SUPPORTED_MODEL",
    "question": "Summarize the three most important points in this request.",
    "stateful": true
  }'

在 JSON 模式下,响应保留了熟悉的结构:

{
  "answer": "...",
  "id": "conversation-uuid"
}

保留返回的 id。在下一次请求中发送它,即可继续托管对话,而无需你的客户端重新发送完整消息历史记录。

stateful 默认为 true。当某一轮不应被存储时,请显式将其设置为 false。

这个第一步迁移让你可以在引入工具或新的流式 UI 之前验证身份验证、模型可用性、延迟和应用程序行为。

当顺序和模态很重要时使用 message

旧版 question 字段便于仅文本提示。对于与图像或文件混合的文本,请使用有序的 message 数组:

{
  "model": "YOUR_SUPPORTED_MODEL",
  "stateful": true,
  "message": [
    {
      "type": "text",
      "text": "Read the attached report and compare its chart with this screenshot. Return five findings."
    },
    {
      "type": "file_url",
      "file_url": {
        "url": "https://example.com/report.pdf"
      }
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/dashboard.png"
      }
    }
  ]
}

支持的内容块包括:

块 必需值 最佳用途
text text 指令、上下文和问题
image_url image_url.url 截图、图表、产品图片
file_url file_url.url PDF、CSV、TXT 和其他文件

AI Chat v2 仍然识别旧版 references 数组。图像扩展名会被转换为图像块,而其他 URL 会成为文件块。这种兼容性在迁移期间很有用,但当内容顺序很重要时,message 是更好的长期契约。

围绕事件而不仅仅是令牌设计客户端

使用 accept 请求头选择响应格式:

客户端 请求头 格式
浏览器 UI text/event-stream 服务器发送事件
Node、Python、CLI、工作器 application/x-ndjson 每行一个 JSON 事件
简单后端请求 application/json 最终 {answer, id} 对象

一个最小的 Python NDJSON 消费者可以在保留其他事件类型的同时组装文本:

import json
import os
import requests

url = "https://api.acedata.cloud/aichat2/conversations"
headers = {
    "accept": "application/x-ndjson",
    "authorization": f"Bearer {os.environ['ACEDATA_API_TOKEN']}",
    "content-type": "application/json",
}
payload = {
    "model": os.environ["ACEDATA_CHAT_MODEL"],
    "question": "Research the topic, cite sources, and return a concise brief.",
    "stateful": True,
}

with requests.post(url, json=payload, headers=headers, stream=True, timeout=120) as response:
    response.raise_for_status()
    answer = []

    for raw_line in response.iter_lines():
        if not raw_line:
            continue

        event = json.loads(raw_line)
        event_type = event.get("type")

        if event_type == "text_delta":
            answer.append(event.get("content", ""))
        elif event_type == "tool_use":
            print("tool started:", event.get("tool_name"))
        elif event_type == "tool_result":
            print("tool finished; error =", event.get("is_error"))
        elif event_type == "citation":
            print("source:", event)
        elif event_type == "artifact":
            print("artifact:", event)
        elif event_type == "error":
            raise RuntimeError(event.get("message", "unknown agent error"))
        elif event_type == "done":
            print("usage:", event.get("usage"))
            print("terminal reason:", event.get("terminal_reason"))

print("".join(answer))

生产接口应为每个事件类别定义渲染器或处理程序:

  • text_delta 更新答案区域。
  • tool_use 和 tool_result 驱动活动状态和审计视图。
  • citation 将来源附加到相关输出。
  • card 渲染结构化预览。
  • artifact 提供单独生成的交付物。
  • 仅当所选模型公开 thinking 时才应处理它。
  • error 终止或恢复当前轮次。
  • done 关闭流,并记录令牌使用量和终止原因。

如果你的界面只需要最终答案,请连接每个 text_delta 中的 content。这等同于 JSON 模式下返回的 answer。

让智能体使用工具——但要让活动可见

工具调用默认启用。AI Chat v2 可以使用网页搜索、页面提取和文件读取等内置能力。它还可以挂载用户授权的 MCP 连接,例如 Google Drive、Notion、Slack 或 GitHub。

流清晰地公开了边界:

{"type":"tool_use","tool_id":"toolu_01","tool_name":"web_search","input":{"query":"topic"}}
{"type":"tool_result","tool_id":"toolu_01","output":"...","is_error":false}

通过 tool_id 配对 tool_use 和 tool_result。这支持进度指示器、延迟测量、错误处理以及供操作员阅读的审计跟踪。

使用 max_turns 来限制单个请求中可以发生多少轮自主工具调用。可接受范围为 1–500;文档中的默认值为 500。较低的值会减少开放式执行。设置 max_turns: 1 会强制单次响应并阻止工具调用。

一种实用的发布模式是:

  1. 在产品 UI 中以不使用工具的 JSON 模式开始。
  2. 添加 NDJSON 或 SSE,并渲染 text_delta 和 done。
  3. 将工具活动显示为折叠时间线。
  4. 添加引用和产物渲染。
  5. 根据任务复杂度和成本容忍度设置明确的 max_turns。
  6. 仅在审查其确认模型后启用具备写入能力的连接。

将问题处理为可恢复的状态机

智能体有时需要澄清。在这种情况下,流可以发出 ask_user_question,并且对话会进入 awaiting_user_input 状态。

你的客户端应当:

  1. 保存对话 id 和 tool_id。
  2. 渲染问题及其选项。
  3. 收集用户的回复。
  4. 使用相同的对话 id 发送另一个请求。
  5. 通过 tool_results 为待处理的工具调用返回答案。 这比假装代理可以在信息缺失的情况下完成任务更稳健。它还使敏感操作的审批关卡成为可能。

分离交互式和无人值守执行

对于 Webhook、CI/CD 作业和监控系统,async: true 会在工作继续进行时返回一个任务标识符。结果可以稍后检索,或传递到 HTTP(S) 回调 URL。

无人值守写入访问应当是明确的。AI Chat v2 支持 allowed_skills、allowed_mcp_servers 或等效的 unattended_policy 对象。空列表不授权任何能力。预授权不会绕过连接器自身的安全机制;不支持无人值守确认的技能仍应进行试运行或拒绝写入。

这种区别很重要:连接可用性并不等同于无需人员在场即可执行操作的权限。

生产检查清单

在启动代理式界面之前,请验证:

  • API 凭据存储在服务器端,绝不存储在浏览器代码中。
  • 模型名称来自当前支持的模型列表,而不是硬编码的假设。
  • 流解析器能够容忍不完整的网络块和未知事件类型。
  • 工具事件通过 tool_id 配对,并且错误会被记录。
  • max_turns 被有意设置。
  • 引用和工件 URL 被安全地渲染。
  • ask_user_question 持久化足够的状态,以便稍后恢复。
  • 具备写入能力的连接保留确认机制或范围严格限定的无人值守授权。
  • done.usage 和 terminal_reason 用于可观测性。
  • 对话删除和保留策略符合你的产品要求。

从聊天机器人到代理的最短路径

AI Chat v2 不会强制进行全面重写。先通过更改端点并保留你当前的请求正文开始。然后迁移到多模态 message 块,采用结构化流式传输,展示工具进度,并添加暂停和恢复处理。

结果是一个能够从简单回答成长为可审计代理工作流的客户端——无需为文件、工具、引用、工件或用户澄清设计单独的协议。

官方资源