From eedc8db4b965b5aa27682b2f371dcc9b1d271d6e Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Mon, 20 Nov 2023 11:55:47 +0800 Subject: [PATCH] fix markdown table overflow bug and add function chatgpt adapter calling feature --- adapter/chatgpt/chat.go | 40 ++++++++++++++++------------------ adapter/chatgpt/test.go | 2 +- adapter/chatgpt/types.go | 33 +++++++++++----------------- adapter/request.go | 4 ++-- addition/web/utils.go | 4 ++-- app/src/assets/pages/chat.less | 3 +++ app/src/assets/pages/home.less | 3 ++- app/src/conf.ts | 2 +- globals/constant.go | 1 + globals/tools.go | 40 ++++++++++++++++++++++++++++++++++ globals/types.go | 6 +++-- utils/base.go | 4 ++++ 12 files changed, 92 insertions(+), 50 deletions(-) create mode 100644 globals/tools.go diff --git a/adapter/chatgpt/chat.go b/adapter/chatgpt/chat.go index 226e6ef..2942bb0 100644 --- a/adapter/chatgpt/chat.go +++ b/adapter/chatgpt/chat.go @@ -8,9 +8,14 @@ import ( ) type ChatProps struct { - Model string - Message []globals.Message - Token int + Model string + Message []globals.Message + Token *int + PresencePenalty *float32 `json:"presence_penalty"` + FrequencyPenalty *float32 `json:"frequency_penalty"` + Temperature *float32 `json:"temperature"` + TopP *float32 `json:"top_p"` + ToolChoice *interface{} `json:"tool_choice"` // string or object } func (c *ChatInstance) GetChatEndpoint(props *ChatProps) string { @@ -39,31 +44,24 @@ func (c *ChatInstance) GetLatestPrompt(props *ChatProps) string { func (c *ChatInstance) GetChatBody(props *ChatProps, stream bool) interface{} { if props.Model == globals.GPT3TurboInstruct { // for completions - return utils.Multi[interface{}](props.Token != -1, CompletionRequest{ + return CompletionRequest{ Model: props.Model, Prompt: c.GetCompletionPrompt(props.Message), MaxToken: props.Token, Stream: stream, - }, CompletionWithInfinity{ - Model: props.Model, - Prompt: c.GetCompletionPrompt(props.Message), - Stream: stream, - }) - } - - if props.Token != -1 { - return ChatRequest{ - Model: props.Model, - Messages: formatMessages(props), - MaxToken: props.Token, - Stream: stream, } } - return ChatRequestWithInfinity{ - Model: props.Model, - Messages: formatMessages(props), - Stream: stream, + return ChatRequest{ + Model: props.Model, + Messages: formatMessages(props), + MaxToken: props.Token, + Stream: stream, + PresencePenalty: props.PresencePenalty, + FrequencyPenalty: props.FrequencyPenalty, + Temperature: props.Temperature, + TopP: props.TopP, + ToolChoice: props.ToolChoice, } } diff --git a/adapter/chatgpt/test.go b/adapter/chatgpt/test.go index ad0fd90..221ecdc 100644 --- a/adapter/chatgpt/test.go +++ b/adapter/chatgpt/test.go @@ -12,7 +12,7 @@ func (c *ChatInstance) Test() bool { result, err := c.CreateChatRequest(&ChatProps{ Model: globals.GPT3Turbo, Message: []globals.Message{{Role: globals.User, Content: "hi"}}, - Token: 1, + Token: utils.ToPtr(1), }) if err != nil { fmt.Println(fmt.Sprintf("%s: test failed (%s)", c.GetApiKey(), err.Error())) diff --git a/adapter/chatgpt/types.go b/adapter/chatgpt/types.go index e68e5fb..dc711ae 100644 --- a/adapter/chatgpt/types.go +++ b/adapter/chatgpt/types.go @@ -6,30 +6,24 @@ import "chat/globals" type ChatRequest struct { Model string `json:"model"` Messages []globals.Message `json:"messages"` - MaxToken int `json:"max_tokens"` + MaxToken *int `json:"max_tokens"` Stream bool `json:"stream"` -} -type ChatRequestWithInfinity struct { - Model string `json:"model"` - Messages []globals.Message `json:"messages"` - Stream bool `json:"stream"` + PresencePenalty *float32 `json:"presence_penalty"` + FrequencyPenalty *float32 `json:"frequency_penalty"` + Temperature *float32 `json:"temperature"` + TopP *float32 `json:"top_p"` + ToolChoice *interface{} `json:"tool_choice"` // string or object } // CompletionRequest ChatRequest is the request body for chatgpt completion type CompletionRequest struct { Model string `json:"model"` Prompt string `json:"prompt"` - MaxToken int `json:"max_tokens"` + MaxToken *int `json:"max_tokens"` Stream bool `json:"stream"` } -type CompletionWithInfinity struct { - Model string `json:"model"` - Prompt string `json:"prompt"` - Stream bool `json:"stream"` -} - // ChatResponse is the native http request body for chatgpt type ChatResponse struct { ID string `json:"id"` @@ -37,9 +31,9 @@ type ChatResponse struct { Created int64 `json:"created"` Model string `json:"model"` Choices []struct { - Message struct { - Content string `json:"content"` - } + Index int `json:"index"` + Message globals.Message `json:"message"` + FinishReason string `json:"finish_reason"` } `json:"choices"` Error struct { Message string `json:"message"` @@ -54,10 +48,9 @@ type ChatStreamResponse struct { Model string `json:"model"` Data struct { Choices []struct { - Delta struct { - Content string `json:"content"` - } - Index int `json:"index"` + Delta globals.Message `json:"delta"` + Index int `json:"index"` + FinishReason string `json:"finish_reason"` } `json:"choices"` } `json:"data"` } diff --git a/adapter/request.go b/adapter/request.go index b07cdb7..b19bd4d 100644 --- a/adapter/request.go +++ b/adapter/request.go @@ -28,8 +28,8 @@ func retryChatGPTPool(props *ChatProps, hook globals.Hook, retry int) error { Message: props.Message, Token: utils.Multi( props.Token == 0, - utils.Multi(globals.IsGPT4Model(props.Model) || props.Plan || props.Infinity, -1, 2500), - props.Token, + utils.Multi(globals.IsGPT4Model(props.Model) || props.Plan || props.Infinity, nil, utils.ToPtr(2500)), + &props.Token, ), }, hook) diff --git a/addition/web/utils.go b/addition/web/utils.go index e64030f..e1af5d2 100644 --- a/addition/web/utils.go +++ b/addition/web/utils.go @@ -14,7 +14,7 @@ func UsingWebSegment(instance *conversation.Conversation) []globals.Message { return chatgpt.NewChatInstanceFromConfig("gpt3").CreateChatRequest(&chatgpt.ChatProps{ Model: globals.GPT3TurboInstruct, Message: message, - Token: token, + Token: &token, }) }, segment, globals.IsLongContextModel(instance.GetModel())) } @@ -28,7 +28,7 @@ func UsingWebNativeSegment(enable bool, message []globals.Message) []globals.Mes return chatgpt.NewChatInstanceFromConfig("gpt3").CreateChatRequest(&chatgpt.ChatProps{ Model: globals.GPT3TurboInstruct, Message: message, - Token: token, + Token: &token, }) }, message, false) } else { diff --git a/app/src/assets/pages/chat.less b/app/src/assets/pages/chat.less index 082dbd9..b5f8310 100644 --- a/app/src/assets/pages/chat.less +++ b/app/src/assets/pages/chat.less @@ -64,6 +64,7 @@ .content-wrapper { display: flex; flex-direction: row; + max-width: 100%; .message-toolbar { display: flex; @@ -124,6 +125,8 @@ .message-content { display: flex; + flex: 1 1 auto; + min-width: 0; flex-direction: column; max-width: 100%; padding: 8px 16px; diff --git a/app/src/assets/pages/home.less b/app/src/assets/pages/home.less index 401ad75..4a4a2cc 100644 --- a/app/src/assets/pages/home.less +++ b/app/src/assets/pages/home.less @@ -505,7 +505,8 @@ } .chat-container { - flex-grow: 1; + flex: 1 1 auto; + min-width: 0; height: 100%; background: hsl(var(--background-container)); transition: width 0.2s ease-in-out; diff --git a/app/src/conf.ts b/app/src/conf.ts index d37f43d..3fa9ff8 100644 --- a/app/src/conf.ts +++ b/app/src/conf.ts @@ -8,7 +8,7 @@ import { } from "@/utils/env.ts"; import { getMemory } from "@/utils/memory.ts"; -export const version = "3.6.31"; +export const version = "3.6.32"; export const dev: boolean = getDev(); export const deploy: boolean = true; export let rest_api: string = getRestApi(deploy); diff --git a/globals/constant.go b/globals/constant.go index bc5a3dc..b763e83 100644 --- a/globals/constant.go +++ b/globals/constant.go @@ -4,4 +4,5 @@ const ( System = "system" User = "user" Assistant = "assistant" + Tool = "tool" ) diff --git a/globals/tools.go b/globals/tools.go new file mode 100644 index 0000000..74a0a35 --- /dev/null +++ b/globals/tools.go @@ -0,0 +1,40 @@ +package globals + +type ToolCallId string +type FunctionTools []FunctionTool +type FunctionTool struct { + Type string `json:"type"` + Function ToolFunction `json:"function"` +} + +type ToolFunction struct { + Name string `json:"name"` + Description string `json:"description"` + Parameters ToolParameters `json:"parameters"` +} + +type ToolParameters struct { + Type string `json:"type"` + Properties ToolProperties `json:"properties"` + Required []string `json:"required"` +} + +type ToolProperties map[string]ToolProperty + +type ToolProperty struct { + Type string `json:"type"` + Description string `json:"description"` + Enum []string `json:"enum"` +} + +type ToolCallFunction struct { + Name string `json:"name"` + Arguments string `json:"arguments"` +} + +type ToolCall struct { + Type string `json:"type"` + Id ToolCallId `json:"id"` + Function ToolCallFunction `json:"function"` +} +type ToolCalls []ToolCall diff --git a/globals/types.go b/globals/types.go index af318c2..65b911d 100644 --- a/globals/types.go +++ b/globals/types.go @@ -2,8 +2,10 @@ package globals type Hook func(data string) error type Message struct { - Role string `json:"role"` - Content string `json:"content"` + Role string `json:"role"` + Content string `json:"content"` + ToolCallId *string `json:"tool_call_id"` // only `tool` role + ToolCalls *ToolCalls `json:"tool_calls"` // only `assistant` role } type ChatSegmentResponse struct { diff --git a/utils/base.go b/utils/base.go index c3bb625..37e67b9 100644 --- a/utils/base.go +++ b/utils/base.go @@ -23,6 +23,10 @@ func Contains[T comparable](value T, slice []T) bool { return false } +func ToPtr[T any](value T) *T { + return &value +} + func TryGet[T any](arr []T, index int) T { if index >= len(arr) { return arr[0]