2023-03-28 20:36:21 +08:00
|
|
|
import models from './models';
|
2023-03-28 22:39:27 +08:00
|
|
|
import {
|
|
|
|
|
atom,
|
|
|
|
|
selector,
|
|
|
|
|
useRecoilValue,
|
|
|
|
|
useSetRecoilState,
|
|
|
|
|
useResetRecoilState,
|
|
|
|
|
useRecoilCallback,
|
|
|
|
|
useRecoilState
|
|
|
|
|
} from 'recoil';
|
2023-03-28 20:36:21 +08:00
|
|
|
import buildTree from '~/utils/buildTree';
|
|
|
|
|
|
|
|
|
|
// current conversation, can be null (need to be fetched from server)
|
|
|
|
|
// sample structure
|
|
|
|
|
// {
|
|
|
|
|
// conversationId: "new",
|
|
|
|
|
// title: "New Chat",
|
|
|
|
|
// jailbreakConversationId: null,
|
|
|
|
|
// conversationSignature: null,
|
|
|
|
|
// clientId: null,
|
|
|
|
|
// invocationId: null,
|
|
|
|
|
// model: "chatgpt",
|
|
|
|
|
// chatGptLabel: null,
|
|
|
|
|
// promptPrefix: null,
|
|
|
|
|
// user: null,
|
|
|
|
|
// suggestions: [],
|
|
|
|
|
// toneStyle: null,
|
|
|
|
|
// }
|
|
|
|
|
const conversation = atom({
|
|
|
|
|
key: 'conversation',
|
|
|
|
|
default: null
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// current messages of the conversation, must be an array
|
|
|
|
|
// sample structure
|
|
|
|
|
// [{text, sender, messageId, parentMessageId, isCreatedByUser}]
|
|
|
|
|
const messages = atom({
|
|
|
|
|
key: 'messages',
|
|
|
|
|
default: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const messagesTree = selector({
|
|
|
|
|
key: 'messagesTree',
|
|
|
|
|
get: ({ get }) => {
|
|
|
|
|
return buildTree(get(messages));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const latestMessage = atom({
|
|
|
|
|
key: 'latestMessage',
|
|
|
|
|
default: null
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const useConversation = () => {
|
|
|
|
|
const setConversation = useSetRecoilState(conversation);
|
|
|
|
|
const setMessages = useSetRecoilState(messages);
|
|
|
|
|
const resetLatestMessage = useResetRecoilState(latestMessage);
|
|
|
|
|
|
2023-03-28 22:39:27 +08:00
|
|
|
const switchToConversation = useRecoilCallback(
|
|
|
|
|
({ snapshot }) =>
|
|
|
|
|
async (_conversation, messages = null) => {
|
|
|
|
|
const prevConversation = await snapshot.getPromise(conversation);
|
|
|
|
|
const prevModelsFilter = await snapshot.getPromise(models.modelsFilter);
|
|
|
|
|
_switchToConversation(_conversation, messages, { prevModelsFilter, prevConversation });
|
|
|
|
|
},
|
|
|
|
|
[]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const _switchToConversation = (
|
|
|
|
|
conversation,
|
|
|
|
|
messages = null,
|
|
|
|
|
{ prevModelsFilter = {}, prev_conversation = {} }
|
|
|
|
|
) => {
|
|
|
|
|
let { model = null, chatGptLabel = null, promptPrefix = null } = conversation;
|
2023-03-28 20:36:21 +08:00
|
|
|
const getDefaultModel = () => {
|
2023-03-28 22:39:27 +08:00
|
|
|
try {
|
|
|
|
|
// try to use current model
|
|
|
|
|
const { _model = null, _chatGptLabel = null, _promptPrefix = null } = prev_conversation || {};
|
|
|
|
|
console.log(_model, _chatGptLabel, _promptPrefix);
|
|
|
|
|
if (prevModelsFilter[_model]) {
|
|
|
|
|
model = _model;
|
|
|
|
|
chatGptLabel = _chatGptLabel;
|
|
|
|
|
promptPrefix = _promptPrefix;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {}
|
|
|
|
|
|
2023-03-28 20:36:21 +08:00
|
|
|
try {
|
|
|
|
|
// try to read latest selected model from local storage
|
|
|
|
|
const lastSelected = JSON.parse(localStorage.getItem('model'));
|
|
|
|
|
const { model: _model, chatGptLabel: _chatGptLabel, promptPrefix: _promptPrefix } = lastSelected;
|
|
|
|
|
|
2023-03-28 22:39:27 +08:00
|
|
|
if (prevModelsFilter[_model]) {
|
2023-03-28 20:36:21 +08:00
|
|
|
model = _model;
|
|
|
|
|
chatGptLabel = _chatGptLabel;
|
|
|
|
|
promptPrefix = _promptPrefix;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {}
|
|
|
|
|
|
|
|
|
|
// if anything happens, reset to default model
|
2023-03-28 22:39:27 +08:00
|
|
|
if (prevModelsFilter?.chatgpt) model = 'chatgpt';
|
|
|
|
|
else if (prevModelsFilter?.bingai) model = 'bingai';
|
|
|
|
|
else if (prevModelsFilter?.chatgptBrowser) model = 'chatgptBrowser';
|
2023-03-28 20:36:21 +08:00
|
|
|
chatGptLabel = null;
|
|
|
|
|
promptPrefix = null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (model === null)
|
|
|
|
|
// get the default model
|
|
|
|
|
getDefaultModel();
|
|
|
|
|
|
|
|
|
|
setConversation({
|
2023-03-28 22:39:27 +08:00
|
|
|
...conversation,
|
2023-03-28 20:36:21 +08:00
|
|
|
model: model,
|
|
|
|
|
chatGptLabel: chatGptLabel,
|
2023-03-28 22:39:27 +08:00
|
|
|
promptPrefix: promptPrefix
|
2023-03-28 20:36:21 +08:00
|
|
|
});
|
2023-03-28 22:39:27 +08:00
|
|
|
setMessages(messages);
|
2023-03-28 20:36:21 +08:00
|
|
|
resetLatestMessage();
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-28 22:39:27 +08:00
|
|
|
const newConversation = ({ model = null, chatGptLabel = null, promptPrefix = null } = {}) => {
|
|
|
|
|
switchToConversation(
|
|
|
|
|
{
|
|
|
|
|
conversationId: 'new',
|
|
|
|
|
title: 'New Chat',
|
|
|
|
|
jailbreakConversationId: null,
|
|
|
|
|
conversationSignature: null,
|
|
|
|
|
clientId: null,
|
|
|
|
|
invocationId: null,
|
|
|
|
|
model: model,
|
|
|
|
|
chatGptLabel: chatGptLabel,
|
|
|
|
|
promptPrefix: promptPrefix,
|
|
|
|
|
user: null,
|
|
|
|
|
suggestions: [],
|
|
|
|
|
toneStyle: null
|
|
|
|
|
},
|
|
|
|
|
[]
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return { newConversation, switchToConversation };
|
2023-03-28 20:36:21 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
conversation,
|
|
|
|
|
messages,
|
|
|
|
|
messagesTree,
|
|
|
|
|
latestMessage,
|
|
|
|
|
useConversation
|
|
|
|
|
};
|