Quay lại Blog
Tích hợp GauGau AI với các Framework phổ biến: React, Next.js và nhiều hơn
Tutorial
8 min read

Tích hợp GauGau AI với các Framework phổ biến: React, Next.js và nhiều hơn

Hướng dẫn từng bước để tích hợp GauGau AI vào các framework yêu thích của bạn. Học các thực hành tốt nhất cho ứng dụng React, Next.js, Vue, Express và FastAPI.

GauGau Team
GauGau Team
Bởi GauGau Team

Tích hợp GauGau AI với các Framework phổ biến

Hướng dẫn toàn diện này chỉ cho bạn cách tích hợp GauGau AI vào các framework web phổ biến nhất. Chúng tôi sẽ đề cập đến React, Next.js, Vue, Express và FastAPI với các ví dụ sẵn sàng cho production.

Tích hợp React

Thiết lập

Đầu tiên, cài đặt OpenAI SDK:

npm install openai

Tạo dịch vụ API

// src/services/ai.js
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.REACT_APP_GAUGAU_API_KEY,
  baseURL: 'https://api.gaugauai.com/v1',
  dangerouslyAllowBrowser: true // Chỉ cho development!
});

export const aiService = {
  async chat(messages, model = 'gpt-4o-mini') {
    const response = await client.chat.completions.create({
      model,
      messages,
    });
    return response.choices[0].message.content;
  },

  async streamChat(messages, model = 'gpt-4o-mini', onChunk) {
    const stream = await client.chat.completions.create({
      model,
      messages,
      stream: true,
    });

    let fullResponse = '';
    for await (const chunk of stream) {
      const content = chunk.choices[0]?.delta?.content || '';
      fullResponse += content;
      onChunk(content, fullResponse);
    }

    return fullResponse;
  },
};

Tạo Chat Component

// src/components/ChatBox.jsx
import { useState } from 'react';
import { aiService } from '../services/ai';

export default function ChatBox() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!input.trim()) return;

    const userMessage = { role: 'user', content: input };
    setMessages((prev) => [...prev, userMessage]);
    setInput('');
    setLoading(true);

    try {
      const response = await aiService.chat([...messages, userMessage]);
      setMessages((prev) => [
        ...prev,
        { role: 'assistant', content: response },
      ]);
    } catch (error) {
      console.error('Lỗi AI:', error);
      setMessages((prev) => [
        ...prev,
        { role: 'assistant', content: 'Xin lỗi, đã xảy ra lỗi.' },
      ]);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="chat-container">
      <div className="messages">
        {messages.map((msg, idx) => (
          <div key={idx} className={`message ${msg.role}`}>
            <strong>{msg.role === 'user' ? 'Bạn' : 'AI'}:</strong>
            <p>{msg.content}</p>
          </div>
        ))}
        {loading && <div className="loading">AI đang suy nghĩ...</div>}
      </div>

      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Nhập tin nhắn của bạn..."
          disabled={loading}
        />
        <button type="submit" disabled={loading}>
          Gửi
        </button>
      </form>
    </div>
  );
}

Tích hợp Next.js

API Route (Khuyến nghị cho bảo mật)

// app/api/chat/route.js
import OpenAI from 'openai';
import { NextResponse } from 'next/server';

const client = new OpenAI({
  apiKey: process.env.GAUGAU_API_KEY,
  baseURL: 'https://api.gaugauai.com/v1',
});

export async function POST(request) {
  try {
    const { messages, model = 'gpt-4o-mini' } = await request.json();

    const response = await client.chat.completions.create({
      model,
      messages,
    });

    return NextResponse.json({
      content: response.choices[0].message.content,
      usage: response.usage,
    });
  } catch (error) {
    console.error('Lỗi AI API:', error);
    return NextResponse.json(
      { error: 'Không thể tạo phản hồi' },
      { status: 500 }
    );
  }
}

Streaming API Route

// app/api/chat/stream/route.js
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.GAUGAU_API_KEY,
  baseURL: 'https://api.gaugauai.com/v1',
});

