2023-03-10 18:25:33 +00:00
|
|
|
import { create } from "zustand";
|
|
|
|
import { persist } from "zustand/middleware";
|
|
|
|
|
2023-03-09 17:01:40 +00:00
|
|
|
import { type ChatCompletionResponseMessage } from "openai";
|
2023-03-26 10:59:09 +00:00
|
|
|
import {
|
|
|
|
ControllerPool,
|
|
|
|
requestChatStream,
|
|
|
|
requestWithPrompt,
|
|
|
|
} from "../requests";
|
2023-04-06 16:14:27 +00:00
|
|
|
import { isMobileScreen, trimTopic } from "../utils";
|
2023-03-09 17:01:40 +00:00
|
|
|
|
2023-03-23 17:00:33 +00:00
|
|
|
import Locale from "../locales";
|
2023-04-06 16:14:27 +00:00
|
|
|
import { showToast } from "../components/ui-lib";
|
2023-04-21 16:12:07 +00:00
|
|
|
import { ModelType, useAppConfig } from "./config";
|
2023-03-20 16:17:45 +00:00
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
export type Message = ChatCompletionResponseMessage & {
|
|
|
|
date: string;
|
2023-03-11 12:54:24 +00:00
|
|
|
streaming?: boolean;
|
2023-04-03 06:13:57 +00:00
|
|
|
isError?: boolean;
|
2023-04-05 19:19:33 +00:00
|
|
|
id?: number;
|
2023-04-20 14:52:14 +00:00
|
|
|
model?: ModelType;
|
2023-03-10 18:25:33 +00:00
|
|
|
};
|
2023-03-09 17:01:40 +00:00
|
|
|
|
2023-04-05 19:19:33 +00:00
|
|
|
export function createMessage(override: Partial<Message>): Message {
|
|
|
|
return {
|
|
|
|
id: Date.now(),
|
|
|
|
date: new Date().toLocaleString(),
|
|
|
|
role: "user",
|
|
|
|
content: "",
|
|
|
|
...override,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-04-02 17:48:43 +00:00
|
|
|
export const ROLES: Message["role"][] = ["system", "user", "assistant"];
|
|
|
|
|
2023-03-19 16:09:30 +00:00
|
|
|
export interface ChatStat {
|
2023-03-10 18:25:33 +00:00
|
|
|
tokenCount: number;
|
|
|
|
wordCount: number;
|
|
|
|
charCount: number;
|
|
|
|
}
|
|
|
|
|
2023-03-19 16:09:30 +00:00
|
|
|
export interface ChatSession {
|
2023-03-11 17:14:07 +00:00
|
|
|
id: number;
|
2023-03-10 18:25:33 +00:00
|
|
|
topic: string;
|
2023-04-05 18:37:12 +00:00
|
|
|
sendMemory: boolean;
|
2023-03-10 18:25:33 +00:00
|
|
|
memoryPrompt: string;
|
2023-04-02 17:48:43 +00:00
|
|
|
context: Message[];
|
2023-03-10 18:25:33 +00:00
|
|
|
messages: Message[];
|
|
|
|
stat: ChatStat;
|
|
|
|
lastUpdate: string;
|
2023-03-19 15:13:10 +00:00
|
|
|
lastSummarizeIndex: number;
|
2023-03-10 18:25:33 +00:00
|
|
|
}
|
|
|
|
|
2023-03-20 16:17:45 +00:00
|
|
|
const DEFAULT_TOPIC = Locale.Store.DefaultTopic;
|
2023-04-05 19:19:33 +00:00
|
|
|
export const BOT_HELLO: Message = createMessage({
|
2023-04-02 13:56:34 +00:00
|
|
|
role: "assistant",
|
|
|
|
content: Locale.Store.BotHello,
|
2023-04-05 19:19:33 +00:00
|
|
|
});
|
2023-03-10 18:25:33 +00:00
|
|
|
|
|
|
|
function createEmptySession(): ChatSession {
|
|
|
|
const createDate = new Date().toLocaleString();
|
|
|
|
|
|
|
|
return {
|
2023-03-11 17:14:07 +00:00
|
|
|
id: Date.now(),
|
2023-03-10 18:25:33 +00:00
|
|
|
topic: DEFAULT_TOPIC,
|
2023-04-05 18:37:12 +00:00
|
|
|
sendMemory: true,
|
2023-03-10 18:25:33 +00:00
|
|
|
memoryPrompt: "",
|
2023-04-02 17:48:43 +00:00
|
|
|
context: [],
|
2023-04-02 13:56:34 +00:00
|
|
|
messages: [],
|
2023-03-10 18:25:33 +00:00
|
|
|
stat: {
|
|
|
|
tokenCount: 0,
|
|
|
|
wordCount: 0,
|
|
|
|
charCount: 0,
|
|
|
|
},
|
|
|
|
lastUpdate: createDate,
|
2023-03-19 15:13:10 +00:00
|
|
|
lastSummarizeIndex: 0,
|
2023-03-10 18:25:33 +00:00
|
|
|
};
|
2023-03-09 17:01:40 +00:00
|
|
|
}
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
interface ChatStore {
|
|
|
|
sessions: ChatSession[];
|
|
|
|
currentSessionIndex: number;
|
2023-04-02 05:42:47 +00:00
|
|
|
clearSessions: () => void;
|
2023-03-10 18:25:33 +00:00
|
|
|
removeSession: (index: number) => void;
|
2023-04-05 17:34:46 +00:00
|
|
|
moveSession: (from: number, to: number) => void;
|
2023-03-10 18:25:33 +00:00
|
|
|
selectSession: (index: number) => void;
|
|
|
|
newSession: () => void;
|
2023-04-09 15:41:16 +00:00
|
|
|
deleteSession: (index?: number) => void;
|
2023-03-10 18:25:33 +00:00
|
|
|
currentSession: () => ChatSession;
|
|
|
|
onNewMessage: (message: Message) => void;
|
|
|
|
onUserInput: (content: string) => Promise<void>;
|
|
|
|
summarizeSession: () => void;
|
|
|
|
updateStat: (message: Message) => void;
|
|
|
|
updateCurrentSession: (updater: (session: ChatSession) => void) => void;
|
2023-03-11 12:54:24 +00:00
|
|
|
updateMessage: (
|
|
|
|
sessionIndex: number,
|
|
|
|
messageIndex: number,
|
2023-04-18 03:44:15 +00:00
|
|
|
updater: (message?: Message) => void,
|
2023-03-11 12:54:24 +00:00
|
|
|
) => void;
|
2023-04-05 18:37:12 +00:00
|
|
|
resetSession: () => void;
|
2023-03-19 15:13:10 +00:00
|
|
|
getMessagesWithMemory: () => Message[];
|
2023-03-21 16:20:32 +00:00
|
|
|
getMemoryPrompt: () => Message;
|
2023-03-11 17:14:07 +00:00
|
|
|
|
2023-03-19 15:13:10 +00:00
|
|
|
clearAllData: () => void;
|
2023-03-09 17:01:40 +00:00
|
|
|
}
|
|
|
|
|
2023-03-29 16:02:50 +00:00
|
|
|
function countMessages(msgs: Message[]) {
|
|
|
|
return msgs.reduce((pre, cur) => pre + cur.content.length, 0);
|
|
|
|
}
|
|
|
|
|
2023-03-13 16:25:07 +00:00
|
|
|
const LOCAL_KEY = "chat-next-web-store";
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
export const useChatStore = create<ChatStore>()(
|
|
|
|
persist(
|
|
|
|
(set, get) => ({
|
|
|
|
sessions: [createEmptySession()],
|
|
|
|
currentSessionIndex: 0,
|
2023-03-12 19:21:48 +00:00
|
|
|
|
2023-04-02 05:45:34 +00:00
|
|
|
clearSessions() {
|
2023-04-02 05:42:47 +00:00
|
|
|
set(() => ({
|
|
|
|
sessions: [createEmptySession()],
|
|
|
|
currentSessionIndex: 0,
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
selectSession(index: number) {
|
|
|
|
set({
|
|
|
|
currentSessionIndex: index,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
removeSession(index: number) {
|
|
|
|
set((state) => {
|
|
|
|
let nextIndex = state.currentSessionIndex;
|
|
|
|
const sessions = state.sessions;
|
|
|
|
|
|
|
|
if (sessions.length === 1) {
|
|
|
|
return {
|
|
|
|
currentSessionIndex: 0,
|
|
|
|
sessions: [createEmptySession()],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
sessions.splice(index, 1);
|
|
|
|
|
|
|
|
if (nextIndex === index) {
|
|
|
|
nextIndex -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
currentSessionIndex: nextIndex,
|
|
|
|
sessions,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2023-04-05 17:34:46 +00:00
|
|
|
moveSession(from: number, to: number) {
|
|
|
|
set((state) => {
|
|
|
|
const { sessions, currentSessionIndex: oldIndex } = state;
|
|
|
|
|
|
|
|
// move the session
|
|
|
|
const newSessions = [...sessions];
|
|
|
|
const session = newSessions[from];
|
|
|
|
newSessions.splice(from, 1);
|
|
|
|
newSessions.splice(to, 0, session);
|
|
|
|
|
|
|
|
// modify current session id
|
|
|
|
let newIndex = oldIndex === from ? to : oldIndex;
|
|
|
|
if (oldIndex > from && oldIndex <= to) {
|
|
|
|
newIndex -= 1;
|
|
|
|
} else if (oldIndex < from && oldIndex >= to) {
|
|
|
|
newIndex += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
currentSessionIndex: newIndex,
|
|
|
|
sessions: newSessions,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
newSession() {
|
|
|
|
set((state) => ({
|
2023-03-11 08:24:17 +00:00
|
|
|
currentSessionIndex: 0,
|
|
|
|
sessions: [createEmptySession()].concat(state.sessions),
|
2023-03-10 18:25:33 +00:00
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
2023-04-09 15:41:16 +00:00
|
|
|
deleteSession(i?: number) {
|
2023-04-06 16:14:27 +00:00
|
|
|
const deletedSession = get().currentSession();
|
2023-04-09 15:41:16 +00:00
|
|
|
const index = i ?? get().currentSessionIndex;
|
2023-04-06 16:14:27 +00:00
|
|
|
const isLastSession = get().sessions.length === 1;
|
|
|
|
if (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) {
|
|
|
|
get().removeSession(index);
|
2023-04-09 15:41:16 +00:00
|
|
|
|
2023-04-09 15:51:12 +00:00
|
|
|
showToast(
|
|
|
|
Locale.Home.DeleteToast,
|
|
|
|
{
|
|
|
|
text: Locale.Home.Revert,
|
|
|
|
onClick() {
|
|
|
|
set((state) => ({
|
|
|
|
sessions: state.sessions
|
|
|
|
.slice(0, index)
|
|
|
|
.concat([deletedSession])
|
|
|
|
.concat(
|
2023-04-18 03:44:15 +00:00
|
|
|
state.sessions.slice(index + Number(isLastSession)),
|
2023-04-09 15:51:12 +00:00
|
|
|
),
|
|
|
|
}));
|
|
|
|
},
|
2023-04-07 06:51:08 +00:00
|
|
|
},
|
2023-04-18 03:44:15 +00:00
|
|
|
5000,
|
2023-04-09 15:51:12 +00:00
|
|
|
);
|
2023-04-06 16:14:27 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
currentSession() {
|
|
|
|
let index = get().currentSessionIndex;
|
|
|
|
const sessions = get().sessions;
|
|
|
|
|
|
|
|
if (index < 0 || index >= sessions.length) {
|
|
|
|
index = Math.min(sessions.length - 1, Math.max(0, index));
|
|
|
|
set(() => ({ currentSessionIndex: index }));
|
|
|
|
}
|
|
|
|
|
2023-03-11 17:14:07 +00:00
|
|
|
const session = sessions[index];
|
|
|
|
|
|
|
|
return session;
|
2023-03-10 18:25:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onNewMessage(message) {
|
2023-03-21 16:20:32 +00:00
|
|
|
get().updateCurrentSession((session) => {
|
|
|
|
session.lastUpdate = new Date().toLocaleString();
|
|
|
|
});
|
2023-03-10 18:25:33 +00:00
|
|
|
get().updateStat(message);
|
|
|
|
get().summarizeSession();
|
|
|
|
},
|
|
|
|
|
|
|
|
async onUserInput(content) {
|
2023-04-05 19:19:33 +00:00
|
|
|
const userMessage: Message = createMessage({
|
2023-03-10 18:25:33 +00:00
|
|
|
role: "user",
|
|
|
|
content,
|
2023-04-05 19:19:33 +00:00
|
|
|
});
|
2023-03-10 18:25:33 +00:00
|
|
|
|
2023-04-05 19:19:33 +00:00
|
|
|
const botMessage: Message = createMessage({
|
2023-03-11 12:54:24 +00:00
|
|
|
role: "assistant",
|
|
|
|
streaming: true,
|
2023-04-16 10:55:29 +00:00
|
|
|
id: userMessage.id! + 1,
|
2023-04-21 16:12:07 +00:00
|
|
|
model: useAppConfig.getState().modelConfig.model,
|
2023-04-05 19:19:33 +00:00
|
|
|
});
|
2023-03-11 12:54:24 +00:00
|
|
|
|
2023-03-21 16:20:32 +00:00
|
|
|
// get recent messages
|
|
|
|
const recentMessages = get().getMessagesWithMemory();
|
|
|
|
const sendMessages = recentMessages.concat(userMessage);
|
2023-03-26 10:59:09 +00:00
|
|
|
const sessionIndex = get().currentSessionIndex;
|
|
|
|
const messageIndex = get().currentSession().messages.length + 1;
|
2023-03-19 16:09:30 +00:00
|
|
|
|
|
|
|
// save user's and bot's message
|
2023-03-11 12:54:24 +00:00
|
|
|
get().updateCurrentSession((session) => {
|
2023-03-19 16:09:30 +00:00
|
|
|
session.messages.push(userMessage);
|
2023-03-11 12:54:24 +00:00
|
|
|
session.messages.push(botMessage);
|
|
|
|
});
|
|
|
|
|
2023-03-26 10:59:09 +00:00
|
|
|
// make request
|
2023-03-21 16:20:32 +00:00
|
|
|
console.log("[User Input] ", sendMessages);
|
2023-03-19 16:09:30 +00:00
|
|
|
requestChatStream(sendMessages, {
|
2023-03-11 12:54:24 +00:00
|
|
|
onMessage(content, done) {
|
2023-03-26 10:59:09 +00:00
|
|
|
// stream response
|
2023-03-11 12:54:24 +00:00
|
|
|
if (done) {
|
2023-03-11 17:14:07 +00:00
|
|
|
botMessage.streaming = false;
|
2023-03-26 06:53:40 +00:00
|
|
|
botMessage.content = content;
|
2023-03-21 16:20:32 +00:00
|
|
|
get().onNewMessage(botMessage);
|
2023-04-05 19:19:33 +00:00
|
|
|
ControllerPool.remove(
|
|
|
|
sessionIndex,
|
2023-04-18 03:44:15 +00:00
|
|
|
botMessage.id ?? messageIndex,
|
2023-04-05 19:19:33 +00:00
|
|
|
);
|
2023-03-11 12:54:24 +00:00
|
|
|
} else {
|
|
|
|
botMessage.content = content;
|
|
|
|
set(() => ({}));
|
|
|
|
}
|
|
|
|
},
|
2023-04-03 06:13:57 +00:00
|
|
|
onError(error, statusCode) {
|
|
|
|
if (statusCode === 401) {
|
|
|
|
botMessage.content = Locale.Error.Unauthorized;
|
2023-04-16 10:07:43 +00:00
|
|
|
} else if (!error.message.includes("aborted")) {
|
2023-04-03 06:13:57 +00:00
|
|
|
botMessage.content += "\n\n" + Locale.Store.Error;
|
|
|
|
}
|
2023-03-11 17:14:07 +00:00
|
|
|
botMessage.streaming = false;
|
2023-04-03 06:13:57 +00:00
|
|
|
userMessage.isError = true;
|
|
|
|
botMessage.isError = true;
|
2023-03-11 17:14:07 +00:00
|
|
|
set(() => ({}));
|
2023-04-05 19:19:33 +00:00
|
|
|
ControllerPool.remove(sessionIndex, botMessage.id ?? messageIndex);
|
2023-03-26 10:59:09 +00:00
|
|
|
},
|
|
|
|
onController(controller) {
|
|
|
|
// collect controller for stop/retry
|
|
|
|
ControllerPool.addController(
|
|
|
|
sessionIndex,
|
2023-04-05 19:19:33 +00:00
|
|
|
botMessage.id ?? messageIndex,
|
2023-04-18 03:44:15 +00:00
|
|
|
controller,
|
2023-03-26 10:59:09 +00:00
|
|
|
);
|
2023-03-11 17:14:07 +00:00
|
|
|
},
|
2023-04-21 16:12:07 +00:00
|
|
|
filterBot: !useAppConfig.getState().sendBotMessages,
|
|
|
|
modelConfig: useAppConfig.getState().modelConfig,
|
2023-03-10 18:25:33 +00:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2023-03-19 16:29:09 +00:00
|
|
|
getMemoryPrompt() {
|
2023-03-21 16:20:32 +00:00
|
|
|
const session = get().currentSession();
|
2023-03-19 16:29:09 +00:00
|
|
|
|
|
|
|
return {
|
2023-03-21 16:20:32 +00:00
|
|
|
role: "system",
|
2023-03-20 16:17:45 +00:00
|
|
|
content: Locale.Store.Prompt.History(session.memoryPrompt),
|
2023-03-21 16:20:32 +00:00
|
|
|
date: "",
|
|
|
|
} as Message;
|
2023-03-19 16:29:09 +00:00
|
|
|
},
|
|
|
|
|
2023-03-19 15:13:10 +00:00
|
|
|
getMessagesWithMemory() {
|
2023-03-21 16:20:32 +00:00
|
|
|
const session = get().currentSession();
|
2023-04-21 16:12:07 +00:00
|
|
|
const config = useAppConfig.getState();
|
2023-04-03 06:13:57 +00:00
|
|
|
const messages = session.messages.filter((msg) => !msg.isError);
|
|
|
|
const n = messages.length;
|
2023-03-19 15:13:10 +00:00
|
|
|
|
2023-04-02 17:48:43 +00:00
|
|
|
const context = session.context.slice();
|
2023-03-19 15:13:10 +00:00
|
|
|
|
2023-04-18 03:42:08 +00:00
|
|
|
// long term memory
|
2023-04-05 18:37:12 +00:00
|
|
|
if (
|
|
|
|
session.sendMemory &&
|
|
|
|
session.memoryPrompt &&
|
|
|
|
session.memoryPrompt.length > 0
|
|
|
|
) {
|
2023-04-02 17:48:43 +00:00
|
|
|
const memoryPrompt = get().getMemoryPrompt();
|
|
|
|
context.push(memoryPrompt);
|
2023-03-19 15:13:10 +00:00
|
|
|
}
|
|
|
|
|
2023-04-18 03:42:08 +00:00
|
|
|
// get short term and unmemoried long term memory
|
|
|
|
const shortTermMemoryMessageIndex = Math.max(
|
|
|
|
0,
|
2023-04-21 17:13:23 +00:00
|
|
|
n - config.modelConfig.historyMessageCount,
|
2023-04-02 17:48:43 +00:00
|
|
|
);
|
2023-04-18 03:44:15 +00:00
|
|
|
const longTermMemoryMessageIndex = session.lastSummarizeIndex;
|
2023-04-19 03:20:07 +00:00
|
|
|
const oldestIndex = Math.max(
|
2023-04-18 03:42:08 +00:00
|
|
|
shortTermMemoryMessageIndex,
|
2023-04-18 03:44:15 +00:00
|
|
|
longTermMemoryMessageIndex,
|
2023-04-18 03:42:08 +00:00
|
|
|
);
|
2023-04-21 17:13:23 +00:00
|
|
|
const threshold = config.modelConfig.compressMessageLengthThreshold;
|
2023-04-18 03:42:08 +00:00
|
|
|
|
|
|
|
// get recent messages as many as possible
|
|
|
|
const reversedRecentMessages = [];
|
|
|
|
for (
|
|
|
|
let i = n - 1, count = 0;
|
|
|
|
i >= oldestIndex && count < threshold;
|
|
|
|
i -= 1
|
|
|
|
) {
|
|
|
|
const msg = messages[i];
|
|
|
|
if (!msg || msg.isError) continue;
|
|
|
|
count += msg.content.length;
|
|
|
|
reversedRecentMessages.push(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// concat
|
|
|
|
const recentMessages = context.concat(reversedRecentMessages.reverse());
|
2023-04-02 17:48:43 +00:00
|
|
|
|
2023-03-21 16:20:32 +00:00
|
|
|
return recentMessages;
|
2023-03-19 15:13:10 +00:00
|
|
|
},
|
|
|
|
|
2023-03-11 12:54:24 +00:00
|
|
|
updateMessage(
|
|
|
|
sessionIndex: number,
|
|
|
|
messageIndex: number,
|
2023-04-18 03:44:15 +00:00
|
|
|
updater: (message?: Message) => void,
|
2023-03-11 12:54:24 +00:00
|
|
|
) {
|
|
|
|
const sessions = get().sessions;
|
|
|
|
const session = sessions.at(sessionIndex);
|
|
|
|
const messages = session?.messages;
|
|
|
|
updater(messages?.at(messageIndex));
|
|
|
|
set(() => ({ sessions }));
|
|
|
|
},
|
|
|
|
|
2023-04-05 18:37:12 +00:00
|
|
|
resetSession() {
|
|
|
|
get().updateCurrentSession((session) => {
|
|
|
|
session.messages = [];
|
|
|
|
session.memoryPrompt = "";
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2023-03-10 18:25:33 +00:00
|
|
|
summarizeSession() {
|
|
|
|
const session = get().currentSession();
|
|
|
|
|
2023-03-29 16:02:50 +00:00
|
|
|
// should summarize topic after chating more than 50 words
|
|
|
|
const SUMMARIZE_MIN_LEN = 50;
|
|
|
|
if (
|
|
|
|
session.topic === DEFAULT_TOPIC &&
|
|
|
|
countMessages(session.messages) >= SUMMARIZE_MIN_LEN
|
|
|
|
) {
|
2023-04-20 15:04:58 +00:00
|
|
|
requestWithPrompt(session.messages, Locale.Store.Prompt.Topic, {
|
|
|
|
model: "gpt-3.5-turbo",
|
|
|
|
}).then((res) => {
|
|
|
|
get().updateCurrentSession(
|
|
|
|
(session) =>
|
|
|
|
(session.topic = res ? trimTopic(res) : DEFAULT_TOPIC),
|
|
|
|
);
|
|
|
|
});
|
2023-03-13 16:25:07 +00:00
|
|
|
}
|
2023-03-19 15:13:10 +00:00
|
|
|
|
2023-04-21 16:12:07 +00:00
|
|
|
const config = useAppConfig.getState();
|
2023-03-21 16:20:32 +00:00
|
|
|
let toBeSummarizedMsgs = session.messages.slice(
|
2023-04-18 03:44:15 +00:00
|
|
|
session.lastSummarizeIndex,
|
2023-03-21 16:20:32 +00:00
|
|
|
);
|
2023-04-02 17:48:43 +00:00
|
|
|
|
2023-03-29 16:02:50 +00:00
|
|
|
const historyMsgLength = countMessages(toBeSummarizedMsgs);
|
2023-03-19 16:29:09 +00:00
|
|
|
|
2023-04-21 16:12:07 +00:00
|
|
|
if (historyMsgLength > config?.modelConfig?.max_tokens ?? 4000) {
|
2023-04-02 17:48:43 +00:00
|
|
|
const n = toBeSummarizedMsgs.length;
|
2023-03-21 16:20:32 +00:00
|
|
|
toBeSummarizedMsgs = toBeSummarizedMsgs.slice(
|
2023-04-21 17:13:23 +00:00
|
|
|
Math.max(0, n - config.modelConfig.historyMessageCount),
|
2023-03-21 16:20:32 +00:00
|
|
|
);
|
2023-03-19 16:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// add memory prompt
|
2023-03-21 16:20:32 +00:00
|
|
|
toBeSummarizedMsgs.unshift(get().getMemoryPrompt());
|
2023-03-19 16:29:09 +00:00
|
|
|
|
2023-03-21 16:20:32 +00:00
|
|
|
const lastSummarizeIndex = session.messages.length;
|
2023-03-19 16:09:30 +00:00
|
|
|
|
2023-03-21 16:20:32 +00:00
|
|
|
console.log(
|
|
|
|
"[Chat History] ",
|
|
|
|
toBeSummarizedMsgs,
|
|
|
|
historyMsgLength,
|
2023-04-21 17:13:23 +00:00
|
|
|
config.modelConfig.compressMessageLengthThreshold,
|
2023-03-21 16:20:32 +00:00
|
|
|
);
|
2023-03-19 16:09:30 +00:00
|
|
|
|
2023-04-18 03:42:08 +00:00
|
|
|
if (
|
2023-04-21 17:13:23 +00:00
|
|
|
historyMsgLength >
|
|
|
|
config.modelConfig.compressMessageLengthThreshold &&
|
2023-04-18 03:42:08 +00:00
|
|
|
session.sendMemory
|
|
|
|
) {
|
2023-03-21 16:20:32 +00:00
|
|
|
requestChatStream(
|
|
|
|
toBeSummarizedMsgs.concat({
|
|
|
|
role: "system",
|
|
|
|
content: Locale.Store.Prompt.Summarize,
|
|
|
|
date: "",
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
filterBot: false,
|
2023-04-21 15:22:02 +00:00
|
|
|
model: "gpt-3.5-turbo",
|
2023-03-21 16:20:32 +00:00
|
|
|
onMessage(message, done) {
|
|
|
|
session.memoryPrompt = message;
|
|
|
|
if (done) {
|
|
|
|
console.log("[Memory] ", session.memoryPrompt);
|
|
|
|
session.lastSummarizeIndex = lastSummarizeIndex;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onError(error) {
|
|
|
|
console.error("[Summarize] ", error);
|
|
|
|
},
|
2023-04-18 03:44:15 +00:00
|
|
|
},
|
2023-03-21 16:20:32 +00:00
|
|
|
);
|
2023-03-19 15:13:10 +00:00
|
|
|
}
|
2023-03-10 18:25:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
updateStat(message) {
|
|
|
|
get().updateCurrentSession((session) => {
|
|
|
|
session.stat.charCount += message.content.length;
|
|
|
|
// TODO: should update chat count and word count
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
updateCurrentSession(updater) {
|
|
|
|
const sessions = get().sessions;
|
|
|
|
const index = get().currentSessionIndex;
|
|
|
|
updater(sessions[index]);
|
|
|
|
set(() => ({ sessions }));
|
|
|
|
},
|
2023-03-19 15:13:10 +00:00
|
|
|
|
|
|
|
clearAllData() {
|
2023-03-20 16:17:45 +00:00
|
|
|
if (confirm(Locale.Store.ConfirmClearAll)) {
|
2023-03-21 16:20:32 +00:00
|
|
|
localStorage.clear();
|
|
|
|
location.reload();
|
2023-03-19 15:13:10 +00:00
|
|
|
}
|
|
|
|
},
|
2023-03-10 18:25:33 +00:00
|
|
|
}),
|
2023-03-13 16:25:07 +00:00
|
|
|
{
|
|
|
|
name: LOCAL_KEY,
|
2023-04-05 18:37:12 +00:00
|
|
|
version: 1.2,
|
2023-04-02 17:48:43 +00:00
|
|
|
migrate(persistedState, version) {
|
|
|
|
const state = persistedState as ChatStore;
|
|
|
|
|
|
|
|
if (version === 1) {
|
|
|
|
state.sessions.forEach((s) => (s.context = []));
|
|
|
|
}
|
|
|
|
|
2023-04-05 18:37:12 +00:00
|
|
|
if (version < 1.2) {
|
|
|
|
state.sessions.forEach((s) => (s.sendMemory = true));
|
|
|
|
}
|
|
|
|
|
2023-04-02 17:48:43 +00:00
|
|
|
return state;
|
|
|
|
},
|
2023-04-18 03:44:15 +00:00
|
|
|
},
|
|
|
|
),
|
2023-03-10 18:25:33 +00:00
|
|
|
);
|