برنامه نویسی

با استفاده از Next.js و OpenAI Text Completion یک پرسش و پاسخ ساده با هوش مصنوعی بسازید

TL; DR

این اجرای API و اجرای فرانت اند در Github را بررسی کنید.

معرفی

OpenAI یک پلتفرم هوش مصنوعی قدرتمند است که به توسعه دهندگان اجازه می دهد تا برنامه های هوشمند ایجاد کنند. Next.js یک چارچوب محبوب React است که رندر سمت سرور و سایر ویژگی های پیشرفته را ارائه می دهد. در این وبلاگ، من یک برنامه پرسش و پاسخ ساده با استفاده از OpenAI و Next.js ایجاد خواهم کرد.

API تکمیل متن OpenAI از هوش مصنوعی برای تولید متنی شبیه به انسان بر اساس یک دستور داده شده استفاده می‌کند و آن را به ابزاری قدرتمند برای کارهایی مانند تولید نوشتن خلاقانه، ساخت ربات‌های گفتگو و ایجاد مدل‌های زبان تبدیل می‌کند. پردازش زبان پیشرفته و منابع داده‌ای گسترده آن را قادر می‌سازد تا متنی را تولید کند که بسیار شبیه به نوشته‌های انسان است و آن را به منبعی ارزشمند برای کسب‌وکارها و توسعه‌دهندگان تبدیل می‌کند.

پیش نیازها

قبل از شروع، باید درک اولیه ای از React و Next.js داشته باشید. همچنین باید یک کلید OpenAI API داشته باشید. اگر کلید OpenAI API ندارید، می توانید برای یک حساب کاربری رایگان در وب سایت آنها ثبت نام کنید.

من فقط از TypeScript و TailwindCSS برای این پروژه استفاده خواهم کرد، اما شما می توانید از جاوا اسکریپت و هر چارچوب CSS که ترجیح می دهید استفاده کنید.

راه اندازی پروژه

یک پروژه NextJS را راه اندازی کنید

شما می توانید یک پروژه را همانطور که در مستندات رسمی NextJS پیشنهاد شده است ایجاد کنید.

npx create-next-app@latest
# or
yarn create next-app
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اما اگر مانند من هستید که ترجیح می دهید TypeScript و Tailwind داشته باشید، می توانید به جای آن این دیگ بخار را شبیه سازی کنید.

npx degit codegino/nextjs-tailwind-slim-boilerplate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Backend API را ایجاد کنید

یک کلاینت OpenAI قابل استفاده مجدد ایجاد کنید

// src/libs/openai.ts
import {Configuration, OpenAIApi} from 'openai';
const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});

export const openai = new OpenAIApi(configuration);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هرگز کلید API خود را به مخزن خود متعهد نکنید. تو می توانی .env خارج از جعبه برای ذخیره کلید API خود.

یک کنترلر NextJS API ایجاد کنید

ما فقط برای رسیدگی به درخواست‌های POST به API نیاز داریم، بنابراین اگر روش درخواست POST نباشد، می‌توانیم خطا را برگردانیم.

ما می توانیم استفاده کنیم OpenAI مشتری برای ایجاد یک تکمیل با استفاده از createCompletion روش. ما می توانیم تنظیم کنیم prompt به سوال، و مدل به text-davinci-003. این temperature و max_tokens را می توان برای به دست آوردن نتایج متفاوت تنظیم کرد. ما می توانیم تنظیم کنیم n به 1 تا فقط یک نتیجه به دست آورید (همچنین برای صرفه جویی در پول).

// src/pages/api/completion.ts
import {NextApiRequest, NextApiResponse} from 'next';
import {openai} from '../../libs/openai';

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const {prompt} = req.body;

  if (req.method !== 'POST') {
    return res.status(400).json({error: 'Invalid request'});
  }

  const response = await openai.createCompletion({
    prompt,
    model: 'text-davinci-003',
    temperature: 0.6,
    max_tokens: 100,
    n: 1,
  });

  return res.status(200).json({
    data: response.data
  });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برنامه را با استفاده از yarn dev. نقطه پایانی جدید ایجاد شده را با استفاده از curl، Postman، Hoppscotch یا هر چیزی که ترجیح می دهید، آزمایش کنید.

ما باید داده های پاسخ را از OpenAI ببینیم.

با استفاده از Nextjs و OpenAI Text Completion یک پرسش

پاسخ API را به روز کنید

از آنجایی که ما به کل پاسخ OpenAI نیاز نداریم، می‌توانیم پاسخ را ساده کنیم تا فقط داده‌های مورد نیاز خود را برگردانیم. زیرا تعداد نتایج را تنها با استفاده از یک عدد تنظیم می کنیم n: 1، می‌توانیم پاسخ را ساده کنیم تا فقط انتخاب اول را استخراج کنیم.

