smgc commited on
Commit
150374e
1 Parent(s): e9fc770

Create app.js

Browse files
Files changed (1) hide show
  1. app.js +125 -0
app.js ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // app.js
2
+ const express = require('express');
3
+ const fetch = require('node-fetch');
4
+ const app = express();
5
+ const port = 8080;
6
+
7
+ const MODEL = 'claude-3-5-sonnet@20240620';
8
+ const PROJECT_ID = process.env.PROJECT_ID;
9
+ const CLIENT_ID = process.env.CLIENT_ID;
10
+ const CLIENT_SECRET = process.env.CLIENT_SECRET;
11
+ const REFRESH_TOKEN = process.env.REFRESH_TOKEN;
12
+ const API_KEY = process.env.API_KEY;
13
+
14
+ const TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
15
+
16
+ let tokenCache = {
17
+ accessToken: '',
18
+ expiry: 0,
19
+ refreshPromise: null
20
+ };
21
+
22
+ async function getAccessToken() {
23
+ const now = Date.now() / 1000;
24
+
25
+ if (tokenCache.accessToken && now < tokenCache.expiry - 120) {
26
+ return tokenCache.accessToken;
27
+ }
28
+
29
+ if (tokenCache.refreshPromise) {
30
+ await tokenCache.refreshPromise;
31
+ return tokenCache.accessToken;
32
+ }
33
+
34
+ tokenCache.refreshPromise = (async () => {
35
+ try {
36
+ const response = await fetch(TOKEN_URL, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json'
40
+ },
41
+ body: JSON.stringify({
42
+ client_id: CLIENT_ID,
43
+ client_secret: CLIENT_SECRET,
44
+ refresh_token: REFRESH_TOKEN,
45
+ grant_type: 'refresh_token'
46
+ })
47
+ });
48
+
49
+ const data = await response.json();
50
+
51
+ tokenCache.accessToken = data.access_token;
52
+ tokenCache.expiry = now + data.expires_in;
53
+ } finally {
54
+ tokenCache.refreshPromise = null;
55
+ }
56
+ })();
57
+
58
+ await tokenCache.refreshPromise;
59
+ return tokenCache.accessToken;
60
+ }
61
+
62
+ function getLocation() {
63
+ const currentSeconds = new Date().getSeconds();
64
+ return currentSeconds < 30 ? 'europe-west1' : 'us-east5';
65
+ }
66
+
67
+ function constructApiUrl(location) {
68
+ return `https://${location}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${location}/publishers/anthropic/models/${MODEL}:streamRawPredict`;
69
+ }
70
+
71
+ app.use(express.json());
72
+
73
+ app.get('/', (req, res) => {
74
+ res.status(200).send('Vertex Claude API From GCP');
75
+ });
76
+
77
+ app.post('/ai/v1/chat/completions', async (req, res) => {
78
+ const apiKey = req.headers['x-api-key'];
79
+ if (apiKey !== API_KEY) {
80
+ return res.status(403).json({
81
+ type: "error",
82
+ error: {
83
+ type: "permission_error",
84
+ message: "Your API key does not have permission to use the specified resource."
85
+ }
86
+ });
87
+ }
88
+
89
+ const accessToken = await getAccessToken();
90
+ const location = getLocation();
91
+ const apiUrl = constructApiUrl(location);
92
+
93
+ let requestBody = req.body;
94
+
95
+ if (requestBody.anthropic_version) {
96
+ delete requestBody.anthropic_version;
97
+ }
98
+
99
+ if (requestBody.model === "claude-3-5-sonnet-20240620") {
100
+ requestBody.model = "claude-3-5-sonnet@20240620";
101
+ }
102
+
103
+ requestBody.anthropic_version = "vertex-2023-10-16";
104
+
105
+ try {
106
+ const response = await fetch(apiUrl, {
107
+ method: 'POST',
108
+ headers: {
109
+ 'Authorization': `Bearer ${accessToken}`,
110
+ 'Content-Type': 'application/json; charset=utf-8'
111
+ },
112
+ body: JSON.stringify(requestBody)
113
+ });
114
+
115
+ const data = await response.text();
116
+ res.status(response.status).send(data);
117
+ } catch (error) {
118
+ console.error('Error:', error);
119
+ res.status(500).json({ error: 'Internal Server Error' });
120
+ }
121
+ });
122
+
123
+ app.listen(port, () => {
124
+ console.log(`Server running on port ${port}`);
125
+ });