Содержание
Искусственный интеллект (ИИ) в последнее время набирает обороты, а ChatGPT произвел революцию в Интернете благодаря функции завершения чата.
С его помощью можно сделать многое: составить письмо или другой документ, ответить на вопросы по набору документов, создать разговорного агента, придать программному обеспечению естественный языковой интерфейс, обучать различным предметам, переводить языки и т.д.
В этой статье мы расскажем об основах создания чат-приложения с использованием функции завершения чата, чтобы каждый программист мог легко с ней справиться. Это не так сложно, как кажется на первый взгляд. Вы убедитесь в этом, следуя данному руководству.
Вы узнаете следующее:
- Как создать чат-приложение с CLI, используя только Node.js.
- Как создать чат-приложение, используя только React.
- Как объединить React и Node.js для создания лучшего программного обеспечения с искусственным интеллектом для чатов.
В данном учебном пособии будет использована модель gpt-3.5-turbo .
Предварительные условия
Этот учебник требует базовых знаний JavaScript, CSS, React и Node.js.
Также необходима учетная запись на платформе OpenAI, где размещен chatGPT. Она бесплатна, и вы можете создать ее здесь.
Как создать приложение искусственного интеллекта для чата с помощью CLI на Node.js
В этом разделе мы рассмотрим создание чат-приложения, которое будет работать только в терминале, с использованием Node.js.
Начните с создания каталога для проекта:
mkdir nodejs-chatgpt-tutorial
Перейдите в папку:
cd nodejs-chatgpt-tutorial
Инициализация проекта:
npm init -y
В результате будет создан файл package.json для хранения деталей проекта
Добавьте в файл следующую строку кода:
"type": "module"
Это позволит использовать оператор импорта модулей ES6.
Установите OpenAI с помощью приведенной ниже команды:
npm i openai
Создайте файл, в котором будет находиться весь код. Назовите его index.js :
touch index.js
Импортируйте Configuration и OpenAIApi из модуля OpenAI и readline из модуля readline:
import { Configuration, OpenAIApi } from 'openai';
import readline from 'readline';
Постройте конфигурацию OpenAI следующим образом:
const configuration = new Configuration({
organization: 'org-0nmrFWw6wSm6xIJXSbx4FpTw',
apiKey: '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',
});
Этот код создает новый экземпляр объекта Configuration . Внутри него вы введете значения для ваших organization и apiKey . Данные о вашей организации можно найти в настройках, а информацию о вашем apiKey - в API-ключах. Если у вас нет существующего ключа API, вы можете его создать.
Введите следующий код после конфигурации для создания нового экземпляра OpenAI API:
const openai = new OpenAIApi(configuration);
Вы будете использовать его на протяжении всего проекта.
Введите приведенный ниже код для проверки функции createChatCompletion :
openai
.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: 'Hello' }],
})
.then((res) => {
console.log(res.data.choices[0].message.content);
})
.catch((e) => {
console.log(e);
});
Этот код вызывает функцию createChatCompletion , которая запускает конечную точку ( https://api.openai.com/v1/chat/completions ). Функция принимает объект аргументов (используемый model chatGPT и массив messages между пользователем и ИИ. В следующем разделе мы рассмотрим, как использовать массив messages для ведения истории чата и улучшения приложения).
Каждое сообщение представляет собой объект, содержащий значение role (то есть кто отправил сообщение. Это значение может быть assistant , если оно исходит от ИИ, или user , если сообщение исходит от человека) и content (отправленная информация).
Наконец, код печатает ответ ( res.data.choices[0].message.content ) от ИИ. Запустите файл в терминале с помощью этой команды:
node index
Это приведет к получению ответа от искусственного интеллекта через несколько секунд.
И это все, что нужно для создания чатбота!
Однако было бы полезно сделать приложение более интерактивным, запрашивая ввод от пользователя, а не жестко кодируя содержимое сообщения в коде. В этом нам поможет модуль readline.
Чтобы сделать его интерактивным, удалите последний набранный код и добавьте следующий:
const userInterface = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
Этот код создает в терминале пользовательский интерфейс, позволяющий пользователям вводить свои вопросы.
Затем предложите пользователю ввести сообщение, используя приведенный ниже код:
userInterface.prompt();
Наконец, введите следующий код:
userInterface.on('line', async (input) => {
await openai
.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: input }],
})
.then((res) => {
console.log(res.data.choices[0].message.content);
userInterface.prompt();
})
.catch((e) => {
console.log(e);
});
});
В приведенном выше коде,
- Когда пользователь набирает текст и нажимает Enter , в приведенном выше коде срабатывает функция обратного вызова.
- В качестве input передается все, что было набрано пользователем.
- В качестве input теперь используется content .
- После вывода на экран ответа ИИ пользователю предлагается ввести еще одно сообщение в блоке then .
Весь код можно посмотреть на GitHub.
Запустите файл и проведите беседу с ИИ. Он будет выглядеть так, как показано на рисунке ниже:

