教你一步步用 ChatUI + Julep 构建 AI 应用

简介: 本文介绍了如何使用 Julep 平台和 ChatUI 构建一个 AI 驱动的电影伴侣应用程序。通过创建用户、代理和会话,实现与用户的交互,并通过 API 获取响应消息。文章详细展示了从前端项目创建到后端集成的完整步骤,包括安装依赖、配置 API 密钥、处理用户输入和响应等。最终,通过运行项目,展示了应用程序的实际效果。源码已发布在 GitHub 上,供读者参考和学习。

本文首发微信公众号:前端徐徐。

前言

从头开始创建一个 AI 应用程序可能是一项非常具有挑战性的任务。无论您是想构建一个简单的聊天机器人还是一个先进的智能虚拟助手,成功开发出理想的应用程序可能需要数周的时间。但是,这正是 Julep 能帮助我们的地方。

Julep 是一个帮助构建具备状态功能和功能性 LLM 驱动应用的平台。使用 Julep,您只需几行代码就可以构建一个功能齐全的 AI 应用程序。

像 OpenAI 的 GPT-3、微软的 Azure Bot Service 和谷歌的 Dialogflow 这样的平台都可以构建 AI 应用程序。然而,Julep 因其优势脱颖而出,例如能够跟踪对话历史和上下文的状态功能、与多种 LLM 的轻松集成以及用于管理用户、代理和会话的用户友好界面。

在这篇文章中,我们将创建一个 MovieCompanion,一个 AI 驱动的电影伴侣应用程序,它可以提供用户所询问的任何电影的推荐和信息。我们将逐步了解如何在您的项目中使用 Julep。让我们开始吧!

前置条件

确保您的设备上已安装 Node.js,从 Node.js 官方网站下载并安装 Node.js。

Node.js 官网:https://nodejs.org/en

了解 Julep:https://github.com/julep-ai/julep/blob/dev/README-CN.md

创建一个前端项目

要创建一个 React 应用程序,请在终端中运行以下命令:

pnpm create vite

你可以查看 Vite 文档来创建一个 React 应用。

安装 ChatUI 依赖:

pnpm add @chatui/core -D

在 App.tsx 文件中创建基本结构。添加一个 <Chat> 组件,允许用户输入问答:

<Chat
    navbar={{ title: "电影伴侣" }}
    messages={messages}
    renderMessageContent={renderMessageContent}
    quickReplies={defaultQuickReplies}
    onQuickReplyClick={handleQuickReplyClick}
    onSend={handleSend}
/>

有了整体的结构只需要完善几个方法就行:

首先是 renderMessageContent

function renderMessageContent(msg: MessageProps) {
    const { type, content } = msg;
    // 根据消息类型来渲染
    switch (type) {
      case "text":
        return <Bubble content={content.text} />;
      case "image":
        return (
          <Bubble type="image">
            <img src={content.picUrl} alt="" />
          </Bubble>
        );
      default:
        return null;
    }
  }

主要是利用 ChatUI 的方法,根据不用的消息渲染不同的消息展示。

然后是 defaultQuickReplies

// 默认快捷短语,可选
const defaultQuickReplies: Array<QuickReplie> = [
  {
    icon: "message",
    name: "来一部喜剧电影",
    isNew: true,
    isHighlight: true,
  },
  {
    name: "随便推荐一部电影",
    isNew: true,
  },
];

这是快捷回复选项,可以让用户进入应用就直接快速询问。

最核心的 handleQuickReplyClick

// 发送回调
  function handleSend(type: string, val: string) {
    if (type === "text" && val.trim()) {
      appendMsg({
        type: "text",
        content: { text: val },
        position: "right",
      });
      setTyping(true);
      axios
        .post("http://127.0.0.1:3000/chat", {
          query:val
        })
        .then((res) => {
          const agentResponse = res.data.response;
          appendMsg({
            type: "text",
            content: { text: agentResponse },
          });
        })
        .catch(() => {
          appendMsg({
            type: "text",
            content: { text: "请求出了点问题,请重试~" },
          });
        });
    }
  }
  // 快捷短语回调,可根据 item 数据做出不同的操作,这里以发送文本消息为例
  function handleQuickReplyClick(item: QuickReplie) {
    handleSend("text", item.name);
  }

这里是输入的处理,然后和后端服务交互。

