Browse Source

增加 gptbots 接口

boweniac 3 months ago
parent
commit
7f96d26d1a

+ 19 - 1
desc/wechat/xiaoice.api

@@ -4,7 +4,21 @@ type (
     SignatureResp {
         BaseDataInfo
 
-        // Sts information | Sts 数据
+        // 临时签名
+        Data *string `json:"data"`
+    }
+
+    MessageReq {
+        // 大模型生成内容
+        UserId *uint64 `json:"user_id"`
+
+        Text *string `json:"text"`
+    }
+
+    MessageResp {
+        BaseDataInfo
+
+        // 大模型生成内容
         Data *string `json:"data"`
     }
 )
@@ -17,4 +31,8 @@ service Wechat {
 	// get xiaoice signature | 获取小冰签名
     @handler signatureGen
     get /api/xiaoice/signature () returns (SignatureResp)
+
+    // gen gptbots | 调用gptbots
+    @handler gptbotsMessage
+    post /api/xiaoice/message (MessageReq) returns (MessageResp)
 }

+ 5 - 0
internal/handler/routes.go

@@ -1480,6 +1480,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				Path:    "/api/xiaoice/signature",
 				Handler: xiaoice.SignatureGenHandler(serverCtx),
 			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/api/xiaoice/message",
+				Handler: xiaoice.GptbotsMessageHandler(serverCtx),
+			},
 		},
 	)
 }

+ 44 - 0
internal/handler/xiaoice/gptbots_message_handler.go

@@ -0,0 +1,44 @@
+package xiaoice
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/xiaoice"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route get /api/xiaoice/message xiaoice GptbotsMessage
+//
+// gen gptbots | 调用gptbots
+//
+// gen gptbots | 调用gptbots
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: MessageReq
+//
+// Responses:
+//  200: MessageResp
+
+func GptbotsMessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.MessageReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := xiaoice.NewGptbotsMessageLogic(r.Context(), svcCtx)
+		resp, err := l.GptbotsMessage(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 165 - 0
internal/logic/xiaoice/gptbots_message_logic.go

@@ -0,0 +1,165 @@
+package xiaoice
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"io"
+	"net/http"
+	"net/url"
+	"strconv"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GptbotsMessageLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGptbotsMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GptbotsMessageLogic {
+	return &GptbotsMessageLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GptbotsMessageLogic) GptbotsMessage(req *types.MessageReq) (resp *types.MessageResp, err error) {
+	apikey := l.svcCtx.Config.Xiaoice.GptbotsAuthorization
+	conversationId, err := l.GetConversation(apikey, strconv.FormatUint(*req.UserId, 10))
+	if conversationId == nil || err != nil {
+		return nil, err
+	}
+
+	baseURL, err := url.Parse("https://api.gptbots.ai/v1/conversation/message")
+	if err != nil {
+		return nil, err
+	}
+
+	// 构建请求体
+	requestBody := map[string]string{
+		"text":            *req.Text,
+		"conversation_id": *conversationId,
+		"response_mode":   "blocking",
+	}
+	jsonBody, err := json.Marshal(requestBody)
+	if err != nil {
+		return nil, err
+	}
+
+	// 创建HTTP请求
+	httpReq, err := http.NewRequest("POST", baseURL.String(), bytes.NewBuffer(jsonBody))
+	if err != nil {
+		return nil, err
+	}
+
+	// 添加必要的Header信息
+	httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apikey))
+	httpReq.Header.Set("Content-Type", "application/json")
+
+	// 创建HTTP客户端并执行请求
+	client := &http.Client{}
+	response, err := client.Do(httpReq)
+	if err != nil {
+		return nil, err
+	}
+	defer func(Body io.ReadCloser) {
+		err := Body.Close()
+		if err != nil {
+			l.Error("生成内容失败: %v", err)
+		}
+	}(response.Body)
+
+	// 读取和输出响应
+	body, err := io.ReadAll(response.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	// 检查响应状态
+	if response.StatusCode != http.StatusOK {
+		//log.Fatalf("请求失败,状态码:%d,响应: %s", response.StatusCode, string(body))
+		return nil, errorx.NewDefaultError(fmt.Sprintf("生成内容失败:%d,响应: %s", response.StatusCode, string(body)))
+	}
+
+	// 解析 JSON 响应
+	var responseMap types.GptbotsMessageResp
+	if err := json.Unmarshal(body, &responseMap); err != nil {
+		return nil, err
+	}
+
+	data := ""
+	if responseMap.FlowOutput != nil && len(responseMap.FlowOutput) > 0 {
+		data = responseMap.FlowOutput[0].Content
+	}
+
+	return &types.MessageResp{Data: &data}, nil
+}
+
+func (l *GptbotsMessageLogic) GetConversation(apikey string, userId string) (conversationId *string, err error) {
+	val, _ := l.svcCtx.Rds.HGet(l.ctx, "xiaoice_conversation", userId).Result()
+	if val == "" {
+		baseURL, err := url.Parse("https://api.gptbots.ai/v1/conversation")
+		if err != nil {
+			return nil, err
+		}
+
+		// 构建请求体
+		requestBody := map[string]string{
+			"user_id": userId,
+		}
+		jsonBody, err := json.Marshal(requestBody)
+		if err != nil {
+			return nil, err
+		}
+
+		// 创建HTTP请求
+		req, err := http.NewRequest("POST", baseURL.String(), bytes.NewBuffer(jsonBody))
+		if err != nil {
+			return nil, err
+		}
+
+		// 添加必要的Header信息
+		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apikey))
+		req.Header.Set("Content-Type", "application/json")
+
+		// 创建HTTP客户端并执行请求
+		client := &http.Client{}
+		response, err := client.Do(req)
+		if err != nil {
+			return nil, err
+		}
+		defer func(Body io.ReadCloser) {
+			err := Body.Close()
+			if err != nil {
+				l.Error("创建会话失败败: %v", err)
+			}
+		}(response.Body)
+
+		// 读取和输出响应
+		body, err := io.ReadAll(response.Body)
+		if err != nil {
+			return nil, err
+		}
+
+		// 检查响应状态
+		if response.StatusCode != http.StatusOK {
+			//log.Fatalf("请求失败,状态码:%d,响应: %s", response.StatusCode, string(body))
+			return nil, errorx.NewDefaultError(fmt.Sprintf("创建会话失败:%d,响应: %s", response.StatusCode, string(body)))
+		}
+
+		// 解析 JSON 响应
+		var responseMap types.ConversationResp
+		if err := json.Unmarshal(body, &responseMap); err != nil {
+			return nil, err
+		}
+		l.svcCtx.Rds.HSet(l.ctx, "xiaoice_conversation", userId, *responseMap.ConversationId)
+		return responseMap.ConversationId, nil
+	}
+	return &val, nil
+}

