-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathai.js
85 lines (71 loc) · 2.74 KB
/
ai.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { insertEntry, updateEntry, removeEntry } from './indexedDB/entry.js'
import { connectRemoteModel as gemini, connectLocalModel as gemma } from './model.js'
import llama from './chromaDB/model.js'
import geminiNano from './webAI/model.js'
const models = { gemini, gemma, llama, geminiNano }
const tryConnect = async (prior) => {
let model = null
let connect = null
for (let i = 0; i < prior.length; i++) {
const [name, connectModel, options] = prior[i]
try {
model = await connectModel(options)
} catch (error) {
console.error('An error occurs when connecting the model', name, '\n', error)
}
if (model) {
console.warn('Connect model', name, 'successfully')
connect = connectModel
break
}
}
return [model, connect]
}
const switchModelFn = (prior, remotes, locals) => async (modelName) => {
const connectModel = models[modelName]
const options = remotes[modelName] || locals[modelName]
const model = await connectModel(options)
return createSession(model, connectModel, prior, remotes, locals)
}
const promptFn = (model, connect, prior) => {
return async (...args) => {
try {
return await model.generateResponse.apply(model, args)
} catch (error) {
console.error('Prompt failed when using the model\n', error)
for (let i = 0; i < prior.length; i++) {
const [name, connectModel, options] = prior[i]
if (connect !== connectModel) {
try {
const subModel = await connectModel(options)
console.warn('Prompt failed, switch the model', name, 'successfully')
return await subModel.generateResponse.apply(subModel, args)
} catch (error) {
console.error('Prompt failed, an error occurs when switching the model', name, '\n', error)
}
}
}
}
}
}
const createSession = (model, connect, prior, remotes, locals) => {
if (model) {
return {
prompt: promptFn(model, connect, prior),
switchModel: switchModelFn(prior, remotes, locals)
}
} else {
throw new Error('No avaliable model can be connected!')
}
}
const connect = async ({ remotes = {}, remote_priority, locals = {}, local_priority, prefer } = {}) => {
const remoteNames = remote_priority || Object.keys(remotes)
const remote = remoteNames.map((name) => [name, models[name], remotes[name]])
const localNames = local_priority || Object.keys(locals)
const local = localNames.map((name) => [name, models[name], locals[name]])
const prior = prefer === 'local' ? local.concat(remote) : remote.concat(local)
const [model, connect] = await tryConnect(prior)
return createSession(model, connect, prior, remotes, locals)
}
const ai = { connect, insertEntry, updateEntry, removeEntry }
export default ai