feat: support amazon bedrock anthropic (#114)

* 🚧 WIP: bedrock

*  feat: support amazon bedrock anthropic
This commit is contained in:
Buer
2024-03-18 16:00:35 +08:00
committed by GitHub
parent 6f76007292
commit b81808e839
23 changed files with 1617 additions and 29 deletions

View File

@@ -0,0 +1,54 @@
package category
import (
"errors"
"net/http"
"one-api/common/requester"
"one-api/providers/base"
"one-api/types"
"strings"
)
var CategoryMap = map[string]Category{}
type Category struct {
ModelName string
ChatComplete ChatCompletionConvert
ResponseChatComplete ChatCompletionResponse
ResponseChatCompleteStrem ChatCompletionStreamResponse
}
func GetCategory(modelName string) (*Category, error) {
modelName = GetModelName(modelName)
// 点分割
provider := strings.Split(modelName, ".")[0]
if category, exists := CategoryMap[provider]; exists {
category.ModelName = modelName
return &category, nil
}
return nil, errors.New("category_not_found")
}
func GetModelName(modelName string) string {
bedrockMap := map[string]string{
"claude-3-sonnet-20240229": "anthropic.claude-3-sonnet-20240229-v1:0",
"claude-3-haiku-20240307": "anthropic.claude-3-haiku-20240307-v1:0",
"claude-2.1": "anthropic.claude-v2:1",
"claude-2.0": "anthropic.claude-v2",
"claude-instant-1.2": "anthropic.claude-instant-v1",
}
if value, exists := bedrockMap[modelName]; exists {
modelName = value
}
return modelName
}
type ChatCompletionConvert func(*types.ChatCompletionRequest) (any, *types.OpenAIErrorWithStatusCode)
type ChatCompletionResponse func(base.ProviderInterface, *http.Response, *types.ChatCompletionRequest) (*types.ChatCompletionResponse, *types.OpenAIErrorWithStatusCode)
type ChatCompletionStreamResponse func(base.ProviderInterface, *types.ChatCompletionRequest) requester.HandlerPrefix[string]

View File

@@ -0,0 +1,63 @@
package category
import (
"encoding/json"
"net/http"
"one-api/common"
"one-api/common/requester"
"one-api/providers/base"
"one-api/providers/claude"
"one-api/types"
)
const anthropicVersion = "bedrock-2023-05-31"
type ClaudeRequest struct {
*claude.ClaudeRequest
AnthropicVersion string `json:"anthropic_version"`
}
func init() {
CategoryMap["anthropic"] = Category{
ChatComplete: ConvertClaudeFromChatOpenai,
ResponseChatComplete: ConvertClaudeToChatOpenai,
ResponseChatCompleteStrem: ClaudeChatCompleteStrem,
}
}
func ConvertClaudeFromChatOpenai(request *types.ChatCompletionRequest) (any, *types.OpenAIErrorWithStatusCode) {
rawRequest, err := claude.ConvertFromChatOpenai(request)
if err != nil {
return nil, err
}
claudeRequest := &ClaudeRequest{}
claudeRequest.ClaudeRequest = rawRequest
claudeRequest.AnthropicVersion = anthropicVersion
// 删除model字段
claudeRequest.Model = ""
claudeRequest.Stream = false
return claudeRequest, nil
}
func ConvertClaudeToChatOpenai(provider base.ProviderInterface, response *http.Response, request *types.ChatCompletionRequest) (*types.ChatCompletionResponse, *types.OpenAIErrorWithStatusCode) {
claudeResponse := &claude.ClaudeResponse{}
err := json.NewDecoder(response.Body).Decode(claudeResponse)
if err != nil {
return nil, common.ErrorWrapper(err, "decode_response_failed", http.StatusInternalServerError)
}
return claude.ConvertToChatOpenai(provider, claudeResponse, request)
}
func ClaudeChatCompleteStrem(provider base.ProviderInterface, request *types.ChatCompletionRequest) requester.HandlerPrefix[string] {
chatHandler := &claude.ClaudeStreamHandler{
Usage: provider.GetUsage(),
Request: request,
Prefix: `{"type"`,
}
return chatHandler.HandlerStream
}