CaIon 1 год назад
Родитель
Сommit
bdc65bdba2
4 измененных файлов с 68 добавлено и 22 удалено
  1. 16 15
      common/model-ratio.go
  2. 23 7
      dto/text_response.go
  3. 12 0
      relay/channel/openai/relay-openai.go
  4. 17 0
      service/token_counter.go

+ 16 - 15
common/model-ratio.go

@@ -12,23 +12,24 @@ import (
 // TODO: when a new api is enabled, check the pricing here
 // 1 === $0.002 / 1K tokens
 // 1 === ¥0.014 / 1k tokens
+
 var DefaultModelRatio = map[string]float64{
 	//"midjourney":                50,
-	"gpt-4-gizmo-*":                15,
-	"gpt-4":                        15,
-	"gpt-4-0314":                   15,
-	"gpt-4-0613":                   15,
-	"gpt-4-32k":                    30,
-	"gpt-4-32k-0314":               30,
-	"gpt-4-32k-0613":               30,
-	"gpt-4-1106-preview":           5,    // $0.01 / 1K tokens
-	"gpt-4-0125-preview":           5,    // $0.01 / 1K tokens
-	"gpt-4-turbo-preview":          5,    // $0.01 / 1K tokens
-	"gpt-4-vision-preview":         5,    // $0.01 / 1K tokens
-	"gpt-4-1106-vision-preview":    5,    // $0.01 / 1K tokens
-	"gpt-4-turbo":                  5,    // $0.01 / 1K tokens
-	"gpt-3.5-turbo":                0.25, // $0.0015 / 1K tokens
-	"gpt-3.5-turbo-0301":           0.75,
+	"gpt-4-gizmo-*": 15,
+	"gpt-4":         15,
+	//"gpt-4-0314":                   15, //deprecated
+	"gpt-4-0613": 15,
+	"gpt-4-32k":  30,
+	//"gpt-4-32k-0314":               30, //deprecated
+	"gpt-4-32k-0613":            30,
+	"gpt-4-1106-preview":        5,    // $0.01 / 1K tokens
+	"gpt-4-0125-preview":        5,    // $0.01 / 1K tokens
+	"gpt-4-turbo-preview":       5,    // $0.01 / 1K tokens
+	"gpt-4-vision-preview":      5,    // $0.01 / 1K tokens
+	"gpt-4-1106-vision-preview": 5,    // $0.01 / 1K tokens
+	"gpt-4-turbo":               5,    // $0.01 / 1K tokens
+	"gpt-3.5-turbo":             0.25, // $0.0015 / 1K tokens
+	//"gpt-3.5-turbo-0301":           0.75, //deprecated
 	"gpt-3.5-turbo-0613":           0.75,
 	"gpt-3.5-turbo-16k":            1.5, // $0.003 / 1K tokens
 	"gpt-3.5-turbo-16k-0613":       1.5,

+ 23 - 7
dto/text_response.go

@@ -54,13 +54,29 @@ type OpenAIEmbeddingResponse struct {
 }
 
 type ChatCompletionsStreamResponseChoice struct {
-	Delta struct {
-		Content   string `json:"content"`
-		Role      string `json:"role,omitempty"`
-		ToolCalls any    `json:"tool_calls,omitempty"`
-	} `json:"delta"`
-	FinishReason *string `json:"finish_reason,omitempty"`
-	Index        int     `json:"index,omitempty"`
+	Delta        ChatCompletionsStreamResponseChoiceDelta `json:"delta"`
+	FinishReason *string                                  `json:"finish_reason,omitempty"`
+	Index        int                                      `json:"index,omitempty"`
+}
+
+type ChatCompletionsStreamResponseChoiceDelta struct {
+	Content   string     `json:"content"`
+	Role      string     `json:"role,omitempty"`
+	ToolCalls []ToolCall `json:"tool_calls,omitempty"`
+}
+
+type ToolCall struct {
+	// Index is not nil only in chat completion chunk object
+	Index    *int         `json:"index,omitempty"`
+	ID       string       `json:"id"`
+	Type     any          `json:"type"`
+	Function FunctionCall `json:"function"`
+}
+
+type FunctionCall struct {
+	Name string `json:"name,omitempty"`
+	// call function with arguments in JSON format
+	Arguments string `json:"arguments,omitempty"`
 }
 
 type ChatCompletionsStreamResponse struct {

+ 12 - 0
relay/channel/openai/relay-openai.go

@@ -68,6 +68,12 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
 					if err == nil {
 						for _, choice := range streamResponse.Choices {
 							responseTextBuilder.WriteString(choice.Delta.Content)
+							if choice.Delta.ToolCalls != nil {
+								for _, tool := range choice.Delta.ToolCalls {
+									responseTextBuilder.WriteString(tool.Function.Name)
+									responseTextBuilder.WriteString(tool.Function.Arguments)
+								}
+							}
 						}
 					}
 				}
@@ -75,6 +81,12 @@ func OpenaiStreamHandler(c *gin.Context, resp *http.Response, relayMode int) (*d
 				for _, streamResponse := range streamResponses {
 					for _, choice := range streamResponse.Choices {
 						responseTextBuilder.WriteString(choice.Delta.Content)
+						if choice.Delta.ToolCalls != nil {
+							for _, tool := range choice.Delta.ToolCalls {
+								responseTextBuilder.WriteString(tool.Function.Name)
+								responseTextBuilder.WriteString(tool.Function.Arguments)
+							}
+						}
 					}
 				}
 			}

+ 17 - 0
service/token_counter.go

@@ -211,6 +211,23 @@ func CountTokenInput(input any, model string, check bool) (int, error, bool) {
 	return CountTokenInput(fmt.Sprintf("%v", input), model, check)
 }
 
+func CountTokenStreamChoices(messages []dto.ChatCompletionsStreamResponseChoice, model string) int {
+	tokens := 0
+	for _, message := range messages {
+		tkm, _, _ := CountTokenInput(message.Delta.Content, model, false)
+		tokens += tkm
+		if message.Delta.ToolCalls != nil {
+			for _, tool := range message.Delta.ToolCalls {
+				tkm, _, _ := CountTokenInput(tool.Function.Name, model, false)
+				tokens += tkm
+				tkm, _, _ = CountTokenInput(tool.Function.Arguments, model, false)
+				tokens += tkm
+			}
+		}
+	}
+	return tokens
+}
+
 func CountAudioToken(text string, model string, check bool) (int, error, bool) {
 	if strings.HasPrefix(model, "tts") {
 		contains, words := SensitiveWordContains(text)