Explorar el Código

Merge branch 'feature/xiaoice'

* feature/xiaoice:
  取出输出文本中的markdown格式
  优化gptbots接口
  增加 gptbots 接口
  修复获取小冰AuthToken问题
  增加小冰签名接口
boweniac hace 4 meses
padre
commit
3fbb88d98b

+ 2 - 1
desc/all.api

@@ -32,4 +32,5 @@ import "./wechat/avatar.api"
 import "./wechat/aliyun_avatar.api"
 import "./wechat/workphone.api"
 import "./wechat/usage_detail.api"
-import "./wechat/usage_total.api"
+import "./wechat/usage_total.api"
+import "./wechat/xiaoice.api"

+ 31 - 0
desc/wechat/xiaoice.api

@@ -0,0 +1,31 @@
+import "../base.api"
+
+type (
+    SignatureResp {
+        BaseDataInfo
+
+        // 临时签名
+        Data *string `json:"data"`
+    }
+
+    MessageReq {
+        // 大模型生成内容
+        UserId *uint64 `json:"user_id"`
+
+        Text *string `json:"text"`
+    }
+)
+
+@server(
+	group: xiaoice
+)
+
+service Wechat {
+	// get xiaoice signature | 获取小冰签名
+    @handler signatureGen
+    get /api/xiaoice/signature () returns (SignatureResp)
+
+    // gen gptbots | 调用gptbots
+    @handler gptbotsMessage
+    post /api/xiaoice/message (MessageReq) returns (BaseDataInfo)
+}

+ 0 - 83
etc/wechat-docker.yaml

@@ -1,83 +0,0 @@
-Name: Wechat.api
-Host: 0.0.0.0
-Port: 19101
-Timeout: 30000
-
-Mode: "dev"
-
-Auth:
-  AccessSecret: LnQD46hBde0AgFXBer8ZZZe3FgC
-  AccessExpire: 259200
-
-CROSConf:
-  Address: '*'
-
-Log:
-  ServiceName: WechatApiLogger
-  Mode: console
-  Encoding: plain
-  Stat: false
-  Path: /tmp
-  Level: info
-  Compress: false
-  KeepDays: 7
-  StackCoolDownMillis: 100
-
-DatabaseConf:
-  Type: mysql
-  Host: scrm-mysql
-  Port: 3306
-  DBName: wechat
-  Username: root
-  Password: simple-admin.
-  MaxOpenConn: 100
-  SSLMode: disable
-  CacheTime: 5
-
-CoreRpc:
-  # Target: k8s://default/core-rpc-svc:9101
-  Endpoints:
-    - core-rpc:9101
-  Enabled: true
-
-RedisConf:
-  Host: scrm-redis:6379
-
-CasbinDatabaseConf:
-  Type: mysql
-  Host: scrm-mysql
-  Port: 3306
-  DBName: wechat-admin
-  Username: root
-  Password: simple-admin.
-  MaxOpenConn: 100
-  SSLMode: disable
-  CacheTime: 5
-
-CasbinConf:
-  ModelText: |
-    [request_definition]
-    r = sub, obj, act
-    [policy_definition]
-    p = sub, obj, act
-    [role_definition]
-    g = _, _
-    [policy_effect]
-    e = some(where (p.eft == allow))
-    [matchers]
-    m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act
-
-Miniprogram:
-  Appid: wx1452f34bba8fe718
-  Secret: 171fdab212fdde0d51b59fa59c9ee070
-  redisaddr: scrm-redis:6379
-
-Aliyun:
-  ACCESS_KEY_ID: LTAI5tSJwCQyuaxXR3UxfnWw
-  ACCESS_KEY_SECRET: 0pv4xhSPJv9IPSxrkB52FspJk27W7V
-  OSS_ENDPOINT: sts.cn-beijing.aliyuncs.com
-  OSS_ROLEARN: acs:ram::1317798064750399:role/ramoss
-
-Fastgpt:
-  BASE_URL: http://new-api.gkscrm.com/v1
-  API_KEY: sk-ZQRNypQOC8ID5WbpCdF263C58dF44271842e86D408Bb3848

+ 1 - 0
go.mod

@@ -18,6 +18,7 @@ require (
 	github.com/imroc/req/v3 v3.43.1
 	github.com/redis/go-redis/v9 v9.6.1
 	github.com/robfig/cron/v3 v3.0.1
+	github.com/russross/blackfriday v1.6.0
 	github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
 	github.com/sashabaranov/go-openai v1.31.0
 	github.com/speps/go-hashids/v2 v2.0.1

+ 2 - 4
go.sum

@@ -445,7 +445,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
@@ -479,7 +478,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
@@ -545,6 +543,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj
 github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
 github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
 github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
+github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
+github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
@@ -576,8 +576,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
 github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
 github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

+ 1 - 0
internal/config/config.go

@@ -20,4 +20,5 @@ type Config struct {
 	Fastgpt            types.Fastgpt
 	Aliyun             types.Aliyun
 	CoreRpc            zrpc.RpcClientConf
+	Xiaoice            types.Xiaoice
 }

+ 16 - 0
internal/handler/routes.go

@@ -39,6 +39,7 @@ import (
 	wxcard "wechat-api/internal/handler/wxcard"
 	wxcarduser "wechat-api/internal/handler/wxcarduser"
 	wxcardvisit "wechat-api/internal/handler/wxcardvisit"
+	xiaoice "wechat-api/internal/handler/xiaoice"
 	"wechat-api/internal/svc"
 
 	"github.com/zeromicro/go-zero/rest"
@@ -1471,4 +1472,19 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
+
+	server.AddRoutes(
+		[]rest.Route{
+			{
+				Method:  http.MethodGet,
+				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)
+		}
+	}
+}

+ 31 - 0
internal/handler/xiaoice/signature_gen_handler.go

@@ -0,0 +1,31 @@
+package xiaoice
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/xiaoice"
+	"wechat-api/internal/svc"
+)
+
+// swagger:route post /api/xiaoice/signature xiaoice SignatureGen
+//
+// get xiaoice signature | 获取小冰签名
+//
+// get xiaoice signature | 获取小冰签名
+//
+// Responses:
+//  200: SignatureResp
+
+func SignatureGenHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		l := xiaoice.NewSignatureGenLogic(r.Context(), svcCtx)
+		resp, err := l.SignatureGen()
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

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

