🎨 Support qwen-vl-plus
This commit is contained in:
parent
c4c89e8e1b
commit
211a862d54
@ -93,6 +93,7 @@ var ModelRatio = map[string]float64{
|
|||||||
"qwen-plus": 1.4286, // ¥0.02 / 1k tokens
|
"qwen-plus": 1.4286, // ¥0.02 / 1k tokens
|
||||||
"qwen-max": 1.4286, // ¥0.02 / 1k tokens
|
"qwen-max": 1.4286, // ¥0.02 / 1k tokens
|
||||||
"qwen-max-longcontext": 1.4286, // ¥0.02 / 1k tokens
|
"qwen-max-longcontext": 1.4286, // ¥0.02 / 1k tokens
|
||||||
|
"qwen-vl-plus": 0.5715, // ¥0.008 / 1k tokens
|
||||||
"text-embedding-v1": 0.05, // ¥0.0007 / 1k tokens
|
"text-embedding-v1": 0.05, // ¥0.0007 / 1k tokens
|
||||||
"SparkDesk": 1.2858, // ¥0.018 / 1k tokens
|
"SparkDesk": 1.2858, // ¥0.018 / 1k tokens
|
||||||
"360GPT_S2_V9": 0.8572, // ¥0.012 / 1k tokens
|
"360GPT_S2_V9": 0.8572, // ¥0.012 / 1k tokens
|
||||||
|
@ -2,6 +2,7 @@ package ali
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"one-api/providers/base"
|
"one-api/providers/base"
|
||||||
|
|
||||||
@ -28,6 +29,16 @@ type AliProvider struct {
|
|||||||
base.BaseProvider
|
base.BaseProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *AliProvider) GetFullRequestURL(requestURL string, modelName string) string {
|
||||||
|
baseURL := strings.TrimSuffix(p.GetBaseURL(), "/")
|
||||||
|
|
||||||
|
if modelName == "qwen-vl-plus" {
|
||||||
|
requestURL = "/api/v1/services/aigc/multimodal-generation/generation"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%s", baseURL, requestURL)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取请求头
|
// 获取请求头
|
||||||
func (p *AliProvider) GetRequestHeaders() (headers map[string]string) {
|
func (p *AliProvider) GetRequestHeaders() (headers map[string]string) {
|
||||||
headers = make(map[string]string)
|
headers = make(map[string]string)
|
||||||
|
@ -26,21 +26,12 @@ func (aliResponse *AliChatResponse) ResponseHandler(resp *http.Response) (OpenAI
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
choice := types.ChatCompletionChoice{
|
|
||||||
Index: 0,
|
|
||||||
Message: types.ChatCompletionMessage{
|
|
||||||
Role: "assistant",
|
|
||||||
Content: aliResponse.Output.Text,
|
|
||||||
},
|
|
||||||
FinishReason: aliResponse.Output.FinishReason,
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenAIResponse = types.ChatCompletionResponse{
|
OpenAIResponse = types.ChatCompletionResponse{
|
||||||
ID: aliResponse.RequestId,
|
ID: aliResponse.RequestId,
|
||||||
Object: "chat.completion",
|
Object: "chat.completion",
|
||||||
Created: common.GetTimestamp(),
|
Created: common.GetTimestamp(),
|
||||||
Model: aliResponse.Model,
|
Model: aliResponse.Model,
|
||||||
Choices: []types.ChatCompletionChoice{choice},
|
Choices: aliResponse.Output.ToChatCompletionChoices(),
|
||||||
Usage: &types.Usage{
|
Usage: &types.Usage{
|
||||||
PromptTokens: aliResponse.Usage.InputTokens,
|
PromptTokens: aliResponse.Usage.InputTokens,
|
||||||
CompletionTokens: aliResponse.Usage.OutputTokens,
|
CompletionTokens: aliResponse.Usage.OutputTokens,
|
||||||
@ -58,10 +49,31 @@ func (p *AliProvider) getChatRequestBody(request *types.ChatCompletionRequest) *
|
|||||||
messages := make([]AliMessage, 0, len(request.Messages))
|
messages := make([]AliMessage, 0, len(request.Messages))
|
||||||
for i := 0; i < len(request.Messages); i++ {
|
for i := 0; i < len(request.Messages); i++ {
|
||||||
message := request.Messages[i]
|
message := request.Messages[i]
|
||||||
messages = append(messages, AliMessage{
|
if request.Model != "qwen-vl-plus" {
|
||||||
Content: message.StringContent(),
|
messages = append(messages, AliMessage{
|
||||||
Role: strings.ToLower(message.Role),
|
Content: message.StringContent(),
|
||||||
})
|
Role: strings.ToLower(message.Role),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
openaiContent := message.ParseContent()
|
||||||
|
var parts []AliMessagePart
|
||||||
|
for _, part := range openaiContent {
|
||||||
|
if part.Type == types.ContentTypeText {
|
||||||
|
parts = append(parts, AliMessagePart{
|
||||||
|
Text: part.Text,
|
||||||
|
})
|
||||||
|
} else if part.Type == types.ContentTypeImageURL {
|
||||||
|
parts = append(parts, AliMessagePart{
|
||||||
|
Image: part.ImageURL.URL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
messages = append(messages, AliMessage{
|
||||||
|
Content: parts,
|
||||||
|
Role: strings.ToLower(message.Role),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enableSearch := false
|
enableSearch := false
|
||||||
@ -77,6 +89,7 @@ func (p *AliProvider) getChatRequestBody(request *types.ChatCompletionRequest) *
|
|||||||
Messages: messages,
|
Messages: messages,
|
||||||
},
|
},
|
||||||
Parameters: AliParameters{
|
Parameters: AliParameters{
|
||||||
|
ResultFormat: "message",
|
||||||
EnableSearch: enableSearch,
|
EnableSearch: enableSearch,
|
||||||
IncrementalOutput: request.Stream,
|
IncrementalOutput: request.Stream,
|
||||||
},
|
},
|
||||||
@ -87,6 +100,7 @@ func (p *AliProvider) getChatRequestBody(request *types.ChatCompletionRequest) *
|
|||||||
func (p *AliProvider) ChatAction(request *types.ChatCompletionRequest, isModelMapped bool, promptTokens int) (usage *types.Usage, errWithCode *types.OpenAIErrorWithStatusCode) {
|
func (p *AliProvider) ChatAction(request *types.ChatCompletionRequest, isModelMapped bool, promptTokens int) (usage *types.Usage, errWithCode *types.OpenAIErrorWithStatusCode) {
|
||||||
|
|
||||||
requestBody := p.getChatRequestBody(request)
|
requestBody := p.getChatRequestBody(request)
|
||||||
|
|
||||||
fullRequestURL := p.GetFullRequestURL(p.ChatCompletions, request.Model)
|
fullRequestURL := p.GetFullRequestURL(p.ChatCompletions, request.Model)
|
||||||
headers := p.GetRequestHeaders()
|
headers := p.GetRequestHeaders()
|
||||||
if request.Stream {
|
if request.Stream {
|
||||||
@ -134,10 +148,15 @@ func (p *AliProvider) ChatAction(request *types.ChatCompletionRequest, isModelMa
|
|||||||
|
|
||||||
// 阿里云响应转OpenAI响应
|
// 阿里云响应转OpenAI响应
|
||||||
func (p *AliProvider) streamResponseAli2OpenAI(aliResponse *AliChatResponse) *types.ChatCompletionStreamResponse {
|
func (p *AliProvider) streamResponseAli2OpenAI(aliResponse *AliChatResponse) *types.ChatCompletionStreamResponse {
|
||||||
|
// chatChoice := aliResponse.Output.ToChatCompletionChoices()
|
||||||
|
// jsonBody, _ := json.MarshalIndent(chatChoice, "", " ")
|
||||||
|
// fmt.Println("requestBody:", string(jsonBody))
|
||||||
var choice types.ChatCompletionStreamChoice
|
var choice types.ChatCompletionStreamChoice
|
||||||
choice.Delta.Content = aliResponse.Output.Text
|
choice.Index = aliResponse.Output.Choices[0].Index
|
||||||
if aliResponse.Output.FinishReason != "null" {
|
choice.Delta.Content = aliResponse.Output.Choices[0].Message.StringContent()
|
||||||
finishReason := aliResponse.Output.FinishReason
|
// fmt.Println("choice.Delta.Content:", chatChoice[0].Message)
|
||||||
|
if aliResponse.Output.Choices[0].FinishReason != "null" {
|
||||||
|
finishReason := aliResponse.Output.Choices[0].FinishReason
|
||||||
choice.FinishReason = &finishReason
|
choice.FinishReason = &finishReason
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +219,8 @@ func (p *AliProvider) sendStreamRequest(req *http.Request, model string) (usage
|
|||||||
stopChan <- true
|
stopChan <- true
|
||||||
}()
|
}()
|
||||||
common.SetEventStreamHeaders(p.Context)
|
common.SetEventStreamHeaders(p.Context)
|
||||||
// lastResponseText := ""
|
lastResponseText := ""
|
||||||
|
index := 0
|
||||||
p.Context.Stream(func(w io.Writer) bool {
|
p.Context.Stream(func(w io.Writer) bool {
|
||||||
select {
|
select {
|
||||||
case data := <-dataChan:
|
case data := <-dataChan:
|
||||||
@ -216,9 +236,11 @@ func (p *AliProvider) sendStreamRequest(req *http.Request, model string) (usage
|
|||||||
usage.TotalTokens = aliResponse.Usage.InputTokens + aliResponse.Usage.OutputTokens
|
usage.TotalTokens = aliResponse.Usage.InputTokens + aliResponse.Usage.OutputTokens
|
||||||
}
|
}
|
||||||
aliResponse.Model = model
|
aliResponse.Model = model
|
||||||
|
aliResponse.Output.Choices[0].Index = index
|
||||||
|
index++
|
||||||
response := p.streamResponseAli2OpenAI(&aliResponse)
|
response := p.streamResponseAli2OpenAI(&aliResponse)
|
||||||
// response.Choices[0].Delta.Content = strings.TrimPrefix(response.Choices[0].Delta.Content, lastResponseText)
|
response.Choices[0].Delta.Content = strings.TrimPrefix(response.Choices[0].Delta.Content, lastResponseText)
|
||||||
// lastResponseText = aliResponse.Output.Text
|
lastResponseText = aliResponse.Output.Choices[0].Message.StringContent()
|
||||||
jsonResponse, err := json.Marshal(response)
|
jsonResponse, err := json.Marshal(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SysError("error marshalling stream response: " + err.Error())
|
common.SysError("error marshalling stream response: " + err.Error())
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package ali
|
package ali
|
||||||
|
|
||||||
|
import (
|
||||||
|
"one-api/types"
|
||||||
|
)
|
||||||
|
|
||||||
type AliError struct {
|
type AliError struct {
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
@ -13,10 +17,15 @@ type AliUsage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AliMessage struct {
|
type AliMessage struct {
|
||||||
Content string `json:"content"`
|
Content any `json:"content"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AliMessagePart struct {
|
||||||
|
Text string `json:"text,omitempty"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type AliInput struct {
|
type AliInput struct {
|
||||||
// Prompt string `json:"prompt"`
|
// Prompt string `json:"prompt"`
|
||||||
Messages []AliMessage `json:"messages"`
|
Messages []AliMessage `json:"messages"`
|
||||||
@ -28,6 +37,7 @@ type AliParameters struct {
|
|||||||
Seed uint64 `json:"seed,omitempty"`
|
Seed uint64 `json:"seed,omitempty"`
|
||||||
EnableSearch bool `json:"enable_search,omitempty"`
|
EnableSearch bool `json:"enable_search,omitempty"`
|
||||||
IncrementalOutput bool `json:"incremental_output,omitempty"`
|
IncrementalOutput bool `json:"incremental_output,omitempty"`
|
||||||
|
ResultFormat string `json:"result_format,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AliChatRequest struct {
|
type AliChatRequest struct {
|
||||||
@ -36,9 +46,25 @@ type AliChatRequest struct {
|
|||||||
Parameters AliParameters `json:"parameters,omitempty"`
|
Parameters AliParameters `json:"parameters,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AliChoice struct {
|
||||||
|
FinishReason string `json:"finish_reason"`
|
||||||
|
Message types.ChatCompletionMessage `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
type AliOutput struct {
|
type AliOutput struct {
|
||||||
Text string `json:"text"`
|
Choices []types.ChatCompletionChoice `json:"choices"`
|
||||||
FinishReason string `json:"finish_reason"`
|
}
|
||||||
|
|
||||||
|
func (o *AliOutput) ToChatCompletionChoices() []types.ChatCompletionChoice {
|
||||||
|
for i := range o.Choices {
|
||||||
|
_, ok := o.Choices[i].Message.Content.(string)
|
||||||
|
if ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Choices[i].Message.Content = o.Choices[i].Message.ParseContent()
|
||||||
|
}
|
||||||
|
return o.Choices
|
||||||
}
|
}
|
||||||
|
|
||||||
type AliChatResponse struct {
|
type AliChatResponse struct {
|
||||||
|
@ -27,11 +27,11 @@ func (m ChatCompletionMessage) StringContent() string {
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if contentMap["type"] == "text" {
|
|
||||||
if subStr, ok := contentMap["text"].(string); ok {
|
if subStr, ok := contentMap["text"].(string); ok && subStr != "" {
|
||||||
contentStr += subStr
|
contentStr += subStr
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return contentStr
|
return contentStr
|
||||||
}
|
}
|
||||||
@ -55,23 +55,26 @@ func (m ChatCompletionMessage) ParseContent() []ChatMessagePart {
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch contentMap["type"] {
|
|
||||||
case ContentTypeText:
|
if subStr, ok := contentMap["text"].(string); ok && subStr != "" {
|
||||||
if subStr, ok := contentMap["text"].(string); ok {
|
contentList = append(contentList, ChatMessagePart{
|
||||||
contentList = append(contentList, ChatMessagePart{
|
Type: ContentTypeText,
|
||||||
Type: ContentTypeText,
|
Text: subStr,
|
||||||
Text: subStr,
|
})
|
||||||
})
|
} else if subObj, ok := contentMap["image_url"].(map[string]any); ok {
|
||||||
}
|
contentList = append(contentList, ChatMessagePart{
|
||||||
case ContentTypeImageURL:
|
Type: ContentTypeImageURL,
|
||||||
if subObj, ok := contentMap["image_url"].(map[string]any); ok {
|
ImageURL: &ChatMessageImageURL{
|
||||||
contentList = append(contentList, ChatMessagePart{
|
URL: subObj["url"].(string),
|
||||||
Type: ContentTypeImageURL,
|
},
|
||||||
ImageURL: &ChatMessageImageURL{
|
})
|
||||||
URL: subObj["url"].(string),
|
} else if subObj, ok := contentMap["image"].(string); ok {
|
||||||
},
|
contentList = append(contentList, ChatMessagePart{
|
||||||
})
|
Type: ContentTypeImageURL,
|
||||||
}
|
ImageURL: &ChatMessageImageURL{
|
||||||
|
URL: subObj,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return contentList
|
return contentList
|
||||||
|
Loading…
Reference in New Issue
Block a user