const axios = require('axios');
const http = require('http');

function prepareJSON(messages) {
    let question = ""
    if(messages[messages.length - 1].role === "system") {
        question = messages.pop().content
        question = messages.pop().content + "\n" + question
    }
    else question = messages.pop().content
    history = new Array()
    for (let i = 0; i < messages.length; i += 2) {
        if (i + 1 < messages.length) {
            history.push([messages[i].content, messages[i + 1].content]);
        } else {
            history.push([messages[i].content]);
        }
      }

    const data = {
        question,
        history,
        newTextInput: ""
    }
    return data
}

const readBody = (res, json, onData) => new Promise((resolve, reject) => {
    let buffer = '';

    res.on('data', chunk => {
        onData?.(chunk.toString());
        buffer += chunk;
    });

    res.on('end', () => {
        try {
            if (json) buffer = JSON.parse(buffer);
            resolve(buffer);
        } catch (e) {
            console.error(buffer);
            reject(e);
        }
    });
})

async function generate(body, onData) {
    const data = prepareJSON(body)

    const headers = {
        "Host": "api-server.langchain.rozetta-deveopment-beta.rozetta-dxtravel.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0",  
        "Accept": "text/event-stream",
        "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
        "Accept-Encoding": "gzip, deflate, br",
        "Referer": "http://183.91.14.181:3001/",
        "Content-Type": "application/json",
        "Content-Length": Buffer.byteLength(JSON.stringify(data)),
        "Origin": "http://183.91.14.181:3001",
        "Connection": "keep-alive",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "cross-site",
    };


    return new Promise(async (resolve, reject) => {
      try {
        let buffer = ""
        const responseStream = await axios.default({
            method: 'POST',
            url: 'https://api-server.langchain.rozetta-deveopment-beta.rozetta-dxtravel.com/api/anth',
            headers,
            data,
            responseType: 'stream'
        });

        responseStream.data.on('data', async (chunk) => {
            let c = chunk.toString().trim()
            if(c.substr(6) !== '[DONE]') {
                if(chunk.toString().trim().split("\n").length-1) { 
                    c = chunk.toString().trim().split("\n")
                    for(i = 0; i <= c.length - 1; i+=2) {
                        let parsedData = JSON.parse(c[i].substr(6))
                        buffer += parsedData.data
                        await onData(parsedData.data);
                    }
                }
                else {
                    c = JSON.parse(c.substr(6))
                    buffer += c.data
                    await onData(c.data);
                }
            }
        });

        responseStream.data.on('end', () => {
            resolve(buffer);
        });

        responseStream.data.on('error', (error) => {
            console.log("Error:",error)
            reject(error);
        });
      } catch (error) {
        console.error(`Error: ${error.message}`);
        reject(error);
      }
    });
}

async function main() {
    const server = http.createServer(async (req, res) => {
        if (req.method.toUpperCase() === 'POST') {
            const body = await readBody(req, true);
            const {
                messages,
                stream
            } = body;
            res.setHeader('Content-Type', 'application/json');
            const id = `chatcmpl-${(Math.random().toString(36).slice(2))}`;
            const created = Math.floor(Date.now() / 1000);

            if (stream) {
                const data = JSON.stringify({
                    id, created,
                    object: 'chat.completion.chunk',
                    model: "Claude",
                    choices: [{
                        delta: { role: 'assistant' },
                        finish_reason: null,
                        index: 0,
                    }],
                });
                res.write(`data: ${data}\n\n`);
            }

            let result = ""
            console.log("Ожидаем ответа...")
            result = await generate(messages,
                (line) => {
                    if (stream) {
                        process.stdout.write(".");
                        const data = JSON.stringify({
                            id, created,
                            object: 'chat.completion.chunk',
                            model: "Claude",
                            choices: [{
                                delta: { content: line },
                                finish_reason: null,
                                index: 0,
                            }]
                        });
                        res.write(`data: ${data}\n\n`);
                    }
                });
            if (stream) {
                const data = JSON.stringify({
                    id, created,
                    object: 'chat.completion.chunk',
                    model: "Claude",
                    choices: [{
                        delta: {},
                        finish_reason: 'stop',
                        index: 0,
                    }],
                });
                res.write(`data: ${data}\n\ndata: [DONE]\n\n`);
            } else {
                if(result) result = result.replace(/\\n/g, ' \n').replace(/\\"/g, '"')
                res.write(JSON.stringify({
                    id, created,
                    object: 'chat.completion',
                    model: "Claude",
                    choices: [{
                        message: {
                            role: 'assistant',
                            content: result,
                        },
                        finish_reason: 'stop',
                        index: 0,
                    }]
                }));
            }
            res.end();
        } else {
            res.setHeader('Content-Type', 'application/json');
            res.write(JSON.stringify({
                object: 'list',
                data: [
                    { id: 'Claude', object: 'model', created: Date.now(), owned_by: 'Anthropic', permission: [], root: 'Claude', parent: null },
                ]
            }));
        }
        res.end();
    });

    server.listen(5009, '0.0.0.0', () => {
        console.log(`proxy for shikiho: 'http://127.0.0.1:5009/'`);
    });
}

main().catch(console.error);
Edit
Pub: 20 Jun 2023 09:11 UTC
Edit: 20 Jun 2023 09:43 UTC
Views: 15008