همچنین، می‌توانیم خطوط جدید را از ابتدای پاسخ با استفاده از عبارت حذف کنیم replace روش.

// src/pages/api/completion.ts
import {NextApiRequest, NextApiResponse} from 'next';
import {openai} from '../../libs/openai';

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const {prompt} = req.body;

  if (req.method !== 'POST') {
    return res.status(400).json({error: 'Invalid request'});
  }

  const response = await openai.createCompletion({
    prompt,
    model: 'text-davinci-003',
    temperature: 0.6,
    max_tokens: 100,
    n: 1,
  });

-  return res.status(200).json({
-    data: response.data
-  });

+  const firstResponse = response.data.choices[0];

+  return res.status(200).json({
+    data: {
+      ...firstResponse,
+      text: firstResponse.text.replace(/^\n+/, ''),
+    },
+  });
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پاسخ باید برای فرانت اند ساده تر باشد
1680199686 520 با استفاده از Nextjs و OpenAI Text Completion یک پرسش

فرم سوال را ایجاد کنید

متغیرهایی برای ذخیره سوال و پاسخ ایجاد کنید

// src/pages/index.tsx
const [prompt, setPrompt] = useState('');
const [response, setResponse] = useState('');
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هنگامی که کاربر روی دکمه کلیک می کند یک کنترل کننده عملکرد ایجاد کنید

// src/pages/index.tsx
const handleSubmit = async e => {
  e.preventDefault();

  const res = await fetch('/api/completion', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({prompt: prompt.trim()}),
  }).then(res => res.json());

  setResponse(res.data.text);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

فرم را با یک ورودی و یک دکمه ارسال ایجاد کنید