@@ -0,0 +1,195 @@
+package xiaoice
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/russross/blackfriday"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"io"
+	"net/http"
+	"net/url"
+	"regexp"
+	"strconv"
+	"strings"
+	"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.BaseDataInfo, 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, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", err))
+	}
+
+	// 构建请求体
+	requestBody := map[string]string{
+		"text":            *req.Text,
+		"conversation_id": *conversationId,
+		"response_mode":   "blocking",
+	}
+	jsonBody, err := json.Marshal(requestBody)
+	if err != nil {
+		return nil, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", err))
+	}
+
+	// 创建HTTP请求
+	httpReq, err := http.NewRequest("POST", baseURL.String(), bytes.NewBuffer(jsonBody))
+	if err != nil {
+		return nil, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", 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, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", 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, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", 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, errorx.NewDefaultError(fmt.Sprintf("生成内容失败: %+v", err))
+	}
+
+	data := ""
+	if responseMap.FlowOutput != nil && len(responseMap.FlowOutput) > 0 {
+		data = TrimHtml(Markdown2Html(responseMap.FlowOutput[0].Content))
+	}
+
+	return &types.BaseDataInfo{Msg: errormsg.Success, 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
+}
+
+// TrimHtml 去除HTML标签
+func TrimHtml(html string) string {
+	//将HTML标签全转换成小写
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
+	html = re.ReplaceAllStringFunc(html, strings.ToLower)
+	//去除STYLE
+	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
+	html = re.ReplaceAllString(html, "")
+	//去除SCRIPT
+	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
+	html = re.ReplaceAllString(html, "")
+	//去除所有尖括号内的HTML代码,并换成换行符
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
+	html = re.ReplaceAllString(html, "\n")
+	//去除连续的换行符
+	re, _ = regexp.Compile("\\s{2,}")
+	html = re.ReplaceAllString(html, "\n")
+	return strings.TrimSpace(html)
+}
+
+// Markdown2Html Markdown format to HTML format
+func Markdown2Html(markdown string) string {
+	html := blackfriday.MarkdownCommon([]byte(markdown))
+	return string(html)
+}

+ 86 - 0
internal/logic/xiaoice/signature_gen_logic.go

@@ -0,0 +1,86 @@
+package xiaoice
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"io"
+	"net/http"
+	"net/url"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SignatureGenLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSignatureGenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SignatureGenLogic {
+	return &SignatureGenLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SignatureGenLogic) SignatureGen() (resp *types.SignatureResp, err error) {
+	// 构建请求URL
+	key := l.svcCtx.Config.Xiaoice.SubscriptionKey
+	baseURL, err := url.Parse("https://interactive-virtualhuman.xiaoice.com/openapi/signature/gen")
+	if err != nil {
+		return nil, err
+	}
+
+	// 在这里设置请求参数
+	//params := url.Values{}
+	// 如果需要设置 token 有效期,请取消下面注释并设置时间(以毫秒为单位)
+	//params.Add("effectiveDurationMilliseconds", strconv.Itoa(24*60*60*1000))
+	//baseURL.RawQuery = params.Encode()
+
+	// 创建 HTTP 请求
+	req, err := http.NewRequest("GET", baseURL.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// 添加必要的Header信息
+	req.Header.Add("subscription-key", key)
+
+	// 创建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("获取小冰 AuthToken 失败: %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("获取小冰 AuthToken 失败:%d,响应: %s", response.StatusCode, string(body)))
+	}
+
+	// 解析 JSON 响应
+	var responseMap types.XiaoiceSignatureResp
+	if err := json.Unmarshal(body, &responseMap); err != nil {
+		return nil, err
+	}
+
+	fmt.Printf("响应: %s\n", string(body))
+	return &types.SignatureResp{Data: &responseMap.Data}, nil
+}

+ 14 - 0
internal/types/types.go

@@ -2890,3 +2890,17 @@ type UsageTotalListReq struct {
 	// 租户id
 	OrganizationId *uint64 `json:"organizationId,optional"`
 }
+
+// swagger:model SignatureResp
+type SignatureResp struct {
+	BaseDataInfo
+	// 临时签名
+	Data *string `json:"data"`
+}
+
+// swagger:model MessageReq
+type MessageReq struct {
+	// 大模型生成内容
+	UserId *uint64 `json:"user_id"`
+	Text   *string `json:"text"`
+}

+ 31 - 0
internal/types/xiaoice.go

@@ -0,0 +1,31 @@
+package types
+
+type Xiaoice struct {
+	SubscriptionKey      string
+	GptbotsAuthorization string
+}
+
+type XiaoiceSignatureResp struct {
+	Code int64  `json:"code"`
+	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"`
+}