From 2d19645c4ed0171bb4e1e8dfd8928334247aa130 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive@protonmail.com>
Date: Mon, 4 Dec 2023 12:53:17 -0500
Subject: [PATCH] Use Express router for openai endpoint

---
 server.js               |   2 +-
 src/endpoints/openai.js | 372 ++++++++++++++++++++--------------------
 2 files changed, 184 insertions(+), 190 deletions(-)

diff --git a/server.js b/server.js
index a0b24bb5b..cd61026e1 100644
--- a/server.js
+++ b/server.js
@@ -3576,7 +3576,7 @@ async function fetchJSON(url, args = {}) {
 // ** END **
 
 // OpenAI API
-require('./src/endpoints/openai').registerEndpoints(app, jsonParser, urlencodedParser);
+app.use('/api/openai', require('./src/endpoints/openai').router);
 
 // Tokenizers
 require('./src/endpoints/tokenizers').registerEndpoints(app, jsonParser);
diff --git a/src/endpoints/openai.js b/src/endpoints/openai.js
index 974027b0d..25c91b8c6 100644
--- a/src/endpoints/openai.js
+++ b/src/endpoints/openai.js
@@ -1,216 +1,210 @@
 const { readSecret, SECRET_KEYS } = require('./secrets');
 const fetch = require('node-fetch').default;
+const express = require('express');
 const FormData = require('form-data');
 const fs = require('fs');
+const { jsonParser, urlencodedParser } = require('../express-common');
 
-/**
- * Registers the OpenAI endpoints.
- * @param {import("express").Express} app Express app
- * @param {any} jsonParser JSON parser
- * @param {any} urlencodedParser Form data parser
- */
-function registerEndpoints(app, jsonParser, urlencodedParser) {
-    app.post('/api/openai/caption-image', jsonParser, async (request, response) => {
-        try {
-            let key = '';
+const router = express.Router();
 
-            if (request.body.api === 'openai') {
-                key = readSecret(SECRET_KEYS.OPENAI);
-            }
+router.post('/caption-image', jsonParser, async (request, response) => {
+    try {
+        let key = '';
 
-            if (request.body.api === 'openrouter') {
-                key = readSecret(SECRET_KEYS.OPENROUTER);
-            }
+        if (request.body.api === 'openai') {
+            key = readSecret(SECRET_KEYS.OPENAI);
+        }
 
-            if (!key) {
-                console.log('No key found for API', request.body.api);
-                return response.sendStatus(401);
-            }
+        if (request.body.api === 'openrouter') {
+            key = readSecret(SECRET_KEYS.OPENROUTER);
+        }
 
-            const body = {
-                model: request.body.model,
-                messages: [
-                    {
-                        role: 'user',
-                        content: [
-                            { type: 'text', text: request.body.prompt },
-                            { type: 'image_url', image_url: { 'url': request.body.image } },
-                        ],
-                    },
-                ],
-                max_tokens: 500,
-            };
+        if (!key) {
+            console.log('No key found for API', request.body.api);
+            return response.sendStatus(401);
+        }
 
-            console.log('Multimodal captioning request', body);
-
-            let apiUrl = '';
-            let headers = {};
-
-            if (request.body.api === 'openrouter') {
-                apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
-                headers['HTTP-Referer'] = request.headers.referer;
-            }
-
-            if (request.body.api === 'openai') {
-                apiUrl = 'https://api.openai.com/v1/chat/completions';
-            }
-
-            const result = await fetch(apiUrl, {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json',
-                    Authorization: `Bearer ${key}`,
-                    ...headers,
+        const body = {
+            model: request.body.model,
+            messages: [
+                {
+                    role: 'user',
+                    content: [
+                        { type: 'text', text: request.body.prompt },
+                        { type: 'image_url', image_url: { 'url': request.body.image } },
+                    ],
                 },
-                body: JSON.stringify(body),
-                timeout: 0,
-            });
+            ],
+            max_tokens: 500,
+        };
 
-            if (!result.ok) {
-                const text = await result.text();
-                console.log('Multimodal captioning request failed', result.statusText, text);
-                return response.status(500).send(text);
-            }
+        console.log('Multimodal captioning request', body);
 
-            const data = await result.json();
-            console.log('Multimodal captioning response', data);
-            const caption = data?.choices[0]?.message?.content;
+        let apiUrl = '';
+        let headers = {};
 
-            if (!caption) {
-                return response.status(500).send('No caption found');
-            }
-
-            return response.json({ caption });
+        if (request.body.api === 'openrouter') {
+            apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
+            headers['HTTP-Referer'] = request.headers.referer;
         }
-        catch (error) {
-            console.error(error);
-            response.status(500).send('Internal server error');
+
+        if (request.body.api === 'openai') {
+            apiUrl = 'https://api.openai.com/v1/chat/completions';
         }
-    });
 
-    app.post('/api/openai/transcribe-audio', urlencodedParser, async (request, response) => {
-        try {
-            const key = readSecret(SECRET_KEYS.OPENAI);
+        const result = await fetch(apiUrl, {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                Authorization: `Bearer ${key}`,
+                ...headers,
+            },
+            body: JSON.stringify(body),
+            timeout: 0,
+        });
 
-            if (!key) {
-                console.log('No OpenAI key found');
-                return response.sendStatus(401);
-            }
-
-            if (!request.file) {
-                console.log('No audio file found');
-                return response.sendStatus(400);
-            }
-
-            const formData = new FormData();
-            console.log('Processing audio file', request.file.path);
-            formData.append('file', fs.createReadStream(request.file.path), { filename: 'audio.wav', contentType: 'audio/wav' });
-            formData.append('model', request.body.model);
-
-            if (request.body.language) {
-                formData.append('language', request.body.language);
-            }
-
-            const result = await fetch('https://api.openai.com/v1/audio/transcriptions', {
-                method: 'POST',
-                headers: {
-                    'Authorization': `Bearer ${key}`,
-                    ...formData.getHeaders(),
-                },
-                body: formData,
-            });
-
-            if (!result.ok) {
-                const text = await result.text();
-                console.log('OpenAI request failed', result.statusText, text);
-                return response.status(500).send(text);
-            }
-
-            fs.rmSync(request.file.path);
-            const data = await result.json();
-            console.log('OpenAI transcription response', data);
-            return response.json(data);
-        } catch (error) {
-            console.error('OpenAI transcription failed', error);
-            response.status(500).send('Internal server error');
+        if (!result.ok) {
+            const text = await result.text();
+            console.log('Multimodal captioning request failed', result.statusText, text);
+            return response.status(500).send(text);
         }
-    });
 
-    app.post('/api/openai/generate-voice', jsonParser, async (request, response) => {
-        try {
-            const key = readSecret(SECRET_KEYS.OPENAI);
+        const data = await result.json();
+        console.log('Multimodal captioning response', data);
+        const caption = data?.choices[0]?.message?.content;
 
-            if (!key) {
-                console.log('No OpenAI key found');
-                return response.sendStatus(401);
-            }
-
-            const result = await fetch('https://api.openai.com/v1/audio/speech', {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json',
-                    Authorization: `Bearer ${key}`,
-                },
-                body: JSON.stringify({
-                    input: request.body.text,
-                    response_format: 'mp3',
-                    voice: request.body.voice ?? 'alloy',
-                    speed: request.body.speed ?? 1,
-                    model: request.body.model ?? 'tts-1',
-                }),
-            });
-
-            if (!result.ok) {
-                const text = await result.text();
-                console.log('OpenAI request failed', result.statusText, text);
-                return response.status(500).send(text);
-            }
-
-            const buffer = await result.arrayBuffer();
-            response.setHeader('Content-Type', 'audio/mpeg');
-            return response.send(Buffer.from(buffer));
-        } catch (error) {
-            console.error('OpenAI TTS generation failed', error);
-            response.status(500).send('Internal server error');
+        if (!caption) {
+            return response.status(500).send('No caption found');
         }
-    });
 
-    app.post('/api/openai/generate-image', jsonParser, async (request, response) => {
-        try {
-            const key = readSecret(SECRET_KEYS.OPENAI);
+        return response.json({ caption });
+    }
+    catch (error) {
+        console.error(error);
+        response.status(500).send('Internal server error');
+    }
+});
 
-            if (!key) {
-                console.log('No OpenAI key found');
-                return response.sendStatus(401);
-            }
+router.post('/transcribe-audio', urlencodedParser, async (request, response) => {
+    try {
+        const key = readSecret(SECRET_KEYS.OPENAI);
 
-            console.log('OpenAI request', request.body);
-
-            const result = await fetch('https://api.openai.com/v1/images/generations', {
-                method: 'POST',
-                headers: {
-                    'Content-Type': 'application/json',
-                    Authorization: `Bearer ${key}`,
-                },
-                body: JSON.stringify(request.body),
-                timeout: 0,
-            });
-
-            if (!result.ok) {
-                const text = await result.text();
-                console.log('OpenAI request failed', result.statusText, text);
-                return response.status(500).send(text);
-            }
-
-            const data = await result.json();
-            return response.json(data);
-        } catch (error) {
-            console.error(error);
-            response.status(500).send('Internal server error');
+        if (!key) {
+            console.log('No OpenAI key found');
+            return response.sendStatus(401);
         }
-    });
-}
 
-module.exports = {
-    registerEndpoints,
-};
+        if (!request.file) {
+            console.log('No audio file found');
+            return response.sendStatus(400);
+        }
+
+        const formData = new FormData();
+        console.log('Processing audio file', request.file.path);
+        formData.append('file', fs.createReadStream(request.file.path), { filename: 'audio.wav', contentType: 'audio/wav' });
+        formData.append('model', request.body.model);
+
+        if (request.body.language) {
+            formData.append('language', request.body.language);
+        }
+
+        const result = await fetch('https://api.openai.com/v1/audio/transcriptions', {
+            method: 'POST',
+            headers: {
+                'Authorization': `Bearer ${key}`,
+                ...formData.getHeaders(),
+            },
+            body: formData,
+        });
+
+        if (!result.ok) {
+            const text = await result.text();
+            console.log('OpenAI request failed', result.statusText, text);
+            return response.status(500).send(text);
+        }
+
+        fs.rmSync(request.file.path);
+        const data = await result.json();
+        console.log('OpenAI transcription response', data);
+        return response.json(data);
+    } catch (error) {
+        console.error('OpenAI transcription failed', error);
+        response.status(500).send('Internal server error');
+    }
+});
+
+router.post('/generate-voice', jsonParser, async (request, response) => {
+    try {
+        const key = readSecret(SECRET_KEYS.OPENAI);
+
+        if (!key) {
+            console.log('No OpenAI key found');
+            return response.sendStatus(401);
+        }
+
+        const result = await fetch('https://api.openai.com/v1/audio/speech', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                Authorization: `Bearer ${key}`,
+            },
+            body: JSON.stringify({
+                input: request.body.text,
+                response_format: 'mp3',
+                voice: request.body.voice ?? 'alloy',
+                speed: request.body.speed ?? 1,
+                model: request.body.model ?? 'tts-1',
+            }),
+        });
+
+        if (!result.ok) {
+            const text = await result.text();
+            console.log('OpenAI request failed', result.statusText, text);
+            return response.status(500).send(text);
+        }
+
+        const buffer = await result.arrayBuffer();
+        response.setHeader('Content-Type', 'audio/mpeg');
+        return response.send(Buffer.from(buffer));
+    } catch (error) {
+        console.error('OpenAI TTS generation failed', error);
+        response.status(500).send('Internal server error');
+    }
+});
+
+router.post('/generate-image', jsonParser, async (request, response) => {
+    try {
+        const key = readSecret(SECRET_KEYS.OPENAI);
+
+        if (!key) {
+            console.log('No OpenAI key found');
+            return response.sendStatus(401);
+        }
+
+        console.log('OpenAI request', request.body);
+
+        const result = await fetch('https://api.openai.com/v1/images/generations', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                Authorization: `Bearer ${key}`,
+            },
+            body: JSON.stringify(request.body),
+            timeout: 0,
+        });
+
+        if (!result.ok) {
+            const text = await result.text();
+            console.log('OpenAI request failed', result.statusText, text);
+            return response.status(500).send(text);
+        }
+
+        const data = await result.json();
+        return response.json(data);
+    } catch (error) {
+        console.error(error);
+        response.status(500).send('Internal server error');
+    }
+});
+
+module.exports = { router };