Ant Design X 初体验

1,953 阅读4分钟

前言

近年来,随着人工智能(AI)的迅猛发展,数字化转型已经成为各行各业的核心推动力。在这一变革过程中,用户体验和界面设计也在不断地演变和提升。作为一款基于 React 的 UI 组件库,Ant Design X(简称 Antd X)应运而生,它不仅继承了 Ant Design 的优雅与简洁,还在性能、可定制性、易用性等方面进行了创新和优化。Ant Design X 旨在为开发者提供更加灵活和高效的前端解决方案,助力构建现代化的企业级应用。

随着 Web 应用的功能日益复杂,Ant Design X 通过引入丰富的组件库、响应式布局和高可用性设计,使得开发者可以更加专注于业务逻辑的实现,而无需过多关注界面的细节优化。

模型选择

chatGPT

这个不用说,目前市面上最好的,最先进的。不过缺点很明显,国内用户无法注册openAI的账号或者购买chatGPT接口的credit次数

openAI封禁了国内的IP以及信用卡,甚至是国内bank办理的visa

解决方案:

  1. wildcard去整一张年费国外虚拟信用卡,用于支付接口的credit
  2. 如果你有国外的信用卡也可以支付credit(这个是最牛解
  3. 如果openAI的账号注册不上的话,建议百度-不细聊
阿里云百炼

我自己测试是用的这个

阿里云提供了一个模型广场,里面有非常多的模型提供给用户选择,如果你是新用户可以申请模型免费使用一段时间(在后期plus肯定还是需要购买的),前期大家就是多体验一下

其他模型

等阿里云的免费体验完成之后,再去体验一下其他厂商的模型。。。。。

安装Antd X

使用Antd X的前提确保

"antd": ">=5.0.0",
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
安装指令
// npm
npm install @ant-design/x --save 

// yarn
yarn add @ant-design/x 

// pnpm
pnpm install @ant-design/x --save
引入组件
import { 
    Bubble,  // 对话气泡
    Prompts, // 提示集
    Conversations, // 管理对话
    Welcome, // 欢迎
    Attachments,  // 附件
    Sender, // 输入框
    Suggestion, // 快捷指令
    // 后续可能会推出新的组件
} from '@ant-design/x';
引入钩子工具等
import { 
    useXAgent,  // 模型调度
    useXChat, // 数据管理 - 与useXAgent搭配进行会话数据管理,并产出页面渲染的数据
    XStream, // 流 - 转换可读数据流
    XRequest, // 请求 - 向符合 OpenAI 标准的 LLM 发起请求
    XProvider, // 全局化配置
    // 后续可能会推出新的工具
} from '@ant-design/x';
简单的对话处理
// 因为我在自己项目中玩了一下,所以使用了zustand做全局的状态管理
import { CHAT_MODEL_CONFIG } from '@/utils/constant';
import { useXAgent, useXChat, XRequest } from '@ant-design/x';
import { useModel } from '@umijs/max';
import { useEffect } from 'react';
import { useStore } from './useStore';

// hooks
export const useRequest: () => any = () => {
  // ... 此处通过异步请求获取 或者 页面初始化后请求并托管到状态机中的 apiKey
  
  const { setMessages } = useStore((state) => state); // zustand

  const { create } = XRequest({
    baseURL: CHAT_MODEL_CONFIG.BASE_URL + CHAT_MODEL_CONFIG.PATH, // 模型的http请求路径
    model: CHAT_MODEL_CONFIG.MODEL, // 选择对话的大模型
    
    // 使用这个配置前,建议查看官网 - https://x.ant.design/docs/react/dangerously-api-key-cn
    dangerouslyApiKey: apiKey, // 这个apiKey是在厂商的控制台去生成的,建议apiKey不要存储在浏览器或者其他客户端中,因为这个非常危险,建议存储在服务端或者数据库,防止被他人窃取,如果发现apiKey被窃取,建议及时销毁旧的apiKey,重新生成新的apiKey
  });

  const [agent] = useXAgent({
    request: async (info, callbacks) => {
      const { message } = info;
      const { onSuccess, onError } = callbacks;

      let content = '';
      try {
        create(
          {
            messages: [
              {
                role: 'user',
                content: message,
              },
            ],
            stream: true,
          },
          {
            onSuccess: () => {
              onSuccess(content);
            },
            onError: (error) => {
              onError(error);
            },
            onUpdate: (response) => {
              try {
                if (!response.data?.includes('[DONE]')) {
                  const data = JSON.parse(response.data);
                  content += data?.choices[0].delta.content;
                }
              } catch (err) {
                console.log(err);
              }
            },
          },
        );
      } catch (err) {
        console.log(err);
      }
    },
  });

  // Chat messages
  const { onRequest, messages } = useXChat({
    agent,
    requestPlaceholder: 'Waiting...',
    requestFallback: 'Mock failed return. Please try again later.',
  });

  useEffect(() => {
    console.log('messages-changed');
    setMessages(messages);
  }, [messages]);

  return [onRequest];
};
输入message
/**
 * @name 输入栏
 */

import { Sender } from '@ant-design/x';
import React, { useState } from 'react';
import { useRequest } from '../../../hooks/useRequest';

const InputPrompt = (props) => {
  const [value, setValue] = useState<string>('');

  const [onRequest] = useRequest();

  // 提交message
  const onSubmit = async (message: string) => {
    onRequest(message);
    setValue("")
  };

  return (
    <div>
      <Sender value={value} onSubmit={onSubmit} onChange={(value) => setValue(value)} />
    </div>
  );
};

export default InputPrompt;
消费模型响应的messages数据
import { UserOutlined } from '@ant-design/icons';

const roles: GetProp<typeof Bubble.List, 'roles'> = {
  ai: {
    placement: 'start',
    avatar: { icon: <UserOutlined />, style: { background: '#fde3cf' } },
    typing: { step: 5, interval: 20 },
    style: {
      maxWidth: 600,
    },
  },
  local: {
    placement: 'end',
    avatar: { icon: <UserOutlined />, style: { background: '#87d068' } },
  },
};

// -------------------

const ChatBoard = () => {
    const {messages} = useStore || {}

    return (
        <Bubble.List
           style={{ width: '100%' }}
           roles={roles}
           items={messages.map(({ id, message, status }) => ({
               key: id,
               loading: status === 'loading',
               role: status === 'local' ? 'local' : 'ai',
               content: message,
           }))}
        />
    )
}

最终呈现

这个简单例子没有使用流式输出,因此有的回答比较长的话,最后渲染在页面上就比较慢,当然可以结合与AntdX内部组件和工具的api加以优化

89_1735221694.gif

文档参考

Ant Design X 官网:x.ant.design/docs/react/…

OpenAI API:platform.openai.com/docs/api-re…