Отлично! Это интерактивный CLI-чат.
Это полезно нескольким людям (например, инженерам), но имеет хорошую безопасность, поскольку находится на стороне сервера.
Но как быть с теми, кто не понимает, как использовать CLI-приложение? Им нужно что-то более простое в использовании, с лучшим пользовательским интерфейсом (UI) и пользовательским опытом (UX). Следующий раздел посвящен созданию такого приложения с использованием React.
Как создать приложение для чата с помощью React
Этот раздел призван помочь фронтенд-разработчикам освоить API ChatGPT для создания чат-приложения и построить более совершенный пользовательский интерфейс, чтобы обеспечить пользователям лучший опыт. Полученные здесь знания можно применить к другим фронтенд-фреймворкам или библиотекам.
Первое, что необходимо сделать, - настроить базовый котел React. Для этого я буду использовать Vite. Vite можно использовать для построения любого современного фронтенд-проекта на JavaScript. Используйте команду, приведенную ниже:
npm create vite@latest
Эта команда предложит вам создать имя и папку для проекта, а также выбрать фреймворк или библиотеку (в данном учебном пособии используется React). После этого нужно перейти в папку и выполнить следующую команду:
npm install
npm run dev
Эти команды установят необходимые зависимости и запустят локальный сервер на порту 5173
Затем установите OpenAI с помощью приведенной ниже команды:
npm i openai
Этот модуль предоставляет доступ ко всему, что необходимо для создания приложения чата.
Теперь мы готовы приступить к написанию кода!
Перейдите в файл src/App.jsx и удалите все его содержимое. Затем добавьте следующие операторы импорта:
import { useState } from 'react';
import { Configuration, OpenAIApi } from 'openai';
Приведенный выше код импортирует Configuration для установки значений конфигурации и OpenAIApi для предоставления доступа к функциям завершения чата.
После этого постройте конфигурацию следующим образом:
const configuration = new Configuration({
organization: 'org-0nmrFWw6wSm6xIJXSbx4FpTw',
apiKey: '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',
});
Этот код создает новый экземпляр объекта Configuration . Внутри него вы вводите значения для своих organization и apiKey . Сведения о вашей организации можно найти в настройках, а информацию о вашем apiKey - в API-ключах. Если у вас нет существующего ключа API, вы можете его создать.
Введите следующий код после конфигурации для создания нового экземпляра OpenAI API:
const openai = new OpenAIApi(configuration);
Мы будем использовать его на протяжении всего проекта.
Создание и экспорт функции по умолчанию:
function App() {
return (
<main>
<h1>Chat AI Tutorial</h1>
<main/>
);
}
export default App;
В этой функции будет находиться остальной код.
Перед оператором return установите следующие состояния:
const [message, setMessage] = useState('');
const [chats, setChats] = useState([]);
const [isTyping, setIsTyping] = useState(false);
- В message будет храниться информация, передаваемая из приложения в ИИ.
- В массиве chats будут храниться все сообщения, отправленные обеими сторонами (пользователем и ИИ).
- Переменная isTyping будет сообщать пользователю, набирает ли бот текст или нет.
Введите следующие строки кода под тегом h1
<div className={isTyping ? '' : 'hide'}>
<i>{isTyping ? 'Typing' : ''}</i>
</div>
Приведенный выше код будет отображать Typing всякий раз, когда пользователь ожидает ответа от ИИ.
Создайте форму, в которой пользователь может ввести сообщение, добавив в элемент main приведенный ниже код:
<form action="" onSubmit={(e) => chat(e, message)}>
<input
type="text"
name="message"
value={message}
placeholder="Type a message here and hit Enter..."
onChange={(e) => setMessage(e.target.value)}
/>
</form>
Этот код создает форму с одним входом. Всякий раз, когда форма отправляется нажатием клавиши Enter , срабатывает функция chat .
Функция chat будет принимать два (2) аргумента ( e и message ) следующим образом:
const chat = async (e, message) => {};
Введите в функцию следующие строки:
e.preventDefault();
if (!message) return;
setIsTyping(true);
Приведенный выше код не позволяет form перезагрузить веб-страницу, проверяет, было ли набрано сообщение перед отправкой, и устанавливает isTyping в true , чтобы указать, что приложение начало работать с введенными данными.
В ChatGPT существует формат, в котором должны быть сообщения. Он принимает следующий вид:
{role: user | assistant, content: message to be sent
Каждое сообщение ( content ) должно показывать, кто его отправил. Роль assistant указывается, если сообщение отправлено искусственным интеллектом, но user - если человеком. Поэтому, прежде чем отправить сообщение, не забудьте правильно его оформить и добавить в массив ( chats ) следующим образом:
let msgs = chats;
msgs.push({ role: 'user', content: message });
setChats(msgs);
setMessage('');
Последняя строка очищает ввод, чтобы пользователь мог набрать еще одну заметку.
Теперь вызовем конечную точку createChatCompletion , вызвав функцию createChatCompletion с помощью приведенного ниже кода:
await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [
{
role: 'system',
content: 'You are a EbereGPT. You can help with graphic design tasks',
},
...chats,
],
});
Функция createChatCompletion принимает не менее двух (2) аргументов ( model и messages ):
- Модель определяет используемую версию chatGPT.
- Сообщения - это список всех сообщений между пользователем и искусственным интеллектом на данный момент, а также системное сообщение, которое дает ИИ представление о том, какую помощь он может оказать.
{
"role": "system",
"content": "You are a EbereGPT. You can help with graphic design tasks"
}
Вы можете менять содержание по своему усмотрению.
В массиве messages не обязательно должно быть более одного объекта. Это может быть просто одно сообщение.
Но если это массив, то в нем содержится история сообщений, на которую ИИ может опираться, чтобы в будущем давать более точные ответы, и это заставляет пользователя набирать меньше текста, поскольку, возможно, нет необходимости постоянно давать слишком подробные описания.
Функция createChatCompletion возвращает обещание. Поэтому для получения ответа используйте блок then…catch… .
.then((res) => {
msgs.push(res.data.choices[0].message);
setChats(msgs);
setIsTyping(false);
})
.catch((error) => {
console.log(error);
});
Этот код добавляет сообщение, полученное от ИИ, в массив chats и устанавливает значение isTyping в false, указывая на то, что ИИ закончил отвечать.
Теперь при отправке сообщения вы должны получать обратную связь ( Typing ):

