龙空技术网

使用 Open AI 构建用于文本生成的 Strapi 自定义字段

豆豆妈超厉害 106

前言:

眼前姐妹们对“请求头添加自定义字段”都比较看重,咱们都需要学习一些“请求头添加自定义字段”的相关资讯。那么小编同时在网络上收集了一些关于“请求头添加自定义字段””的相关文章,希望朋友们能喜欢,你们快快来学习一下吧!

在本文中,我将教您如何使用 AI 在 Strapi 中生成内容。 Strapi 现在本身不允许您利用 AI 来创建内容,因此我们将使用自定义字段。 事实上,我们会自己从头开始构建一个。 本文的第二个目标是解释如何创建他们的 Strapi 自定义字段。

Strapi 自定义字段

Strapi 配备了几个字段。 从内容创建者的角度来看,这些字段描述了您将输入的内容类型。 它们的范围从富文本到 JSON 等等。 您可以在我们的用户文档中阅读有关字段的更多信息。

自定义字段,顾名思义,让我们在 Strapi 附带的默认字段之外定义字段,为我们提供了一种与各种第三方工具集成的很酷的方式。 今天对我们来说,这个工具将是 Open AI。

我们将建造什么

想象一下在文本字段中键入文本。 发布后,我们会在我们想要发送内容的任何地方显示输入文本。 同样,在 AI 领域,我们会分担大部分写作工作,让 AI 完成繁重的工作,而我们校对它是因为……计算机很笨。

在这一点上,我们对要构建的内容有一个非常可靠的想法。 如果您想在我们学习本教程时参考完成的项目详细信息,请参阅此处。

推文解释器

GitHub 回购

npm 包

创建自定义字段

让我们首先使用以下命令在我们的终端中创建一个全新的 Strapi 项目:

Npx create-strapi-app@latest plugin-dev —quickstart

一旦我们的项目启动并运行,创建一个管理员用户并登录到您的管理面板。 接下来,我们需要创建一个插件,因为自定义字段与 Strapi 的插件 API 一起工作。

在您的终端中,导航到您的项目路径并输入以下命令

npm run strapi generate

从选项列表中选择“插件”并将其命名为 ai-text-generation。 命名插件后,我们需要通过将其添加到 ./config/plugins.js 中的 Strapi 插件配置文件来启用它。

