Skip to content

Commit

Permalink
v2.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jparkerweb committed Feb 27, 2025
1 parent 6b842bd commit be120cc
Show file tree
Hide file tree
Showing 14 changed files with 1,990 additions and 728 deletions.
11 changes: 11 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CONSOLE_LOGGING=false # set to true to enable console logging
HTTP_ENABLED=true # set to true to enable HTTP
HTTP_PORT=88 # only used if HTTP_ENABLED=true
MAX_REQUEST_BODY_SIZE=50mb # maximum size for request body (for handling base64 images)
HTTPS_ENABLED=false # set to true to enable HTTPS
HTTPS_PORT=443 # only used if HTTPS_ENABLED=true
HTTPS_KEY_PATH=./some-path/mykey.key # or privkey.pem
HTTPS_CERT_PATH=./some-path/mycert.pem # or fullchain.pem
IP_RATE_LIMIT_ENABLED=true # enable rate limiting by IP
IP_RATE_LIMIT_WINDOW_MS=60000 # window in milliseconds to limit requests
IP_RATE_LIMIT_MAX_REQUESTS=100 # limit each IP to X requests per set window
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
/.vscode
/node_modules
.env
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.

## [2.2.0] - 2025-01-01 - Bedrock Wrapper v2.2.0
## [2.3.0] - 2025-02-27 - Claude Sonnet 3.7 + Vision
### Added
- Support for Claude Sonnet 3.7
- Support for Clause Sonnet 3.7 Thinking
- Support for Claude Sonnet 3.x Vision

## [2.2.0] - 2025-01-01 - Llama 3.3 70b
### Added
- Support for Llama 3.3 70b

## [2.1.0] - 2024-11-21 - Bedrock Wrapper v2.1.0
## [2.1.0] - 2024-11-21 - Claude Haiku 3.5
### Added
- Support for "Anthropic Claude 3.5 Haiku"

## [2.0.0] - 2024-10-31 - Bedrock Wrapper v2.0.0
## [2.0.0] - 2024-10-31 - Claude
### Added
- Updated to use Bedrock Wrapper v2.0.0
- Model support for:
Expand Down
69 changes: 37 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 🔀 Bedrock Proxy Endpoint
Spin up your own custom OpenAI API server endpoint for easy AWS Bedrock LLM text inference (using standard `baseUrl`, and `apiKey` params)

---
![bedrock-proxy-endpoint](https://raw.githubusercontent.com/jparkerweb/bedrock-proxy-endpoint/refs/heads/main/.readme/bedrock-proxy-endpoint.jpg)

### Maintained by
<a href="https://www.equilllabs.com">
Expand All @@ -18,7 +18,6 @@ Are you are stuck with using AWS Bedrock for all LLM text inference, but you wan

- Great for getting existing OpenAI API compatible applications working with AWS Bedrock.

---

### Prerequisites

Expand Down Expand Up @@ -47,8 +46,6 @@ Before getting started, make sure you have the following installed:
npm ci
```

---

### Configuration

* Update the `.env` file in the root directory of the project with the following
Expand All @@ -59,6 +56,7 @@ Before getting started, make sure you have the following installed:
| CONSOLE_LOGGING | boolean | false | Show realtime logs |
| HTTP_ENABLED | boolean | true | Start a HTTP server |
| HTTP_PORT | integer | 80 | HTTP server port |
| MAX_REQUEST_BODY_SIZE | string | 50mb | Maximum size for request body |
| HTTPS_ENABLED | boolean | false | Start a HTTPS server |
| HTTPS_PORT | integer | 443 | HTTPS server port |
| HTTPS_KEY_PATH | string | ./path/mykey.key | Path to key file for HTTPS |
Expand All @@ -67,17 +65,13 @@ Before getting started, make sure you have the following installed:
| IP_RATE_LIMIT_WINDOW_MS | integer | 60000 | Window in milliseconds |
| IP_RATE_LIMIT_MAX_REQUESTS | integer | 100 | Max requests per IP per window |

---

### Authentication

`Bedrock Proxy` authenticates with AWS via `IAM`. Since the OpenAI API intance accpets an API Key we will utilize this value to hold your credentials. Construct your `apiKey` for inference in the next step following this format:

- `AWS_REGION` + `.` + `AWS_ACCESS_KEY_ID` + `.` + `AWS_SECRET_ACCESS_KEY`
- `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}`
- example `apiKey` value:
`us-west-2.AKIAWSGBPOAB34JZUEPP.ySssDeZBXGab+eqeaAxblSL+iEc/CS8Ff1HW3VV7`

---
`us-west-2.AKIAWSXXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYYYY`

### Usage

Expand All @@ -91,11 +85,13 @@ Before getting started, make sure you have the following installed:
- `baseUrl`: Root address of server based on your `.env` configuration.
- `apiKey`: Descibed in the *Authentication* section above.
- `messages`: Array of objects in role / content format.
- `model`: This can be either the `modelName` or `modelId` from the list of supported models found on the `Bedrock Wrapper` README file [here](/~https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.

---
- `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](/~https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.
- `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).
### Example OpenAI API Call
Look at the example folder for complete examples of how to use the server:
- `example.js` - Basic text completion example
- `example-vision.js` - Vision model example with image processing (image can be passed as a base64 string or a URL)
```javascript
import OpenAI from 'openai';
Expand All @@ -115,39 +111,48 @@ const messages = [
},
];
const baseURL = "http://localhost";
// this is only an example apiKey
const apiKey = "us-west-2.AKIAWSGBPOAB34JZUEPP.ySssDeZBXGab+eqeaAxblSL+iEc/CS8Ff1HW3VV7"
const baseURL = "http://localhost"; // URL of the Bedrock Proxy Endpoint
const apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key
const openai = new OpenAI({
baseURL: baseURL,
apiKey: apiKey,
});
const chatCompletion = await openai.chat.completions.create({
messages: messages,
model: "Claude-3-5-Sonnet-v2",
max_tokens: 800,
temperature: 0.4,
top_p: 0.7,
stream: true,
})
for await (const chunk of chatCompletion) {
const response = chunk.choices[0]?.delta?.content || "";
process.stdout.write(response);
async function main() {
try {
const chatCompletion = await openai.chat.completions.create({
messages: messages,
model: "Claude-3-7-Sonnet-Thinking",
max_tokens: 2048,
temperature: 0.4,
top_p: 0.7,
stream: true,
include_thinking_data: true, // Enable to include the model's thinking process in the response
});

if (chatCompletion) {
for await (const chunk of chatCompletion) {
const response = chunk.choices[0]?.delta?.content || "";
process.stdout.write(response);
}
}
} catch (error) {
console.error('Error:', error);
} finally {
process.exit(0);
}
}
```

---
main();
```
### Root Info Page
Point your browser to the root of your endpoint server to view the info page: (example: `http://localhost`)
<img src="docs/bedrock-proxy-endpoint.png" style="max-width:700px">
---

### Note
Alternativly you can incorporate 🪨 <a href="/~https://github.com/jparkerweb/bedrock-wrapper" target="bedrockWrapper">`Bedrock Wrapper`</a> core directly into your code base. If you would like to explore that option checkout the npm package here: https://www.npmjs.com/package/bedrock-wrapper
Expand Down
3 changes: 3 additions & 0 deletions example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
AWS_REGION=us-west-2 # AWS Region
AWS_ACCESS_KEY_ID=AKIAWSxxxxxxxxxxxxxx # AWS Access Key ID
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxx # AWS Secret Access Key
2 changes: 2 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
73 changes: 73 additions & 0 deletions example/example-vision.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import OpenAI from 'openai';
import fs from 'fs';
import path from 'path';
import dotenv from 'dotenv';

dotenv.config();
const { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = process.env;

const __dirname = path.resolve();
const base64Image = fs.readFileSync(path.join(__dirname, 'lizard.jpg')).toString('base64');
const messages = [
{
role: "system",
content: "You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.",
},
{
role: "user",
content: [
{
type: "text",
text: "What's in this image? Please describe it in detail."
},
{
type: "image_url",
image_url: {
url: `data:image/jpeg;base64,${base64Image}`
// url: "/~https://github.com/jparkerweb/ref/blob/main/equill-labs/bedrock-proxy-endpoint/bedrock-proxy-endpoint.png?raw=true"
}
}
]
},
{
role: "assistant",
content: "",
},
];

const baseURL = "http://localhost:88"; // URL of the Bedrock Proxy Endpoint
const apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key

const openai = new OpenAI({
baseURL: baseURL,
apiKey: apiKey,
});

async function main() {
try {
const chatCompletion = await openai.chat.completions.create({
messages: messages,
model: "Claude-3-7-Sonnet-Thinking",
max_tokens: 2048,
temperature: 0.4,
top_p: 0.7,
stream: true,
});

if (chatCompletion) {
for await (const chunk of chatCompletion) {
const response = chunk.choices[0]?.delta?.content || "";
process.stdout.write(response);
}
// Add a newline at the end for cleaner output
process.stdout.write('\n');
}
} catch (error) {
console.error('Error:', error);
} finally {
// Explicitly exit the process when done
process.exit(0);
}
}

main();
58 changes: 58 additions & 0 deletions example/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import OpenAI from 'openai';
import dotenv from 'dotenv';

dotenv.config();
const { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = process.env;

const messages = [
{
role: "system",
content: "You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.",
},
{
role: "user",
content: "Describe why the OpenAI API standard is so great. Limit your response to five sentences.",
},
{
role: "assistant",
content: "",
},
];

const baseURL = "http://localhost:88"; // URL of the Bedrock Proxy Endpoint
const apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key

const openai = new OpenAI({
baseURL: baseURL,
apiKey: apiKey,
});

async function main() {
try {
const chatCompletion = await openai.chat.completions.create({
messages: messages,
model: "Claude-3-7-Sonnet-Thinking",
max_tokens: 2048,
temperature: 0.4,
top_p: 0.7,
stream: true,
include_thinking_data: true,
});

if (chatCompletion) {
for await (const chunk of chatCompletion) {
const response = chunk.choices[0]?.delta?.content || "";
process.stdout.write(response);
}
// Add a newline at the end for cleaner output
process.stdout.write('\n');
}
} catch (error) {
console.error('Error:', error);
} finally {
// Explicitly exit the process when done
process.exit(0);
}
}

main();
Binary file added example/lizard.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit be120cc

Please sign in to comment.