OvidijusParsiunas / deep-chat

Fully customizable AI chatbot component for your website
https://deepchat.dev
MIT License
1.43k stars 218 forks source link

OpenAI Assistants - continue conversation #115

Closed jackitaliano closed 7 months ago

jackitaliano commented 7 months ago

Scenario

My thought for solution

  1. Deepchat consumer saves OpenAI thread id in local storage
  2. Deepchat allows setting thread_id in onComponentRender similar to what can be done for chatElementRef.directConnection.openAI.assistant.assistant_id
  3. Either deepchat loads conversation history from thread, or consumer loads messages themselves with initialMessages. a. If consumer loads message, deepchat would still retain thread_id set by consumer

My request

Reason

Similar Requests

Save and Retrieve Chat Sessions | Issue #49

In the comments of this request, you mentioned adding a way to load messages, but merely loading messages in the UI is not as useful as loading a thread for the purposes of an assistant.

Example Psuedocode

<deep-chat
    onComponentRender = function() {
        ...
        const local_thread_id = localstorage.getItem('openai-thread-id');
        if (local_thread_id) {
            chatElementRef.directConnection.openAI.assistant.thread_id = local_thread_id;
        }
        ...
    }
...
/>

I'm open to other solutions to this issue if you have any ideas, or maybe I'm missing something that might already solve this (though I feel I have thoroughly searched).

The work you're doing is fantastic, thank you very much!

OvidijusParsiunas commented 7 months ago

Hi @jackitaliano. Just so I understand correctly, you want to set the thread_id and automatically start the chat with the previous messages being pre-populated in the chat box?

jackitaliano commented 7 months ago

Hi @jackitaliano. Just so I understand correctly, you want to set the thread_id and automatically start the chat with the previous messages being pre-populated in the chat box?

Hello @OvidijusParsiunas

That would be the ideal solution for me.

The main thing is being able to set the thread_id so the assistant has the context of thread. With the current deep-chat api and docs, it is certainly possible for me to pre-populate the previous messages in the chat box; however, I am not able to give those messages to the Assistant as I'd like to.

In the case where no thread_id is set by the consumer, it would default to it's current functionality.

If you're willing/able to implement both setting the thread_id and pre-populating the chat, that would be even better.

Thanks for the response!

OvidijusParsiunas commented 7 months ago

Let me see what I can do. I'll try out a couple of things and give you an update on what's possible. Depending on the complexity of the solution I may need to continue this tomorrow as it is quite late where I live. I'll give you an update as soon as I have something. Thanks!

jackitaliano commented 7 months ago

Let me see what I can do. I'll try out a couple of things and give you an update on what's possible. Depending on the complexity of the solution I may need to continue this tomorrow as it is quite late where I live. I'll give you an update as soon as I have something. Thanks!

Great! No problem at all if you're not able to complete it tonight. Thanks.

OvidijusParsiunas commented 7 months ago

Hi. I have updated the assistant interface with two new properties - thread_id and load_thread_history. Full interface:

interface OpenAIAssistant {
  assistant_id?: string;
  thread_id?: string;
  load_thread_history?: boolean;
  new_assistant?: OpenAINewAssistant;
  function_handler?: AssistantFunctionHandler;
}

When thread_id is set, the conversation will continue using that thread. When load_thread_history is also set, it will attempt to fetch that thread's history and populate the messages. The reason for using the second property is that devs may want to store messages on their end and use initialMessages instead, or they may not want the extra fetch API call every time the chat loads up, hence they can use it to set their preference.

Example usage:

directConnection = {
  openAI: {
    assistant: {thread_id: 'thread-id-here', load_thread_history: true},
    key: 'api-key-here',
  },
}

This is available in deep-chat-dev and deep-chat-react-dev packages version 9.0.127. These packages work exactly the same as the normal ones except their names are different.

Let me know if this works for you and I will promote these changes for the next core package release later this week.

Thanks!

jackitaliano commented 7 months ago

This works great, thank you very much!

For anyone seeing this in the future, this is roughly my first shot implementation: (not exact because contains validation/logic not relevant here):

(svelte)

async function getThread() { return localStorage.getItem('openai-thread-id'); }
async function setThread(thread_id) { localStorage.setItem('openai-thread-id', thread_id); }

let openAIThreadIdSet = false;

{#await getThread() then thread_id}
<deep-chat
    onNewMessage = {async function(message) {
        ...
        if (!openAIThreadIdSet && message.message._sessionId && message.message._sessionId != thread_id) {
          setThread(message.message._sessionId);
          openAIThreadIdSet = true;
        }
        ...
    }}
     directConnection={{
        openAI: {
          ...
          assistant: {
            ...
            thread_id: thread_id,
            load_thread_history: thread_id ? true : false,
            ...
          }
        }
      }}
...
/>
OvidijusParsiunas commented 7 months ago

This has now been released in Deep Chat version 1.4.11. Checkout the updated assistant documentation for more.