mirror of
https://github.com/coaidev/coai.git
synced 2025-05-19 04:50:14 +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
|
||||
}
|
||||
|
||||
type InstanceProps struct {
|
||||
Model string
|
||||
Plan bool
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetEndpoint() string {
|
||||
return c.Endpoint
|
||||
}
|
||||
|
@ -11,11 +11,6 @@ type ChatInstance struct {
|
||||
ApiKey string
|
||||
}
|
||||
|
||||
type InstanceProps struct {
|
||||
Model string
|
||||
Plan bool
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetEndpoint() string {
|
||||
return c.Endpoint
|
||||
}
|
||||
|
@ -4,71 +4,144 @@ import (
|
||||
adaptercommon "chat/adapter/common"
|
||||
"chat/globals"
|
||||
"chat/utils"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *ChatInstance) GetChatEndpoint(model string) string {
|
||||
return fmt.Sprintf("%s/api/paas/v3/model-api/%s/sse-invoke", c.GetEndpoint(), c.GetModel(model))
|
||||
func (c *ChatInstance) GetChatEndpoint() string {
|
||||
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 {
|
||||
case globals.ZhiPuChatGLMTurbo:
|
||||
return ChatGLMTurbo
|
||||
return GLMTurbo
|
||||
case globals.ZhiPuChatGLMPro:
|
||||
return ChatGLMPro
|
||||
return GLMPro
|
||||
case globals.ZhiPuChatGLMStd:
|
||||
return ChatGLMStd
|
||||
return GLMStd
|
||||
case globals.ZhiPuChatGLMLite:
|
||||
return ChatGLMLite
|
||||
return GLMLite
|
||||
default:
|
||||
return ChatGLMStd
|
||||
return GLMStd
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatInstance) FormatMessages(messages []globals.Message) []globals.Message {
|
||||
messages = utils.DeepCopy[[]globals.Message](messages)
|
||||
for i := range messages {
|
||||
if messages[i].Role == globals.Tool {
|
||||
continue
|
||||
}
|
||||
|
||||
if messages[i].Role == globals.System {
|
||||
messages[i].Role = globals.User
|
||||
func (c *ChatInstance) GetChatBody(props *adaptercommon.ChatProps, stream bool) interface{} {
|
||||
if props.Model == globals.GPT3TurboInstruct {
|
||||
// for completions
|
||||
return CompletionRequest{
|
||||
Model: c.ConvertModel(props.Model),
|
||||
Prompt: c.GetCompletionPrompt(props.Message),
|
||||
MaxToken: props.MaxTokens,
|
||||
Stream: stream,
|
||||
}
|
||||
}
|
||||
return messages
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetBody(props *adaptercommon.ChatProps) ChatRequest {
|
||||
messages := formatMessages(props)
|
||||
|
||||
// chatglm top_p should be (0.0, 1.0) and cannot be 0 or 1
|
||||
if props.TopP != nil && *props.TopP >= 1.0 {
|
||||
props.TopP = utils.ToPtr[float32](0.99)
|
||||
} else if props.TopP != nil && *props.TopP <= 0.0 {
|
||||
props.TopP = utils.ToPtr[float32](0.01)
|
||||
}
|
||||
|
||||
return ChatRequest{
|
||||
Prompt: c.FormatMessages(props.Message),
|
||||
TopP: props.TopP,
|
||||
Temperature: props.Temperature,
|
||||
Model: props.Model,
|
||||
Messages: messages,
|
||||
MaxToken: props.MaxTokens,
|
||||
Stream: stream,
|
||||
PresencePenalty: props.PresencePenalty,
|
||||
FrequencyPenalty: props.FrequencyPenalty,
|
||||
Temperature: props.Temperature,
|
||||
TopP: props.TopP,
|
||||
Tools: props.Tools,
|
||||
ToolChoice: props.ToolChoice,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChatInstance) CreateStreamChatRequest(props *adaptercommon.ChatProps, hook globals.Hook) error {
|
||||
return utils.EventSource(
|
||||
"POST",
|
||||
c.GetChatEndpoint(props.Model),
|
||||
map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"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})
|
||||
},
|
||||
// CreateChatRequest is the native http request body for chatglm
|
||||
func (c *ChatInstance) CreateChatRequest(props *adaptercommon.ChatProps) (string, error) {
|
||||
res, err := utils.Post(
|
||||
c.GetChatEndpoint(),
|
||||
c.GetHeader(),
|
||||
c.GetChatBody(props, false),
|
||||
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"
|
||||
"chat/globals"
|
||||
"chat/utils"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
type ChatInstance struct {
|
||||
@ -14,6 +16,27 @@ type ChatInstance struct {
|
||||
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 {
|
||||
// get jwt token for zhipuai api
|
||||
segment := strings.Split(c.ApiKey, ".")
|
||||
@ -37,17 +60,16 @@ func (c *ChatInstance) GetToken() string {
|
||||
return token
|
||||
}
|
||||
|
||||
func (c *ChatInstance) GetEndpoint() string {
|
||||
return c.Endpoint
|
||||
}
|
||||
|
||||
func NewChatInstance(endpoint, apikey string) *ChatInstance {
|
||||
func NewChatInstance(endpoint, apiKey string) *ChatInstance {
|
||||
return &ChatInstance{
|
||||
Endpoint: endpoint,
|
||||
ApiKey: apikey,
|
||||
ApiKey: apiKey,
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
const (
|
||||
ChatGLMTurbo = "chatglm_turbo"
|
||||
ChatGLMPro = "chatglm_pro"
|
||||
ChatGLMStd = "chatglm_std"
|
||||
ChatGLMLite = "chatglm_lite"
|
||||
GLM4 = "glm-4"
|
||||
GLM4Vision = "glm-4v"
|
||||
GLMTurbo = "glm-3-turbo" // GLM3 Turbo
|
||||
GLMPro = "chatglm_pro" // GLM3 Pro (deprecated)
|
||||
GLMStd = "chatglm_std" // GLM3 Standard (deprecated)
|
||||
GLMLite = "chatglm_lite" // GLM3 Lite (deprecated)
|
||||
)
|
||||
|
||||
type Payload struct {
|
||||
ApiKey string `json:"api_key"`
|
||||
Exp int64 `json:"exp"`
|
||||
TimeStamp int64 `json:"timestamp"`
|
||||
type ImageUrl struct {
|
||||
Url string `json:"url"`
|
||||
Detail *string `json:"detail,omitempty"`
|
||||
}
|
||||
|
||||
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 {
|
||||
Prompt []globals.Message `json:"prompt"`
|
||||
Temperature *float32 `json:"temperature,omitempty"`
|
||||
TopP *float32 `json:"top_p,omitempty"`
|
||||
Ref *ChatRef `json:"ref,omitempty"`
|
||||
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"`
|
||||
TopP *float32 `json:"top_p,omitempty"`
|
||||
Tools *globals.FunctionTools `json:"tools,omitempty"`
|
||||
ToolChoice *interface{} `json:"tool_choice,omitempty"` // string or object
|
||||
}
|
||||
|
||||
type ChatRef struct {
|
||||
Enable *bool `json:"enable,omitempty"`
|
||||
SearchQuery *string `json:"search_query,omitempty"`
|
||||
// CompletionRequest is the request body for chatglm completion
|
||||
type CompletionRequest struct {
|
||||
Model string `json:"model"`
|
||||
Prompt string `json:"prompt"`
|
||||
MaxToken *int `json:"max_tokens,omitempty"`
|
||||
Stream bool `json:"stream"`
|
||||
}
|
||||
|
||||
type Occurrence struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Success bool `json:"success"`
|
||||
// ChatResponse is the native http request body for chatglm
|
||||
type ChatResponse struct {
|
||||
ID string `json:"id"`
|
||||
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",
|
||||
format: "<x-api-key>",
|
||||
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: [
|
||||
"claude-instant-1.2",
|
||||
"claude-2",
|
||||
@ -188,14 +188,12 @@ export const ChannelInfos: Record<string, ChannelInfo> = {
|
||||
endpoint: "https://open.bigmodel.cn",
|
||||
format: "<api-key>",
|
||||
models: [
|
||||
"zhipu-chatglm-turbo",
|
||||
"zhipu-chatglm-pro",
|
||||
"zhipu-chatglm-std",
|
||||
"zhipu-chatglm-lite",
|
||||
"glm-4",
|
||||
"glm-4v",
|
||||
"glm-3-turbo"
|
||||
],
|
||||
description:
|
||||
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n" +
|
||||
"> 智谱 ChatGLM 模型为了区分和 LocalAI 的开源 ChatGLM 模型,规定模型名称前缀为 **zhipu-**,系统内部已经做好适配,正常填入模板模型即可,无需额外任何设置 \n",
|
||||
"> 智谱 ChatGLM 密钥格式为 **api-key**,接入点填写 *https://open.bigmodel.cn* \n"
|
||||
},
|
||||
qwen: {
|
||||
endpoint: "https://dashscope.aliyuncs.com",
|
||||
@ -299,4 +297,4 @@ export function getChannelType(type?: string): string {
|
||||
export function getShortChannelType(type?: string): string {
|
||||
if (type && type in ShortChannelTypes) return ShortChannelTypes[type];
|
||||
return ShortChannelTypes.openai;
|
||||
}
|
||||
}
|
@ -70,6 +70,9 @@ export const modelColorMapper: Record<string, string> = {
|
||||
"zhipu-chatglm-pro": "lime-500",
|
||||
"zhipu-chatglm-std": "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-net": "indigo-600",
|
||||
|
@ -167,7 +167,13 @@ export const pricing: PricingDataset = [
|
||||
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,
|
||||
output: 0.005,
|
||||
currency: Currency.CNY,
|
||||
|
@ -1,9 +1,10 @@
|
||||
package globals
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const ChatMaxThread = 5
|
||||
@ -22,26 +23,43 @@ var AcceptImageStore bool
|
||||
var CloseRegistration bool
|
||||
var CloseRelay bool
|
||||
|
||||
func OriginIsAllowed(uri string) bool {
|
||||
if len(AllowedOrigins) == 0 {
|
||||
// if allowed origins is empty, allow all origins
|
||||
return true
|
||||
}
|
||||
var EpayBusinessId string
|
||||
var EpayBusinessKey string
|
||||
var EpayEndpoint string
|
||||
var EpayEnabled bool
|
||||
var EpayMethods []string
|
||||
|
||||
instance, _ := url.Parse(uri)
|
||||
if instance == nil {
|
||||
var SoftAuthPass byte
|
||||
var SoftDomain []byte
|
||||
var SoftName []byte
|
||||
|
||||
func OriginIsAllowed(uri string) bool {
|
||||
instance, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if instance.Hostname() == "localhost" || instance.Scheme == "file" {
|
||||
if instance.Scheme == "file" {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.HasPrefix(instance.Host, "www.") {
|
||||
instance.Host = instance.Host[4:]
|
||||
if instance.Hostname() == "localhost" || strings.HasPrefix(instance.Hostname(), "localhost") ||
|
||||
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 {
|
||||
@ -92,6 +110,9 @@ const (
|
||||
BingCreative = "bing-creative"
|
||||
BingBalanced = "bing-balanced"
|
||||
BingPrecise = "bing-precise"
|
||||
ZhiPuChatGLM4 = "glm-4"
|
||||
ZhiPuChatGLM4Vision = "glm-4v"
|
||||
ZhiPuChatGLM3Turbo = "glm-3-turbo"
|
||||
ZhiPuChatGLMTurbo = "zhipu-chatglm-turbo"
|
||||
ZhiPuChatGLMPro = "zhipu-chatglm-pro"
|
||||
ZhiPuChatGLMStd = "zhipu-chatglm-std"
|
||||
@ -118,8 +139,9 @@ var OpenAIDalleModels = []string{
|
||||
|
||||
var VisionModels = []string{
|
||||
GPT4VisionPreview, GPT41106VisionPreview, // openai
|
||||
GeminiProVision, // gemini
|
||||
Claude3, // anthropic
|
||||
GeminiProVision, // gemini
|
||||
Claude3, // anthropic
|
||||
ZhiPuChatGLM4Vision, // chatglm
|
||||
}
|
||||
|
||||
func in(value string, slice []string) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user