@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
247 lines (210 loc) • 6.86 kB
text/typescript
import Dexie, { Transaction } from 'dexie';
import { MigrationLLMSettings } from '@/migrations/FromV3ToV4';
import { MigrationAgentChatConfig } from '@/migrations/FromV5ToV6';
import { MigrationKeyValueSettings } from '@/migrations/FromV6ToV7';
import { uuid } from '@/utils/uuid';
import { DB_File } from '../schemas/files';
import { DB_Message } from '../schemas/message';
import { DB_Plugin } from '../schemas/plugin';
import { DB_Session } from '../schemas/session';
import { DB_SessionGroup } from '../schemas/sessionGroup';
import { DB_Topic } from '../schemas/topic';
import { DB_User } from '../schemas/user';
import { migrateSettingsToUser } from './migrations/migrateSettingsToUser';
import {
dbSchemaV1,
dbSchemaV2,
dbSchemaV3,
dbSchemaV4,
dbSchemaV5,
dbSchemaV6,
dbSchemaV7,
dbSchemaV9,
} from './schemas';
import { DBModel, LOBE_CHAT_LOCAL_DB_NAME } from './types/db';
export interface LobeDBSchemaMap {
files: DB_File;
messages: DB_Message;
plugins: DB_Plugin;
sessionGroups: DB_SessionGroup;
sessions: DB_Session;
topics: DB_Topic;
users: DB_User;
}
// Define a local DB
export class BrowserDB extends Dexie {
public files: BrowserDBTable<'files'>;
public sessions: BrowserDBTable<'sessions'>;
public messages: BrowserDBTable<'messages'>;
public topics: BrowserDBTable<'topics'>;
public plugins: BrowserDBTable<'plugins'>;
public sessionGroups: BrowserDBTable<'sessionGroups'>;
public users: BrowserDBTable<'users'>;
constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
this.version(1).stores(dbSchemaV1);
this.version(2).stores(dbSchemaV2);
this.version(3).stores(dbSchemaV3);
this.version(4)
.stores(dbSchemaV4)
.upgrade((trans) => this.upgradeToV4(trans));
this.version(5)
.stores(dbSchemaV5)
.upgrade((trans) => this.upgradeToV5(trans));
this.version(6)
.stores(dbSchemaV6)
.upgrade((trans) => this.upgradeToV6(trans));
this.version(7)
.stores(dbSchemaV7)
.upgrade((trans) => this.upgradeToV7(trans));
this.version(8)
.stores(dbSchemaV7)
.upgrade((trans) => this.upgradeToV8(trans));
this.version(9)
.stores(dbSchemaV9)
.upgrade((trans) => this.upgradeToV9(trans));
this.version(10)
.stores(dbSchemaV9)
.upgrade((trans) => this.upgradeToV10(trans));
this.version(11)
.stores(dbSchemaV9)
.upgrade((trans) => this.upgradeToV11(trans));
this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
this.sessionGroups = this.table('sessionGroups');
this.users = this.table('users');
}
/**
* 2024.01.22
*
* DB V3 to V4
* from `group = pinned` to `pinned:true`
*/
upgradeToV4 = async (trans: Transaction) => {
const sessions = trans.table('sessions');
await sessions.toCollection().modify((session) => {
// translate boolean to number
session.pinned = session.group === 'pinned' ? 1 : 0;
session.group = 'default';
});
};
/**
* 2024.01.29
* settings from localStorage to indexedDB
*/
upgradeToV5 = async (trans: Transaction) => {
const users = trans.table('users');
// if no user, create one
if ((await users.count()) === 0) {
const data = localStorage.getItem('LOBE_SETTINGS');
if (data) {
let json;
try {
json = JSON.parse(data);
} catch {
/* empty */
}
if (!json?.state?.settings) return;
const settings = json.state.settings;
const user = migrateSettingsToUser(settings);
await users.add(user);
}
}
};
/**
* 2024.02.27
* add uuid to user
*/
upgradeToV6 = async (trans: Transaction) => {
const users = trans.table('users');
await users.toCollection().modify((user: DB_User) => {
if (!user.uuid) user.uuid = uuid();
});
};
/**
* 2024.03.14
* add `id` in plugins
*/
upgradeToV7 = async (trans: Transaction) => {
const plugins = trans.table('plugins');
await plugins.toCollection().modify((plugin: DB_Plugin) => {
plugin.id = plugin.identifier;
});
};
upgradeToV8 = async (trans: Transaction) => {
const users = trans.table('users');
await users.toCollection().modify((user: DB_User) => {
if (user.settings) {
user.settings = MigrationLLMSettings.migrateSettings(user.settings as any);
}
});
};
/**
* 2024.05.11
*
* message role=function to role=tool
*/
upgradeToV9 = async (trans: Transaction) => {
const messages = trans.table('messages');
await messages.toCollection().modify(async (message: DBModel<DB_Message>) => {
if ((message.role as string) === 'function') {
const origin = Object.assign({}, message);
const toolCallId = `tool_call_${message.id}`;
const assistantMessageId = `tool_calls_${message.id}`;
message.role = 'tool';
message.tool_call_id = toolCallId;
message.parentId = assistantMessageId;
await messages.add({
...origin,
content: '',
createdAt: message.createdAt - 10,
error: undefined,
id: assistantMessageId,
role: 'assistant',
tools: [{ ...message.plugin!, id: toolCallId }],
updatedAt: message.updatedAt - 10,
} as DBModel<DB_Message>);
}
});
};
/**
* 2024.05.25
* migrate some agent config to chatConfig
*/
upgradeToV10 = async (trans: Transaction) => {
const sessions = trans.table('sessions');
await sessions.toCollection().modify(async (session: DBModel<DB_Session>) => {
if (session.config)
session.config = MigrationAgentChatConfig.migrateChatConfig(session.config as any);
});
};
/**
* 2024.05.27
* migrate apiKey in languageModel to keyVaults
*/
upgradeToV11 = async (trans: Transaction) => {
const users = trans.table('users');
await users.toCollection().modify((user: DB_User) => {
if (user.settings) {
user.settings = MigrationKeyValueSettings.migrateSettings(user.settings as any);
}
});
};
}
export const browserDB = new BrowserDB();
// ================================================ //
// ================================================ //
// ================================================ //
// ================================================ //
// ================================================ //
// types helper
export type BrowserDBSchema = {
[t in keyof LobeDBSchemaMap]: {
model: LobeDBSchemaMap[t];
table: Dexie.Table<DBModel<LobeDBSchemaMap[t]>, string>;
};
};
type BrowserDBTable<T extends keyof LobeDBSchemaMap> = BrowserDBSchema[T]['table'];