Skip to content

Commit

Permalink
fix(llm): Allow to load available models from the OpenAI models API e…
Browse files Browse the repository at this point in the history
…ndpoint
  • Loading branch information
andris9 committed Nov 27, 2023
1 parent 185d613 commit 00fffda
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 66 deletions.
80 changes: 62 additions & 18 deletions lib/routes-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,20 @@ const SMTP_TEST_HOST = 'https://api.nodemailer.com';
const OPEN_AI_MODELS = [
{
name: 'GPT-3 (instruct)',
key: 'gpt-3.5-turbo-instruct',
instruct: true
id: 'gpt-3.5-turbo-instruct'
},

{
name: 'GPT-3 (chat)',
key: 'gpt-3.5-turbo'
id: 'gpt-3.5-turbo'
},

{
name: 'GPT-4',
key: 'gpt-4'
id: 'gpt-4'
}
];

const OPEN_AI_MODELS_CHAT = OPEN_AI_MODELS.filter(model => !model.instruct);

const notificationTypes = Object.keys(consts)
.map(key => {
if (/_NOTIFY$/.test(key)) {
Expand All @@ -128,18 +125,18 @@ const cachedTemplates = {
testSend: fs.readFileSync(pathlib.join(__dirname, '..', 'views', 'partials', 'test_send.hbs'), 'utf-8')
};

const getOpenAiModels = (models, selectedModel) => {
let modelList = pfStructuredClone(models);
const getOpenAiModels = async (models, selectedModel) => {
let modelList = (await settings.get('openAiModels')) || pfStructuredClone(models);

if (selectedModel && !models.find(model => model.key === selectedModel)) {
modelList.push({
if (selectedModel && !modelList.find(model => model.id === selectedModel)) {
modelList.unshift({
name: selectedModel,
key: selectedModel
id: selectedModel
});
}

return modelList.map(model => {
model.selected = model.key === selectedModel;
model.selected = model.id === selectedModel;
return model;
});
};
Expand Down Expand Up @@ -1400,7 +1397,7 @@ return true;`

hasOpenAiAPIKey,
openAiError,
openAiModels: getOpenAiModels(OPEN_AI_MODELS, openAiModel),
openAiModels: await getOpenAiModels(OPEN_AI_MODELS, openAiModel),

scriptEnvJson: JSON.stringify((await settings.get('scriptEnv')) || '{}'),
examplePayloadsJson: JSON.stringify(
Expand Down Expand Up @@ -1499,7 +1496,7 @@ return true;`

hasOpenAiAPIKey,
openAiError,
openAiModels: getOpenAiModels(OPEN_AI_MODELS, request.payload.openAiModel),
openAiModels: await getOpenAiModels(OPEN_AI_MODELS, request.payload.openAiModel),

scriptEnvJson: JSON.stringify((await settings.get('scriptEnv')) || '{}'),
examplePayloadsJson: JSON.stringify(
Expand Down Expand Up @@ -1563,7 +1560,7 @@ return true;`

hasOpenAiAPIKey,
openAiError,
openAiModels: getOpenAiModels(OPEN_AI_MODELS, request.payload.openAiModel),
openAiModels: await getOpenAiModels(OPEN_AI_MODELS, request.payload.openAiModel),

scriptEnvJson: JSON.stringify((await settings.get('scriptEnv')) || '{}'),
examplePayloadsJson: JSON.stringify(
Expand Down Expand Up @@ -1677,6 +1674,53 @@ return true;`
}
});

server.route({
method: 'POST',
path: '/admin/config/ai/reload-models',
async handler(request) {
try {
request.logger.info({ msg: 'Reload models' });

const { models } = await call({
cmd: 'openAiListModels',
data: {
openAiAPIKey: request.payload.openAiAPIKey,
openAiAPIUrl: request.payload.openAiAPIUrl
},
timeout: 2 * 60 * 1000
});

if (models && models.length) {
await settings.set('openAiModels', models);
}

return { success: true, models };
} catch (err) {
request.logger.error({ msg: 'Failed reloading OpenAI models', err });
return {
success: false,
error: err.message
};
}
},
options: {
validate: {
options: {
stripUnknown: true,
abortEarly: false,
convert: true
},

failAction,

payload: Joi.object({
openAiAPIKey: settingsSchema.openAiAPIKey.empty(''),
openAiAPIUrl: settingsSchema.openAiAPIUrl.default('')
})
}
}
});

server.route({
method: 'POST',
path: '/admin/config/service/preview',
Expand Down Expand Up @@ -7567,7 +7611,7 @@ ${Buffer.from(data.content, 'base64url').toString('base64')}
hasOpenAiAPIKey: !!(await settings.get('openAiAPIKey')),
indexInfo: await settings.get('embeddings:index'),

openAiModels: getOpenAiModels(OPEN_AI_MODELS_CHAT, documentStoreChatModel),
openAiModels: await getOpenAiModels(OPEN_AI_MODELS, documentStoreChatModel),

values: {
documentStoreGenerateEmbeddings: (await settings.get(`documentStoreGenerateEmbeddings`)) || false
Expand Down Expand Up @@ -7607,7 +7651,7 @@ ${Buffer.from(data.content, 'base64url').toString('base64')}
hasOpenAiAPIKey: !!(await settings.get('openAiAPIKey')),
indexInfo: await settings.get('embeddings:index'),

openAiModels: getOpenAiModels(OPEN_AI_MODELS_CHAT, request.payload.documentStoreChatModel)
openAiModels: await getOpenAiModels(OPEN_AI_MODELS_CHAT, request.payload.documentStoreChatModel)

Check failure on line 7654 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (16.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined

Check failure on line 7654 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (18.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined

Check failure on line 7654 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (20.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined
},
{
layout: 'app'
Expand Down Expand Up @@ -7649,7 +7693,7 @@ ${Buffer.from(data.content, 'base64url').toString('base64')}
hasOpenAiAPIKey: !!(await settings.get('openAiAPIKey')),
indexInfo: await settings.get('embeddings:index'),

openAiModels: getOpenAiModels(OPEN_AI_MODELS_CHAT, request.payload.documentStoreChatModel),
openAiModels: await getOpenAiModels(OPEN_AI_MODELS_CHAT, request.payload.documentStoreChatModel),

Check failure on line 7696 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (16.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined

Check failure on line 7696 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (18.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined

Check failure on line 7696 in lib/routes-ui.js

View workflow job for this annotation

GitHub Actions / test (20.x, ubuntu-20.04)

'OPEN_AI_MODELS_CHAT' is not defined

errors
},
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
"@hapi/vision": "7.0.3",
"@phc/pbkdf2": "1.1.14",
"@postalsys/certs": "1.0.7",
"@postalsys/email-ai-tools": "1.7.2",
"@postalsys/email-ai-tools": "1.8.0",
"@postalsys/email-text-tools": "2.1.3",
"@postalsys/hecks": "3.0.0-fork.3",
"@postalsys/templates": "1.0.7",
"ace-builds": "1.31.2",
"base32.js": "0.1.0",
"bull-arena": "4.1.0",
"bullmq": "4.14.1",
"bullmq": "4.14.2",
"compare-versions": "6.1.0",
"dotenv": "16.3.1",
"encoding-japanese": "2.0.0",
Expand Down Expand Up @@ -104,7 +104,7 @@
"speakeasy": "2.0.0",
"startbootstrap-sb-admin-2": "3.3.7",
"timezones-list": "3.0.2",
"undici": "5.27.2",
"undici": "5.28.1",
"uuid": "9.0.1",
"wild-config": "1.7.1",
"xml2js": "0.6.2"
Expand Down
2 changes: 1 addition & 1 deletion sbom.json

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const {
getChunkEmbeddings,
embeddingsQuery,
questionQuery,
listModels: openAiListModels,
DEFAULT_USER_PROMPT: openAiDefaultPrompt
} = require('@postalsys/email-ai-tools');
const { fetch: fetchCmd, Agent } = require('undici');
Expand Down Expand Up @@ -1626,6 +1627,29 @@ async function onCommand(worker, message) {
return data;
}

case 'openAiListModels': {
let requestOpts = {
verbose: getBoolean(process.env.EE_OPENAPI_VERBOSE)
};

let openAiAPIKey = message.data.openAiAPIKey || (await settings.get('openAiAPIKey'));

if (!openAiAPIKey) {
throw new Error(`OpenAI API key is not set`);
}

let openAiAPIUrl = message.data.openAiAPIUrl || (await settings.get('openAiAPIUrl'));
if (openAiAPIUrl) {
requestOpts.baseApiUrl = openAiAPIUrl;
}

requestOpts.user = message.data.account;

const data = await openAiListModels(openAiAPIKey, requestOpts);

return data;
}

case 'openAiDefaultPrompt': {
return openAiDefaultPrompt;
}
Expand Down
28 changes: 14 additions & 14 deletions static/licenses.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!doctype html><html><head><meta charset="utf-8"><title>EmailEngine Licenses</title><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous"></head><body>
<div class="container-fluid">
<h1>EmailEngine v2.39.0</h1><p>EmailEngine includes code from the following software packages:</p>
<h1>EmailEngine v2.39.1</h1><p>EmailEngine includes code from the following software packages:</p>
<table class="table table-sm">
<tr><thead class="thead-dark"><th>Package</th><th>Version</th><th>License</th><th>Publisher</th><th>Publisher's Email</th><th>Package URL</th></tr>
<tbody>
Expand Down Expand Up @@ -856,7 +856,7 @@ <h1>EmailEngine v2.39.0</h1><p>EmailEngine includes code from the following soft
</tr>
<tr>
<td><a href="https://npmjs.com/package/@postalsys/email-ai-tools">@postalsys/email-ai-tools</a></td>
<td>1.7.2</td>
<td>1.8.0</td>
<td>MIT</td>
<td>Postal Systems O&#xDC;</td>
<td></td>
Expand Down Expand Up @@ -1616,7 +1616,7 @@ <h1>EmailEngine v2.39.0</h1><p>EmailEngine includes code from the following soft
</tr>
<tr>
<td><a href="https://npmjs.com/package/bullmq">bullmq</a></td>
<td>4.14.1</td>
<td>4.14.2</td>
<td>MIT</td>
<td>Taskforce.sh Inc.</td>
<td></td>
Expand Down Expand Up @@ -7354,6 +7354,16 @@ <h1>EmailEngine v2.39.0</h1><p>EmailEngine includes code from the following soft
</td
</tr>
<tr>
<td><a href="https://npmjs.com/package/tlds">tlds</a></td>
<td>1.247.0</td>
<td>MIT</td>
<td>Stephen Mathieson</td>
<td></td>
<td>
<a href="https://github.com/stephenmathieson/node-tlds">github.com/stephenmathieson/node-tlds</a>
</td
</tr>
<tr>
<td><a href="https://npmjs.com/package/to-fast-properties">to-fast-properties</a></td>
<td>2.0.0</td>
<td>MIT</td>
Expand Down Expand Up @@ -7575,17 +7585,7 @@ <h1>EmailEngine v2.39.0</h1><p>EmailEngine includes code from the following soft
</tr>
<tr>
<td><a href="https://npmjs.com/package/undici">undici</a></td>
<td>5.27.0</td>
<td>MIT</td>
<td></td>
<td></td>
<td>
<a href="https://github.com/nodejs/undici">github.com/nodejs/undici</a>
</td
</tr>
<tr>
<td><a href="https://npmjs.com/package/undici">undici</a></td>
<td>5.27.2</td>
<td>5.28.1</td>
<td>MIT</td>
<td></td>
<td></td>
Expand Down
54 changes: 27 additions & 27 deletions translations/messages.pot
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=ascii\n"
"POT-Creation-Date: 2023-11-24 07:38+0000\n"
"POT-Creation-Date: 2023-11-27 14:28+0000\n"

#: views/config/license.hbs:48
msgid "%d day"
msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""

#: views/redirect.hbs:1
msgid "Click <a href=\"%s\">here</a> to continue&mldr;"
msgstr ""

#: views/unsubscribe.hbs:1
#: views/unsubscribe.hbs:79
msgid "Unsubscribe"
Expand Down Expand Up @@ -57,12 +53,8 @@ msgstr ""
msgid "Enter your email address"
msgstr ""

#: views/accounts/register/index.hbs:2
msgid "Choose your email account provider"
msgstr ""

#: views/accounts/register/index.hbs:15
msgid "Standard IMAP"
#: views/redirect.hbs:1
msgid "Click <a href=\"%s\">here</a> to continue&mldr;"
msgstr ""

#: views/accounts/register/imap.hbs:11
Expand Down Expand Up @@ -189,40 +181,48 @@ msgstr ""
msgid "HTTP error!"
msgstr ""

#: lib/routes-ui.js:603
#: views/accounts/register/index.hbs:2
msgid "Choose your email account provider"
msgstr ""

#: views/accounts/register/index.hbs:15
msgid "Standard IMAP"
msgstr ""

#: lib/routes-ui.js:600
msgid "Invalid API key for OpenAI"
msgstr ""

#: lib/routes-ui.js:4568
#: lib/routes-ui.js:6490
#: lib/routes-ui.js:6501
#: lib/routes-ui.js:4612
#: lib/routes-ui.js:6534
#: lib/routes-ui.js:6545
msgid "Server hostname was not found"
msgstr ""

#: lib/routes-ui.js:4571
#: lib/routes-ui.js:6493
#: lib/routes-ui.js:6504
#: lib/routes-ui.js:4615
#: lib/routes-ui.js:6537
#: lib/routes-ui.js:6548
msgid "Invalid username or password"
msgstr ""

#: lib/routes-ui.js:4575
#: lib/routes-ui.js:6508
#: lib/routes-ui.js:4619
#: lib/routes-ui.js:6552
msgid "TLS protocol error"
msgstr ""

#: lib/routes-ui.js:6302
#: lib/routes-ui.js:6342
#: lib/routes-ui.js:9036
#: lib/routes-ui.js:6346
#: lib/routes-ui.js:6386
#: lib/routes-ui.js:9080
msgid "Failed to validate request arguments"
msgstr ""

#: lib/routes-ui.js:6428
#: lib/routes-ui.js:6682
#: lib/routes-ui.js:6472
#: lib/routes-ui.js:6726
msgid "Failed to process account"
msgstr ""

#: lib/routes-ui.js:9136
#: lib/routes-ui.js:9169
#: lib/routes-ui.js:9180
#: lib/routes-ui.js:9213
msgid "Failed to process request"
msgstr ""

Expand Down
Loading

0 comments on commit 00fffda

Please sign in to comment.