教你一步步用 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

相关文章
|
3天前
|
人工智能 Serverless
AI助理精准匹配------助力快速搭建Stable Difussion图像生成应用
【10月更文挑战第7天】过去在阿里云社区搭建Stable Diffusion图像生成应用需查阅在线实验室或官方文档,耗时且不便。现阿里云AI助理提供精准匹配服务,直接在首页询问AI助理即可获取详细部署步骤,简化了操作流程,提高了效率。用户可按AI助理提供的步骤快速完成应用创建、参数设置、应用部署及资源释放等操作,轻松体验Stable Diffusion图像生成功能。
|
1天前
|
机器学习/深度学习 人工智能 监控
探索AI技术在医疗健康领域的应用与挑战
【10月更文挑战第13天】 本文探讨了人工智能(AI)在医疗健康领域的多种创新应用,包括疾病诊断、个性化治疗、患者监护和药物研发等方面。同时,文章也分析了当前AI技术在实际应用中面临的挑战,如数据隐私、算法透明度、监管问题等,并提出了一些可能的解决思路。通过综合分析,本文旨在为读者提供一个关于AI在医疗领域应用现状及未来的全面视角。
15 3
|
1天前
|
人工智能
添加一个Stable Difussion图像生成应用,通过向AI助手简单的提问,即可快速搭建Stable Diffusion应用至自己的网站中,大幅提升开发效率。
添加一个Stable Difussion图像生成应用,通过向AI助手简单的提问,即可快速搭建Stable Diffusion应用至自己的网站中,大幅提升开发效率。
|
1天前
|
人工智能 NoSQL 测试技术
使用 MongoDB 构建 AI:Patronus 如何自动进行大语言模型评估来增强对生成式 AI 的信心
若需了解更多MongoDB Atlas相关内容,可前往:https://www.mongodb.com/zh-cn/atlas
使用 MongoDB 构建 AI:Patronus 如何自动进行大语言模型评估来增强对生成式 AI 的信心
|
2天前
|
存储 消息中间件 人工智能
ApsaraMQ Serverless 能力再升级,事件驱动架构赋能 AI 应用
本文整理自2024年云栖大会阿里云智能集团高级技术专家金吉祥的演讲《ApsaraMQ Serverless 能力再升级,事件驱动架构赋能 AI 应用》。
|
2天前
|
人工智能 自然语言处理 搜索推荐
【通义】AI视界|微软Copilot Studio推出新功能,帮助企业更便捷地构建和部署AI代理
本文介绍了近期科技领域的五大重要动态:马斯克旗下xAI发布首个API,苹果内部研究显示ChatGPT比Siri准确率高25%,微软Copilot Studio推出新功能,霍尼韦尔与谷歌合作引入Gemini AI,浑水创始人建议买入科技七巨头股票。更多资讯请访问【通义】。
|
3天前
|
人工智能
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
122 2
|
2天前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
1天前
|
存储 人工智能 NoSQL
使用 MongoDB 构建 AI:Gradient Accelerator Block 如何在几秒钟内让您从零开发 AI
借助 MongoDB,开发者可以存储任何结构的数据,然后使用单一查询 API 和驱动程序将这些数据用于 OLTP、文本搜索和向量搜索处理。
|
1天前
|
人工智能 自然语言处理 NoSQL