KudoAI / chatgpt.js

🤖 A powerful, open source client-side JavaScript library for ChatGPT
https://chatgpt.js.org
MIT License
1.86k stars 122 forks source link

Rewriting getResponse #78

Closed madkarmaa closed 1 year ago

madkarmaa commented 1 year ago

I'm using a userscript I made to rewrite the fetch function calls and log the details, and I found an API-way to get a response. I'm working on it, and it might even be better than the DOM solution

const endpoints = {
    session: 'https://chat.openai.com/api/auth/session',
    chat: 'https://chat.openai.com/backend-api/conversations',
    singleChat: 'https://chat.openai.com/backend-api/conversation'
};

    test: function(chatIdx, responseIdx, regeneratedIdx) {
        chatIdx = chatIdx ? chatIdx : 0; // leave it as is because getChatDetails already takes care of the -1
        responseIdx = responseIdx ? responseIdx - 1 : 0;
        regeneratedIdx = regeneratedIdx ? regeneratedIdx - 1 : 0;
        return new Promise((resolve) => { chatgpt.getAccessToken().then(token => {
            getChatData(token).then(data => { resolve(data); });});});

        function getChatData(token) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                chatgpt.getChatDetails(chatIdx).then(chat => {
                    xhr.open('GET', endpoints.singleChat + '/' + chat.id, true); // GET request to the conversation
                    xhr.setRequestHeader('Content-Type', 'application/json');
                    xhr.setRequestHeader('Authorization', 'Bearer ' + token);
                    xhr.onload = () => {
                        if (xhr.status !== 200) return reject('🤖 chatgpt.js >> Request failed. Cannot retrieve chat messages.');
                        const data = JSON.parse(xhr.responseText).mapping; // all messages
                        const userMessages = [];
                        const responses = [];
                        for (const key in data) if (data[key].message && data[key].message.author.role === 'user') userMessages.push(data[key].id); // filter out user messages
                        for (const key in data)
                            // match responses with their indexed parent (user message)
                            if (data[key].message && data[key].message.author.role === 'assistant' && data[key].parent === userMessages[responseIdx]) // use responseIdx because at each user message corresponds a response so it doesn't matter if the variable says response
                                responses.push(data[key].message); // push only chatgpt responses
                        responses.sort((a, b) => a.create_time - b.create_time); // sort by creation time (in case of the response being regenerated)
                        resolve(responses[regeneratedIdx].content.parts[0]); // resolve promise giving the regenerate value requested
                    };
                    xhr.send();
                });
        });}
    },
adamlui commented 1 year ago

Then we can eventually market it as ultimate frontend + backend lib when all the components will be there to use on any site, which is really just getAccessToken + getReply(prompt)

adamlui commented 1 year ago

My DDGPT and bravegpt scripts already do this you can copy the logic from there

madkarmaa commented 1 year ago

@adamlui for some reason getChatDetails inside of the test function keeps returning me the whole object, that's why I used .id instead of passing the id argument string

madkarmaa commented 1 year ago

but if I call it alone it works perfectly

adamlui commented 1 year ago

..but I never implemented using /conversation , instead for continuation I sent a previous reply as part of prompt

adamlui commented 1 year ago

(but /conversation obviously better)

madkarmaa commented 1 year ago

I've left some comments so it's easier to understand. install this userscript so you can see the fetch requests' data the function is in a raw state and has no name and it can be done better

// ==UserScript==
// @name        Requests checker | ChatGPT
// @namespace   Violentmonkey Scripts
// @match       https://chat.openai.com/*
// @grant       none
// @version     1.0
// @author      -
// @description 7/9/2023, 3:21:31 PM
// @run-at      document-start
// ==/UserScript==

(async () => {

const originalFetch = window.fetch;

window.fetch = function (url, options) {
  return originalFetch.apply(this, arguments)
    .then((response) => {
      let resp = response.clone();
      resp.json().then((data) => {
        console.log(resp.url, '\n\n', JSON.parse(JSON.stringify(options)), '\n\n', data);
      });
      return response;
    });
};

})();
adamlui commented 1 year ago

Ok I'm currently adding some functions to the chatgpt.js-chrome-starter then i'll check it out

madkarmaa commented 1 year ago

by 'it can be done better' I mean that it can be more user friendly, I suck at this 😭

madkarmaa commented 1 year ago

how's it going with the method? also, if you need help with translations, I can help you with my language

adamlui commented 1 year ago

@madkarmaa i didn't look at it yet but will now, also yes your language would be good