Tích hợp DeepSeek AI vào ứng dụng Web hiện đại với Vite

Việc tích hợp trực tiếp các mô hình ngôn ngữ lớn (LLM) vào giao diện người dùng đang trở thành một xu hướng mạnh mẽ, giúp rút ngắn thời gian phát triển các ứng dụng AI. Dưới đây là hướng dẫn chi tiết cách xây dựng một dự án sử dụng Vite để tương tác với DeepSeek API thông qua phương thức HTTP request.

1. Khởi tạo môi trường phát triển với Vite

Vite là một công cụ đóng gói (bundler) thế hệ mới, nổi bật với tốc độ phản hồi cực nhanh. Chúng ta sẽ bắt đầu bằng cách tạo một dự án sử dụng JavaScript thuần (Vanilla JS).

npm create vite@latest my-ai-app -- --template vanilla
cd my-ai-app
npm install

Cấu trúc thư mục cơ bản sẽ bao gồm:

  • index.html: Giao diện người dùng.
  • main.js: Logic xử lý chính.
  • .env.local: Nơi lưu trữ mã bảo mật API.

2. Cấu hình biến môi trường

Để bảo vệ API Key và giúp Vite nhận diện được các biến này, bạn cần tạo file .env.local trong thư mục gốc của dự án:

VITE_DEEPSEEK_TOKEN=your_api_key_here

Lưu ý: Trong Vite, chỉ những biến bắt đầu bằng tiền tố VITE_ mới được phép truy cập từ mã nguồn frontend.

3. Xây dựng giao diện và logic gọi API

Cấu trúc HTML (index.html)

Thiết lập một giao diện đơn giản để hiển thị kết quả phản hồi từ AI.

<div id="app">
  <h1>AI Assistant</h1>
  <div id="chat-container">
    <p id="status">Đang chờ phản hồi...</p>
    <div id="response-content"></div>
  </div>
</div>

Logic xử lý JavaScript (main.js)

Sử dụng fetch để gửi yêu cầu POST đến endpoint của DeepSeek. Chúng ta sẽ thay đổi cấu trúc hàm và cách quản lý dữ liệu so với các ví dụ thông thường.

const API_ENDPOINT = 'https://api.deepseek.com/chat/completions';
const API_KEY = import.meta.env.VITE_DEEPSEEK_TOKEN;

/**
 * Gửi yêu cầu đến DeepSeek API
 * @param {string} prompt - Nội dung người dùng nhập
 */
async function getAIResponse(prompt) {
  const displayArea = document.getElementById('response-content');
  const statusLabel = document.getElementById('status');

  const requestOptions = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`
    },
    body: JSON.stringify({
      model: "deepseek-chat",
      messages: [
        { role: "system", content: "Bạn là một trợ lý ảo chuyên nghiệp." },
        { role: "user", content: prompt }
      ],
      stream: false
    })
  };

  try {
    statusLabel.textContent = 'Đang xử lý...';
    const response = await fetch(API_ENDPOINT, requestOptions);
    
    if (!response.ok) {
      throw new Error(`Lỗi hệ thống: ${response.status}`);
    }

    const result = await response.json();
    displayArea.innerHTML = result.choices[0].message.content;
    statusLabel.textContent = 'Hoàn tất:';
  } catch (error) {
    console.error('Lỗi khi gọi API:', error);
    displayArea.textContent = 'Không thể kết nối với AI. Vui lòng kiểm tra lại cấu hình.';
    statusLabel.textContent = 'Lỗi!';
  }
}

// Thực thi khi trang web sẵn sàng
window.addEventListener('DOMContentLoaded', () => {
  getAIResponse('Giải thích ngắn gọn về cơ chế Fetch API trong JavaScript');
});

4. Phân tích chi tiết kỹ thuật

Giao thức HTTP và Header

Khi làm việc với các RESTful API của các mô hình ngôn ngữ, cấu trúc Header đóng vai trò quan trọng:

  • Content-Type: Định dạng dữ liệu gửi đi luôn là application/json.
  • Authorization: Sử dụng cơ chế Bearer Token để xác thực danh tính người dùng.

Xử lý bất đồng bộ

Sử dụng async/await giúp mã nguồn trông giống như tuần tự, dễ đọc và dễ bảo trì hơn so với chuỗi .then() truyền thống. Việc đặt fetch trong khối try...catch là bắt buộc để xử lý các tình huống mất kết nối mạng hoặc lỗi server.

5. Chiến lược bảo mật và tối ưu hóa

Mặc dù việc gọi API trực tiếp từ frontend rất nhanh chóng, nhưng nó tiềm ẩn nguy cơ lộ API Key nếu mã nguồn bị dịch ngược hoặc theo dõi qua tab Network của trình duyệt. Để khắc phục, bạn có thể triển khai một Proxy Server đơn giản bằng Express.js:

// server.js (Node.js backend)
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

app.post('/api/proxy-chat', async (req, res) => {
  try {
    const aiResponse = await axios.post('https://api.deepseek.com/chat/completions', req.body, {
      headers: {
        'Authorization': `Bearer ${process.env.SECRET_KEY}`
      }
    });
    res.json(aiResponse.data);
  } catch (err) {
    res.status(500).send('Lỗi máy chủ trung gian');
  }
});

app.listen(5000);

Bằng cách này, trình duyệt sẽ gọi đến server của chính bạn (localhost:5000) thay vì gọi trực tiếp đến DeepSeek, giúp giấu kín mã bảo mật API trong môi trường server an toàn.

6. Các lưu ý về CORS và Giới hạn tốc độ

DeepSeek API hỗ trợ CORS cho phép các yêu cầu từ trình duyệt. Tuy nhiên, bạn cần lưu ý đến giới hạn Rate Limit (số lượng yêu cầu mỗi phút) để tránh bị khóa tài khoản tạm thời. Việc tối ưu hóa kích thước prompt (nội dung gửi đi) cũng giúp tiết kiệm chi phí và tăng tốc độ phản hồi từ mô hình AI.

Thẻ: DeepSeek vite JavaScript API Integration Frontend Development

Đăng vào ngày 3 tháng 10 lúc 16:28