export async function POST(request) {
  const { messages, model = 'gpt-4o-mini' } = await request.json();

  const stream = await client.chat.completions.create({
    model,
    messages,
    stream: true,
  });

  const encoder = new TextEncoder();

  const readableStream = new ReadableStream({
    async start(controller) {
      for await (const chunk of stream) {
        const content = chunk.choices[0]?.delta?.content || '';
        if (content) {
          controller.enqueue(encoder.encode(content));
        }
      }
      controller.close();
    },
  });

  return new Response(readableStream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    },
  });
}

Client Component

// app/components/Chat.jsx
'use client';

import { useState } from 'react';

export default function Chat() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!input.trim()) return;

    const userMessage = { role: 'user', content: input };
    setMessages((prev) => [...prev, userMessage]);
    setInput('');
    setLoading(true);

    try {
      const response = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          messages: [...messages, userMessage],
          model: 'gpt-4o-mini',
        }),
      });

      const data = await response.json();
      setMessages((prev) => [
        ...prev,
        { role: 'assistant', content: data.content },
      ]);
    } catch (error) {
      console.error('Lỗi:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="max-w-2xl mx-auto p-4">
      <div className="space-y-4 mb-4">
        {messages.map((msg, idx) => (
          <div
            key={idx}
            className={`p-4 rounded-lg ${
              msg.role === 'user'
                ? 'bg-blue-100 ml-auto max-w-[80%]'
                : 'bg-gray-100 mr-auto max-w-[80%]'
            }`}
          >
            {msg.content}
          </div>
        ))}
      </div>

      <form onSubmit={handleSubmit} className="flex gap-2">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          className="flex-1 p-2 border rounded"
          placeholder="Nhập tin nhắn của bạn..."
          disabled={loading}
        />
        <button
          type="submit"
          disabled={loading}
          className="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
        >
          {loading ? 'Đang gửi...' : 'Gửi'}
        </button>
      </form>
    </div>
  );
}

Tích hợp Vue 3

Composable

// src/composables/useAI.js
import { ref } from 'vue';
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: import.meta.env.VITE_GAUGAU_API_KEY,
  baseURL: 'https://api.gaugauai.com/v1',
  dangerouslyAllowBrowser: true,
});

export function useAI() {
  const loading = ref(false);
  const error = ref(null);

  const chat = async (messages, model = 'gpt-4o-mini') => {
    loading.value = true;
    error.value = null;

    try {
      const response = await client.chat.completions.create({
        model,
        messages,
      });
      return response.choices[0].message.content;
    } catch (err) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  };

  return {
    loading,
    error,
    chat,
  };
}

Chat Component

<!-- src/components/ChatBox.vue -->
<template>
  <div class="chat-container">
    <div class="messages">
      <div
        v-for="(msg, idx) in messages"
        :key="idx"
        :class="['message', msg.role]"
      >
        <strong>{{ msg.role === 'user' ? 'Bạn' : 'AI' }}:</strong>
        <p>{{ msg.content }}</p>
      </div>
      <div v-if="loading" class="loading">AI đang suy nghĩ...</div>
    </div>

    <form @submit.prevent="handleSubmit">
      <input
        v-model="input"
        type="text"
        placeholder="Nhập tin nhắn của bạn..."
        :disabled="loading"
      />
      <button type="submit" :disabled="loading">Gửi</button>
    </form>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useAI } from '../composables/useAI';

const { loading, chat } = useAI();
const messages = ref([]);
const input = ref('');

const handleSubmit = async () => {
  if (!input.value.trim()) return;

  const userMessage = { role: 'user', content: input.value };
  messages.value.push(userMessage);
  input.value = '';

  try {
    const response = await chat(messages.value);
    messages.value.push({ role: 'assistant', content: response });
  } catch (error) {
    console.error('Lỗi AI:', error);
    messages.value.push({
      role: 'assistant',
      content: 'Xin lỗi, đã xảy ra lỗi.',
    });
  }
};
</script>

<style scoped>
.chat-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.messages {
  height: 400px;
  overflow-y: auto;
  margin-bottom: 20px;
  border: 1px solid #ddd;
  padding: 10px;
  border-radius: 8px;
}

