Του Hassan Djirdeh (@djirdehh)

Αυτό το άρθρο είναι το πρώτο άρθρο και σεμινάριο που αποστέλλεται στο ενημερωτικό δελτίο frontendfresh.com. Εγγραφείτε στοΕνημερωτικό δελτίο Front-end Freshγια να λαμβάνετε συμβουλές μηχανικής, σεμινάρια και έργα στο front-end που αποστέλλονται στα εισερχόμενά σας σε εβδομαδιαία βάση!

Αυτό το άρθρο είναι το πρώτο email μιας σειράς εκμάθησης 3 έως 4 μερών, όπου θα εργαστούμε για να δημιουργήσουμε το δικό μας προσαρμοσμένο chatbot Q&A. Αυτό θα το πετύχουμε με:

  • Δημιουργία διακομιστή Node/Express για αλληλεπίδραση με τα API του OpenAI (σημερινό email).
  • Χρησιμοποιώντας το React για τη δημιουργία της διεπαφής χρήστη του chatbot Q&A.
  • Τέλος, στη συνέχεια, θα διερευνήσουμε πώς να βελτιστοποιήσουμε την εφαρμογή μας, ώστε το chatbot Q&A να επιστρέφει προσαρμοσμένες πληροφορίες.

Η τελική μας εφαρμογή θα μοιάζει με το εξής:

Σήμερα, θα επικεντρωθούμε αποκλειστικά στη δημιουργία ενός διακομιστή Node.js όπου μπορούμε να αλληλεπιδράσουμε απευθείας με τα API του OpenAI. Αυτός είναι ένας πρόδρομος για τη ρύθμιση της εφαρμογής διεπαφής μας, η οποία στη συνέχεια θα αλληλεπιδρά με το τοπικό API που θα δημιουργήσουμε.

Εάν θέλετε να ακολουθήσετε, θα χρειαστείτε το Node και το NPM εγκατεστημένο στον υπολογιστή σας και ένα κλειδί OpenAI API (θα σας δείξουμε πώς να το αποκτήσετε στην επόμενη ενότητα).

Δημιουργία κλειδιού OpenAI API

Ακολουθήστε αυτά τα βήματα για να δημιουργήσετε ένα κλειδί API με το OpenAI:

  • Εγγραφείτε για έναν λογαριασμό μεταβαίνοντας στον ιστότοπο του OpenAI (https://platform.openai.com/).
  • Μόλις δημιουργηθεί ένας λογαριασμός, επισκεφτείτε τη σελίδα κλειδιών API στη διεύθυνση https://platform.openai.com/account/api-keys.
  • Δημιουργήστε ένα νέο κλειδί κάνοντας κλικ στο κουμπί "Δημιουργία νέου μυστικού κλειδιού".

Όταν δημιουργείται ένα κλειδί API, θα μπορείτε να αντιγράψετε το μυστικό κλειδί και να το χρησιμοποιήσετε όταν ξεκινήσετε την ανάπτυξη.

Σημείωση: Το OpenAI παρέχει επί του παρόντος δωρεάν πιστώσεις 18$ για 3 μήνες, κάτι που είναι υπέροχο, καθώς δεν θα χρειαστεί να παρέχετε τα στοιχεία πληρωμής σας για να αρχίσετε να αλληλεπιδράτε με το API για πρώτη φορά.

Ρύθμιση εφαρμογής Node/Express

Τώρα θα προχωρήσουμε στη δημιουργία ενός νέου καταλόγου για το έργο Node μας και θα το ονομάσουμε custom_chat_gpt.

mkdir custom_chat_gpt

Θα πλοηγηθούμε στον νέο κατάλογο και θα εκτελέσουμε την ακόλουθη εντολή για να δημιουργήσουμε ένα αρχείο package.json.

npm init -y

Μόλις δημιουργηθεί κατάλληλα το αρχείο package.json, θα εγκαταστήσουμε τις τρεις εξαρτήσεις που θα χρειαστούμε προς το παρόν.

npm install dotenv express openai
  • dotenv: θα μας επιτρέψει να φορτώσουμε μεταβλητές περιβάλλοντος από ένα αρχείο .env όταν εργαζόμαστε τοπικά.
  • express: είναι το πλαίσιο Node.js που θα χρησιμοποιήσουμε για την περιστροφή ενός διακομιστή Node.
  • openai: είναι η βιβλιοθήκη Node.js για το OpenAI API.

Στη συνέχεια, θα δημιουργήσουμε ένα αρχείο με το όνομα index.js. Το αρχείο index.js είναι το μέρος όπου θα δημιουργήσουμε τον διακομιστή Node.js/Express.

Στο αρχείο index.js, θα:

  • Συμπεριλάβετε την ενότητα express με require("express").
  • Στη συνέχεια, θα εκτελέσουμε τη συνάρτηση express() για να ορίσουμε το στιγμιότυπο Express και να το αντιστοιχίσουμε σε μια σταθερά με την ένδειξη app.
  • Θα καθορίσουμε ένα ενδιάμεσο λογισμικό στην παρουσία μας Express (με app.use()) για την ανάλυση των εισερχόμενων αιτημάτων JSON και την τοποθέτηση των αναλυμένων δεδομένων σε ένα σώμα req.
  • Θα καθορίσουμε μια μεταβλητή port στην οποία θα δοθεί μια τιμή που προέρχεται από μια μεταβλητή περιβάλλοντος PORT ή 5000 εάν η μεταβλητή περιβάλλοντος PORT δεν έχει οριστεί.
const express = require("express");

const app = express();
app.use(express.json());

const port = process.env.PORT || 5000;

Στη συνέχεια, θα ρυθμίσουμε μια διαδρομή POST με την ένδειξη /ask που θα λειτουργεί ως το τελικό σημείο που θα ενεργοποιήσει ο πελάτης μας. Σε αυτήν τη διαδρομή, θα περιμένουμε να υπάρχει μια τιμή prompt στο σώμα του αιτήματος και αν δεν υπάρχει, θα ρίξουμε ένα σφάλμα. Εάν η τιμή prompt υπάρχει, απλώς θα επιστρέψουμε μια απάντηση κατάστασης 200 που περιέχει το prompt σε ένα πεδίο message.

Τέλος, θα εκτελέσουμε τη συνάρτηση app.listen() για να ακούει η εφαρμογή μας την τιμή θύρας που έχουμε καθορίσει στη μεταβλητή port.

const express = require("express");

const app = express();
app.use(express.json());

const port = process.env.PORT || 5000;

// POST request endpoint
app.post("/ask", async (req, res) => {
  // getting prompt question from request
  const prompt = req.body.prompt;

  try {
    if (prompt == null) {
      throw new Error("Uh oh, no prompt was provided");
    }
    // return the result
    return res.status(200).json({
      success: true,
      message: prompt,
    });
  } catch (error) {
    console.log(error.message);
  }
});

app.listen(port, () => console.log(`Server is running on port ${port}!!`));

Με αυτή την αλλαγή αποθηκευμένη, θα είναι η κατάλληλη στιγμή να ελέγξουμε ότι οι αλλαγές μας λειτουργούν. Θα τρέξουμε τον διακομιστή με:

node index.js

Με τον διακομιστή μας σε λειτουργία, μπορούμε στη συνέχεια να προσπαθήσουμε να ενεργοποιήσουμε το αίτημα /ask POST μέσω μιας εντολής CURL για να επαληθεύσουμε ότι ο διακομιστής μας έχει ρυθμιστεί κατάλληλα.

curl -X POST \
  http://localhost:5000/ask \
  -H 'Content-Type: application/json' \
  -d '{ "prompt": "Hi! This is a test prompt!" }'

Θα λάβουμε επιτυχή απάντηση και θα μας επιστραφεί η προτροπή μας.

Με τον διακομιστή μας να λειτουργεί τώρα όπως προβλέπεται, μπορούμε να προχωρήσουμε στην αλληλεπίδραση του τελικού σημείου /ask με το τελικό σημείο /completions του OpenAI.

Αλληλεπίδραση με το τελικό σημείο ολοκλήρωσης του OpenAI

Το OpenAI παρέχει ένα /completions τελικό σημείο στο API του που παρέχει προτάσεις ολοκλήρωσης για την εισαγωγή κειμένου.

Όταν στέλνουμε ένα αίτημα στο τελικό σημείο /completions και συμπεριλάβουμε ένα μήνυμα προτροπής ή ένα αρχικό κείμενο, το API θα δημιουργήσει μια συνέχεια αυτού του κειμένου με βάση τα δεδομένα εκπαίδευσης του.

Με αυτό το τελικό σημείο /completions, μπορούμε να δημιουργήσουμε τη δική μας προσαρμοσμένη έκδοση του ChatGPT (με κάποια προειδοποίηση ότι το ChatGPT πιθανότατα χρησιμοποιεί ένα πιο ισχυρό μοντέλο Machine Learning που δεν είναι διαθέσιμο μέσω του OpenAI API).

Για να αλληλεπιδράσουμε με το OpenAI API, θα χρειαστούμε το μοναδικό κλειδί API που δημιουργήσαμε νωρίτερα μέσω του ιστότοπου OpenAI. Οι ευαίσθητες πληροφορίες, όπως τα κλειδιά API, δεν πρέπει να κωδικοποιούνται απευθείας στον πηγαίο κώδικα της εφαρμογής.

Θα δημιουργήσουμε ένα αρχείο .env στον ριζικό κατάλογο του έργου μας για την αποθήκευση μεταβλητών περιβάλλοντος που περιέχουν ευαίσθητες πληροφορίες.

custom_chat_gpt
  .env
  // ...

Στο αρχείο .env, θα δημιουργήσουμε μια νέα μεταβλητή περιβάλλοντος με την ετικέτα OPENAI_API_KEY και θα της δώσουμε την τιμή του κλειδιού OpenAI API.

# your unique API key value goes here
OPENAI_API_KEY=sk-############

Στο αρχείο index.js, θα απαιτήσουμε και θα χρησιμοποιήσουμε τη λειτουργική μονάδα dotenv για να φορτώσουμε μεταβλητές περιβάλλοντος από το αρχείο .env στο περιβάλλον process της εφαρμογής μας. Θα εισαγάγουμε επίσης τις κλάσεις που θα χρειαστούμε από τη βιβλιοθήκη openai Node.js — τις κλάσεις Configuration και OpenAIApi.

// configure dotenv
require("dotenv").config();

// import modules from OpenAI library
const { Configuration, OpenAIApi } = require("openai");

// ...

Στη συνέχεια, θα χρειαστεί να δημιουργήσουμε ένα αντικείμενο διαμόρφωσης για την αλληλεπίδραση με το OpenAI API. Θα το κάνουμε αυτό εγκαθιστώντας τον κατασκευαστή Configuration() και περνώντας την τιμή της μεταβλητής περιβάλλοντος OPENAI_API_KEY στο πεδίο apiKey.

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});

Στη συνέχεια, θα ρυθμίσουμε μια νέα παρουσία της κλάσης OpenAI API όπως η εξής:

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

Μπορούμε τώρα να χρησιμοποιήσουμε τη μεταβλητή openai που δημιουργήσαμε για να πραγματοποιούμε κλήσεις API και να επεξεργαστούμε απαντήσεις από το OpenAI.

Στη συνάρτηση αιτήματος /ask POST, θα εκτελέσουμε τη συνάρτηση openai.createCompletion() που ουσιαστικά ενεργοποιεί μια κλήση στο τελικό σημείο ολοκλήρωσης του OpenAI.

app.post("/ask", async (req, res) => {
  const prompt = req.body.prompt;

  try {
    if (prompt == null) {
      throw new Error("Uh oh, no prompt was provided");
    }
    // trigger OpenAI completion
    const response = await openai.createCompletion();
    // ...
  } catch (error) {
    console.log(error.message);
  }
});

Το τελικό σημείο ολοκλήρωσης OpenAI μας επιτρέπει να μεταβιβάσουμε έναν μεγάλο αριθμό προαιρετικών πεδίων στο αίτημα για να τροποποιήσουμε τον τρόπο με τον οποίο θέλουμε να συμπεριφέρεται η συμπλήρωση του κειμένου μας. Για την περίπτωση χρήσης μας, θα εξετάσουμε μόνο την παροχή τιμών για δύο πεδία — model και prompt.

  • model: καθορίζει το όνομα του μοντέλου γλώσσας που πρέπει να χρησιμοποιήσει το API για να δημιουργήσει την απάντηση στο αίτημα. Το OpenAI παρέχει πολλά διαφορετικά μοντέλα γλώσσας, το καθένα με τα δυνατά του σημεία και τις δυνατότητές του. Για την περίπτωση χρήσης μας, θα καθορίσουμε ότι θέλουμε να χρησιμοποιήσουμε το μοντέλο text-davinci-003 που είναι το πιο ικανό μοντέλο GPT-3 του OpenAI.
  • prompt: είναι η προτροπή για την οποία θέλουμε το OpenAI να δημιουργήσει μια ολοκλήρωση. Εδώ απλώς θα μεταβιβάσουμε την τιμή prompt που υπάρχει στο σώμα του αιτήματός μας /ask.
app.post("/ask", async (req, res) => {
  const prompt = req.body.prompt;

  try {
    if (prompt == null) {
      throw new Error("Uh oh, no prompt was provided");
    }
    // trigger OpenAI completion
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt,
    });
    // ...
  } catch (error) {
    console.log(error.message);
  }
});

Το κείμενο που επιστρέφεται από την απόκριση OpenAI υπάρχει μέσα σε έναν πίνακα choices που ο ίδιος βρίσκεται μέσα σε ένα αντικείμενο response.data. Θα προσπαθήσουμε να αποκτήσουμε πρόσβαση στο κείμενο που επιστράφηκε από την πρώτη επιλογή που επιστράφηκε στο API, το οποίο θα έχει την εξής μορφή:

app.post("/ask", async (req, res) => {
  const prompt = req.body.prompt;

  try {
    if (prompt == null) {
      throw new Error("Uh oh, no prompt was provided");
    }
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt,
    });
    // retrieve the completion text from response
    const completion = response.data.choices[0].text;
    // ...
  } catch (error) {
    console.log(error.message);
  }
});

Το τελευταίο πράγμα που θα κάνουμε είναι να επιστραφεί αυτή η απάντηση ολοκλήρωσης στην επιτυχή απάντηση του αιτήματός μας /ask. Με αυτήν την αλλαγή και όλες τις αλλαγές που κάναμε, το αρχείο index.js μας θα έχει την εξής μορφή.

require("dotenv").config();
const express = require("express");
const { Configuration, OpenAIApi } = require("openai");

const app = express();
app.use(express.json());

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

const port = process.env.PORT || 5000;

app.post("/ask", async (req, res) => {
  const prompt = req.body.prompt;
  try {
    if (prompt == null) {
      throw new Error("Uh oh, no prompt was provided");
    }
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt,
    });
    const completion = response.data.choices[0].text;
    return res.status(200).json({
      success: true,
      message: completion,
    });
  } catch (error) {
    console.log(error.message);
  }
});

app.listen(port, () => console.log(`Server is running on port ${port}!!`));

Θα αποθηκεύσουμε τις αλλαγές μας και θα επανεκκινήσουμε τον διακομιστή μας. Με τον διακομιστή μας σε λειτουργία, μπορούμε να κάνουμε ορισμένες ερωτήσεις στο API μας όπως "What is the typical weather in Dubai?".

curl -X POST \
  http://localhost:5000/ask \
  -H 'Content-Type: application/json' \
  -d '{ "prompt": "What is the typical weather in Dubai?" }'

Αφού περιμένουμε μερικά δευτερόλεπτα, το API μας θα μας επιστρέψει μια έγκυρη απάντηση στην ερώτησή μας!

Αυτό είναι! Καταφέραμε να δημιουργήσουμε ένα απλό API με Node/Express για αλληλεπίδραση με το τελικό σημείο ολοκλήρωσης του OpenAI.

Στο επόμενο εκπαιδευτικό μήνυμα ηλεκτρονικού ταχυδρομείου που θα στείλουμε, θα συνεχίσουμε σε αυτόν τον οδηγό δημιουργώντας μια εφαρμογή React που ενεργοποιεί το αίτημα /ask όταν υποβάλλεται ένα πεδίο εισαγωγής.

Κλείσιμο σκέψεις

  • Μπορείτε να βρείτε τον πηγαίο κώδικα για αυτό το άρθρο στη διεύθυνση github.com/djirdehh/frontend-fresh/articles_source_code.
  • Αλληλεπιδράστε με το τελικό σημείο /completions και μη διστάσετε να το ζητήσετε όποια προτροπή θέλετε!
  • Εάν δεν είστε λάτρης της χρήσης curl για τη δοκιμή αιτημάτων τοπικά, το Postman είναι ένα δημοφιλές εργαλείο για τη δοκιμή αιτημάτων API μέσω ενός πελάτη.
  • Διαβάστε περισσότερα για όλα τα διαφορετικά προαιρετικά πεδία που μπορούμε να παρέχουμε στο τελικό σημείο /completion του OpenAI στην τεκμηρίωση OpenAI API.
  • Εγγραφείτε στο https://www.frontendfresh.com/ για περισσότερα σεμινάρια όπως αυτό για να βγάζετε τα εισερχόμενά σας σε εβδομαδιαία βάση!

Δημιουργήστε εφαρμογές με επαναχρησιμοποιήσιμα στοιχεία, όπως και η Lego

Το εργαλείο ανοιχτού κώδικα του Bitβοηθά 250.000+ προγραμματιστές να δημιουργήσουν εφαρμογές με στοιχεία.

Μετατρέψτε οποιαδήποτε διεπαφή χρήστη, δυνατότητα ή σελίδα σε επαναχρησιμοποιήσιμο στοιχείο — και μοιραστείτε το στις εφαρμογές σας. Είναι πιο εύκολο να συνεργαστείτε και να χτίσετε πιο γρήγορα.

Μάθετε περισσότερα

Διαχωρίστε τις εφαρμογές σε στοιχεία για να διευκολύνετε την ανάπτυξη εφαρμογών και απολαύστε την καλύτερη εμπειρία για τις ροές εργασίας που θέλετε:

Micro-Frontends

Σύστημα σχεδίασης

Κοινή χρήση κώδικα και επαναχρησιμοποίηση

Monorepo

Μάθε περισσότερα: