mirror of
https://github.com/coaidev/coai.git
synced 2025-05-20 05:20:15 +09:00
update gpt-4-vison and 32k model
This commit is contained in:
parent
0ed99d3b7e
commit
baa4754cf4
@ -61,9 +61,10 @@
|
||||
- GPT-3.5-Turbo (_0613_, _0301_)
|
||||
- GPT-3.5-Turbo-16k (_0613_, _0301_)
|
||||
- GPT-3.5-Reverse (_text-davincci-002-render-sha_, _text-davincci-002-render-paid_)
|
||||
- GPT-3.5-Turbo-Instruct
|
||||
- GPT-4 (_0314_, _0613_)
|
||||
- GPT-4-32k (_0314_, _0613_)
|
||||
- GPT-4-Reverse (_gpt-4_)
|
||||
- GPT-4-Reverse (_gpt-4_, _**gpt-4v**_)
|
||||
- DALL-E
|
||||
- Claude
|
||||
- Slack-Claude (unstable)
|
||||
@ -72,6 +73,7 @@
|
||||
- SparkDesk 讯飞星火
|
||||
- v1.5
|
||||
- v2.0
|
||||
- v3.0
|
||||
- Google PaLM2
|
||||
- Chat
|
||||
- Text
|
||||
|
@ -4,7 +4,6 @@ import "C"
|
||||
import (
|
||||
"chat/globals"
|
||||
"chat/utils"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/spf13/viper"
|
||||
"strings"
|
||||
@ -16,11 +15,36 @@ type ChatProps struct {
|
||||
Token int
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetChatEndpoint() string {
|
||||
func (c *ChatInstance) GetChatEndpoint(props *ChatProps) string {
|
||||
if props.Model == globals.GPT3TurboInstruct {
|
||||
return fmt.Sprintf("%s/v1/completions", c.GetEndpoint())
|
||||
}
|
||||
return fmt.Sprintf("%s/v1/chat/completions", c.GetEndpoint())
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetCompletionPrompt(messages []globals.Message) string {
|
||||
result := ""
|
||||
for _, message := range messages {
|
||||
result += fmt.Sprintf("%s: %s\n", message.Role, message.Content)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetChatBody(props *ChatProps, stream bool) interface{} {
|
||||
if props.Model == globals.GPT3TurboInstruct {
|
||||
// for completions
|
||||
return utils.Multi[interface{}](props.Token != -1, 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,
|
||||
@ -37,54 +61,10 @@ func (c *ChatInstance) GetChatBody(props *ChatProps, stream bool) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatInstance) ProcessLine(buf, data string) (string, error) {
|
||||
rep := strings.NewReplacer(
|
||||
"data: {",
|
||||
"\"data\": {",
|
||||
)
|
||||
item := rep.Replace(data)
|
||||
if !strings.HasPrefix(item, "{") {
|
||||
item = "{" + item
|
||||
}
|
||||
if !strings.HasSuffix(item, "}}") {
|
||||
item = item + "}"
|
||||
}
|
||||
|
||||
if item == "{data: [DONE]}" || item == "{data: [DONE]}}" || item == "{[DONE]}" {
|
||||
return "", nil
|
||||
} else if item == "{data:}" || item == "{data:}}" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var form *ChatStreamResponse
|
||||
if form = utils.UnmarshalForm[ChatStreamResponse](item); form == nil {
|
||||
if form = utils.UnmarshalForm[ChatStreamResponse](item[:len(item)-1]); form == nil {
|
||||
if len(buf) > 0 {
|
||||
return c.ProcessLine("", buf+item)
|
||||
}
|
||||
|
||||
var err *ChatStreamErrorResponse
|
||||
if err = utils.UnmarshalForm[ChatStreamErrorResponse](item); err == nil {
|
||||
if err = utils.UnmarshalForm[ChatStreamErrorResponse](item + "}"); err == nil {
|
||||
globals.Warn(fmt.Sprintf("chatgpt error: cannot parse response: %s", item))
|
||||
return data, errors.New("parser error: cannot parse response")
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("chatgpt error: %s (type: %s)", err.Data.Error.Message, err.Data.Error.Type)
|
||||
}
|
||||
}
|
||||
|
||||
if len(form.Data.Choices) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return form.Data.Choices[0].Delta.Content, nil
|
||||
}
|
||||
|
||||
// CreateChatRequest is the native http request body for chatgpt
|
||||
func (c *ChatInstance) CreateChatRequest(props *ChatProps) (string, error) {
|
||||
res, err := utils.Post(
|
||||
c.GetChatEndpoint(),
|
||||
c.GetChatEndpoint(props),
|
||||
c.GetHeader(),
|
||||
c.GetChatBody(props, false),
|
||||
)
|
||||
@ -105,14 +85,15 @@ func (c *ChatInstance) CreateChatRequest(props *ChatProps) (string, error) {
|
||||
// CreateStreamChatRequest is the stream response body for chatgpt
|
||||
func (c *ChatInstance) CreateStreamChatRequest(props *ChatProps, callback globals.Hook) error {
|
||||
buf := ""
|
||||
instruct := props.Model == globals.GPT3TurboInstruct
|
||||
|
||||
return utils.EventSource(
|
||||
"POST",
|
||||
c.GetChatEndpoint(),
|
||||
c.GetChatEndpoint(props),
|
||||
c.GetHeader(),
|
||||
c.GetChatBody(props, true),
|
||||
func(data string) error {
|
||||
data, err := c.ProcessLine(buf, data)
|
||||
data, err := c.ProcessLine(instruct, buf, data)
|
||||
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "chatgpt error") {
|
||||
|
123
adapter/chatgpt/processor.go
Normal file
123
adapter/chatgpt/processor.go
Normal file
@ -0,0 +1,123 @@
|
||||
package chatgpt
|
||||
|
||||
import (
|
||||
"chat/globals"
|
||||
"chat/utils"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processFormat(data string) string {
|
||||
rep := strings.NewReplacer(
|
||||
"data: {",
|
||||
"\"data\": {",
|
||||
)
|
||||
item := rep.Replace(data)
|
||||
if !strings.HasPrefix(item, "{") {
|
||||
item = "{" + item
|
||||
}
|
||||
if !strings.HasSuffix(item, "}}") {
|
||||
item = item + "}"
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func processChatResponse(data string) *ChatStreamResponse {
|
||||
if strings.HasPrefix(data, "{") {
|
||||
var form *ChatStreamResponse
|
||||
if form = utils.UnmarshalForm[ChatStreamResponse](data); form != nil {
|
||||
return form
|
||||
}
|
||||
|
||||
if form = utils.UnmarshalForm[ChatStreamResponse](data[:len(data)-1]); form != nil {
|
||||
return form
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processCompletionResponse(data string) *CompletionResponse {
|
||||
if strings.HasPrefix(data, "{") {
|
||||
var form *CompletionResponse
|
||||
if form = utils.UnmarshalForm[CompletionResponse](data); form != nil {
|
||||
return form
|
||||
}
|
||||
|
||||
if form = utils.UnmarshalForm[CompletionResponse](data[:len(data)-1]); form != nil {
|
||||
return form
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processChatErrorResponse(data string) *ChatStreamErrorResponse {
|
||||
if strings.HasPrefix(data, "{") {
|
||||
var form *ChatStreamErrorResponse
|
||||
if form = utils.UnmarshalForm[ChatStreamErrorResponse](data); form != nil {
|
||||
return form
|
||||
}
|
||||
if form = utils.UnmarshalForm[ChatStreamErrorResponse](data + "}"); form != nil {
|
||||
return form
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isDone(data string) bool {
|
||||
return utils.Contains[string](data, []string{
|
||||
"{data: [DONE]}", "{data: [DONE]}}",
|
||||
"{[DONE]}", "{data:}", "{data:}}",
|
||||
})
|
||||
}
|
||||
|
||||
func getChoices(form *ChatStreamResponse) string {
|
||||
if len(form.Data.Choices) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return form.Data.Choices[0].Delta.Content
|
||||
}
|
||||
|
||||
func getCompletionChoices(form *CompletionResponse) string {
|
||||
if len(form.Data.Choices) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return form.Data.Choices[0].Text
|
||||
}
|
||||
|
||||
func (c *ChatInstance) ProcessLine(instruct bool, buf, data string) (string, error) {
|
||||
item := processFormat(buf + data)
|
||||
if isDone(item) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if form := processChatResponse(item); form == nil {
|
||||
if instruct {
|
||||
// legacy support
|
||||
if completion := processCompletionResponse(item); completion != nil {
|
||||
return getCompletionChoices(completion), nil
|
||||
}
|
||||
}
|
||||
|
||||
// recursive call
|
||||
if len(buf) > 0 {
|
||||
return c.ProcessLine(instruct, "", buf+item)
|
||||
}
|
||||
|
||||
if err := processChatErrorResponse(item); err == nil {
|
||||
globals.Warn(fmt.Sprintf("chatgpt error: cannot parse response: %s", item))
|
||||
return data, errors.New("parser error: cannot parse response")
|
||||
} else {
|
||||
return "", fmt.Errorf("chatgpt error: %s (type: %s)", err.Data.Error.Message, err.Data.Error.Type)
|
||||
}
|
||||
|
||||
} else {
|
||||
return getChoices(form), nil
|
||||
}
|
||||
}
|
@ -57,9 +57,10 @@ func NewChatInstanceFromModel(props *InstanceProps) *ChatInstance {
|
||||
case globals.GPT432k,
|
||||
globals.GPT432k0613,
|
||||
globals.GPT432k0314:
|
||||
return NewChatInstanceFromConfig("gpt4")
|
||||
return NewChatInstanceFromConfig("32k")
|
||||
|
||||
case globals.GPT3Turbo,
|
||||
globals.GPT3TurboInstruct,
|
||||
globals.GPT3Turbo0613,
|
||||
globals.GPT3Turbo0301,
|
||||
globals.GPT3Turbo16k,
|
||||
|
@ -16,6 +16,20 @@ type ChatRequestWithInfinity struct {
|
||||
Stream bool `json:"stream"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
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"`
|
||||
@ -48,6 +62,20 @@ type ChatStreamResponse struct {
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// CompletionResponse is the native http request body / stream response body for chatgpt completion
|
||||
type CompletionResponse struct {
|
||||
ID string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
Created int64 `json:"created"`
|
||||
Model string `json:"model"`
|
||||
Data struct {
|
||||
Choices []struct {
|
||||
Text string `json:"text"`
|
||||
Index int `json:"index"`
|
||||
} `json:"choices"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type ChatStreamErrorResponse struct {
|
||||
Data struct {
|
||||
Error struct {
|
||||
|
@ -32,6 +32,21 @@ func retryChatGPTPool(props *ChatProps, hook globals.Hook, retry int) error {
|
||||
),
|
||||
}, hook)
|
||||
|
||||
if globals.IsGPT4NativeModel(props.Model) && IsAvailableError(err) {
|
||||
if !strings.Contains(err.Error(), "429") {
|
||||
// not rate limited
|
||||
return chatgpt.NewChatInstanceFromConfig("32k").CreateStreamChatRequest(&chatgpt.ChatProps{
|
||||
Model: props.Model,
|
||||
Message: props.Message,
|
||||
Token: utils.Multi(
|
||||
props.Token == 0,
|
||||
utils.Multi(globals.IsGPT4Model(props.Model) || props.Plan || props.Infinity, -1, 2500),
|
||||
props.Token,
|
||||
),
|
||||
}, hook)
|
||||
}
|
||||
}
|
||||
|
||||
if IsAvailableError(err) && retry < MaxRetries {
|
||||
fmt.Println(fmt.Sprintf("retrying chatgpt pool (times: %d, error: %s)", retry, err.Error()))
|
||||
return retryChatGPTPool(props, hook, retry+1)
|
||||
|
@ -13,7 +13,7 @@ func UsingWebSegment(instance *conversation.Conversation) (string, []globals.Mes
|
||||
if instance.IsEnableWeb() {
|
||||
keyword, segment = ChatWithWeb(func(message []globals.Message, token int) (string, error) {
|
||||
return chatgpt.NewChatInstanceFromConfig("gpt3").CreateChatRequest(&chatgpt.ChatProps{
|
||||
Model: globals.GPT3Turbo0613,
|
||||
Model: globals.GPT3TurboInstruct,
|
||||
Message: message,
|
||||
Token: token,
|
||||
})
|
||||
@ -28,7 +28,7 @@ func UsingWebNativeSegment(enable bool, message []globals.Message) (string, []gl
|
||||
if enable {
|
||||
return ChatWithWeb(func(message []globals.Message, token int) (string, error) {
|
||||
return chatgpt.NewChatInstanceFromConfig("gpt3").CreateChatRequest(&chatgpt.ChatProps{
|
||||
Model: globals.GPT3Turbo0613,
|
||||
Model: globals.GPT3TurboInstruct,
|
||||
Message: message,
|
||||
Token: token,
|
||||
})
|
||||
|
@ -22,14 +22,14 @@ export const supportModels: Model[] = [
|
||||
{ id: "gpt-4", name: "GPT-4", free: false, auth: true },
|
||||
{ id: "gpt-4-32k", name: "GPT-4-32k", free: false, auth: true },
|
||||
|
||||
// spark desk
|
||||
{ id: "spark-desk-v2", name: "讯飞星火 V2", free: false, auth: true },
|
||||
{ id: "spark-desk-v3", name: "讯飞星火 V3", free: false, auth: true },
|
||||
|
||||
// anthropic models
|
||||
{ id: "claude-1", name: "Claude-2", free: true, auth: false },
|
||||
{ id: "claude-2", name: "Claude-2-100k", free: false, auth: true }, // not claude-2-100k
|
||||
|
||||
// spark desk
|
||||
{ id: "spark-desk-v2", name: "SparkDesk 讯飞星火", free: false, auth: true },
|
||||
{ id: "spark-desk-v3", name: "SparkDesk 讯飞星火 V3", free: false, auth: true },
|
||||
|
||||
// google palm2
|
||||
{ id: "chat-bison-001", name: "Palm2", free: true, auth: true },
|
||||
|
||||
@ -39,19 +39,19 @@ export const supportModels: Model[] = [
|
||||
// zhipu models
|
||||
{
|
||||
id: "zhipu-chatglm-pro",
|
||||
name: "智谱 ChatGLM Pro",
|
||||
name: "ChatGLM Pro",
|
||||
free: false,
|
||||
auth: true,
|
||||
},
|
||||
{
|
||||
id: "zhipu-chatglm-std",
|
||||
name: "智谱 ChatGLM Std",
|
||||
name: "ChatGLM Std",
|
||||
free: false,
|
||||
auth: true,
|
||||
},
|
||||
{
|
||||
id: "zhipu-chatglm-lite",
|
||||
name: "智谱 ChatGLM Lite",
|
||||
name: "ChatGLM Lite",
|
||||
free: true,
|
||||
auth: true,
|
||||
},
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
// CanEnableModel returns whether the model can be enabled (without subscription)
|
||||
func CanEnableModel(db *sql.DB, user *User, model string) bool {
|
||||
switch model {
|
||||
case globals.GPT3Turbo, globals.GPT3Turbo0301, globals.GPT3Turbo0613,
|
||||
case globals.GPT3Turbo, globals.GPT3TurboInstruct, globals.GPT3Turbo0301, globals.GPT3Turbo0613,
|
||||
globals.Claude2:
|
||||
return true
|
||||
case globals.GPT4, globals.GPT4Vision, globals.GPT40613, globals.GPT40314:
|
||||
|
@ -39,6 +39,7 @@ func OriginIsOpen(c *gin.Context) bool {
|
||||
|
||||
const (
|
||||
GPT3Turbo = "gpt-3.5-turbo"
|
||||
GPT3TurboInstruct = "gpt-3.5-turbo-instruct"
|
||||
GPT3Turbo0613 = "gpt-3.5-turbo-0613"
|
||||
GPT3Turbo0301 = "gpt-3.5-turbo-0301"
|
||||
GPT3Turbo16k = "gpt-3.5-turbo-16k"
|
||||
@ -69,6 +70,7 @@ const (
|
||||
|
||||
var GPT3TurboArray = []string{
|
||||
GPT3Turbo,
|
||||
GPT3TurboInstruct,
|
||||
GPT3Turbo0613,
|
||||
GPT3Turbo0301,
|
||||
}
|
||||
@ -128,6 +130,7 @@ var LongContextModelArray = []string{
|
||||
|
||||
var FreeModelArray = []string{
|
||||
GPT3Turbo,
|
||||
GPT3TurboInstruct,
|
||||
GPT3Turbo0613,
|
||||
GPT3Turbo0301,
|
||||
GPT3Turbo16k,
|
||||
@ -143,6 +146,7 @@ var FreeModelArray = []string{
|
||||
|
||||
var AllModels = []string{
|
||||
GPT3Turbo,
|
||||
GPT3TurboInstruct,
|
||||
GPT3Turbo0613,
|
||||
GPT3Turbo0301,
|
||||
GPT3Turbo16k,
|
||||
|
@ -42,6 +42,7 @@ func GetWeightByModel(model string) int {
|
||||
globals.GPT432k0314:
|
||||
return 3 * 10
|
||||
case globals.GPT3Turbo,
|
||||
globals.GPT3TurboInstruct,
|
||||
globals.GPT3Turbo0613,
|
||||
|
||||
globals.GPT3Turbo16k,
|
||||
@ -103,7 +104,7 @@ func CountTokenPrice(messages []globals.Message, model string) int {
|
||||
|
||||
func CountInputToken(model string, v []globals.Message) float32 {
|
||||
switch model {
|
||||
case globals.GPT3Turbo, globals.GPT3Turbo0613, globals.GPT3Turbo0301,
|
||||
case globals.GPT3Turbo, globals.GPT3Turbo0613, globals.GPT3Turbo0301, globals.GPT3TurboInstruct,
|
||||
globals.GPT3Turbo16k, globals.GPT3Turbo16k0613, globals.GPT3Turbo16k0301:
|
||||
return 0
|
||||
case globals.GPT4, globals.GPT4Vision, globals.GPT40314, globals.GPT40613:
|
||||
@ -129,7 +130,7 @@ func CountInputToken(model string, v []globals.Message) float32 {
|
||||
|
||||
func CountOutputToken(model string, t int) float32 {
|
||||
switch model {
|
||||
case globals.GPT3Turbo, globals.GPT3Turbo0613, globals.GPT3Turbo0301,
|
||||
case globals.GPT3Turbo, globals.GPT3Turbo0613, globals.GPT3Turbo0301, globals.GPT3TurboInstruct,
|
||||
globals.GPT3Turbo16k, globals.GPT3Turbo16k0613, globals.GPT3Turbo16k0301:
|
||||
return 0
|
||||
case globals.GPT4, globals.GPT4Vision, globals.GPT40314, globals.GPT40613:
|
||||
|
Loading…
Reference in New Issue
Block a user