.message {
  margin-bottom: 15px;
  padding: 10px;
  border-radius: 8px;
}

.message.user {
  background: #e3f2fd;
  margin-left: 20%;
}

.message.assistant {
  background: #f5f5f5;
  margin-right: 20%;
}

form {
  display: flex;
  gap: 10px;
}

input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  padding: 10px 20px;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
</style>

Express.js Backend

// server.js
import express from 'express';
import OpenAI from 'openai';
import cors from 'cors';

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

const client = new OpenAI({
  apiKey: process.env.GAUGAU_API_KEY,
  baseURL: 'https://api.gaugauai.com/v1',
});

// Chat endpoint
app.post('/api/chat', async (req, res) => {
  try {
    const { messages, model = 'gpt-4o-mini' } = req.body;

    const response = await client.chat.completions.create({
      model,
      messages,
    });

    res.json({
      content: response.choices[0].message.content,
      usage: response.usage,
    });
  } catch (error) {
    console.error('Lỗi AI:', error);
    res.status(500).json({ error: 'Không thể tạo phản hồi' });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server đang chạy trên cổng ${PORT}`);
});

FastAPI Backend (Python)

# main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from openai import OpenAI
import os

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

client = OpenAI(
    api_key=os.getenv("GAUGAU_API_KEY"),
    base_url="https://api.gaugauai.com/v1"
)

class ChatRequest(BaseModel):
    messages: list
    model: str = "gpt-4o-mini"

@app.post("/api/chat")
async def chat(request: ChatRequest):
    try:
        response = client.chat.completions.create(
            model=request.model,
            messages=request.messages
        )
        
        return {
            "content": response.choices[0].message.content,
            "usage": {
                "prompt_tokens": response.usage.prompt_tokens,
                "completion_tokens": response.usage.completion_tokens,
                "total_tokens": response.usage.total_tokens
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Thực hành tốt nhất

1. Không bao giờ để lộ API Key ở Frontend

Tệ:

const client = new OpenAI({
  apiKey: 'gaugau_xxx', // Bị lộ trong trình duyệt!
  baseURL: 'https://api.gaugauai.com/v1',
  dangerouslyAllowBrowser: true,
});

Tốt:

// Sử dụng backend API route
const response = await fetch('/api/chat', {
  method: 'POST',
  body: JSON.stringify({ messages }),
});

2. Triển khai Rate Limiting

// Express middleware
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 phút
  max: 100, // Giới hạn mỗi IP 100 request mỗi windowMs
});

app.use('/api/chat', limiter);

3. Thêm xử lý lỗi

try {
  const response = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages,
  });
  return response.choices[0].message.content;
} catch (error) {
  if (error.status === 429) {
    // Vượt quá giới hạn tốc độ
    return 'Quá nhiều request. Vui lòng thử lại sau.';
  } else if (error.status === 401) {
    // API key không hợp lệ
    console.error('API key không hợp lệ');
    return 'Lỗi xác thực.';
  } else {
    // Các lỗi khác
    console.error('Lỗi AI:', error);
    return 'Đã xảy ra lỗi. Vui lòng thử lại.';
  }
}

4. Sử dụng biến môi trường

# .env
GAUGAU_API_KEY=your_api_key_here
// Load với dotenv
import 'dotenv/config';

const apiKey = process.env.GAUGAU_API_KEY;

Kết luận

Tích hợp GauGau AI vào ứng dụng của bạn rất đơn giản bất kể bạn chọn framework nào. Những điểm chính:

  • Luôn sử dụng backend API route để bảo vệ API key của bạn
  • Triển khai streaming cho UX tốt hơn
  • Thêm xử lý lỗi và rate limiting phù hợp
  • Sử dụng biến môi trường cho cấu hình
  • Giám sát việc sử dụng và chi phí

Bắt đầu xây dựng các tính năng được hỗ trợ bởi AI vào ứng dụng của bạn ngay hôm nay!

Tài nguyên

Có câu hỏi? Liên hệ chúng tôi tại @gaugauai hoặc support@gaugauai.com.

Thẻ:#integration#react#nextjs#vue#frameworks
Chia sẻ bài viết: