realcoloride / node_characterai

Unofficial Character AI wrapper for node.
https://beta.character.ai/
341 stars 72 forks source link

problem when trying to continue the chat session #182

Closed aiprojectchiwa closed 3 weeks ago

aiprojectchiwa commented 3 weeks ago

Issue Description

I am encountering an issue in my project where attempting to change the chat ID results in starting a new session, even though a valid session ID is provided. Below is the relevant code:

// ==== START CAI ====
const CharacterAI = require('node_characterai');
const characterAI = new CharacterAI();

characterAI.puppeteerPath = '/usr/bin/chromium';

let sessionToken;

// Temporary session storage
const sessionStore = {};

async function authenticate() {
    if (!sessionToken) {
        sessionToken = await characterAI.authenticateWithToken('IM_FORGOT_TO_CENSOR_THE_TOKEN_LOL');
    }
}

async function ensureSession(sessionId, characterId) {
    try {
        let chat;
        if (sessionId) {
            // Create chat with the existing sessionId
            chat = new characterAI.Chat(characterAI, characterId, { external_id: sessionId });

            // Switch to the provided chat session
            await chat.changeToConversationId(sessionId, false);
        } else {
            // If no sessionId, create a new session
            chat = await characterAI.createOrContinueChat(characterId || 'xnSbLWXop06fpWEKz-VKImTjIgQw3-PiRGmqfoziFFA');
            await chat.saveAndStartNewChat();
        }

        return chat;
    } catch (error) {
        console.error('Error handling session:', error);
        throw error;
    }
}

app.get('/api/v2/cai', async (req, res) => {
    const { message, sessionId } = req.query;

    try {
        await authenticate();

        let chat;
        let response;
        let sessionMessage = '';

        if (sessionId && sessionStore[sessionId]) {
            // Continue existing session and switch to the provided chat
            const { characterId } = sessionStore[sessionId];
            chat = await ensureSession(sessionId, characterId);
            sessionMessage = 'Using existing session and switching to the desired chat';
        } else {
            // Create a new session if sessionId is not provided or not found in store
            const chosenCharacterId = 'xnSbLWXop06fpWEKz-VKImTjIgQw3-PiRGmqfoziFFA';
            chat = await ensureSession(null, chosenCharacterId);

            // Use externalId from chat as sessionId
            const newSessionId = chat.externalId;
            sessionStore[newSessionId] = {
                characterId: chat.characterId,
                sessionId: newSessionId
            };

            sessionMessage = 'Using new session';
        }

        try {
            // Send message
            response = await chat.sendAndAwaitResponse(message, true);

            // Save chat and start new chat after sending the message
            const savedChat = await chat.saveAndStartNewChat();

            // Capture new chat ID after saving
            const newChatId = savedChat.externalId;

            res.json({
                success: true,
                sessionMessage: sessionMessage,
                sessionId: sessionId || chat.externalId,  // Send the existing or new sessionId to client
                newChatId: newChatId,  // Sending new chat ID
                result: {
                    text: response.text,
                    id: response.id,
                    srcCharacterName: response.srcCharacterName,
                    srcAvatarFileName: response.srcAvatarFileName,
                    isFinalChunk: response.isFinalChunk,
                    lastUserMessageId: response.lastUserMessageId,
                    characterId: chat.characterId
                }
            });

        } catch (error) {
            console.error('Error sending message:', error);
            res.status(500).send('Error sending message');
        }
    } catch (error) {
        console.error('Error:', error);
        res.status(500).send('Something went wrong');
    }
});
// ==== END CAI ====

Expected Behavior

When I provide a valid session ID, I expect the chat to continue within the same session rather than starting a new session.

Actual Behavior

Despite providing a valid session ID, a new session is initiated instead of continuing the existing one.

Steps to Reproduce

  1. Run the code provided above.
  2. Supply a valid session ID in the sessionId query parameter.
  3. Observe that a new session is started instead of continuing with the provided session.

Environment

Additional Context

Create a Session

/api/v2/cai?characterId=xnSbLWXop06fpWEKz-VKImTjIgQw3-PiRGmqfoziFFA&sessionId=&message=hi

Response

{
  "success": true,
  "sessionMessage": "Using new session",
  "sessionId": "Jv1Vp77jofSpSLJWQ3Ci0xv4_crE1u5vvohGu00JqwI",
  "result": {
    "text": "*Chino looking at the patron who was just staring at the menu*\n\nYou need help with choosing a coffee?",
    "id": "1023372048201371294",
    "srcCharacterName": "Chino Kafuu",
    "srcAvatarFileName": "uploaded/2022/10/19/nrF9qOI9hk4TtWJbatN0IJ_7_zv3VA0H_6nOs-lll-8.webp",
    "isFinalChunk": true,
    "lastUserMessageId": 0,
    "characterId": "xnSbLWXop06fpWEKz-VKImTjIgQw3-PiRGmqfoziFFA"
  }
}

Attempt to Continue the Session

Despite using the same session ID, the response indicates a new session is being created:

{
  "success": true,
  "sessionMessage": "Using new session",
  "sessionId": "Jv1Vp77jofSpSLJWQ3Ci0xv4_crE1u5vvohGu00JqwI",
  "result": {
    "text": "Can you please repeat that? Or write the question in English?",
    "id": "223372047844464454",
    "srcCharacterName": "Chino Kafuu",
    "srcAvatarFileName": "uploaded/2022/10/19/nrF9qOI9hk4TtWJbatN0IJ_7_zv3VA0H_6nOs-lll-8.webp",
    "isFinalChunk": true,
    "lastUserMessageId": "223372047844464453",
    "characterId": "xnSbLWXop06fpWEKz-VKImTjIgQw3-PiRGmqfoziFFA"
  }
}

Request for Assistance

I am not entirely sure if the logic in the code is correct according to how the node_characterai module is supposed to work. Could someone please review the logic and confirm whether it is accurate? Any guidance or suggestions for improvement would be greatly appreciated.

realcoloride commented 3 weeks ago

Hello! You are not using node_characterai correctly.

Introduction

The way node_characterai works is meant to simulate the way you would use the website. As such, you should treat the code like the way you would interact with the website as a regular user.

The problem

image

Chat instances are NOT supposed to be created. The client is in charge of fetching and loading a conversation correctly. image

_Source: client.js_

Instead, use await characterAI.createOrContinueChat(characterId);. You can also specify a specific external conversation id to continue a conversation. image

The client will return a new Chat object that contains the conversation and what you need to chat with your character. chat. ... -> interact with the conversation that you fetched.

You can use createOrContinueChat as long as you need to store conversations. Remember: you are storing a CHAT object, so you will have to manage these objects yourself.

Using changeToConversationId will reset the chat object to an externalId (conversation identifier) whilst saveAndStartNewChat will reset and directly switch the externalId.

The solution

image

When mentioning to continue a conversation, I recommend you use the chat that you need to continue with. Eg, if you've used createOrContinueChat and you have a conversation where you're talking about fruits, and one other about vegetables, you need to keep both chat objects in order to get both conversations running. Eg:

// you wish to talk about fruits, use this one.
let fruitsConversation = await characterAI.createOrContinueChat(characterId, fruitConversationExternalId);

// you wish to talk about vegetables, use this one.
let vegetablesConversation = await characterAI.createOrContinueChat(characterId, vegetablesConversationExternalId);

Conclusion

If you're still confused about how the package works, it should be fairly straightforward, but I recommend you review the client.js and chat.js file for more information.

realcoloride commented 3 weeks ago

Since this is not a problem related to the actual package itself, I will close the issue. Feel free to re-open however if you need to or open a new issue if you need.