Update petits-llms.adoc, config samples and open ticket 53
- docs/fr/explanation/petits-llms.adoc: fetch_content (tool list, error codes, output kept out of the context, URL repair), provider and model in session files, config.samples in p13/p15, measured prompt breakdown in p7, references table, revdate 2026-09-30. - config.samples/*.yaml: fetchContentTool: true, as in agent.dmr.yaml. - .tickets/issues/0053: tool order changes on every question (Genkit builds the tool list from a map; not fixed in v1.13.1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1fa0c42 parent: 2d919bd added
.tickets/issues/0053-tool-order-changes-on-every-question.yaml +82 -0 | new file mode 100644 | ||
| @@ -0,0 +1,82 @@ | ||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | |
| 2 | +id: 53 | |
| 3 | +title: Tool order changes on every question (breaks the KV prefix cache) | |
| 4 | +state: open | |
| 5 | +author: | |
| 6 | + name: k33g | |
| 7 | + email: ph.charriere@gmail.com | |
| 8 | +createdAt: 2026-09-30T05:52:16.000Z | |
| 9 | +updatedAt: 2026-09-30T05:57:31.000Z | |
| 10 | +labels: | |
| 11 | + - kind::bug | |
| 12 | + - priority::high | |
| 13 | + - llama.cpp | |
| 14 | +related: | |
| 15 | + - 43 | |
| 16 | +body: | | |
| 17 | + The `tools` array of the chat request comes in a different order on every | |
| 18 | + `Generate` call, i.e. on every user question of the same session. | |
| 19 | + | |
| 20 | + Cause: Genkit v1.10, `ai/generate.go` (GenerateWithRequest, ~l.236-273) | |
| 21 | + puts the tool definitions in a map (`toolDefMap`) and builds `toolDefs` by | |
| 22 | + ranging over it — Go map iteration order is random. Within one question the | |
| 23 | + same request is reused, so the order only changes between questions. | |
| 24 | + | |
| 25 | + Seen on 2026-09-30 with a fake OpenAI server capturing mm's requests | |
| 26 | + (agent.dmr.yaml, 7 tools): a rotation of the same order on 6 runs of | |
| 27 | + `mm -p hello`, and on the 4 questions of one `mm -acp` session. | |
| 28 | + | |
| 29 | + Why it matters: llama.cpp only reuses its KV cache for the part of the | |
| 30 | + prompt that is identical to the previous request. Templates that render the | |
| 31 | + tools in the system block (Qwen-style) would then re-read the tools AND the | |
| 32 | + whole history on every question — minutes of prefill on a 20k-token session | |
| 33 | + with a local 27B. Not measured yet (needs `cached_tokens`, see | |
| 34 | + petits-llms.adoc, piste p10). | |
| 35 | + | |
| 36 | + Fix candidate: sort `req.Tools` by name in mm's `WrapModel` middleware in | |
| 37 | + `engine.Generate` (internal/engine/engine.go), which already sees every | |
| 38 | + request. | |
| 39 | +tasks: | |
| 40 | + - id: 1 | |
| 41 | + title: Sort req.Tools by name in WrapModel, with a test (fake model, several Generate calls, same order) | |
| 42 | + state: open | |
| 43 | + priority: none | |
| 44 | + author: | |
| 45 | + name: k33g | |
| 46 | + email: ph.charriere@gmail.com | |
| 47 | + createdAt: 2026-09-30T05:52:16.000Z | |
| 48 | + updatedAt: 2026-09-30T05:52:16.000Z | |
| 49 | + - id: 2 | |
| 50 | + title: Measure cached_tokens / prefill time on llama-server before and after (same session, 3-4 questions) | |
| 51 | + state: open | |
| 52 | + priority: none | |
| 53 | + author: | |
| 54 | + name: k33g | |
| 55 | + email: ph.charriere@gmail.com | |
| 56 | + createdAt: 2026-09-30T05:52:16.000Z | |
| 57 | + updatedAt: 2026-09-30T05:52:16.000Z | |
| 58 | + - id: 3 | |
| 59 | + title: Document the result in petits-llms.adoc (p7 / p10) | |
| 60 | + state: open | |
| 61 | + priority: none | |
| 62 | + author: | |
| 63 | + name: k33g | |
| 64 | + email: ph.charriere@gmail.com | |
| 65 | + createdAt: 2026-09-30T05:52:16.000Z | |
| 66 | + updatedAt: 2026-09-30T05:52:16.000Z | |
| 67 | +comments: | |
| 68 | + - id: 1 | |
| 69 | + author: | |
| 70 | + name: k33g | |
| 71 | + email: ph.charriere@gmail.com | |
| 72 | + createdAt: 2026-09-30T05:57:31.000Z | |
| 73 | + body: | | |
| 74 | + Upgrading Genkit does not fix it. Checked on 2026-09-30: | |
| 75 | + - v1.13.1 (latest; same code under github.com/firebase/genkit/go and | |
| 76 | + github.com/genkit-ai/genkit/go): ai/generate.go l.470-511 still builds | |
| 77 | + toolDefs by ranging over toolDefMap. | |
| 78 | + - main branch (raw generate.go of the day): same lines, unchanged. | |
| 79 | + - plugins/compat_oai WithTools keeps the order it is given, and no Sort | |
| 80 | + on tools anywhere in ai/ or compat_oai. | |
| 81 | + So the fix stays on mm's side (sort req.Tools in WrapModel). An upstream | |
| 82 | + issue/PR on genkit-ai/genkit could fix it for everyone. | |
| new file mode 100644 | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | +# Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | ||
| 2 | +id: 53 | ||
| 3 | +title: Tool order changes on every question (breaks the KV prefix cache) | ||
| 4 | +state: open | ||
| 5 | +author: | ||
| 6 | + name: k33g | ||
| 7 | + email: ph.charriere@gmail.com | ||
| 8 | +createdAt: 2026-09-30T05:52:16.000Z | ||
| 9 | +updatedAt: 2026-09-30T05:57:31.000Z | ||
| 10 | +labels: | ||
| 11 | + - kind::bug | ||
| 12 | + - priority::high | ||
| 13 | + - llama.cpp | ||
| 14 | +related: | ||
| 15 | + - 43 | ||
| 16 | +body: | | ||
| 17 | + The `tools` array of the chat request comes in a different order on every | ||
| 18 | + `Generate` call, i.e. on every user question of the same session. | ||
| 19 | + | ||
| 20 | + Cause: Genkit v1.10, `ai/generate.go` (GenerateWithRequest, ~l.236-273) | ||
| 21 | + puts the tool definitions in a map (`toolDefMap`) and builds `toolDefs` by | ||
| 22 | + ranging over it — Go map iteration order is random. Within one question the | ||
| 23 | + same request is reused, so the order only changes between questions. | ||
| 24 | + | ||
| 25 | + Seen on 2026-09-30 with a fake OpenAI server capturing mm's requests | ||
| 26 | + (agent.dmr.yaml, 7 tools): a rotation of the same order on 6 runs of | ||
| 27 | + `mm -p hello`, and on the 4 questions of one `mm -acp` session. | ||
| 28 | + | ||
| 29 | + Why it matters: llama.cpp only reuses its KV cache for the part of the | ||
| 30 | + prompt that is identical to the previous request. Templates that render the | ||
| 31 | + tools in the system block (Qwen-style) would then re-read the tools AND the | ||
| 32 | + whole history on every question — minutes of prefill on a 20k-token session | ||
| 33 | + with a local 27B. Not measured yet (needs `cached_tokens`, see | ||
| 34 | + petits-llms.adoc, piste p10). | ||
| 35 | + | ||
| 36 | + Fix candidate: sort `req.Tools` by name in mm's `WrapModel` middleware in | ||
| 37 | + `engine.Generate` (internal/engine/engine.go), which already sees every | ||
| 38 | + request. | ||
| 39 | +tasks: | ||
| 40 | + - id: 1 | ||
| 41 | + title: Sort req.Tools by name in WrapModel, with a test (fake model, several Generate calls, same order) | ||
| 42 | + state: open | ||
| 43 | + priority: none | ||
| 44 | + author: | ||
| 45 | + name: k33g | ||
| 46 | + email: ph.charriere@gmail.com | ||
| 47 | + createdAt: 2026-09-30T05:52:16.000Z | ||
| 48 | + updatedAt: 2026-09-30T05:52:16.000Z | ||
| 49 | + - id: 2 | ||
| 50 | + title: Measure cached_tokens / prefill time on llama-server before and after (same session, 3-4 questions) | ||
| 51 | + state: open | ||
| 52 | + priority: none | ||
| 53 | + author: | ||
| 54 | + name: k33g | ||
| 55 | + email: ph.charriere@gmail.com | ||
| 56 | + createdAt: 2026-09-30T05:52:16.000Z | ||
| 57 | + updatedAt: 2026-09-30T05:52:16.000Z | ||
| 58 | + - id: 3 | ||
| 59 | + title: Document the result in petits-llms.adoc (p7 / p10) | ||
| 60 | + state: open | ||
| 61 | + priority: none | ||
| 62 | + author: | ||
| 63 | + name: k33g | ||
| 64 | + email: ph.charriere@gmail.com | ||
| 65 | + createdAt: 2026-09-30T05:52:16.000Z | ||
| 66 | + updatedAt: 2026-09-30T05:52:16.000Z | ||
| 67 | +comments: | ||
| 68 | + - id: 1 | ||
| 69 | + author: | ||
| 70 | + name: k33g | ||
| 71 | + email: ph.charriere@gmail.com | ||
| 72 | + createdAt: 2026-09-30T05:57:31.000Z | ||
| 73 | + body: | | ||
| 74 | + Upgrading Genkit does not fix it. Checked on 2026-09-30: | ||
| 75 | + - v1.13.1 (latest; same code under github.com/firebase/genkit/go and | ||
| 76 | + github.com/genkit-ai/genkit/go): ai/generate.go l.470-511 still builds | ||
| 77 | + toolDefs by ranging over toolDefMap. | ||
| 78 | + - main branch (raw generate.go of the day): same lines, unchanged. | ||
| 79 | + - plugins/compat_oai WithTools keeps the order it is given, and no Sort | ||
| 80 | + on tools anywhere in ai/ or compat_oai. | ||
| 81 | + So the fix stays on mm's side (sort req.Tools in WrapModel). An upstream | ||
| 82 | + issue/PR on genkit-ai/genkit could fix it for everyone. | ||
modified
config.samples/agent.dmr.gemma.yaml +5 -0 | @@ -24,6 +24,11 @@ editTools: true | ||
| 24 | 24 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 25 | 25 | planTool: true |
| 26 | 26 | |
| 27 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | |
| 28 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | |
| 29 | +# Honours the site's robots.txt. Off by default — it reaches the network. | |
| 30 | +fetchContentTool: true | |
| 31 | + | |
| 27 | 32 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 28 | 33 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 29 | 34 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
| @@ -24,6 +24,11 @@ editTools: true | |||
| 24 | # Set to false to disable plan creation and tracking via the `plan` tool. | 24 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 25 | planTool: true | 25 | planTool: true |
| 26 | 26 | ||
| 27 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | ||
| 28 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | ||
| 29 | +# Honours the site's robots.txt. Off by default — it reaches the network. | ||
| 30 | +fetchContentTool: true | ||
| 31 | + | ||
| 27 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | 32 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 28 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. | 33 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 29 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): | 34 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
modified
config.samples/agent.dmr.gpt-oss.yaml +5 -0 | @@ -25,6 +25,11 @@ editTools: true | ||
| 25 | 25 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 26 | 26 | planTool: true |
| 27 | 27 | |
| 28 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | |
| 29 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | |
| 30 | +# Honours the site's robots.txt. Off by default — it reaches the network. | |
| 31 | +fetchContentTool: true | |
| 32 | + | |
| 28 | 33 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 29 | 34 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 30 | 35 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
| @@ -25,6 +25,11 @@ editTools: true | |||
| 25 | # Set to false to disable plan creation and tracking via the `plan` tool. | 25 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 26 | planTool: true | 26 | planTool: true |
| 27 | 27 | ||
| 28 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | ||
| 29 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | ||
| 30 | +# Honours the site's robots.txt. Off by default — it reaches the network. | ||
| 31 | +fetchContentTool: true | ||
| 32 | + | ||
| 28 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | 33 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 29 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. | 34 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 30 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): | 35 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
modified
config.samples/agent.dmr.qwen3.6.yaml +5 -0 | @@ -27,6 +27,11 @@ editTools: true | ||
| 27 | 27 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 28 | 28 | planTool: true |
| 29 | 29 | |
| 30 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | |
| 31 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | |
| 32 | +# Honours the site's robots.txt. Off by default — it reaches the network. | |
| 33 | +fetchContentTool: true | |
| 34 | + | |
| 30 | 35 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 31 | 36 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 32 | 37 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
| @@ -27,6 +27,11 @@ editTools: true | |||
| 27 | # Set to false to disable plan creation and tracking via the `plan` tool. | 27 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 28 | planTool: true | 28 | planTool: true |
| 29 | 29 | ||
| 30 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | ||
| 31 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | ||
| 32 | +# Honours the site's robots.txt. Off by default — it reaches the network. | ||
| 33 | +fetchContentTool: true | ||
| 34 | + | ||
| 30 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | 35 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 31 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. | 36 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 32 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): | 37 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
modified
config.samples/agent.llamacpp.ornith.yaml +5 -0 | @@ -30,6 +30,11 @@ editTools: true | ||
| 30 | 30 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 31 | 31 | planTool: true |
| 32 | 32 | |
| 33 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | |
| 34 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | |
| 35 | +# Honours the site's robots.txt. Off by default — it reaches the network. | |
| 36 | +fetchContentTool: true | |
| 37 | + | |
| 33 | 38 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 34 | 39 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 35 | 40 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
| @@ -30,6 +30,11 @@ editTools: true | |||
| 30 | # Set to false to disable plan creation and tracking via the `plan` tool. | 30 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 31 | planTool: true | 31 | planTool: true |
| 32 | 32 | ||
| 33 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | ||
| 34 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | ||
| 35 | +# Honours the site's robots.txt. Off by default — it reaches the network. | ||
| 36 | +fetchContentTool: true | ||
| 37 | + | ||
| 33 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | 38 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 34 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. | 39 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 35 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): | 40 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
modified
config.samples/agent.llamacpp.qwen3.8.yaml +5 -0 | @@ -30,6 +30,11 @@ editTools: true | ||
| 30 | 30 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 31 | 31 | planTool: true |
| 32 | 32 | |
| 33 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | |
| 34 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | |
| 35 | +# Honours the site's robots.txt. Off by default — it reaches the network. | |
| 36 | +fetchContentTool: true | |
| 37 | + | |
| 33 | 38 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 34 | 39 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 35 | 40 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
| @@ -30,6 +30,11 @@ editTools: true | |||
| 30 | # Set to false to disable plan creation and tracking via the `plan` tool. | 30 | # Set to false to disable plan creation and tracking via the `plan` tool. |
| 31 | planTool: true | 31 | planTool: true |
| 32 | 32 | ||
| 33 | +# The built-in fetch_content tool: fetch a web page and get it as Markdown | ||
| 34 | +# ("récupère le contenu de https://…", optionally "et sauve le dans page.md"). | ||
| 35 | +# Honours the site's robots.txt. Off by default — it reaches the network. | ||
| 36 | +fetchContentTool: true | ||
| 37 | + | ||
| 33 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). | 38 | # Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename). |
| 34 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. | 39 | # The file extension picks the server. A server missing from the PATH is skipped with a warning. |
| 35 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): | 40 | # No server listed = no `lsp` tool. Examples (uncomment what you have installed): |
modified
docs/fr/explanation/petits-llms.adoc +43 -6 | @@ -6,7 +6,7 @@ | ||
| 6 | 6 | :icons: font |
| 7 | 7 | :source-highlighter: rouge |
| 8 | 8 | :lang: fr |
| 9 | -:revdate: 2026-09-26 | |
| 9 | +:revdate: 2026-09-30 | |
| 10 | 10 | |
| 11 | 11 | [abstract] |
| 12 | 12 | Mini Me (`mm`) a été conçu pour tourner avec des modèles *locaux* — typiquement 2 à 12 milliards de paramètres servis par Docker Model Runner ou llama-server. |
| @@ -56,6 +56,8 @@ L'agent est né autour d'un seul outil, `bash` (`internal/tools/tools.go`). Les | ||
| 56 | 56 | * `read_skill` n'existe pas si `skillsDir` ne contient aucun `.md` ; |
| 57 | 57 | * `lsp` n'existe pas si aucun serveur de langage n'est configuré *et* présent dans le `PATH`. |
| 58 | 58 | |
| 59 | +Un dernier, `fetch_content` (voir <<fetch>>), est désactivé par défaut (`fetchContentTool: true` pour l'activer, comme dans `agent.dmr.yaml`) : c'est le seul outil intégré qui accède au réseau. | |
| 60 | + | |
| 59 | 61 | Chaque outil déclaré coûte des tokens à chaque requête et une option de plus parmi lesquelles un petit modèle doit choisir. Moins il y en a, mieux il choisit. |
| 60 | 62 | |
| 61 | 63 | === Des descriptions écrites pour être suivies |
| @@ -66,6 +68,7 @@ Les descriptions d'outils ne décrivent pas seulement l'API, elles anticipent le | ||
| 66 | 68 | * `read_file` : « edit_file needs the EXACT text of the file … Do not type it from memory. » |
| 67 | 69 | * `edit_file` : six règles *numérotées*, dont « do not switch to write_file to force the change through ». |
| 68 | 70 | * `write_file` : rappelle qu'il écrase tout et renvoie vers `edit_file`. |
| 71 | +* `fetch_content` : donne des exemples de demandes en plusieurs langues (« récupère le contenu de https://example.com »), avec la consigne « do not use curl or wget through bash for that ». | |
| 69 | 72 | |
| 70 | 73 | Le prompt système des configurations livrées (`agent.dmr.yaml`, `agent.llamacpp.yaml`) répète ces règles en sections courtes en majuscules (`SKILLS`, `FILE EDITING`, `RULES`, `BACKGROUND JOBS`). La redondance est voulue : un petit modèle suit mieux une consigne qu'il lit deux fois, à deux endroits. |
| 71 | 74 | |
| @@ -85,7 +88,8 @@ Commande en échec (`[exit code: …]`), délai dépassé (`[error: 30s timeout | ||
| 85 | 88 | Les messages sont rédigés comme des *consignes de réparation* : |
| 86 | 89 | |
| 87 | 90 | * `read_skill` avec un nom inconnu répond `[skill: no skill named "x" — available: a, b, c]` ; |
| 88 | -* `edit_file` avec un texte en double donne les numéros de ligne des occurrences et explique comment rendre `old` unique (`internal/fileedit/edits.go`). | |
| 91 | +* `edit_file` avec un texte en double donne les numéros de ligne des occurrences et explique comment rendre `old` unique (`internal/fileedit/edits.go`) ; | |
| 92 | +* `fetch_content` classe ses échecs en trois codes, `[fetch_content: error N (…) — raison]` : 1 = page non convertible, 2 = page inaccessible (hôte, statut HTTP, `robots.txt`), 3 = argument invalide. La description dit au modèle que le code 3 signifie « corrige ton appel », pour qu'il ne s'acharne pas sur un site en panne. | |
| 89 | 93 | |
| 90 | 94 | La seule exception est volontaire : l'arrêt par le détecteur de boucle (voir <<boucles>>). |
| 91 | 95 | |
| @@ -193,7 +197,7 @@ Test réel sur Docker Model Runner avec Mellum 12B, `max_tokens` volontairement | ||
| 193 | 197 | * le mécanisme fonctionne : le modèle reprend la main deux fois, puis le message clair s'affiche ; |
| 194 | 198 | * *le modèle a ignoré la consigne* les deux fois et a retenté le fichier entier, même avec un budget chiffré en caractères. |
| 195 | 199 | |
| 196 | -La relance rend l'échec lisible et laisse une chance aux modèles qui suivent les instructions. Elle ne remplace pas un `max_tokens` adapté : 16 384 est une valeur raisonnable pour un modèle « thinking », avec une marge sous la fenêtre de contexte. Voir aussi la piste <<p15>>. | |
| 200 | +La relance rend l'échec lisible et laisse une chance aux modèles qui suivent les instructions. Elle ne remplace pas un `max_tokens` adapté : 16 384 est une valeur raisonnable pour un modèle « thinking », avec une marge sous la fenêtre de contexte. Les configurations de `config.samples/` montent à 32 768 (voir <<p13>>), alors que `agent.dmr.yaml` et `agent.llamacpp.yaml` restent à 4 096. Voir aussi la piste <<p15>>. | |
| 197 | 201 | |
| 198 | 202 | == Modèles à raisonnement |
| 199 | 203 | |
| @@ -208,6 +212,17 @@ Le greffon OpenAI de Genkit ignore `reasoning_content`. `mm` le lit lui-même, u | ||
| 208 | 212 | |
| 209 | 213 | `truncate` limite chaque sortie d'outil à `maxOutput` caractères en conservant *le début et la fin* (la fin porte souvent l'erreur ou le résumé d'une commande). `bash` ne relit jamais plus d'1 Mio par extrémité depuis le disque. |
| 210 | 214 | |
| 215 | +[[fetch]] | |
| 216 | +=== Une page web qui ne passe pas par le contexte | |
| 217 | + | |
| 218 | +`fetch_content` (`internal/tools/fetchcontent.go`, conversion dans `internal/webmd`) récupère une page et la rend en Markdown, après avoir retiré les scripts, la navigation, les publicités et les bandeaux de cookies. Trois choix visent directement les petits modèles : | |
| 219 | + | |
| 220 | +* *Enregistrer sans afficher.* Avec `output`, le Markdown est écrit dans le fichier et l'outil ne renvoie qu'une ligne (`[fetch_content: saved N lines … — the content is not shown]`). « Sauve-le dans hello.txt, ne l'affiche pas » ne coûte donc pas une page entière de contexte, et le modèle n'a pas de texte à recopier. | |
| 221 | +* *Une URL mal tapée est réparée.* `NormalizeURL` (`internal/webmd/fetch.go`) complète un nom de site sans schéma (`k33g.org` → `https://k33g.org`) et corrige un schéma sans deux-points (`https//k33g.org`), faute fréquente quand le modèle recopie la demande. | |
| 222 | +* *Une page vide est signalée, pas enregistrée* : le modèle ne confirme pas l'enregistrement d'un fichier vide. | |
| 223 | + | |
| 224 | +Sans `output`, la page passe par `truncate`, comme toute sortie d'outil. Vérifié le 29/09/2026 avec Mellum 12B (`mm -p`, Docker Model Runner) : pour « récupère le contenu de https//k33g.org », puis la même demande avec « ne l'affiche pas et sauve-le dans hello.txt », le modèle a choisi `fetch_content` les deux fois, a écrit le fichier et n'a pas recopié son contenu. | |
| 225 | + | |
| 211 | 226 | === Une compression hybride |
| 212 | 227 | |
| 213 | 228 | `internal/compact` remplace les vieux tours par *un* résumé écrit par le modèle et garde les `keepLastTurns` derniers tours intacts (le modèle travaille sur eux). Points notables : |
| @@ -242,7 +257,7 @@ Un petit modèle choisit mal une procédure sur son seul nom. `internal/skills` | ||
| 242 | 257 | |
| 243 | 258 | == Une méthode : mesurer |
| 244 | 259 | |
| 245 | -La plupart des décisions sont justifiées dans le code par une *mesure datée* (« measured on qwen3.5-2b », « the demo audit of 2026-09-18 », « ticket 27 »). Le reste de `mm` est testé contre un moteur factice (rapide, déterministe) ; seul le routage des skills, qui est une propriété du modèle, est mesuré contre un vrai modèle. Garder cette discipline est la meilleure garantie que les améliorations ci-dessous en soient vraiment. | |
| 260 | +La plupart des décisions sont justifiées dans le code par une *mesure datée* (« measured on qwen3.5-2b », « the demo audit of 2026-09-18 », « ticket 27 »). Le reste de `mm` est testé contre un moteur factice (rapide, déterministe) ; seul le routage des skills, qui est une propriété du modèle, est mesuré contre un vrai modèle. Depuis le 27/09/2026, chaque fichier de session enregistre `provider` et `model`, et chaque erreur le modèle qui l'a produite (`internal/store`). Une session qui a échoué peut donc être rattachée au modèle en cause, même quand on en change en cours de route. Garder cette discipline est la meilleure garantie que les améliorations ci-dessous en soient vraiment. | |
| 246 | 261 | |
| 247 | 262 | [[pistes]] |
| 248 | 263 | == Pistes d'amélioration |
| @@ -336,9 +351,28 @@ Le cas voisin des arguments qui ne sont pas du JSON valide (JSON coupé par `max | ||
| 336 | 351 | |
| 337 | 352 | *Constat.* Mesuré sur `agent.dmr.yaml` : la première requête d'une session pèse ≈ 3,4k tokens avant toute question (prompt système ≈ 3,7k caractères, six descriptions d'outils et leurs schémas, catalogue de skills). La description de `plan` à elle seule fait ≈ 1,3k caractères, pour un outil utile seulement aux demandes en plusieurs étapes. |
| 338 | 353 | |
| 354 | +Cette mesure date d'avant `fetch_content`. Le 30/09/2026, la première requête de `mm -p hello` avec `agent.dmr.yaml` a été capturée par un faux serveur OpenAI, avec et sans `fetchContentTool` : | |
| 355 | + | |
| 356 | +[cols="2,1,1,1",options="header"] | |
| 357 | +|=== | |
| 358 | +| Élément (caractères) | Description | Schéma | Total | |
| 359 | + | |
| 360 | +| Prompt système | | | 3 436 | |
| 361 | +| `edit_file` | 1 383 | 758 | 2 141 | |
| 362 | +| `plan` | 1 335 | 842 | 2 177 | |
| 363 | +| `fetch_content` | 1 037 | 1 068 | 2 105 | |
| 364 | +| `read_skill` (catalogue de 7 skills) | 1 373 | 222 | 1 595 | |
| 365 | +| `read_file` | 311 | 534 | 845 | |
| 366 | +| `bash` | 575 | 164 | 739 | |
| 367 | +| `write_file` | 348 | 307 | 655 | |
| 368 | +| *Requête entière* (JSON) | | | *14 993* (12 762 sans `fetch_content`) | |
| 369 | +|=== | |
| 370 | + | |
| 371 | +Les outils pèsent trois fois le prompt système (10 257 caractères contre 3 436). `fetch_content` ajoute 2 231 caractères à la requête, soit +17 %. À ≈ 3,4k tokens pour la version à six outils, cela fait ≈ 4k tokens. Ce chiffre est une estimation par proportion : le compte exact du serveur reste à relever. Le schéma de `fetch_content` est le plus lourd des sept, à cause des descriptions de ses quatre paramètres optionnels (`baseUrl`, `tables`, `strikethrough`, `taskList`). | |
| 372 | + | |
| 339 | 373 | *Proposition.* |
| 340 | 374 | |
| 341 | -* Condenser la description de `plan` (l'exemple de workflow en sept étapes pourrait passer dans un skill), ou désactiver `planTool` par défaut dans les configurations pour petits modèles. | |
| 375 | +* Condenser la description de `plan` (l'exemple de workflow en sept étapes pourrait passer dans un skill), ou désactiver `planTool` par défaut dans les configurations pour petits modèles. La même question se pose pour `fetchContentTool` sur les petites fenêtres, et pour les paramètres optionnels de `fetch_content`, qu'un petit modèle n'utilise presque jamais. | |
| 342 | 376 | * Éviter les doublons entre prompt système et descriptions quand ils ne servent pas. |
| 343 | 377 | * Mesurer chaque retrait avec `internal/eval` : la redondance est parfois ce qui fait marcher un 4B. |
| 344 | 378 | |
| @@ -401,7 +435,7 @@ Sur une machine locale, un préfixe en cache fait la différence entre une répo | ||
| 401 | 435 | [[p13]] |
| 402 | 436 | === Profils par modèle |
| 403 | 437 | |
| 404 | -*Constat.* Les réglages utiles varient d'une famille à l'autre : pénalité de répétition, `top_k`, `min_p`, gestion du rôle `system`, longueur de prompt supportée. `tests/` contient déjà des variantes par modèle (`agent.dmr-qwen.yaml`, `agent.dmr-gemma.yaml`). | |
| 438 | +*Constat.* Les réglages utiles varient d'une famille à l'autre : pénalité de répétition, `top_k`, `min_p`, gestion du rôle `system`, longueur de prompt supportée. `tests/` contient déjà des variantes par modèle (`agent.dmr-qwen.yaml`, `agent.dmr-gemma.yaml`). Depuis le 28/09/2026, `config.samples/` en ajoute cinq, complètes, pour des modèles plus gros : Gemma 4 26B-A4B, gpt-oss 20B, Qwen3.6 35B-A3B (DMR), Ornith 1.5 35B-A3B et Qwen3.8 27B (llama-server). Toutes fixent `max_tokens: 32768`, `watchdogTimeout: 300s` et `summaryMaxTokens: 1200`. Ce sont des profils de fait, mais recopiés à la main : chaque changement de la configuration de base est à reporter dans chacun des fichiers (`fetchContentTool: true` y a été ajouté à la main le 30/09/2026). | |
| 405 | 439 | |
| 406 | 440 | *Proposition.* Une clé `profile:` (ou un fichier de profils) qui applique des valeurs par défaut connues par famille de modèle, surchargées par le YAML. |
| 407 | 441 | |
| @@ -448,5 +482,8 @@ Sur une machine locale, un préfixe en cache fait la différence entre une répo | ||
| 448 | 482 | | Compression | `internal/compact/` |
| 449 | 483 | | Skills et catalogue | `internal/skills/`, `skills/` |
| 450 | 484 | | Évaluation du routage | `internal/eval/` |
| 485 | +| Page web en Markdown (`fetch_content`) | `internal/tools/fetchcontent.go`, `internal/webmd/` | |
| 486 | +| Sessions (fournisseur et modèle enregistrés) | `internal/store/store.go` | |
| 487 | +| Configurations par modèle | `config.samples/`, `tests/` | |
| 451 | 488 | | Explications d'erreurs | `internal/engine/explain.go`, `internal/engine/openai_compat.go` |
| 452 | 489 | |=== |
| @@ -6,7 +6,7 @@ | |||
| 6 | :icons: font | 6 | :icons: font |
| 7 | :source-highlighter: rouge | 7 | :source-highlighter: rouge |
| 8 | :lang: fr | 8 | :lang: fr |
| 9 | -:revdate: 2026-09-26 | 9 | +:revdate: 2026-09-30 |
| 10 | 10 | ||
| 11 | [abstract] | 11 | [abstract] |
| 12 | Mini Me (`mm`) a été conçu pour tourner avec des modèles *locaux* — typiquement 2 à 12 milliards de paramètres servis par Docker Model Runner ou llama-server. | 12 | Mini Me (`mm`) a été conçu pour tourner avec des modèles *locaux* — typiquement 2 à 12 milliards de paramètres servis par Docker Model Runner ou llama-server. |
| @@ -56,6 +56,8 @@ L'agent est né autour d'un seul outil, `bash` (`internal/tools/tools.go`). Les | |||
| 56 | * `read_skill` n'existe pas si `skillsDir` ne contient aucun `.md` ; | 56 | * `read_skill` n'existe pas si `skillsDir` ne contient aucun `.md` ; |
| 57 | * `lsp` n'existe pas si aucun serveur de langage n'est configuré *et* présent dans le `PATH`. | 57 | * `lsp` n'existe pas si aucun serveur de langage n'est configuré *et* présent dans le `PATH`. |
| 58 | 58 | ||
| 59 | +Un dernier, `fetch_content` (voir <<fetch>>), est désactivé par défaut (`fetchContentTool: true` pour l'activer, comme dans `agent.dmr.yaml`) : c'est le seul outil intégré qui accède au réseau. | ||
| 60 | + | ||
| 59 | Chaque outil déclaré coûte des tokens à chaque requête et une option de plus parmi lesquelles un petit modèle doit choisir. Moins il y en a, mieux il choisit. | 61 | Chaque outil déclaré coûte des tokens à chaque requête et une option de plus parmi lesquelles un petit modèle doit choisir. Moins il y en a, mieux il choisit. |
| 60 | 62 | ||
| 61 | === Des descriptions écrites pour être suivies | 63 | === Des descriptions écrites pour être suivies |
| @@ -66,6 +68,7 @@ Les descriptions d'outils ne décrivent pas seulement l'API, elles anticipent le | |||
| 66 | * `read_file` : « edit_file needs the EXACT text of the file … Do not type it from memory. » | 68 | * `read_file` : « edit_file needs the EXACT text of the file … Do not type it from memory. » |
| 67 | * `edit_file` : six règles *numérotées*, dont « do not switch to write_file to force the change through ». | 69 | * `edit_file` : six règles *numérotées*, dont « do not switch to write_file to force the change through ». |
| 68 | * `write_file` : rappelle qu'il écrase tout et renvoie vers `edit_file`. | 70 | * `write_file` : rappelle qu'il écrase tout et renvoie vers `edit_file`. |
| 71 | +* `fetch_content` : donne des exemples de demandes en plusieurs langues (« récupère le contenu de https://example.com »), avec la consigne « do not use curl or wget through bash for that ». | ||
| 69 | 72 | ||
| 70 | Le prompt système des configurations livrées (`agent.dmr.yaml`, `agent.llamacpp.yaml`) répète ces règles en sections courtes en majuscules (`SKILLS`, `FILE EDITING`, `RULES`, `BACKGROUND JOBS`). La redondance est voulue : un petit modèle suit mieux une consigne qu'il lit deux fois, à deux endroits. | 73 | Le prompt système des configurations livrées (`agent.dmr.yaml`, `agent.llamacpp.yaml`) répète ces règles en sections courtes en majuscules (`SKILLS`, `FILE EDITING`, `RULES`, `BACKGROUND JOBS`). La redondance est voulue : un petit modèle suit mieux une consigne qu'il lit deux fois, à deux endroits. |
| 71 | 74 | ||
| @@ -85,7 +88,8 @@ Commande en échec (`[exit code: …]`), délai dépassé (`[error: 30s timeout | |||
| 85 | Les messages sont rédigés comme des *consignes de réparation* : | 88 | Les messages sont rédigés comme des *consignes de réparation* : |
| 86 | 89 | ||
| 87 | * `read_skill` avec un nom inconnu répond `[skill: no skill named "x" — available: a, b, c]` ; | 90 | * `read_skill` avec un nom inconnu répond `[skill: no skill named "x" — available: a, b, c]` ; |
| 88 | -* `edit_file` avec un texte en double donne les numéros de ligne des occurrences et explique comment rendre `old` unique (`internal/fileedit/edits.go`). | 91 | +* `edit_file` avec un texte en double donne les numéros de ligne des occurrences et explique comment rendre `old` unique (`internal/fileedit/edits.go`) ; |
| 92 | +* `fetch_content` classe ses échecs en trois codes, `[fetch_content: error N (…) — raison]` : 1 = page non convertible, 2 = page inaccessible (hôte, statut HTTP, `robots.txt`), 3 = argument invalide. La description dit au modèle que le code 3 signifie « corrige ton appel », pour qu'il ne s'acharne pas sur un site en panne. | ||
| 89 | 93 | ||
| 90 | La seule exception est volontaire : l'arrêt par le détecteur de boucle (voir <<boucles>>). | 94 | La seule exception est volontaire : l'arrêt par le détecteur de boucle (voir <<boucles>>). |
| 91 | 95 | ||
| @@ -193,7 +197,7 @@ Test réel sur Docker Model Runner avec Mellum 12B, `max_tokens` volontairement | |||
| 193 | * le mécanisme fonctionne : le modèle reprend la main deux fois, puis le message clair s'affiche ; | 197 | * le mécanisme fonctionne : le modèle reprend la main deux fois, puis le message clair s'affiche ; |
| 194 | * *le modèle a ignoré la consigne* les deux fois et a retenté le fichier entier, même avec un budget chiffré en caractères. | 198 | * *le modèle a ignoré la consigne* les deux fois et a retenté le fichier entier, même avec un budget chiffré en caractères. |
| 195 | 199 | ||
| 196 | -La relance rend l'échec lisible et laisse une chance aux modèles qui suivent les instructions. Elle ne remplace pas un `max_tokens` adapté : 16 384 est une valeur raisonnable pour un modèle « thinking », avec une marge sous la fenêtre de contexte. Voir aussi la piste <<p15>>. | 200 | +La relance rend l'échec lisible et laisse une chance aux modèles qui suivent les instructions. Elle ne remplace pas un `max_tokens` adapté : 16 384 est une valeur raisonnable pour un modèle « thinking », avec une marge sous la fenêtre de contexte. Les configurations de `config.samples/` montent à 32 768 (voir <<p13>>), alors que `agent.dmr.yaml` et `agent.llamacpp.yaml` restent à 4 096. Voir aussi la piste <<p15>>. |
| 197 | 201 | ||
| 198 | == Modèles à raisonnement | 202 | == Modèles à raisonnement |
| 199 | 203 | ||
| @@ -208,6 +212,17 @@ Le greffon OpenAI de Genkit ignore `reasoning_content`. `mm` le lit lui-même, u | |||
| 208 | 212 | ||
| 209 | `truncate` limite chaque sortie d'outil à `maxOutput` caractères en conservant *le début et la fin* (la fin porte souvent l'erreur ou le résumé d'une commande). `bash` ne relit jamais plus d'1 Mio par extrémité depuis le disque. | 213 | `truncate` limite chaque sortie d'outil à `maxOutput` caractères en conservant *le début et la fin* (la fin porte souvent l'erreur ou le résumé d'une commande). `bash` ne relit jamais plus d'1 Mio par extrémité depuis le disque. |
| 210 | 214 | ||
| 215 | +[[fetch]] | ||
| 216 | +=== Une page web qui ne passe pas par le contexte | ||
| 217 | + | ||
| 218 | +`fetch_content` (`internal/tools/fetchcontent.go`, conversion dans `internal/webmd`) récupère une page et la rend en Markdown, après avoir retiré les scripts, la navigation, les publicités et les bandeaux de cookies. Trois choix visent directement les petits modèles : | ||
| 219 | + | ||
| 220 | +* *Enregistrer sans afficher.* Avec `output`, le Markdown est écrit dans le fichier et l'outil ne renvoie qu'une ligne (`[fetch_content: saved N lines … — the content is not shown]`). « Sauve-le dans hello.txt, ne l'affiche pas » ne coûte donc pas une page entière de contexte, et le modèle n'a pas de texte à recopier. | ||
| 221 | +* *Une URL mal tapée est réparée.* `NormalizeURL` (`internal/webmd/fetch.go`) complète un nom de site sans schéma (`k33g.org` → `https://k33g.org`) et corrige un schéma sans deux-points (`https//k33g.org`), faute fréquente quand le modèle recopie la demande. | ||
| 222 | +* *Une page vide est signalée, pas enregistrée* : le modèle ne confirme pas l'enregistrement d'un fichier vide. | ||
| 223 | + | ||
| 224 | +Sans `output`, la page passe par `truncate`, comme toute sortie d'outil. Vérifié le 29/09/2026 avec Mellum 12B (`mm -p`, Docker Model Runner) : pour « récupère le contenu de https//k33g.org », puis la même demande avec « ne l'affiche pas et sauve-le dans hello.txt », le modèle a choisi `fetch_content` les deux fois, a écrit le fichier et n'a pas recopié son contenu. | ||
| 225 | + | ||
| 211 | === Une compression hybride | 226 | === Une compression hybride |
| 212 | 227 | ||
| 213 | `internal/compact` remplace les vieux tours par *un* résumé écrit par le modèle et garde les `keepLastTurns` derniers tours intacts (le modèle travaille sur eux). Points notables : | 228 | `internal/compact` remplace les vieux tours par *un* résumé écrit par le modèle et garde les `keepLastTurns` derniers tours intacts (le modèle travaille sur eux). Points notables : |
| @@ -242,7 +257,7 @@ Un petit modèle choisit mal une procédure sur son seul nom. `internal/skills` | |||
| 242 | 257 | ||
| 243 | == Une méthode : mesurer | 258 | == Une méthode : mesurer |
| 244 | 259 | ||
| 245 | -La plupart des décisions sont justifiées dans le code par une *mesure datée* (« measured on qwen3.5-2b », « the demo audit of 2026-09-18 », « ticket 27 »). Le reste de `mm` est testé contre un moteur factice (rapide, déterministe) ; seul le routage des skills, qui est une propriété du modèle, est mesuré contre un vrai modèle. Garder cette discipline est la meilleure garantie que les améliorations ci-dessous en soient vraiment. | 260 | +La plupart des décisions sont justifiées dans le code par une *mesure datée* (« measured on qwen3.5-2b », « the demo audit of 2026-09-18 », « ticket 27 »). Le reste de `mm` est testé contre un moteur factice (rapide, déterministe) ; seul le routage des skills, qui est une propriété du modèle, est mesuré contre un vrai modèle. Depuis le 27/09/2026, chaque fichier de session enregistre `provider` et `model`, et chaque erreur le modèle qui l'a produite (`internal/store`). Une session qui a échoué peut donc être rattachée au modèle en cause, même quand on en change en cours de route. Garder cette discipline est la meilleure garantie que les améliorations ci-dessous en soient vraiment. |
| 246 | 261 | ||
| 247 | [[pistes]] | 262 | [[pistes]] |
| 248 | == Pistes d'amélioration | 263 | == Pistes d'amélioration |
| @@ -336,9 +351,28 @@ Le cas voisin des arguments qui ne sont pas du JSON valide (JSON coupé par `max | |||
| 336 | 351 | ||
| 337 | *Constat.* Mesuré sur `agent.dmr.yaml` : la première requête d'une session pèse ≈ 3,4k tokens avant toute question (prompt système ≈ 3,7k caractères, six descriptions d'outils et leurs schémas, catalogue de skills). La description de `plan` à elle seule fait ≈ 1,3k caractères, pour un outil utile seulement aux demandes en plusieurs étapes. | 352 | *Constat.* Mesuré sur `agent.dmr.yaml` : la première requête d'une session pèse ≈ 3,4k tokens avant toute question (prompt système ≈ 3,7k caractères, six descriptions d'outils et leurs schémas, catalogue de skills). La description de `plan` à elle seule fait ≈ 1,3k caractères, pour un outil utile seulement aux demandes en plusieurs étapes. |
| 338 | 353 | ||
| 354 | +Cette mesure date d'avant `fetch_content`. Le 30/09/2026, la première requête de `mm -p hello` avec `agent.dmr.yaml` a été capturée par un faux serveur OpenAI, avec et sans `fetchContentTool` : | ||
| 355 | + | ||
| 356 | +[cols="2,1,1,1",options="header"] | ||
| 357 | +|=== | ||
| 358 | +| Élément (caractères) | Description | Schéma | Total | ||
| 359 | + | ||
| 360 | +| Prompt système | | | 3 436 | ||
| 361 | +| `edit_file` | 1 383 | 758 | 2 141 | ||
| 362 | +| `plan` | 1 335 | 842 | 2 177 | ||
| 363 | +| `fetch_content` | 1 037 | 1 068 | 2 105 | ||
| 364 | +| `read_skill` (catalogue de 7 skills) | 1 373 | 222 | 1 595 | ||
| 365 | +| `read_file` | 311 | 534 | 845 | ||
| 366 | +| `bash` | 575 | 164 | 739 | ||
| 367 | +| `write_file` | 348 | 307 | 655 | ||
| 368 | +| *Requête entière* (JSON) | | | *14 993* (12 762 sans `fetch_content`) | ||
| 369 | +|=== | ||
| 370 | + | ||
| 371 | +Les outils pèsent trois fois le prompt système (10 257 caractères contre 3 436). `fetch_content` ajoute 2 231 caractères à la requête, soit +17 %. À ≈ 3,4k tokens pour la version à six outils, cela fait ≈ 4k tokens. Ce chiffre est une estimation par proportion : le compte exact du serveur reste à relever. Le schéma de `fetch_content` est le plus lourd des sept, à cause des descriptions de ses quatre paramètres optionnels (`baseUrl`, `tables`, `strikethrough`, `taskList`). | ||
| 372 | + | ||
| 339 | *Proposition.* | 373 | *Proposition.* |
| 340 | 374 | ||
| 341 | -* Condenser la description de `plan` (l'exemple de workflow en sept étapes pourrait passer dans un skill), ou désactiver `planTool` par défaut dans les configurations pour petits modèles. | 375 | +* Condenser la description de `plan` (l'exemple de workflow en sept étapes pourrait passer dans un skill), ou désactiver `planTool` par défaut dans les configurations pour petits modèles. La même question se pose pour `fetchContentTool` sur les petites fenêtres, et pour les paramètres optionnels de `fetch_content`, qu'un petit modèle n'utilise presque jamais. |
| 342 | * Éviter les doublons entre prompt système et descriptions quand ils ne servent pas. | 376 | * Éviter les doublons entre prompt système et descriptions quand ils ne servent pas. |
| 343 | * Mesurer chaque retrait avec `internal/eval` : la redondance est parfois ce qui fait marcher un 4B. | 377 | * Mesurer chaque retrait avec `internal/eval` : la redondance est parfois ce qui fait marcher un 4B. |
| 344 | 378 | ||
| @@ -401,7 +435,7 @@ Sur une machine locale, un préfixe en cache fait la différence entre une répo | |||
| 401 | [[p13]] | 435 | [[p13]] |
| 402 | === Profils par modèle | 436 | === Profils par modèle |
| 403 | 437 | ||
| 404 | -*Constat.* Les réglages utiles varient d'une famille à l'autre : pénalité de répétition, `top_k`, `min_p`, gestion du rôle `system`, longueur de prompt supportée. `tests/` contient déjà des variantes par modèle (`agent.dmr-qwen.yaml`, `agent.dmr-gemma.yaml`). | 438 | +*Constat.* Les réglages utiles varient d'une famille à l'autre : pénalité de répétition, `top_k`, `min_p`, gestion du rôle `system`, longueur de prompt supportée. `tests/` contient déjà des variantes par modèle (`agent.dmr-qwen.yaml`, `agent.dmr-gemma.yaml`). Depuis le 28/09/2026, `config.samples/` en ajoute cinq, complètes, pour des modèles plus gros : Gemma 4 26B-A4B, gpt-oss 20B, Qwen3.6 35B-A3B (DMR), Ornith 1.5 35B-A3B et Qwen3.8 27B (llama-server). Toutes fixent `max_tokens: 32768`, `watchdogTimeout: 300s` et `summaryMaxTokens: 1200`. Ce sont des profils de fait, mais recopiés à la main : chaque changement de la configuration de base est à reporter dans chacun des fichiers (`fetchContentTool: true` y a été ajouté à la main le 30/09/2026). |
| 405 | 439 | ||
| 406 | *Proposition.* Une clé `profile:` (ou un fichier de profils) qui applique des valeurs par défaut connues par famille de modèle, surchargées par le YAML. | 440 | *Proposition.* Une clé `profile:` (ou un fichier de profils) qui applique des valeurs par défaut connues par famille de modèle, surchargées par le YAML. |
| 407 | 441 | ||
| @@ -448,5 +482,8 @@ Sur une machine locale, un préfixe en cache fait la différence entre une répo | |||
| 448 | | Compression | `internal/compact/` | 482 | | Compression | `internal/compact/` |
| 449 | | Skills et catalogue | `internal/skills/`, `skills/` | 483 | | Skills et catalogue | `internal/skills/`, `skills/` |
| 450 | | Évaluation du routage | `internal/eval/` | 484 | | Évaluation du routage | `internal/eval/` |
| 485 | +| Page web en Markdown (`fetch_content`) | `internal/tools/fetchcontent.go`, `internal/webmd/` | ||
| 486 | +| Sessions (fournisseur et modèle enregistrés) | `internal/store/store.go` | ||
| 487 | +| Configurations par modèle | `config.samples/`, `tests/` | ||
| 451 | | Explications d'erreurs | `internal/engine/explain.go`, `internal/engine/openai_compat.go` | 488 | | Explications d'erreurs | `internal/engine/explain.go`, `internal/engine/openai_compat.go` |
| 452 | |=== | 489 | |=== |