mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-15 12:57:10 +00:00
feat: chaite 初始化逻辑
This commit is contained in:
parent
88312cdf38
commit
fbcf4e6c08
16 changed files with 549 additions and 1269 deletions
|
|
@ -1,9 +1,15 @@
|
||||||
class ChatGPTConfig {
|
class ChatGPTConfig {
|
||||||
dataDir = 'data'
|
dataDir = 'data'
|
||||||
processorsDirPath = 'data/processors'
|
processorsDirPath = 'utils/processors'
|
||||||
toolsDirPath = 'data/tools'
|
toolsDirPath = 'utils/tools'
|
||||||
cloudBaseUrl = ''
|
cloudBaseUrl = ''
|
||||||
cloudApiKey = ''
|
cloudApiKey = ''
|
||||||
|
|
||||||
|
embeddingModel = 'gemini-embedding-exp-03-07'
|
||||||
|
dimensions = 0
|
||||||
|
|
||||||
|
serverAuthKey = ''
|
||||||
|
version = '3.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new ChatGPTConfig()
|
export default new ChatGPTConfig()
|
||||||
|
|
|
||||||
1117
guoba.support.js
1117
guoba.support.js
File diff suppressed because it is too large
Load diff
17
index.js
17
index.js
|
|
@ -1,7 +1,6 @@
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import { Config } from './utils/config.js'
|
import ChatGPTConfig from './config/config.js'
|
||||||
import { createServer, runServer } from './server/index.js'
|
import { initChaite } from './models/chaite/cloud.js'
|
||||||
|
|
||||||
logger.info('**************************************')
|
logger.info('**************************************')
|
||||||
logger.info('chatgpt-plugin加载中')
|
logger.info('chatgpt-plugin加载中')
|
||||||
|
|
||||||
|
|
@ -36,17 +35,9 @@ for (let i in files) {
|
||||||
global.chatgpt = {
|
global.chatgpt = {
|
||||||
|
|
||||||
}
|
}
|
||||||
// 启动服务器
|
initChaite()
|
||||||
if (Config.enableToolbox) {
|
|
||||||
logger.info('开启工具箱配置项,工具箱启动中')
|
|
||||||
await createServer()
|
|
||||||
await runServer()
|
|
||||||
logger.info('工具箱启动成功')
|
|
||||||
} else {
|
|
||||||
logger.info('提示:当前配置未开启chatgpt工具箱,可通过锅巴或`#chatgpt开启工具箱`指令开启')
|
|
||||||
}
|
|
||||||
logger.info('chatgpt-plugin加载成功')
|
logger.info('chatgpt-plugin加载成功')
|
||||||
logger.info(`当前版本${Config.version}`)
|
logger.info(`当前版本${ChatGPTConfig.version}`)
|
||||||
logger.info('仓库地址 https://github.com/ikechan8370/chatgpt-plugin')
|
logger.info('仓库地址 https://github.com/ikechan8370/chatgpt-plugin')
|
||||||
logger.info('文档地址 https://www.yunzai.chat')
|
logger.info('文档地址 https://www.yunzai.chat')
|
||||||
logger.info('插件群号 559567232')
|
logger.info('插件群号 559567232')
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
import ChatGPTStorage from '../storage.js'
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
import { ChaiteStorage } from 'chaite'
|
||||||
|
|
||||||
/**
|
class LowDBChannelStorage extends ChaiteStorage {
|
||||||
* @returns {import('chaite').ChannelsStorage}
|
|
||||||
*/
|
|
||||||
export async function createChannelsStorage () {
|
|
||||||
return new LowDBChannelStorage(ChatGPTStorage)
|
|
||||||
}
|
|
||||||
|
|
||||||
class LowDBChannelStorage {
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param { LowDBStorage } storage
|
* @param { LowDBStorage } storage
|
||||||
*/
|
*/
|
||||||
constructor (storage) {
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
/**
|
/**
|
||||||
* 集合
|
* 集合
|
||||||
|
|
@ -21,54 +16,50 @@ class LowDBChannelStorage {
|
||||||
this.collection = this.storage.collection('channel')
|
this.collection = this.storage.collection('channel')
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveChannel (channel) {
|
/**
|
||||||
await this.collection.insert(channel)
|
*
|
||||||
}
|
* @param {string} key
|
||||||
|
* @returns {Promise<import('chaite').Channel>}
|
||||||
async getChannel (id) {
|
*/
|
||||||
return this.collection.collection()
|
async getItem (key) {
|
||||||
|
return this.collection.findOne({ id: key })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param name
|
* @param {string} id
|
||||||
* @returns {Promise<import('chaite').Channel[]>}
|
* @param {import('chaite').Channel} channel
|
||||||
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
async getChannelByName (name) {
|
async setItem (id, channel) {
|
||||||
return this.collection.find({ name })
|
if (id) {
|
||||||
}
|
await this.collection.updateById(id, channel)
|
||||||
|
return id
|
||||||
async deleteChannel (name) {
|
}
|
||||||
await this.collection.delete({ name })
|
const result = await this.collection.insert(channel)
|
||||||
|
return result.id
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有渠道
|
*
|
||||||
* @param {string?} model
|
* @param {string} key
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async removeItem (key) {
|
||||||
|
await this.collection.deleteById(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
* @returns {Promise<import('chaite').Channel[]>}
|
* @returns {Promise<import('chaite').Channel[]>}
|
||||||
*/
|
*/
|
||||||
async getAllChannels (model) {
|
async listItems () {
|
||||||
if (model) {
|
|
||||||
return this.collection.find({ 'options.model': model })
|
|
||||||
}
|
|
||||||
return this.collection.findAll()
|
return this.collection.findAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async clear () {
|
||||||
*
|
await this.collection.deleteAll()
|
||||||
* @param {import('chaite').ClientType} type
|
|
||||||
* @returns {Promise<Object[]>}
|
|
||||||
*/
|
|
||||||
async getChannelByType (type) {
|
|
||||||
return this.collection.find({ type })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {'enabled' | 'disabled'} status
|
|
||||||
* @returns {Promise<*>}
|
|
||||||
*/
|
|
||||||
async getChannelByStatus (status) {
|
|
||||||
return this.collection.find({ status })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default new LowDBChannelStorage()
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
import ChatGPTStorage from '../storage.js'
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
import { ChaiteStorage } from 'chaite'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {import('chaite').ChatPresetsStorage}
|
* @extends {ChaiteStorage<import('chaite').ChatPreset>}
|
||||||
*/
|
*/
|
||||||
export async function createChatPresetsStorage () {
|
class LowDBChatPresetsStorage extends ChaiteStorage {
|
||||||
return new LowDBChatPresetsStorage(ChatGPTStorage)
|
|
||||||
}
|
|
||||||
|
|
||||||
class LowDBChatPresetsStorage {
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param { LowDBStorage } storage
|
* @param { LowDBStorage } storage
|
||||||
*/
|
*/
|
||||||
constructor (storage) {
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
/**
|
/**
|
||||||
* 集合
|
* 集合
|
||||||
|
|
@ -23,31 +21,48 @@ class LowDBChatPresetsStorage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import('chaite').ChatPreset} preset
|
* @param key
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<import('chaite').ChatPreset>}
|
||||||
*/
|
*/
|
||||||
async savePreset (preset) {
|
async getItem (key) {
|
||||||
await this.collection.insert(preset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param { string } name
|
* @param {string} id
|
||||||
* @returns {Promise<import('chaite').ChatPreset | null>}
|
* @param {import('chaite').ChatPreset} preset
|
||||||
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
async getPreset (name) {
|
async setItem (id, preset) {
|
||||||
return this.collection.findOne({ name })
|
if (id) {
|
||||||
|
await this.collection.updateById(id, preset)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
const result = await this.collection.insert(preset)
|
||||||
|
return result.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async removeItem (key) {
|
||||||
|
await this.collection.deleteById(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns {Promise<import('chaite').ChatPreset[]>}
|
* @returns {Promise<import('chaite').ChatPreset[]>}
|
||||||
*/
|
*/
|
||||||
async getAllPresets () {
|
async listItems () {
|
||||||
return this.collection.findAll()
|
return this.collection.findAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
async deletePreset (name) {
|
async clear () {
|
||||||
await this.collection.delete({ name })
|
await this.collection.deleteAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default new LowDBChatPresetsStorage()
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,133 @@
|
||||||
import { DefaultToolCloudService, ToolManager } from 'chaite'
|
import { Chaite, ChannelsManager, ChatPresetManager, DefaultChannelLoadBalancer, GeminiClient, OpenAIClient, ProcessorsManager, RAGManager, ToolManager } from 'chaite'
|
||||||
import ChatGPTConfig from '../../config/config.js'
|
import ChatGPTConfig from '../../config/config.js'
|
||||||
import { createToolsSettingsStorage } from './tool_settings_storage.js'
|
import ChatGPTChannelStorage from './channel_storage.js'
|
||||||
const ChatGPTToolCloudService = new DefaultToolCloudService(ChatGPTConfig.cloudBaseUrl, '', {})
|
import ChatPresetStorage from './chat_preset_storage.js'
|
||||||
/**
|
import ChatGPTToolStorage from './tools_storage.js'
|
||||||
* @type {import('chaite').ToolManager}
|
import ChatGPTProcessorsStorage from './processors_storage.js'
|
||||||
*/
|
import { ChatGPTUserModeSelector } from './user_mode_selector.js'
|
||||||
let ChatGPTToolManager
|
import { LowDBUserStateStorage } from './user_state_storage.js'
|
||||||
ToolManager.getInstance(ChatGPTConfig.toolsDirPath, createToolsSettingsStorage(), ChatGPTToolCloudService).then((manager) => {
|
import { LowDBHistoryManager } from './history_manager.js'
|
||||||
ChatGPTToolManager = manager
|
import { ChatGPTVectorDatabase } from './vector_database.js'
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证,以便共享上传
|
* 认证,以便共享上传
|
||||||
* @param apiKey
|
* @param apiKey
|
||||||
* @returns {Promise<import('chaite').User>}
|
* @returns {Promise<import('chaite').User> | null}
|
||||||
*/
|
*/
|
||||||
export async function authCloud (apiKey) {
|
export async function authCloud (apiKey = ChatGPTConfig.cloudApiKey) {
|
||||||
const user = await ChatGPTToolCloudService.authenticate(apiKey)
|
await Chaite.getInstance().auth(apiKey)
|
||||||
ChatGPTToolManager.setCloudService(ChatGPTToolCloudService)
|
return Chaite.getInstance().getToolsManager().cloudService.getUser()
|
||||||
return user
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
ChatGPTToolCloudService,
|
*
|
||||||
ChatGPTToolManager
|
* @param {import('chaite').Channel} channel
|
||||||
|
* @returns {Promise<import('chaite').IClient>}
|
||||||
|
*/
|
||||||
|
async function getIClientByChannel (channel) {
|
||||||
|
await channel.ready()
|
||||||
|
switch (channel.adapterType) {
|
||||||
|
case 'openai': {
|
||||||
|
return new OpenAIClient(channel.options)
|
||||||
|
}
|
||||||
|
case 'gemini': {
|
||||||
|
return new GeminiClient(channel.options)
|
||||||
|
}
|
||||||
|
case 'claude': {
|
||||||
|
throw new Error('claude doesn\'t support embedding')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化RAG管理器
|
||||||
|
* @param {string} model
|
||||||
|
* @param {number} dimensions
|
||||||
|
*/
|
||||||
|
export async function initRagManager (model, dimensions) {
|
||||||
|
const vectorizer = new class {
|
||||||
|
async textToVector (text) {
|
||||||
|
const channels = await Chaite.getInstance().getChannelsManager().getChannelByModel(model)
|
||||||
|
if (channels.length === 0) {
|
||||||
|
throw new Error('No channel found for model: ' + model)
|
||||||
|
}
|
||||||
|
const channel = channels[0]
|
||||||
|
const client = await getIClientByChannel(channel)
|
||||||
|
const result = await client.getEmbedding(text)
|
||||||
|
return result.embeddings[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string[]} texts
|
||||||
|
* @returns {Promise<Array<number>[]>}
|
||||||
|
*/
|
||||||
|
async batchTextToVector (texts) {
|
||||||
|
const availableChannels = (await Chaite.getInstance().getChannelsManager().getAllChannels()).filter(c => c.models.includes(model))
|
||||||
|
if (availableChannels.length === 0) {
|
||||||
|
throw new Error('No channel found for model: ' + model)
|
||||||
|
}
|
||||||
|
const channels = await Chaite.getInstance().getChannelsManager().getChannelsByModel(model, texts.length)
|
||||||
|
/**
|
||||||
|
* @type {import('chaite').IClient[]}
|
||||||
|
*/
|
||||||
|
const clients = await Promise.all(channels.map(({ channel }) => getIClientByChannel(channel)))
|
||||||
|
const results = []
|
||||||
|
let startIndex = 0
|
||||||
|
for (let i = 0; i < channels.length; i++) {
|
||||||
|
const { quantity } = channels[i]
|
||||||
|
const textsSlice = texts.slice(startIndex, startIndex + quantity)
|
||||||
|
const embeddings = await clients[i].getEmbedding(textsSlice, {
|
||||||
|
model,
|
||||||
|
dimensions
|
||||||
|
})
|
||||||
|
results.push(...embeddings.embeddings)
|
||||||
|
startIndex += quantity
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
const ragManager = new RAGManager(ChatGPTVectorDatabase, vectorizer)
|
||||||
|
return Chaite.getInstance().setRAGManager(ragManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initChaite () {
|
||||||
|
const channelsManager = await ChannelsManager.init(ChatGPTChannelStorage, new DefaultChannelLoadBalancer())
|
||||||
|
const toolsManager = await ToolManager.init(ChatGPTConfig.toolsDirPath, ChatGPTToolStorage)
|
||||||
|
const processorsManager = await ProcessorsManager.init(ChatGPTConfig.processorsDirPath, ChatGPTProcessorsStorage)
|
||||||
|
const chatPresetManager = await ChatPresetManager.init(ChatPresetStorage)
|
||||||
|
const userModeSelector = new ChatGPTUserModeSelector()
|
||||||
|
const userStateStorage = new LowDBUserStateStorage()
|
||||||
|
const historyManager = new LowDBHistoryManager()
|
||||||
|
let chaite = Chaite.init(channelsManager, toolsManager, processorsManager, chatPresetManager,
|
||||||
|
userModeSelector, userStateStorage, historyManager, logger)
|
||||||
|
logger.info('Chaite 初始化完成')
|
||||||
|
chaite.setCloudService(ChatGPTConfig.cloudBaseUrl)
|
||||||
|
logger.info('Chaite.Cloud 初始化完成')
|
||||||
|
ChatGPTConfig.cloudApiKey && await chaite.auth(ChatGPTConfig.cloudApiKey)
|
||||||
|
await initRagManager(ChatGPTConfig.embeddingModel, ChatGPTConfig.dimensions)
|
||||||
|
// 监听Chaite配置变化,同步需要同步的配置
|
||||||
|
chaite.on('config-change', obj => {
|
||||||
|
const { key, newVal, oldVal } = obj
|
||||||
|
if (key === 'authKey') {
|
||||||
|
ChatGPTConfig.serverAuthKey = newVal
|
||||||
|
}
|
||||||
|
logger.debug(`Chaite config changed: ${key} from ${oldVal} to ${newVal}`)
|
||||||
|
})
|
||||||
|
// 监听通过chaite对插件配置修改
|
||||||
|
chaite.setUpdateConfigCallback(config => {
|
||||||
|
logger.debug('chatgpt-plugin config updated')
|
||||||
|
Object.keys(config).forEach(key => {
|
||||||
|
ChatGPTConfig[key] = config[key]
|
||||||
|
// 回传部分需要同步的配置,以防不一致
|
||||||
|
if (key === 'serverAuthKey') {
|
||||||
|
chaite.getGlobalConfig().setAuthKey(config[key])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// 授予Chaite获取插件配置的能力以便通过api放出
|
||||||
|
chaite.setGetConfig(async () => {
|
||||||
|
return ChatGPTConfig
|
||||||
|
})
|
||||||
|
logger.info('Chaite.RAGManager 初始化完成')
|
||||||
|
}
|
||||||
|
|
|
||||||
57
models/chaite/history_manager.js
Normal file
57
models/chaite/history_manager.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { AbstractHistoryManager } from 'chaite'
|
||||||
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
|
||||||
|
export class LowDBHistoryManager extends AbstractHistoryManager {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param { LowDBStorage } storage
|
||||||
|
*/
|
||||||
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
|
this.storage = storage
|
||||||
|
/**
|
||||||
|
* 集合
|
||||||
|
* @type {LowDBCollection}
|
||||||
|
*/
|
||||||
|
this.collection = this.storage.collection('history')
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveHistory (message, conversationId) {
|
||||||
|
const historyObj = { ...message, conversationId }
|
||||||
|
if (message.id) {
|
||||||
|
await this.collection.updateById(message.id, historyObj)
|
||||||
|
}
|
||||||
|
await this.collection.insert(historyObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param messageId
|
||||||
|
* @param conversationId
|
||||||
|
* @returns {Promise<import('chaite').HistoryMessage[]>}
|
||||||
|
*/
|
||||||
|
async getHistory (messageId, conversationId) {
|
||||||
|
if (messageId) {
|
||||||
|
const messages = []
|
||||||
|
let currentId = messageId
|
||||||
|
while (currentId) {
|
||||||
|
const message = await this.collection.findOne({ id: currentId })
|
||||||
|
if (!message) break
|
||||||
|
messages.unshift(message)
|
||||||
|
currentId = message.parentMessageId
|
||||||
|
}
|
||||||
|
return messages
|
||||||
|
} else if (conversationId) {
|
||||||
|
return this.collection.find({ conversationId })
|
||||||
|
}
|
||||||
|
return this.collection.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteConversation (conversationId) {
|
||||||
|
await this.collection.delete({ conversationId })
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOneHistory (messageId, conversationId) {
|
||||||
|
return this.collection.findOne({ id: messageId, conversationId })
|
||||||
|
}
|
||||||
|
}
|
||||||
68
models/chaite/processors_storage.js
Normal file
68
models/chaite/processors_storage.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
import { ChaiteStorage } from 'chaite'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {ChaiteStorage<import('chaite').Processor>}
|
||||||
|
*/
|
||||||
|
class LowDBProcessorsStorage extends ChaiteStorage {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param { LowDBStorage } storage
|
||||||
|
*/
|
||||||
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
|
this.storage = storage
|
||||||
|
/**
|
||||||
|
* 集合
|
||||||
|
* @type {LowDBCollection}
|
||||||
|
*/
|
||||||
|
this.collection = this.storage.collection('processors')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<import('chaite').Processor>}
|
||||||
|
*/
|
||||||
|
async getItem (key) {
|
||||||
|
return this.collection.findOne({ id: key })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {import('chaite').Processor} processor
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
async setItem (id, processor) {
|
||||||
|
if (id) {
|
||||||
|
await this.collection.updateById(id, processor)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
const result = await this.collection.insert(processor)
|
||||||
|
return result.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async removeItem (key) {
|
||||||
|
await this.collection.deleteById(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {Promise<import('chaite').Processor[]>}
|
||||||
|
*/
|
||||||
|
async listItems () {
|
||||||
|
return this.collection.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
async clear () {
|
||||||
|
await this.collection.deleteAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new LowDBProcessorsStorage()
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
import ChatGPTStorage from '../storage.js'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {import('chaite').ToolSettingsStorage}
|
|
||||||
*/
|
|
||||||
export function createToolsSettingsStorage () {
|
|
||||||
return new LowDBToolsSettingsStorage(ChatGPTStorage)
|
|
||||||
}
|
|
||||||
|
|
||||||
class LowDBToolsSettingsStorage {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param { LowDBStorage } storage
|
|
||||||
*/
|
|
||||||
constructor (storage) {
|
|
||||||
this.storage = storage
|
|
||||||
/**
|
|
||||||
* 集合
|
|
||||||
* @type {LowDBCollection}
|
|
||||||
*/
|
|
||||||
this.collection = this.storage.collection('tool_settings')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import('chaite').ToolSettings} settings
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
async saveToolSettings (settings) {
|
|
||||||
await this.collection.insert(settings)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param { string } name
|
|
||||||
* @returns {Promise<import('chaite').ToolSettings | null>}
|
|
||||||
*/
|
|
||||||
async getToolSettings (name) {
|
|
||||||
return this.collection.findOne({ name })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {Promise<import('chaite').ToolSettings[]>}
|
|
||||||
*/
|
|
||||||
async getAllToolSettings () {
|
|
||||||
return this.collection.findAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteToolSettings (name) {
|
|
||||||
await this.collection.delete({ name })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
68
models/chaite/tools_storage.js
Normal file
68
models/chaite/tools_storage.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
import { ChaiteStorage } from 'chaite'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {ChaiteStorage<import('chaite').ToolDTO>}
|
||||||
|
*/
|
||||||
|
class LowDBToolSettingsStorage extends ChaiteStorage {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param { LowDBStorage } storage
|
||||||
|
*/
|
||||||
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
|
this.storage = storage
|
||||||
|
/**
|
||||||
|
* 集合
|
||||||
|
* @type {LowDBCollection}
|
||||||
|
*/
|
||||||
|
this.collection = this.storage.collection('tools')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<import('chaite').ToolDTO>}
|
||||||
|
*/
|
||||||
|
async getItem (key) {
|
||||||
|
return this.collection.findOne({ id: key })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {import('chaite').ToolDTO} tools
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
async setItem (id, tools) {
|
||||||
|
if (id) {
|
||||||
|
await this.collection.updateById(id, tools)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
const result = await this.collection.insert(tools)
|
||||||
|
return result.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async removeItem (key) {
|
||||||
|
await this.collection.deleteById(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {Promise<import('chaite').ToolDTO[]>}
|
||||||
|
*/
|
||||||
|
async listItems () {
|
||||||
|
return this.collection.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
async clear () {
|
||||||
|
await this.collection.deleteAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new LowDBToolSettingsStorage()
|
||||||
12
models/chaite/user_mode_selector.js
Normal file
12
models/chaite/user_mode_selector.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { AbstractUserModeSelector } from '../../../../../../../WebstormProjects/node-chaite/src/types/external.js'
|
||||||
|
|
||||||
|
export class ChatGPTUserModeSelector extends AbstractUserModeSelector {
|
||||||
|
/**
|
||||||
|
* 根据e判断当前要使用的预设,非常灵活。
|
||||||
|
* @param e
|
||||||
|
* @returns {Promise<import('chaite').ChatPreset>}
|
||||||
|
*/
|
||||||
|
getChatPreset (e) {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
}
|
||||||
66
models/chaite/user_state_storage.js
Normal file
66
models/chaite/user_state_storage.js
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import ChatGPTStorage from '../storage.js'
|
||||||
|
import { ChaiteStorage } from 'chaite'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {ChaiteStorage<import('chaite').UserState>}
|
||||||
|
*/
|
||||||
|
export class LowDBUserStateStorage extends ChaiteStorage {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {LowDBStorage} storage
|
||||||
|
*/
|
||||||
|
constructor (storage = ChatGPTStorage) {
|
||||||
|
super()
|
||||||
|
this.storage = storage
|
||||||
|
/**
|
||||||
|
* 集合
|
||||||
|
* @type {LowDBCollection}
|
||||||
|
*/
|
||||||
|
this.collection = this.storage.collection('user_states')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<import('chaite').UserState>}
|
||||||
|
*/
|
||||||
|
async getItem (key) {
|
||||||
|
return this.collection.findOne({ id: key })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} id
|
||||||
|
* @param {import('chaite').UserState} state
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
async setItem (id, state) {
|
||||||
|
if (id) {
|
||||||
|
await this.collection.updateById(id, state)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
const result = await this.collection.insert(state)
|
||||||
|
return result.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async removeItem (key) {
|
||||||
|
await this.collection.deleteById(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {Promise<import('chaite').UserState[]>}
|
||||||
|
*/
|
||||||
|
async listItems () {
|
||||||
|
return this.collection.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
async clear () {
|
||||||
|
await this.collection.deleteAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,36 +1,90 @@
|
||||||
// todo
|
import { LocalIndex } from 'vectra'
|
||||||
class FaissVectorDatabase {
|
import { md5 } from '../../utils/common.js'
|
||||||
constructor (index) {
|
|
||||||
this.index = index
|
/**
|
||||||
|
* 基于Vectra实现的简单向量数据库,作为默认实现
|
||||||
|
*/
|
||||||
|
class VectraVectorDatabase {
|
||||||
|
constructor (indexFile) {
|
||||||
|
this.index = new LocalIndex(indexFile)
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
async init () {
|
||||||
|
if (!(await this.index.isIndexCreated())) {
|
||||||
|
await this.index.createIndex()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async addVector (vector, text) {
|
async addVector (vector, text) {
|
||||||
|
const id = md5(text)
|
||||||
|
await this.index.insertItem({
|
||||||
|
vector,
|
||||||
|
id,
|
||||||
|
metadata: { text }
|
||||||
|
})
|
||||||
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param vectors
|
||||||
|
* @param texts
|
||||||
|
* @returns {Promise<string[]>}
|
||||||
|
*/
|
||||||
async addVectors (vectors, texts) {
|
async addVectors (vectors, texts) {
|
||||||
|
return await Promise.all(vectors.map((v, i) => this.addVector(v, texts[i])))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param queryVector
|
||||||
|
* @param k
|
||||||
|
* @returns {Promise<Array<{ id: string, score: number, text: string }>>}
|
||||||
|
*/
|
||||||
async search (queryVector, k) {
|
async search (queryVector, k) {
|
||||||
|
const results = await this.index.queryItems(queryVector, k)
|
||||||
|
return results.map(r => ({ id: r.item.id, score: r.score, text: r.item.metadata.text }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @returns {Promise<{ vector: number[], text: string } | null>}
|
||||||
|
*/
|
||||||
async getVector (id) {
|
async getVector (id) {
|
||||||
|
const result = await this.index.getItem(id)
|
||||||
|
return {
|
||||||
|
vector: result.vector,
|
||||||
|
text: result.metadata.text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteVector (id) {
|
async deleteVector (id) {
|
||||||
|
await this.index.deleteItem(id)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateVector (id, newVector, newText) {
|
async updateVector (id, newVector, newText) {
|
||||||
|
await this.index.upsertItem({
|
||||||
|
id,
|
||||||
|
vector: newVector,
|
||||||
|
metadata: { text: newText }
|
||||||
|
})
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async count () {
|
async count () {
|
||||||
|
return (await this.index.getIndexStats()).items
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear () {
|
async clear () {
|
||||||
|
await this.index.deleteIndex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认向量库
|
* 默认向量库 todo
|
||||||
* @type {import('chaite').VectorDatabase}
|
* @type {import('chaite').VectorDatabase}
|
||||||
*/
|
*/
|
||||||
export const ChatGPTVectorDatabase = new FaissVectorDatabase()
|
export const ChatGPTVectorDatabase = new VectraVectorDatabase()
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ export class LowDBCollection {
|
||||||
/**
|
/**
|
||||||
* 创建新文档
|
* 创建新文档
|
||||||
* @param {Object} doc 要插入的文档
|
* @param {Object} doc 要插入的文档
|
||||||
* @returns {Promise<Object>} 插入的文档(带ID)
|
* @returns {Promise<Object & {id: string}>} 插入的文档(带ID)
|
||||||
*/
|
*/
|
||||||
async insert (doc) {
|
async insert (doc) {
|
||||||
// 生成唯一ID,如果没有提供
|
// 生成唯一ID,如果没有提供
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "ikechan8370",
|
"author": "ikechan8370",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chaite": "^1.0.3",
|
"chaite": "^1.1.1",
|
||||||
"keyv": "^5.3.1",
|
"keyv": "^5.3.1",
|
||||||
"keyv-file": "^5.1.2",
|
"keyv-file": "^5.1.2",
|
||||||
"lowdb": "^7.0.1"
|
"lowdb": "^7.0.1",
|
||||||
|
"vectra": "^0.9.0"
|
||||||
},
|
},
|
||||||
"pnpm": {}
|
"pnpm": {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
utils/common.js
Normal file
4
utils/common.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import * as crypto from 'node:crypto'
|
||||||
|
export function md5 (str) {
|
||||||
|
return crypto.createHash('md5').update(str).digest('hex')
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue