Bootstrap

使用GoZero框架抓取GPT对话记录

在本文中,我们将介绍如何使用GoZero框架构建一个简单的服务,来抓取与OpenAI GPT的对话记录并存储。这些对话记录可以包括用户输入、GPT响应以及其他相关信息。我们会展示如何设计接口、保存对话记录并实现基本的错误处理。

## 1. 背景

GoZero是一个高效的微服务框架,基于Go语言构建,旨在简化微服务的开发。本文的目标是通过GoZero框架调用GPT接口并抓取对话记录,同时提供一些常见的错误处理机制和日志记录。

我们假设已经从OpenAI获得了API密钥,并且准备好使用GoZero来访问GPT的对话接口。

## 2. 环境准备

### 2.1 安装GoZero

首先,我们需要安装GoZero框架及相关工具:

```bash

go get -u github.com/zeromicro/go-zero
go get -u github.com/zeromicro/go-zero/tools/goctl


```

### 2.2 获取OpenAI API密钥

请确保你已经在OpenAI平台注册并获得了API密钥。可以通过以下链接生成API密钥:[OpenAI平台](https://platform.openai.com/signup)。

## 3. 项目结构

我们将创建一个简单的GoZero项目,项目结构如下:

```
myservice/
├── config/
│   └── config.yaml
├── handler/
│   └── gpt_handler.go
├── logic/
│   └── gpt_logic.go
├── svc/
│   └── service_context.go
├── types/
│   └── gpt_types.go
├── main.go
└── go.mod
```

### 3.1 配置文件 (`config/config.yaml`)

首先,我们需要一个配置文件来存储GPT API的密钥以及其他配置:```yaml

Name: myservice
Host: 0.0.0.0
Port: 8080

GPT:
  ApiKey: "your-openai-api-key"
  Endpoint: "https://api.openai.com/v1/completions"


```

### 3.2 定义请求和响应结构 (`types/gpt_types.go`)

为了与OpenAI GPT接口交互,我们需要定义请求和响应的结构。以下是一个简单的结构体定义:```go

package types

// GPTRequest 是发送给OpenAI的请求结构体
type GPTRequest struct {
    Model    string   `json:"model"`
    Messages []string `json:"messages"`
}

// GPTResponse 是从OpenAI获取的响应结构体
type GPTResponse struct {
    ID      string `json:"id"`
    Object  string `json:"object"`
    Created int64  `json:"created"`
    Choices []struct {
        Text string `json:"text"`
    } `json:"choices"`
}

// HistoryRecord 用于存储对话记录
type HistoryRecord struct {
    ID        string `json:"id"`
    UserInput string `json:"user_input"`
    GPTResponse string `json:"gpt_response"`
    Timestamp int64  `json:"timestamp"`
}


```

### 3.3 编写逻辑层 (`logic/gpt_logic.go`)

逻辑层负责处理业务逻辑,包括发送请求到OpenAI和保存对话记录。```go

package logic

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "time"
    "myservice/types"
    "myservice/service/internal/svc"
    "myservice/service/internal/config"
    "log"
)

type GPTLogic struct {
    ctx    context.Context
    svcCtx *svc.ServiceContext
}

func NewGPTLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GPTLogic {
    return &GPTLogic{
        ctx:    ctx,
        svcCtx: svcCtx,
    }
}

// CallGPT 向OpenAI发送请求并返回结果
func (l *GPTLogic) CallGPT(req *types.GPTRequest) (*types.GPTResponse, error) {
    // 构造请求体
    url := l.svcCtx.Config.GPT.Endpoint
    body, err := json.Marshal(req)
    if err != nil {
        return nil, fmt.Errorf("failed to marshal request: %v", err)
    }

    // 创建HTTP请求
    httpReq, err := http.NewRequest("POST", url, bytes.NewReader(body))
    if err != nil {
        return nil, fmt.Errorf("failed to create HTTP request: %v", err)
    }

    // 设置请求头
    httpReq.Header.Set("Content-Type", "application/json")
    httpReq.Header.Set("Authorization", "Bearer "+l.svcCtx.Config.GPT.ApiKey)

    // 发送请求
    client := &http.Client{}
    resp, err := client.Do(httpReq)
    if err != nil {
        return nil, fmt.Errorf("failed to send request: %v", err)
    }
    defer resp.Body.Close()

    // 解析响应
    var gptResp types.GPTResponse
    if err := json.NewDecoder(resp.Body).Decode(&gptResp); err != nil {
        return nil, fmt.Errorf("failed to decode response: %v", err)
    }

    // 记录对话
    record := types.HistoryRecord{
        ID:         gptResp.ID,
        UserInput:  req.Messages[0],
        GPTResponse: gptResp.Choices[0].Text,
        Timestamp:  time.Now().Unix(),
    }
    l.saveHistory(record)

    return &gptResp, nil
}

// saveHistory 将对话记录保存到数据库(示例中简单打印)
func (l *GPTLogic) saveHistory(record types.HistoryRecord) {
    // 此处可以改为保存到数据库,例如使用ORM或数据库驱动
    log.Printf("Saved conversation record: %+v", record)
}


```

### 3.4 创建服务上下文 (`svc/service_context.go`)

服务上下文用于管理配置和服务实例的生命周期。我们将在其中加载配置文件。```go

package svc

import (
    "myservice/service/internal/config"
    "github.com/zeromicro/go-zero/zrpc"
)

type ServiceContext struct {
    Config config.Config
    Zrpc   zrpc.Client
}

func NewServiceContext(c config.Config) *ServiceContext {
    return &ServiceContext{
        Config: c,
    }
}


```

### 3.5 定义API处理器 (`handler/gpt_handler.go`)

处理HTTP请求,接收来自用户的消息,调用GPT接口并返回响应。```go

package handler

import (
    "fmt"
    "net/http"
    "myservice/types"
    "myservice/service/internal/logic"
    "myservice/service/internal/svc"
    "encoding/json"
    "github.com/zeromicro/go-zero/rest"
)

func CallGPTHandler(ctx *svc.ServiceContext) rest.Handler {
    return func(w http.ResponseWriter, r *http.Request) {
        var req types.GPTRequest
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, fmt.Sprintf("Invalid request: %v", err), http.StatusBadRequest)
            return
        }

        // 调用GPT接口
        logic := logic.NewGPTLogic(r.Context(), ctx)
        gptResp, err := logic.CallGPT(&req)
        if err != nil {
            http.Error(w, fmt.Sprintf("Error calling GPT: %v", err), http.StatusInternalServerError)
            return
        }

        // 返回GPT响应
        respData := map[string]interface{}{
            "response": gptResp.Choices[0].Text,
        }
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(respData)
    }
}


```

### 3.6 启动服务器 (`main.go`)

最后,我们需要启动HTTP服务器来提供对话记录的API。```go

package main

import (
    "fmt"
    "log"
    "net/http"
    "myservice/service/internal/config"
    "myservice/service/internal/svc"
    "myservice/service/internal/handler"
    "github.com/zeromicro/go-zero/rest"
)

func main() {
    // 加载配置
    c := config.Config{
        Name:   "myservice",
        Host:   "0.0.0.0",
        Port:   8080,
        GPT:    config.GPTConfig{ApiKey: "your-openai-api-key", Endpoint: "https://api.openai.com/v1/completions"},
    }
    ctx := svc.NewServiceContext(c)

    // 创建REST服务
    server := rest.MustNewServer(c)
    defer server.Stop()

    // 注册API处理器
    server.AddRoute(rest.Route{
        Method:  http.MethodPost,
        Path:    "/callgpt",
        Handler: handler.CallGPTHandler(ctx),
    })

    // 启动服务器
    log.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
    if err := server.Start(); err != nil {
        log.Fatal(fmt.Sprintf("Failed to start server: %v", err))
    }
}


```

### 3.7 启动服务

运行以下命令来启动服务:

```bash

go run main.go


```

现在,服务已经启动,并且可以接受POST请求。你可以通过以下请求调用GPT并保存对话记录:

```bash

curl -X POST http://localhost:8080/callgpt \
    -d '{"model": "text-davinci-003", "messages}'

启动服务

运行main.go后,服务会启动并监听在8080端口,客户端可以通过HTTP POST请求与GPT进行对话。

总结

该项目展示了如何通过GoZero框架搭建一个简单的微服务,它能够调用OpenAI的GPT接口,并保存每次交互的历史记录。关键流程包括配置管理、API请求处理和对话记录保存,确保服务具有可扩展性和易维护性。

;