mirror of
https://github.com/coaidev/coai.git
synced 2025-05-19 21:10:18 +09:00
feat: update zhipuai chatglm channel api format v3 to v4 and support glm-4 & glm-4v (#147)
feat: update zhipuai chatglm channel api format v3 to v4 and support glm-4 & glm-4v (#147) Co-Authored-By: Minghan Zhang <112773885+zmh-program@users.noreply.github.com>
This commit is contained in:
parent
d0bf9776c4
commit
5ddfbbc295
@ -11,11 +11,6 @@ type ChatInstance struct {
|
|||||||
Resource string
|
Resource string
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceProps struct {
|
|
||||||
Model string
|
|
||||||
Plan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChatInstance) GetEndpoint() string {
|
func (c *ChatInstance) GetEndpoint() string {
|
||||||
return c.Endpoint
|
return c.Endpoint
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,6 @@ type ChatInstance struct {
|
|||||||
ApiKey string
|
ApiKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceProps struct {
|
|
||||||
Model string
|
|
||||||
Plan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChatInstance) GetEndpoint() string {
|
func (c *ChatInstance) GetEndpoint() string {
|
||||||
return c.Endpoint
|
return c.Endpoint
|
||||||
}
|
}
|
||||||
|
@ -4,71 +4,144 @@ import (
|
|||||||
adaptercommon "chat/adapter/common"
|
adaptercommon "chat/adapter/common"
|
||||||
"chat/globals"
|
"chat/globals"
|
||||||
"chat/utils"
|
"chat/utils"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ChatInstance) GetChatEndpoint(model string) string {
|
func (c *ChatInstance) GetChatEndpoint() string {
|
||||||
return fmt.Sprintf("%s/api/paas/v3/model-api/%s/sse-invoke", c.GetEndpoint(), c.GetModel(model))
|
return fmt.Sprintf("%s/api/paas/v4/chat/completions", c.GetEndpoint())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) GetModel(model string) string {
|
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) GetLatestPrompt(props *adaptercommon.ChatProps) string {
|
||||||
|
if len(props.Message) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.Message[len(props.Message)-1].Content
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatInstance) ConvertModel(model string) string {
|
||||||
|
// for v3 legacy adapter
|
||||||
switch model {
|
switch model {
|
||||||
case globals.ZhiPuChatGLMTurbo:
|
case globals.ZhiPuChatGLMTurbo:
|
||||||
return ChatGLMTurbo
|
return GLMTurbo
|
||||||
case globals.ZhiPuChatGLMPro:
|
case globals.ZhiPuChatGLMPro:
|
||||||
return ChatGLMPro
|
return GLMPro
|
||||||
case globals.ZhiPuChatGLMStd:
|
case globals.ZhiPuChatGLMStd:
|
||||||
return ChatGLMStd
|
return GLMStd
|
||||||
case globals.ZhiPuChatGLMLite:
|
case globals.ZhiPuChatGLMLite:
|
||||||
return ChatGLMLite
|
return GLMLite
|
||||||
default:
|
default:
|
||||||
return ChatGLMStd
|
return GLMStd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) FormatMessages(messages []globals.Message) []globals.Message {
|
func (c *ChatInstance) GetChatBody(props *adaptercommon.ChatProps, stream bool) interface{} {
|
||||||
messages = utils.DeepCopy[[]globals.Message](messages)
|
if props.Model == globals.GPT3TurboInstruct {
|
||||||
for i := range messages {
|
// for completions
|
||||||
if messages[i].Role == globals.Tool {
|
return CompletionRequest{
|
||||||
continue
|
Model: c.ConvertModel(props.Model),
|
||||||
|
Prompt: c.GetCompletionPrompt(props.Message),
|
||||||
|
MaxToken: props.MaxTokens,
|
||||||
|
Stream: stream,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if messages[i].Role == globals.System {
|
messages := formatMessages(props)
|
||||||
messages[i].Role = globals.User
|
|
||||||
}
|
// chatglm top_p should be (0.0, 1.0) and cannot be 0 or 1
|
||||||
}
|
if props.TopP != nil && *props.TopP >= 1.0 {
|
||||||
return messages
|
props.TopP = utils.ToPtr[float32](0.99)
|
||||||
|
} else if props.TopP != nil && *props.TopP <= 0.0 {
|
||||||
|
props.TopP = utils.ToPtr[float32](0.01)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) GetBody(props *adaptercommon.ChatProps) ChatRequest {
|
|
||||||
return ChatRequest{
|
return ChatRequest{
|
||||||
Prompt: c.FormatMessages(props.Message),
|
Model: props.Model,
|
||||||
TopP: props.TopP,
|
Messages: messages,
|
||||||
|
MaxToken: props.MaxTokens,
|
||||||
|
Stream: stream,
|
||||||
|
PresencePenalty: props.PresencePenalty,
|
||||||
|
FrequencyPenalty: props.FrequencyPenalty,
|
||||||
Temperature: props.Temperature,
|
Temperature: props.Temperature,
|
||||||
|
TopP: props.TopP,
|
||||||
|
Tools: props.Tools,
|
||||||
|
ToolChoice: props.ToolChoice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) CreateStreamChatRequest(props *adaptercommon.ChatProps, hook globals.Hook) error {
|
// CreateChatRequest is the native http request body for chatglm
|
||||||
return utils.EventSource(
|
func (c *ChatInstance) CreateChatRequest(props *adaptercommon.ChatProps) (string, error) {
|
||||||
"POST",
|
res, err := utils.Post(
|
||||||
c.GetChatEndpoint(props.Model),
|
c.GetChatEndpoint(),
|
||||||
map[string]string{
|
c.GetHeader(),
|
||||||
"Content-Type": "application/json",
|
c.GetChatBody(props, false),
|
||||||
"Accept": "text/event-stream",
|
|
||||||
"Authorization": c.GetToken(),
|
|
||||||
},
|
|
||||||
ChatRequest{
|
|
||||||
Prompt: c.FormatMessages(props.Message),
|
|
||||||
},
|
|
||||||
func(data string) error {
|
|
||||||
if !strings.HasPrefix(data, "data:") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data = strings.TrimPrefix(data, "data:")
|
|
||||||
return hook(&globals.Chunk{Content: data})
|
|
||||||
},
|
|
||||||
props.Proxy,
|
props.Proxy,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if err != nil || res == nil {
|
||||||
|
return "", fmt.Errorf("chatglm error: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
data := utils.MapToStruct[ChatResponse](res)
|
||||||
|
if data == nil {
|
||||||
|
return "", fmt.Errorf("chatglm error: cannot parse response")
|
||||||
|
} else if data.Error.Message != "" {
|
||||||
|
return "", fmt.Errorf("chatglm error: %s", data.Error.Message)
|
||||||
|
}
|
||||||
|
return data.Choices[0].Message.Content, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideRequestId(message string) string {
|
||||||
|
// xxx (request id: 2024020311120561344953f0xfh0TX)
|
||||||
|
|
||||||
|
exp := regexp.MustCompile(`\(request id: [a-zA-Z0-9]+\)`)
|
||||||
|
return exp.ReplaceAllString(message, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStreamChatRequest is the stream response body for chatglm
|
||||||
|
func (c *ChatInstance) CreateStreamChatRequest(props *adaptercommon.ChatProps, callback globals.Hook) error {
|
||||||
|
ticks := 0
|
||||||
|
err := utils.EventScanner(&utils.EventScannerProps{
|
||||||
|
Method: "POST",
|
||||||
|
Uri: c.GetChatEndpoint(),
|
||||||
|
Headers: c.GetHeader(),
|
||||||
|
Body: c.GetChatBody(props, true),
|
||||||
|
Callback: func(data string) error {
|
||||||
|
ticks += 1
|
||||||
|
|
||||||
|
partial, err := c.ProcessLine(data, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return callback(partial)
|
||||||
|
},
|
||||||
|
}, props.Proxy)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if form := processChatErrorResponse(err.Body); form != nil {
|
||||||
|
if form.Error.Type == "" && form.Error.Message == "" {
|
||||||
|
return errors.New(utils.ToMarkdownCode("json", err.Body))
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("%s (code: %s)", form.Error.Message, form.Error.Code)
|
||||||
|
return errors.New(hideRequestId(msg))
|
||||||
|
}
|
||||||
|
return err.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if ticks == 0 {
|
||||||
|
return errors.New("no response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
139
adapter/zhipuai/processor.go
Normal file
139
adapter/zhipuai/processor.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package zhipuai
|
||||||
|
|
||||||
|
import (
|
||||||
|
adaptercommon "chat/adapter/common"
|
||||||
|
"chat/globals"
|
||||||
|
"chat/utils"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func formatMessages(props *adaptercommon.ChatProps) interface{} {
|
||||||
|
if globals.IsVisionModel(props.Model) {
|
||||||
|
return utils.Each[globals.Message, Message](props.Message, func(message globals.Message) Message {
|
||||||
|
if message.Role == globals.User {
|
||||||
|
content, urls := utils.ExtractImages(message.Content, true)
|
||||||
|
images := utils.EachNotNil[string, MessageContent](urls, func(url string) *MessageContent {
|
||||||
|
obj, err := utils.NewImage(url)
|
||||||
|
props.Buffer.AddImage(obj)
|
||||||
|
if err != nil {
|
||||||
|
globals.Info(fmt.Sprintf("cannot process image: %s (source: %s)", err.Error(), utils.Extract(url, 24, "...")))
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(url, "data:image/") {
|
||||||
|
// remove base64 image prefix
|
||||||
|
if idx := strings.Index(url, "base64,"); idx != -1 {
|
||||||
|
url = url[idx+7:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MessageContent{
|
||||||
|
Type: "image_url",
|
||||||
|
ImageUrl: &ImageUrl{
|
||||||
|
Url: url,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return Message{
|
||||||
|
Role: message.Role,
|
||||||
|
Content: utils.Prepend(images, MessageContent{
|
||||||
|
Type: "text",
|
||||||
|
Text: &content,
|
||||||
|
}),
|
||||||
|
Name: message.Name,
|
||||||
|
FunctionCall: message.FunctionCall,
|
||||||
|
ToolCalls: message.ToolCalls,
|
||||||
|
ToolCallId: message.ToolCallId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Message{
|
||||||
|
Role: message.Role,
|
||||||
|
Content: message.Content,
|
||||||
|
Name: message.Name,
|
||||||
|
FunctionCall: message.FunctionCall,
|
||||||
|
ToolCalls: message.ToolCalls,
|
||||||
|
ToolCallId: message.ToolCallId,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func processChatResponse(data string) *ChatStreamResponse {
|
||||||
|
return utils.UnmarshalForm[ChatStreamResponse](data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processCompletionResponse(data string) *CompletionResponse {
|
||||||
|
return utils.UnmarshalForm[CompletionResponse](data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processChatErrorResponse(data string) *ChatStreamErrorResponse {
|
||||||
|
return utils.UnmarshalForm[ChatStreamErrorResponse](data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getChoices(form *ChatStreamResponse) *globals.Chunk {
|
||||||
|
if len(form.Choices) == 0 {
|
||||||
|
return &globals.Chunk{Content: ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
choice := form.Choices[0].Delta
|
||||||
|
|
||||||
|
return &globals.Chunk{
|
||||||
|
Content: choice.Content,
|
||||||
|
ToolCall: choice.ToolCalls,
|
||||||
|
FunctionCall: choice.FunctionCall,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCompletionChoices(form *CompletionResponse) string {
|
||||||
|
if len(form.Choices) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return form.Choices[0].Text
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRobustnessResult(chunk string) string {
|
||||||
|
exp := `\"content\":\"(.*?)\"`
|
||||||
|
compile, err := regexp.Compile(exp)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := compile.FindStringSubmatch(chunk)
|
||||||
|
if len(matches) > 1 {
|
||||||
|
return utils.ProcessRobustnessChar(matches[1])
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatInstance) ProcessLine(data string, isCompletionType bool) (*globals.Chunk, error) {
|
||||||
|
if isCompletionType {
|
||||||
|
// chatglm legacy support
|
||||||
|
if completion := processCompletionResponse(data); completion != nil {
|
||||||
|
return &globals.Chunk{
|
||||||
|
Content: getCompletionChoices(completion),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
globals.Warn(fmt.Sprintf("chatglm error: cannot parse completion response: %s", data))
|
||||||
|
return &globals.Chunk{Content: ""}, errors.New("parser error: cannot parse completion response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if form := processChatResponse(data); form != nil {
|
||||||
|
return getChoices(form), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if form := processChatErrorResponse(data); form != nil {
|
||||||
|
return &globals.Chunk{Content: ""}, errors.New(fmt.Sprintf("chatglm error: %s (type: %s)", form.Error.Message, form.Error.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
globals.Warn(fmt.Sprintf("chatglm error: cannot parse chat completion response: %s", data))
|
||||||
|
return &globals.Chunk{Content: ""}, errors.New("parser error: cannot parse chat completion response")
|
||||||
|
}
|
@ -4,9 +4,11 @@ import (
|
|||||||
factory "chat/adapter/common"
|
factory "chat/adapter/common"
|
||||||
"chat/globals"
|
"chat/globals"
|
||||||
"chat/utils"
|
"chat/utils"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatInstance struct {
|
type ChatInstance struct {
|
||||||
@ -14,6 +16,27 @@ type ChatInstance struct {
|
|||||||
ApiKey string
|
ApiKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Payload struct {
|
||||||
|
ApiKey string `json:"api_key"`
|
||||||
|
Exp int64 `json:"exp"`
|
||||||
|
TimeStamp int64 `json:"timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatInstance) GetEndpoint() string {
|
||||||
|
return c.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatInstance) GetApiKey() string {
|
||||||
|
return c.ApiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatInstance) GetHeader() map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": fmt.Sprintf("Bearer %s", c.GetToken()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) GetToken() string {
|
func (c *ChatInstance) GetToken() string {
|
||||||
// get jwt token for zhipuai api
|
// get jwt token for zhipuai api
|
||||||
segment := strings.Split(c.ApiKey, ".")
|
segment := strings.Split(c.ApiKey, ".")
|
||||||
@ -37,17 +60,16 @@ func (c *ChatInstance) GetToken() string {
|
|||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ChatInstance) GetEndpoint() string {
|
func NewChatInstance(endpoint, apiKey string) *ChatInstance {
|
||||||
return c.Endpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewChatInstance(endpoint, apikey string) *ChatInstance {
|
|
||||||
return &ChatInstance{
|
return &ChatInstance{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ApiKey: apikey,
|
ApiKey: apiKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChatInstanceFromConfig(conf globals.ChannelConfig) factory.Factory {
|
func NewChatInstanceFromConfig(conf globals.ChannelConfig) factory.Factory {
|
||||||
return NewChatInstance(conf.GetEndpoint(), conf.GetRandomSecret())
|
return NewChatInstance(
|
||||||
|
conf.GetEndpoint(),
|
||||||
|
conf.GetRandomSecret(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,32 +3,128 @@ package zhipuai
|
|||||||
import "chat/globals"
|
import "chat/globals"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ChatGLMTurbo = "chatglm_turbo"
|
GLM4 = "glm-4"
|
||||||
ChatGLMPro = "chatglm_pro"
|
GLM4Vision = "glm-4v"
|
||||||
ChatGLMStd = "chatglm_std"
|
GLMTurbo = "glm-3-turbo" // GLM3 Turbo
|
||||||
ChatGLMLite = "chatglm_lite"
|
GLMPro = "chatglm_pro" // GLM3 Pro (deprecated)
|
||||||
|
GLMStd = "chatglm_std" // GLM3 Standard (deprecated)
|
||||||
|
GLMLite = "chatglm_lite" // GLM3 Lite (deprecated)
|
||||||
)
|
)
|
||||||
|
|
||||||
type Payload struct {
|
type ImageUrl struct {
|
||||||
ApiKey string `json:"api_key"`
|
Url string `json:"url"`
|
||||||
Exp int64 `json:"exp"`
|
Detail *string `json:"detail,omitempty"`
|
||||||
TimeStamp int64 `json:"timestamp"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessageContent struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Text *string `json:"text,omitempty"`
|
||||||
|
ImageUrl *ImageUrl `json:"image_url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageContents []MessageContent
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Role string `json:"role"`
|
||||||
|
Content interface{} `json:"content"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
FunctionCall *globals.FunctionCall `json:"function_call,omitempty"` // only `function` role
|
||||||
|
ToolCallId *string `json:"tool_call_id,omitempty"` // only `tool` role
|
||||||
|
ToolCalls *globals.ToolCalls `json:"tool_calls,omitempty"` // only `assistant` role
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChatRequest is the request body for chatglm
|
||||||
type ChatRequest struct {
|
type ChatRequest struct {
|
||||||
Prompt []globals.Message `json:"prompt"`
|
Model string `json:"model"`
|
||||||
|
Messages interface{} `json:"messages"`
|
||||||
|
MaxToken *int `json:"max_tokens,omitempty"`
|
||||||
|
Stream bool `json:"stream"`
|
||||||
|
PresencePenalty *float32 `json:"presence_penalty,omitempty"`
|
||||||
|
FrequencyPenalty *float32 `json:"frequency_penalty,omitempty"`
|
||||||
Temperature *float32 `json:"temperature,omitempty"`
|
Temperature *float32 `json:"temperature,omitempty"`
|
||||||
TopP *float32 `json:"top_p,omitempty"`
|
TopP *float32 `json:"top_p,omitempty"`
|
||||||
Ref *ChatRef `json:"ref,omitempty"`
|
Tools *globals.FunctionTools `json:"tools,omitempty"`
|
||||||
|
ToolChoice *interface{} `json:"tool_choice,omitempty"` // string or object
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChatRef struct {
|
// CompletionRequest is the request body for chatglm completion
|
||||||
Enable *bool `json:"enable,omitempty"`
|
type CompletionRequest struct {
|
||||||
SearchQuery *string `json:"search_query,omitempty"`
|
Model string `json:"model"`
|
||||||
|
Prompt string `json:"prompt"`
|
||||||
|
MaxToken *int `json:"max_tokens,omitempty"`
|
||||||
|
Stream bool `json:"stream"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Occurrence struct {
|
// ChatResponse is the native http request body for chatglm
|
||||||
Code int `json:"code"`
|
type ChatResponse struct {
|
||||||
Msg string `json:"msg"`
|
ID string `json:"id"`
|
||||||
Success bool `json:"success"`
|
Object string `json:"object"`
|
||||||
|
Created int64 `json:"created"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Choices []struct {
|
||||||
|
Index int `json:"index"`
|
||||||
|
Message globals.Message `json:"message"`
|
||||||
|
FinishReason string `json:"finish_reason"`
|
||||||
|
} `json:"choices"`
|
||||||
|
Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
} `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChatStreamResponse is the stream response body for chatglm
|
||||||
|
type ChatStreamResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Object string `json:"object"`
|
||||||
|
Created int64 `json:"created"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Choices []struct {
|
||||||
|
Delta globals.Message `json:"delta"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
FinishReason string `json:"finish_reason"`
|
||||||
|
} `json:"choices"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompletionResponse is the native http request body / stream response body for chatglm completion
|
||||||
|
type CompletionResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Object string `json:"object"`
|
||||||
|
Created int64 `json:"created"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Choices []struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
} `json:"choices"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChatStreamErrorResponse struct {
|
||||||
|
Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
} `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageSize string
|
||||||
|
|
||||||
|
// ImageRequest is the request body for chatglm dalle image generation
|
||||||
|
type ImageRequest struct {
|
||||||
|
Model string `json:"model"`
|
||||||
|
Prompt string `json:"prompt"`
|
||||||
|
Size ImageSize `json:"size"`
|
||||||
|
N int `json:"n"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageResponse struct {
|
||||||
|
Data []struct {
|
||||||
|
Url string `json:"url"`
|
||||||
|
} `json:"data"`
|
||||||
|
Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
} `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ImageSize256 ImageSize = "256x256"
|
||||||
|
ImageSize512 ImageSize = "512x512"
|
||||||
|
ImageSize1024 ImageSize = "1024x1024"
|
||||||
|
)
|
||||||
|
@ -154,7 +154,7 @@ export const ChannelInfos: Record<string, ChannelInfo> = {
|
|||||||
endpoint: "https://api.anthropic.com",
|
endpoint: "https://api.anthropic.com",
|
||||||
format: "<x-api-key>",
|
format: "<x-api-key>",
|
||||||
description:
|
description:
|
||||||
"> Anthropic Claude 密钥格式为 **x-api-key**,Anthropic 对请求 IP 地域有限制,可能出现 **Request not allowed** 的错误,请尝试更换 IP 或者使用代理。\n",
|
"> Anthropic Claude 密钥即为 **x-api-key**,Anthropic 对请求 IP 地域有限制,可能出现 **Request not allowed** 的错误,请尝试更换 IP 或者使用代理。\n",
|
||||||
models: [
|
models: [
|
||||||
"claude-instant-1.2",
|
"claude-instant-1.2",
|
||||||
"claude-2",
|
"claude-2",
|
||||||
@ -188,14 +188,12 @@ export const ChannelInfos: Record<string, ChannelInfo> = {
|
|||||||
endpoint: "https://open.bigmodel.cn",
|
endpoint: "https://open.bigmodel.cn",
|
||||||
format: "<api-key>",
|
format: "<api-key>",
|
||||||
models: [
|
models: [
|
||||||
"zhipu-chatglm-turbo",
|
"glm-4",
|
||||||
"zhipu-chatglm-pro",
|
"glm-4v",
|
||||||
"zhipu-chatglm-std",
|
"glm-3-turbo"
|
||||||
"zhipu-chatglm-lite",
|
|
||||||
],
|
],
|
||||||
description:
|
description:
|
||||||
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n" +
|
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n"
|
||||||
"> 智谱 ChatGLM 模型为了区分和 LocalAI 的开源 ChatGLM 模型,规定模型名称前缀为 **zhipu-**,系统内部已经做好适配,正常填入模板模型即可,无需额外任何设置 \n",
|
|
||||||
},
|
},
|
||||||
qwen: {
|
qwen: {
|
||||||
endpoint: "https://dashscope.aliyuncs.com",
|
endpoint: "https://dashscope.aliyuncs.com",
|
||||||
|
@ -70,6 +70,9 @@ export const modelColorMapper: Record<string, string> = {
|
|||||||
"zhipu-chatglm-pro": "lime-500",
|
"zhipu-chatglm-pro": "lime-500",
|
||||||
"zhipu-chatglm-std": "lime-500",
|
"zhipu-chatglm-std": "lime-500",
|
||||||
"zhipu-chatglm-lite": "lime-500",
|
"zhipu-chatglm-lite": "lime-500",
|
||||||
|
"glm-4": "lime-500",
|
||||||
|
"glm-4v": "lime-500",
|
||||||
|
"glm-3-turbo": "lime-500",
|
||||||
|
|
||||||
"qwen-plus": "indigo-600",
|
"qwen-plus": "indigo-600",
|
||||||
"qwen-plus-net": "indigo-600",
|
"qwen-plus-net": "indigo-600",
|
||||||
|
@ -167,7 +167,13 @@ export const pricing: PricingDataset = [
|
|||||||
currency: Currency.CNY,
|
currency: Currency.CNY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
models: ["zhipu-chatglm-lite", "zhipu-chatglm-std", "zhipu-chatglm-turbo"],
|
models: ["glm-4", "glm-4v"],
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.1,
|
||||||
|
currency: Currency.CNY,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
models: ["zhipu-chatglm-lite", "zhipu-chatglm-std", "zhipu-chatglm-turbo", "glm-3-turbo"],
|
||||||
input: 0.005,
|
input: 0.005,
|
||||||
output: 0.005,
|
output: 0.005,
|
||||||
currency: Currency.CNY,
|
currency: Currency.CNY,
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package globals
|
package globals
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ChatMaxThread = 5
|
const ChatMaxThread = 5
|
||||||
@ -22,26 +23,43 @@ var AcceptImageStore bool
|
|||||||
var CloseRegistration bool
|
var CloseRegistration bool
|
||||||
var CloseRelay bool
|
var CloseRelay bool
|
||||||
|
|
||||||
func OriginIsAllowed(uri string) bool {
|
var EpayBusinessId string
|
||||||
if len(AllowedOrigins) == 0 {
|
var EpayBusinessKey string
|
||||||
// if allowed origins is empty, allow all origins
|
var EpayEndpoint string
|
||||||
return true
|
var EpayEnabled bool
|
||||||
}
|
var EpayMethods []string
|
||||||
|
|
||||||
instance, _ := url.Parse(uri)
|
var SoftAuthPass byte
|
||||||
if instance == nil {
|
var SoftDomain []byte
|
||||||
|
var SoftName []byte
|
||||||
|
|
||||||
|
func OriginIsAllowed(uri string) bool {
|
||||||
|
instance, err := url.Parse(uri)
|
||||||
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if instance.Hostname() == "localhost" || instance.Scheme == "file" {
|
if instance.Scheme == "file" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(instance.Host, "www.") {
|
if instance.Hostname() == "localhost" || strings.HasPrefix(instance.Hostname(), "localhost") ||
|
||||||
instance.Host = instance.Host[4:]
|
instance.Hostname() == "127.0.0.1" || strings.HasPrefix(instance.Hostname(), "127.0.0.1") ||
|
||||||
|
strings.HasPrefix(instance.Hostname(), "192.168.") || strings.HasPrefix(instance.Hostname(), "10.") {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return in(instance.Host, AllowedOrigins)
|
// get top level domain (example: sub.chatnio.net -> chatnio.net, chatnio.net -> chatnio.net)
|
||||||
|
// if the domain is in the allowed origins, return true
|
||||||
|
|
||||||
|
allow := string(SoftDomain)
|
||||||
|
|
||||||
|
domain := instance.Hostname()
|
||||||
|
if strings.HasSuffix(domain, allow) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func OriginIsOpen(c *gin.Context) bool {
|
func OriginIsOpen(c *gin.Context) bool {
|
||||||
@ -92,6 +110,9 @@ const (
|
|||||||
BingCreative = "bing-creative"
|
BingCreative = "bing-creative"
|
||||||
BingBalanced = "bing-balanced"
|
BingBalanced = "bing-balanced"
|
||||||
BingPrecise = "bing-precise"
|
BingPrecise = "bing-precise"
|
||||||
|
ZhiPuChatGLM4 = "glm-4"
|
||||||
|
ZhiPuChatGLM4Vision = "glm-4v"
|
||||||
|
ZhiPuChatGLM3Turbo = "glm-3-turbo"
|
||||||
ZhiPuChatGLMTurbo = "zhipu-chatglm-turbo"
|
ZhiPuChatGLMTurbo = "zhipu-chatglm-turbo"
|
||||||
ZhiPuChatGLMPro = "zhipu-chatglm-pro"
|
ZhiPuChatGLMPro = "zhipu-chatglm-pro"
|
||||||
ZhiPuChatGLMStd = "zhipu-chatglm-std"
|
ZhiPuChatGLMStd = "zhipu-chatglm-std"
|
||||||
@ -120,6 +141,7 @@ var VisionModels = []string{
|
|||||||
GPT4VisionPreview, GPT41106VisionPreview, // openai
|
GPT4VisionPreview, GPT41106VisionPreview, // openai
|
||||||
GeminiProVision, // gemini
|
GeminiProVision, // gemini
|
||||||
Claude3, // anthropic
|
Claude3, // anthropic
|
||||||
|
ZhiPuChatGLM4Vision, // chatglm
|
||||||
}
|
}
|
||||||
|
|
||||||
func in(value string, slice []string) bool {
|
func in(value string, slice []string) bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user