| const express = require('express'); |
| const fetch = require('node-fetch'); |
| const crypto = require('crypto'); |
| const { v4: uuidv4 } = require('uuid'); |
|
|
| const app = express(); |
| const port = 8000; |
| const next_action = process.env.NEXT_ACTION; |
| const Auth_key = process.env.AUTH_KEY; |
|
|
| const NOTDIAMOND_URL = 'https://chat.notdiamond.ai/mini-chat'; |
| const NOTDIAMOND_HEADERS = { |
| 'Content-Type': 'application/json', |
| 'accept': '*/*', |
| 'next-action': `${next_action}`, |
| 'accept-language': 'en,en-US;q=0.9', |
| 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' |
| }; |
|
|
| const DEFAULT_MODEL = 'gpt-4-turbo'; |
|
|
| const MODEL_MAPPING = { |
| 'gpt-4o-mini': 'gpt-4o-mini', |
| 'gpt-4o': 'gpt-4o', |
| 'gpt-4-turbo': 'gpt-4-turbo-2024-04-09', |
| 'claude-3-haiku-20240307': 'anthropic.claude-3-haiku-20240307-v1:0', |
| 'claude-3-5-sonnet-20240620': 'anthropic.claude-3-5-sonnet-20240620-v1:0', |
| 'gemini-1.5-pro-latest': 'models/gemini-1.5-pro-latest', |
| 'gemini-1.5-pro-exp-0801': 'models/gemini-1.5-pro-exp-0801', |
| 'llama-3.1-405b-instruct': 'meta.llama3-1-405b-instruct-v1:0', |
| 'llama-3.1-70b-instruct': 'meta.llama3-1-70b-instruct-v1:0', |
| 'perplexity': 'llama-3.1-sonar-large-128k-online' |
| }; |
|
|
| function getAuthKey(req) { |
| const authHeader = req.headers['authorization']; |
| if (authHeader && authHeader.startsWith('Bearer ')) { |
| return authHeader.slice(7); |
| } |
| return null; |
| } |
|
|
| function generateSystemFingerprint() { |
| return `fp_${uuidv4().replace(/-/g, '').substr(0, 10)}`; |
| } |
| const systemFingerprint = generateSystemFingerprint(); |
|
|
| function createOpenAIChunk(content, model, finishReason = null) { |
| return { |
| id: `chatcmpl-${crypto.randomUUID()}`, |
| object: "chat.completion.chunk", |
| created: Math.floor(Date.now() / 1000), |
| model: model, |
| system_fingerprint: systemFingerprint, |
| choices: [ |
| { |
| index: 0, |
| delta: content ? { content: content } : {}, |
| logprobs: null, |
| finish_reason: finishReason |
| } |
| ], |
| usage: null |
| }; |
| } |
|
|
| async function* streamNotdiamondResponse(response, model) { |
| let buffer = ""; |
| let lastContent = ""; |
|
|
| function processDollars(str) { |
| return str.replace(/\${2,}/, match => match.slice(1)); |
| } |
|
|
| for await (const chunk of response.body) { |
| buffer += chunk.toString(); |
| let lines = buffer.split('\n'); |
| buffer = lines.pop() || ""; |
|
|
| for (const line of lines) { |
| if (line.trim() === '') continue; |
| |
| try { |
| const jsonMatch = line.match(/\{.*\}/); |
| if (jsonMatch) { |
| const data = JSON.parse(jsonMatch[0]); |
| let content = ''; |
| |
| if (data.output?.curr !== undefined) { |
| content = processDollars(data.output.curr); |
| lastContent = content; |
| } else if (data.curr !== undefined) { |
| content = processDollars(data.curr); |
| lastContent = content; |
| } else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length > 1) { |
| const newContent = processDollars(data.diff[1]); |
| content = lastContent + newContent; |
| lastContent = content; |
| } else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length === 1) { |
| content = lastContent; |
| } |
| |
| if (content) { |
| yield createOpenAIChunk(content, model); |
| } |
| } |
| } catch (error) { |
| console.error('Error processing line:', error, 'Raw line:', line); |
| } |
| } |
| } |
|
|
| if (buffer.trim()) { |
| try { |
| const jsonMatch = buffer.match(/\{.*\}/); |
| if (jsonMatch) { |
| const data = JSON.parse(jsonMatch[0]); |
| let content = ''; |
| if (data.output?.curr !== undefined) { |
| content = processDollars(data.output.curr); |
| } else if (data.curr !== undefined) { |
| content = processDollars(data.curr); |
| } else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length > 1) { |
| const newContent = processDollars(data.diff[1]); |
| content = lastContent + newContent; |
| } else if (data.diff !== undefined && Array.isArray(data.diff) && data.diff.length === 1) { |
| content = lastContent; |
| } |
| if (content) { |
| yield createOpenAIChunk(content, model); |
| } |
| } |
| } catch (error) { |
| console.error('Error processing final buffer:', error); |
| } |
| } |
|
|
| yield createOpenAIChunk('', model, 'stop'); |
| } |
|
|
| app.use(express.json()); |
|
|
| app.get('/ai/v1/models', (req, res) => { |
| const authKey = getAuthKey(req); |
| if (authKey !== process.env.AUTH_KEY) { |
| return res.status(401).json({ error: 'Unauthorized' }); |
| } |
|
|
| res.json({ |
| object: "list", |
| data: Object.keys(MODEL_MAPPING).map(model => ({ |
| id: model, |
| object: "model", |
| created: Math.floor(Date.now() / 1000), |
| owned_by: "notdiamond" |
| })) |
| }); |
|
|
| console.log(`${new Date().toISOString()} - ${req.ip || req.connection.remoteAddress} - GET /ai/v1/models - 200`); |
| }); |
|
|
| app.post('/ai/v1/chat/completions', async (req, res) => { |
| const startTime = new Date(); |
| const clientIP = req.ip || req.connection.remoteAddress; |
| let userModel = req.body.model || DEFAULT_MODEL; |
| let status = 200; |
|
|
| try { |
| const authKey = getAuthKey(req); |
| if (authKey !== process.env.AUTH_KEY) { |
| status = 401; |
| throw new Error('Unauthorized'); |
| } |
|
|
| let requestData = req.body; |
| let messages = requestData.messages; |
| let model = MODEL_MAPPING[userModel] || userModel; |
| const stream = requestData.stream || false; |
|
|
| if (!messages || !Array.isArray(messages)) { |
| status = 400; |
| throw new Error('Invalid request body: messages should be an array of message objects'); |
| } |
|
|
| const payload = { |
| messages: messages, |
| model: model, |
| stream: stream, |
| frequency_penalty: requestData.frequency_penalty || 0, |
| presence_penalty: requestData.presence_penalty || 0, |
| temperature: requestData.temperature || 0.8, |
| top_p: requestData.top_p || 1 |
| }; |
|
|
| const headers = { |
| 'Content-Type': 'application/json', |
| 'accept': '*/*', |
| 'next-action': `${next_action}`, |
| 'accept-language': 'en,en-US;q=0.9', |
| 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', |
| }; |
|
|
| const response = await fetch(NOTDIAMOND_URL, { |
| method: 'POST', |
| headers: headers, |
| body: JSON.stringify([payload]) |
| }); |
|
|
| const generator = streamNotdiamondResponse(response, model); |
| |
| if (stream) { |
| res.writeHead(200, { |
| 'Content-Type': 'text/event-stream', |
| 'Cache-Control': 'no-cache', |
| 'Connection': 'keep-alive' |
| }); |
|
|
| for await (const chunk of generator) { |
| res.write(`data: ${JSON.stringify(chunk)}\n\n`); |
| } |
| res.write("data: [DONE]\n\n"); |
| res.end(); |
| } else { |
| let fullContent = ""; |
| for await (const chunk of generator) { |
| if (chunk.choices[0].delta.content) { |
| fullContent += chunk.choices[0].delta.content; |
| } |
| } |
|
|
| res.json({ |
| id: `chatcmpl-${crypto.randomUUID()}`, |
| object: "chat.completion", |
| created: Math.floor(Date.now() / 1000), |
| model: userModel, |
| system_fingerprint: systemFingerprint, |
| choices: [ |
| { |
| index: 0, |
| message: { |
| role: "assistant", |
| content: fullContent |
| }, |
| finish_reason: "stop" |
| } |
| ], |
| usage: { |
| prompt_tokens: Math.floor(fullContent.length / 4), |
| completion_tokens: Math.floor(fullContent.length / 4), |
| total_tokens: Math.floor(fullContent.length / 2) |
| } |
| }); |
| } |
| } catch (error) { |
| status = status === 200 ? 500 : status; |
| res.status(status).json({ |
| error: 'Error', |
| details: error.message |
| }); |
| } finally { |
| const endTime = new Date(); |
| const duration = endTime - startTime; |
| console.log(`${endTime.toISOString()} - ${clientIP} - ${userModel} - ${status} - ${duration}ms`); |
| } |
| }); |
|
|
| app.listen(port, () => { |
| console.log(`Server running on port ${port}`); |
| }); |