Tích hợp Mô hình AI với Node.js: Xây Dựng Ứng Dụng Chat Toàn Bộ

Bài viết này sẽ hướng dẫn bạn cách tích hợp một mô hình AI vào ứng dụng toàn bộ (full-stack) sử dụng Node.js và tạo giao diện người dùng đơn giản.

1. Chuẩn bị Dự Án và Cấu Hình Môi Trường

1.1 Kiểm Tra và Cấu Hình Môi Trường Node.js

Bắt đầu bằng việc kiểm tra phiên bản Node.js:

node --version

Nếu chưa cài đặt, tải từ trang chủ của Node.js.

Tạo thư mục dự án và khởi tạo:

mkdir ai_chat_app && cd ai_chat_app
npm init -y

Cài đặt các gói cần thiết:

npm install express http-client cors dotenv

Giải thích nhanh về các gói:

  • express: Framework web phổ biến cho Node.js.
  • http-client: HTTP client để gọi API.
  • cors: Middleware quản lý chia sẻ tài nguyên liên miền.
  • dotenv: Quản lý biến môi trường.

1.2 Lấy Thông Tin Truy Cập API

Sau khi triển khai mô hình trên nền tảng GPU, lưu thông tin như URL cơ sở API và khóa API trong file .env.

touch .env

Thêm nội dung vào file .env:

AI_API_BASE_URL=https://your-api-endpoint/v1
AI_API_KEY=your-api-key-here
PORT=3000

2. Xây Dựng Dịch Vụ Backend với Node.js

2.1 Tạo Server Express và Định Nghĩa Route Cơ Bản

Tạo file server.js:

// server.js
require('dotenv').config();
const express = require('express');
const httpClient = require('http-client');
const cors = require('cors');

const app = express();
const port = process.env.PORT || 3000;

app.use(cors());
app.use(express.json());

const AI_API_BASE = process.env.AI_API_BASE_URL;
const AI_API_KEY = process.env.AI_API_KEY;

const aiApiClient = httpClient.create({
  baseURL: AI_API_BASE,
  headers: {
    'Authorization': `Bearer ${AI_API_KEY}`,
    'Content-Type': 'application/json',
  },
});

app.get('/health', (req, res) => {
  res.json({ status: 'OK', message: 'Backend is running.' });
});

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

2.2 Thực Hiện Giao Tiếp Core API

Thêm route chat:

app.post('/api/chat', async (req, res) => {
  try {
    const userMessage = req.body.message;
    if (!userMessage || !userMessage.trim()) {
      return res.status(400).json({ error: 'Message cannot be empty.' });
    }

    const requestBody = {
      model: 'light-ai-model',
      messages: [{ role: 'user', content: userMessage }],
      stream: false
    };

    const response = await aiApiClient.post('/chat/completions', requestBody);
    const aiReply = response.data.choices[0]?.message?.content || 'No reply.';
    
    res.json({
      reply: aiReply,
      usage: response.data.usage
    });

  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
    res.status(500).json({ error: 'Failed to get response.', details: error.message });
  }
});

2.3 Thực Hiện Xuất Ra Stream

Thực hiện xuất ra theo dạng stream:

app.post('/api/chat/stream', async (req, res) => {
  const userMessage = req.body.message;
  
  if (!userMessage || !userMessage.trim()) {
    return res.status(400).json({ error: 'Message cannot be empty.' });
  }

  const requestBody = {
    model: 'light-ai-model',
    messages: [{ role: 'user', content: userMessage }],
    stream: true
  };

  try {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    const apiResponse = await aiApiClient.post('/chat/completions', requestBody, { responseType: 'stream' });
    apiResponse.data.pipe(res);

    apiResponse.data.on('error', (err) => {
      console.error('Stream error:', err);
      if (!res.headersSent) {
        res.status(500).end();
      }
    });

  } catch (error) {
    console.error('Error setting up stream:', error);
    if (!res.headersSent) {
      res.status(500).json({ error: 'Failed to establish stream.' });
    }
  }
});

3. Phát Triển Giao Diện Chat Frontend

3.1 Tạo Giao Diện HTML Cho Chat

Tạo file public/index.html:

<!DOCTYPE html>
<html lang="vi">

3.2 Thực Hiện Logic Tương Tác Frontend

Tạo file public/app.js:

document.addEventListener('DOMContentLoaded', function() {
    const chatHistory = document.getElementById('chat-history');
    const messageInput = document.getElementById('message-input');
    const sendButton = document.getElementById('send-button');

    function sendMessage() {
        const message = messageInput.value.trim();
        if (!message) return;

        messageInput.disabled = true;
        sendButton.disabled = true;

        appendMessage(message, 'user');
        messageInput.value = '';

        fetch('/api/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ message: message })
        }).then(response => response.json()).then(data => {
            messageInput.disabled = false;
            sendButton.disabled = false;
            messageInput.focus();

            appendMessage(data.reply, 'ai');
        }).catch(error => {
            console.error('Request failed:', error);
        });
    }

    function appendMessage(text, sender) {
        const messageElem = document.createElement('div');
        messageElem.className = `message ${sender}-message`;
        messageElem.textContent = text;
        chatHistory.appendChild(messageElem);
        chatHistory.scrollTop = chatHistory.scrollHeight;
    }

    sendButton.addEventListener('click', sendMessage);
    messageInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            e.preventDefault();
            sendMessage();
        }
    });

    messageInput.focus();
});

3.3 Cung Cấp Tệp Tĩnh Với Express

Trong file server.js, thêm dòng sau:

app.use(express.static('public'));

4. Đề Xuất Tối Ưu Hóa và Triển Khai

Xem xét các bước tối ưu hóa và triển khai để nâng cao hiệu suất và bảo mật.

Node.js,Express,API Integration,AI Model Deployment,Full Stack Development

Thẻ: Node.js Express API Integration AI Model Deployment Full Stack Development

Đăng vào ngày 17 tháng 6 lúc 06:00