大数跨境

如何在 5 分钟内为你的应用添加人工智能

如何在 5 分钟内为你的应用添加人工智能 索引目录
2026-03-12
0
导读:关注「索引目录」公众号,获取更多干货。大多数人工智能集成都存在过度设计的问题。

关注「索引目录」公众号,获取更多干货。

大多数人工智能集成都存在过度设计的问题。

就连添加AI助手的入门教程都会把LangGraph工作流和FastAPI服务器混为一谈。你根本不需要这些。

今天,我们将构建一个无需任何外部代理框架或编排层的AI。它只需要一个了解你的应用内容并能实际执行操作的AI。

你还将学习如何实现生成式用户界面模式,该模式允许你渲染实际组件,而不仅仅是文本响应。

让我们开始吧。


为什么人工智能集成会变得复杂

在应用程序中添加人工智能听起来很简单,但当你真正尝试时就会发现并非如此。

一旦你超越了基本的聊天界面,就会遇到一个根本性的问题:LLM本身什么都做不了,它们只能生成文本。

要创建一个能够真正执行操作的人工智能:读取应用程序的状态、更新数据、调用 API——你需要自己构建底层架构。

人工智能代理的本质就是这种底层架构。从本质上讲,每个代理都运行着相同的循环:

  1. 观察——考虑上下文(用户输入、工具结果、内存)
  2. 理由——决定下一步该怎么做
  3. 执行操作——调用工具、写入文件、调用 API,或者做任何需要做的事情。
图片来源:人类学

理论上很简单。但实际上,你最终需要编写编排层来管理这个循环,编写工具注册表将应用程序的功能暴露给 LLM,编写状态管理来跟踪代理知道的内容,以及编写错误处理程序来处理模型出现异常时的错误。

context = [initial_event]
while True:
  next_step = await llm.determine_next_step(context)
  context.append(next_step)
  if next_step.intent == "done":
    return next_step.final_answer
  result = await execute_step(next_step)
  context.append(result)

在完整的代理设置中,LLM 位于中心——协调数据源、工具、模型和外部服务。

图片来源:Medium博客

这就是为什么教程会讲解 LangGraph 和 FastAPI 服务器的原因。对于复杂的自动化流程来说,这种复杂性是合理的。

但如果你的目标只是在你的产品中添加一个 AI 助手——一个能够理解你的用户界面、读取你的数据并代表用户执行操作的助手,那么你就是在构建大量的基础设施来解决一个小得多的问题。

CopilotKit处理循环、上下文、流式传输和前端集成,因此您无需自己进行任何连接。



在本教程中,我们将使用 CopilotKit,无需任何外部代理框架,只需钩子和您选择的 LLM。


CopilotKit 的实际功能

CopilotKit是一个开源框架,可将 AI 代理添加到您的应用程序中,它抽象化了您刚才读到的所有内容。

您无需构建自己的代理循环、工具注册表和流式传输层,而是可以获得一组钩子和预构建组件,这些组件可以直接插入到您现有的前端中。

这个思维模型很简单,你只需要向人工智能提供两样东西:

  • 您的应用程序状态
    ——以便它了解屏幕上显示的内容以及用户正在操作的内容。
  • 一套工具
    ——这样它就能真正做一些有用的事情,而不仅仅是回复文本。

实际上,这对应着两个钩子:

  • useAgentContext
     - 与 AI 共享应用状态。您传递的任何内容都会成为 LLM 上下文的一部分:当前用户、选定项目、已加载数据 - AI 了解您的应用所知道的一切。
  • useFrontendTool
     - 定义 AI 可以触发的操作。您需要为其命名、描述并指定处理程序。LLM 会根据用户的请求决定何时调用它。

结果是,在应用程序中添加 AI 助手变成了一个前端问题,而不是一个基础设施问题。

您的用户界面、代理和工具都在同一个交互循环中。




如何连接所有线路(1分钟)

你可以参考官方文档,也可以直接看我的教程。我会详细解释每个部分的作用和原因。

我使用的是 Next.js 和 TypeScript,但这也适用于任何 React/Angular 框架!

// creates a nextjs app  
npx create-next-app@latest .



安装所需的三个 CopilotKit 软件包:

npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime
  • @copilotkit/react-core/v2
    :钩子和内置聊天组件
  • @copilotkit/react-ui/v2
    样式
  • @copilotkit/runtime
    后端运行时和LLM适配器



创建 API 路由app/api/copilotkit/route.ts

它是接收来自用户界面的消息、通过代理循环处理消息并将响应流式返回的唯一端点。

  • BuiltInAgent
    就是运行观察→推理→行动循环的程序。
  • CopilotRuntime
    管理会话、流式传输和工具执行

这就是你的整个后端。

import { CopilotRuntime, copilotRuntimeNextJSAppRouterEndpoint } from "@copilotkit/runtime";
import { BuiltInAgent } from "@copilotkit/runtime/v2";
import { NextRequest } from "next/server";

const builtInAgent = new BuiltInAgent({
  model: "openai:gpt-5",
  // apiKey: process.env.OPENAI_API_KEY,
});

const runtime = new CopilotRuntime({
  agents: { default: builtInAgent },
});

export const POST = async (req: NextRequest) => {
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    endpoint: "/api/copilotkit",
  });
  return handleRequest(req);
};

.env.local在根目录下创建并添加您的OpenAI API 密钥

OPENAI_API_KEY=sk-proj-...

如果您想切换到其他 LLM 提供商,只需BuiltInAgent在 API 路由中传递修改后的字符串即可。其他所有设置保持不变。

// Anthropic
const builtInAgent = new BuiltInAgent({ model: "anthropic:claude-sonnet-4-5" });

// Google
const builtInAgent = new BuiltInAgent({ model: "google:gemini-2.0-flash" });

添加匹配的键,.env.local就完成了。对于 Azure OpenAI、AWS Bedrock 或 Ollama 等自定义模型,请查看模型选择文档

现在,通过将你的应用程序包装在 . 中,将前端连接到后端app/layout.tsx

import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/v2/styles.css";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <CopilotKit runtimeUrl="/api/copilotkit">
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}

CopilotKit是其下所有钩子所依赖的上下文提供程序。runtimeUrl指向您刚刚创建的路由。

CopilotSidebarCopilotChatCopilotPopup等都是内置组件。本文将介绍如何添加聊天侧边栏。

import { CopilotSidebar } from "@copilotkit/react-core/v2";

export default function Page() {
  return (
    <main>
      <h1>Your App</h1>
      <CopilotSidebar />
    </main>
  );
}

运行一下npm run dev,你现在就拥有一个可用的AI侧边栏助手啦!🎉



它可以对任何操作做出响应,但它完全不知道你的应用里实际有什么。它不知道你的数据、你的用户界面状态,也不知道用户正在查看什么。接下来的两个步骤将解决这个问题。


为人工智能提供背景信息

默认情况下,人工智能对你的应用内容一无所知。你可以问它“我花了多少钱买食物?”,它完全不知道——它只能看到对话内容,看不到你应用的运行状态。

useAgentContext可以解决这个问题。它会在每一回合都将你的 React 状态推送到代理的上下文窗口中,这样 AI 就能始终掌握 UI 中内容的最新快照。

让我们构建一个简单的费用跟踪器来看看它是如何运作的。

"use client";
import { useState } from "react";
import { useAgentContext, CopilotSidebar } from "@copilotkit/react-core/v2";

type Expense = {
  id: number;
  description: string;
  amount: number;
  category: string;
};

const initialExpenses: Expense[] = [
  { id: 1, description: "Groceries", amount: 85, category: "Food" },
  { id: 2, description: "Netflix", amount: 15, category: "Entertainment" },
  { id: 3, description: "Uber", amount: 22, category: "Transport" },
];

export default function Page() {
  const [expenses, setExpenses] = useState<Expense[]>(initialExpenses);

  useAgentContext({
    description: "The user's current expense list. Each item has an id, description, amount in dollars, and category.",
    value: expenses,
  });

  return (
    <main className="p-8">
      <h1 className="text-2xl font-bold mb-4">My Expenses</h1>
      <ul className="space-y-2">
        {expenses.map((e) => (
          <li key={e.id} className="flex justify-between border-b py-2">
            <span>
              {e.description}{" "}
              <span className="text-gray-400 text-sm">({e.category})</span>
            </span>
            <span>${e.amount}</span>
          </li>
        ))}
      </ul>
      <CopilotSidebar />
    </main>
  );
}

expenses这是你的普通 React 状态。useAgentContext它会在每一轮调用时将其注入到 LLM 的上下文中。

现在,如果用户问“我最大的开支是什么?”,人工智能会查看与你的用户界面渲染的同一个列表。




让人工智能做事

意识是一回事,但能够采取行动才是使智能体真正发挥作用的关键。

useFrontendTool允许您向 AI 提供一组它可以触发的操作。您可以定义一个工具,包括名称、描述和处理程序——LLM 会根据用户的请求决定何时调用它。

LLM 会读取description字段以了解每个工具的功能和每个参数的预期值,因此请清晰地编写它们,即使是随意的对话输入,模型也能准确地填充它们。

添加useFrontendTool到同一页面内。

parameters它接受一个Zod schema(一个以 TypeScript 为主的验证库)。如果您之前没有使用过它,它的原理很简单:您定义数据的结构z.object({...}),每个字段都会收到一个.describe()调用,该调用告诉 LLM 该字段的含义。

使用以下命令安装npm install zod

"use client";
import { useState } from "react";
import { useAgentContext, useFrontendTool, CopilotSidebar } from "@copilotkit/react-core/v2";
import { z } from "zod";

// ... type and initialExpenses stay the same

export default function Page() {
  const [expenses, setExpenses] = useState<Expense[]>(initialExpenses);

  // ... useAgentContext

  useFrontendTool({
  name: "addExpense",
  description:
    "Add a new expense when the user mentions spending money on something.",
  parameters: z.object({
    description: z
      .string()
      .describe("What the expense was for, e.g. Lunch, Taxi, Coffee"),
    amount: z.number().describe("How much was spent in dollars"),
    category: z
      .string()
      .describe("Category: Food, Transport, Entertainment, Health, or Other"),
  }),
  handler: async ({ description, amount, category }) => {
    setExpenses((prev) => [
      ...prev,
      { id: Date.now(), description, amount, category },
    ]);
  },
});

  return (
    // ... remains the same
  );
}

您可以发送类似“我昨晚花了 40 美元吃晚饭”这样的示例查询。代理人打电话addExpense过来{ description: "Dinner", amount: 40, category: "Food" },您的处理程序更新信息expenses,新项目会立即出现在列表中。



这是观察→原因→行动的端到端循环。

代理程序通过观察您的消息和当前支出情况useAgentContext,判断这addExpense是正确的选择,并使用正确的参数调用了您的处理程序。CopilotKit 处理了所有中间步骤。


额外内容:生成式用户界面

人工智能可以读取并更新你的数据。但目前为止,它只能以文本形式回复。

生成式用户界面是一种新概念:它不是由代理描述结果,而是直接渲染实际的用户界面。例如,如果有人询问他们的消费情况,应用程序会显示一个明细卡片。

renderCopilotKit 通过属性支持此功能useFrontendTool。该工具不会返回文本回复,而是返回一个 React 组件——使用您自己的设计系统在聊天中内联渲染。

让我们在同一个组件中添加一个摘要工具。

import { ToolCallStatus, useFrontendTool } from "@copilotkit/react-core/v2";

useFrontendTool({
  name: "showSpendingSummary",
  description:
    "Call this when the user asks for a summary or overview of their expenses.",
  parameters: z.object({}),
  handler: async () => {
    const summary = expenses.reduce(
      (acc, e) => {
        acc[e.category] = (acc[e.category] ?? 0) + e.amount;
        return acc;
      },
      {} as Record<string, number>,
    );
    const total = expenses.reduce((sum, e) => sum + e.amount, 0);
    return JSON.stringify({ summary, total });
  },
  render: ({ result, status }) => {
    return (
      <div className="rounded-lg border p-4 mt-2 space-y-3">
        <p className="font-semibold text-sm">
          {status === ToolCallStatus.InProgress ? "Calculating..." : "Spending Breakdown"}
        </p>
        {status === ToolCallStatus.Complete && result && (
          <>
            {Object.entries(
              (JSON.parse(result) as { summary: Record<string, number>; total: number }).summary
            ).map(([category, amount]) => (
              <div key={category} className="flex justify-between text-sm">
                <span className="text-gray-600">{category}</span>
                <span className="font-medium">${amount}</span>
              </div>
            ))}
            <div className="flex justify-between text-sm font-semibold border-t pt-2">
              <span>Total</span>
              <span>${(JSON.parse(result) as { summary: Record<string, number>; total: number }).total}</span>
            </div>
          </>
        )}
      </div>
    );
  },
});

这里发生了什么:

  • parameters: z.object({})
    为空。LLM 不需要传递任何参数,它只需要决定何时调用该工具。
  • handler
    实际执行计算,根据状态计算类别总数expenses并返回结果。
  • ToolCallStatus
    提供工具调用的确切生命周期状态
  • result
    这是你的处理程序返回的 JSON 字符串,它被解析回一个对象。render

当你问“汇总我的支出”时,LLM 会读取查询,查看上下文,识别出这showSpendingSummary是要调用的正确工具并触发它。



这就是模式:LLM 决定何时行动,你的代码执行工作,你的组件显示结果。

这个极简费用跟踪器的工作实现可以在GitHub 仓库的example/basic分支中找到。

main分支机构进一步采用了相同的模式,使用了完整的看板:

  • 通过询问人工智能,将任务在不同列之间移动。
  • 通过自然语言添加、删除和重新分配任务
  • 利用生成式用户界面获取可视化看板摘要。

关注「索引目录」公众号,获取更多干货。


【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444