diff --git a/.gitignore b/.gitignore
index f0cb2f7..d9a6c29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ bribes
site/
.obsidian
.task/
+webllm/node_modules/
diff --git a/doc/WebLlm.md b/doc/WebLlm.md
index 1ecfa6c..6ff3e5d 100644
--- a/doc/WebLlm.md
+++ b/doc/WebLlm.md
@@ -34,9 +34,51 @@ Use a recent Chrome/Edge (≥ 113) or Safari 18+ (chrome://flags/#enable-unsafe-
## install webllm
-
[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
diff --git a/webllm/index.html b/webllm/index.html
new file mode 100644
index 0000000..e6a0ad6
--- /dev/null
+++ b/webllm/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ Test WebLLM
+
+
+ Test de WebLLM
+
+
+
+
+
+
diff --git a/webllm/index.js b/webllm/index.js
new file mode 100644
index 0000000..d4db07c
--- /dev/null
+++ b/webllm/index.js
@@ -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);
diff --git a/webllm/index.js.1 b/webllm/index.js.1
new file mode 100644
index 0000000..d086e9c
--- /dev/null
+++ b/webllm/index.js.1
@@ -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);
diff --git a/webllm/package.json b/webllm/package.json
new file mode 100644
index 0000000..3652d11
--- /dev/null
+++ b/webllm/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "@mlc-ai/web-llm": "^0.2.85"
+ }
+}
diff --git a/webllm/persona.txt b/webllm/persona.txt
new file mode 100644
index 0000000..622a43b
--- /dev/null
+++ b/webllm/persona.txt
@@ -0,0 +1,75 @@
+Provided this markdown documentation:
+
+```markdown
+| Variable | Description |
+|------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **proxy_mode**
[`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | Configure Proxy Access to the Internet.
**Choices**:
• No proxy **← (default)**
• Auto-detect proxy settings for this network
• Use system proxy settings
• Manual proxy configuration
• 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 |
+|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **manual.http_proxy.address**
[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTP proxy address.
**Validators**:
• type domainname
• the domain name can be an IP |
+| **manual.http_proxy.port**
[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTP proxy port.
**Validators**:
• well-known ports (1 to 1023) are allowed
• registred ports (1024 to 49151) are allowed
• private ports (greater than 49152) are allowed
**Default**: 8080 |
+
+| Variable | Description |
+|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
+| **manual.use_for_https**
[`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | Also use this proxy for HTTPS.
**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 |
+|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **manual.https_proxy.address**
[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTPS proxy address.
**Validators**:
• type domainname
• the domain name can be an IP
**Default**: the value of the variable "[HTTP proxy address](#manual.http_proxy.address)". |
+| **manual.https_proxy.port**
[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | HTTPS proxy port.
**Validators**:
• well-known ports (1 to 1023) are allowed
• registred ports (1024 to 49151) are allowed
• private ports (greater than 49152) are allowed
**Default**: the value of the variable "[HTTP proxy port](#manual.http_proxy.port)". |
+
+## SOCKS Proxy
+
+> [!NOTE]
+>
+> **Path**: manual.socks_proxy
+
+| Variable | Description |
+|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **manual.socks_proxy.address**
[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | SOCKS proxy address.
**Validators**:
• type domainname
• the domain name can be an IP |
+| **manual.socks_proxy.port**
[`port`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | SOCKS proxy port.
**Validators**:
• well-known ports (1 to 1023) are allowed
• registred ports (1024 to 49151) are allowed
• private ports (greater than 49152) are allowed
**Default**: 1080
**Disabled**: when the variable "[SOCKS proxy address](#manual.socks_proxy.address)" has the value "null". |
+| **manual.socks_proxy.version**
[`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | SOCKS host version used by proxy.
**Choices**:
• v4
• v5 **← (default)**
**Disabled**: when the variable "[SOCKS proxy address](#manual.socks_proxy.address)" has the value "null". |
+
+| Variable | Description |
+|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **auto**
[`web address`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` *`disabled`* | Automatic proxy configuration URL.
**Validators**:
• well-known ports (1 to 1023) are allowed
• registred ports (1024 to 49151) are allowed
• type domainname
• the domain name can be a hostname
**Disabled**: when the variable "[Configure Proxy Access to the Internet](#proxy_mode)" hasn't the value "Automatic proxy configuration URL". |
+| **no_proxy**
[`domainname`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` *`disabled`* `unique` | Address for which proxy will be desactivated.
Connections to localhost, 127.0.0.1/8 and ::1 are never proxied.
**Validators**:
• type domainname
• the domain name can starts by a dot
• the domain name can be a hostname
• the domain name can be an IP
• the domain name can be network in CIDR format
**Examples**:
• .mozilla.org
• .net.nz
• 192.168.1.0/24
**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.
diff --git a/webllm/personaLoader.js b/webllm/personaLoader.js
new file mode 100644
index 0000000..7180946
--- /dev/null
+++ b/webllm/personaLoader.js
@@ -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;
+ }
+}