package tencent import ( "crypto/hmac" "crypto/sha1" "encoding/base64" "encoding/json" "errors" "fmt" "net/http" "one-api/common/requester" "one-api/model" "one-api/providers/base" "one-api/types" "sort" "strconv" "strings" ) type TencentProviderFactory struct{} // 创建 TencentProvider func (f TencentProviderFactory) Create(channel *model.Channel) base.ProviderInterface { return &TencentProvider{ BaseProvider: base.BaseProvider{ Config: getConfig(), Channel: channel, Requester: requester.NewHTTPRequester(channel.Proxy, requestErrorHandle), }, } } type TencentProvider struct { base.BaseProvider } func getConfig() base.ProviderConfig { return base.ProviderConfig{ BaseURL: "https://hunyuan.cloud.tencent.com", ChatCompletions: "/hyllm/v1/chat/completions", } } // 请求错误处理 func requestErrorHandle(resp *http.Response) *types.OpenAIError { tencentError := &TencentResponseError{} err := json.NewDecoder(resp.Body).Decode(tencentError) if err != nil { return nil } return errorHandle(tencentError) } // 错误处理 func errorHandle(tencentError *TencentResponseError) *types.OpenAIError { if tencentError.Error.Code == 0 { return nil } return &types.OpenAIError{ Message: tencentError.Error.Message, Type: "tencent_error", Code: tencentError.Error.Code, } } // 获取请求头 func (p *TencentProvider) GetRequestHeaders() (headers map[string]string) { headers = make(map[string]string) p.CommonRequestHeaders(headers) return headers } func (p *TencentProvider) parseTencentConfig(config string) (appId int64, secretId string, secretKey string, err error) { parts := strings.Split(config, "|") if len(parts) != 3 { err = errors.New("invalid tencent config") return } appId, err = strconv.ParseInt(parts[0], 10, 64) secretId = parts[1] secretKey = parts[2] return } func (p *TencentProvider) getTencentSign(req TencentChatRequest) string { apiKey := p.Channel.Key appId, secretId, secretKey, err := p.parseTencentConfig(apiKey) if err != nil { return "" } req.AppId = appId req.SecretId = secretId params := make([]string, 0) params = append(params, "app_id="+strconv.FormatInt(req.AppId, 10)) params = append(params, "secret_id="+req.SecretId) params = append(params, "timestamp="+strconv.FormatInt(req.Timestamp, 10)) params = append(params, "query_id="+req.QueryID) params = append(params, "temperature="+strconv.FormatFloat(req.Temperature, 'f', -1, 64)) params = append(params, "top_p="+strconv.FormatFloat(req.TopP, 'f', -1, 64)) params = append(params, "stream="+strconv.Itoa(req.Stream)) params = append(params, "expired="+strconv.FormatInt(req.Expired, 10)) var messageStr string for _, msg := range req.Messages { messageStr += fmt.Sprintf(`{"role":"%s","content":"%s"},`, msg.Role, msg.Content) } messageStr = strings.TrimSuffix(messageStr, ",") params = append(params, "messages=["+messageStr+"]") sort.Strings(params) url := "hunyuan.cloud.tencent.com/hyllm/v1/chat/completions?" + strings.Join(params, "&") mac := hmac.New(sha1.New, []byte(secretKey)) signURL := url mac.Write([]byte(signURL)) sign := mac.Sum([]byte(nil)) return base64.StdEncoding.EncodeToString(sign) }