以下是完整的 App.tsx 代码:

import Chat, { Bubble, useMessages, MessageProps } from "@chatui/core";
import axios from "axios";
const initialMessages = [
  {
    type: "text",
    content: { text: "主人好,我是您的贴心电影伴侣~" },
    user: {
      avatar: "//gw.alicdn.com/tfs/TB1DYHLwMHqK1RjSZFEXXcGMXXa-56-62.svg",
    },
  },
];
interface QuickReplie {
  icon?: string;
  name: string;
  isNew?: boolean;
  isHighlight?: boolean;
}
// 默认快捷短语,可选
const defaultQuickReplies: Array<QuickReplie> = [
  {
    icon: "message",
    name: "来一部喜剧电影",
    isNew: true,
    isHighlight: true,
  },
  {
    name: "随便推荐一部电影",
    isNew: true,
  },
];
const App = () => {
  // 消息列表
  const { messages, appendMsg, setTyping } = useMessages(initialMessages);
  // 发送回调
  function handleSend(type: string, val: string) {
    if (type === "text" && val.trim()) {
      appendMsg({
        type: "text",
        content: { text: val },
        position: "right",
      });
      setTyping(true);
      axios
        .post("http://127.0.0.1:3000/chat", {
          query:val
        })
        .then((res) => {
          const agentResponse = res.data.response;
          appendMsg({
            type: "text",
            content: { text: agentResponse },
          });
        })
        .catch(() => {
          appendMsg({
            type: "text",
            content: { text: "请求出了点问题,请重试~" },
          });
        });
    }
  }
  // 快捷短语回调,可根据 item 数据做出不同的操作,这里以发送文本消息为例
  function handleQuickReplyClick(item: QuickReplie) {
    handleSend("text", item.name);
  }
  function renderMessageContent(msg: MessageProps) {
    const { type, content } = msg;
    // 根据消息类型来渲染
    switch (type) {
      case "text":
        return <Bubble content={content.text} />;
      case "image":
        return (
          <Bubble type="image">
            <img src={content.picUrl} alt="" />
          </Bubble>
        );
      default:
        return null;
    }
  }
  return (
    <Chat
      navbar={{ title: "电影伴侣" }}
      messages={messages}
      renderMessageContent={renderMessageContent}
      quickReplies={defaultQuickReplies}
      onQuickReplyClick={handleQuickReplyClick}
      onSend={handleSend}
    />
  );
};
export default App;

下面是前端页面效果:

客户端做好了,我们需要将 Julep 集成到我们的项目中,并能够对话,让我们开始集成吧。

安装依赖

为了完成电影伴侣应用程序,我们需要安装一些必要的库。这些库包括:

  • express - 用于创建和管理您的 Web 服务器
  • julep SDK - 用于与 Julep 提供的特定服务或 API 进行交互
  • body-parser - 用于解析传入的请求体,使处理客户端发送的数据更加容易
  • cors - 用于启用跨源请求,允许您的服务器处理来自不同域的请求
  • dotenv - 用于检索存储在.env文件中的值
  • axios - 一个基于 Promise 的 HTTP 客户端,用于 node.js 和浏览器

运行以下命令来安装这些库:

pnpm add express @julep/sdk cors body-parser dotenv axios -D

集成 Julep

要集成 Julep,我们需要一个 API 密钥。

访问 platform.julep.ai 并使用 Google 账号登录。复制位于右上角的 "YOUR API TOKEN"。

这个 API 令牌将作为你的 API 密钥。

在你的项目目录中创建一个 .env 文件,并粘贴以下代码:

JULEP_API_KEY = "api_key"

api_key 替换为复制的 API 令牌。

src 目录中创建一个名为 server.js 的文件。所有 Julep 的代码都将在此文件中编写。

首先,我们将导入所需的库。

import express from "express";
import julep from "@julep/sdk";
import bodyParser from "body-parser";
import cors from "cors";
import { fileURLToPath } from "url"; // 导入 fileURLToPath 函数
import path from "path";
import dotenv from "dotenv";

使用 Julep SDK 的 Client 类创建一个新客户端。此客户端与 Julep API 交互,并初始化代理、用户、会话、文档、记忆和工具的管理器。

const apiKey = process.env.JULEP_API_KEY;
const client = new julep.Client({ apiKey });