// src/pages/index.tsx
return (
  <div className="max-w-md mx-auto pt-20">
    <h1 className="text-3xl font-bold text-center mb-6 bg-white">Ask Me Anything!</h1>
    <form onSubmit={handleSubmit} className="bg-white shadow-md rounded p-8">
      <div className="mb-4">
        <label htmlFor="prompt" className="block text-gray-700 text-sm font-bold mb-2">
          What do you want to know?
        </label>
        <input id="prompt" type="text" name="prompt" value={prompt} autoComplete="off"
          onChange={e => setPrompt(e.target.value)} placeholder="How to ask a question?"
          className="shadow border rounded w-full py-2 px-3 text-gray-700"
        />
      </div>
      <div className="flex gap-2">
        <button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4 rounded">
          Ask
        </button>
      </div>
    </form>
  </div>
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پاسخ را در صورت وجود ارائه دهید

// src/pages/index.tsx
return (
  <div className="max-w-md mx-auto pt-20">
    <h1 className="text-3xl font-bold text-center mb-6 bg-white">Ask Me Anything!</h1>
    <form onSubmit={handleSubmit} className="bg-white shadow-md rounded p-8">
      <div className="mb-4">
        <label htmlFor="prompt" className="block text-gray-700 text-sm font-bold mb-2">
          What do you want to know?
        </label>
        <input id="prompt" type="text" name="prompt" value={prompt} autoComplete="off"
          onChange={e => setPrompt(e.target.value)} placeholder="How to ask a question?"
          className="shadow border rounded w-full py-2 px-3 text-gray-700"
        />
      </div>
+      {response && (
+        <div className="mb-4">
+          <h2 className="font-bold">Response</h2>
+          <p className="pl-2 text-gray-700 whitespace-pre-line">{response}</p>
+        </div>
+      )}
      <div className="flex gap-2">
        <button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4 rounded">
          Ask
        </button>
      </div>
    </form>
  </div>
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

(اختیاری) سبک جهانی را به صفحه اضافه کنید

// src/styles/tailwind
body {
  background-image: radial-gradient(blue 0.1px, transparent 0.5px);
  background-size: 10px 10px;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کل جزء باید به این شکل باشد

// src/pages/index.tsx
import {useState} from 'react';

const IndexPage = () => {
  const [prompt, setPrompt] = useState('');
  const [response, setResponse] = useState('');

  const handleSubmit = async e => {
    e.preventDefault();

    const res = await fetch('/api/completion', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({prompt: prompt.trim()}),
    }).then(res => res.json());

    setResponse(res.data.text);
  };

  return (
    <div className="max-w-md mx-auto pt-20">
      <h1 className="text-3xl font-bold text-center mb-6 bg-white">Ask Me Anything!</h1>
      <form onSubmit={handleSubmit} className="bg-white shadow-md rounded p-8">
        <div className="mb-4">
          <label htmlFor="prompt" className="block text-gray-700 text-sm font-bold mb-2">
            What do you want to know?
          </label>
          <input id="prompt" type="text" name="prompt" value={prompt} autoComplete="off"
            onChange={e => setPrompt(e.target.value)} placeholder="How to ask a question?"
            className="shadow border rounded w-full py-2 px-3 text-gray-700"
          />
        </div>
        {response && (
          <div className="mb-4">
            <h2 className="font-bold">Response</h2>
            <p className="pl-2 text-gray-700 whitespace-pre-line">{response}</p>
          </div>
        )}
        <div className="flex gap-2">
          <button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4 rounded">
            Ask
          </button>
        </div>
      </form>
    </div>
  );
};

export default IndexPage;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا نشانه گذاری به نظر می رسد:
1680199686 482 با استفاده از Nextjs و OpenAI Text Completion یک پرسش

و در اینجا خروجی زمانی است که کاربر فرم را ارسال می کند:
1680199686 73 با استفاده از Nextjs و OpenAI Text Completion یک پرسش

نکته: می توانید از باد دم استفاده کنید whitespace-pre-line یا CSS وانیلی white-space: pre-line; سبک برای حفظ خطوط جدید در پاسخ.

1680199687 197 با استفاده از Nextjs و OpenAI Text Completion یک پرسش

کمی UX را بهبود ببخشید

می‌توانیم حالت بارگیری را به دکمه اضافه کنیم و فیلد ورودی را در حین پردازش درخواست غیرفعال کنیم. همچنین، به جای اسپم کردن Ask را فشار دهید، ما می توانیم a اضافه کنیم Try Again دکمه برای تنظیم مجدد فرم. به این ترتیب می توانیم برخی از اعتبارات ارزشمند OpenAI خود را ذخیره کنیم.

// src/pages/index.tsx
import {useState} from 'react';

const IndexPage = () => {
  const [response, setResponse] = useState('');
  const [prompt, setPrompt] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async e => {
    e.preventDefault();

    setLoading(true);
    setResponse('');

    const res = await fetch('/api/completion', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({prompt: prompt.trim()}),
    }).then(res => res.json());

    setResponse(res.data.text);
    setLoading(false);
  };

  const handleTryAgain = () => {
    setResponse('');
    setPrompt('');
  };

  return (
    <div className="max-w-md mx-auto pt-20">
      <h1 className="text-3xl font-bold text-center mb-6 bg-white">
        Ask Me Anything!
      </h1>
      <form onSubmit={handleSubmit} className="bg-white shadow-md rounded p-8">
        <div className="mb-4">
          <label
            className="block text-gray-700 text-sm font-bold mb-2"
            htmlFor="prompt"
          >
            What do you want to know?
          </label>
          <input id="prompt" type="text" name="prompt" value={prompt}
            onChange={e => setPrompt(e.target.value)} placeholder="How to ask a question?"
            autoComplete="off" disabled={!!response || loading}
            className="shadow border rounded w-full py-2 px-3 text-gray-700"
          />
        </div>
        {response && (
          <div className="mb-4">
            <h2 className="font-bold">Response</h2>
            <p className="pl-2 text-gray-700 whitespace-pre-line">{response}</p>
          </div>
        )}
        <div className="flex gap-2">
          {response ? (
            <button
              onClick={handleTryAgain}
              className="bg-blue-500 text-white font-bold py-2 px-4 rounded"
            >
              Try again
            </button>
          ) : (
            <button
              type="submit"
              disabled={!!loading || prompt.length < 5}
              className="bg-blue-500 text-white font-bold py-2 px-4 rounded disabled:opacity-50"
            >
              {loading ? 'Thinking...' : 'Ask'}
            </button>
          )}
        </div>
      </form>
    </div>
  );
};

export default IndexPage;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و در اینجا یک تجربه کمی بهتر است:
با استفاده از Nextjs و OpenAI Text Completion یک پرسش

کد منبع

کد منبع این پروژه در GitHub موجود است

نتیجه

در این پست وبلاگ، من نشان دادم که چقدر ساده است که از تکمیل متن OpenAI با Next.js استفاده کنید. ما نحوه ایجاد یک مسیر API را در Next.js، نحوه ایجاد یک درخواست API به OpenAI API با استفاده از openai کتابخانه، و یک فرم سمت کلاینت برای پذیرش درخواست‌ها و نمایش پاسخ از API ایجاد کنید. و این سه مرحله تمام چیزی است که ما برای ایجاد یک برنامه عالی تر نیاز داریم.

بعد چه است

  • تولید تصویر با OpenAI
  • پاسخ ها را در پایگاه داده ذخیره کنید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا