webllm
This commit is contained in:
parent
ee66e9fdfa
commit
724bcd8572
8 changed files with 237 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,3 +7,4 @@ bribes
|
||||||
site/
|
site/
|
||||||
.obsidian
|
.obsidian
|
||||||
.task/
|
.task/
|
||||||
|
webllm/node_modules/
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,51 @@ Use a recent Chrome/Edge (≥ 113) or Safari 18+ (chrome://flags/#enable-unsafe-
|
||||||
|
|
||||||
## install webllm
|
## install webllm
|
||||||
|
|
||||||
|
|
||||||
[Suivre l'install](https://github.com/mlc-ai/web-llm) dans le readme.
|
[Suivre l'install](https://github.com/mlc-ai/web-llm) dans le readme.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install -y nodejs npm
|
||||||
|
|
||||||
|
npm install @mlc-ai/web-llm
|
||||||
|
|
||||||
|
python -m"http.server" 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
ou bien, lancer le serveur nodejs :
|
||||||
|
```
|
||||||
|
npm install -g serve
|
||||||
|
serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### usage
|
||||||
|
|
||||||
|
La méthode principale : le System Prompt. Exemple de script:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
import { CreateMLCEngine } from "@mlc-ai/web-llm";
|
||||||
|
|
||||||
|
// 1. Définir la persona (comme votre instruction SYSTEM dans Ollama)
|
||||||
|
const systemPrompt = "Tu es un assistant culinaire expert, spécialisé dans la cuisine française. Tu réponds toujours avec enthousiasme et proposes des alternatives aux ingrédients difficiles à trouver. Tu ne parles jamais de sujets hors de la cuisine.";
|
||||||
|
|
||||||
|
const messages = [
|
||||||
|
// 2. Le message système définit le comportement pour toute la conversation
|
||||||
|
{ role: "system", content: systemPrompt },
|
||||||
|
{ role: "user", content: "Comment faire une bonne quiche lorraine ?" }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 3. Envoyer la requête
|
||||||
|
const engine = await CreateMLCEngine("Llama-3.1-8B-Instruct-q4f32_1-MLC");
|
||||||
|
const reply = await engine.chat.completions.create({ messages });
|
||||||
|
|
||||||
|
console.log(reply.choices[0].message.content);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- Aller dans le dossier `webllm` et lancer un serveur type `python -m"http.server"`
|
||||||
|
dans ce dossier.
|
||||||
|
- Utiliser un browser compatible (j'ai utilisé un-googled-chromium),
|
||||||
|
le résultat du chat apparaît dans la console.
|
||||||
|
|
||||||
## install the python mlc local chat utility
|
## install the python mlc local chat utility
|
||||||
|
|
||||||
|
|
|
||||||
14
webllm/index.html
Normal file
14
webllm/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Test WebLLM</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Test de WebLLM</h1>
|
||||||
|
<div id="output"></div>
|
||||||
|
|
||||||
|
<!-- Lier votre script JavaScript -->
|
||||||
|
<script type="module" src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
55
webllm/index.js
Normal file
55
webllm/index.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// import { CreateMLCEngine } from "@mlc-ai/web-llm";
|
||||||
|
|
||||||
|
import { CreateMLCEngine } from "./node_modules/@mlc-ai/web-llm/lib/index.js";
|
||||||
|
|
||||||
|
|
||||||
|
// Callback function to update model loading progress
|
||||||
|
const initProgressCallback = (initProgress) => {
|
||||||
|
console.log(initProgress);
|
||||||
|
};
|
||||||
|
const selectedModel = "Llama-3.1-8B-Instruct-q4f32_1-MLC";
|
||||||
|
|
||||||
|
const engine = await CreateMLCEngine(
|
||||||
|
selectedModel,
|
||||||
|
{ initProgressCallback: initProgressCallback }, // engineConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
// chat
|
||||||
|
|
||||||
|
const messages = [
|
||||||
|
{ role: "system", content: "You are a helpful AI assistant." },
|
||||||
|
{ role: "user", content: "Hello!" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 1. Définir la persona (comme votre instruction SYSTEM dans Ollama)
|
||||||
|
//const systemPrompt = "Tu es un assistant culinaire expert, spécialisé dans la cuisine française. Tu réponds toujours avec enthousiasme et proposes des alternatives aux ingrédients difficiles à trouver. Tu ne parles jamais de sujets hors de la cuisine.";
|
||||||
|
|
||||||
|
//const messages = [
|
||||||
|
// // 2. Le message système définit le comportement pour toute la conversation
|
||||||
|
// { role: "system", content: systemPrompt },
|
||||||
|
// { role: "user", content: "Comment faire une bonne quiche lorraine ?" }
|
||||||
|
//];
|
||||||
|
|
||||||
|
//import { loadPersona } from './personaLoader.js';
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
// Chunks is an AsyncGenerator object
|
||||||
|
const chunks = await engine.chat.completions.create({
|
||||||
|
messages,
|
||||||
|
temperature: 0
|
||||||
|
// stream: true, // <-- Enable streaming
|
||||||
|
// stream_options: { include_usage: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
let reply = "";
|
||||||
|
for await (const chunk of chunks) {
|
||||||
|
reply += chunk.choices[0]?.delta.content || "";
|
||||||
|
console.log(reply);
|
||||||
|
if (chunk.usage) {
|
||||||
|
console.log(chunk.usage); // only last chunk has usage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullReply = await engine.getMessage();
|
||||||
|
console.log(fullReply);
|
||||||
28
webllm/index.js.1
Normal file
28
webllm/index.js.1
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// import { CreateMLCEngine } from "@mlc-ai/web-llm";
|
||||||
|
|
||||||
|
import { CreateMLCEngine } from "./node_modules/@mlc-ai/web-llm/lib/index.js";
|
||||||
|
|
||||||
|
|
||||||
|
// Callback function to update model loading progress
|
||||||
|
const initProgressCallback = (initProgress) => {
|
||||||
|
console.log(initProgress);
|
||||||
|
};
|
||||||
|
const selectedModel = "Llama-3.1-8B-Instruct-q4f32_1-MLC";
|
||||||
|
|
||||||
|
const engine = await CreateMLCEngine(
|
||||||
|
selectedModel,
|
||||||
|
{ initProgressCallback: initProgressCallback }, // engineConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
// chat
|
||||||
|
|
||||||
|
const messages = [
|
||||||
|
{ role: "system", content: "You are a helpful AI assistant." },
|
||||||
|
{ role: "user", content: "Hello!" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const reply = await engine.chat.completions.create({
|
||||||
|
messages,
|
||||||
|
});
|
||||||
|
console.log(reply.choices[0].message);
|
||||||
|
console.log(reply.usage);
|
||||||
5
webllm/package.json
Normal file
5
webllm/package.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@mlc-ai/web-llm": "^0.2.85"
|
||||||
|
}
|
||||||
|
}
|
||||||
75
webllm/persona.txt
Normal file
75
webllm/persona.txt
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
Provided this markdown documentation:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| Variable | Description |
|
||||||
|
|------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| **<a id="proxy_mode" name="proxy_mode">proxy_mode</a>**<br/>[`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | Configure Proxy Access to the Internet.<br/>**Choices**: <br/>• No proxy **← (default)**<br/>• Auto-detect proxy settings for this network<br/>• Use system proxy settings<br/>• Manual proxy configuration<br/>• Automatic proxy configuration URL |
|
||||||
|
|
||||||
|
# Manual proxy configuration
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> **Path**: manual\
|
||||||
|
> *`disabled`*\
|
||||||
|
> **Disabled**: when the variable "[Configure Proxy Access to the Internet](#proxy_mode)" hasn't the value "Manual proxy configuration".
|
||||||
|
|
||||||
|
## HTTP Proxy
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> **Path**: manual.http_proxy
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| **<a id="manual.http_proxy.address" name="manual.http_proxy.address">manual.http_proxy.address</a>**<br/>[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTP proxy address.<br/>**Validators**: <br/>• type domainname<br/>• the domain name can be an IP |
|
||||||
|
| **<a id="manual.http_proxy.port" name="manual.http_proxy.port">manual.http_proxy.port</a>**<br/>[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTP proxy port.<br/>**Validators**: <br/>• well-known ports (1 to 1023) are allowed<br/>• registred ports (1024 to 49151) are allowed<br/>• private ports (greater than 49152) are allowed<br/>**Default**: 8080 |
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
|
||||||
|
| **<a id="manual.use_for_https" name="manual.use_for_https">manual.use_for_https</a>**<br/>[`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | Also use this proxy for HTTPS.<br/>**Default**: true |
|
||||||
|
|
||||||
|
## HTTPS Proxy
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> **Path**: manual.https_proxy\
|
||||||
|
> *`hidden`*\
|
||||||
|
> **Hidden**: when the variable "[Also use this proxy for HTTPS](#manual.use_for_https)" has the value "true".
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| **<a id="manual.https_proxy.address" name="manual.https_proxy.address">manual.https_proxy.address</a>**<br/>[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTPS proxy address.<br/>**Validators**: <br/>• type domainname<br/>• the domain name can be an IP<br/>**Default**: the value of the variable "[HTTP proxy address](#manual.http_proxy.address)". |
|
||||||
|
| **<a id="manual.https_proxy.port" name="manual.https_proxy.port">manual.https_proxy.port</a>**<br/>[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTPS proxy port.<br/>**Validators**: <br/>• well-known ports (1 to 1023) are allowed<br/>• registred ports (1024 to 49151) are allowed<br/>• private ports (greater than 49152) are allowed<br/>**Default**: the value of the variable "[HTTP proxy port](#manual.http_proxy.port)". |
|
||||||
|
|
||||||
|
## SOCKS Proxy
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> **Path**: manual.socks_proxy
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| **<a id="manual.socks_proxy.address" name="manual.socks_proxy.address">manual.socks_proxy.address</a>**<br/>[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | SOCKS proxy address.<br/>**Validators**: <br/>• type domainname<br/>• the domain name can be an IP |
|
||||||
|
| **<a id="manual.socks_proxy.port" name="manual.socks_proxy.port">manual.socks_proxy.port</a>**<br/>[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | SOCKS proxy port.<br/>**Validators**: <br/>• well-known ports (1 to 1023) are allowed<br/>• registred ports (1024 to 49151) are allowed<br/>• private ports (greater than 49152) are allowed<br/>**Default**: 1080<br/>**Disabled**: when the variable "[SOCKS proxy address](#manual.socks_proxy.address)" has the value "null". |
|
||||||
|
| **<a id="manual.socks_proxy.version" name="manual.socks_proxy.version">manual.socks_proxy.version</a>**<br/>[`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | SOCKS host version used by proxy.<br/>**Choices**: <br/>• v4<br/>• v5 **← (default)**<br/>**Disabled**: when the variable "[SOCKS proxy address](#manual.socks_proxy.address)" has the value "null". |
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| **<a id="auto" name="auto">auto</a>**<br/>[`web address`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | Automatic proxy configuration URL.<br/>**Validators**: <br/>• well-known ports (1 to 1023) are allowed<br/>• registred ports (1024 to 49151) are allowed<br/>• type domainname<br/>• the domain name can be a hostname<br/>**Disabled**: when the variable "[Configure Proxy Access to the Internet](#proxy_mode)" hasn't the value "Automatic proxy configuration URL". |
|
||||||
|
| **<a id="no_proxy" name="no_proxy">no_proxy</a>**<br/>[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` *`disabled`* `unique` | Address for which proxy will be desactivated.<br/>Connections to localhost, 127.0.0.1/8 and ::1 are never proxied.<br/>**Validators**: <br/>• type domainname<br/>• the domain name can starts by a dot<br/>• the domain name can be a hostname<br/>• the domain name can be an IP<br/>• the domain name can be network in CIDR format<br/>**Examples**: <br/>• .mozilla.org<br/>• .net.nz<br/>• 192.168.1.0/24<br/>**Disabled**: when the variable "[Configure Proxy Access to the Internet](#proxy_mode)" has the value "No proxy". |
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This markdown describes an organised data set.
|
||||||
|
It describes some kind of a storage content with variables names.
|
||||||
|
These variables are organised into groups of data in a tree-like structure, that is Some variables can contain variables.
|
||||||
|
Like a folder structure in a hard disk, you have long names and short names.
|
||||||
|
When the user talks about a variable's name, he means the long name.
|
||||||
|
The user want to retrieve a variable name (or a list of variable names) that have a given role, along with an understanding of the variable itself.
|
||||||
|
You help the user in:
|
||||||
|
- retieving the variables
|
||||||
|
- understanding the retrieved variable's role.
|
||||||
|
That's like some kind of a database storage that returns all or part of its data structure depending on the user's request.
|
||||||
|
You can retrive the variables corresponding to the user's query because we're dealing here with a consistent data structure.
|
||||||
|
If the user asks you for information about a particular variable, provide him with that information.
|
||||||
|
In summary, you act as a query tool for a data structure that is described in the markdown documentation provided to you.
|
||||||
16
webllm/personaLoader.js
Normal file
16
webllm/personaLoader.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// personaLoader.js
|
||||||
|
export async function loadPersona(filepath = './persona.txt') {
|
||||||
|
try {
|
||||||
|
const response = await fetch(filepath);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Erreur ${response.status}: impossible de charger la persona`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemPrompt = await response.text();
|
||||||
|
return systemPrompt.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur chargement persona:", error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue