Skip to content

Commit

Permalink
Create provider settings at build time and update the settings list d…
Browse files Browse the repository at this point in the history
…ynamically
  • Loading branch information
brichet committed Nov 4, 2024
1 parent f0637eb commit a01f764
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ jupyterlab_codestral/labextension
# Version file is handled by hatchling
jupyterlab_codestral/_version.py

# Settings schema are built
src/_provider-settings

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python

Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"url": "https://github.com/jupyterlite/jupyterlab-codestral.git"
},
"scripts": {
"build": "jlpm build:lib && jlpm build:labextension:dev",
"build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
"build": "node ./scripts/settings-generator.js && jlpm build:lib && jlpm build:labextension:dev",
"build:dev": "jlpm build:lib && jlpm build:labextension:dev",
"build:prod": "node ./scripts/settings-generator.js && jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc --sourceMap",
Expand Down Expand Up @@ -87,6 +88,7 @@
"stylelint-config-standard": "^34.0.0",
"stylelint-csstree-validator": "^3.0.0",
"stylelint-prettier": "^4.0.0",
"ts-json-schema-generator": "^2.3.0",
"typescript": "~5.0.2",
"yjs": "^13.5.0"
},
Expand Down
8 changes: 1 addition & 7 deletions schema/ai-provider.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@
"description": "The AI provider to use for chat and completion",
"default": "None",
"enum": ["None", "MistralAI"]
},
"apiKey": {
"type": "string",
"title": "The Codestral API key",
"description": "The API key to use for Codestral",
"default": ""
}
},
"additionalProperties": false
"additionalProperties": true
}
95 changes: 95 additions & 0 deletions scripts/settings-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const fs = require('fs');
const tsj = require('ts-json-schema-generator');
const path = require('path');

console.log('Building settings schema\n');

const outputDir = 'src/_provider-settings';
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}

// Build the langchain BaseLanguageModelParams object
const configBase = {
path: 'node_modules/@langchain/core/dist/language_models/base.d.ts',
tsconfig: './tsconfig.json',
type: 'BaseLanguageModelParams',
};

const schemaBase = tsj.createGenerator(configBase).createSchema(configBase.type);

const providers = {
mistralAI: {
path: 'node_modules/@langchain/mistralai/dist/chat_models.d.ts',
type: 'ChatMistralAIInput'
}
};

