| import express from 'express'; |
| import fetch from 'node-fetch'; |
| import { v4 as uuidv4 } from 'uuid'; |
| import dotenv from 'dotenv'; |
| import { Buffer } from 'buffer'; |
|
|
| dotenv.config(); |
|
|
| const app = express(); |
|
|
|
|
| const modelMapping = { |
| "gpt-4o-mini": "GPT-4o mini", |
| "claude-haiku": "Claude Haiku", |
| "llama-3": "Llama 3", |
| "gemini-1.5": "Gemini 1.5", |
| "gemini-flash": "Gemini Flash", |
| "command-r": "Command R" |
| }; |
|
|
| app.use(express.json()); |
|
|
| const getCurrentTimestamp = () => Math.floor(Date.now() / 1000); |
|
|
| const splitIntoChunks = (text, chunkSize) => { |
| const chunks = []; |
| for (let i = 0; i < text.length; i += chunkSize) { |
| chunks.push(text.slice(i, i + chunkSize)); |
| } |
| return chunks; |
| }; |
|
|
| const getTempUserID = async () => { |
| try { |
| const response = await fetch('https://playground.julius.ai/api/temp_user_id'); |
| const data = await response.json(); |
| return data.temp_user_id; |
| } catch (error) { |
| throw new Error('Failed to get temp user ID'); |
| } |
| }; |
|
|
| const sendToJulius = async (tempUserID, message, model) => { |
| const conversationID = uuidv4(); |
| const juliusReq = { |
| message: { |
| content: message, |
| role: "user" |
| }, |
| provider: "default", |
| chat_mode: "auto", |
| client_version: "20240130", |
| theme: "dark", |
| selectedModels: [model] |
| }; |
|
|
| try { |
| const response = await fetch('https://playground.julius.ai/api/chat/message', { |
| method: 'POST', |
| headers: { |
| 'is-demo': tempUserID, |
| 'Content-Type': 'application/json', |
| 'Platform': 'web', |
| 'conversation-id': conversationID, |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' |
| }, |
| body: JSON.stringify(juliusReq) |
| }); |
|
|
| const reader = response.body.pipeThrough(new TextDecoderStream()).getReader(); |
| let fullResponse = ''; |
|
|
| while (true) { |
| const { done, value } = await reader.read(); |
| if (done) break; |
| |
| const lines = value.split('\n'); |
| for (const line of lines) { |
| try { |
| const jsonResp = JSON.parse(line); |
| if (jsonResp.content) { |
| fullResponse += jsonResp.content; |
| } |
| } catch (e) { |
| |
| } |
| } |
| } |
|
|
| return fullResponse; |
| } catch (error) { |
| throw new Error('Failed to send to Julius'); |
| } |
| }; |
|
|
| app.all('*', async (req, res) => { |
| |
| const authToken = process.env.AUTH_TOKEN; |
| if (authToken) { |
| const requestToken = req.headers.authorization?.replace('Bearer ', ''); |
| if (!requestToken || requestToken !== authToken) { |
| return res.status(401).send('Access Denied'); |
| } |
| } |
|
|
| |
| if (req.path !== '/v1/chat/completions') { |
| return res.json({ |
| status: "Julius2Api Service Running...", |
| message: "MoLoveSze..." |
| }); |
| } |
|
|
| if (req.method !== 'POST') { |
| return res.status(405).send('Method not allowed'); |
| } |
|
|
| try { |
| const openAIReq = req.body; |
| const isStream = openAIReq.stream || false; |
|
|
| |
| const mappedModel = modelMapping[openAIReq.model] || 'GPT-4o mini'; |
| openAIReq.model = mappedModel; |
|
|
| const tempUserID = await getTempUserID(); |
| const juliusResp = await sendToJulius(tempUserID, |
| openAIReq.messages[openAIReq.messages.length - 1].content, |
| mappedModel |
| ); |
|
|
| const respId = `chatcmpl-${tempUserID}`; |
| const created = getCurrentTimestamp(); |
|
|
| if (isStream) { |
| res.writeHead(200, { |
| 'Content-Type': 'text/event-stream', |
| 'Cache-Control': 'no-cache', |
| 'Connection': 'keep-alive' |
| }); |
|
|
| |
| const firstResponse = { |
| id: respId, |
| object: "chat.completion.chunk", |
| created: created, |
| model: mappedModel, |
| choices: [{ |
| delta: { role: "assistant" }, |
| index: 0 |
| }] |
| }; |
| res.write(`data: ${JSON.stringify(firstResponse)}\n\n`); |
|
|
| |
| const chunks = splitIntoChunks(juliusResp, 50); |
| chunks.forEach((chunk, index) => { |
| const response = { |
| id: respId, |
| object: "chat.completion.chunk", |
| created: created, |
| model: mappedModel, |
| choices: [{ |
| delta: { content: chunk }, |
| index: 0, |
| finish_reason: index === chunks.length - 1 ? 'stop' : null |
| }] |
| }; |
| res.write(`data: ${JSON.stringify(response)}\n\n`); |
| }); |
|
|
| res.write('data: [DONE]\n\n'); |
| res.end(); |
| } else { |
| const response = { |
| id: respId, |
| object: "chat.completion", |
| created: created, |
| model: mappedModel, |
| choices: [{ |
| message: { |
| role: "assistant", |
| content: juliusResp |
| }, |
| finish_reason: "stop" |
| }] |
| }; |
| res.json(response); |
| } |
| } catch (error) { |
| console.error(error); |
| res.status(500).send(error.message); |
| } |
| }); |
|
|
| const PORT = process.env.PORT || 3000; |
| app.listen(PORT, () => { |
| console.log(`Server running on port ${PORT}`); |
| }); |