Skip to content

Commit 9826a7b

Browse files
authored
Improve Mistral completions (#85)
* Improve Mistral completions * prepend system prompt * add note about supported models in the instructions
1 parent c64ad86 commit 9826a7b

File tree

2 files changed

+33
-47
lines changed

2 files changed

+33
-47
lines changed

src/default-providers/MistralAI/completer.ts

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,70 +2,54 @@ import {
22
CompletionHandler,
33
IInlineCompletionContext
44
} from '@jupyterlab/completer';
5-
import {
6-
BaseMessage,
7-
HumanMessage,
8-
SystemMessage
9-
} from '@langchain/core/messages';
10-
import { ChatMistralAI } from '@langchain/mistralai';
11-
import { Throttler } from '@lumino/polling';
5+
import { MistralAI } from '@langchain/mistralai';
126

137
import { BaseCompleter } from '../../base-completer';
148

15-
/**
16-
* The Mistral API has a rate limit of 1 request per second
17-
*/
18-
const INTERVAL = 1000;
9+
const CODE_BLOCK_START_REGEX = /^```(?:[a-zA-Z]+)?\n?/;
10+
const CODE_BLOCK_END_REGEX = /```$/;
1911

2012
export class CodestralCompleter extends BaseCompleter {
2113
constructor(options: BaseCompleter.IOptions) {
2214
super(options);
23-
this._completer = new ChatMistralAI({ ...options.settings });
24-
this._throttler = new Throttler(
25-
async (messages: BaseMessage[]) => {
26-
const response = await this._completer.invoke(messages);
27-
// Extract results of completion request.
28-
const items = [];
29-
if (typeof response.content === 'string') {
30-
items.push({
31-
insertText: response.content
32-
});
33-
} else {
34-
response.content.forEach(content => {
35-
if (content.type !== 'text') {
36-
return;
37-
}
38-
items.push({
39-
insertText: content.text
40-
});
41-
});
42-
}
43-
return { items };
44-
},
45-
{ limit: INTERVAL }
46-
);
15+
this._completer = new MistralAI({ ...options.settings });
4716
}
4817

4918
async fetch(
5019
request: CompletionHandler.IRequest,
5120
context: IInlineCompletionContext
5221
) {
53-
const { text, offset: cursorOffset } = request;
54-
const prompt = text.slice(0, cursorOffset);
55-
56-
const messages: BaseMessage[] = [
57-
new SystemMessage(this.systemPrompt),
58-
new HumanMessage(prompt)
59-
];
60-
6122
try {
62-
return await this._throttler.invoke(messages);
23+
const { text, offset: cursorOffset } = request;
24+
const prompt = this.systemPrompt.concat(text.slice(0, cursorOffset));
25+
const suffix = text.slice(cursorOffset);
26+
this._controller.abort();
27+
this._controller = new AbortController();
28+
29+
const response = await this._completer.completionWithRetry(
30+
{
31+
prompt,
32+
model: this._completer.model,
33+
suffix
34+
},
35+
{ signal: this._controller.signal },
36+
false
37+
);
38+
const items = response.choices.map(choice => {
39+
const content = choice.message.content
40+
.replace(CODE_BLOCK_START_REGEX, '')
41+
.replace(CODE_BLOCK_END_REGEX, '');
42+
return {
43+
insertText: content
44+
};
45+
});
46+
return { items };
6347
} catch (error) {
64-
console.error('Error fetching completions', error);
48+
// the request may be aborted
6549
return { items: [] };
6650
}
6751
}
6852

69-
private _throttler: Throttler;
70-
protected _completer: ChatMistralAI;
53+
private _controller = new AbortController();
54+
protected _completer: MistralAI;
7155
}

src/default-providers/MistralAI/instructions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export default `
1010
1111
<img src="https://raw.githubusercontent.com/jupyterlite/ai/refs/heads/main/img/2-jupyterlab-settings.png" alt="Screenshot showing how to add the API key to the settings" width="500px">
1212
13+
**Note:** When using MistralAI for completions, only a subset of models are available. Please check [this resource](https://docs.mistral.ai/api/#tag/fim) to see the list of supported models for completions.
14+
1315
3. Open the chat, or use the inline completer
1416
1517
<img src="https://raw.githubusercontent.com/jupyterlite/ai/refs/heads/main/img/3-usage.png" alt="Screenshot showing how to use the chat" width="500px">

0 commit comments

Comments
 (0)