如果此文件尚不存在,您可以创建它。

    module.exports = {      // ...    'ai-text-generation': {      enabled: true,      resolve: './src/plugins/ai-text-generation'    },//...    }

当我们重新启动服务器时,我们应该会在 Strapi 管理面板中看到我们的插件。 我们将以监视模式重启服务器,这样我们就不必在每次更改管理代码时都重新构建管理应用程序。 为此,请在您的终端中输入以下命令:

Npm run develop –watch-admin

在我们可以尝试我们的自定义字段之前,我们必须做几件事。 首先,我们需要在我们的服务器上注册它。 转到 ./src/plugins/ai-text-generation/server/register.js 并粘贴以下代码。

'use strict';module.exports = ({ strapi }) => {  strapi.customFields.register({    name: 'text-ai',    plugin: 'ai-text-generation',    type: 'string',  });};

其次,我们需要在管理面板中注册我们的自定义字段。 为此,转到 ./src/plugins/ai-text-generation/admin/src/index.js 并粘贴以下代码:

import { prefixPluginTranslations } from '@strapi/helper-plugin';import pluginPkg from '../../package.json';import pluginId from './pluginId';import PluginIcon from './components/PluginIcon';const name = pluginPkg.strapi.name;export default {   register(app) {    app.customFields.register({      name: "text-ai",      pluginId: "ai-text-generation",       type: "string",       intlLabel: {        id: "ai-text-generation.text-ai.label",        defaultMessage: "Text AI",      },      intlDescription: {        id: "ai-text-generation.text-ai.description",        defaultMessage: "Let AI do your writing!",      },      icon: PluginIcon,      components: {        Input: async () => import(/* webpackChunkName: "input-component" */ "./components/Input"),      },      options: {      },    });  },  bootstrap(app) {},  async registerTrads({ locales }) {    const importedTrads = await Promise.all(      locales.map((locale) => {        return import(          /* webpackChunkName: "translation-[request]" */ `./translations/${locale}.json`        )          .then(({ default: data }) => {            return {              data: prefixPluginTranslations(data, pluginId),              locale,            };          })          .catch(() => {            return {              data: {},              locale,            };          });      })    );    return Promise.resolve(importedTrads);  },};

如果您的自定义字段之后中断,请不要担心。 在注册我们的自定义字段时,我们为自定义字段做了三件基本的事情:

我们定义 type: "string" - 它告诉我们自定义字段将保存什么类型的数据。 根据您正在构建的内容,您可能想要更改此设置。 对于我们今天的用例,我们将使用类型:“字符串”。

我们在 ./components/Input 中为我们的字段分配一个 Input 组件。 所有自定义字段都需要一个管理员用户可以在内容管理器中访问的输入组件。 我们可以根据需要使用 Strapi 设计系统自由设计输入组件,但必须返回我们存储在数据库中的单个值。 我们将在下一节中创建输入组件时看到更多内容。

我们用图标定义了一个插件图标:PluginIcon,这有助于我们识别内容类型生成器中的自定义字段。

创建输入组件

如上所述,所有自定义字段都需要一个输入组件。 在 ./src/plugins/ai-text-generation/admin/src/components/ 中,创建一个名为 Input 的文件夹。 在您的 Input 文件夹中,创建一个名为 index.js 的文件并将以下代码粘贴到其中:

import React, { useState } from 'react';import { useIntl } from 'react-intl';import { TextInput } from '@strapi/design-system/TextInput';import { Stack } from '@strapi/design-system/Stack';import { Button } from '@strapi/design-system/Button';import { Textarea } from '@strapi/design-system';import { auth } from '@strapi/helper-plugin'export default function Index({  name,  error,  description,  onChange,  value,  intlLabel,  attribute,}) {  const { formatMessage } = useIntl();  const [prompt, setPrompt] = useState('');  const [err, setErr] = useState('');   const generateText = async () => {    try {      const response = await fetch(`/ai-text-generation/generate-text`, {        method: 'POST',        headers: {          'Content-Type': 'application/json',          'Authorization': `Bearer ${auth.getToken()}`         },        body: JSON.stringify({          'model': 'text-davinci-001',          'prompt': `${prompt}`,          'temperature': 0.4,          'max_tokens': 64,          'top_p': 1,          'frequency_penalty': 0,          'presence_penalty': 0        })      });      if (!response.ok) {        throw new Error(`Error! status: ${response.status}`);      }      const result = await response.json();      const parsedResult = result.choices[0].text.replace(/(?:\r\n|\r|\n)/g, '');      onChange({ target: { name, value: parsedResult, type: attribute.type } })    } catch (err) {      setErr(err.message);    }  }  const clearGeneratedText = async () => {    onChange({ target: { name, value: '', type: attribute.type } })  }  return (    <Stack spacing={1}>      <TextInput        placeholder="Please write a prompt for content to generate"        label="Prompt"        name="Prompt"        onChange={(e) => setPrompt(e.target.value)}        value={prompt}      />      <Stack padding={4} spacing={2}>        <Textarea          placeholder="Generated text"          label="Content"          name="content"          onChange={(e) =>            onChange({              target: { name, value: e.target.value, type: attribute.type },            })          }        >          {value}        </Textarea>        <Stack horizontal spacing={4}>          <Button onClick={() => generateText()}>Generate</Button>          <Button onClick={() => clearGeneratedText()}>Clear</Button>        </Stack>      </Stack>    </Stack>  )}

这里发生了几件事。 我们将查看主要元素的作用以更好地理解它。

<TextInput /> :充当我们的提示输入; 我们使用 onChange() ‘watcher’ 在我们输入数据时更新提示状态的值。 然后我们将提示存储在一个名为 prompt 的变量中。 TextArea />:是我们用来存储我们生成的文本的值。 我们使用 <TextArea /> 来编辑生成的文本。 我们使用 onChange() 观察器的特殊实现,它允许我们传递一个具有多个值的对象,以便在该组件发生更改时进行更新。

我们还有两个按钮,所有的魔法都在这里发生。 一键调用 generateText() - 此函数使用 fetch 调用我们的后端服务,/ai-text-generation/generate-text 对 Open AI API 进行经过身份验证的调用(我们将在接下来创建它)。 为了验证这一点,我们使用来自 @strapi/helper-plugin 的 auth,它帮助我们向我们将使用 Admins 令牌创建的 Strapi 服务发出安全请求。

然后我们解析我们的结果并使用 onChange() 的特殊实现将解析后的响应作为内容传递,这些内容将通过 onChange({ target: { name, value: parsedResult, type: attribute.type } }) 添加到我们的数据库中 .

另一个按钮调用 clearGeneratedText() - 这个函数会清除 AI 生成的所有文本,以防我们想要重新开始。 此时,我们的应用程序应该看起来像这样。

在 Strapi 中构建自定义开放式 AI 路由

要访问 Open AI,我们需要提供一个 API KEY; 在管理员中拥有这个密钥会带来安全风险,为了解决这个问题,我们将创建一个自定义路由,当调用该路由时,它会对 Open AIs API 进行 API 调用并返回生成的文本,然后我们可以将其发送给管理员。

所以开始,在我们的 ./config/plugins.js 文件中添加一个配置对象 below enabled: true,你的配置文件应该如下所示:

// …'ai-text-generation': {      enabled: true,      config: {        apiToken: process.env.OPEN_AI_API_TOKEN,      },      resolve: './src/plugins/ai-text-generation'    },

现在,在 ./src/plugins/ai-text-generation/server/services 中创建一个名为 open-ai.js 的文件,并将以下代码粘贴到其中。

为了使代码正常工作,您还必须安装 axios,导航到您的插件根目录并键入 yarn add axios

'use strict';const axios = require('axios');module.exports = ({ strapi }) => ({  async generateText(prompt) {    try {      const response = await axios(        {          url: ';,          method: 'POST',          headers: {            'Content-Type': 'application/json',            'Authorization': `Bearer ${strapi.plugin('ai-text-generation').config('apiToken')}`          },          data: JSON.stringify({            'model': 'text-davinci-001',            'prompt': `${prompt}`,            'temperature': 0.4,            'max_tokens': 64,            'top_p': 1,            'frequency_penalty': 0,            'presence_penalty': 0          })        })      return response.data;    }    catch (err) {      console.log(err.response)    }  }});

这里我们定义了一个函数 generateText() ,它将提示作为参数。 然后,我们在请求 Open AI 时使用提示作为参数。

接下来,在同一个服务文件夹中,将以下代码粘贴到您的 index.js 文件中。

'use strict';const openAi = require('./open-ai');module.exports = {  openAi,};

在我们这样做之前,这段代码在 Strapi 中注册了一个我们从控制器调用的服务。 我们需要创建一个控制器。 在 ./src/plugins/ai-text-generation/server/controllers 中,创建一个名为 ai-controller.js 的文件并将以下代码粘贴到其中:

'use strict';module.exports = ({ strapi }) => ({  async generate(ctx) {    ctx.body = await strapi      .plugin('ai-text-generation')      .service('openAi')      .generateText(ctx.request.body.prompt);  },});

在这个文件中,我们调用我们在刚刚创建的服务中定义的 generateText() 函数并传递 ctx.request.body.prompt(来自我们的 POST 请求)。

在同一个文件夹中,我们需要将以下代码粘贴到我们的 index.js 文件中:

'use strict';const aiController = require('./ai-controller');module.exports = {  aiController,};

最后,我们必须创建一个路由来访问我们刚刚创建的控制器。 在 ./src/plugins/ai-text-generation/server/routes 我们需要粘贴以下代码:

module.exports = [  {    method: 'POST',    path: '/generate-text',    handler: 'aiController.generate',    config: {      policies: [],    },  },];

在这个文件中,我们定义了端点的行为方式。 使用此代码,我们在 /generate-text URI 上创建一个 POST 方法,并传递我们创建的 aiController 控制器来定义其行为。

在您首选的 API 客户端中,您现在可以向 localhost:1337/ai-text-generation/generate-text 发出请求,您应该会得到 AI 生成的文本作为响应。 请务必将您的提示添加为参数,并通过您的管理员 JWT 进行身份验证。

当我们输入提示并在我们的自定义字段中单击“生成”时,我们也应该得到响应。

发布到 npm

来自 Strapi 团队的 Maxime 写了一篇关于如何将你的插件发布到 npm 的精彩文章,如果你有任何问题,你可以参考我的 package.json 文件来了解如何构建你的插件。

您还可以将您的自定义字段提升到一个新的水平,并将其提交到官方 Strapi 市场。

希望您现在对如何构建自定义字段有了更好的了解,更好的是,您拥有一个使用 Open AI 为您生成内容的自定义字段。

标签: #请求头添加自定义字段