IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    使用CloudFlare Workers 创建自己的AI程序,基于meta llama-2-7b大语言模型

    怕刺发表于 2023-10-16 03:42:00
    love 0

    CloudFlare近期推出了无服务器 GPU 驱动推理,可以使用多个AI模型,包括大语言模型、翻译、图像识别、语音转换等。其中的大语言模型,使用了meta的llama-2-7b-chat-int8模型。本人一直使用OpenAI的ChatGPT,想试一下自己部署,所以按照文档,整理出如下部署教程。

    提醒:CloudFlare Workers AI 仍然处于测试阶段,每分钟限制50个问题,每天最大提问为100000个;输入限制在768tokens,输出限制在256tokens。由于使用的是7b模型,表现并没有免费的ChatGPT 3.5好。

    账号准备工作

    注册一个 CloudFlare 的账号,并启用 workers and pages 功能。如果没有账号,可以在 https://dash.cloudflare.com/sign-up/workers-and-pages 处注册。

    配置开发环境

    CloudFlare 官方提供了一个名为 Wrangler 的开发工具(基于 Node.js),所以我们需要安装 Node.js 和 npm 包管理工具。

    安装 Node.js 和 npm

    以 Windows 系统为例,在 Node.js 的官网 https://nodejs.org/ 下载并安装,建议选择 LST 版本。Windows 版本的安装包自带 npm ,所以不需要额外手动安装 npm 包。打开终端/Windows terminal (下文命令行操作,默认在终端/Windows terminal中),输入以下命令确认已经正确安装:

    node -v # 查询 node.js 版本
    v18.18.1 # 返回已安装的版本号
    npm -v # 查询 npm 版本
    9.8.1 # 返回已安装的版本号

    安装Git

    点击此处下载安装Git https://git-scm.com/download/win ,用于后续管理程序。

    安装 Wrangler

    新建一个文件夹,比如D:\Program\nodejs\cf_ai,下面的所有终端/Windows terminal 操作,都默认此文件夹路径中进行。

    Wrangler 可以使用 npm 直接安装:

    npm install wrangler --save-dev

    随后依旧是检查是否正确安装:

    npx wrangler --version # 查询 wrangler 版本
    wrangler 3.13.1 # 返回已安装的版本号,如果报错找不到,说明没有在默认文件夹中打开终端

    使用 Wrangler 登陆 CloudFlare 账号:

    npx wrangler login

    随后会给出一个URL地址,复制到浏览器中国打开,并同意登陆即可。

    创建 Workers AI 项目

    创建工作目录

    依旧在D:\Program\nodejs\cf_ai中进行下面的所有终端/Windows terminal 操作。

    npm create cloudflare@latest

    随后,在弹出来的选项中,选择Hello World项目,项目名称为hello-ai,TypeScript和Git都选择yes,Deploying选择no

    此时,你将在D:\Program\nodejs\cf_ai文件夹中看到一个名为hello-ai的文件夹,进入此文件夹,你将发现wrangler.toml文件和在src文件夹中的index.ts文件。前者是用以连接Workers AI的配置文件,后者是主程序。

    连接到Workers AI和安装必要的库

    使用任意编辑器打开wrangler.toml这个文件夹,在最末尾加入以下内容即可:

    [ai]
    binding = "AI"

    在D:\Program\nodejs\cf_ai\hello-ai中进行下面的所有终端/Windows terminal 操作,注意路径是hello-ai文件夹!

    npm install --save @cloudflare/ai

    开发Workers AI

    本地开发与测试

    在D:\Program\nodejs\cf_ai\hello-ai中进行下面的所有终端/Windows terminal 操作,注意路径是hello-ai文件夹!

    打开index.ts文件,输入以下内容,下列promot中的内容即是向AI的提问。

    import { Ai } from '@cloudflare/ai'
    
    export interface Env {
      // If you set another name in wrangler.toml as the value for 'binding',
      // replace "AI" with the variable name you defined.
      AI: any;
    }
    
    export default {
      async fetch(request: Request, env: Env) {
        const ai = new Ai(env.AI);
    
        const response = await ai.run('@cf/meta/llama-2-7b-chat-int8', {
            prompt: "What is the origin of the phrase Hello, World"
          }
        );
    
        return new Response(JSON.stringify(response));
      },
    };

    在终端中输入以下内容,测试程序与环境是否正常工作:

    npx wrangler dev --remote

    随后,终端中会出现一系列以8787端口结尾的URL,在浏览器中打开127.0.0.1:8787,将出现类似以下内容:

    "response": "Hello, World first appeared in 1974 at Bell Labs when Brian Kernighan included it in the C programming language example. It became widely used as a basic test program due to simplicity and clarity. It represents an inviting greeting from a program to the world."

    说明本地测试完成,程序正常工作,AI给出正确的回答。

    开发与远程部署

    在D:\Program\nodejs\cf_ai\hello-ai中进行下面的所有终端/Windows terminal 操作,注意路径是hello-ai文件夹!

    打开index.ts文件,删除旧内容,输入以下内容,下列promot中有两个用户,system为系统用户(告诉AI行为规范),user内容是实际用户(向AI提问)。

    import { Ai } from '@cloudflare/ai';
    import { marked } from 'marked';
    
    export interface Env {
      AI: any;
    }
    
    export default {
      async fetch(request: Request, env: Env) {
        const ai = new Ai(env.AI);
        let isRequestSent = false; // 用于跟踪请求状态
    
        if (request.method === 'POST') {
          const formData = await request.formData();
          const userQuestion = formData.get('question') || '';
    
          const messages = [
            { role: 'system', content: 'You are a friendly assistant' },
            { role: 'user', content: userQuestion }
          ];
          const response = await ai.run('@cf/meta/llama-2-7b-chat-int8', { messages });
    
          const htmlResponse = marked.parse(response.response);
    
          isRequestSent = true; // 设置请求状态为已发送
    
          return new Response(htmlResponse, { headers: { 'Content-Type': 'text/html' } });
        }
    
        return new Response(`
          <!DOCTYPE html>
          <html>
          <head>
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <style>
              h1 {
                text-align: center;
              }
              form {
                width: 80%;
                margin: 0 auto;
              }
              label {
                display: block;
                text-align: center;
              }
              input[type="text"] {
                width: 100%;
                padding: 10px;
                margin: 8px 0;
                box-sizing: border-box;
              }
              input[type="submit"] {
                width: 100%;
                padding: 10px;
                margin: 8px 0;
                box-sizing: border-box;
                background-color: ${isRequestSent ? 'lightcyan' : 'initial'}; // 根据请求状态设置颜色
              }
              #response {
                width: 80%;
                margin: 0 auto;
              }
            </style>
          </head>
          <body>
            <h1>Llama-2-7b LLM Answerer</h1>
            <form action="" method="POST" id="question-form"> <!-- 添加 id 属性 -->
              <label for="question">Input a Question:</label>
              <input type="text" id="question" name="question">
              <input type="submit" value="Submit" id="submit-button"> <!-- 添加 id 属性 -->
            </form>
            <div id="response"></div>
            <script>
              document.querySelector('#question-form').addEventListener('submit', async (e) => {
                e.preventDefault();
                const formData = new FormData(e.target);
                const submitButton = document.getElementById('submit-button');
                
                submitButton.style.backgroundColor = 'lightcyan';
                submitButton.disabled = true;
    
                const response = await fetch('', { method: 'POST', body: formData });
                const data = await response.text();
                document.getElementById('response').innerHTML = data;
    
                // 恢复按钮状态
                submitButton.style.backgroundColor = 'initial';
                submitButton.disabled = false;
              });
            </script>
          </body>
          </html>
        `, { headers: { 'Content-Type': 'text/html' } });
      },
    };

    在终端中输入以下内容,远程部署程序到CloudFlare Pages中:

    npx wrangler login # 登陆账号
    npx wrangler deploy # 部署程序

    随后,终端中会出现:

    hello-ai.<sub_domain>.workers.dev

    这是你的AI程序的网址,其中<sub-domain>是可自定义的用户域名,效果图如下:

    1.jpg

    输入问题后,点击提交(submit)按钮,后台(serverless GPU)将会使用llama-2-7b模型回答问题。在收到回复之前,提交按钮将处于青色,并无法再次按下。回答的效果如下(提问:简要回答VPS是说明):

    2.jpg



沪ICP备19023445号-2号
友情链接