vertex2api / app.js
smgc's picture
Create app.js
150374e verified
raw
history blame
3.28 kB
// app.js
const express = require('express');
const fetch = require('node-fetch');
const app = express();
const port = 8080;
const MODEL = 'claude-3-5-sonnet@20240620';
const PROJECT_ID = process.env.PROJECT_ID;
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
const REFRESH_TOKEN = process.env.REFRESH_TOKEN;
const API_KEY = process.env.API_KEY;
const TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
let tokenCache = {
accessToken: '',
expiry: 0,
refreshPromise: null
};
async function getAccessToken() {
const now = Date.now() / 1000;
if (tokenCache.accessToken && now < tokenCache.expiry - 120) {
return tokenCache.accessToken;
}
if (tokenCache.refreshPromise) {
await tokenCache.refreshPromise;
return tokenCache.accessToken;
}
tokenCache.refreshPromise = (async () => {
try {
const response = await fetch(TOKEN_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
refresh_token: REFRESH_TOKEN,
grant_type: 'refresh_token'
})
});
const data = await response.json();
tokenCache.accessToken = data.access_token;
tokenCache.expiry = now + data.expires_in;
} finally {
tokenCache.refreshPromise = null;
}
})();
await tokenCache.refreshPromise;
return tokenCache.accessToken;
}
function getLocation() {
const currentSeconds = new Date().getSeconds();
return currentSeconds < 30 ? 'europe-west1' : 'us-east5';
}
function constructApiUrl(location) {
return `https://${location}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${location}/publishers/anthropic/models/${MODEL}:streamRawPredict`;
}
app.use(express.json());
app.get('/', (req, res) => {
res.status(200).send('Vertex Claude API From GCP');
});
app.post('/ai/v1/chat/completions', async (req, res) => {
const apiKey = req.headers['x-api-key'];
if (apiKey !== API_KEY) {
return res.status(403).json({
type: "error",
error: {
type: "permission_error",
message: "Your API key does not have permission to use the specified resource."
}
});
}
const accessToken = await getAccessToken();
const location = getLocation();
const apiUrl = constructApiUrl(location);
let requestBody = req.body;
if (requestBody.anthropic_version) {
delete requestBody.anthropic_version;
}
if (requestBody.model === "claude-3-5-sonnet-20240620") {
requestBody.model = "claude-3-5-sonnet@20240620";
}
requestBody.anthropic_version = "vertex-2023-10-16";
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify(requestBody)
});
const data = await response.text();
res.status(response.status).send(data);
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});