Skip to content

Commit 336fb46

Browse files
authored
Completer plugin (#49)
* Make the inline completer a plugin, that depends on AIProvider * Rename some attributes/functions in AIProvider
1 parent 43aa54c commit 336fb46

File tree

5 files changed

+57
-71
lines changed

5 files changed

+57
-71
lines changed

src/chat-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class ChatHandler extends ChatModel {
4040
this._aiProvider = options.aiProvider;
4141
this._prompt = chatSystemPrompt({ provider_name: this._aiProvider.name });
4242

43-
this._aiProvider.modelChange.connect(() => {
43+
this._aiProvider.providerChanged.connect(() => {
4444
this._errorMessage = this._aiProvider.chatError;
4545
this._prompt = chatSystemPrompt({ provider_name: this._aiProvider.name });
4646
});

src/completion-provider.ts

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ import {
33
IInlineCompletionContext,
44
IInlineCompletionProvider
55
} from '@jupyterlab/completer';
6-
import { BaseLanguageModel } from '@langchain/core/language_models/base';
7-
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
86

9-
import { getCompleter, IBaseCompleter, BaseCompleter } from './llm-models';
7+
import { IBaseCompleter } from './llm-models';
8+
import { IAIProvider } from './token';
109

1110
/**
1211
* The generic completion provider to register to the completion provider manager.
@@ -15,67 +14,44 @@ export class CompletionProvider implements IInlineCompletionProvider {
1514
readonly identifier = '@jupyterlite/ai';
1615

1716
constructor(options: CompletionProvider.IOptions) {
18-
const { name, settings } = options;
17+
this._aiProvider = options.aiProvider;
1918
this._requestCompletion = options.requestCompletion;
20-
this.setCompleter(name, settings);
21-
}
2219

23-
/**
24-
* Set the completer.
25-
*
26-
* @param name - the name of the completer.
27-
* @param settings - The settings associated to the completer.
28-
*/
29-
setCompleter(name: string, settings: ReadonlyPartialJSONObject) {
30-
try {
31-
this._completer = getCompleter(name, settings);
32-
if (this._completer) {
33-
this._completer.requestCompletion = this._requestCompletion;
20+
this._aiProvider.providerChanged.connect(() => {
21+
if (this.completer) {
22+
this.completer.requestCompletion = this._requestCompletion;
3423
}
35-
this._name = this._completer === null ? 'None' : name;
36-
} catch (e: any) {
37-
this._completer = null;
38-
this._name = 'None';
39-
throw e;
40-
}
24+
});
4125
}
4226

4327
/**
4428
* Get the current completer name.
4529
*/
4630
get name(): string {
47-
return this._name;
31+
return this._aiProvider.name;
4832
}
4933

5034
/**
5135
* Get the current completer.
5236
*/
5337
get completer(): IBaseCompleter | null {
54-
return this._completer;
55-
}
56-
57-
/**
58-
* Get the LLM completer.
59-
*/
60-
get llmCompleter(): BaseLanguageModel | null {
61-
return this._completer?.provider || null;
38+
return this._aiProvider.completer;
6239
}
6340

6441
async fetch(
6542
request: CompletionHandler.IRequest,
6643
context: IInlineCompletionContext
6744
) {
68-
return this._completer?.fetch(request, context);
45+
return this.completer?.fetch(request, context);
6946
}
7047

71-
private _name: string = 'None';
48+
private _aiProvider: IAIProvider;
7249
private _requestCompletion: () => void;
73-
private _completer: IBaseCompleter | null = null;
7450
}
7551

7652
export namespace CompletionProvider {
77-
export interface IOptions extends BaseCompleter.IOptions {
78-
name: string;
53+
export interface IOptions {
54+
aiProvider: IAIProvider;
7955
requestCompletion: () => void;
8056
}
8157
}

src/index.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { getSettings } from './llm-models';
2222
import { AIProvider } from './provider';
2323
import { renderSlashCommandOption } from './slash-commands';
2424
import { IAIProvider } from './token';
25+
import { CompletionProvider } from './completion-provider';
2526

2627
const autocompletionRegistryPlugin: JupyterFrontEndPlugin<IAutocompletionRegistry> =
2728
{
@@ -129,20 +130,33 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
129130
}
130131
};
131132

133+
const completerPlugin: JupyterFrontEndPlugin<void> = {
134+
id: '@jupyterlite/ai:completer',
135+
autoStart: true,
136+
requires: [IAIProvider, ICompletionProviderManager],
137+
activate: (
138+
app: JupyterFrontEnd,
139+
aiProvider: IAIProvider,
140+
manager: ICompletionProviderManager
141+
): void => {
142+
const completer = new CompletionProvider({
143+
aiProvider,
144+
requestCompletion: () => app.commands.execute('inline-completer:invoke')
145+
});
146+
manager.registerInlineProvider(completer);
147+
}
148+
};
149+
132150
const aiProviderPlugin: JupyterFrontEndPlugin<IAIProvider> = {
133151
id: '@jupyterlite/ai:ai-provider',
134152
autoStart: true,
135-
requires: [ICompletionProviderManager, ISettingRegistry],
153+
requires: [ISettingRegistry],
136154
provides: IAIProvider,
137155
activate: (
138156
app: JupyterFrontEnd,
139-
manager: ICompletionProviderManager,
140157
settingRegistry: ISettingRegistry
141158
): IAIProvider => {
142-
const aiProvider = new AIProvider({
143-
completionProviderManager: manager,
144-
requestCompletion: () => app.commands.execute('inline-completer:invoke')
145-
});
159+
const aiProvider = new AIProvider();
146160

147161
let currentProvider = 'None';
148162
settingRegistry
@@ -172,7 +186,7 @@ const aiProviderPlugin: JupyterFrontEndPlugin<IAIProvider> = {
172186
}
173187

174188
// Update the settings to the AI providers.
175-
aiProvider.setModels(provider, settings.composite);
189+
aiProvider.setProvider(provider, settings.composite);
176190
};
177191

178192
settings.changed.connect(() => updateProvider());
@@ -189,4 +203,9 @@ const aiProviderPlugin: JupyterFrontEndPlugin<IAIProvider> = {
189203
}
190204
};
191205

192-
export default [chatPlugin, autocompletionRegistryPlugin, aiProviderPlugin];
206+
export default [
207+
aiProviderPlugin,
208+
autocompletionRegistryPlugin,
209+
chatPlugin,
210+
completerPlugin
211+
];

src/provider.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { BaseChatModel } from '@langchain/core/language_models/chat_models';
44
import { ISignal, Signal } from '@lumino/signaling';
55
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
66

7-
import { CompletionProvider } from './completion-provider';
8-
import { getChatModel, IBaseCompleter } from './llm-models';
7+
import { getChatModel, getCompleter, IBaseCompleter } from './llm-models';
98
import { IAIProvider } from './token';
109

1110
export const chatSystemPrompt = (options: AIProvider.IPromptOptions) => `
@@ -37,17 +36,9 @@ Do not include the prompt in the output, only the string that should be appended
3736
`;
3837

3938
export class AIProvider implements IAIProvider {
40-
constructor(options: AIProvider.IOptions) {
41-
this._completionProvider = new CompletionProvider({
42-
name: 'None',
43-
settings: {},
44-
requestCompletion: options.requestCompletion
45-
});
46-
options.completionProviderManager.registerInlineProvider(
47-
this._completionProvider
48-
);
49-
}
50-
39+
/**
40+
* Get the provider name.
41+
*/
5142
get name(): string {
5243
return this._name;
5344
}
@@ -59,7 +50,7 @@ export class AIProvider implements IAIProvider {
5950
if (this._name === null) {
6051
return null;
6152
}
62-
return this._completionProvider.completer;
53+
return this._completer;
6354
}
6455

6556
/**
@@ -87,15 +78,15 @@ export class AIProvider implements IAIProvider {
8778
}
8879

8980
/**
90-
* Set the models (chat model and completer).
91-
* Creates the models if the name has changed, otherwise only updates their config.
81+
* Set the provider (chat model and completer).
82+
* Creates the providers if the name has changed, otherwise only updates their config.
9283
*
93-
* @param name - the name of the model to use.
84+
* @param name - the name of the provider to use.
9485
* @param settings - the settings for the models.
9586
*/
96-
setModels(name: string, settings: ReadonlyPartialJSONObject) {
87+
setProvider(name: string, settings: ReadonlyPartialJSONObject) {
9788
try {
98-
this._completionProvider.setCompleter(name, settings);
89+
this._completer = getCompleter(name, settings);
9990
this._completerError = '';
10091
} catch (e: any) {
10192
this._completerError = e.message;
@@ -108,17 +99,17 @@ export class AIProvider implements IAIProvider {
10899
this._llmChatModel = null;
109100
}
110101
this._name = name;
111-
this._modelChange.emit();
102+
this._providerChanged.emit();
112103
}
113104

114-
get modelChange(): ISignal<IAIProvider, void> {
115-
return this._modelChange;
105+
get providerChanged(): ISignal<IAIProvider, void> {
106+
return this._providerChanged;
116107
}
117108

118-
private _completionProvider: CompletionProvider;
109+
private _completer: IBaseCompleter | null = null;
119110
private _llmChatModel: BaseChatModel | null = null;
120111
private _name: string = 'None';
121-
private _modelChange = new Signal<IAIProvider, void>(this);
112+
private _providerChanged = new Signal<IAIProvider, void>(this);
122113
private _chatError: string = '';
123114
private _completerError: string = '';
124115
}

src/token.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface IAIProvider {
88
name: string;
99
completer: IBaseCompleter | null;
1010
chatModel: BaseChatModel | null;
11-
modelChange: ISignal<IAIProvider, void>;
11+
providerChanged: ISignal<IAIProvider, void>;
1212
chatError: string;
1313
completerError: string;
1414
}

0 commit comments

Comments
 (0)