Пришло время отобразить историю чата для просмотра пользователем.
Введите следующий код непосредственно под тегом h1 :
<section>
{chats && chats.length
? chats.map((chat, index) => (
<p key={index} className={chat.role === 'user' ? 'user_msg' : ''}>
<span>
<b>{chat.role.toUpperCase()}</b>
</span>
<span>:</span>
<span>{chat.content}</span>
))
: ''}
</section>
Приведенный выше код перебирает все chats и последовательно выводит их пользователю. Он выводит role в верхнем регистре и content сообщения рядом.
Вот как должен выглядеть вывод:

Это выглядит круто!
Но если добавить некоторые элементы оформления, то приложение приобретет привлекательный вид, как в WhatsApp или Messenger.
Замените содержимое файла src/index.css на следующее:
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
text-align: center;
position: sticky;
top: 0;
background-color: #242424;
}
main {
max-width: 500px;
margin: auto;
}
p {
background-color: darkslategray;
max-width: 70%;
padding: 15px;
border-radius: 50px;
}
p span {
margin: 5px;
}
p span:first-child {
margin-right: 0;
}
.user_msg {
text-align: right;
margin-left: 30%;
display: flex;
flex-direction: row-reverse;
}
.hide {
visibility: hidden;
display: none;
}
form {
text-align: center;
position: sticky;
bottom: 0;
}
input {
width: 100%;
height: 40px;
border: none;
padding: 10px;
font-size: 1.2rem;
}
input:focus {
outline: none;
}
И удалите все стили из файла src/App.css .
Полный код можно найти на GitHub.
Теперь приложение должно иметь новый вид:

На этом создание чатбота с помощью React и ChatGPT завершено. Это не так сложно, как кажется.
Но фронтенд-приложения, подобные этому, лучше использовать для демонстрации, а не для производства. Проблема создания приложения таким образом заключается в том, что фронтенд подвергает API-ключ кибернетическим атакам.
Для решения этой проблемы целесообразно сохранить API Key и Organisation Id в безопасном месте в облаке и ссылаться на них, либо создать бэкенд для своего приложения с более высокой степенью защиты.
В следующем разделе будет рассмотрена эта проблема.
Как объединить React и Node.js для создания Fullstack-программы искусственного интеллекта для чата
В этом разделе мы объединим все возможности предыдущих разделов, чтобы создать более безопасное приложение с улучшенным пользовательским интерфейсом и UX.
Мы улучшим раздел Node, используя сервер для выставления конечной точки для потребления фронтендом и упростим взаимодействие фронтенда с бэкендом вместо прямого обращения к OpenAI.
Как настроить проект
В этой части будут созданы необходимые для проекта папки и файлы.
Создайте каталог проекта:
mkdir react-node-chatgpt-tutorial
Перейдите в папку:
cd react-node-chatgpt-tutorial
Установите React с помощью Vite и назовите папку frontend . Используйте эту команду:
npm create vite@latest
После этого перейдите в папку и выполните следующую команду:
npm install
npm run dev
Эти команды установят необходимые зависимости и запустят локальный сервер на порту 5173 .
Создайте папку backend:
mkdir backend
Теперь перейдите в папку backend и инициализируйте проект с помощью этой команды:
npm init -y
При этом будет создан файл package.json для хранения деталей проекта.
Добавьте в файл следующую строку кода:
"type": "module"
Это позволит использовать оператор импорта модулей ES6.
Установите OpenAI и другие зависимости с помощью приведенной ниже команды:
npm i openai body-parser cors express
Создайте файл, в котором будет находиться весь код. Назовите его index.js :
touch index.js
На этом настройка проекта завершена. Теперь есть две папки ( frontend и backend ).
Как построить сервер
В этой части мы рассмотрим создание локального сервера для прослушивания порта 8000 .
Первое, что нужно сделать, - импортировать необходимые модули следующим образом:
import { Configuration, OpenAIApi } from 'openai';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
Далее установите express , port для прослушивания, body-parser для приема входных данных и cors для свободного обмена данными между фронтендом и бэкендом. Используйте приведенный ниже код:
const app = express();
const port = 8000;
app.use(bodyParser.json());
app.use(cors());
Наконец, введите следующий код:
app.listen(port, () => {
console.log(`listening on port ${port}`);
});
На этом настройка сервера завершена.
При выполнении команды index.js должен быть получен следующий результат:
listening on port 8000
Как создать конечную точку
В этой части мы создадим конечную точку, которая будет принимать сообщения от фронтенда, используя тело запроса, и возвращать ответ вызывающей стороне.
Начните с установки параметров конфигурации, как мы это делали в предыдущих разделах:
const configuration = new Configuration({
organization: 'org-0nmrFWw6wSm6xIJXSbx4FpTw',
apiKey: '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',
});
const openai = new OpenAIApi(configuration);
Далее создайте асинхронный POST-маршрут, используя приведенный ниже код:
app.post('/', async (request, response) => {});
Вызов этой конечной точки будет осуществляться с помощью http://localhost:8000/
В функции обратного вызова введите приведенный ниже код для получения входных данных chats из тела запроса ( request.body ):
const { chats } = request.body;
Теперь вызовите конечную точку createChatCompletion , как мы это делали в разделе React:
const result = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [
{
role: 'system',
content: 'You are a EbereGPT. You can help with graphic design tasks',
},
...chats,
],
});
Разница заключается в том, что вместо использования блока then…catch… мы присвоили его переменной ( result ) и вернули ответ с помощью response.json() , как показано в следующем коде:
response.json({
output: result.data.choices[0].message,
});
Код этой части можно найти на GitHub.
Вот вывод при тестировании на Postman:

На этом часть кода, посвященная бэкенду, завершена. В следующей части будет выполнено подключение фронтенда к бэкенду с помощью только что созданной конечной точки ( http://localhost:8000/ ).
Как подключиться к бэкенду из фронтенда.
В этой части мы переходим на фронтенд, где создадим форму. Форма будет отправлять сообщение на бэкенд через конечную точку API и получать ответ через ту же среду.
Перейдите в файл frontend/src/App.jsx и введите следующий код:
import { useState } from 'react';
function App() {
const [message, setMessage] = useState('');
const [chats, setChats] = useState([]);
const [isTyping, setIsTyping] = useState(false);
const chat = async (e, message) => {
e.preventDefault();
if (!message) return;
setIsTyping(true);
let msgs = chats;
msgs.push({ role: 'user', content: message });
setChats(msgs);
setMessage('');
alert(message);
};
return (
<main>
<h1>FullStack Chat AI Tutorial</h1>
<section>
{chats && chats.length
? chats.map((chat, index) => (
<p key={index} className={chat.role === 'user' ? 'user_msg' : ''}>
<span>
<b>{chat.role.toUpperCase()}</b>
</span>
<span>:</span>
<span>{chat.content}</span>
))
: ''}
</section>
<div className={isTyping ? '' : 'hide'}>
<i>{isTyping ? 'Typing' : ''}</i>
</div>
<form action="" onSubmit={(e) => chat(e, message)}>
<input
type="text"
name="message"
value={message}
placeholder="Type a message here and hit Enter..."
onChange={(e) => setMessage(e.target.value)}
/>
</form>
</main>
);
}
export default App;
Этот код аналогичен коду из предыдущего раздела. Но мы удалили конфигурации OpenAI, так как в этом разделе они нам больше не понадобятся.
На данный момент при отправке формы на экран выводится предупреждение. Через некоторое время это изменится.
В функции чата избавьтесь от сообщения alert и наберите следующее:
fetch('http://localhost:8000/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chats,
}),
})
.then((response) => response.json())
.then((data) => {
msgs.push(data.output);
setChats(msgs);
setIsTyping(false);
})
.catch((error) => {
console.log(error);
});
Приведенный выше код вызывает созданную нами конечную точку и передает ей для обработки массив chats . Затем он возвращает ответ, который добавляется в массив chats и отображается в пользовательском интерфейсе.
Ниже показано, как выглядит пользовательский интерфейс на данный момент:

Пользовательский интерфейс может выглядеть лучше, если добавить в файл frontend/src/index.css следующие стили:
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
html,
body {
scroll-behavior: smooth;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
text-align: center;
position: sticky;
top: 0;
background-color: #242424;
}
main {
max-width: 800px;
margin: auto;
}
p {
background-color: darkslategray;
max-width: 70%;
padding: 15px;
border-radius: 50px;
}
p span {
margin: 5px;
}
p span:first-child {
margin-right: 0;
}
.user_msg {
text-align: right;
margin-left: 30%;
display: flex;
flex-direction: row-reverse;
}
.hide {
visibility: hidden;
display: none;
}
form {
text-align: center;
position: sticky;
bottom: 0;
}
input {
width: 100%;
height: 40px;
border: none;
padding: 10px;
font-size: 1.2rem;
background-color: rgb(28, 23, 23);
}
input:focus {
outline: none;
}
И удалите все стили из файла frontend/src/App.css .
Код для этой части находится на GitHub.
А вот и конечный результат:

Поздравляю с завершением проекта!
Работа над чатботом с полным стеком была более трудоемкой, но она помогла нам разделить проблемы, создать более безопасное и привлекательное приложение и предложить пользователям лучший опыт. Так что это стоило затраченных усилий.
Код для этой секции можно найти на GitHub.
Заключение
Этот учебник, надеюсь, показал вам, что любой человек, обладающий базовыми знаниями в области программирования, может создавать программное обеспечение на основе искусственного интеллекта. Вы узнали, как создать чатбота с помощью React и Nodejs, а также обсудили плюсы и минусы каждой технологии.
В итоге мы создали решение, которое было функциональным, безопасным и визуально привлекательным.
После прочтения этого руководства вы сможете изучить такие функциональные возможности AI, как работа с изображениями и взаимодействие со звуком. Потратьте время на изучение документации и посмотрите, как можно расширить то, что мы здесь рассмотрели.