Object.entries(providers).forEach(([name, desc], index) => {
const config = {
path: desc.path,
tsconfig: './tsconfig.json',
type: desc.type
};

const outputPath = path.join(outputDir, `${name}.json`);

const schema =tsj.createGenerator(config).createSchema(config.type);

if (!schema.definitions) {
return;
}

// Remove the properties from extended class.
const providerKeys = Object.keys(
schema.definitions[desc.type]['properties']
);
Object.keys(
schemaBase.definitions?.['BaseLanguageModelParams']['properties']
).forEach(key => {
if (providerKeys.includes(key)) {
delete schema.definitions?.[desc.type]['properties'][key];
}
});

// Remove the useless definitions.
let change = true;
while (change) {
change = false;
const temporarySchemaString = JSON.stringify(schema);

Object.keys(schema.definitions).forEach(key => {
const index = temporarySchemaString.indexOf(`#/definitions/${key}`);
if (index === -1) {
delete schema.definitions?.[key];
change = true;
}
});
}

// Transform the default values.
Object.values(schema.definitions[desc.type]['properties']).forEach(value => {
const defaultValue = value.default;
if (!defaultValue) {
return;
}
if (value.type === 'number') {
value.default = Number(/{(.*)}/.exec(value.default)?.[1] ?? 0);
} else if (value.type === 'boolean') {
value.default = (/{(.*)}/.exec(value.default))?.[1] === 'true';
} else if (value.type === 'string') {
value.default = /{\"(.*)\"}/.exec(value.default)?.[1] ?? '';
}
});

// Write JSON file.
const schemaString = JSON.stringify(schema, null, 2);
fs.writeFile(outputPath, schemaString, err => {
if (err) {
throw err;
}
});
});

console.log('Settings schema built\n');
console.log('=====================\n');
25 changes: 24 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { ISettingRegistry } from '@jupyterlab/settingregistry';

import { ChatHandler } from './chat-handler';
import { getSettings } from './llm-models';
import { AIProvider } from './provider';
import { IAIProvider } from './token';

Expand Down Expand Up @@ -105,12 +106,34 @@ const aiProviderPlugin: JupyterFrontEndPlugin<IAIProvider> = {
settingRegistry: ISettingRegistry
): IAIProvider => {
const aiProvider = new AIProvider({ completionProviderManager: manager });

let currentProvider = 'None';
settingRegistry
.load(aiProviderPlugin.id)
.then(settings => {
const updateProvider = () => {
const provider = settings.get('provider').composite as string;
if (provider !== currentProvider) {
// Update the settings panel.
currentProvider = provider;
const settingsProperties = settings.schema.properties;
if (settingsProperties) {
const schemaKeys = Object.keys(settingsProperties);
schemaKeys.forEach(key => {
if (key !== 'provider') {
delete settings.schema.properties?.[key];
}
});
const properties = getSettings(provider);
if (properties === null) {
return;
}
Object.entries(properties).forEach(([name, value], index) => {
settingsProperties[name] = value as ISettingRegistry.IProperty;
});
}
}

// Update the settings to the AI providers.
aiProvider.setModels(provider, settings.composite);
};

Expand Down
14 changes: 14 additions & 0 deletions src/llm-models/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
import { ChatMistralAI } from '@langchain/mistralai';
import { JSONObject } from '@lumino/coreutils';

import { IBaseCompleter } from './base-completer';
import { CodestralCompleter } from './codestral-completer';

import mistralAI from '../_provider-settings/mistralAI.json';

/**
* Get an LLM completer from the name.
*/
Expand All @@ -22,3 +26,13 @@ export function getChatModel(name: string): BaseChatModel | null {
}
return null;
}

/**
* Get an LLM completer from the name.
*/
export function getSettings(name: string): JSONObject | null {
if (name === 'MistralAI') {
return mistralAI.definitions.ChatMistralAIInput.properties;
}
return null;
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
"strictNullChecks": true,
"target": "ES2018"
},
"include": ["src/*", "src/**/*"]
"include": ["src/*", "src/**/*", "src/_provider-settings/*.json"]
}
78 changes: 77 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2258,7 +2258,7 @@ __metadata:
languageName: node
linkType: hard

"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98
Expand Down Expand Up @@ -3132,6 +3132,13 @@ __metadata:
languageName: node
linkType: hard

"commander@npm:^12.0.0":
version: 12.1.0
resolution: "commander@npm:12.1.0"
checksum: 68e9818b00fc1ed9cdab9eb16905551c2b768a317ae69a5e3c43924c2b20ac9bb65b27e1cab36aeda7b6496376d4da908996ba2c0b5d79463e0fb1e77935d514
languageName: node
linkType: hard

"commander@npm:^2.20.0":
version: 2.20.3
resolution: "commander@npm:2.20.3"
Expand Down Expand Up @@ -4135,6 +4142,22 @@ __metadata:
languageName: node
linkType: hard

"glob@npm:^10.3.12":
version: 10.4.5
resolution: "glob@npm:10.4.5"
dependencies:
foreground-child: ^3.1.0
jackspeak: ^3.1.2
minimatch: ^9.0.4
minipass: ^7.1.2
package-json-from-dist: ^1.0.0
path-scurry: ^1.11.1
bin:
glob: dist/esm/bin.mjs
checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a
languageName: node
linkType: hard

"glob@npm:^10.3.7":
version: 10.4.1
resolution: "glob@npm:10.4.1"
Expand Down Expand Up @@ -4907,6 +4930,7 @@ __metadata:
stylelint-config-standard: ^34.0.0
stylelint-csstree-validator: ^3.0.0
stylelint-prettier: ^4.0.0
ts-json-schema-generator: ^2.3.0
typescript: ~5.0.2
yjs: ^13.5.0
languageName: unknown
Expand Down Expand Up @@ -5552,6 +5576,13 @@ __metadata:
languageName: node
linkType: hard

"package-json-from-dist@npm:^1.0.0":
version: 1.0.1
resolution: "package-json-from-dist@npm:1.0.1"
checksum: 58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602
languageName: node
linkType: hard

"parent-module@npm:^1.0.0":
version: 1.0.1
resolution: "parent-module@npm:1.0.1"
Expand Down Expand Up @@ -6150,6 +6181,13 @@ __metadata:
languageName: node
linkType: hard

"safe-stable-stringify@npm:^2.4.3":
version: 2.5.0
resolution: "safe-stable-stringify@npm:2.5.0"
checksum: d3ce103ed43c6c2f523e39607208bfb1c73aa48179fc5be53c3aa97c118390bffd4d55e012f5393b982b65eb3e0ee954dd57b547930d3f242b0053dcdb923d17
languageName: node
linkType: hard

"safer-buffer@npm:>= 2.1.2 < 3.0.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
Expand Down Expand Up @@ -6875,6 +6913,24 @@ __metadata:
languageName: node
linkType: hard

"ts-json-schema-generator@npm:^2.3.0":
version: 2.3.0
resolution: "ts-json-schema-generator@npm:2.3.0"
dependencies:
"@types/json-schema": ^7.0.15
commander: ^12.0.0
glob: ^10.3.12
json5: ^2.2.3
normalize-path: ^3.0.0
safe-stable-stringify: ^2.4.3
tslib: ^2.6.2
typescript: ^5.4.5
bin:
ts-json-schema-generator: bin/ts-json-schema-generator.js
checksum: 72ee16d822a3f20c6e27ccd660f3cb16f498d8a763236e3cd9639e5a8cc58629c5f0514cc76268e28e23081a00059f4d165865e4a28326e187f43ea9a5d0ea48
languageName: node
linkType: hard

"tslib@npm:^1.13.0":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
Expand Down Expand Up @@ -6964,6 +7020,16 @@ __metadata:
languageName: node
linkType: hard

"typescript@npm:^5.4.5":
version: 5.6.3
resolution: "typescript@npm:5.6.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: ba302f8822777ebefb28b554105f3e074466b671e7444ec6b75dadc008a62f46f373d9e57ceced1c433756d06c8b7dc569a7eefdf3a9573122a49205ff99021a
languageName: node
linkType: hard

"typescript@npm:~5.0.2":
version: 5.0.4
resolution: "typescript@npm:5.0.4"
Expand All @@ -6974,6 +7040,16 @@ __metadata:
languageName: node
linkType: hard

"typescript@patch:typescript@^5.4.5#~builtin<compat/typescript>":
version: 5.6.3
resolution: "typescript@patch:typescript@npm%3A5.6.3#~builtin<compat/typescript>::version=5.6.3&hash=85af82"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: ade87bce2363ee963eed0e4ca8a312ea02c81873ebd53609bc3f6dc0a57f6e61ad7e3fb8cbb7f7ab8b5081cbee801b023f7c4823ee70b1c447eae050e6c7622b
languageName: node
linkType: hard

"typescript@patch:typescript@~5.0.2#~builtin<compat/typescript>":
version: 5.0.4
resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin<compat/typescript>::version=5.0.4&hash=85af82"
Expand Down

0 comments on commit a01f764

Please sign in to comment.