现在,我们将创建一个 Express 应用实例作为后台服务器。使用 bodyParser.json() 配置应用自动解析传入的 JSON 请求,并使用 cors() 启用跨源资源共享 (CORS),允许来自多个源的请求。

const app = express();
app.use(bodyParser.json());
app.use(cors());

为 Express 应用的 /chat 端点设置一个异步的 POST 请求处理器。

app.post("/chat", async (req, res) => {
  try {
    const query = req.body.query;
    // 现在,让我们创建用户、代理和会话以与 Julep API 进行交互。
  } catch (error) {
    res.status(500).send(error.message);
  }
});

try 块内,创建一个存储用户输入查询的 query 变量。

try {
  const query = req.body.query;
  // 接下来,创建用户、代理和会话以与 Julep API 进行交互。
} catch (error) {
  res.status(500).send(error.message);
}

请根据需要继续完成与 Julep API 的交互代码。

创建用户

用户对象代表与应用程序交互的实体,可以是真实的人或系统。每个使用 Julep 开发的 AI 应用程序都支持多个用户,每个用户都能够与代理进行交互。每个用户都是独立的,意味着他们有自己独特的身份和分配的角色。

用户是一个可选的实体,应用程序在没有定义用户的情况下也能正常运行。然而,建议为每个与代理交互的个人或系统创建用户档案,以便更好地组织和跟踪。特别是,添加一些关于用户的基本信息可以帮助应用程序更好地理解他们的行为,从而提供个性化的结果,以满足用户的偏好和需求。

在创建用户时,Julep 提供了 users.create() 方法,我们可以在客户端上使用该方法来创建用户。创建用户需要4个属性:

  • Name- 用户的姓名
  • About- 用户的简短描述
  • Documents- 按照用户需求格式化的文本形式的重要文件(可选)
  • Metadata- 应用程序中与用户相关的附加数据,超出 ID 范围(可选)

例如:

const user = await client.users.create({
  name: "xiaohong",
  about: "Machine Learning Developer and AI Enthusiast",
  docs: [{"title": "AI Efficiency Report", "content": "...", "metadata": {"page": 1}}],  // 可选
  metadata: {"db_uuid": "1234"}, // 可选
});

现在,让我们为我们的电影伴侣应用程序创建一个用户:

const user = await client.users.create({
   name: "Xiaoxu",
   about: "前端开发工程师",
});

在这里,我们创建了一个名为 xiaoxu 的用户,并且描述为前端开发工程师。

创建 Agent

代理是用户与应用程序之间的智能接口,负责处理所有交互并增强用户体验。代理被编程为处理用户提出的查询,并提供定制的结果或建议。

代理包含了你希望在 AI 应用程序中使用的 LLM 模型的所有配置和设置。这使得应用程序能够执行特定任务,并满足用户的个人偏好。

这些代理可以简单到只是一个聊天机器人,也可以复杂到能够理解自然语言并执行复杂任务的高度智能助手。

与用户类似,Julep 包括 agents.create() 方法来创建代理。创建代理需要一组属性:

  • Name- 代理的名称
  • About- 代理的简短描述(可选)
  • Instructions- 代理需要遵循的指令列表(可选)
  • Tools- 代理执行任务的函数列表(可选)
  • Model Name- 代理将使用的 LLM 模型(可选)
  • Settings- LLM 模型的配置(可选)
  • Documents- 代理使用的重要文本格式文件,以改善其角色(可选)
  • Metadata- 除 ID 之外的附加信息,用于识别用户或代理(可选)

例如:

const agent = client.agents.create(
  (name = "Cody"),
  (about =
    "Cody is an AI powered code reviewer. It can review code, provide feedback, suggest improvements, and answer questions about code."),
  (instructions = [
    "On every new issue, Review the issue made in the code. Summarize the issue made in the code and add a comment",
    "Scrutinize the changes very deeply for potential bugs, errors, security vulnerabilities. Assume the worst case scenario and explain your reasoning for the same.",
  ]),
  (tools = [
    {
      type: "function",
      function: {
        name: "github_comment",
        description:
          "Posts a comment made on a GitHub Pull Request after every new commit. The tool will return a boolean value to indicate if the comment was successfully posted or not.",
        parameters: {
          type: "object",
          properties: {
            comment: {
              type: "string",
              description:
                "The comment to be posted on the issue. It should be a summary of the changes made in the PR and the feedback on the same.",
            },
            pr_number: {
              type: "number",
              description:
                "The issue number on which the comment is to be posted.",
            },
          },
          required: ["comment", "pr_number"],
        },
      },
    },
  ]),
  (model = "gpt-4"),
  (default_settings = {
    temperature: 0.7,
    top_p: 1,
    min_p: 0.01,
    presence_penalty: 0,
    frequency_penalty: 0,
    length_penalty: 1.0,
  }),
  (docs = [{ title: "API Reference", content: "...", metadata: { page: 1 } }]),
  (metadata = { db_uuid: "1234" })
);

现在,让我们为我们的 Movio 应用程序创建一个代理:

const agent = await client.agents.create({
  name: "Movie suggesting assistant",
  model: "gpt-4-turbo",
});

如你所见,在这个代理中我们使用了 gpt-4-turbo LLM 模型,但 Julep 支持多种 LLM 模型,你可以用它们来创建 AI 应用程序。查看文档以了解更多信息。

创建会话

会话是用户与代理之间进行互动的实体。这是用户与代理之间互动的时间段。它作为整个互动的框架,包括来回的消息查询和其他相关细节。

会话记录了用户和代理之间交换的所有消息。这些记录帮助 AI 更好地理解正在进行的对话,并提供更个性化的回答。

要创建会话,我们可以使用 sessions.create() 方法。让我们来看一下它所需的属性:

  • Agent ID- 创建的代理的 ID
  • User ID- 创建的用户的 ID(可选)
  • Situation- 描述互动背景的提示
  • Metadata- 用于标识会话的除 ID 之外的附加信息

situation 属性在会话中起着至关重要的作用,因为它为互动或对话提供了上下文。这个情境帮助代理更好地理解和计算用户的查询,并提供更个性化的回复。

例如:

// 假设 'client' 是一个包含 'sessions' 属性和 'create' 方法的对象
let session = client.sessions.create({
  agent_id: agent.id,
  user_id: user.id,
  situation: `
        You are James, a Software Developer, public speaker & renowned educator.
        You are an educator who is qualified to train students, developers & entrepreneurs.
        About you:
        ...
        Important guidelines:
        ...
    `,
  metadata: { db_uuid: "1234" },
});

现在,让我们为我们的 Movio 应用程序创建一个会话:

const session = await client.sessions.create({
  agentId: agent.id,
  userId: user.id,
  situation: "你是一个电影伴侣。告诉人们他们想要的电影,并向用户推荐电影。",
});

在这里,agentIduserId 是我们之前创建的代理和用户的 ID,而 situation 是为互动提供的小上下文。

获取响应消息

在创建用户、代理和会话之后,我们需要处理互动。我们将使用 sessions.chat() 方法来处理聊天互动并获取响应消息。

该方法需要两个属性才能运行——session.id 和一个包含 messages 数组的对象。

const chatParams = {
  messages: [
    {
      role: "user",
      name: "Ayush",
      content: query,
    },
  ],
};
const chatResponse = await client.sessions.chat(session.id, chatParams);
const responseMessage = chatResponse.response[0][0].content;
res.json({ response: responseMessage });

这里,chatParams 对象包含 messages 数组,其中包括一个具有三个属性的对象:

  • role: 消息发送者的角色,"user"。
  • name: 用户的名字,"Ayush"。
  • content: 用户的查询,存储在变量query中。

然后,在 client 上调用 sessions.chat() 方法,传入 session.idchatParams 作为参数。结果对象存储在 chatResponse 中。

chatResponse 中提取 content 属性的值,并将其存储在 responseMessage 中。

处理错误

为了处理错误,我们将使用 catch 块来捕获错误并显示它。

catch (error) {
  res.status(500).json({ error: error.message });
}

启动服务器

要在本地启动服务器,我们使用 app 上的 listen() 方法指定端口号。

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

这将在 localhost:3000 上托管服务器,并在控制台窗口中打印定义的字符串。

恭喜!你的 AI 应用程序已经成功创建。

运行应用程序

项目已完成,我们将运行它并进行尝试。

要运行应用程序,首先,我们需要运行 server.js 文件以启动 Julep API,然后运行 React 应用以启动用户界面。

运行以下命令以启动服务器:

node src/server.js

要运行 React 应用程序,运行以下命令:

npm run dev

这将使你的项目在本地主机上运行。以下是项目的演示:

总结

通过结合使用 ChatUI 和 Julep,开发者可以快速构建一个具有交互式界面和强大 AI 后端支持的应用。这一过程涉及前端界面的设计和后端 AI 服务的集成,并通过 API 实现前后端的交互。完成后,可以将应用部署到云端,方便用户访问和使用。这篇文章只是一个简单的入门教程,如果正式生产环境还需要一些调整和优化,希望大家可以通过本篇文章去创建一个属于自己的 AI 小应用。

源码

https://github.com/Xutaotaotao/movie-companion-app

目录
打赏
0
0
0
0
39
分享
相关文章
从零开始即刻拥有 DeepSeek-R1 满血版并使用 Dify 部署 AI 应用
本文介绍了如何使用阿里云提供的DeepSeek-R1大模型解决方案,通过Chatbox和Dify平台调用百炼API,实现稳定且高效的模型应用。首先,文章详细描述了如何通过Chatbox配置API并开始对话,适合普通用户快速上手。接着,深入探讨了使用Dify部署AI应用的过程,包括选购云服务器、安装Dify、配置对接DeepSeek-R1模型及创建工作流,展示了更复杂场景下的应用潜力。最后,对比了Chatbox与Dify的输出效果,证明Dify能提供更详尽、精准的回复。总结指出,阿里云的解决方案不仅操作简便,还为专业用户提供了强大的功能支持,极大提升了用户体验和应用效率。
623 18
从零开始即刻拥有 DeepSeek-R1 满血版并使用 Dify 部署 AI 应用
Archon – 开源 AI 智能体框架,自主生成代码构建 AI 智能体
Archon 是一个开源的 AI 智能体框架,能够自主生成代码并优化智能体性能,支持多智能体协作、领域知识集成和文档爬取等功能,适用于企业、教育、智能家居等多个领域。
74 10
Archon – 开源 AI 智能体框架,自主生成代码构建 AI 智能体
AI程序员:通义灵码 2.0应用VScode前端开发深度体验
AI程序员:通义灵码 2.0应用VScode前端开发深度体验,在软件开发领域,人工智能技术的融入正深刻改变着程序员的工作方式。通义灵码 2.0 作为一款先进的 AI 编程助手,与广受欢迎的代码编辑器 Visual Studio Code(VScode)相结合,为前端开发带来了全新的可能性。本文将详细分享通义灵码 2.0 在 VScode 前端开发环境中的深度使用体验。
54 2
Spring AI与DeepSeek实战一:快速打造智能对话应用
在 AI 技术蓬勃发展的今天,国产大模型DeepSeek凭借其低成本高性能的特点,成为企业智能化转型的热门选择。而Spring AI作为 Java 生态的 AI 集成框架,通过统一API、简化配置等特性,让开发者无需深入底层即可快速调用各类 AI 服务。本文将手把手教你通过spring-ai集成DeepSeek接口实现普通对话与流式对话功能,助力你的Java应用轻松接入 AI 能力!虽然通过Spring AI能够快速完成DeepSeek大模型与。
246 11
Serverless + AI 让应用开发更简单,加速应用智能化
Serverless + AI 让应用开发更简单,加速应用智能化
Java 也能快速搭建 AI 应用?一文带你玩转 Spring AI 可观测性
Java 也能快速搭建 AI 应用?一文带你玩转 Spring AI 可观测性
金鸡电影节创投大会AI短片《天线》:构建基于现实世界的想象空间
金鸡电影节创投大会AI短片《天线》:构建基于现实世界的想象空间
探索HarmonyOS在智慧出行领域的AI类目标签应用
在科技飞速发展的今天,智慧出行成为交通领域的重要发展方向。HarmonyOS凭借强大的系统能力,为智慧出行注入新活力,特别是在AI类目标签技术的应用上。通过精准分类和标签化处理车辆、路况及出行者数据,AI类目标签技术提升了出行体验与交通管理效率。HarmonyOS的分布式软总线技术和隐私保护机制,确保了设备间的无缝连接与数据安全。实际应用中,该技术助力智能交通管理和个性化出行服务,为解决交通拥堵、优化资源配置提供了新思路。开发者也迎来了广阔的机遇与挑战,共同推动智慧出行的美好未来。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等