@jupyterlite/ai 0.8.0 → 0.9.0-a0
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/agent.d.ts +233 -0
- package/lib/agent.js +604 -0
- package/lib/chat-model.d.ts +195 -0
- package/lib/chat-model.js +590 -0
- package/lib/completion/completion-provider.d.ts +83 -0
- package/lib/completion/completion-provider.js +209 -0
- package/lib/completion/index.d.ts +1 -0
- package/lib/completion/index.js +1 -0
- package/lib/components/clear-button.d.ts +18 -0
- package/lib/components/clear-button.js +31 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.js +3 -0
- package/lib/components/model-select.d.ts +19 -0
- package/lib/components/model-select.js +154 -0
- package/lib/components/stop-button.d.ts +3 -3
- package/lib/components/stop-button.js +8 -9
- package/lib/components/token-usage-display.d.ts +45 -0
- package/lib/components/token-usage-display.js +74 -0
- package/lib/components/tool-select.d.ts +27 -0
- package/lib/components/tool-select.js +130 -0
- package/lib/icons.d.ts +3 -1
- package/lib/icons.js +10 -13
- package/lib/index.d.ts +4 -5
- package/lib/index.js +322 -167
- package/lib/mcp/browser.d.ts +68 -0
- package/lib/mcp/browser.js +132 -0
- package/lib/models/settings-model.d.ts +69 -0
- package/lib/models/settings-model.js +295 -0
- package/lib/providers/built-in-providers.d.ts +9 -0
- package/lib/providers/built-in-providers.js +192 -0
- package/lib/providers/models.d.ts +37 -0
- package/lib/providers/models.js +28 -0
- package/lib/providers/provider-registry.d.ts +94 -0
- package/lib/providers/provider-registry.js +155 -0
- package/lib/tokens.d.ts +157 -86
- package/lib/tokens.js +16 -12
- package/lib/tools/commands.d.ts +11 -0
- package/lib/tools/commands.js +126 -0
- package/lib/tools/file.d.ts +27 -0
- package/lib/tools/file.js +262 -0
- package/lib/tools/notebook.d.ts +40 -0
- package/lib/tools/notebook.js +762 -0
- package/lib/tools/tool-registry.d.ts +35 -0
- package/lib/tools/tool-registry.js +55 -0
- package/lib/widgets/ai-settings.d.ts +39 -0
- package/lib/widgets/ai-settings.js +506 -0
- package/lib/widgets/chat-wrapper.d.ts +144 -0
- package/lib/widgets/chat-wrapper.js +390 -0
- package/lib/widgets/provider-config-dialog.d.ts +13 -0
- package/lib/widgets/provider-config-dialog.js +104 -0
- package/package.json +150 -41
- package/schema/settings-model.json +153 -0
- package/src/agent.ts +800 -0
- package/src/chat-model.ts +770 -0
- package/src/completion/completion-provider.ts +308 -0
- package/src/completion/index.ts +1 -0
- package/src/components/clear-button.tsx +56 -0
- package/src/components/index.ts +3 -0
- package/src/components/model-select.tsx +245 -0
- package/src/components/stop-button.tsx +11 -11
- package/src/components/token-usage-display.tsx +130 -0
- package/src/components/tool-select.tsx +218 -0
- package/src/icons.ts +12 -14
- package/src/index.ts +468 -238
- package/src/mcp/browser.ts +213 -0
- package/src/models/settings-model.ts +409 -0
- package/src/providers/built-in-providers.ts +216 -0
- package/src/providers/models.ts +79 -0
- package/src/providers/provider-registry.ts +189 -0
- package/src/tokens.ts +203 -90
- package/src/tools/commands.ts +151 -0
- package/src/tools/file.ts +307 -0
- package/src/tools/notebook.ts +964 -0
- package/src/tools/tool-registry.ts +63 -0
- package/src/types.d.ts +4 -0
- package/src/widgets/ai-settings.tsx +1100 -0
- package/src/widgets/chat-wrapper.tsx +543 -0
- package/src/widgets/provider-config-dialog.tsx +256 -0
- package/style/base.css +335 -14
- package/style/icons/jupyternaut-lite.svg +1 -1
- package/lib/base-completer.d.ts +0 -49
- package/lib/base-completer.js +0 -14
- package/lib/chat-handler.d.ts +0 -56
- package/lib/chat-handler.js +0 -201
- package/lib/completion-provider.d.ts +0 -34
- package/lib/completion-provider.js +0 -32
- package/lib/default-prompts.d.ts +0 -2
- package/lib/default-prompts.js +0 -31
- package/lib/default-providers/Anthropic/completer.d.ts +0 -12
- package/lib/default-providers/Anthropic/completer.js +0 -46
- package/lib/default-providers/Anthropic/settings-schema.json +0 -70
- package/lib/default-providers/ChromeAI/completer.d.ts +0 -12
- package/lib/default-providers/ChromeAI/completer.js +0 -56
- package/lib/default-providers/ChromeAI/instructions.d.ts +0 -6
- package/lib/default-providers/ChromeAI/instructions.js +0 -42
- package/lib/default-providers/ChromeAI/settings-schema.json +0 -18
- package/lib/default-providers/Gemini/completer.d.ts +0 -12
- package/lib/default-providers/Gemini/completer.js +0 -48
- package/lib/default-providers/Gemini/instructions.d.ts +0 -2
- package/lib/default-providers/Gemini/instructions.js +0 -9
- package/lib/default-providers/Gemini/settings-schema.json +0 -64
- package/lib/default-providers/MistralAI/completer.d.ts +0 -13
- package/lib/default-providers/MistralAI/completer.js +0 -52
- package/lib/default-providers/MistralAI/instructions.d.ts +0 -2
- package/lib/default-providers/MistralAI/instructions.js +0 -18
- package/lib/default-providers/MistralAI/settings-schema.json +0 -75
- package/lib/default-providers/Ollama/completer.d.ts +0 -12
- package/lib/default-providers/Ollama/completer.js +0 -43
- package/lib/default-providers/Ollama/instructions.d.ts +0 -2
- package/lib/default-providers/Ollama/instructions.js +0 -70
- package/lib/default-providers/Ollama/settings-schema.json +0 -143
- package/lib/default-providers/OpenAI/completer.d.ts +0 -12
- package/lib/default-providers/OpenAI/completer.js +0 -43
- package/lib/default-providers/OpenAI/settings-schema.json +0 -628
- package/lib/default-providers/WebLLM/completer.d.ts +0 -21
- package/lib/default-providers/WebLLM/completer.js +0 -127
- package/lib/default-providers/WebLLM/instructions.d.ts +0 -6
- package/lib/default-providers/WebLLM/instructions.js +0 -32
- package/lib/default-providers/WebLLM/settings-schema.json +0 -19
- package/lib/default-providers/index.d.ts +0 -2
- package/lib/default-providers/index.js +0 -179
- package/lib/provider.d.ts +0 -144
- package/lib/provider.js +0 -412
- package/lib/settings/base.json +0 -7
- package/lib/settings/index.d.ts +0 -3
- package/lib/settings/index.js +0 -3
- package/lib/settings/panel.d.ts +0 -226
- package/lib/settings/panel.js +0 -510
- package/lib/settings/textarea.d.ts +0 -2
- package/lib/settings/textarea.js +0 -18
- package/lib/settings/utils.d.ts +0 -2
- package/lib/settings/utils.js +0 -4
- package/lib/types/ai-model.d.ts +0 -24
- package/lib/types/ai-model.js +0 -5
- package/schema/chat.json +0 -28
- package/schema/provider-registry.json +0 -29
- package/schema/system-prompts.json +0 -22
- package/src/base-completer.ts +0 -75
- package/src/chat-handler.ts +0 -262
- package/src/completion-provider.ts +0 -64
- package/src/default-prompts.ts +0 -33
- package/src/default-providers/Anthropic/completer.ts +0 -59
- package/src/default-providers/ChromeAI/completer.ts +0 -73
- package/src/default-providers/ChromeAI/instructions.ts +0 -45
- package/src/default-providers/Gemini/completer.ts +0 -61
- package/src/default-providers/Gemini/instructions.ts +0 -9
- package/src/default-providers/MistralAI/completer.ts +0 -69
- package/src/default-providers/MistralAI/instructions.ts +0 -18
- package/src/default-providers/Ollama/completer.ts +0 -54
- package/src/default-providers/Ollama/instructions.ts +0 -70
- package/src/default-providers/OpenAI/completer.ts +0 -54
- package/src/default-providers/WebLLM/completer.ts +0 -151
- package/src/default-providers/WebLLM/instructions.ts +0 -33
- package/src/default-providers/index.ts +0 -211
- package/src/global.d.ts +0 -9
- package/src/provider.ts +0 -514
- package/src/settings/index.ts +0 -3
- package/src/settings/panel.tsx +0 -773
- package/src/settings/textarea.tsx +0 -33
- package/src/settings/utils.ts +0 -5
- package/src/types/ai-model.ts +0 -37
- package/src/types/service-worker.d.ts +0 -6
package/src/base-completer.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CompletionHandler,
|
|
3
|
-
IInlineCompletionContext
|
|
4
|
-
} from '@jupyterlab/completer';
|
|
5
|
-
import { BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
6
|
-
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
|
|
7
|
-
|
|
8
|
-
import { DEFAULT_COMPLETION_SYSTEM_PROMPT } from './default-prompts';
|
|
9
|
-
import { IAIProviderRegistry } from './tokens';
|
|
10
|
-
|
|
11
|
-
export interface IBaseCompleter {
|
|
12
|
-
/**
|
|
13
|
-
* The completion prompt.
|
|
14
|
-
*/
|
|
15
|
-
readonly systemPrompt: string;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The function to fetch a new completion.
|
|
19
|
-
*/
|
|
20
|
-
requestCompletion?: () => void;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The fetch request for the LLM completer.
|
|
24
|
-
*/
|
|
25
|
-
fetch(
|
|
26
|
-
request: CompletionHandler.IRequest,
|
|
27
|
-
context: IInlineCompletionContext
|
|
28
|
-
): Promise<any>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export abstract class BaseCompleter implements IBaseCompleter {
|
|
32
|
-
constructor(options: BaseCompleter.IOptions) {
|
|
33
|
-
this._providerRegistry = options.providerRegistry;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get the system prompt for the completion.
|
|
38
|
-
*/
|
|
39
|
-
get systemPrompt(): string {
|
|
40
|
-
return (
|
|
41
|
-
this._providerRegistry.completerSystemPrompt ??
|
|
42
|
-
DEFAULT_COMPLETION_SYSTEM_PROMPT
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* The fetch request for the LLM completer.
|
|
48
|
-
*/
|
|
49
|
-
abstract fetch(
|
|
50
|
-
request: CompletionHandler.IRequest,
|
|
51
|
-
context: IInlineCompletionContext
|
|
52
|
-
): Promise<any>;
|
|
53
|
-
|
|
54
|
-
protected _providerRegistry: IAIProviderRegistry;
|
|
55
|
-
protected abstract _completer: BaseLanguageModel<any, any>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* The namespace for the base completer.
|
|
60
|
-
*/
|
|
61
|
-
export namespace BaseCompleter {
|
|
62
|
-
/**
|
|
63
|
-
* The options for the constructor of a completer.
|
|
64
|
-
*/
|
|
65
|
-
export interface IOptions {
|
|
66
|
-
/**
|
|
67
|
-
* The provider registry.
|
|
68
|
-
*/
|
|
69
|
-
providerRegistry: IAIProviderRegistry;
|
|
70
|
-
/**
|
|
71
|
-
* The settings of the provider.
|
|
72
|
-
*/
|
|
73
|
-
settings: ReadonlyPartialJSONObject;
|
|
74
|
-
}
|
|
75
|
-
}
|
package/src/chat-handler.ts
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) Jupyter Development Team.
|
|
3
|
-
* Distributed under the terms of the Modified BSD License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
ChatCommand,
|
|
8
|
-
AbstractChatContext,
|
|
9
|
-
AbstractChatModel,
|
|
10
|
-
IChatCommandProvider,
|
|
11
|
-
IChatContext,
|
|
12
|
-
IChatHistory,
|
|
13
|
-
IChatMessage,
|
|
14
|
-
IChatModel,
|
|
15
|
-
IInputModel,
|
|
16
|
-
INewMessage
|
|
17
|
-
} from '@jupyter/chat';
|
|
18
|
-
import {
|
|
19
|
-
AIMessage,
|
|
20
|
-
HumanMessage,
|
|
21
|
-
mergeMessageRuns,
|
|
22
|
-
SystemMessage
|
|
23
|
-
} from '@langchain/core/messages';
|
|
24
|
-
import { UUID } from '@lumino/coreutils';
|
|
25
|
-
|
|
26
|
-
import { DEFAULT_CHAT_SYSTEM_PROMPT } from './default-prompts';
|
|
27
|
-
import { jupyternautLiteIcon } from './icons';
|
|
28
|
-
import { IAIProviderRegistry } from './tokens';
|
|
29
|
-
import { AIChatModel } from './types/ai-model';
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The base64 encoded SVG string of the jupyternaut lite icon.
|
|
33
|
-
* Encode so it can be passed as avatar_url to jupyter-chat.
|
|
34
|
-
*/
|
|
35
|
-
const AI_AVATAR_BASE64 = btoa(jupyternautLiteIcon.svgstr);
|
|
36
|
-
const AI_AVATAR = `data:image/svg+xml;base64,${AI_AVATAR_BASE64}`;
|
|
37
|
-
|
|
38
|
-
export const welcomeMessage = (providers: string[]) => `
|
|
39
|
-
#### Ask JupyterLite AI
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
The provider to use can be set in the <button data-commandLinker-command="settingeditor:open" data-commandLinker-args='{"query": "AI provider"}' href="#">settings editor</button>, by selecting it from
|
|
43
|
-
the <img src="${AI_AVATAR}" width="16" height="16"> _AI provider_ settings.
|
|
44
|
-
|
|
45
|
-
The current providers that are available are _${providers.sort().join('_, _')}_.
|
|
46
|
-
|
|
47
|
-
To clear the chat, you can use the \`/clear\` command from the chat input.
|
|
48
|
-
`;
|
|
49
|
-
|
|
50
|
-
export type ConnectionMessage = {
|
|
51
|
-
type: 'connection';
|
|
52
|
-
client_id: string;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export class ChatHandler extends AbstractChatModel {
|
|
56
|
-
constructor(options: ChatHandler.IOptions) {
|
|
57
|
-
super(options);
|
|
58
|
-
this._providerRegistry = options.providerRegistry;
|
|
59
|
-
|
|
60
|
-
this._providerRegistry.providerChanged.connect(() => {
|
|
61
|
-
this._errorMessage = this._providerRegistry.chatError;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
get provider(): AIChatModel | null {
|
|
66
|
-
return this._providerRegistry.currentChatModel;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Getter and setter for the persona name.
|
|
71
|
-
*/
|
|
72
|
-
get personaName(): string {
|
|
73
|
-
return this._personaName;
|
|
74
|
-
}
|
|
75
|
-
set personaName(value: string) {
|
|
76
|
-
this.messages.forEach(message => {
|
|
77
|
-
if (message.sender.username === this._personaName) {
|
|
78
|
-
const updated: IChatMessage = { ...message };
|
|
79
|
-
updated.sender.username = value;
|
|
80
|
-
this.messageAdded(updated);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
this._personaName = value;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Get/set the system prompt for the chat.
|
|
88
|
-
*/
|
|
89
|
-
get systemPrompt(): string {
|
|
90
|
-
return (
|
|
91
|
-
this._providerRegistry.chatSystemPrompt ?? DEFAULT_CHAT_SYSTEM_PROMPT
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async sendMessage(message: INewMessage): Promise<boolean> {
|
|
96
|
-
const body = message.body;
|
|
97
|
-
if (body.startsWith('/clear')) {
|
|
98
|
-
// TODO: do we need a clear method?
|
|
99
|
-
this.messagesDeleted(0, this.messages.length);
|
|
100
|
-
this._history.messages = [];
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
message.id = UUID.uuid4();
|
|
104
|
-
const msg: IChatMessage = {
|
|
105
|
-
id: message.id,
|
|
106
|
-
body,
|
|
107
|
-
sender: { username: 'User' },
|
|
108
|
-
time: Private.getTimestampMs(),
|
|
109
|
-
type: 'msg'
|
|
110
|
-
};
|
|
111
|
-
this.messageAdded(msg);
|
|
112
|
-
|
|
113
|
-
if (this._providerRegistry.currentChatModel === null) {
|
|
114
|
-
const errorMsg: IChatMessage = {
|
|
115
|
-
id: UUID.uuid4(),
|
|
116
|
-
body: `**${this._errorMessage ? this._errorMessage : this._defaultErrorMessage}**`,
|
|
117
|
-
sender: { username: 'ERROR' },
|
|
118
|
-
time: Private.getTimestampMs(),
|
|
119
|
-
type: 'msg'
|
|
120
|
-
};
|
|
121
|
-
this.messageAdded(errorMsg);
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this._history.messages.push(msg);
|
|
126
|
-
|
|
127
|
-
const messages = mergeMessageRuns([new SystemMessage(this.systemPrompt)]);
|
|
128
|
-
messages.push(
|
|
129
|
-
...this._history.messages.map(msg => {
|
|
130
|
-
if (msg.sender.username === 'User') {
|
|
131
|
-
return new HumanMessage(msg.body);
|
|
132
|
-
}
|
|
133
|
-
return new AIMessage(msg.body);
|
|
134
|
-
})
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const sender = { username: this._personaName, avatar_url: AI_AVATAR };
|
|
138
|
-
this.updateWriters([{ user: sender }]);
|
|
139
|
-
|
|
140
|
-
// create an empty message to be filled by the AI provider
|
|
141
|
-
const botMsg: IChatMessage = {
|
|
142
|
-
id: UUID.uuid4(),
|
|
143
|
-
body: '',
|
|
144
|
-
sender,
|
|
145
|
-
time: Private.getTimestampMs(),
|
|
146
|
-
type: 'msg'
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
let content = '';
|
|
150
|
-
|
|
151
|
-
this._controller = new AbortController();
|
|
152
|
-
try {
|
|
153
|
-
for await (const chunk of await this._providerRegistry.currentChatModel.stream(
|
|
154
|
-
messages,
|
|
155
|
-
{ signal: this._controller.signal }
|
|
156
|
-
)) {
|
|
157
|
-
content += chunk.content ?? chunk;
|
|
158
|
-
botMsg.body = content;
|
|
159
|
-
this.messageAdded(botMsg);
|
|
160
|
-
}
|
|
161
|
-
this._history.messages.push(botMsg);
|
|
162
|
-
return true;
|
|
163
|
-
} catch (reason) {
|
|
164
|
-
const error = this._providerRegistry.formatErrorMessage(reason);
|
|
165
|
-
const errorMsg: IChatMessage = {
|
|
166
|
-
id: UUID.uuid4(),
|
|
167
|
-
body: `**${error}**`,
|
|
168
|
-
sender: { username: 'ERROR' },
|
|
169
|
-
time: Private.getTimestampMs(),
|
|
170
|
-
type: 'msg'
|
|
171
|
-
};
|
|
172
|
-
this.messageAdded(errorMsg);
|
|
173
|
-
return false;
|
|
174
|
-
} finally {
|
|
175
|
-
this.updateWriters([]);
|
|
176
|
-
this._controller = null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async getHistory(): Promise<IChatHistory> {
|
|
181
|
-
return this._history;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
dispose(): void {
|
|
185
|
-
super.dispose();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
messageAdded(message: IChatMessage): void {
|
|
189
|
-
super.messageAdded(message);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
stopStreaming(): void {
|
|
193
|
-
this._controller?.abort();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
createChatContext(): IChatContext {
|
|
197
|
-
return new ChatHandler.ChatContext({ model: this });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
private _providerRegistry: IAIProviderRegistry;
|
|
201
|
-
private _personaName = 'AI';
|
|
202
|
-
private _errorMessage: string = '';
|
|
203
|
-
private _history: IChatHistory = { messages: [] };
|
|
204
|
-
private _defaultErrorMessage = 'AI provider not configured';
|
|
205
|
-
private _controller: AbortController | null = null;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export namespace ChatHandler {
|
|
209
|
-
/**
|
|
210
|
-
* The options used to create a chat handler.
|
|
211
|
-
*/
|
|
212
|
-
export interface IOptions extends IChatModel.IOptions {
|
|
213
|
-
providerRegistry: IAIProviderRegistry;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* The minimal chat context.
|
|
218
|
-
*/
|
|
219
|
-
export class ChatContext extends AbstractChatContext {
|
|
220
|
-
users = [];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* The chat command provider for the chat.
|
|
225
|
-
*/
|
|
226
|
-
export class ClearCommandProvider implements IChatCommandProvider {
|
|
227
|
-
public id: string = '@jupyterlite/ai:clear-commands';
|
|
228
|
-
private _slash_commands: ChatCommand[] = [
|
|
229
|
-
{
|
|
230
|
-
name: '/clear',
|
|
231
|
-
providerId: this.id,
|
|
232
|
-
replaceWith: '/clear',
|
|
233
|
-
description: 'Clear the chat'
|
|
234
|
-
}
|
|
235
|
-
];
|
|
236
|
-
async listCommandCompletions(inputModel: IInputModel) {
|
|
237
|
-
const match = inputModel.currentWord?.match(/^\/\w*/)?.[0];
|
|
238
|
-
if (!match) {
|
|
239
|
-
return [];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const commands = this._slash_commands.filter(cmd =>
|
|
243
|
-
cmd.name.startsWith(match)
|
|
244
|
-
);
|
|
245
|
-
return commands;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
async onSubmit(inputModel: IInputModel): Promise<void> {
|
|
249
|
-
// no handling needed because `replaceWith` is set in each command.
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
namespace Private {
|
|
256
|
-
/**
|
|
257
|
-
* Return the current timestamp in milliseconds.
|
|
258
|
-
*/
|
|
259
|
-
export function getTimestampMs(): number {
|
|
260
|
-
return Date.now() / 1000;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CompletionHandler,
|
|
3
|
-
IInlineCompletionContext,
|
|
4
|
-
IInlineCompletionProvider
|
|
5
|
-
} from '@jupyterlab/completer';
|
|
6
|
-
|
|
7
|
-
import { IAIProviderRegistry } from './tokens';
|
|
8
|
-
import { AICompleter } from './types/ai-model';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* The generic completion provider to register to the completion provider manager.
|
|
12
|
-
*/
|
|
13
|
-
export class CompletionProvider implements IInlineCompletionProvider {
|
|
14
|
-
readonly identifier = '@jupyterlite/ai';
|
|
15
|
-
|
|
16
|
-
constructor(options: CompletionProvider.IOptions) {
|
|
17
|
-
this._providerRegistry = options.providerRegistry;
|
|
18
|
-
this._requestCompletion = options.requestCompletion;
|
|
19
|
-
|
|
20
|
-
this._providerRegistry.providerChanged.connect(() => {
|
|
21
|
-
if (this.completer) {
|
|
22
|
-
this.completer.requestCompletion = this._requestCompletion;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Get the current completer name.
|
|
29
|
-
*/
|
|
30
|
-
get name(): string {
|
|
31
|
-
return this._providerRegistry.currentName('completer');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get the current completer.
|
|
36
|
-
*/
|
|
37
|
-
get completer(): AICompleter | null {
|
|
38
|
-
return this._providerRegistry.currentCompleter;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async fetch(
|
|
42
|
-
request: CompletionHandler.IRequest,
|
|
43
|
-
context: IInlineCompletionContext
|
|
44
|
-
) {
|
|
45
|
-
return this.completer?.fetch(request, context);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private _providerRegistry: IAIProviderRegistry;
|
|
49
|
-
private _requestCompletion: () => void;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export namespace CompletionProvider {
|
|
53
|
-
export interface IOptions {
|
|
54
|
-
/**
|
|
55
|
-
* The registry where the completion provider belongs.
|
|
56
|
-
*/
|
|
57
|
-
providerRegistry: IAIProviderRegistry;
|
|
58
|
-
/**
|
|
59
|
-
* The request completion commands, can be useful if a provider needs to request
|
|
60
|
-
* the completion by itself.
|
|
61
|
-
*/
|
|
62
|
-
requestCompletion: () => void;
|
|
63
|
-
}
|
|
64
|
-
}
|
package/src/default-prompts.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) Jupyter Development Team.
|
|
3
|
-
* Distributed under the terms of the Modified BSD License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const DEFAULT_CHAT_SYSTEM_PROMPT = `
|
|
7
|
-
You are Jupyternaut, a conversational assistant living in JupyterLab to help users.
|
|
8
|
-
You are not a language model, but rather an application built on a foundation model from $provider_name$.
|
|
9
|
-
You are talkative and you provide lots of specific details from the foundation model's context.
|
|
10
|
-
You may use Markdown to format your response.
|
|
11
|
-
If your response includes code, they must be enclosed in Markdown fenced code blocks (with triple backticks before and after).
|
|
12
|
-
If your response includes mathematical notation, they must be expressed in LaTeX markup and enclosed in LaTeX delimiters.
|
|
13
|
-
All dollar quantities (of USD) must be formatted in LaTeX, with the \`$\` symbol escaped by a single backslash \`\\\`.
|
|
14
|
-
- Example prompt: \`If I have \\\\$100 and spend \\\\$20, how much money do I have left?\`
|
|
15
|
-
- **Correct** response: \`You have \\(\\$80\\) remaining.\`
|
|
16
|
-
- **Incorrect** response: \`You have $80 remaining.\`
|
|
17
|
-
If you do not know the answer to a question, answer truthfully by responding that you do not know.
|
|
18
|
-
The following is a friendly conversation between you and a human.
|
|
19
|
-
`;
|
|
20
|
-
|
|
21
|
-
export const DEFAULT_COMPLETION_SYSTEM_PROMPT = `
|
|
22
|
-
You are an application built to provide helpful code completion suggestions.
|
|
23
|
-
You should only produce code. Keep comments to minimum, use the
|
|
24
|
-
programming language comment syntax. Produce clean code.
|
|
25
|
-
The code is written in JupyterLab, a data analysis and code development
|
|
26
|
-
environment which can execute code extended with additional syntax for
|
|
27
|
-
interactive features, such as magics.
|
|
28
|
-
Only give raw strings back, do not format the response using backticks.
|
|
29
|
-
The output should be a single string, and should only contain the code that will complete the
|
|
30
|
-
give code passed as input, no explanation whatsoever.
|
|
31
|
-
Do not include the prompt in the output, only the string that should be appended to the current input.
|
|
32
|
-
Here is the code to complete:
|
|
33
|
-
`;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CompletionHandler,
|
|
3
|
-
IInlineCompletionContext
|
|
4
|
-
} from '@jupyterlab/completer';
|
|
5
|
-
import { ChatAnthropic } from '@langchain/anthropic';
|
|
6
|
-
import { AIMessage, SystemMessage } from '@langchain/core/messages';
|
|
7
|
-
|
|
8
|
-
import { BaseCompleter } from '../../base-completer';
|
|
9
|
-
|
|
10
|
-
export class AnthropicCompleter extends BaseCompleter {
|
|
11
|
-
constructor(options: BaseCompleter.IOptions) {
|
|
12
|
-
super(options);
|
|
13
|
-
this._completer = new ChatAnthropic({ ...options.settings });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async fetch(
|
|
17
|
-
request: CompletionHandler.IRequest,
|
|
18
|
-
context: IInlineCompletionContext
|
|
19
|
-
) {
|
|
20
|
-
const { text, offset: cursorOffset } = request;
|
|
21
|
-
const prompt = text.slice(0, cursorOffset);
|
|
22
|
-
|
|
23
|
-
// Anthropic does not allow whitespace at the end of the AIMessage
|
|
24
|
-
const trimmedPrompt = prompt.trim();
|
|
25
|
-
|
|
26
|
-
const messages = [
|
|
27
|
-
new SystemMessage(this.systemPrompt),
|
|
28
|
-
new AIMessage(trimmedPrompt)
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const response = await this._completer.invoke(messages);
|
|
33
|
-
const items = [];
|
|
34
|
-
|
|
35
|
-
// Anthropic can return string or complex content, a list of string/images/other.
|
|
36
|
-
if (typeof response.content === 'string') {
|
|
37
|
-
items.push({
|
|
38
|
-
insertText: response.content
|
|
39
|
-
});
|
|
40
|
-
} else {
|
|
41
|
-
response.content.forEach(content => {
|
|
42
|
-
if (content.type !== 'text') {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
items.push({
|
|
46
|
-
insertText: content.text,
|
|
47
|
-
filterText: prompt.substring(trimmedPrompt.length)
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return { items };
|
|
52
|
-
} catch (error) {
|
|
53
|
-
console.error('Error fetching completions', error);
|
|
54
|
-
return { items: [] };
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
protected _completer: ChatAnthropic;
|
|
59
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CompletionHandler,
|
|
3
|
-
IInlineCompletionContext
|
|
4
|
-
} from '@jupyterlab/completer';
|
|
5
|
-
import { ChromeAI } from '@langchain/community/experimental/llms/chrome_ai';
|
|
6
|
-
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
7
|
-
|
|
8
|
-
import { BaseCompleter } from '../../base-completer';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Regular expression to match the '```' string at the start of a string.
|
|
12
|
-
* So the completions returned by the LLM can still be kept after removing the code block formatting.
|
|
13
|
-
*
|
|
14
|
-
* For example, if the response contains the following content after typing `import pandas`:
|
|
15
|
-
*
|
|
16
|
-
* ```python
|
|
17
|
-
* as pd
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* The formatting string after removing the code block delimiters will be:
|
|
21
|
-
*
|
|
22
|
-
* as pd
|
|
23
|
-
*/
|
|
24
|
-
const CODE_BLOCK_START_REGEX = /^```(?:[a-zA-Z]+)?\n?/;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Regular expression to match the '```' string at the end of a string.
|
|
28
|
-
*/
|
|
29
|
-
const CODE_BLOCK_END_REGEX = /```$/;
|
|
30
|
-
|
|
31
|
-
export class ChromeCompleter extends BaseCompleter {
|
|
32
|
-
constructor(options: BaseCompleter.IOptions) {
|
|
33
|
-
super(options);
|
|
34
|
-
this._completer = new ChromeAI({ ...options.settings });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async fetch(
|
|
38
|
-
request: CompletionHandler.IRequest,
|
|
39
|
-
context: IInlineCompletionContext
|
|
40
|
-
) {
|
|
41
|
-
const { text, offset: cursorOffset } = request;
|
|
42
|
-
const prompt = text.slice(0, cursorOffset);
|
|
43
|
-
|
|
44
|
-
const trimmedPrompt = prompt.trim();
|
|
45
|
-
|
|
46
|
-
const messages = [
|
|
47
|
-
new SystemMessage(this.systemPrompt),
|
|
48
|
-
new HumanMessage(trimmedPrompt)
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
let response = await this._completer.invoke(messages);
|
|
53
|
-
|
|
54
|
-
// ChromeAI sometimes returns a string starting with '```',
|
|
55
|
-
// so process the response to remove the code block delimiters
|
|
56
|
-
if (CODE_BLOCK_START_REGEX.test(response)) {
|
|
57
|
-
response = response
|
|
58
|
-
.replace(CODE_BLOCK_START_REGEX, '')
|
|
59
|
-
.replace(CODE_BLOCK_END_REGEX, '');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const items = [{ insertText: response }];
|
|
63
|
-
return {
|
|
64
|
-
items
|
|
65
|
-
};
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.error('Error fetching completion:', error);
|
|
68
|
-
return { items: [] };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
protected _completer: ChromeAI;
|
|
73
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export default `
|
|
2
|
-
<i class="fas fa-exclamation-triangle"></i> Support for ChromeAI is still experimental and only available in Google Chrome.
|
|
3
|
-
|
|
4
|
-
You can test ChromeAI is enabled in your browser by going to the following URL: <https://chromeai.org/>
|
|
5
|
-
|
|
6
|
-
Enable the proper flags in Google Chrome.
|
|
7
|
-
|
|
8
|
-
- chrome://flags/#prompt-api-for-gemini-nano
|
|
9
|
-
- Select: \`Enabled\`
|
|
10
|
-
- chrome://flags/#optimization-guide-on-device-model
|
|
11
|
-
- Select: \`Enabled BypassPrefRequirement\`
|
|
12
|
-
- chrome://components
|
|
13
|
-
- Click \`Check for Update\` on Optimization Guide On Device Model to download the model
|
|
14
|
-
- [Optional] chrome://flags/#text-safety-classifier
|
|
15
|
-
|
|
16
|
-
<img src="https://github.com/user-attachments/assets/d48f46cc-52ee-4ce5-9eaf-c763cdbee04c" alt="A screenshot showing how to enable the ChromeAI flag in Google Chrome" width="500px">
|
|
17
|
-
|
|
18
|
-
Then restart Chrome for these changes to take effect.
|
|
19
|
-
|
|
20
|
-
<i class="fas fa-exclamation-triangle"></i> On first use, Chrome will download the on-device model, which can be as large as 22GB (according to their docs and at the time of writing).
|
|
21
|
-
During the download, ChromeAI may not be available via the extension.
|
|
22
|
-
|
|
23
|
-
<i class="fa fa-info-circle" aria-hidden="true"></i> For more information about Chrome Built-in AI: <https://developer.chrome.com/docs/ai/get-started>
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Check if the browser supports ChromeAI and the model is available.
|
|
28
|
-
*/
|
|
29
|
-
export async function compatibilityCheck(): Promise<string | null> {
|
|
30
|
-
// Check if the browser supports the ChromeAI model
|
|
31
|
-
if (
|
|
32
|
-
typeof window === 'undefined' ||
|
|
33
|
-
!('LanguageModel' in window) ||
|
|
34
|
-
window.LanguageModel === undefined ||
|
|
35
|
-
(window.LanguageModel as any).availability === undefined
|
|
36
|
-
) {
|
|
37
|
-
return 'Your browser does not support ChromeAI. Please use an updated chrome based browser like Google Chrome, and follow the instructions in settings to enable it.';
|
|
38
|
-
}
|
|
39
|
-
const languageModel = window.LanguageModel as any;
|
|
40
|
-
if (!(await languageModel.availability())) {
|
|
41
|
-
return 'The ChromeAI model is not available in your browser. Please ensure you have enabled the necessary flags in Google Chrome as described in the instructions in settings.';
|
|
42
|
-
}
|
|
43
|
-
// If the model is available, return null to indicate compatibility
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CompletionHandler,
|
|
3
|
-
IInlineCompletionContext
|
|
4
|
-
} from '@jupyterlab/completer';
|
|
5
|
-
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
|
|
6
|
-
import { AIMessage, SystemMessage } from '@langchain/core/messages';
|
|
7
|
-
|
|
8
|
-
import { BaseCompleter } from '../../base-completer';
|
|
9
|
-
|
|
10
|
-
export class GeminiCompleter extends BaseCompleter {
|
|
11
|
-
constructor(options: BaseCompleter.IOptions) {
|
|
12
|
-
super(options);
|
|
13
|
-
this._completer = new ChatGoogleGenerativeAI({
|
|
14
|
-
model: 'gemini-pro',
|
|
15
|
-
...options.settings
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async fetch(
|
|
20
|
-
request: CompletionHandler.IRequest,
|
|
21
|
-
context: IInlineCompletionContext
|
|
22
|
-
) {
|
|
23
|
-
const { text, offset: cursorOffset } = request;
|
|
24
|
-
const prompt = text.slice(0, cursorOffset);
|
|
25
|
-
|
|
26
|
-
const trimmedPrompt = prompt.trim();
|
|
27
|
-
|
|
28
|
-
const messages = [
|
|
29
|
-
new SystemMessage(this.systemPrompt),
|
|
30
|
-
new AIMessage(trimmedPrompt)
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
const response = await this._completer.invoke(messages);
|
|
35
|
-
const items = [];
|
|
36
|
-
|
|
37
|
-
// Gemini can return string or complex content, a list of string/images/other.
|
|
38
|
-
if (typeof response.content === 'string') {
|
|
39
|
-
items.push({
|
|
40
|
-
insertText: response.content
|
|
41
|
-
});
|
|
42
|
-
} else {
|
|
43
|
-
response.content.forEach(content => {
|
|
44
|
-
if (content.type !== 'text') {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
items.push({
|
|
48
|
-
insertText: content.text,
|
|
49
|
-
filterText: prompt.substring(trimmedPrompt.length)
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return { items };
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error('Error fetching completions', error);
|
|
56
|
-
return { items: [] };
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
protected _completer: ChatGoogleGenerativeAI;
|
|
61
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export default `
|
|
2
|
-
<i class="fas fa-exclamation-triangle"></i> This extension is still very much experimental. It is not an official Google extension.
|
|
3
|
-
|
|
4
|
-
1. Go to <https://aistudio.google.com> and create an API key.
|
|
5
|
-
|
|
6
|
-
2. Open the JupyterLab settings and go to the **Ai providers** section to select the \`Gemini\`
|
|
7
|
-
provider and add your API key (required).
|
|
8
|
-
3. Open the chat, or use the inline completer.
|
|
9
|
-
`;
|