Skip to content

Commit

Permalink
Add anthropic
Browse files Browse the repository at this point in the history
  • Loading branch information
imshashank committed Nov 12, 2024
1 parent be92c9c commit 13a0a3c
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust

.env

### Rust ###
# Generated by Cargo
# will have compiled files and executables
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "magicapi-ai-gateway"
version = "0.1.4"
version = "0.1.5"
edition = "2021"
description = "A high-performance AI Gateway proxy for routing requests to various AI providers, offering seamless integration and management of multiple AI services"
authors = ["MagicAPI Team <team@magicapi.com>"]
Expand Down Expand Up @@ -33,4 +33,5 @@ tower = "0.4"
bytes = "1.0"
dotenv = "0.15"
futures-util = "0.3"
once_cell = "1.18"
once_cell = "1.18"
hyper = { version = "1.0", features = ["full"] }
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MagicAPI AI Gateway

The world's fastest AI Gateway proxy, written in Rust and optimized for maximum performance. This high-performance API gateway routes requests to various AI providers (OpenAI, GROQ) with streaming support, making it perfect for developers who need reliable and blazing-fast AI API access.
The world's fastest AI Gateway proxy, written in Rust and optimized for maximum performance. This high-performance API gateway routes requests to various AI providers (OpenAI, Anthropic, GROQ) with streaming support, making it perfect for developers who need reliable and blazing-fast AI API access.

[![Rust](https://github.com/MagicAPI/ai-gateway/actions/workflows/rust.yml/badge.svg)](https://github.com/MagicAPI/ai-gateway/actions/workflows/rust.yml)
[![Crates.io](https://img.shields.io/crates/v/magicapi-ai-gateway.svg)](https://crates.io/crates/magicapi-ai-gateway)
Expand All @@ -9,7 +9,7 @@ The world's fastest AI Gateway proxy, written in Rust and optimized for maximum

- 🚀 Blazing fast performance - built in Rust with zero-cost abstractions
- ⚡ Optimized for low latency and high throughput
- 🔄 Unified API interface for multiple AI providers (OpenAI, GROQ)
- 🔄 Unified API interface for multiple AI providers (OpenAI, Anthropic, GROQ)
- 📡 Real-time streaming support with minimal overhead
- 🔍 Built-in health checking
- 🛡️ Configurable CORS
Expand Down Expand Up @@ -103,6 +103,26 @@ curl -X POST http://localhost:3000/v1/chat/completions \
}'
```

#### Example: Anthropic Request

```bash
curl -X POST http://localhost:3000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-provider: anthropic" \
-H "Authorization: Bearer your-anthropic-api-key" \
-d '{
"model": "claude-3-5-sonnet-20241022",
"messages": [{"role": "user", "content": "Write a poem"}],
"stream": true,
"max_tokens": 1024
}'
```

Note: When using Anthropic as the provider, the gateway automatically:
- Routes requests to Anthropic's message API
- Converts the Authorization Bearer token to the required x-api-key format
- Adds the required anthropic-version header

## Configuration

The gateway can be configured using environment variables:
Expand Down
44 changes: 38 additions & 6 deletions src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,30 @@ pub async fn proxy_request_to_provider(
"Incoming request"
);

let base_url = match provider {
"openai" => "https://api.openai.com",
"anthropic" => "https://api.anthropic.com",
"groq" => "https://api.groq.com/openai",
let path = original_request.uri().path();
let (base_url, modified_path) = match provider {
"openai" => ("https://api.openai.com", path),
"anthropic" => {
if path.contains("/chat/completions") {
("https://api.anthropic.com", "/v1/messages")
} else {
("https://api.anthropic.com", path)
}
},
"groq" => ("https://api.groq.com/openai", path),
_ => {
error!(provider = provider, "Unsupported provider");
return Err(AppError::UnsupportedProvider);
}
};

let path = original_request.uri().path();
let query = original_request
.uri()
.query()
.map(|q| format!("?{}", q))
.unwrap_or_default();

let url = format!("{}{}{}", base_url, path, query);
let url = format!("{}{}{}", base_url, modified_path, query);
info!(
provider = provider,
url = %url,
Expand Down Expand Up @@ -121,6 +127,32 @@ pub async fn proxy_request_to_provider(
return Err(AppError::MissingApiKey);
}
},
"anthropic" => {
tracing::debug!("Processing Anthropic request headers");
if let Some(auth) = original_request.headers().get("authorization")
.and_then(|h| h.to_str().ok()) {
tracing::debug!("Using provided authorization header for Anthropic");
// Convert Bearer token to x-api-key format
let api_key = auth.trim_start_matches("Bearer ");
reqwest_headers.insert(
reqwest::header::HeaderName::from_static("x-api-key"),
reqwest::header::HeaderValue::from_str(api_key)
.map_err(|_| {
tracing::error!("Failed to process Anthropic authorization header");
AppError::InvalidHeader
})?
);

// Add required Anthropic version header
reqwest_headers.insert(
reqwest::header::HeaderName::from_static("anthropic-version"),
reqwest::header::HeaderValue::from_static("2023-06-01")
);
} else {
tracing::error!("No authorization header found for Anthropic request");
return Err(AppError::MissingApiKey);
}
},
_ => return Err(AppError::UnsupportedProvider),
}

Expand Down

0 comments on commit 13a0a3c

Please sign in to comment.