+ 15 - 1
internal/types/types.go

@@ -2894,6 +2894,20 @@ type UsageTotalListReq struct {
 // swagger:model SignatureResp
 type SignatureResp struct {
 	BaseDataInfo
-	// Sts information | Sts 数据
+	// 临时签名
+	Data *string `json:"data"`
+}
+
+// swagger:model MessageReq
+type MessageReq struct {
+	// 大模型生成内容
+	UserId *uint64 `json:"user_id"`
+	Text   *string `json:"text"`
+}
+
+// swagger:model MessageResp
+type MessageResp struct {
+	BaseDataInfo
+	// 大模型生成内容
 	Data *string `json:"data"`
 }

+ 21 - 1
internal/types/xiaoice.go

@@ -1,7 +1,8 @@
 package types
 
 type Xiaoice struct {
-	SubscriptionKey string
+	SubscriptionKey      string
+	GptbotsAuthorization string
 }
 
 type XiaoiceSignatureResp struct {
@@ -9,3 +10,22 @@ type XiaoiceSignatureResp struct {
 	Data string `json:"data"`
 	Msg  string `json:"msg"`
 }
+
+type ConversationResp struct {
+	ConversationId *string `json:"conversation_id"`
+}
+
+type GptbotsMessageResp struct {
+	MessageID      string       `json:"message_id"`
+	MessageType    string       `json:"message_type"`
+	Text           string       `json:"text"`
+	FlowOutput     []FlowOutput `json:"flow_output"`
+	CreateTime     int64        `json:"create_time"`
+	ConversationID *string      `json:"conversation_id"`
+}
+
+type FlowOutput struct {
+	Content           string `json:"content"`
+	Branch            string `json:"branch"`
+	FromComponentName string `json:"from_component_name"`
+}