使用 Gin 和 OpenAI 实现实时聊天:后端代码与前端集成
在本篇文章中,我们将详细介绍如何使用 Go 语言的 Gin 框架与 OpenAI API 实现一个实时聊天功能。本文涵盖了后端代码的实现、.env 配置文件的设置方法,以及前端如何通过 SSE(Server-Sent Events)与后端交互以实现实时消息的接收。
1. 后端代码简介
首先,让我们来了解一下后端代码的主要逻辑。
该代码通过 Gin 框架创建了一个 API 接口,接收用户的请求内容,并将其转发给 OpenAI 的 GPT-4 模型进行处理。然后,后端会通过 SSE 实时将 OpenAI 的响应推送给前端,实现与用户的实时互动。
主要的步骤包括:
- 接收并处理用户请求。
- 加载配置文件 .env。
- 向 OpenAI API 发送请求。
- 通过 SSE 将 OpenAI 的响应实时推送给前端。
2. .env 配置文件
为了管理 API 密钥和其他配置项,我们使用了 .env 文件。这个文件存储了与 OpenAI API 交互所需的关键配置信息,如 API 密钥、模型类型、最大 Token 数量、温度值等。
以下是一个示例 .env 文件的配置内容:
# OpenAI API Key
OPENAI_API_KEY=your-openai-api-key
# OpenAI API Base URL
OPENAI_URL=https://api.openai.com
# 使用的 GPT 模型(例如:gpt-3.5-turbo)
GPT_MODEL=gpt-4
# 最大Token数
MAX_TOKENS=1000
# 生成文本的温度(控制输出的随机性)
TEMPERATURE=0.7
- OPENAI_API_KEY: 你的 OpenAI API 密钥,确保其安全性。
- OPENAI_URL: OpenAI API 的基础 URL,通常为- https://api.openai.com。
- GPT_MODEL: 要使用的 GPT 模型,如- gpt-3.5-turbo。
- MAX_TOKENS: 设置 GPT 模型生成的最大 token 数量,影响输出长度。
- TEMPERATURE: 控制生成文本的随机性,值越高越随机。
3. 后端代码实现细节
在代码中,我们首先通过 godotenv 包加载 .env 文件中的配置项。然后,创建一个 POST 请求,将用户输入的内容发送给 OpenAI API。
以下是代码片段的主要逻辑:
// 加载 .env 文件中的配置
err := godotenv.Load()
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load .env file"})
    return
}
apiKey := os.Getenv("OPENAI_API_KEY")
url := os.Getenv("OPENAI_URL")
model := os.Getenv("GPT_MODEL")
maxTokens, _ := strconv.Atoi(os.Getenv("MAX_TOKENS"))
temperature, _ := strconv.ParseFloat(os.Getenv("TEMPERATURE"), 64)
接下来,将用户输入的内容封装到请求体中,并将其发送到 OpenAI API:
requestBody := GPTRequest{
    Model: model,
    Messages: []Message{
        {
            Role:    "system",
            Content: "You are a helpful assistant.",
        },
        {
            Role:    "user",
            Content: content,
        },
    },
    Stream:      true,
    MaxTokens:   maxTokens,
    Temperature: temperature,
}
jsonData, err := json.Marshal(requestBody)
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to marshal request"})
    return
}
req, err := http.NewRequest("POST", url+"/v1/chat/completions", bytes.NewBuffer(jsonData))
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
    return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+apiKey)
然后,我们通过 http.Client 发送请求,并处理返回的流式响应。Gin 的 SSE 功能可以帮助我们实时将数据推送到前端:
c.Stream(func(w io.Writer) bool {
    scanner := bufio.NewScanner(resp.Body)
    for scanner.Scan() {
        line := strings.TrimPrefix(scanner.Text(), "data: ")
        if len(line) > 0 {
            var streamResp StreamResponse
            err := json.Unmarshal([]byte(line), &streamResp)
            if err != nil {
                continue
            }
            if len(streamResp.Choices) > 0 {
                content := streamResp.Choices[0].Delta.Content
                c.SSEvent("message", content)
            }
            flusher, ok := w.(http.Flusher)
            if ok {
                flusher.Flush()
            }
        }
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintf(w, "data: %s\n\n", "Stream ended with an error")
        return false
    }
    return false // End the stream
})
4. 前端使用方法
为了在前端与后端进行实时交互,你可以使用 JavaScript 的 EventSource 对象来接收服务端推送的消息。
以下是前端代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GPT-3 Chat</title>
</head>
<body>
    <h1>GPT-3 Chat</h1>
    <div id="chat"></div>
    <input type="text" id="userInput" placeholder="Type a message...">
    <button onclick="sendMessage()">Send</button>
    <script>
        function sendMessage() {
            var userInput = document.getElementById('userInput').value;
            var eventSource = new EventSource(`/openai?action=chat&content=${encodeURIComponent(userInput)}`);
            
            eventSource.onmessage = function(event) {
                var chatDiv = document.getElementById('chat');
                var newMessage = document.createElement('p');
                newMessage.textContent = event.data;
                chatDiv.appendChild(newMessage);
            };
            eventSource.onerror = function() {
                console.error("EventSource failed.");
                eventSource.close();
            };
        }
    </script>
</body>
</html>
步骤解释:
- 输入框与发送按钮:用户在输入框中输入消息,并通过点击“Send”按钮发送消息。
- 创建 EventSource:在用户点击按钮后,创建一个EventSource对象,指定后端 API 的路径并带上用户输入的消息作为查询参数。
- 处理 onmessage事件:当后端推送消息时,前端通过onmessage事件接收消息并将其显示在页面上。
- 处理错误:通过 onerror事件处理连接错误,并关闭EventSource连接。
5. 总结
通过本文,你已经学会了如何使用 Go 和 Gin 实现一个与 OpenAI 的 GPT-3 模型实时交互的后端 API,并且能够通过前端使用 SSE 技术实时接收来自后端的响应。 .env 文件使得 API 配置管理更加简单和安全,前端的 EventSource 允许你轻松实现实时通讯功能。这个方案适用于需要实时反馈的应用场景,如智能客服、实时聊天机器人等。
通过这种方式,你可以将强大的 GPT-4 模型集成到你的应用中,为用户提供智能且即时的交互体验。