@jupyterlite/ai 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/chat-handler.d.ts +10 -4
- package/lib/chat-handler.js +42 -10
- package/lib/completion-provider.d.ts +5 -18
- package/lib/completion-provider.js +8 -34
- package/lib/{llm-models/anthropic-completer.d.ts → default-providers/Anthropic/completer.d.ts} +1 -1
- package/lib/{llm-models/anthropic-completer.js → default-providers/Anthropic/completer.js} +1 -1
- package/lib/{llm-models/chrome-completer.d.ts → default-providers/ChromeAI/completer.d.ts} +1 -1
- package/lib/{llm-models/chrome-completer.js → default-providers/ChromeAI/completer.js} +1 -1
- package/lib/default-providers/ChromeAI/instructions.d.ts +2 -0
- package/lib/default-providers/ChromeAI/instructions.js +24 -0
- package/lib/{llm-models/codestral-completer.d.ts → default-providers/MistralAI/completer.d.ts} +1 -1
- package/lib/{llm-models/codestral-completer.js → default-providers/MistralAI/completer.js} +1 -1
- package/lib/default-providers/MistralAI/instructions.d.ts +2 -0
- package/lib/default-providers/MistralAI/instructions.js +16 -0
- package/lib/{llm-models/openai-completer.d.ts → default-providers/OpenAI/completer.d.ts} +1 -1
- package/lib/{llm-models/openai-completer.js → default-providers/OpenAI/completer.js} +1 -1
- package/lib/default-providers/index.d.ts +2 -0
- package/lib/default-providers/index.js +60 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.js +51 -64
- package/lib/provider.d.ts +45 -17
- package/lib/provider.js +97 -41
- package/lib/settings/base.json +7 -0
- package/lib/settings/panel.d.ts +84 -0
- package/lib/settings/panel.js +267 -0
- package/lib/tokens.d.ts +103 -0
- package/lib/tokens.js +5 -0
- package/package.json +12 -5
- package/schema/provider-registry.json +23 -0
- package/src/chat-handler.ts +50 -13
- package/src/completion-provider.ts +13 -37
- package/src/{llm-models/anthropic-completer.ts → default-providers/Anthropic/completer.ts} +2 -2
- package/src/{llm-models/chrome-completer.ts → default-providers/ChromeAI/completer.ts} +3 -2
- package/src/default-providers/ChromeAI/instructions.ts +24 -0
- package/src/{llm-models/codestral-completer.ts → default-providers/MistralAI/completer.ts} +2 -2
- package/src/default-providers/MistralAI/instructions.ts +16 -0
- package/src/{llm-models/openai-completer.ts → default-providers/OpenAI/completer.ts} +2 -2
- package/src/default-providers/index.ts +71 -0
- package/src/index.ts +75 -77
- package/src/provider.ts +100 -43
- package/src/settings/panel.tsx +346 -0
- package/src/tokens.ts +112 -0
- package/style/base.css +4 -0
- package/lib/llm-models/index.d.ts +0 -3
- package/lib/llm-models/index.js +0 -3
- package/lib/llm-models/utils.d.ts +0 -16
- package/lib/llm-models/utils.js +0 -86
- package/lib/slash-commands.d.ts +0 -16
- package/lib/slash-commands.js +0 -25
- package/lib/token.d.ts +0 -13
- package/lib/token.js +0 -2
- package/schema/ai-provider.json +0 -17
- package/src/llm-models/index.ts +0 -3
- package/src/llm-models/utils.ts +0 -90
- package/src/slash-commands.tsx +0 -55
- package/src/token.ts +0 -19
- /package/lib/{llm-models/base-completer.d.ts → base-completer.d.ts} +0 -0
- /package/lib/{llm-models/base-completer.js → base-completer.js} +0 -0
- /package/lib/{_provider-settings/anthropic.json → default-providers/Anthropic/settings-schema.json} +0 -0
- /package/lib/{_provider-settings/chromeAI.json → default-providers/ChromeAI/settings-schema.json} +0 -0
- /package/lib/{_provider-settings/mistralAI.json → default-providers/MistralAI/settings-schema.json} +0 -0
- /package/lib/{_provider-settings/openAI.json → default-providers/OpenAI/settings-schema.json} +0 -0
- /package/src/{llm-models/base-completer.ts → base-completer.ts} +0 -0
- /package/src/{llm-models/svg.d.ts → global.d.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ActiveCellManager,
|
|
3
|
-
AutocompletionRegistry,
|
|
4
3
|
buildChatSidebar,
|
|
5
4
|
buildErrorWidget,
|
|
5
|
+
ChatCommandRegistry,
|
|
6
6
|
IActiveCellManager,
|
|
7
|
-
|
|
8
|
-
IAutocompletionRegistry
|
|
7
|
+
IChatCommandRegistry
|
|
9
8
|
} from '@jupyter/chat';
|
|
10
9
|
import {
|
|
11
10
|
JupyterFrontEnd,
|
|
@@ -16,51 +15,40 @@ import { ICompletionProviderManager } from '@jupyterlab/completer';
|
|
|
16
15
|
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
17
16
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
18
17
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
18
|
+
import { IFormRendererRegistry } from '@jupyterlab/ui-components';
|
|
19
|
+
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
|
|
20
|
+
import { ISecretsManager } from 'jupyter-secrets-manager';
|
|
19
21
|
|
|
20
22
|
import { ChatHandler } from './chat-handler';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
id: option.slice(1),
|
|
40
|
-
label: option,
|
|
41
|
-
description: 'Clear the chat window'
|
|
42
|
-
};
|
|
43
|
-
}),
|
|
44
|
-
props: {
|
|
45
|
-
renderOption: renderSlashCommandOption
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
autocompletionRegistry.add('jupyterlite-ai', autocompletionCommands);
|
|
49
|
-
return autocompletionRegistry;
|
|
50
|
-
}
|
|
51
|
-
};
|
|
23
|
+
import { CompletionProvider } from './completion-provider';
|
|
24
|
+
import { defaultProviderPlugins } from './default-providers';
|
|
25
|
+
import { AIProviderRegistry } from './provider';
|
|
26
|
+
import { aiSettingsRenderer } from './settings/panel';
|
|
27
|
+
import { IAIProviderRegistry } from './tokens';
|
|
28
|
+
|
|
29
|
+
const chatCommandRegistryPlugin: JupyterFrontEndPlugin<IChatCommandRegistry> = {
|
|
30
|
+
id: '@jupyterlite/ai:autocompletion-registry',
|
|
31
|
+
description: 'Autocompletion registry',
|
|
32
|
+
autoStart: true,
|
|
33
|
+
provides: IChatCommandRegistry,
|
|
34
|
+
activate: () => {
|
|
35
|
+
const registry = new ChatCommandRegistry();
|
|
36
|
+
registry.addProvider(new ChatHandler.ClearCommandProvider());
|
|
37
|
+
return registry;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
52
40
|
|
|
53
41
|
const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
54
42
|
id: '@jupyterlite/ai:chat',
|
|
55
43
|
description: 'LLM chat extension',
|
|
56
44
|
autoStart: true,
|
|
57
|
-
requires: [
|
|
45
|
+
requires: [IAIProviderRegistry, IRenderMimeRegistry, IChatCommandRegistry],
|
|
58
46
|
optional: [INotebookTracker, ISettingRegistry, IThemeManager],
|
|
59
47
|
activate: async (
|
|
60
48
|
app: JupyterFrontEnd,
|
|
61
|
-
|
|
49
|
+
providerRegistry: IAIProviderRegistry,
|
|
62
50
|
rmRegistry: IRenderMimeRegistry,
|
|
63
|
-
|
|
51
|
+
chatCommandRegistry: IChatCommandRegistry,
|
|
64
52
|
notebookTracker: INotebookTracker | null,
|
|
65
53
|
settingsRegistry: ISettingRegistry | null,
|
|
66
54
|
themeManager: IThemeManager | null
|
|
@@ -74,8 +62,8 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
74
62
|
}
|
|
75
63
|
|
|
76
64
|
const chatHandler = new ChatHandler({
|
|
77
|
-
|
|
78
|
-
activeCellManager
|
|
65
|
+
providerRegistry,
|
|
66
|
+
activeCellManager
|
|
79
67
|
});
|
|
80
68
|
|
|
81
69
|
let sendWithShiftEnter = false;
|
|
@@ -116,7 +104,7 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
116
104
|
model: chatHandler,
|
|
117
105
|
themeManager,
|
|
118
106
|
rmRegistry,
|
|
119
|
-
|
|
107
|
+
chatCommandRegistry
|
|
120
108
|
});
|
|
121
109
|
chatWidget.title.caption = 'Jupyterlite AI Chat';
|
|
122
110
|
} catch (e) {
|
|
@@ -129,50 +117,54 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
129
117
|
}
|
|
130
118
|
};
|
|
131
119
|
|
|
132
|
-
const
|
|
133
|
-
id: '@jupyterlite/ai:
|
|
120
|
+
const completerPlugin: JupyterFrontEndPlugin<void> = {
|
|
121
|
+
id: '@jupyterlite/ai:completer',
|
|
134
122
|
autoStart: true,
|
|
135
|
-
requires: [
|
|
136
|
-
provides: IAIProvider,
|
|
123
|
+
requires: [IAIProviderRegistry, ICompletionProviderManager],
|
|
137
124
|
activate: (
|
|
138
125
|
app: JupyterFrontEnd,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
):
|
|
142
|
-
const
|
|
143
|
-
|
|
126
|
+
providerRegistry: IAIProviderRegistry,
|
|
127
|
+
manager: ICompletionProviderManager
|
|
128
|
+
): void => {
|
|
129
|
+
const completer = new CompletionProvider({
|
|
130
|
+
providerRegistry,
|
|
144
131
|
requestCompletion: () => app.commands.execute('inline-completer:invoke')
|
|
145
132
|
});
|
|
133
|
+
manager.registerInlineProvider(completer);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
146
136
|
|
|
147
|
-
|
|
137
|
+
const providerRegistryPlugin: JupyterFrontEndPlugin<IAIProviderRegistry> = {
|
|
138
|
+
id: '@jupyterlite/ai:provider-registry',
|
|
139
|
+
autoStart: true,
|
|
140
|
+
requires: [IFormRendererRegistry, ISettingRegistry],
|
|
141
|
+
optional: [IRenderMimeRegistry, ISecretsManager],
|
|
142
|
+
provides: IAIProviderRegistry,
|
|
143
|
+
activate: (
|
|
144
|
+
app: JupyterFrontEnd,
|
|
145
|
+
editorRegistry: IFormRendererRegistry,
|
|
146
|
+
settingRegistry: ISettingRegistry,
|
|
147
|
+
rmRegistry?: IRenderMimeRegistry,
|
|
148
|
+
secretsManager?: ISecretsManager
|
|
149
|
+
): IAIProviderRegistry => {
|
|
150
|
+
const providerRegistry = new AIProviderRegistry();
|
|
151
|
+
|
|
152
|
+
editorRegistry.addRenderer(
|
|
153
|
+
'@jupyterlite/ai:provider-registry.AIprovider',
|
|
154
|
+
aiSettingsRenderer({ providerRegistry, rmRegistry, secretsManager })
|
|
155
|
+
);
|
|
148
156
|
settingRegistry
|
|
149
|
-
.load(
|
|
157
|
+
.load(providerRegistryPlugin.id)
|
|
150
158
|
.then(settings => {
|
|
151
159
|
const updateProvider = () => {
|
|
152
|
-
const provider = settings.get('provider').composite as string;
|
|
153
|
-
if (provider !== currentProvider) {
|
|
154
|
-
// Update the settings panel.
|
|
155
|
-
currentProvider = provider;
|
|
156
|
-
const settingsProperties = settings.schema.properties;
|
|
157
|
-
if (settingsProperties) {
|
|
158
|
-
const schemaKeys = Object.keys(settingsProperties);
|
|
159
|
-
schemaKeys.forEach(key => {
|
|
160
|
-
if (key !== 'provider') {
|
|
161
|
-
delete settings.schema.properties?.[key];
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
const properties = getSettings(provider);
|
|
165
|
-
if (properties === null) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
Object.entries(properties).forEach(([name, value], index) => {
|
|
169
|
-
settingsProperties[name] = value as ISettingRegistry.IProperty;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
160
|
// Update the settings to the AI providers.
|
|
175
|
-
|
|
161
|
+
const providerSettings = (settings.get('AIprovider').composite ?? {
|
|
162
|
+
provider: 'None'
|
|
163
|
+
}) as ReadonlyPartialJSONObject;
|
|
164
|
+
providerRegistry.setProvider(
|
|
165
|
+
providerSettings.provider as string,
|
|
166
|
+
providerSettings
|
|
167
|
+
);
|
|
176
168
|
};
|
|
177
169
|
|
|
178
170
|
settings.changed.connect(() => updateProvider());
|
|
@@ -180,13 +172,19 @@ const aiProviderPlugin: JupyterFrontEndPlugin<IAIProvider> = {
|
|
|
180
172
|
})
|
|
181
173
|
.catch(reason => {
|
|
182
174
|
console.error(
|
|
183
|
-
`Failed to load settings for ${
|
|
175
|
+
`Failed to load settings for ${providerRegistryPlugin.id}`,
|
|
184
176
|
reason
|
|
185
177
|
);
|
|
186
178
|
});
|
|
187
179
|
|
|
188
|
-
return
|
|
180
|
+
return providerRegistry;
|
|
189
181
|
}
|
|
190
182
|
};
|
|
191
183
|
|
|
192
|
-
export default [
|
|
184
|
+
export default [
|
|
185
|
+
providerRegistryPlugin,
|
|
186
|
+
chatCommandRegistryPlugin,
|
|
187
|
+
chatPlugin,
|
|
188
|
+
completerPlugin,
|
|
189
|
+
...defaultProviderPlugins
|
|
190
|
+
];
|
package/src/provider.ts
CHANGED
|
@@ -4,11 +4,13 @@ import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
|
4
4
|
import { ISignal, Signal } from '@lumino/signaling';
|
|
5
5
|
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { IBaseCompleter } from './base-completer';
|
|
8
|
+
import { IAIProvider, IAIProviderRegistry } from './tokens';
|
|
9
|
+
import { JSONSchema7 } from 'json-schema';
|
|
10
10
|
|
|
11
|
-
export const chatSystemPrompt = (
|
|
11
|
+
export const chatSystemPrompt = (
|
|
12
|
+
options: AIProviderRegistry.IPromptOptions
|
|
13
|
+
) => `
|
|
12
14
|
You are Jupyternaut, a conversational assistant living in JupyterLab to help users.
|
|
13
15
|
You are not a language model, but rather an application built on a foundation model from ${options.provider_name}.
|
|
14
16
|
You are talkative and you provide lots of specific details from the foundation model's context.
|
|
@@ -36,40 +38,79 @@ would write.
|
|
|
36
38
|
Do not include the prompt in the output, only the string that should be appended to the current input.
|
|
37
39
|
`;
|
|
38
40
|
|
|
39
|
-
export class
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
export class AIProviderRegistry implements IAIProviderRegistry {
|
|
42
|
+
/**
|
|
43
|
+
* Get the list of provider names.
|
|
44
|
+
*/
|
|
45
|
+
get providers(): string[] {
|
|
46
|
+
return Array.from(this._providers.keys());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Add a new provider.
|
|
51
|
+
*/
|
|
52
|
+
add(provider: IAIProvider): void {
|
|
53
|
+
if (this._providers.has(provider.name)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`A AI provider named '${provider.name}' is already registered`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
this._providers.set(provider.name, provider);
|
|
49
59
|
}
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Get the current provider name.
|
|
63
|
+
*/
|
|
64
|
+
get currentName(): string {
|
|
52
65
|
return this._name;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
/**
|
|
56
69
|
* Get the current completer of the completion provider.
|
|
57
70
|
*/
|
|
58
|
-
get
|
|
59
|
-
if (this._name ===
|
|
71
|
+
get currentCompleter(): IBaseCompleter | null {
|
|
72
|
+
if (this._name === 'None') {
|
|
60
73
|
return null;
|
|
61
74
|
}
|
|
62
|
-
return this.
|
|
75
|
+
return this._completer;
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
/**
|
|
66
79
|
* Get the current llm chat model.
|
|
67
80
|
*/
|
|
68
|
-
get
|
|
69
|
-
if (this._name ===
|
|
81
|
+
get currentChatModel(): BaseChatModel | null {
|
|
82
|
+
if (this._name === 'None') {
|
|
70
83
|
return null;
|
|
71
84
|
}
|
|
72
|
-
return this.
|
|
85
|
+
return this._chatModel;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get the settings schema of a given provider.
|
|
90
|
+
*/
|
|
91
|
+
getSettingsSchema(provider: string): JSONSchema7 {
|
|
92
|
+
return (this._providers.get(provider)?.settingsSchema?.properties ||
|
|
93
|
+
{}) as JSONSchema7;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get the instructions of a given provider.
|
|
98
|
+
*/
|
|
99
|
+
getInstructions(provider: string): string | undefined {
|
|
100
|
+
return this._providers.get(provider)?.instructions;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Format an error message from the current provider.
|
|
105
|
+
*/
|
|
106
|
+
formatErrorMessage(error: any): string {
|
|
107
|
+
if (this._currentProvider?.errorMessage) {
|
|
108
|
+
return this._currentProvider?.errorMessage(error);
|
|
109
|
+
}
|
|
110
|
+
if (error.message) {
|
|
111
|
+
return error.message;
|
|
112
|
+
}
|
|
113
|
+
return error;
|
|
73
114
|
}
|
|
74
115
|
|
|
75
116
|
/**
|
|
@@ -87,43 +128,59 @@ export class AIProvider implements IAIProvider {
|
|
|
87
128
|
}
|
|
88
129
|
|
|
89
130
|
/**
|
|
90
|
-
* Set the
|
|
91
|
-
* Creates the
|
|
131
|
+
* Set the providers (chat model and completer).
|
|
132
|
+
* Creates the providers if the name has changed, otherwise only updates their config.
|
|
92
133
|
*
|
|
93
|
-
* @param name - the name of the
|
|
134
|
+
* @param name - the name of the provider to use.
|
|
94
135
|
* @param settings - the settings for the models.
|
|
95
136
|
*/
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
137
|
+
setProvider(name: string, settings: ReadonlyPartialJSONObject): void {
|
|
138
|
+
this._currentProvider = this._providers.get(name) ?? null;
|
|
139
|
+
|
|
140
|
+
if (this._currentProvider?.completer !== undefined) {
|
|
141
|
+
try {
|
|
142
|
+
this._completer = new this._currentProvider.completer({ ...settings });
|
|
143
|
+
this._completerError = '';
|
|
144
|
+
} catch (e: any) {
|
|
145
|
+
this._completerError = e.message;
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
this._completer = null;
|
|
102
149
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
150
|
+
|
|
151
|
+
if (this._currentProvider?.chatModel !== undefined) {
|
|
152
|
+
try {
|
|
153
|
+
this._chatModel = new this._currentProvider.chatModel({ ...settings });
|
|
154
|
+
this._chatError = '';
|
|
155
|
+
} catch (e: any) {
|
|
156
|
+
this._chatError = e.message;
|
|
157
|
+
this._chatModel = null;
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
this._chatModel = null;
|
|
109
161
|
}
|
|
110
162
|
this._name = name;
|
|
111
|
-
this.
|
|
163
|
+
this._providerChanged.emit();
|
|
112
164
|
}
|
|
113
165
|
|
|
114
|
-
|
|
115
|
-
|
|
166
|
+
/**
|
|
167
|
+
* A signal emitting when the provider or its settings has changed.
|
|
168
|
+
*/
|
|
169
|
+
get providerChanged(): ISignal<IAIProviderRegistry, void> {
|
|
170
|
+
return this._providerChanged;
|
|
116
171
|
}
|
|
117
172
|
|
|
118
|
-
private
|
|
119
|
-
private
|
|
173
|
+
private _currentProvider: IAIProvider | null = null;
|
|
174
|
+
private _completer: IBaseCompleter | null = null;
|
|
175
|
+
private _chatModel: BaseChatModel | null = null;
|
|
120
176
|
private _name: string = 'None';
|
|
121
|
-
private
|
|
177
|
+
private _providerChanged = new Signal<IAIProviderRegistry, void>(this);
|
|
122
178
|
private _chatError: string = '';
|
|
123
179
|
private _completerError: string = '';
|
|
180
|
+
private _providers = new Map<string, IAIProvider>();
|
|
124
181
|
}
|
|
125
182
|
|
|
126
|
-
export namespace
|
|
183
|
+
export namespace AIProviderRegistry {
|
|
127
184
|
/**
|
|
128
185
|
* The options for the LLM provider.
|
|
129
186
|
*/
|