Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dto/channel_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type AwsKeyType string

const (
AwsKeyTypeAKSK AwsKeyType = "ak_sk" // 默认
AwsKeyTypeAKSKRegionPrefix AwsKeyType = "ak_sk_region_prefix"
AwsKeyTypeApiKey AwsKeyType = "api_key"
)

Expand Down
1 change: 1 addition & 0 deletions relay/channel/aws/adaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Adaptor struct {
AwsModelId string
AwsReq any
IsNova bool
ModelPrefix string // 可配置的模型前缀,如 "global", "us", "eu", "apac", "jp" 等
}

func (a *Adaptor) ConvertGeminiRequest(*gin.Context, *relaycommon.RelayInfo, *dto.GeminiChatRequest) (any, error) {
Expand Down
52 changes: 42 additions & 10 deletions relay/channel/aws/relay-aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,24 @@ import (
"github.com/aws/smithy-go/auth/bearer"
)

func newAwsClient(c *gin.Context, info *relaycommon.RelayInfo) (*bedrockruntime.Client, error) {
func newAwsClient(c *gin.Context, info *relaycommon.RelayInfo) (*bedrockruntime.Client, string, bool, error) {
var (
httpClient *http.Client
err error
)
if info.ChannelSetting.Proxy != "" {
httpClient, err = service.NewProxyHttpClient(info.ChannelSetting.Proxy)
if err != nil {
return nil, fmt.Errorf("new proxy http client failed: %w", err)
return nil, "", false, fmt.Errorf("new proxy http client failed: %w", err)
}
} else {
httpClient = service.GetHttpClient()
}

awsSecret := strings.Split(info.ApiKey, "|")
var client *bedrockruntime.Client
var modelPrefix string
var hasCustomPrefix bool
switch len(awsSecret) {
case 2:
apiKey := awsSecret[0]
Expand All @@ -50,6 +52,9 @@ func newAwsClient(c *gin.Context, info *relaycommon.RelayInfo) (*bedrockruntime.
BearerAuthTokenProvider: bearer.StaticTokenProvider{Token: bearer.Token{Value: apiKey}},
HTTPClient: httpClient,
})
// 对于2参数格式,从region推导prefix
modelPrefix = getAwsRegionPrefix(region)
hasCustomPrefix = false
case 3:
ak := awsSecret[0]
sk := awsSecret[1]
Expand All @@ -59,28 +64,50 @@ func newAwsClient(c *gin.Context, info *relaycommon.RelayInfo) (*bedrockruntime.
Credentials: aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(ak, sk, "")),
HTTPClient: httpClient,
})
modelPrefix = getAwsRegionPrefix(region)
hasCustomPrefix = false
case 4:
ak := awsSecret[0]
sk := awsSecret[1]
region := awsSecret[2]
prefix := awsSecret[3]
client = bedrockruntime.New(bedrockruntime.Options{
Region: region,
Credentials: aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(ak, sk, "")),
HTTPClient: httpClient,
})
// 对于4参数格式,使用配置的prefix
modelPrefix = prefix
hasCustomPrefix = true
default:
return nil, errors.New("invalid aws secret key")
return nil, "", false, errors.New("invalid aws secret key")
}

return client, nil
return client, modelPrefix, hasCustomPrefix, nil
}

