diff --git a/plugins/wasm-go/extensions/ai-proxy/README.md b/plugins/wasm-go/extensions/ai-proxy/README.md index ce6e43c7..ffc5f29b 100644 --- a/plugins/wasm-go/extensions/ai-proxy/README.md +++ b/plugins/wasm-go/extensions/ai-proxy/README.md @@ -275,6 +275,16 @@ Google Vertex AI 所对应的 type 为 vertex。它特有的配置字段如下 | `vertexGeminiSafetySetting` | map of string | 非必填 | - | Gemini 模型的内容安全过滤设置。 | | `vertexTokenRefreshAhead` | number | 非必填 | - | Vertex access token刷新提前时间(单位秒) | +#### AWS Bedrock + +AWS Bedrock 所对应的 type 为 bedrock。它特有的配置字段如下: + +| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 | +|----------------|--------|------|-----|------------------------------| +| `awsAccessKey` | string | 必填 | - | AWS Access Key,用于身份认证 | +| `awsSecretKey` | string | 必填 | - | AWS Secret Access Key,用于身份认证 | +| `awsRegion` | string | 必填 | - | AWS 区域,例如:us-east-1 | + ## 用法示例 ### 使用 OpenAI 协议代理 Azure OpenAI 服务 @@ -1704,6 +1714,59 @@ provider: } ``` +### 使用 OpenAI 协议代理 AWS Bedrock 服务 + +**配置信息** + +```yaml +provider: + type: bedrock + awsAccessKey: "YOUR_AWS_ACCESS_KEY_ID" + awsSecretKey: "YOUR_AWS_SECRET_ACCESS_KEY" + awsRegion: "YOUR_AWS_REGION" +``` + +**请求示例** + +```json +{ + "model": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0", + "messages": [ + { + "role": "user", + "content": "你好,你是谁?" + } + ], + "stream": false +} +``` + +**响应示例** + +```json +{ + "id": "dc5812e2-6a62-49d6-829e-5c327b15e4e2", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "你好!我是Claude,一个由Anthropic开发的AI助手。很高兴认识你!我的目标是以诚实、有益且有意义的方式与人类交流。我会尽力提供准确和有帮助的信息,同时保持诚实和正直。请问我今天能为你做些什么呢?" + }, + "finish_reason": "stop" + } + ], + "created": 1749657608, + "model": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0", + "object": "chat.completion", + "usage": { + "prompt_tokens": 16, + "completion_tokens": 101, + "total_tokens": 117 + } +} +``` + ## 完整配置示例 diff --git a/plugins/wasm-go/extensions/ai-proxy/README_EN.md b/plugins/wasm-go/extensions/ai-proxy/README_EN.md index b0586d89..ed7931a8 100644 --- a/plugins/wasm-go/extensions/ai-proxy/README_EN.md +++ b/plugins/wasm-go/extensions/ai-proxy/README_EN.md @@ -220,6 +220,16 @@ For Vertex, the corresponding `type` is `vertex`. Its unique configuration field | `vertexGeminiSafetySetting` | map of string | Optional | - | Gemini model content safety filtering settings. | | `vertexTokenRefreshAhead` | number | Optional | - | Vertex access token refresh ahead time in seconds | +#### AWS Bedrock + +For AWS Bedrock, the corresponding `type` is `bedrock`. Its unique configuration field is: + +| Name | Data Type | Requirement | Default | Description | +|----------------|-----------|-------------|---------|-----------------------------------------------| +| `awsAccessKey` | string | Required | - | AWS Access Key used for authentication | +| `awsSecretKey` | string | Required | - | AWS Secret Access Key used for authentication | +| `awsRegion` | string | Required | - | AWS region, e.g., us-east-1 | + ## Usage Examples ### Using OpenAI Protocol Proxy for Azure OpenAI Service @@ -1481,6 +1491,55 @@ provider: } ``` +### Utilizing OpenAI Protocol Proxy for AWS Bedrock Services +**Configuration Information** +```yaml +provider: + type: bedrock + awsAccessKey: "YOUR_AWS_ACCESS_KEY_ID" + awsSecretKey: "YOUR_AWS_SECRET_ACCESS_KEY" + awsRegion: "YOUR_AWS_REGION" +``` + +**Request Example** +```json +{ + "model": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0", + "messages": [ + { + "role": "user", + "content": "who are you" + } + ], + "stream": false +} +``` + +**Response Example** +```json +{ + "id": "d52da49d-daf3-49d9-a105-0b527481fe14", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "I'm Claude, an AI created by Anthropic. I aim to be helpful, honest, and harmless. I won't pretend to be human, and I'll always try to be direct and truthful about what I am and what I can do." + }, + "finish_reason": "stop" + } + ], + "created": 1749659050, + "model": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0", + "object": "chat.completion", + "usage": { + "prompt_tokens": 10, + "completion_tokens": 57, + "total_tokens": 67 + } +} +``` + ## Full Configuration Example ### Kubernetes Example diff --git a/plugins/wasm-go/extensions/ai-proxy/provider/bedrock.go b/plugins/wasm-go/extensions/ai-proxy/provider/bedrock.go index 588a1365..9f0621c5 100644 --- a/plugins/wasm-go/extensions/ai-proxy/provider/bedrock.go +++ b/plugins/wasm-go/extensions/ai-proxy/provider/bedrock.go @@ -760,10 +760,11 @@ func (b *bedrockProvider) buildChatCompletionResponse(ctx wrapper.HttpContext, b }, } requestId := ctx.GetStringContext(requestIdHeader, "") + modelId, _ := url.QueryUnescape(ctx.GetStringContext(ctxKeyFinalRequestModel, "")) return &chatCompletionResponse{ Id: requestId, Created: time.Now().UnixMilli() / 1000, - Model: ctx.GetStringContext(ctxKeyFinalRequestModel, ""), + Model: modelId, SystemFingerprint: "", Object: objectChatCompletion, Choices: choices, @@ -908,6 +909,7 @@ func (b *bedrockProvider) setAuthHeaders(body []byte, headers http.Header) { } func (b *bedrockProvider) generateSignature(path, amzDate, dateStamp string, body []byte) string { + path = encodeSigV4Path(path) hashedPayload := sha256Hex(body) endpoint := fmt.Sprintf(bedrockDefaultDomain, b.config.awsRegion) @@ -925,6 +927,17 @@ func (b *bedrockProvider) generateSignature(path, amzDate, dateStamp string, bod return signature } +func encodeSigV4Path(path string) string { + segments := strings.Split(path, "/") + for i, seg := range segments { + if seg == "" { + continue + } + segments[i] = url.PathEscape(seg) + } + return strings.Join(segments, "/") +} + func getSignatureKey(key, dateStamp, region, service string) []byte { kDate := hmacSha256([]byte("AWS4"+key), dateStamp) kRegion := hmacSha256(kDate, region)