func doAwsClientRequest(c *gin.Context, info *relaycommon.RelayInfo, a *Adaptor, requestBody io.Reader) (any, error) {
awsCli, err := newAwsClient(c, info)
awsCli, modelPrefix, hasCustomPrefix, err := newAwsClient(c, info)
if err != nil {
return nil, types.NewError(err, types.ErrorCodeChannelAwsClientError)
}
a.AwsClient = awsCli
a.ModelPrefix = modelPrefix

println(info.UpstreamModelName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove debug println statement

This debug statement should be removed before merging to production.

Apply this diff:

-println(info.UpstreamModelName)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
println(info.UpstreamModelName)
🤖 Prompt for AI Agents
In relay/channel/aws/relay-aws.go around line 97 there is a leftover debug
println(info.UpstreamModelName); remove this debug print before merging — either
delete the println call or replace it with an appropriate structured logger call
at the correct log level if the model name must be recorded (e.g., use existing
logger.Debug/Info with context), ensuring no stray stdout prints remain.

// 获取对应的AWS模型ID
awsModelId := getAwsModelID(info.UpstreamModelName)

awsRegionPrefix := getAwsRegionPrefix(awsCli.Options().Region)
canCrossRegion := awsModelCanCrossRegion(awsModelId, awsRegionPrefix)
if canCrossRegion {
awsModelId = awsModelCrossRegion(awsModelId, awsRegionPrefix)
if hasCustomPrefix {
// 如果配置了自定义prefix(4个参数格式),直接使用
awsModelId = modelPrefix + "." + awsModelId
} else {
// 否则,从region推导并检查模型是否支持跨区域
awsRegionPrefix := getAwsRegionPrefix(awsCli.Options().Region)
canCrossRegion := awsModelCanCrossRegion(awsModelId, awsRegionPrefix)
if canCrossRegion {
awsModelId = awsModelCrossRegion(awsModelId, awsRegionPrefix, modelPrefix)
}
}

if isNovaModel(awsModelId) {
Expand Down Expand Up @@ -151,7 +178,12 @@ func awsModelCanCrossRegion(awsModelId, awsRegionPrefix string) bool {
return exists && regionSet[awsRegionPrefix]
}

func awsModelCrossRegion(awsModelId, awsRegionPrefix string) string {
func awsModelCrossRegion(awsModelId, awsRegionPrefix, configuredPrefix string) string {
// 如果配置了prefix,优先使用配置的prefix
if configuredPrefix != "" {
return configuredPrefix + "." + awsModelId
}
// 否则从region推导
modelPrefix, find := awsRegionCrossModelPrefixMap[awsRegionPrefix]
if !find {
return awsModelId
Expand Down
15 changes: 12 additions & 3 deletions web/src/components/table/channels/modals/EditChannelModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1491,9 +1491,13 @@ const EditChannelModal = (props) => {
placeholder={t('请选择密钥格式')}
optionList={[
{
label: 'AccessKey / SecretAccessKey',
label: 'AccessKey / SecretAccessKey / Region',
value: 'ak_sk',
},
{
label: 'AccessKey / SecretAccessKey / Region / Prefix',
value: 'ak_sk_region_prefix',
},
{ label: 'API Key', value: 'api_key' },
]}
style={{ width: '100%' }}
Expand Down Expand Up @@ -1580,7 +1584,10 @@ const EditChannelModal = (props) => {
inputs.type === 33
? inputs.aws_key_type === 'api_key'
? t('请输入 API Key,一行一个,格式:APIKey|Region')
: t(
: inputs.aws_key_type === 'ak_sk_region_prefix'
? t('请输入密钥,一行一个,格式:AccessKey|SecretAccessKey|Region|Prefix')
:
t(
'请输入密钥,一行一个,格式:AccessKey|SecretAccessKey|Region',
)
: t('请输入密钥,一行一个')
Expand Down Expand Up @@ -1782,7 +1789,9 @@ const EditChannelModal = (props) => {
inputs.type === 33
? inputs.aws_key_type === 'api_key'
? t('请输入 API Key,格式:APIKey|Region')
: t('按照如下格式输入:AccessKey|SecretAccessKey|Region')
: inputs.aws_key_type === 'ak_sk_region_prefix'
? t('请输入密钥,一行一个,格式:AccessKey|SecretAccessKey|Region|Prefix')
: t('按照如下格式输入:AccessKey|SecretAccessKey|Region')
: t(type2secretPrompt(inputs.type))
}
rules={
Expand Down