« Hermes » : différence entre les versions
Autres actions
Balise : Révoqué |
|||
| (315 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
[https://hermesatlas.com/ Hermes Atlas] | |||
= Prérequis = | = Prérequis = | ||
(Hermes seul) | (Hermes seul) | ||
* Une machine ou VM dédiée (LXC compatible) | * Une machine ou VM dédiée (LXC compatible / VM recommandée) | ||
Pour un Hermes de base (sans LLM local) : | Pour un Hermes de base (sans LLM local) : | ||
* RAM : | * RAM : | ||
| Ligne 15 : | Ligne 16 : | ||
* GPU : | * GPU : | ||
** Inutile | ** Inutile | ||
= Installation Hermes (service dédié) = | = Installation Hermes (service dédié) = | ||
| Ligne 39 : | Ligne 41 : | ||
Display name [192.168.2.216:11434]: <font color = blue>Ollama</font> | Display name [192.168.2.216:11434]: <font color = blue>Ollama</font> | ||
----- | |||
* Llama.cpp : | |||
<font color = gold>Select provider:</font> | |||
><font color = lightgreen>(○) Custom endpoint (enter URL manually)</font> | |||
Custom OpenAI-compatible endpoint configuration: | |||
API base URL [e.g. <nowiki>https://</nowiki>api.example.com/v1]: http<font color = red>s</font>://<font color = blue>IP_OLLAMA</font>:<font color = green>11434</font>/v1 | |||
----- | ----- | ||
Remplir les options désirées puis fin de l'installation : | Remplir les options désirées puis fin de l'installation : | ||
| Ligne 51 : | Ligne 60 : | ||
# systemctl enable hermes-gateway.service | # systemctl enable hermes-gateway.service | ||
# systemctl start hermes-gateway.service | # systemctl start hermes-gateway.service | ||
== Configuration == | == Configuration == | ||
=== Activer le serveur API === | |||
On édite le fichier : | On édite le fichier : | ||
# vi ~/.hermes/.env | # vi ~/.hermes/.env | ||
| Ligne 67 : | Ligne 77 : | ||
| niveau = grave | | niveau = grave | ||
| icône = grave | | icône = grave | ||
| texte = Si API_SERVER_HOST=0.0.0.0 : | | texte = Si <code>API_SERVER_HOST=0.0.0.0</code> : l’API est accessible sur le réseau. Définir impérativement une clé <code>API_SERVER_KEY</code> longue et aléatoire, au minimum 16 caractères, idéalement générée avec <code>openssl rand -hex 32</code>. Limiter aussi l’accès via firewall ou réseau privé recommandé. | ||
}} | |||
On relance le service : | On relance le service : | ||
# systemctl restart hermes-gateway.service | # systemctl restart hermes-gateway.service | ||
| Ligne 77 : | Ligne 87 : | ||
Pour vérifier le modèle exposé : | Pour vérifier le modèle exposé : | ||
# curl http://<font color = blue>IP_HERMES</font>:8642/v1/models -H "Authorization: Bearer <font color = blue>maclefsecrete</font>" | # curl http://<font color = blue>IP_HERMES</font>:8642/v1/models -H "Authorization: Bearer <font color = blue>maclefsecrete</font>" | ||
=== Retarder le démarrage de Hermes au boot pour laisser le temps aux autres services de se lancer === | |||
# systemctl edit hermes-gateway.service | |||
Ajouter dans la zone d’édition (partie supérieure du fichier) : | |||
<font color = grey>...</font> | |||
<font color = grey>### Anything between here and the comment below will become the contents of the drop-in file</font> | |||
<font color = blue>[Service] | |||
ExecStartPre=/bin/sh -c 'uptime=$(cut -d. -f1 /proc/uptime); [ "$uptime" -lt 120 ] && sleep 30 || true'</font> | |||
<font color = grey>### Edits below this comment will be discarded</font> | |||
<font color = grey>...</font> | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = | |||
Cette commande ajoute une pause de 30 secondes uniquement si la machine a démarré depuis moins de 120 secondes. | |||
Cela permet d’éviter que Hermes tente de se connecter trop tôt à certains services encore en cours de démarrage. | |||
}} | |||
=== Activer le backend Hermes === | |||
Le backend Hermes expose les API utilisées notamment par le Dashboard, [[Hermes#Hermes_Workspace|Hermes Worspace]], [https://hermes-ai.net/desktop/ Hermes Desktop], les sessions, skills, configuration, jobs et certaines fonctions MCP. | |||
La commande <code>hermes serve</code> permet de lancer ce backend en mode headless, sans ouvrir l'interface web du Dashboard. | |||
Avant de modifier la configuration, on génère le hash du mot de passe qui sera utilisé pour l’authentification : | |||
# python3 -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('<font color = blue>MON_MOT_DE_PASSE</font>'))" | |||
La commande retourne une valeur de la forme : | |||
scrypt$16384$8$1$... | |||
On génère ensuite le secret utilisé pour signer les sessions : | |||
# openssl rand -hex 32 | |||
On édite alors le fichier : | |||
# vi ~/.hermes/.env | |||
Ajouter : | |||
<font color = grey>...</font> | |||
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=<font color = blue>admin</font> | |||
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH="<font color = blue>scrypt$16384$8$1$...</font>" | |||
HERMES_DASHBOARD_BASIC_AUTH_SECRET="<font color = blue>secret_généré_par_openssl</font>" | |||
<font color = grey>...</font> | |||
{{Méta bandeau | |||
| niveau = grave | |||
| icône = grave | |||
| texte = Le backend Hermes donne accès à des fonctions sensibles. Dès qu’il écoute sur une interface réseau autre que <code>127.0.0.1</code>, Hermes active la protection par authentification. Utiliser un mot de passe fort et limiter également l’accès au port <code>9119</code> via firewall ou réseau privé. | |||
}} | |||
On crée un service systemd pour lancer automatiquement le backend après Hermes Gateway : | |||
# vi /etc/systemd/system/hermes-backend.service | |||
Ajouter : | |||
[Unit] | |||
Description=Hermes Backend | |||
Requires=hermes-gateway.service | |||
After=hermes-gateway.service | |||
[Service] | |||
Type=simple | |||
User=root | |||
Environment=HOME=/root | |||
EnvironmentFile=/root/.hermes/.env | |||
WorkingDirectory=/root | |||
ExecStartPre=/bin/sh -c 'until /usr/bin/curl -fsS <nowiki>http://</nowiki><font color = blue>IP_GATEWAY_HERMES</font>:<font color = green>8642</font>/health >/dev/null; do sleep 1; done' | |||
ExecStart=/root/.local/bin/hermes serve --host <font color = blue>IP_BACKEND_HERMES</font> --port <font color = green>9119</font> | |||
Restart=on-failure | |||
RestartSec=5 | |||
[Install] | |||
WantedBy=multi-user.target | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = Remplacer <code><font color = blue>IP_GATEWAY_HERMES</font></code> par l’adresse à laquelle le Gateway Hermes est accessible.<br> | |||
Remplacer <code><font color = blue>IP_BACKEND_HERMES</font></code> par l’adresse locale de l’interface réseau sur laquelle le backend doit écouter. Utiliser une adresse précise plutôt que <code>0.0.0.0</code> permet de limiter son exposition au réseau souhaité. | |||
}} | |||
On active le plugin pour authentifier le dashboard : | |||
# hermes plugins enable dashboard_auth/basic | |||
On recharge la configuration systemd : | |||
# systemctl daemon-reload | |||
On active le service au démarrage : | |||
# systemctl enable hermes-backend.service | |||
On le démarre : | |||
# systemctl start hermes-backend.service | |||
Pour vérifier son état : | |||
# systemctl status hermes-backend.service | |||
Pour suivre les logs : | |||
# journalctl -u hermes-backend.service -f | |||
Pour vérifier que le backend écoute : | |||
# ss -lntp | grep 9119 | |||
Pour tester son API : | |||
# curl <nowiki>http://</nowiki>IP_HERMES:9119/api/status | |||
Pour ouvrir l'interface web d'administration, on peut toujours utiliser : | |||
# hermes dashboard --host <font color = blue>IP_DASHBOARD</font> --port <font color = green>9119</font> --no-open | |||
=== Utiliser une CA privée avec Hermes === | |||
Si Hermes doit se connecter à un service HTTPS signé par une CA privée locale, il peut être nécessaire d’indiquer explicitement à Python et aux bibliothèques HTTP quel bundle de certificats utiliser. | |||
Éditer l’override systemd du service : | |||
# systemctl edit hermes-gateway.service | |||
Ajouter dans la zone d’édition (partie supérieure du fichier) : | |||
<font color = grey>...</font> | |||
<font color = grey>### Anything between here and the comment below will become the contents of the drop-in file</font> | |||
<font color = blue>[Service] | |||
Environment="SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" | |||
Environment="REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" | |||
Environment="CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt"</font> | |||
<font color = grey>### Edits below this comment will be discarded</font> | |||
<font color = grey>...</font> | |||
Explication rapide : | |||
* <code>SSL_CERT_FILE</code> : utilisé par Python / OpenSSL | |||
* <code>REQUESTS_CA_BUNDLE</code> : utilisé par la bibliothèque Python <code>requests</code> | |||
* <code>CURL_CA_BUNDLE</code> : utilisé par <code>curl</code> et parfois comme variable de repli | |||
Puis recharger et redémarrer le service : | |||
# systemctl daemon-reload | |||
# systemctl restart hermes-gateway.service | |||
==== Cas particulier : bundle certifi du venv Hermes ==== | |||
Dans certains cas, le runtime Python embarqué par Hermes peut continuer à utiliser le bundle interne de certifi au lieu du magasin système. | |||
Si curl valide déjà le certificat avec /etc/ssl/certs/ca-certificates.crt mais que Hermes/OpenAI/httpx échoue avec CERTIFICATE_VERIFY_FAILED, on peut remplacer le bundle certifi du venv Hermes par le bundle système. | |||
Sauvegarder le bundle actuel : | |||
# cp /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem.bak | |||
Remplacer par le bundle système : | |||
# cp /etc/ssl/certs/ca-certificates.crt /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem | |||
Attention : cette modification peut être écrasée lors d’une mise à jour de Hermes, du venv Python ou du paquet certifi. | |||
===== Automatiser le remplacement du certificat du venv ===== | |||
On édite le service Hermes : | |||
# systemctl edit hermes-gateway.service | |||
Ajouter dans la zone d’édition (partie supérieure du fichier) : | |||
<font color = grey>...</font> | |||
<font color = grey>### Anything between here and the comment below will become the contents of the drop-in file</font> | |||
<font color = blue>[Service] | |||
ExecStartPre=/bin/cp /etc/ssl/certs/ca-certificates.crt /root/.hermes/hermes-agent/venv/lib/python<font color = green>3.11</font>/site-packages/certifi/cacert.pem</font> | |||
<font color = grey>### Edits below this comment will be discarded</font> | |||
<font color = grey>...</font> | |||
Puis recharger systemd et redémarrer le service : | |||
# systemctl daemon-reload | |||
# systemctl restart hermes-gateway.service | |||
=== Éditer le prompt système === | |||
On édite le fichier suivant : | |||
# vi ~/.hermes/SOUL.md | |||
Puis on modifie le contenu de <code>SOUL.md</code>, qui constitue la partie personnalisée du prompt système de Hermes, par exemple : | |||
<font color = grey>You are Hermes Agent, an intelligent AI assistant created by Nous Research. You are helpful, knowledgeable, and direct. You assist users with a wide range of tasks including answering questions, writing and editing code, analyzing information, creative work, and executing actions via your tools. You communicate clearly, admit uncertainty when appropriate, and prioritize being genuinely useful over being verbose unless otherwise directed below. Be targeted and efficient in your exploration and investigations.</font> | |||
TOOLS: | |||
- For current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions, use searxng_web_search. | |||
- To read a specific URL, use web_url_read. | |||
- For search suggestions, use searxng_search_suggestions. | |||
- For SearXNG instance capabilities, categories, engines, locales, and plugins, use searxng_instance_info. | |||
- For indexed documents, internal documentation, knowledge bases, or when the user asks to check the docs, use the RAGFlow MCP tools: ragflow_retrieval, ragflow_list_datasets, and ragflow_list_chats. | |||
RULES: | |||
- Respond in the same language as the user. | |||
- Do not invent tool results. | |||
- If a tool fails, say so explicitly. | |||
- Do not promise to continue later, follow up later, or say that results are still coming. | |||
- When the user asks multiple questions, use the tools needed, then answer all requested items in one final structured response. | |||
- Never answer current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions without using the required tool first. | |||
- This includes weather, news, prices, schedules, releases, availability, rankings, versions, and other facts that may have changed. | |||
- If no tool result is available, say you cannot verify and do not guess. | |||
- Use search categories when relevant. | |||
- For image searches, use searxng_web_search with categories=images. | |||
- For video searches, use searxng_web_search with categories=videos. | |||
- For image search results, use the `img_src` field as the direct image URL. | |||
- When displaying an image result, ALWAYS output the direct image URL exactly in this format:  | |||
- Do not output the image URL as a normal Markdown link. | |||
- For video results, output links in this format: ~_~N [Titre de la vidéo](URL) | |||
- Do not use tools for simple rewriting, translation, or opinion unless needed. | |||
- Do not use terminal/curl to query RAGFlow unless explicitly asked for a network diagnostic. | |||
- If no RAGFlow dataset exists or no relevant result is found, say so clearly. | |||
Enfin, on redémarre le service : | |||
# systemctl restart hermes-gateway.service | |||
=== Installer les dépendances pour la voix du CLI === | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = | |||
Cette étape est utile uniquement si le CLI est exécuté localement sur le serveur Hermes Agent, avec un microphone et des haut-parleurs accessibles. | |||
}} | |||
# cd ~/.hermes/hermes-agent | |||
# uv pip install --python ./venv/bin/python -e ".[voice]" | |||
# apt update | |||
# apt install libportaudio2 | |||
==== LXC ==== | |||
Voir [[Audio_Passthrough|audio passthrough]] | |||
=== Signal === | |||
Signal est une messagerie instantanée axée sur la confidentialité. | |||
Tous les messages et appels y sont chiffrés de bout en bout par défaut via le Signal Protocol, de sorte que ni Signal ni un tiers ne peuvent en lire le contenu. Signal se distingue également par une collecte de données très limitée, l’absence de publicité et de traqueurs, ainsi qu’un effort particulier pour réduire les métadonnées accessibles au service. | |||
Signal permet de relier Hermes à la messagerie chiffrée Signal. | |||
La connexion ne se fait pas directement avec le téléphone, mais via <code>signal-cli</code> exécuté en mode daemon HTTP, auquel Hermes se connecte ensuite. | |||
* Installation : | |||
==== Via [[Docker|Docker]] ==== | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = Installation séparée (Docker sur autre machine) : Les images et fichiers audio générés par Hermes ne peuvent pas être envoyés en pièces jointes natives, signal-cli n'a pas accès au cache local de Hermes (/root/.hermes/image_cache/). Seules les URLs brutes seront transmises. | |||
Pour les pièces jointes natives (images, audio TTS, vidéos), installer signal-cli sur le même serveur qu'Hermes via [[Hermes#Native|l'installation native]]. | |||
}} | |||
<div class="mw-collapsible mw-collapsed" style="text-align:left;"> | |||
'''Procédure d'installation via <code>Docker</code> (non recommandée)''' | |||
<div class="mw-collapsible-content"> | |||
# mkdir -p /opt/signal-cli | |||
# vi /opt/signal-cli/docker-compose.yml | |||
services: | |||
signal-cli: | |||
image: registry.gitlab.com/packaging/signal-cli/signal-cli-jre:latest | |||
container_name: signal-cli | |||
restart: unless-stopped | |||
command: daemon --http 0.0.0.0:8080 | |||
ports: | |||
- "<font color = blue>IP_SERVEUR</font>:8080:8080" # Remplacer par IP du serveur, ou 127.0.0.1 pour restreindre acces local uniquement | |||
volumes: | |||
- signal-cli-data:/var/lib/signal-cli | |||
tmpfs: | |||
- /tmp:exec | |||
volumes: | |||
signal-cli-data: | |||
# docker compose -f /opt/signal-cli/docker-compose.yml --project-directory /opt/signal-cli up -d | |||
* Connexion au téléphone : | |||
Installer <code>qrencode</code> : | |||
# apt install qrencode | |||
Dans le terminal : | |||
# docker exec signal-cli signal-cli link -n "<font color = blue>HermesAgent</font>" > /tmp/signal-link.txt 2>&1 & sleep 3 && grep -o 'sgnl://[^ ]*' /tmp/signal-link.txt | qrencode -t ANSIUTF8 && wait | |||
Puis scanner le QR code avec l’application Signal via <code>Paramètres</code> -> <code>Appareils associés</code>. | |||
* Connecter Hermes à Signal : | |||
# hermes setup | |||
<font color = gold>Connect a messaging platform? (Telegram, Discord, etc.)</font> | |||
-> <font color = lightgreen>●) Set up messaging now (recommended)</font> | |||
Puis redémarrer le service : | |||
# systemctl restart hermes-gateway.service | |||
* Communiquer avec le serveur via Signal (depuis le téléphone dans l'application Signal) : | |||
** Appuyer sur l’icône ✏️ (nouveau message) | |||
** Tout en haut de la liste, "Note to Self" ou votre propre nom apparaît | |||
** Taper votre message : Hermes répond dans cette même conversation | |||
** (Optionnel) taper <code>/sethome</code> pour définir le canal par défaut pour les notifications et les tâches planifiées. | |||
</div> | |||
</div> | |||
==== Native ==== | |||
* Installation : | |||
On installe les dépendances si nécessaire : | |||
# apt update && apt upgrade | |||
# apt install tar qrencode openjdk-<font color = green>25</font>-jre-headless | |||
On s'assure que Java 25 est la version utilisée par défaut : | |||
# update-alternatives --set java /usr/lib/jvm/java-25-openjdk-amd64/bin/java | |||
# java -version | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = Si <code>signal-cli --version</code> retourne une erreur <code>UnsupportedClassVersionError</code>, vérifier la version de Java actuellement utilisée avec <code>java -version</code>. Installer si nécessaire la version requise avec <code>apt install openjdk-XX-jre-headless</code>, puis la sélectionner avec <code>update-alternatives --config java</code>. | |||
}} | |||
On Installe le programme : | |||
# cd /tmp | |||
# VERSION=$(curl -Ls -o /dev/null -w %{url_effective} <nowiki>https://</nowiki>github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//') | |||
# curl -L -O "<nowiki>https://</nowiki>github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz" | |||
# tar xf "signal-cli-${VERSION}.tar.gz" -C /opt | |||
# ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/ | |||
# rm /tmp/signal-cli-${VERSION}.tar.gz | |||
Appareillage du téléphone : | |||
# signal-cli link -n "HermesAgent" > /tmp/signal-link.txt 2>&1 & sleep 5 && grep -o 'sgnl://[^ ]*' /tmp/signal-link.txt | qrencode -t ANSIUTF8 && wait | |||
Puis scanner le QR code avec l’application Signal via <code>Paramètres</code> -> <code>Appareils associés</code>. | |||
On créé un service : | |||
# vi /etc/systemd/system/signal-cli.service | |||
[Unit] | |||
Description=signal-cli daemon | |||
After=network.target | |||
[Service] | |||
Environment="JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64" | |||
ExecStart=/usr/local/bin/signal-cli --account +<font color = blue>VOTRE_NUMERO</font> daemon --http 127.0.0.1:8080 | |||
Restart=always | |||
RestartSec=5 | |||
[Install] | |||
WantedBy=multi-user.target | |||
# systemctl daemon-reload | |||
# systemctl enable --now signal-cli | |||
# systemctl status signal-cli | |||
* Connecter Hermes à Signal : | |||
# hermes setup | |||
<font color = gold>Connect a messaging platform? (Telegram, Discord, etc.)</font> | |||
-> <font color = lightgreen>●) Set up messaging now (recommended)</font> | |||
Puis redémarrer le service : | |||
# systemctl restart hermes-gateway.service | |||
* Communiquer avec le serveur via Signal (depuis le téléphone dans l'application Signal) : | |||
** Appuyer sur l’icône ✏️ (nouveau message) | |||
** Tout en haut de la liste, "Note to Self" ou votre propre nom apparaît | |||
** Taper votre message : Hermes répond dans cette même conversation | |||
** (Optionnel) taper <code>/sethome</code> pour définir le canal par défaut pour les notifications et les tâches planifiées. | |||
==== Mise à jour automatique ==== | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = Il est recommandé de mettre à jour l'application Signal au moins tous les trois mois. | |||
}} | |||
* Version native : | |||
On créé un script : | |||
# vi /usr/local/bin/update-signal-cli.sh | |||
#!/bin/bash | |||
set -e | |||
systemctl stop signal-cli || true | |||
cd /tmp | |||
VERSION=$(curl -Ls -o /dev/null -w '%{url_effective}' <nowiki>https://</nowiki>github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//') | |||
curl -L -O "<nowiki>https://</nowiki>github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz" | |||
rm -rf "/opt/signal-cli-${VERSION}" | |||
tar xf "signal-cli-${VERSION}.tar.gz" -C /opt | |||
ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/signal-cli | |||
rm -f "/tmp/signal-cli-${VERSION}.tar.gz" | |||
# Vérifier la compatibilité Java | |||
if ! signal-cli --version > /dev/null 2>&1; then | |||
ERROR="$(signal-cli --version 2>&1 || true)" | |||
echo "$ERROR" | |||
REQUIRED="$(echo "$ERROR" | grep -oE 'class file (version|major version) [0-9]+' | grep -oE '[0-9]+' | tail -n1 || true)" | |||
if [ -z "$REQUIRED" ]; then | |||
echo "Impossible de détecter automatiquement la version Java requise." | |||
echo "Installation de Java 21 par défaut..." | |||
JAVA_VERSION=21 | |||
else | |||
JAVA_VERSION=$((REQUIRED - 44)) | |||
echo "Class file version $REQUIRED détectée => Java $JAVA_VERSION requis." | |||
fi | |||
apt update | |||
apt install -y "openjdk-${JAVA_VERSION}-jre-headless" | |||
if [ -x "/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64/bin/java" ]; then | |||
update-alternatives --set java "/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64/bin/java" | |||
else | |||
echo "Java $JAVA_VERSION installé, mais chemin update-alternatives non trouvé. Vérifie avec :" | |||
echo "update-alternatives --config java" | |||
fi | |||
fi | |||
systemctl start signal-cli | |||
# chmod +x /usr/local/bin/update-signal-cli.sh | |||
On ajoute le script au crontab : | |||
# crontab -e | |||
Ajouter : | |||
<font color = grey>...</font> | |||
0 3 1 * * /usr/local/bin/update-signal-cli.sh | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = | |||
* 0 → minute 0 | |||
* 3 → 3h du matin | |||
* 1 → le 1er du mois | |||
* * → tous les mois | |||
* * → peu importe le jour de la semaine | |||
}} | |||
* Version docker : | |||
Voir [[Watchtower]] pour la mise à jour automatique de tous les containers Docker. (tuto à faire..) | |||
=== SearXNG === | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = information | |||
| texte = L’intégration native de SearXNG dans Hermes Agent convient aux recherches web classiques et offre une configuration plus simple. Pour un accès plus complet aux fonctions de SearXNG, notamment aux catégories images, vidéos, actualités et à certains paramètres avancés, il est préférable d’utiliser [[Hermes#SearXNG_2|le serveur MCP SearXNG]]. | |||
}} | |||
Il faut d’abord avoir [[SearXNG|installé une instance SearXNG]]. | |||
Sur le serveur Hermes, lancer : | |||
# hermes tools | |||
→ (○) Reconfigure an existing tool's provider or API key | |||
→ (○) 🔍 Web Search & Scraping | |||
→ (●) SearXNG [free · self-hosted] — Free, privacy-respecting metasearch. Point SEARXNG_URL at your instance. [active] | |||
Entrer ensuite l’adresse de l’instance SearXNG : | |||
SearXNG instance URL (e.g. <nowiki>http://</nowiki>localhost:8080) (Enter to keep current): | |||
=== Scraping via Firecrawl === | |||
Il faut d’abord avoir [[Firecrawl|installé une instance Firecrawl]]. | |||
On renseigne l'adresse de l'instance Firecrawl : | |||
# vi ~/.hermes/.env | |||
<font color = grey>...</font> | |||
FIRECRAWL_API_URL=http://<font color = blue>IP_DE_FIRECRAWL</font>:<font color = green>3002</font> | |||
<font color = grey>...</font> | |||
Si besoin configurer l'API key : | |||
<font color = grey>...</font> | |||
FIRECRAWL_API_KEY=<font color = blue>c-xxxxxxxxxxxxxxxx</font> | |||
<font color = grey>...</font> | |||
Ensuite on édite la configuration de Hermes : | |||
# vi ~/.hermes/config.yaml | |||
On remplace : | |||
web: | |||
backend: searxng | |||
search_backend: '' | |||
extract_backend: '' | |||
Par : | |||
web: | |||
backend: searxng | |||
search_backend: searxng | |||
extract_backend: firecrawl | |||
Enfin on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== Camofox === | |||
==== Installation native ==== | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = | |||
Méthode recommandé mais déconseillé en cas d'utilisation conjointe avec le MCP SearXNG afin de pouvoir désactiver les outils web natifs de Hermes. | |||
}} | |||
Il faut d’abord avoir [[Camofox|installé une instance Camofox]]. | |||
Sur le serveur Hermes, lancer : | |||
# hermes tools | |||
→ (○) Reconfigure an existing tool's provider or API key | |||
→ (○) 🌐 Browser Automation | |||
→ (●) Camofox [free · local] — Anti-detection browser (Firefox/Camoufox) | |||
Entrer ensuite l’adresse de l’instance Camofox: | |||
Camofox server URL (Enter to keep current): | |||
* Règle prompt système facultative : | |||
<font color=grey>... | |||
RULES:</font> | |||
- If `web_extract` fails or is blocked, use `browser_navigate` through the Camofox browser provider. | |||
<font color=grey>...</font> | |||
==== Via MCP ==== | |||
Voir [[Hermes#MCP-CamoFox|MCP-CamoFox]] | |||
=== Forcer les timeouts d'une IA locale pour une IA derrière une URL === | |||
Si l'API de votre IA locale est desservie derrière une URL publique, Hermes peut ne pas la détecter comme un fournisseur local. Il est possible de modifier les timeouts utilisés pour les fournisseurs locaux : | |||
# vi ~/.hermes/.env | |||
<font color="grey">...</font> | |||
HERMES_API_TIMEOUT=1800 | |||
HERMES_STREAM_READ_TIMEOUT=1800 | |||
# HERMES_STREAM_STALE_TIMEOUT=180 | |||
HERMES_API_CALL_STALE_TIMEOUT=900 | |||
HERMES_AGENT_TIMEOUT=900 | |||
# systemctl restart hermes-gateway.service | |||
=== Fonctions auxiliaires === | |||
Configuration des modèles utilisés par Hermes pour les tâches secondaires, indépendamment du modèle principal de conversation. | |||
Editer la section <code>auxiliary</code> dans : | |||
# vi ~/.hermes/config.yaml | |||
* <code>vision</code> : analyse d’images (modèle multimodal avec vision) | |||
* <code>compression</code> : compression et résumé du contexte (LLM texte avec un contexte suffisamment long) | |||
* <code>skills_hub</code> : recherche et sélection de compétences (LLM texte léger) | |||
* <code>approval</code> : évaluation et validation des actions sensibles (LLM texte léger et fiable) | |||
* <code>mcp</code> : sélection et routage des outils MCP (LLM texte efficace en appel d’outils) | |||
* <code>title_generation</code> : génération de titres de conversations (petit LLM texte rapide) | |||
* <code>tts_audio_tags</code> : génération de balises expressives pour la synthèse vocale (LLM texte léger) | |||
* <code>triage_specifier</code> : génération d’une spécification détaillée à partir d’une tâche placée dans le Triage du Kanban (LLM texte léger) | |||
* <code>kanban_decomposer</code> : décomposition d’un projet en tâches Kanban (LLM texte avec de bonnes capacités de planification) | |||
* <code>profile_describer</code> : génération d’une description de profil (LLM texte) | |||
* <code>curator</code> : sélection et organisation du contenu (LLM texte avec de bonnes capacités de synthèse) | |||
* <code>monitor</code> : analyse des résultats de surveillance (LLM texte léger) | |||
* <code>background_review</code> : révision et analyse en arrière-plan (LLM texte) | |||
* <code>moa_reference</code> : production d’une réponse de référence pour le MoA (LLM texte performant) | |||
* <code>moa_aggregator</code> : agrégation et synthèse des réponses MoA (LLM texte performant avec un contexte long) | |||
* <code>memory_query_rewrite</code> : reformulation des requêtes destinées aux systèmes de mémoire afin d'améliorer la pertinence de la recherche (LLM texte léger) | |||
* <code>goal_judge</code> : évaluation de l'état d'un objectif actif afin de déterminer s'il est terminé, doit continuer ou doit attendre (LLM texte léger et fiable) | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = | |||
Dans les versions récentes de Hermes, <code>web_extract</code> n'utilise plus de modèle auxiliaire, <code>session_search</code> effectue directement ses recherches dans les sessions sans appel LLM et <code>flush_memories</code> a été supprimé. Ces trois anciennes entrées n'ont donc plus à être configurées dans <code>auxiliary</code>. | |||
}} | |||
==== Note sur vision et les modèles principaux multimodaux ==== | |||
Certains modèles principaux (ex. Qwen3.6-27B) sont '''nativement multimodaux''' (encodeur vision intégré au checkpoint) — ce n’est donc pas systématiquement une histoire de « modèle texte qui ne sait pas voir ». Même dans ce cas, garder <code>vision</code> sur un petit modèle auxiliaire séparé reste recommandé pour trois raisons : | |||
# Évite de mobiliser le modèle principal (VRAM + temps de calcul) pour une tâche que 4B suffit à traiter. | |||
# Le petit modèle peut se décharger automatiquement (<code>--sleep-idle-seconds</code>), pas forcément possible/souhaitable sur le principal. | |||
# Latence : un 4B répond bien plus vite qu’un 27B pour une simple description/OCR d’image. | |||
==== Recommandations ==== | |||
Dans une configuration locale disposant de peu de VRAM disponible, il est recommandé d’attribuer certaines fonctions auxiliaires à des modèles plus petits et plus rapides, afin d’éviter de mobiliser inutilement le modèle principal. | |||
* <code>vision</code> : fortement recommandé avec un modèle multimodal séparé (environ 3 à 4 milliards de paramètres ; par exemple Qwen2.5-VL-3B-Instruct, Qwen3-VL-4B-Instruct ou Gemma 3 4B). Un modèle quantifié en Q4 est généralement suffisant pour l’analyse d’images courante. '''Pour de l’OCR/transcription de texte dense''', augmenter <code>--image-min-tokens</code>/<code>--image-max-tokens</code> (ex. 2048/8192) et ajouter un <code>--repeat-penalty 1.1</code> pour éviter les boucles de génération sur du texte peu lisible à basse résolution. | |||
* <code>title_generation</code> : recommandé avec un petit modèle texte très rapide (environ 0,5 à 3 milliards de paramètres ; par exemple Qwen3 0.6B, 1.7B ou un modèle instruct équivalent). Tâche simple, ne nécessite pas un modèle puissant. | |||
* <code>compression</code> : recommandé avec un modèle texte disposant d’un contexte long et de bonnes capacités de résumé. Un petit modèle rapide peut convenir si sa qualité et sa fenêtre de contexte sont suffisantes. | |||
* <code>mcp</code> : petit modèle texte fiable en sélection/appel d’outils (environ 3 à 8 milliards de paramètres). Éviter les modèles extrêmement petits si plusieurs outils ont des descriptions proches. | |||
* <code>approval</code> : petit modèle texte fiable (environ 3 à 8 milliards de paramètres). Qualité et respect des consignes plus importants que la vitesse brute — valide des actions sensibles, ne pas sous-dimensionner. | |||
* <code>skills_hub</code>, <code>triage_specifier</code>, <code>tts_audio_tags</code>, <code>monitor</code> et <code>memory_query_rewrite</code> : petit modèle texte rapide suffisant (environ 1 à 4 milliards de paramètres). | |||
* <code>goal_judge</code> : petit modèle texte rapide mais fiable (environ 1 à 4 milliards de paramètres). La sortie est courte et structurée ; un modèle rapide convient bien s'il respecte correctement les consignes et le format demandé. | |||
* <code>profile_describer</code> : petit ou moyen modèle texte (environ 3 à 8 milliards de paramètres). | |||
* <code>kanban_decomposer</code>, <code>background_review</code> : modèle texte intermédiaire avec de bonnes capacités de planification/analyse (environ 7 à 14 milliards de paramètres). | |||
* <code>curator</code> : modèle texte intermédiaire à performant pour synthèse (7 à 14 milliards de paramètres, plus pour analyses complexes). | |||
* <code>moa_reference</code> : modèle texte performant (14 milliards de paramètres ou plus). | |||
* <code>moa_aggregator</code> : modèle texte performant avec contexte long (14B+, au moins 64 000 jetons de contexte). | |||
Pour une première optimisation, il est conseillé de configurer en priorité : | |||
* <code>vision</code> : modèle multimodal de 3 à 4 milliards de paramètres | |||
* <code>title_generation</code> : petit modèle texte très rapide | |||
* <code>triage_specifier</code> : petit modèle texte rapide | |||
* <code>memory_query_rewrite</code> : petit modèle texte rapide | |||
* <code>goal_judge</code> : petit modèle texte rapide et fiable | |||
* <code>compression</code> : modèle disposant d’un contexte long et de bonnes capacités de résumé | |||
Les autres fonctions peuvent rester sur <code>provider: auto</code> tant qu’elles ne provoquent pas de lenteurs, de délais d’attente ou une consommation excessive de ressources. | |||
==== Contexte et reasoning recommandés par fonction ==== | |||
Le sur-dimensionnement du contexte (<code>-c</code>) est l’un des plus gros gaspillages de VRAM sur les petits modèles auxiliaires. Il est donc préférable d’adapter le contexte à chaque fonction plutôt que d’utiliser une valeur unique « confortable » pour toutes les routes. | |||
Hermes permet également de contrôler le niveau de reasoning indépendamment pour chaque tâche auxiliaire avec : | |||
<pre> | |||
auxiliary: | |||
vision: | |||
reasoning_effort: "none" | |||
compression: | |||
reasoning_effort: "low" | |||
</pre> | |||
Les valeurs disponibles sont : | |||
<code>none</code>, <code>minimal</code>, <code>low</code>, <code>medium</code>, <code>high</code>, <code>xhigh</code>, <code>max</code> et <code>ultra</code>. | |||
Une valeur vide ou absente laisse le provider choisir son comportement par défaut. | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = | |||
Certains modèles, comme LFM2.5-2.6B, ne permettent pas de sélectionner le niveau de raisonnement. Dans ce cas, laisser le champ vide. | |||
}} | |||
{| class="wikitable" | |||
! Fonction !! Contexte suggéré !! Reasoning suggéré !! Remarque | |||
|- | |||
| <code>title_generation</code> || 2-4K || <code>none</code> || Ne voit généralement que les premiers messages. Aucun raisonnement complexe nécessaire. | |||
|- | |||
| <code>tts_audio_tags</code> || 2-4K || <code>none</code> || Annotation d’un passage de texte court. Le thinking apporte très peu. | |||
|- | |||
| <code>triage_specifier</code> || 4-8K || <code>none</code> / <code>minimal</code> || Développe une tâche courte du Triage Kanban en spécification plus détaillée. Un reasoning profond est généralement inutile. | |||
|- | |||
| <code>memory_query_rewrite</code> || 4-8K || <code>none</code> / <code>minimal</code> || Reformulation courte destinée à améliorer la recherche mémoire ; aucun reasoning profond n'est normalement nécessaire. | |||
|- | |||
| <code>goal_judge</code> || 4-8K || <code>none</code> / <code>minimal</code> || Évalue l'objectif et la dernière réponse pour produire un verdict structuré. La fiabilité du respect du format est plus importante que la profondeur du reasoning. | |||
|- | |||
| <code>skills_hub</code> || 4-8K || <code>none</code> / <code>minimal</code> || Recherche ou sélection de compétences. Un reasoning profond est inutile dans la majorité des cas. | |||
|- | |||
| <code>monitor</code> || 8K || <code>none</code> / <code>minimal</code> || Selon la taille des données surveillées. Le plus souvent détection/classification. | |||
|- | |||
| <code>profile_describer</code> || 8K || <code>low</code> || Synthèse d’un historique modéré. | |||
|- | |||
| <code>approval</code> || 8-16K || <code>low</code> / <code>medium</code> || Analyse d’une action proposée et de son contexte. Conserver davantage de reasoning pour les décisions sensibles. | |||
|- | |||
| <code>mcp</code> || 8-16K || <code>low</code> || Dépend principalement du nombre et de la taille des définitions d’outils. Un peu de reasoning aide à sélectionner correctement l’outil. | |||
|- | |||
| <code>kanban_decomposer</code> || 8-16K || <code>low</code> / <code>medium</code> || Décomposition d’un projet en tâches ; le reasoning peut réellement améliorer la structure. | |||
|- | |||
| <code>vision</code> || 16K || <code>none</code> || Recommandé pour description/OCR simple : le modèle principal peut effectuer le raisonnement ensuite. Passer à <code>low</code> pour diagrammes ou analyse visuelle complexe. Ajuster le contexte si usage OCR intensif. | |||
|- | |||
| <code>curator</code> || 16-32K || <code>low</code> || Peut agréger plusieurs sources et doit sélectionner les éléments pertinents. | |||
|- | |||
| <code>background_review</code> || 16-32K || <code>low</code> / hérité || Si un modèle auxiliaire distinct est utilisé, <code>low</code> est généralement suffisant. Un review fork utilisant le même modèle que l’agent hérite du reasoning du modèle principal. | |||
|- | |||
| <code>moa_reference</code> || 32K ou plus || Par preset || Le reasoning ne se configure pas via <code>auxiliary.moa_reference.reasoning_effort</code>. Il se règle individuellement dans <code>moa.presets.<nom>.reference_models[].reasoning_effort</code>. | |||
|- | |||
| <code>compression</code> || 64-128K typiquement || <code>low</code> || Nécessite une fenêtre de contexte suffisamment grande pour recevoir le contenu à compresser. | |||
|- | |||
| <code>moa_aggregator</code> || 64K minimum, souvent davantage || Par preset, généralement <code>medium</code> / <code>high</code> || Agrège plusieurs réponses longues et bénéficie réellement du reasoning. Le réglage se fait dans <code>moa.presets.<nom>.aggregator.reasoning_effort</code>. | |||
|} | |||
===== Quand désactiver le reasoning ===== | |||
Le reasoning peut généralement être désactivé avec <code>reasoning_effort: "none"</code> lorsque la tâche consiste principalement à classer, annoter, extraire ou décrire des données sans prise de décision complexe. | |||
Bonnes candidates : | |||
* <code>title_generation</code> | |||
* <code>tts_audio_tags</code> | |||
* <code>triage_specifier</code> | |||
* <code>memory_query_rewrite</code> | |||
* <code>goal_judge</code> | |||
* <code>vision</code> pour description ou OCR simple | |||
* <code>monitor</code> | |||
* <code>skills_hub</code> | |||
Pour les tâches de synthèse ou de décision, <code>low</code> constitue généralement un meilleur compromis : | |||
* <code>compression</code> | |||
* <code>profile_describer</code> | |||
* <code>curator</code> | |||
* <code>mcp</code> | |||
Les tâches de planification ou d’agrégation complexe peuvent conserver <code>medium</code> ou davantage : | |||
* <code>kanban_decomposer</code> | |||
* <code>approval</code> pour les décisions sensibles | |||
* <code>moa_aggregator</code> | |||
À noter que <code>reasoning_effort</code> est un raccourci Hermes. Si un <code>extra_body.reasoning</code> explicite est également défini pour la même tâche, celui-ci est prioritaire. | |||
Pour le modèle principal, le réglage global reste : | |||
<pre> | |||
agent: | |||
reasoning_effort: "medium" | |||
</pre> | |||
et peut être modifié temporairement dans une session avec : | |||
<pre> | |||
/reasoning none | |||
/reasoning low | |||
/reasoning medium | |||
/reasoning high | |||
</pre> | |||
Le réglage <code>/reasoning</code> concerne le modèle principal ; il ne remplace pas les réglages <code>reasoning_effort</code> propres aux tâches auxiliaires. | |||
===== Cas particulier de la compression ===== | |||
Le contexte nécessaire pour <code>compression</code> dépend directement du volume de contexte transmis au modèle auxiliaire. | |||
Le réglage général de la compression se fait dans : | |||
<pre> | |||
~/.hermes/config.yaml | |||
</pre> | |||
Par défaut : | |||
<pre> | |||
compression: | |||
enabled: true | |||
threshold: 0.50 | |||
</pre> | |||
<code>threshold</code> représente une fraction de la fenêtre de contexte du modèle principal. | |||
Par exemple, avec un modèle principal configuré à 262144 tokens : | |||
<pre> | |||
262144 × 0.50 = 131072 tokens | |||
</pre> | |||
La compression peut donc être déclenchée autour de 131K tokens. | |||
Le modèle auxiliaire lui-même se configure séparément : | |||
<pre> | |||
auxiliary: | |||
compression: | |||
provider: auto | |||
model: NOM_DU_MODELE | |||
base_url: http://ADRESSE:PORT/v1 | |||
api_key: CLE_API | |||
timeout: 120 | |||
</pre> | |||
Le modèle utilisé pour la compression doit disposer d'une fenêtre de contexte suffisamment grande pour traiter les données que Hermes lui transmet. | |||
Dans le cas d'un petit modèle local disposant malgré tout d'un contexte long, comme LFM2.5-2.6B configuré à 128K, celui-ci peut être particulièrement intéressant grâce à son coût réduit et à sa vitesse élevée de traitement du prompt. | |||
==== Quantification (poids du modèle) ==== | |||
* '''Tâches à faible enjeu''' (<code>title_generation</code>, <code>tts_audio_tags</code>, <code>skills_hub</code>, <code>monitor</code>, <code>triage_specifier</code>, <code>memory_query_rewrite</code>, <code>goal_judge</code>) : Q4_K_M suffit largement. | |||
* '''Tâches à enjeu réel''' (<code>approval</code>, <code>mcp</code>, <code>compression</code>, <code>vision</code>) : privilégier Q5_K_M ou Q6_K — sur des modèles 4-8B, l’écart VRAM entre Q4 et Q6 reste faible (souvent < 1,5 Go), autant prendre la marge. | |||
==== KV cache (contexte) ==== | |||
* '''En dessous de 16K de contexte''' : pas de quantification ou <code>q8_0</code>/<code>q8_0</code> en KV cache partout par défaut sur les routes auxiliaires — risque de dégradation négligeable. | |||
* '''À partir de 32K''' (<code>moa_reference</code>, <code>compression</code>) : <code>q8_0</code>/<code>q8_0</code> devient intéressant, avec un gain notable de mémoire pour un risque faible. | |||
* '''<code>moa_aggregator</code> à 64K+''' : seule route où une approche plus poussée type <code>q8_0</code>/<code>q6_0</code> + Hadamard (si le fork le supporte) peut se justifier, vu le volume réel de KV cache à comprimer. | |||
=== Réglages de la voix === | |||
==== Text-to-Speech (TTS) ==== | |||
# vi ~/.hermes/config.yaml | |||
Configuration par défaut : | |||
<font color = grey>...</font> | |||
tts: | |||
provider: <font color = green>edge</font> | |||
edge: | |||
voice: <font color = blue>en-US-AriaNeural</font> | |||
<font color = grey>...</font> | |||
Parmi les options gratuites et simples proposées par Hermes, Edge constitue probablement le meilleur choix par défaut. Il est toutefois recommandé de sélectionner une voix adaptée à la langue utilisée. Exemple pour le français : | |||
<font color = grey>...</font> | |||
tts: | |||
provider: <font color = green>edge</font> | |||
edge: | |||
voice: <font color = blue>fr-FR-DeniseNeural</font> | |||
<font color = grey>...</font> | |||
===== TTS via CrispASR ===== | |||
Voir [[CrispASR#Text-to-Speech|CrispASR]] | |||
CrispASR expose une API de synthèse vocale compatible avec l’API audio d’OpenAI. Hermes doit donc utiliser le fournisseur <code>openai</code> pour envoyer le texte au serveur TTS. | |||
* Dans le fichier <code>~/.hermes/config.yaml</code> : | |||
<font color="grey">...</font> | |||
tts: | |||
provider: <font color="green">openai</font> | |||
<font color="grey">...</font> | |||
openai: | |||
model: <font color="blue">qwen3-tts-12hz-0.6b-base-q8_0</font> | |||
voice: <font color="blue">default</font> | |||
base_url: http://<font color="blue">IP_CRISPASR</font>:<font color="blue">7981</font>/v1 | |||
<font color="green">consent_attestation: "I have the speaker's consent"</font> | |||
<font color="grey">...</font> | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = | |||
<code><font color="green">consent_attestation: "I have the speaker's consent"</font></code> est nécessaire à l'utilisation du clonage de voix. | |||
}} | |||
Lorsque CrispASR est lancé avec une voix de référence fixe, la valeur <code>default</code> peut être utilisée pour l’option <code>voice</code>. La voix réellement utilisée dépend alors du fichier WAV et de sa transcription chargés par le serveur. | |||
Le nom du modèle exposé peut être vérifié avec la commande suivante : | |||
curl http://<font color="blue">IP_CRISPASR</font>:<font color="blue">7980</font>/v1/models | |||
* Dans le fichier <code>~/.hermes/.env</code> : | |||
<font color="grey">...</font> | |||
VOICE_TOOLS_OPENAI_KEY=<font color="blue">local</font> | |||
<font color="grey">...</font> | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = important | |||
| texte = | |||
La valeur <code><font color="blue">local</font></code> sert uniquement de clé fictive lorsque l’authentification n’est pas activée sur CrispASR. Hermes exige néanmoins qu’une clé soit définie pour utiliser le fournisseur OpenAI. | |||
}} | |||
==== Speech-to-Text (STT) ==== | |||
# vi ~/.hermes/config.yaml | |||
Configuration par défaut : | |||
<font color = grey>...</font> | |||
stt: | |||
enabled: true | |||
provider: local | |||
local: | |||
model: base | |||
language: '' | |||
openai: | |||
model: whisper-1 | |||
mistral: | |||
model: voxtral-mini-latest | |||
elevenlabs: | |||
model_id: scribe_v2 | |||
language_code: '' | |||
tag_audio_events: false | |||
diarize: false | |||
<font color = grey>...</font> | |||
Le Speech-to-Text permet de convertir les enregistrements vocaux en texte. Par défaut, Hermes utilise localement <code>faster-whisper</code> avec le modèle <code>base</code>. Cette solution est gratuite, ne nécessite aucune clé API et conserve les enregistrements sur la machine. | |||
Lorsque le champ <code>language</code> reste vide, la langue est détectée automatiquement. Il est toutefois possible de préciser la langue afin de limiter les erreurs de détection, par exemple avec <code>fr</code> pour le français. | |||
Le modèle <code>base</code> offre un bon compromis entre rapidité et consommation de ressources, mais il peut manquer de précision avec les noms propres, les nombres, les adresses IP ou les termes techniques. Il est alors possible d’utiliser un modèle local plus volumineux, par exemple <code>small</code> ou <code>medium</code>. Plus le modèle est grand, plus la transcription est généralement précise, mais plus elle demande de mémoire et de temps de traitement. | |||
Exemple avec un modèle local plus précis configuré pour le français : | |||
<font color="grey">...</font> | |||
stt: | |||
enabled: true | |||
provider: local | |||
local: | |||
model: small | |||
language: fr | |||
<font color="grey">...</font> | |||
Hermes peut également utiliser un service externe de reconnaissance vocale, par exemple OpenAI, Mistral ou ElevenLabs. Dans ce cas, il suffit de sélectionner le fournisseur souhaité avec l’option <code>provider</code> et de renseigner la clé API correspondante dans le fichier <code>~/.hermes/.env</code>. | |||
===== STT via CrispASR ===== | |||
Voir [[CrispASR#Speech-to-Text|CrisASR]] | |||
CrispASR expose une API compatible avec l’API audio d’OpenAI. Hermes doit donc utiliser le fournisseur <code>openai</code> pour envoyer les fichiers audio au serveur. | |||
* Dans le fichier <code>~/.hermes/config.yaml</code> (exemple avec parakeet-tdt-0.6b-v3) : | |||
<font color = grey>...</font> | |||
stt: | |||
enabled: true | |||
provider: openai | |||
<font color = grey>local: | |||
model: small | |||
language: 'fr'</font> | |||
openai: | |||
model: <font color = blue>parakeet-tdt-0.6b-v3-q8_0</font> | |||
<font color = grey>...</font> | |||
* Dans le fichier <code>~/.hermes/.env</code> : | |||
<font color = grey>...</font> | |||
VOICE_TOOLS_OPENAI_KEY=local | |||
STT_OPENAI_BASE_URL=http://<font color="blue">IP_CRISPASR</font>:<font color="blue">7980</font>/v1 | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = important | |||
| texte = | |||
La valeur <code>local</code> sert uniquement de clé fictive lorsque l’authentification n’est pas activée sur CrispASR. Hermes exige néanmoins qu’une clé soit définie pour utiliser le fournisseur OpenAI. | |||
}} | |||
Après modification, on redémarre Hermes afin que la nouvelle configuration soit prise en compte. | |||
=== Changer le mode d'approbation des commandes === | |||
# vi ~/.hermes/config.yaml | |||
approvals: | |||
mode: <font color="green">manual</font> | |||
Remplacer <code>manual</code> par <code>smart</code> pour confier l’évaluation des commandes sensibles à un LLM. Les opérations jugées sûres sont automatiquement autorisées, les opérations dangereuses sont refusées et les cas incertains sont soumis à l’utilisateur. Par défaut, Hermes utilise le modèle principal pour cette évaluation, sauf si un modèle auxiliaire spécifique est configuré pour la tâche approval. | |||
= Commandes = | = Commandes = | ||
| Ligne 105 : | Ligne 976 : | ||
* Diagnostiquer les problèmes : | * Diagnostiquer les problèmes : | ||
# hermes doctor | # hermes doctor | ||
= | = Modules d’extension et d’intégration = | ||
== | Ressource : | ||
*exemple | * [https://github.com/0xNyk/awesome-hermes-agent Awesome Hermes Agent] : liste de différentes extensions classé par catégorie. | ||
<font color = | * [https://hermesatlas.com/skills/ Hermes Agent skills] : top selon le site hermes atlas | ||
On édite la configuration : | == [https://github.com/fathah/hermes-desktop Hermes Agent Desktop] == | ||
Pour accéder a toutes les fonctionnalités sur une connexion distante il est préférable de se connecter via SSH, sur le serveur Hermes Agent : | |||
# ssh-keygen -t ed25519 -f ~/.ssh/hermes_desktop | |||
Ne PAS entrer de mot de passe : | |||
Enter passphrase for "/root/.ssh/hermes_desktop" (empty for no passphrase): | |||
Enter same passphrase again: | |||
Ensuite, ajouter la clé publique aux clés autorisées du compte auquel Hermes Desktop doit se connecter : | |||
# cat ~/.ssh/hermes_desktop.pub >> ~/.ssh/authorized_keys | |||
# chmod 600 ~/.ssh/authorized_keys | |||
=== Windows === | |||
On lance <code>PowerShell</code> et on récupère la clef : | |||
> scp <font color = blue>utilisateur</font>@<font color = blue>IP_DU_SERVEUR</font>:~/.ssh/hermes_desktop "$env:USERPROFILE\.ssh\hermes_desktop" | |||
Dans <code>Private Key Path</code> il faudra alors entrer : | |||
C:\Users\<font color=blue>NOM_UTILISATEUR</font>\.ssh\hermes_desktop | |||
== [https://github.com/nesquena/hermes-webui Hermes WebUI] == | |||
Sur le serveur Hermes Agent : | |||
# apt update && apt upgrade | |||
# apt install -y git python3 python3-venv | |||
# cd /opt/ | |||
# git clone <nowiki>https://</nowiki>github.com/nesquena/hermes-webui.git | |||
# cd hermes-webui | |||
# ./ctl.sh start | |||
On arrête temporairement le serveur : | |||
# ./ctl.sh stop | |||
On crée un service systemd pour qu'il se lance automatiquement : | |||
# vi /etc/systemd/system/hermes-webui.service | |||
[Unit] | |||
Description=Hermes WebUI | |||
Wants=network-online.target | |||
After=network-online.target | |||
[Service] | |||
Type=simple | |||
User=root | |||
Group=root | |||
WorkingDirectory=/opt/hermes-webui | |||
Environment=HOME=/root | |||
Environment=HERMES_HOME=/root/.hermes | |||
Environment=HERMES_WEBUI_HOST=<font color = blue>127.0.0.1</font> | |||
Environment=HERMES_WEBUI_PORT=<font color = green>8787</font> | |||
EnvironmentFile=-/opt/hermes-webui/.env | |||
ExecStart=/bin/bash /opt/hermes-webui/start.sh --foreground | |||
Restart=on-failure | |||
RestartSec=5 | |||
KillSignal=SIGTERM | |||
TimeoutStopSec=20 | |||
[Install] | |||
WantedBy=multi-user.target | |||
Par défaut l'interface n'est accessible que depuis le serveur, pour autoriser l'écoute sur une IP remplacer <code>HERMES_WEBUI_HOST=<font color = blue>127.0.0.1</font></code> par 0.0.0.0 ou une interface IP du serveur. | |||
Ensuite on ajoute un mot de passe : | |||
# vi /opt/hermes-webui/.env | |||
HERMES_WEBUI_PASSWORD=<font color = blue>MOT_DE_PASSE</font> | |||
# chmod 600 /opt/hermes-webui/.env | |||
(Recommandé) On peut également conserver <code>127.0.0.1</code> et passer par un [[Caddy_ReverseProxy|proxy Caddy]]. | |||
On active le service systemd : | |||
# systemctl daemon-reload | |||
# systemctl enable --now hermes-webui.service | |||
Pour pouvoir utiliser un reverse-proxy il faut ajouter : | |||
# vi /opt/hermes-webui/.env | |||
HERMES_WEBUI_PASSWORD=<font color = blue>MOT_DE_PASSE</font> | |||
HERMES_WEBUI_SECURE=1 | |||
HERMES_WEBUI_ALLOWED_ORIGINS=<font color = blue><nowiki>https://</nowiki>hermes.exemple.net</font> | |||
HERMES_WEBUI_TRUST_FORWARDED_HOST=1 | |||
HERMES_WEBUI_TRUST_FORWARDED_FOR=1 | |||
HERMES_WEBUI_TRUST_FORWARDED_PROTO=1 | |||
# systemctl restart hermes-webui | |||
Exemple de vhost [[Nginx_ReverseProxy_LXC_Alpine_Linux|Nginx]] : | |||
server { | |||
listen 80; | |||
listen [::]:80; | |||
server_name <font color = blue>hermes.exemple.net</font>; | |||
return 301 <nowiki>https://</nowiki>$host$request_uri; | |||
} | |||
server { | |||
server_name <font color = blue>hermes.exemple.net</font>; | |||
# protection | |||
add_header X-Content-Type-Options "nosniff" always; | |||
add_header X-Frame-Options "SAMEORIGIN" always; | |||
add_header Referrer-Policy "strict-origin-when-cross-origin" always; | |||
add_header Strict-Transport-Security "max-age=31536000" always; | |||
client_max_body_size 256m; | |||
location / { | |||
proxy_set_header Host $proxy_host; | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header X-Forwarded-Proto https; | |||
proxy_set_header X-Forwarded-Host $host; | |||
proxy_set_header X-Forwarded-Port $server_port; | |||
proxy_http_version 1.1; | |||
proxy_read_timeout 3600; | |||
proxy_send_timeout 3600; | |||
proxy_pass <nowiki>http<font color = red>s</font>://</nowiki><font color = blue>192.168.1.123</font>:<font color = green>8787</font>; | |||
proxy_ssl_verify off; | |||
proxy_ssl_server_name on; | |||
proxy_ssl_name 192.168.1.123; | |||
proxy_buffering off; | |||
proxy_cache off; | |||
} | |||
listen [::]:443 ssl; # managed by Certbot | |||
listen 443 ssl; # managed by Certbot | |||
ssl_certificate /etc/letsencrypt/live/<font color = blue>hermes.exemple.net</font>/fullchain.pem; | |||
ssl_certificate_key /etc/letsencrypt/live/<font color = blue>hermes.exemple.net</font>/privkey.pem; | |||
include /etc/letsencrypt/options-ssl-nginx.conf; | |||
} | |||
=== Mise à jour === | |||
Mettre à jour Hermes Agent : | |||
# hermes update | |||
Mettre à jour Hermes WebUI : | |||
# cd /opt/hermes-webui | |||
# git pull --ff-only | |||
# systemctl restart hermes-webui.service | |||
=== Garder toutes les parties de réponse ouvertes (extension keep-expanded) === | |||
Par défaut, Hermes WebUI replie automatiquement les parties intermédiaires d'une réponse (le texte que l'IA écrit entre deux appels d'outils) dès qu'il y en a plus de 3 : un lien <code>Show N earlier updates</code> apparaît pour les retrouver. Ce comportement est codé en dur (<code>INTERIM_COLLAPSE_THRESHOLD=3</code> dans <code>static/messages.js</code>) et ne propose aucune option. Les modèles qui produisent beaucoup de petites notes de progression (Qwen par exemple) le rendent vite pénible, car le bloc de code final peut se retrouver dans une partie repliée. | |||
Le WebUI supporte les extensions CSS (voir <code>docs/EXTENSIONS.md</code> dans le dépôt). Voici une petite extension maison qui désactive ce repli. | |||
* Étape 1 — Créer le fichier CSS : | |||
# mkdir -p ~/.hermes/webui/extensions | |||
# vi ~/.hermes/webui/extensions/keep-expanded.css | |||
Y coller : | |||
/* Extension hermes-webui : garder depliee chaque segment de reponse | |||
(desactive le repli automatique des notes intermediaires). */ | |||
.interim-collapsed { display: revert !important; } | |||
.interim-collapse-toggle { display: none !important; } | |||
* Étape 2 — Déclarer l'extension au service : le service systemd lit déjà <code>EnvironmentFile=-/opt/hermes-webui/.env</code> (voir le service plus haut), on y ajoute donc deux lignes : | |||
# vi /opt/hermes-webui/.env | |||
HERMES_WEBUI_EXTENSION_DIR=/root/.hermes/webui/extensions | |||
HERMES_WEBUI_EXTENSION_STYLESHEET_URLS=/extensions/keep-expanded.css | |||
* Étape 3 — Redémarrer et vérifier : | |||
# systemctl restart hermes-webui.service | |||
# systemctl is-active hermes-webui.service | |||
Puis recharger la page du WebUI dans le navigateur (F5) : toutes les parties des réponses restent ouvertes, et le lien <code>Show N earlier updates</code> a disparu. | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = information | |||
| texte = Redémarrer le service coupe brièvement la session WebUI en cours (les conversations sont sauvegardées, mais la réponse en cours de rédaction peut être perdue). | |||
}} | |||
'''Retour en arrière :''' supprimer les deux lignes de <code>/opt/hermes-webui/.env</code> (ou le fichier CSS), puis relancer le service — le repli automatique revient. | |||
'''Résistance aux mises à jour :''' cette configuration survit aux mises à jour normales (<code>git pull</code> dans <code>/opt/hermes-webui</code> puis redémarrage) : | |||
* <code>.env</code> est listé dans le <code>.gitignore</code> du projet : git ne le touche jamais ; | |||
* le CSS vit dans <code>~/.hermes/webui/extensions/</code>, hors du dépôt git — c'est le répertoire officiellement recommandé pour les extensions. | |||
Seuls une réinstallation complète (suppression + re-clone) ou un changement de nom des classes <code>interim-collapsed</code> / <code>interim-collapse-toggle</code> côté développeur pourraient casser l'extension. Si le repli revient tout seul après une mise à jour, il suffit de vérifier ces sélecteurs dans le CSS. | |||
== [https://github.com/outsourc-e/hermes-workspace Hermes Workspace] == | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = important | |||
| texte = | |||
Le projet semble ne plus être maintenu ; il est recommandé d’utiliser [[Hermes#Hermes_WebUI|Hermes WebUI]]. | |||
}} | |||
Un espace de travail complet : orchestrez vos agents, parcourez la mémoire, gérez les compétences et contrôlez l’ensemble depuis une interface unique. | |||
=== Docker === | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = Au moment d'écrire ce tutoriel l'accès au Dashboard et à la page MCP ne fonctionne plus avec la version officielle du conteneur, voir [[Hermes#Fix_Temporaire|cette procédure]] pour le patcher. Sinon, utliser [https://github.com/LugMuad/hermes-workspace-voice mon fork]. | |||
}} | |||
# mkdir -p /opt/hermes-workspace/hermes-workspace-data | |||
# chown -R 1000:1000 /opt/hermes-workspace/hermes-workspace-data | |||
# vi /opt/hermes-workspace/docker-compose.yml | |||
services: | |||
hermes-workspace: | |||
image: ghcr.io/outsourc-e/hermes-workspace:latest | |||
container_name: hermes-workspace | |||
restart: unless-stopped | |||
environment: | |||
#HERMES_HOME: /home/workspace/.hermes | |||
#HERMES_WORKSPACE_DIR: /workspace | |||
HERMES_API_URL: http://<font color = blue>IP_HERMES</font>:<font color = green>8642</font> | |||
HERMES_DASHBOARD_URL: http://<font color = blue>IP_HERMES</font>:<font color = green>9119</font> | |||
HERMES_API_TOKEN: "" | |||
HERMES_PASSWORD: "<font color = blue>change-moi</font>" | |||
HERMES_DASHBOARD_BASIC_AUTH_USERNAME: "<font color = green>admin</font>" | |||
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD: "<font color = blue>MOT_DE_PASSE_DASHBOARD</font>" | |||
HERMES_UID: 1000 | |||
HERMES_GID: 1000 | |||
COOKIE_SECURE: "<font color = blue>0</font>" | |||
TRUST_PROXY: "<font color = blue>0</font>" | |||
volumes: | |||
- ./hermes-workspace-data:/home/workspace/.hermes | |||
- ./workspace:/workspace | |||
ports: | |||
- "<font color = green>3000</font>:3000" | |||
{{Méta bandeau | |||
| niveau = attention | |||
| icône = attention | |||
| texte = Si Hermes Workspace est utilisé directement en HTTP sur le réseau local, utiliser <code>COOKIE_SECURE=0</code> et <code>TRUST_PROXY=0</code>. Si Hermes Workspace est publié derrière un reverse proxy HTTPS, utiliser <code>COOKIE_SECURE=1</code> et <code>TRUST_PROXY=1</code>. Avec <code>COOKIE_SECURE=1</code>, le cookie de session n'est transmis que via HTTPS. <code>TRUST_PROXY=1</code> permet à Hermes Workspace de faire confiance aux informations de protocole et d'adresse transmises par le reverse proxy. | |||
}} | |||
# docker compose -f /opt/hermes-workspace/docker-compose.yml --project-directory /opt/hermes-workspace up -d | |||
Exemple de [[Nginx_ReverseProxy_LXC_Alpine_Linux|vhost]] : | |||
server { | |||
listen 80; | |||
listen [::]:80; | |||
server_name <font color = blue>hermes.exemple.net</font>; | |||
return 301 <nowiki>https://</nowiki>$host$request_uri; | |||
} | |||
server { | |||
server_name <font color = blue>hermes.exemple.net</font>; | |||
# protection | |||
add_header X-Content-Type-Options "nosniff" always; | |||
add_header X-Frame-Options "SAMEORIGIN" always; | |||
add_header Referrer-Policy "strict-origin-when-cross-origin" always; | |||
add_header Strict-Transport-Security "max-age=31536000" always; | |||
client_max_body_size 256m; | |||
location = /api/terminal-stream { | |||
proxy_pass http://<font color = blue>IP_SERVEUR_HERMES</font>:<font color = green>3000</font>; | |||
proxy_http_version 1.1; | |||
proxy_set_header Host $host; | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header X-Forwarded-Proto $scheme; | |||
proxy_set_header X-Forwarded-Host $host; | |||
proxy_set_header X-Forwarded-Port $server_port; | |||
proxy_set_header Connection ""; | |||
proxy_buffering off; | |||
proxy_cache off; | |||
proxy_read_timeout 3600s; | |||
proxy_send_timeout 3600s; | |||
} | |||
location / { | |||
proxy_set_header Upgrade $http_upgrade; | |||
proxy_set_header Connection "upgrade"; | |||
proxy_set_header Host $host; | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header X-Forwarded-Proto $scheme; | |||
proxy_set_header X-Forwarded-Host $host; | |||
proxy_set_header X-Forwarded-Port $server_port; | |||
proxy_http_version 1.1; | |||
proxy_read_timeout 3600; | |||
proxy_send_timeout 3600; | |||
proxy_pass http://<font color = blue>IP_SERVEUR_HERMES</font>:<font color = green>3000</font>; | |||
# proxy_buffering off; | |||
} | |||
listen [::]:443 ssl; # managed by Certbot | |||
listen 443 ssl; # managed by Certbot | |||
ssl_certificate /etc/letsencrypt/live/<font color = blue>hermes.exemple.net</font>/fullchain.pem; | |||
ssl_certificate_key /etc/letsencrypt/live/<font color = blue>hermes.exemple.net</font>/privkey.pem; | |||
include /etc/letsencrypt/options-ssl-nginx.conf; | |||
} | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = loupe | |||
| texte = Penser a mettre <code>COOKIE_SECURE=1</code> et <code>TRUST_PROXY=1</code> dans le fichier <code>docker-compose.yml</code> lorsque Hermes Workspace est accessible en HTTPS derrière un proxy. | |||
}} | |||
==== Fix Temporaire ==== | |||
On construit une version patché du conteneur : | |||
# cd /opt/ | |||
# git clone <nowiki>https://</nowiki>github.com/outsourc-e/hermes-workspace.git | |||
# cd hermes-workspace | |||
# git fetch origin pull/758/head:pr-758 | |||
# git fetch origin pull/735/head:pr-759 | |||
# git checkout -b hermes-fixed origin/main | |||
# git cherry-pick f7a50c5dcad8ba0f88e8d29e6f85c60b07681362 | |||
# git cherry-pick 36b7192 | |||
# docker build -t hermes-workspace:fixed . | |||
Dans le fichier <code>docker-compose.yml</code> remplacer <code>image: ghcr.io/outsourc-e/hermes-workspace:latest</code> par <code>image: hermes-workspace:fixed</code>. | |||
# docker compose -f /opt/hermes-workspace/docker-compose.yml --project-directory /opt/hermes-workspace up -d | |||
==== Réglage voix ==== | |||
Pour le moment le plus simple est d'utiliser [https://github.com/LugMuad/hermes-workspace-voice mon fork]. | |||
==== Catalogue des Skills et serveurs MCP dans le conteneur ==== | |||
Pour le moment le plus simple est d'utiliser [https://github.com/LugMuad/hermes-workspace-voice mon fork]. | |||
<div class="mw-collapsible mw-collapsed" style="text-align:left;"> | |||
'''Modification de <code>Dockerfile</code> pour référence''' | |||
<div class="mw-collapsible-content"> | |||
Le catalogue des Skills nécessite le script <code>skills-search.py</code> de Hermes Workspace ainsi que certains modules de Hermes Agent. | |||
Pour les intégrer directement à l'image Docker : | |||
# cd /opt/hermes-workspace | |||
# vi Dockerfile | |||
Ajouter les éléments suivant en bleu : | |||
<font color = grey>...</font> | |||
RUN apt-get update && apt-get install -y --no-install-recommends \ | |||
ca-certificates curl tini python3 <font color = blue>python3-httpx python3-yaml</font> \ | |||
&& rm -rf /var/lib/apt/lists/* \ | |||
&& groupadd -r workspace && useradd -r -g workspace -u 10010 -m workspace | |||
<font color = blue>COPY scripts/skills-search.py /app/scripts/skills-search.py | |||
RUN curl -L \ | |||
<nowiki>https://</nowiki>codeload.github.com/NousResearch/hermes-agent/tar.gz/refs/heads/main \ | |||
-o /tmp/hermes-agent.tar.gz \ | |||
&& mkdir -p /hermes-agent \ | |||
&& tar -xzf /tmp/hermes-agent.tar.gz -C /hermes-agent --strip-components=1 \ | |||
&& rm /tmp/hermes-agent.tar.gz | |||
ENV PYTHONPATH=/hermes-agent</font> | |||
<font color = grey>...</font> | |||
Puis plus bas : | |||
<font color = grey>...</font> | |||
COPY --from=build --chown=workspace:workspace /app/dist ./dist | |||
COPY --from=build --chown=workspace:workspace /app/node_modules ./node_modules | |||
COPY --from=build --chown=workspace:workspace /app/package.json ./package.json | |||
COPY --from=build --chown=workspace:workspace /app/server-entry.js ./server-entry.js | |||
COPY --from=build --chown=workspace:workspace /app/skills ./skills | |||
COPY --chown=workspace:workspace docker/entrypoint.sh /usr/local/bin/docker-entrypoint.sh | |||
<font color = blue>COPY --chown=workspace:workspace assets/mcp-presets.seed.json ./assets/mcp-presets.seed.json</font> | |||
<font color = grey>...</font> | |||
Reconstruire ensuite l'image et recréer le conteneur : | |||
# docker build -t hermes-workspace:fixed . | |||
# docker compose up -d --force-recreate | |||
On peut vérifier le fonctionnement avec : | |||
# docker exec hermes-workspace python3 -c \ | |||
'import httpx, yaml, tools.skills_hub; print("Skills Hub OK")' | |||
Le résultat attendu est : | |||
Skills Hub OK | |||
</div> | |||
</div> | |||
== [https://github.com/robbyczgw-cla/hermes-web-search-plus Hermes Web Search Plus] avec [https://github.com/dondai44423/donsetch DonSeTch] == | |||
Les opérations se déroulent directement sur l'hôte Hermes. | |||
La configuration présentée ici utilise DonSeTch avec SearXNG et Firecrawl comme services locaux. Il faut d’abord avoir [[SearXNG|installé une instance SearXNG]] et [[Firecrawl|installé une instance Firecrawl]]. | |||
* On installe et active le plugin : | |||
# hermes plugins install web-search-plus --enable | |||
Répondre <code>y</code> si l’installation des dépendances Node est proposée : | |||
Install them into the plugin's own node_modules now? [y/N]: y | |||
Répondre <code>yes</code> si une autorisation est demandée : | |||
This is a privileged capability: an override can intercept everything the agent routes | |||
through that tool. | |||
Grant it? | |||
On initialise le plugin avec le preset <code>self-hosted</code> : | |||
# hermes web-search-plus setup --preset self-hosted | |||
L’assistant propose ensuite d’activer Jev : | |||
Enable optional Jev (TypeSafe) for search-type overlay, extract quality, and language fill? [y/N]: | |||
Jev est un service extérieur optionnel utilisé pour améliorer la détection du type de recherche, l’évaluation des extractions et la détection de la langue. Il n’est pas nécessaire pour une configuration locale avec SearXNG, DonSeTch et Firecrawl. Répondre : | |||
n | |||
On renseigne l’adresse de l’instance SearXNG : | |||
# hermes config set SEARXNG_INSTANCE_URL <nowiki>http://</nowiki><font color = blue>IP_PRIVEE_SEARXNG</font>:<font color = green>PORT</font> | |||
Si le service SearXNG est accessible via une adresse IP privée, il faut l’autoriser explicitement : | |||
# hermes config set SEARXNG_ALLOW_PRIVATE 1 | |||
Le preset <code>self-hosted</code> peut utiliser Keenable comme service de secours extérieur sans clé API. Pour l’autoriser : | |||
# hermes config set KEENABLE_ALLOW_PUBLIC 1 | |||
Cette commande doit être omise pour conserver une configuration strictement locale. | |||
Pour que Web Search Plus considère Firecrawl comme configuré, une valeur doit être renseignée dans <code>FIRECRAWL_API_KEY</code>. Si l’instance locale n’utilise aucune authentification, employer une valeur factice : | |||
# hermes config set FIRECRAWL_API_KEY <font color = blue>local-firecrawl</font> | |||
* On installe DonSeTch : | |||
# npm install -g --allow-scripts=donsetch,@google/genai,protobufjs donsetch | |||
Pour s'assurer que le service Hermes puisse trouver Node : | |||
# test -e /usr/local/bin/node || ln -s /root/.local/bin/node /usr/local/bin/node | |||
On installe Chromium et Xvfb pour les fonctions nécessitant un navigateur : | |||
# apt update | |||
# apt install chromium xvfb | |||
On vérifie le fonctionnement de DonSeTch : | |||
# /root/.hermes/node/bin/donsetch --version | |||
# /root/.hermes/node/bin/donsetch doctor | |||
On enregistre le chemin du binaire dans le profil Hermes : | |||
# hermes config set DONSETCH_BIN /root/.hermes/node/bin/donsetch | |||
Le preset <code>self-hosted</code> limite le routage automatique à SearXNG et Keenable. Pour utiliser DonSeTch en priorité pour la recherche et Firecrawl pour l’extraction, on réinitialise la configuration avec le profil standard : | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config reset --yes | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-routing on | |||
On désactive les fournisseurs inutilisés : | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable brave | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable exa | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable linkup | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable octen | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable parallel | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable querit | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable serpbase | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable serper | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable tavily | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable tinyfish | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable you | |||
On définit les priorités de recherche et d’extraction : | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-priority donsetch,searxng | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-extract-priority donsetch,firecrawl | |||
On autorise l’utilisation automatique de DonSeTch : | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-auto-allow donsetch on | |||
Si Keenable a été activé, on le définit comme fournisseur de secours : | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-fallback keenable | |||
Cette commande doit également être omise pour conserver une configuration strictement locale. | |||
Le preset <code>self-hosted</code> ajoute l’autorisation d’utiliser le service public Keenable dans le fichier de routage du plugin. Ce réglage étant ignoré sous Hermes, il faut supprimer uniquement le bloc correspondant dans ce fichier. | |||
On édite le fichier de routage : | |||
# vi ~/.hermes/plugins/config.json | |||
On supprime uniquement le bloc suivant : | |||
"keenable": { | |||
"allow_public": true | |||
}, | |||
Il ne faut pas supprimer les autres occurrences de <code>keenable</code>, notamment celles qui le définissent comme fournisseur de secours. | |||
On ajoute ou modifie ensuite l’objet <code>firecrawl</code> situé à la racine du fichier : | |||
"firecrawl": { | |||
"api_url": "<nowiki>http://</nowiki><font color = blue>IP_FIRECRAWL</font>:<font color = green>3002</font>/v2/search", | |||
"scrape_url": "<nowiki>http://</nowiki><font color = blue>IP_FIRECRAWL</font>:<font color = green>3002</font>/v2/scrape" | |||
}, | |||
L’option suivante n’est nécessaire que si <code>web_extract_plus</code> doit être autorisé à extraire des pages situées sur un réseau privé ou un intranet : | |||
"extract": { | |||
"allow_private_urls": <font color = blue>true</font> | |||
}, | |||
Les objets doivent être séparés par une virgule afin de conserver un fichier JSON valide. Les valeurs booléennes JSON s’écrivent en minuscules : <code>true</code> et <code>false</code>. | |||
Hermes peut réessayer automatiquement les appels Web qui échouent auprès de services externes anonymes comme Exa, Parallel, Firecrawl ou Keenable. Web Search Plus disposant déjà de son propre fournisseur de secours, on désactive ce second mécanisme : | |||
# hermes config set web.keyless_rescue false | |||
On vérifie la syntaxe du fichier de routage : | |||
# python3 -m json.tool ~/.hermes/plugins/config.json >/dev/null && echo "JSON valide" | |||
On vérifie la configuration finale : | |||
# hermes web-search-plus status | |||
# python3 ~/.hermes/plugins/web-search-plus/setup.py config show --json | |||
=== Provider Web pour les outils natifs Hermes === | |||
Web Search Plus peut servir directement de backend aux outils natifs <code>web_search</code> et <code>web_extract</code> de Hermes. | |||
On active Web Search Plus pour la recherche et l’extraction : | |||
# hermes config set web.search_backend wsp | |||
# hermes config set web.extract_backend wsp | |||
Le backend <code>wsp</code> ne doit être sélectionné pour l’extraction que si au moins un fournisseur compatible est disponible, comme DonSeTch ou Firecrawl. | |||
Les outils natifs nécessitent que le toolset <code>web</code> reste activé. Si celui-ci figure dans <code>agent.disabled_toolsets</code>, il faut le retirer. | |||
On vérifie l’intégration : | |||
# hermes web-search-plus fastpath | |||
# hermes web-search-plus status | |||
Enfin, on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== Test === | |||
On teste directement le fournisseur Firecrawl : | |||
# cd ~/.hermes/plugins/web-search-plus | |||
# FIRECRAWL_API_KEY=<font color = green>local-firecrawl</font> python3 search.py --query "Hermes Agent latest release" --provider firecrawl --quality-report | |||
On lance ensuite Hermes : | |||
# hermes | |||
On lui demande d’effectuer une recherche avec Web Search Plus : | |||
Recherche la dernière version de Hermes Agent en utilisant web_search_plus et indique le fournisseur utilisé. | |||
On peut également demander un test explicite de DonSeTch : | |||
Recherche la documentation de Hermes Agent avec web_search_plus en imposant le fournisseur donsetch. | |||
=== Mise à jour === | |||
* Hermes Web Search Plus | |||
# hermes plugins update web-search-plus | |||
Si l’installation des dépendances Node est de nouveau proposée, répondre <code>y</code>. | |||
Le scanner de sécurité de Hermes peut désactiver le plugin après une mise à jour. Si nécessaire, le réactiver : | |||
# hermes plugins enable web-search-plus | |||
Puis redémarrer Hermes : | |||
# systemctl restart hermes-gateway.service | |||
* DonSeTch | |||
On met à jour DonSeTch vers la dernière version disponible : | |||
# npm install -g --allow-scripts=donsetch,@google/genai,protobufjs donsetch@latest | |||
On vérifie ensuite la version et le bon fonctionnement de DonSeTch : | |||
# /root/.hermes/node/bin/donsetch --version | |||
# /root/.hermes/node/bin/donsetch doctor | |||
Sources : | |||
* [https://github.com/robbyczgw-cla/hermes-web-search-plus/blob/main/docs/USER_GUIDE.md Guide de Web Search Plus] | |||
* [https://github.com/robbyczgw-cla/hermes-web-search-plus/blob/main/docs/DONSETCH.md Intégration de DonSeTch] | |||
* [https://github.com/robbyczgw-cla/hermes-web-search-plus/blob/main/docs/NATIVE_BACKEND.md Backend natif Hermes] | |||
==[https://github.com/mnemosyne-oss/mnemosyne Mnemosyne]== | |||
Mnemosyne est une couche de mémoire universelle, conçue en priorité pour Hermes, mais compatible avec n’importe quel framework d’agents. | |||
* On installe le plugin : | |||
# source ~/.hermes/hermes-agent/venv/bin/activate | |||
# python -m ensurepip --upgrade | |||
# python -m pip install --upgrade pip | |||
# python -m pip install mnemosyne-hermes | |||
# mkdir -p ~/.hermes/plugins/mnemosyne | |||
# ln -sfn "$(~/.hermes/hermes-agent/venv/bin/python -c 'import pathlib, mnemosyne_hermes; print(pathlib.Path(mnemosyne_hermes.__file__).resolve().parent)')"/* ~/.hermes/plugins/mnemosyne/ | |||
# hermes config set memory.provider mnemosyne | |||
On édite ensuite la configuration de Hermes : | |||
# vi ~/.hermes/config.yaml | # vi ~/.hermes/config.yaml | ||
<font color = grey>...</font> | |||
memory: | |||
memory_enabled: <font color = blue>false</font> | |||
user_profile_enabled: <font color = blue>false</font> | |||
<font color = grey>...</font> | |||
Ces deux options désactivent la mémoire native de Hermes (<code>MEMORY.md</code> et <code>USER.md</code>) afin d'utiliser Mnemosyne comme fournisseur de mémoire. | |||
=== Embedding === | |||
Mnemosyne-Hermes est livré avec le support des embeddings locaux. Un modèle d'embedding est nécessaire au fonctionnement de la mémoire vectorielle ; il peut être exécuté localement ou fourni par un serveur externe. | |||
==== Modèle local ==== | |||
Le modèle utilisé par défaut, <code>BAAI/bge-small-en-v1.5</code>, est principalement destiné à l'anglais. Pour un usage multilingue, on peut par exemple utiliser le modèle léger <code>sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2</code> : | |||
# mnemosyne config set embedding_model sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 | |||
# mnemosyne config set embedding_dim 384 | |||
# mnemosyne config set embedding_api_url "" | |||
# mnemosyne config set embedding_api_key "" | |||
# mnemosyne config set embeddings_via_api false | |||
Le modèle local est téléchargé automatiquement lors de sa première utilisation. | |||
Voir la [https://github.com/mnemosyne-oss/mnemosyne/blob/main/docs/configuration.md#custom-embedding-models liste des modèles d'embedding disponibles]. | |||
==== Serveur d'embedding externe ==== | |||
Mnemosyne peut également utiliser un serveur d'embedding compatible avec l'API OpenAI : | |||
# mnemosyne config set embedding_api_url "http://<font color = blue>ADRESSE_SERVEUR</font>:<font color = blue>PORT</font>/v1" | |||
# mnemosyne config set embedding_api_key "<font color = blue>CLEF_API</font>" | |||
# mnemosyne config set embedding_model "<font color = blue>NOM_EXACT_DU_MODELE</font>" | |||
# mnemosyne config set embedding_dim <font color = blue>DIMENSION_DU_MODELE</font> | |||
# mnemosyne config set embeddings_via_api true | |||
La valeur de <code>embedding_dim</code> doit impérativement correspondre à la dimension produite par le modèle d'embedding utilisé. | |||
'''Attention :''' changer de modèle d'embedding ou de dimension sur une base Mnemosyne contenant déjà des données peut nécessiter une reconstruction des embeddings existants. | |||
==== Changer de modèle d'embedding ou de dimension ==== | |||
Pour changer de modèle d'embedding en toute sécurité, il faut d'abord enregistrer le nouveau modèle et, si nécessaire, sa dimension dans la configuration utilisée par Hermes après redémarrage. | |||
On arrête ensuite Hermes ainsi que tout autre processus susceptible d'écrire dans la même base SQLite : | |||
# systemctl stop hermes-gateway.service | |||
On vérifie alors le plan de réindexation sans modifier la base : | |||
# mnemosyne reindex --model <font color = blue>NOM_EXACT_DU_MODELE</font> --dry-run | |||
La commande doit afficher le modèle et la dimension attendus. Il ne faut pas poursuivre si ces valeurs ne correspondent pas à la configuration qui sera utilisée après le redémarrage. | |||
Une fois le résultat vérifié, on lance la réindexation : | |||
# mnemosyne reindex --model <font color = blue>NOM_EXACT_DU_MODELE</font> --yes | |||
Par défaut, Mnemosyne crée une sauvegarde, recalcule les embeddings des mémoires de travail et épisodiques et, lorsque <code>sqlite-vec</code> est disponible, reconstruit les tables vectorielles avec la dimension définie par la configuration effective. | |||
'''Attention :''' l'option <code>--model</code> ne remplace pas une valeur explicite de <code>embedding_dim</code>. Si une dimension est configurée, elle doit correspondre à la dimension réellement produite par le nouveau modèle. | |||
On redémarre ensuite Hermes : | |||
# systemctl start hermes-gateway.service | |||
=== LLM optionnel === | |||
Mnemosyne peut utiliser un LLM en complément du modèle d'embedding. | |||
Ce LLM n'est pas nécessaire au fonctionnement de base de la mémoire. Lorsqu'il est activé, il est notamment utilisé pour : | |||
* la consolidation et la synthèse des souvenirs lors des opérations de <code>sleep</code> ; | |||
* l'extraction structurée de faits ; | |||
* certaines opérations avancées basées sur un LLM. | |||
En l'absence de LLM disponible, Mnemosyne peut continuer à fonctionner en utilisant ses mécanismes de traitement non-LLM. | |||
==== Aucun LLM ==== | |||
Par défaut dans la configuration déclarée de Mnemosyne, le LLM est désactivé. | |||
Pour forcer explicitement ce fonctionnement : | |||
# mnemosyne config set llm_enabled false | |||
# mnemosyne config set host_llm_enabled false | |||
# mnemosyne config set llm_base_url "" | |||
# mnemosyne config set llm_api_key "" | |||
# mnemosyne config set llm_model "" | |||
Mnemosyne fonctionne alors sans LLM pour les opérations de consolidation et d'extraction. | |||
==== Utiliser le LLM local ==== | |||
Mnemosyne possède une configuration par défaut pour un petit LLM local GGUF utilisé pour les opérations de consolidation, de synthèse et d'extraction de faits. | |||
Le backend local n'est toutefois disponible que si ses dépendances optionnelles sont installées : | |||
# source ~/.hermes/hermes-agent/venv/bin/activate | |||
# python -m pip install -U 'mnemosyne-memory[all]' | |||
On active ensuite le support LLM de Mnemosyne et on désactive l'utilisation du LLM fourni par Hermes : | |||
# mnemosyne config set llm_enabled true | |||
# mnemosyne config set host_llm_enabled false | |||
Pour forcer l'utilisation du modèle local plutôt qu'un éventuel serveur LLM distant : | |||
# mnemosyne config set force_local true | |||
Par défaut, Mnemosyne utilise : | |||
* Dépôt : <code>openbmb/MiniCPM5-1B-GGUF</code> | |||
* Modèle : <code>MiniCPM5-1B-Q4_K_M.gguf</code> | |||
* Contexte : <code>2048</code> tokens | |||
* Sortie maximale : <code>2048</code> tokens | |||
* Threads CPU : <code>4</code> | |||
* Cache : <code>~/.hermes/mnemosyne/models</code> | |||
On peut enregistrer explicitement ces valeurs dans la configuration : | |||
# mnemosyne config set llm_repo "openbmb/MiniCPM5-1B-GGUF" | |||
# mnemosyne config set llm_file "MiniCPM5-1B-Q4_K_M.gguf" | |||
# mnemosyne config set llm_n_ctx 2048 | |||
# mnemosyne config set llm_max_tokens 2048 | |||
# mnemosyne config set llm_n_threads 4 | |||
# mnemosyne config set model_cache_dir "~/.hermes/mnemosyne/models" | |||
Le modèle GGUF est téléchargé dans le cache lors de sa première utilisation. | |||
Les valeurs par défaut correspondantes sont : | |||
MNEMOSYNE_LLM_ENABLED=true | |||
MNEMOSYNE_LLM_N_CTX=2048 | |||
MNEMOSYNE_LLM_MAX_TOKENS=2048 | |||
MNEMOSYNE_LLM_N_THREADS=4 | |||
MNEMOSYNE_LLM_REPO=openbmb/MiniCPM5-1B-GGUF | |||
MNEMOSYNE_LLM_FILE=MiniCPM5-1B-Q4_K_M.gguf | |||
MNEMOSYNE_MODEL_CACHE_DIR=~/.hermes/mnemosyne/models | |||
==== Utiliser le modèle auxiliaire de Hermes ==== | |||
Mnemosyne peut déléguer ses opérations LLM au client auxiliaire de Hermes. | |||
On active d'abord les opérations LLM de Mnemosyne ainsi que le backend fourni par Hermes : | |||
# mnemosyne config set llm_enabled true | |||
# mnemosyne config set host_llm_enabled true | |||
Pour utiliser directement la configuration auxiliaire de Hermes, on laisse les éventuelles surcharges Mnemosyne vides : | |||
# mnemosyne config set host_llm_provider "" | |||
# mnemosyne config set host_llm_model "" | |||
Pour utiliser le LLM auxiliaire de Hermes, le backend hôte doit également être activé dans l'environnement du service Hermes : | |||
# systemctl edit hermes-gateway.service | |||
[Service] | |||
Environment="MNEMOSYNE_HOST_LLM_ENABLED=true" | |||
Environment="MNEMOSYNE_LLM_ENABLED=true" | |||
Puis : | |||
# systemctl restart hermes-gateway.service | |||
Mnemosyne utilise alors la configuration <code>auxiliary.compression</code> de Hermes. Si aucun modèle auxiliaire particulier n'est configuré dans Hermes, la configuration par défaut fait utiliser à Hermes son modèle principal pour cette tâche. | |||
==== Utiliser un LLM via une API ==== | |||
Mnemosyne peut également utiliser directement un serveur compatible avec l'API OpenAI. | |||
On désactive dans ce cas le backend LLM fourni par Hermes : | |||
# mnemosyne config set host_llm_enabled false | |||
Puis on active le LLM et on configure l'API : | |||
# mnemosyne config set llm_enabled true | |||
# mnemosyne config set llm_base_url "http://<font color = blue>ADRESSE_SERVEUR</font>:<font color = blue>PORT</font>/v1" | |||
# mnemosyne config set llm_api_key "<font color = blue>CLEF_API</font>" | |||
# mnemosyne config set llm_model "<font color = blue>NOM_EXACT_DU_MODELE</font>" | |||
Cette API peut être fournie par exemple par llama.cpp, vLLM, Ollama, LM Studio ou tout autre serveur proposant une interface compatible avec l'API OpenAI. | |||
Si le serveur n'exige pas de clé API, <code>llm_api_key</code> peut rester vide : | |||
# mnemosyne config set llm_api_key "" | |||
=== Fin de la configuration === | |||
Après modification de la configuration, on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== Mise à jour === | |||
# source ~/.hermes/hermes-agent/venv/bin/activate | |||
# python -m pip install --upgrade mnemosyne-hermes | |||
# systemctl restart hermes-gateway.service | |||
== [https://github.com/stephenschoettler/hermes-lcm Hermes-LCM] == | |||
Hermes-LCM est un plugin de gestion de contexte « lossless » pour Hermes Agent. Lorsqu’il est utilisé comme moteur de contexte, il remplace la compression ponctuelle du contexte actif par un système persistant basé sur SQLite et une structure hiérarchique en DAG. | |||
On installe les fichiers du projet : | |||
# git clone https://github.com/stephenschoettler/hermes-lcm \ | |||
~/.hermes/plugins/hermes-lcm | |||
Puis on exécute le script d'installation afin d'exposer également le skill Hermes-LCM : | |||
# cd ~/.hermes/plugins/hermes-lcm | |||
# ./scripts/install.sh | |||
On active la configuration de Hermes pour activer le plugin : | |||
# vi ~/.hermes/config.yaml | |||
Dans la sction <code>plugins:</code> ajouter : | |||
<font color = grey>... | <font color = grey>... | ||
plugins:</font> | |||
- | enabled: | ||
- hermes-lcm | |||
<font color = grey>...</font> | |||
<font color = blue> | Puis rempalcer : | ||
<font color = grey>...</font> | |||
context: | |||
engine: compressor | |||
<font color = grey>...</font> | |||
Par : | |||
<font color = grey>...</font> | |||
context: | |||
engine: <font color = blue>lcm</font> | |||
<font color = grey>...</font> | |||
Enfin, on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== Mise à jour === | |||
# cd ~/.hermes/plugins/hermes-lcm && git pull --ff-only | |||
= MCP = | |||
== MCP pour remplacer les outils web natifs de Hermes == | |||
{{Méta bandeau | |||
| niveau = grave | |||
| icône = important | |||
| texte = Expérimental et non recommandé. Après de nombreux essais, l'utilisation de serveurs MCP pour remplacer des outils natifs destinés à des tâches basiques, comme la recherche web, complexifie fortement l'architecture de Hermes au quotidien. | |||
}} | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = important | |||
| texte = | |||
Utiliser des serveurs MCP pour remplacer les outils web natifs de Hermes augmente fortement le nombre d'outils disponibles, ce qui peut rendre leur gestion plus complexe pour les LLM. | |||
}} | |||
=== Désactiver Tool Search === | |||
Hermes utilise <code>Tool Search</code> pour éviter d'envoyer au modèle la description complète de tous les outils disponibles à chaque requête. | |||
Lorsque <code>Tool Search</code> est activé, Hermes conserve directement dans le contexte les outils principaux, tandis qu'une partie des outils supplémentaires — notamment ceux provenant des serveurs MCP et de certains plugins — est placée dans une liste d'outils différés. | |||
Le modèle doit alors retrouver l'outil dont il a besoin à l'aide de mécanismes comme : | |||
tool_search | |||
tool_describe | |||
tool_call | |||
Cela permet de réduire la taille du prompt lorsque des dizaines ou des centaines d'outils sont disponibles. | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = important | |||
| texte = Lorsque les outils web natifs de Hermes sont remplacés par des serveurs MCP, les outils de recherche web et de navigation peuvent eux-mêmes devenir des outils différés. Le modèle doit alors commencer par les rechercher ou en demander la description avant de pouvoir les utiliser. | |||
}} | |||
----- | |||
Dans : | |||
# vi ~/.hermes/config.yaml | |||
Ajouter ou modifier : | |||
tools: | |||
tool_search: | |||
enabled: off | |||
Puis redémarrer Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== [[IA_MCP#MCP-SearXNG|MCP-SearXNG]] === | |||
{{Méta bandeau | |||
| niveau = information | |||
| icône = important | |||
| texte = Depuis la version 0.7, SearXNG est pris en charge nativement par Hermes Agent pour les recherches web classiques. Un serveur MCP dédié n’est donc plus indispensable dans ce cas. En revanche, le MCP SearXNG reste utile pour accéder aux catégories spécialisées telles que les images, les vidéos ou d’autres paramètres avancés qui ne sont pas encore pleinement exposés par l’intégration native. Voir [[Hermes#SearXNG|configuration native SearXNG]] | |||
}} | |||
# vi ~/.hermes/config.yaml | |||
On inscrit le serveur MCP SearXNG (créer la section <code>mcp_servers</code> si absente) : | |||
<font color=grey>... | |||
mcp_servers:</font> | |||
searxng: | |||
url: http://<font color=blue>IP_MCP</font>:<font color=green>3000</font>/mcp | |||
<font color=grey>...</font> | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = modéré | |||
| texte = La section <code>mcp_servers</code> doit être au niveau racine (tout à gauche). Vérifier également que le port correspond bien à celui exposé par le conteneur MCP SearXNG. | |||
}} | |||
On redémarre le service : | |||
# systemctl restart hermes-gateway.service | |||
Ou depuis Hermes : | |||
/reload-mcp | |||
Test : | |||
# hermes mcp list | |||
# hermes mcp test searxng | |||
Le serveur <code>ihor-sokoliuk/mcp-searxng</code> expose notamment les outils suivants : | |||
searxng_web_search | |||
searxng_search_suggestions | |||
searxng_instance_info | |||
web_url_read | |||
* Prompt système recommandé (voir [[#Éditer_le_prompt_système|Éditer le prompt système]]) : | |||
<font color=grey>...</font> | |||
TOOLS: | |||
- For current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions, use searxng_web_search. | |||
- To read a specific URL, use web_url_read. | |||
- For search suggestions, use searxng_search_suggestions. | |||
- For SearXNG instance capabilities, categories, engines, locales, and plugins, use searxng_instance_info. | |||
<font color=grey>- For system tasks, use terminal.</font> | |||
RULES: | |||
<font color=grey>- Respond in the same language as the user. | |||
- Do not invent tool results. | |||
- If a tool fails, say so explicitly. | |||
- Do not promise to continue later, follow up later, or say that results are still coming. | |||
- When the user asks multiple questions, use the tools needed, then answer all requested items in one final structured response.</font> | |||
- Never answer current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions without using the required tool first. | |||
- This includes weather, news, prices, schedules, releases, availability, rankings, versions, and other facts that may have changed. | |||
- If no tool result is available, say you cannot verify and do not guess. | |||
- Use search categories when relevant. | |||
- For image searches, use searxng_web_search with categories=images. | |||
- For video searches, use searxng_web_search with categories=videos. | |||
- For image search results, use the `img_src` field as the direct image URL. | |||
- When displaying an image result, ALWAYS output the direct image URL exactly in this format:  | |||
- Do not output the image URL as a normal Markdown link. | |||
- For video results, output links in this format: 🎬 [Titre de la vidéo](URL) | |||
- Do not use tools for simple rewriting, translation, or opinion unless needed. | |||
----- | |||
* Recommandation : | |||
Il est recommandé de désactiver le service natif correspondant : | |||
# hermes tools | |||
Décocher pour les environnements concernés : | |||
🔍 Web Search & Scraping (web_search, web_extract) [no API key] | |||
=== Skill pour aider la recherche et l'affichage d'images === | |||
Dans <code>SOUL.md</code> on remplace : | |||
- For image searches, use searxng_web_search with categories=images. | |||
- For image search results, use the `img_src` field as the direct image URL. | |||
- When displaying an image result, ALWAYS output the direct image URL exactly in this format:  | |||
- Do not output the image URL as a normal Markdown link. | |||
Par : | |||
- For any image or photo search, ALWAYS load and follow the `searxng-photo` skill before using any search, browser, or web tool. | |||
Puis on crée le skill : | |||
# mkdir -p ~/.hermes/skills/searxng-photo | |||
# vi ~/.hermes/skills/searxng-photo/SKILL.md | |||
<pre> | |||
--- | |||
name: searxng-photo | |||
description: Find and display an image using the SearXNG MCP image search tool. | |||
--- | |||
Use this skill when asked to find, show, or search for an image or photo. | |||
Steps: | |||
1. Call `mcp__searxng__searxng_web_search` with: | |||
- `query`: a concise image search query | |||
- `categories`: `"images"` | |||
- `num_results`: `5` | |||
- `response_format`: `"json"` | |||
2. Select a relevant result containing `img_src`. | |||
3. For each selected image result, output its direct `img_src` URL using this exact Markdown format: | |||
 | |||
Replace `DIRECT_IMAGE_URL` with the exact value of the result's `img_src` field. | |||
Rules: | |||
- `categories` must be the string `"images"`, not an array. | |||
- Use `num_results`, not `max_results`. | |||
- Use the exact returned `img_src`. | |||
- Once a usable `img_src` is found, do not call another tool. | |||
- If no usable `img_src` is found, retry once with a better query. | |||
- Do not output the image URL as a normal link. | |||
</pre> | |||
Enfin on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
=== [[IA_MCP#CamoFox_MCP|MCP-CamoFox]] === | |||
On inscrit le serveur MCP CamoFox (créer la section <code>mcp_servers</code> si absente) : | |||
<font color=grey>... | |||
mcp_servers:</font> | |||
camofox: | |||
url: http://<font color=blue>IP_MCP</font>:<font color=green>3000</font>/mcp | |||
headers: | |||
Authorization: Bearer <font color=blue>UNE_CLE_ALEATOIRE_DE_32_CARACTERES_MINIMUM</font> | |||
<font color=grey>...</font> | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = modéré | |||
| texte = La section <code>mcp_servers</code> doit être au niveau racine (tout à gauche). | |||
}} | |||
On redémarre le service : | On redémarre le service : | ||
# systemctl restart hermes-gateway | |||
# systemctl restart hermes-gateway.service | |||
Ou depuis Hermes : | |||
/reload-mcp | |||
Test : | |||
# hermes mcp list | |||
# hermes mcp test camofox | |||
* Prompt système recommandé (avec le [[Hermes#MCP-SearXNG|MCP-SearXNG]]) (voir [[#Éditer_le_prompt_système|Éditer le prompt système]]) : | |||
<font color=grey>... | |||
TOOLS:</font> | |||
- For browser navigation, clicking, typing, page interaction, snapshots, screenshots, or rendered page inspection, use the Camofox MCP tools. | |||
- Do not use Camofox web_search for general web searches; use searxng_web_search instead. | |||
<font color=grey>... | |||
RULES:</font> | |||
- Do not use memory for ordinary factual lookups, web searches, image searches, or one-off questions unless the user explicitly asks to remember or recall something. | |||
- Do not search local files for ordinary factual or web questions unless the user explicitly asks about local files or documents. | |||
----- | |||
* Recommandation : | |||
Il est recommandé de désactiver le service natif correspondant : | |||
# hermes tools | |||
Décocher pour les environnements concernés : | |||
[ ] 🌐 Browser Automation (navigate, click, type, scroll) | |||
=== Désactiver les outils web natifs de Hermes === | |||
Afin d'être sûr qu'Hermes n'expose plus ses outils web natifs aux modèles, il faut modifier la section <code>platform_toolsets</code> : | |||
# vi ~/.hermes/config.yaml | |||
On supprime les occurrences de <code>web</code> et <code>browser</code> dans les sections souhaitées. | |||
Il faut également éviter les toolsets composites susceptibles de les réintroduire, comme <code>hermes_cli</code>, et définir explicitement les outils souhaités. | |||
Pour les requêtes effectuées via l'API Hermes, notamment depuis OpenWebUI, on crée également une section <code>api_server</code>. | |||
Exemple : | |||
<font color = grey>...</font> | |||
platform_toolsets: | |||
cli: | |||
- clarify | |||
- code_execution | |||
- computer_use | |||
- cronjob | |||
- delegation | |||
- file | |||
- image_gen | |||
- mcp | |||
- memory | |||
- messaging | |||
- session_search | |||
- skills | |||
- terminal | |||
- todo | |||
- tts | |||
- vision | |||
telegram: | |||
- hermes-telegram | |||
discord: | |||
- clarify | |||
- code_execution | |||
- computer_use | |||
- cronjob | |||
- delegation | |||
- file | |||
- image_gen | |||
- mcp | |||
- memory | |||
- session_search | |||
- skills | |||
- terminal | |||
- todo | |||
- tts | |||
- vision | |||
api_server: | |||
- clarify | |||
- code_execution | |||
- computer_use | |||
- context_engine | |||
- cronjob | |||
- delegation | |||
- discord | |||
- discord_admin | |||
- file | |||
- homeassistant | |||
- image_gen | |||
- mcp | |||
- memory | |||
- session_search | |||
- skills | |||
- spotify | |||
- stt | |||
- terminal | |||
- todo | |||
- tts | |||
- video | |||
- video_gen | |||
- vision | |||
- x_search | |||
- yuanbao | |||
<font color = grey>...</font> | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = modéré | |||
| texte = La liste ci-dessus est un exemple. Conserver uniquement les outils réellement utilisés. Le point important est de ne pas inclure <code>web</code>, <code>browser</code> ni un toolset composite susceptible de les réintroduire, tout en conservant <code>mcp</code> si les serveurs MCP doivent rester accessibles. | |||
}} | |||
Enfin on redémarre Hermes : | |||
# systemctl restart hermes-gateway.service | |||
== [[RAGFlow|RAGFlow]] == | |||
# vi ~/.hermes/config.yaml | |||
On inscrit le serveur MCP RAGFlow (créer la section <code>mcp_servers</code> si absente) : | |||
<font color=grey>... | |||
mcp_servers:</font> | |||
ragflow: | |||
url: http://<font color=blue>IP_MCP</font>:<font color=green>9382</font>/mcp | |||
<font color=grey>...</font> | |||
{{Méta bandeau | |||
| niveau = modéré | |||
| icône = modéré | |||
| texte = La section <code>mcp_servers</code> doit être au niveau racine (tout à gauche). | |||
}} | |||
On redémarre le service : | |||
# systemctl restart hermes-gateway.service | |||
Ou depuis Hermes : | |||
/reload-mcp | |||
Test : | |||
# hermes mcp list | |||
# hermes mcp test ragflow | |||
Prompt système recommandé : | |||
TOOLS: | |||
- For indexed documents, internal documentation, knowledge bases, or when the user asks to check the docs, use the RAGFlow MCP tools: ragflow_retrieval, ragflow_list_datasets, and ragflow_list_chats. | |||
RULES: | |||
- Do not use terminal/curl to query RAGFlow unless explicitly asked for a network diagnostic. | |||
- If no RAGFlow dataset exists or no relevant result is found, say so clearly. | |||
=== Rerank === | |||
Il faut d’abord identifier l’identifiant complet du modèle de reranking. | |||
[[File:Hermes ragflow rerank.webp|Exemple de reranker configuré dans RAGFlow.]] | |||
Dans cet exemple, l’identifiant est : | |||
/opt/models/jina-reranker-v3/Q8_0/jina-reranker-v3-Q8_0.gguf@Serveur Rerank@OpenAI-API-Compatible | |||
Il faut ensuite créer un skill Hermes afin de demander l’utilisation systématique du reranker lors des appels à <code>ragflow_retrieval</code>. | |||
* Créer le dossier du skill : | |||
# mkdir -p ~/.hermes/skills/ragflow-search | |||
* Créer le fichier principal du skill : | |||
# vi ~/.hermes/skills/ragflow-search/SKILL.md | |||
Y placer le contenu suivant : | |||
--- | |||
name: ragflow-search | |||
description: Use this skill whenever querying RAGFlow datasets through the `ragflow_retrieval` MCP tool. Always include the configured reranker. | |||
version: 1.0.0 | |||
--- | |||
# RAGFlow Search | |||
Use this skill for every call to the `ragflow_retrieval` MCP tool. | |||
## Tool | |||
Call the MCP tool: | |||
`ragflow_retrieval` | |||
Do not use a generic web search when the requested information is expected to be present in RAGFlow. | |||
## Mandatory reranker | |||
For every call to `ragflow_retrieval`, always include this exact argument: | |||
```yaml | |||
rerank_id: "<font color = blue>/opt/models/jina-reranker-v3/Q8_0/jina-reranker-v3-Q8_0.gguf@Serveur Rerank@OpenAI-API-Compatible</font>" | |||
``` | |||
Do not omit, shorten, rename, translate, or modify this value. | |||
## Dataset selection | |||
- Use `ragflow_list_datasets` when the relevant dataset ID is unknown. | |||
- Prefer selecting only the datasets relevant to the question. | |||
- Do not invent dataset IDs. | |||
- Omit `dataset_ids` only when searching across all datasets is appropriate. | |||
## Recommended retrieval parameters | |||
Use these defaults unless the task requires otherwise: | |||
```yaml | |||
page: 1 | |||
page_size: 10 | |||
top_k: 30 | |||
similarity_threshold: 0.2 | |||
vector_similarity_weight: 0.3 | |||
keyword: false | |||
``` | |||
## Verification | |||
Do not claim that reranking was used unless `rerank_id` was actually included in the tool call. | |||
If `ragflow_retrieval` is called without `rerank_id`, treat the call as invalid and retry it with the exact configured value. | |||
Une fois le fichier enregistré, démarrer une nouvelle session Hermes afin que le skill soit détecté. | |||
Dernière version du 28 octobre 2026 à 13:18
Prérequis
(Hermes seul)
- Une machine ou VM dédiée (LXC compatible / VM recommandée)
Pour un Hermes de base (sans LLM local) :
- RAM :
- 1 Go → minimum (test uniquement)
- 2 Go → recommandé
- 4 Go -> confortable
- CPU / vCPU :
- 1 vCPU → suffisant
- 2 vCPU → recommandé
- Espace disque :
- 5 Go → minimum
- 10 Go → confortable
- GPU :
- Inutile
Installation Hermes (service dédié)
Installation (Debian)
# apt update && apt upgrade # apt install curl git # curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
How would you like to set up Hermes? > (○) Quick setup — provider, model & messaging (recommended)
- Ollama local :
Select provider: >(○) Custom endpoint (enter URL manually)
Custom OpenAI-compatible endpoint configuration: API base URL [e.g. https://api.example.com/v1]: http://IP_OLLAMA:11434/v1 API key [optional]:
Detected model: mon_model Use this model? [Y/n]: Y
Context length in tokens [leave blank for auto-detect]:
Display name [192.168.2.216:11434]: Ollama
- Llama.cpp :
Select provider: >(○) Custom endpoint (enter URL manually)
Custom OpenAI-compatible endpoint configuration: API base URL [e.g. https://api.example.com/v1]: https://IP_OLLAMA:11434/v1
Remplir les options désirées puis fin de l'installation :
Launch hermes chat now? [Y/n]: y
Ensuite, inscrire Hermes comme service pour qu'il se lance automatiquement :
- Sur une machine physique ou VM :
# hermes gateway install --system
- Dans un LXC :
# hermes gateway install --system --run-as-user root
# systemctl enable hermes-gateway.service # systemctl start hermes-gateway.service
Configuration
Activer le serveur API
On édite le fichier :
# vi ~/.hermes/.env
Ajouter :
... API_SERVER_ENABLED=true API_SERVER_KEY="maclefsecrete" # pour autoriser toutes les interfaces : API_SERVER_HOST=0.0.0.0 # pour autoriser une seule interface : # API_SERVER_HOST=IP_HERMES API_SERVER_PORT=8642
On relance le service :
# systemctl restart hermes-gateway.service
Pour tester :
# curl http://IP_HERMES:8642/health
Doit renvoyer :
{"status":"ok"}
Pour vérifier le modèle exposé :
# curl http://IP_HERMES:8642/v1/models -H "Authorization: Bearer maclefsecrete"
Retarder le démarrage de Hermes au boot pour laisser le temps aux autres services de se lancer
# systemctl edit hermes-gateway.service
Ajouter dans la zone d’édition (partie supérieure du fichier) :
... ### Anything between here and the comment below will become the contents of the drop-in file [Service] ExecStartPre=/bin/sh -c 'uptime=$(cut -d. -f1 /proc/uptime); [ "$uptime" -lt 120 ] && sleep 30 || true' ### Edits below this comment will be discarded ...
Activer le backend Hermes
Le backend Hermes expose les API utilisées notamment par le Dashboard, Hermes Worspace, Hermes Desktop, les sessions, skills, configuration, jobs et certaines fonctions MCP.
La commande hermes serve permet de lancer ce backend en mode headless, sans ouvrir l'interface web du Dashboard.
Avant de modifier la configuration, on génère le hash du mot de passe qui sera utilisé pour l’authentification :
# python3 -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('MON_MOT_DE_PASSE'))"
La commande retourne une valeur de la forme :
scrypt$16384$8$1$...
On génère ensuite le secret utilisé pour signer les sessions :
# openssl rand -hex 32
On édite alors le fichier :
# vi ~/.hermes/.env
Ajouter :
... HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH="scrypt$16384$8$1$..." HERMES_DASHBOARD_BASIC_AUTH_SECRET="secret_généré_par_openssl" ...
On crée un service systemd pour lancer automatiquement le backend après Hermes Gateway :
# vi /etc/systemd/system/hermes-backend.service
Ajouter :
[Unit] Description=Hermes Backend Requires=hermes-gateway.service After=hermes-gateway.service [Service] Type=simple User=root Environment=HOME=/root EnvironmentFile=/root/.hermes/.env WorkingDirectory=/root ExecStartPre=/bin/sh -c 'until /usr/bin/curl -fsS http://IP_GATEWAY_HERMES:8642/health >/dev/null; do sleep 1; done' ExecStart=/root/.local/bin/hermes serve --host IP_BACKEND_HERMES --port 9119 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
On active le plugin pour authentifier le dashboard :
# hermes plugins enable dashboard_auth/basic
On recharge la configuration systemd :
# systemctl daemon-reload
On active le service au démarrage :
# systemctl enable hermes-backend.service
On le démarre :
# systemctl start hermes-backend.service
Pour vérifier son état :
# systemctl status hermes-backend.service
Pour suivre les logs :
# journalctl -u hermes-backend.service -f
Pour vérifier que le backend écoute :
# ss -lntp | grep 9119
Pour tester son API :
# curl http://IP_HERMES:9119/api/status
Pour ouvrir l'interface web d'administration, on peut toujours utiliser :
# hermes dashboard --host IP_DASHBOARD --port 9119 --no-open
Utiliser une CA privée avec Hermes
Si Hermes doit se connecter à un service HTTPS signé par une CA privée locale, il peut être nécessaire d’indiquer explicitement à Python et aux bibliothèques HTTP quel bundle de certificats utiliser.
Éditer l’override systemd du service :
# systemctl edit hermes-gateway.service
Ajouter dans la zone d’édition (partie supérieure du fichier) :
... ### Anything between here and the comment below will become the contents of the drop-in file [Service] Environment="SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" Environment="REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" Environment="CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" ### Edits below this comment will be discarded ...
Explication rapide :
SSL_CERT_FILE: utilisé par Python / OpenSSLREQUESTS_CA_BUNDLE: utilisé par la bibliothèque PythonrequestsCURL_CA_BUNDLE: utilisé parcurlet parfois comme variable de repli
Puis recharger et redémarrer le service :
# systemctl daemon-reload # systemctl restart hermes-gateway.service
Cas particulier : bundle certifi du venv Hermes
Dans certains cas, le runtime Python embarqué par Hermes peut continuer à utiliser le bundle interne de certifi au lieu du magasin système.
Si curl valide déjà le certificat avec /etc/ssl/certs/ca-certificates.crt mais que Hermes/OpenAI/httpx échoue avec CERTIFICATE_VERIFY_FAILED, on peut remplacer le bundle certifi du venv Hermes par le bundle système.
Sauvegarder le bundle actuel :
# cp /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem.bak
Remplacer par le bundle système :
# cp /etc/ssl/certs/ca-certificates.crt /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem
Attention : cette modification peut être écrasée lors d’une mise à jour de Hermes, du venv Python ou du paquet certifi.
Automatiser le remplacement du certificat du venv
On édite le service Hermes :
# systemctl edit hermes-gateway.service
Ajouter dans la zone d’édition (partie supérieure du fichier) :
... ### Anything between here and the comment below will become the contents of the drop-in file [Service] ExecStartPre=/bin/cp /etc/ssl/certs/ca-certificates.crt /root/.hermes/hermes-agent/venv/lib/python3.11/site-packages/certifi/cacert.pem ### Edits below this comment will be discarded ...
Puis recharger systemd et redémarrer le service :
# systemctl daemon-reload # systemctl restart hermes-gateway.service
Éditer le prompt système
On édite le fichier suivant :
# vi ~/.hermes/SOUL.md
Puis on modifie le contenu de SOUL.md, qui constitue la partie personnalisée du prompt système de Hermes, par exemple :
You are Hermes Agent, an intelligent AI assistant created by Nous Research. You are helpful, knowledgeable, and direct. You assist users with a wide range of tasks including answering questions, writing and editing code, analyzing information, creative work, and executing actions via your tools. You communicate clearly, admit uncertainty when appropriate, and prioritize being genuinely useful over being verbose unless otherwise directed below. Be targeted and efficient in your exploration and investigations.
TOOLS:
- For current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions, use searxng_web_search.
- To read a specific URL, use web_url_read.
- For search suggestions, use searxng_search_suggestions.
- For SearXNG instance capabilities, categories, engines, locales, and plugins, use searxng_instance_info.
- For indexed documents, internal documentation, knowledge bases, or when the user asks to check the docs, use the RAGFlow MCP tools: ragflow_retrieval, ragflow_list_datasets, and ragflow_list_chats.
RULES:
- Respond in the same language as the user.
- Do not invent tool results.
- If a tool fails, say so explicitly.
- Do not promise to continue later, follow up later, or say that results are still coming.
- When the user asks multiple questions, use the tools needed, then answer all requested items in one final structured response.
- Never answer current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions without using the required tool first.
- This includes weather, news, prices, schedules, releases, availability, rankings, versions, and other facts that may have changed.
- If no tool result is available, say you cannot verify and do not guess.
- Use search categories when relevant.
- For image searches, use searxng_web_search with categories=images.
- For video searches, use searxng_web_search with categories=videos.
- For image search results, use the `img_src` field as the direct image URL.
- When displaying an image result, ALWAYS output the direct image URL exactly in this format: 
- Do not output the image URL as a normal Markdown link.
- For video results, output links in this format: ~_~N [Titre de la vidéo](URL)
- Do not use tools for simple rewriting, translation, or opinion unless needed.
- Do not use terminal/curl to query RAGFlow unless explicitly asked for a network diagnostic.
- If no RAGFlow dataset exists or no relevant result is found, say so clearly.
Enfin, on redémarre le service :
# systemctl restart hermes-gateway.service
Installer les dépendances pour la voix du CLI
# cd ~/.hermes/hermes-agent # uv pip install --python ./venv/bin/python -e ".[voice]" # apt update # apt install libportaudio2
LXC
Voir audio passthrough
Signal
Signal est une messagerie instantanée axée sur la confidentialité. Tous les messages et appels y sont chiffrés de bout en bout par défaut via le Signal Protocol, de sorte que ni Signal ni un tiers ne peuvent en lire le contenu. Signal se distingue également par une collecte de données très limitée, l’absence de publicité et de traqueurs, ainsi qu’un effort particulier pour réduire les métadonnées accessibles au service.
Signal permet de relier Hermes à la messagerie chiffrée Signal.
La connexion ne se fait pas directement avec le téléphone, mais via signal-cli exécuté en mode daemon HTTP, auquel Hermes se connecte ensuite.
- Installation :
Via Docker
Procédure d'installation via Docker (non recommandée)
# mkdir -p /opt/signal-cli # vi /opt/signal-cli/docker-compose.yml
services:
signal-cli:
image: registry.gitlab.com/packaging/signal-cli/signal-cli-jre:latest
container_name: signal-cli
restart: unless-stopped
command: daemon --http 0.0.0.0:8080
ports:
- "IP_SERVEUR:8080:8080" # Remplacer par IP du serveur, ou 127.0.0.1 pour restreindre acces local uniquement
volumes:
- signal-cli-data:/var/lib/signal-cli
tmpfs:
- /tmp:exec
volumes:
signal-cli-data:
# docker compose -f /opt/signal-cli/docker-compose.yml --project-directory /opt/signal-cli up -d
- Connexion au téléphone :
Installer qrencode :
# apt install qrencode
Dans le terminal :
# docker exec signal-cli signal-cli link -n "HermesAgent" > /tmp/signal-link.txt 2>&1 & sleep 3 && grep -o 'sgnl://[^ ]*' /tmp/signal-link.txt | qrencode -t ANSIUTF8 && wait
Puis scanner le QR code avec l’application Signal via Paramètres -> Appareils associés.
- Connecter Hermes à Signal :
# hermes setup
Connect a messaging platform? (Telegram, Discord, etc.) -> ●) Set up messaging now (recommended)
Puis redémarrer le service :
# systemctl restart hermes-gateway.service
- Communiquer avec le serveur via Signal (depuis le téléphone dans l'application Signal) :
- Appuyer sur l’icône ✏️ (nouveau message)
- Tout en haut de la liste, "Note to Self" ou votre propre nom apparaît
- Taper votre message : Hermes répond dans cette même conversation
- (Optionnel) taper
/sethomepour définir le canal par défaut pour les notifications et les tâches planifiées.
Native
- Installation :
On installe les dépendances si nécessaire :
# apt update && apt upgrade # apt install tar qrencode openjdk-25-jre-headless
On s'assure que Java 25 est la version utilisée par défaut :
# update-alternatives --set java /usr/lib/jvm/java-25-openjdk-amd64/bin/java # java -version
On Installe le programme :
# cd /tmp
# VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//')
# curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz"
# tar xf "signal-cli-${VERSION}.tar.gz" -C /opt
# ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/
# rm /tmp/signal-cli-${VERSION}.tar.gz
Appareillage du téléphone :
# signal-cli link -n "HermesAgent" > /tmp/signal-link.txt 2>&1 & sleep 5 && grep -o 'sgnl://[^ ]*' /tmp/signal-link.txt | qrencode -t ANSIUTF8 && wait
Puis scanner le QR code avec l’application Signal via Paramètres -> Appareils associés.
On créé un service :
# vi /etc/systemd/system/signal-cli.service
[Unit] Description=signal-cli daemon After=network.target [Service] Environment="JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64" ExecStart=/usr/local/bin/signal-cli --account +VOTRE_NUMERO daemon --http 127.0.0.1:8080 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
# systemctl daemon-reload # systemctl enable --now signal-cli # systemctl status signal-cli
- Connecter Hermes à Signal :
# hermes setup
Connect a messaging platform? (Telegram, Discord, etc.) -> ●) Set up messaging now (recommended)
Puis redémarrer le service :
# systemctl restart hermes-gateway.service
- Communiquer avec le serveur via Signal (depuis le téléphone dans l'application Signal) :
- Appuyer sur l’icône ✏️ (nouveau message)
- Tout en haut de la liste, "Note to Self" ou votre propre nom apparaît
- Taper votre message : Hermes répond dans cette même conversation
- (Optionnel) taper
/sethomepour définir le canal par défaut pour les notifications et les tâches planifiées.
Mise à jour automatique
- Version native :
On créé un script :
# vi /usr/local/bin/update-signal-cli.sh
#!/bin/bash
set -e
systemctl stop signal-cli || true
cd /tmp
VERSION=$(curl -Ls -o /dev/null -w '%{url_effective}' https://github.com/AsamK/signal-cli/releases/latest | sed 's/^.*\/v//')
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}.tar.gz"
rm -rf "/opt/signal-cli-${VERSION}"
tar xf "signal-cli-${VERSION}.tar.gz" -C /opt
ln -sf "/opt/signal-cli-${VERSION}/bin/signal-cli" /usr/local/bin/signal-cli
rm -f "/tmp/signal-cli-${VERSION}.tar.gz"
# Vérifier la compatibilité Java
if ! signal-cli --version > /dev/null 2>&1; then
ERROR="$(signal-cli --version 2>&1 || true)"
echo "$ERROR"
REQUIRED="$(echo "$ERROR" | grep -oE 'class file (version|major version) [0-9]+' | grep -oE '[0-9]+' | tail -n1 || true)"
if [ -z "$REQUIRED" ]; then
echo "Impossible de détecter automatiquement la version Java requise."
echo "Installation de Java 21 par défaut..."
JAVA_VERSION=21
else
JAVA_VERSION=$((REQUIRED - 44))
echo "Class file version $REQUIRED détectée => Java $JAVA_VERSION requis."
fi
apt update
apt install -y "openjdk-${JAVA_VERSION}-jre-headless"
if [ -x "/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64/bin/java" ]; then
update-alternatives --set java "/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64/bin/java"
else
echo "Java $JAVA_VERSION installé, mais chemin update-alternatives non trouvé. Vérifie avec :"
echo "update-alternatives --config java"
fi
fi
systemctl start signal-cli
# chmod +x /usr/local/bin/update-signal-cli.sh
On ajoute le script au crontab :
# crontab -e
Ajouter :
... 0 3 1 * * /usr/local/bin/update-signal-cli.sh
- Version docker :
Voir Watchtower pour la mise à jour automatique de tous les containers Docker. (tuto à faire..)
SearXNG
Il faut d’abord avoir installé une instance SearXNG.
Sur le serveur Hermes, lancer :
# hermes tools
→ (○) Reconfigure an existing tool's provider or API key
→ (○) 🔍 Web Search & Scraping
→ (●) SearXNG [free · self-hosted] — Free, privacy-respecting metasearch. Point SEARXNG_URL at your instance. [active]
Entrer ensuite l’adresse de l’instance SearXNG :
SearXNG instance URL (e.g. http://localhost:8080) (Enter to keep current):
Scraping via Firecrawl
Il faut d’abord avoir installé une instance Firecrawl.
On renseigne l'adresse de l'instance Firecrawl :
# vi ~/.hermes/.env
... FIRECRAWL_API_URL=http://IP_DE_FIRECRAWL:3002 ...
Si besoin configurer l'API key :
... FIRECRAWL_API_KEY=c-xxxxxxxxxxxxxxxx ...
Ensuite on édite la configuration de Hermes :
# vi ~/.hermes/config.yaml
On remplace :
web: backend: searxng search_backend: extract_backend:
Par :
web: backend: searxng search_backend: searxng extract_backend: firecrawl
Enfin on redémarre Hermes :
# systemctl restart hermes-gateway.service
Camofox
Installation native
Il faut d’abord avoir installé une instance Camofox.
Sur le serveur Hermes, lancer :
# hermes tools
→ (○) Reconfigure an existing tool's provider or API key
→ (○) 🌐 Browser Automation
→ (●) Camofox [free · local] — Anti-detection browser (Firefox/Camoufox)
Entrer ensuite l’adresse de l’instance Camofox:
Camofox server URL (Enter to keep current):
- Règle prompt système facultative :
... RULES: - If `web_extract` fails or is blocked, use `browser_navigate` through the Camofox browser provider. ...
Via MCP
Voir MCP-CamoFox
Forcer les timeouts d'une IA locale pour une IA derrière une URL
Si l'API de votre IA locale est desservie derrière une URL publique, Hermes peut ne pas la détecter comme un fournisseur local. Il est possible de modifier les timeouts utilisés pour les fournisseurs locaux :
# vi ~/.hermes/.env
... HERMES_API_TIMEOUT=1800 HERMES_STREAM_READ_TIMEOUT=1800 # HERMES_STREAM_STALE_TIMEOUT=180 HERMES_API_CALL_STALE_TIMEOUT=900 HERMES_AGENT_TIMEOUT=900
# systemctl restart hermes-gateway.service
Fonctions auxiliaires
Configuration des modèles utilisés par Hermes pour les tâches secondaires, indépendamment du modèle principal de conversation.
Editer la section auxiliary dans :
# vi ~/.hermes/config.yaml
vision: analyse d’images (modèle multimodal avec vision)compression: compression et résumé du contexte (LLM texte avec un contexte suffisamment long)skills_hub: recherche et sélection de compétences (LLM texte léger)approval: évaluation et validation des actions sensibles (LLM texte léger et fiable)mcp: sélection et routage des outils MCP (LLM texte efficace en appel d’outils)title_generation: génération de titres de conversations (petit LLM texte rapide)tts_audio_tags: génération de balises expressives pour la synthèse vocale (LLM texte léger)triage_specifier: génération d’une spécification détaillée à partir d’une tâche placée dans le Triage du Kanban (LLM texte léger)kanban_decomposer: décomposition d’un projet en tâches Kanban (LLM texte avec de bonnes capacités de planification)profile_describer: génération d’une description de profil (LLM texte)curator: sélection et organisation du contenu (LLM texte avec de bonnes capacités de synthèse)monitor: analyse des résultats de surveillance (LLM texte léger)background_review: révision et analyse en arrière-plan (LLM texte)moa_reference: production d’une réponse de référence pour le MoA (LLM texte performant)moa_aggregator: agrégation et synthèse des réponses MoA (LLM texte performant avec un contexte long)memory_query_rewrite: reformulation des requêtes destinées aux systèmes de mémoire afin d'améliorer la pertinence de la recherche (LLM texte léger)goal_judge: évaluation de l'état d'un objectif actif afin de déterminer s'il est terminé, doit continuer ou doit attendre (LLM texte léger et fiable)
Note sur vision et les modèles principaux multimodaux
Certains modèles principaux (ex. Qwen3.6-27B) sont nativement multimodaux (encodeur vision intégré au checkpoint) — ce n’est donc pas systématiquement une histoire de « modèle texte qui ne sait pas voir ». Même dans ce cas, garder vision sur un petit modèle auxiliaire séparé reste recommandé pour trois raisons :
- Évite de mobiliser le modèle principal (VRAM + temps de calcul) pour une tâche que 4B suffit à traiter.
- Le petit modèle peut se décharger automatiquement (
--sleep-idle-seconds), pas forcément possible/souhaitable sur le principal. - Latence : un 4B répond bien plus vite qu’un 27B pour une simple description/OCR d’image.
Recommandations
Dans une configuration locale disposant de peu de VRAM disponible, il est recommandé d’attribuer certaines fonctions auxiliaires à des modèles plus petits et plus rapides, afin d’éviter de mobiliser inutilement le modèle principal.
vision: fortement recommandé avec un modèle multimodal séparé (environ 3 à 4 milliards de paramètres ; par exemple Qwen2.5-VL-3B-Instruct, Qwen3-VL-4B-Instruct ou Gemma 3 4B). Un modèle quantifié en Q4 est généralement suffisant pour l’analyse d’images courante. Pour de l’OCR/transcription de texte dense, augmenter--image-min-tokens/--image-max-tokens(ex. 2048/8192) et ajouter un--repeat-penalty 1.1pour éviter les boucles de génération sur du texte peu lisible à basse résolution.title_generation: recommandé avec un petit modèle texte très rapide (environ 0,5 à 3 milliards de paramètres ; par exemple Qwen3 0.6B, 1.7B ou un modèle instruct équivalent). Tâche simple, ne nécessite pas un modèle puissant.compression: recommandé avec un modèle texte disposant d’un contexte long et de bonnes capacités de résumé. Un petit modèle rapide peut convenir si sa qualité et sa fenêtre de contexte sont suffisantes.mcp: petit modèle texte fiable en sélection/appel d’outils (environ 3 à 8 milliards de paramètres). Éviter les modèles extrêmement petits si plusieurs outils ont des descriptions proches.approval: petit modèle texte fiable (environ 3 à 8 milliards de paramètres). Qualité et respect des consignes plus importants que la vitesse brute — valide des actions sensibles, ne pas sous-dimensionner.skills_hub,triage_specifier,tts_audio_tags,monitoretmemory_query_rewrite: petit modèle texte rapide suffisant (environ 1 à 4 milliards de paramètres).goal_judge: petit modèle texte rapide mais fiable (environ 1 à 4 milliards de paramètres). La sortie est courte et structurée ; un modèle rapide convient bien s'il respecte correctement les consignes et le format demandé.profile_describer: petit ou moyen modèle texte (environ 3 à 8 milliards de paramètres).kanban_decomposer,background_review: modèle texte intermédiaire avec de bonnes capacités de planification/analyse (environ 7 à 14 milliards de paramètres).curator: modèle texte intermédiaire à performant pour synthèse (7 à 14 milliards de paramètres, plus pour analyses complexes).moa_reference: modèle texte performant (14 milliards de paramètres ou plus).moa_aggregator: modèle texte performant avec contexte long (14B+, au moins 64 000 jetons de contexte).
Pour une première optimisation, il est conseillé de configurer en priorité :
vision: modèle multimodal de 3 à 4 milliards de paramètrestitle_generation: petit modèle texte très rapidetriage_specifier: petit modèle texte rapidememory_query_rewrite: petit modèle texte rapidegoal_judge: petit modèle texte rapide et fiablecompression: modèle disposant d’un contexte long et de bonnes capacités de résumé
Les autres fonctions peuvent rester sur provider: auto tant qu’elles ne provoquent pas de lenteurs, de délais d’attente ou une consommation excessive de ressources.
Contexte et reasoning recommandés par fonction
Le sur-dimensionnement du contexte (-c) est l’un des plus gros gaspillages de VRAM sur les petits modèles auxiliaires. Il est donc préférable d’adapter le contexte à chaque fonction plutôt que d’utiliser une valeur unique « confortable » pour toutes les routes.
Hermes permet également de contrôler le niveau de reasoning indépendamment pour chaque tâche auxiliaire avec :
auxiliary:
vision:
reasoning_effort: "none"
compression:
reasoning_effort: "low"
Les valeurs disponibles sont :
none, minimal, low, medium, high, xhigh, max et ultra.
Une valeur vide ou absente laisse le provider choisir son comportement par défaut.
| Fonction | Contexte suggéré | Reasoning suggéré | Remarque |
|---|---|---|---|
title_generation |
2-4K | none |
Ne voit généralement que les premiers messages. Aucun raisonnement complexe nécessaire. |
tts_audio_tags |
2-4K | none |
Annotation d’un passage de texte court. Le thinking apporte très peu. |
triage_specifier |
4-8K | none / minimal |
Développe une tâche courte du Triage Kanban en spécification plus détaillée. Un reasoning profond est généralement inutile. |
memory_query_rewrite |
4-8K | none / minimal |
Reformulation courte destinée à améliorer la recherche mémoire ; aucun reasoning profond n'est normalement nécessaire. |
goal_judge |
4-8K | none / minimal |
Évalue l'objectif et la dernière réponse pour produire un verdict structuré. La fiabilité du respect du format est plus importante que la profondeur du reasoning. |
skills_hub |
4-8K | none / minimal |
Recherche ou sélection de compétences. Un reasoning profond est inutile dans la majorité des cas. |
monitor |
8K | none / minimal |
Selon la taille des données surveillées. Le plus souvent détection/classification. |
profile_describer |
8K | low |
Synthèse d’un historique modéré. |
approval |
8-16K | low / medium |
Analyse d’une action proposée et de son contexte. Conserver davantage de reasoning pour les décisions sensibles. |
mcp |
8-16K | low |
Dépend principalement du nombre et de la taille des définitions d’outils. Un peu de reasoning aide à sélectionner correctement l’outil. |
kanban_decomposer |
8-16K | low / medium |
Décomposition d’un projet en tâches ; le reasoning peut réellement améliorer la structure. |
vision |
16K | none |
Recommandé pour description/OCR simple : le modèle principal peut effectuer le raisonnement ensuite. Passer à low pour diagrammes ou analyse visuelle complexe. Ajuster le contexte si usage OCR intensif.
|
curator |
16-32K | low |
Peut agréger plusieurs sources et doit sélectionner les éléments pertinents. |
background_review |
16-32K | low / hérité |
Si un modèle auxiliaire distinct est utilisé, low est généralement suffisant. Un review fork utilisant le même modèle que l’agent hérite du reasoning du modèle principal.
|
moa_reference |
32K ou plus | Par preset | Le reasoning ne se configure pas via auxiliary.moa_reference.reasoning_effort. Il se règle individuellement dans moa.presets.<nom>.reference_models[].reasoning_effort.
|
compression |
64-128K typiquement | low |
Nécessite une fenêtre de contexte suffisamment grande pour recevoir le contenu à compresser. |
moa_aggregator |
64K minimum, souvent davantage | Par preset, généralement medium / high |
Agrège plusieurs réponses longues et bénéficie réellement du reasoning. Le réglage se fait dans moa.presets.<nom>.aggregator.reasoning_effort.
|
Quand désactiver le reasoning
Le reasoning peut généralement être désactivé avec reasoning_effort: "none" lorsque la tâche consiste principalement à classer, annoter, extraire ou décrire des données sans prise de décision complexe.
Bonnes candidates :
title_generationtts_audio_tagstriage_specifiermemory_query_rewritegoal_judgevisionpour description ou OCR simplemonitorskills_hub
Pour les tâches de synthèse ou de décision, low constitue généralement un meilleur compromis :
compressionprofile_describercuratormcp
Les tâches de planification ou d’agrégation complexe peuvent conserver medium ou davantage :
kanban_decomposerapprovalpour les décisions sensiblesmoa_aggregator
À noter que reasoning_effort est un raccourci Hermes. Si un extra_body.reasoning explicite est également défini pour la même tâche, celui-ci est prioritaire.
Pour le modèle principal, le réglage global reste :
agent: reasoning_effort: "medium"
et peut être modifié temporairement dans une session avec :
/reasoning none /reasoning low /reasoning medium /reasoning high
Le réglage /reasoning concerne le modèle principal ; il ne remplace pas les réglages reasoning_effort propres aux tâches auxiliaires.
Cas particulier de la compression
Le contexte nécessaire pour compression dépend directement du volume de contexte transmis au modèle auxiliaire.
Le réglage général de la compression se fait dans :
~/.hermes/config.yaml
Par défaut :
compression: enabled: true threshold: 0.50
threshold représente une fraction de la fenêtre de contexte du modèle principal.
Par exemple, avec un modèle principal configuré à 262144 tokens :
262144 × 0.50 = 131072 tokens
La compression peut donc être déclenchée autour de 131K tokens.
Le modèle auxiliaire lui-même se configure séparément :
auxiliary:
compression:
provider: auto
model: NOM_DU_MODELE
base_url: http://ADRESSE:PORT/v1
api_key: CLE_API
timeout: 120
Le modèle utilisé pour la compression doit disposer d'une fenêtre de contexte suffisamment grande pour traiter les données que Hermes lui transmet.
Dans le cas d'un petit modèle local disposant malgré tout d'un contexte long, comme LFM2.5-2.6B configuré à 128K, celui-ci peut être particulièrement intéressant grâce à son coût réduit et à sa vitesse élevée de traitement du prompt.
Quantification (poids du modèle)
- Tâches à faible enjeu (
title_generation,tts_audio_tags,skills_hub,monitor,triage_specifier,memory_query_rewrite,goal_judge) : Q4_K_M suffit largement. - Tâches à enjeu réel (
approval,mcp,compression,vision) : privilégier Q5_K_M ou Q6_K — sur des modèles 4-8B, l’écart VRAM entre Q4 et Q6 reste faible (souvent < 1,5 Go), autant prendre la marge.
KV cache (contexte)
- En dessous de 16K de contexte : pas de quantification ou
q8_0/q8_0en KV cache partout par défaut sur les routes auxiliaires — risque de dégradation négligeable. - À partir de 32K (
moa_reference,compression) :q8_0/q8_0devient intéressant, avec un gain notable de mémoire pour un risque faible. moa_aggregatorà 64K+ : seule route où une approche plus poussée typeq8_0/q6_0+ Hadamard (si le fork le supporte) peut se justifier, vu le volume réel de KV cache à comprimer.
Réglages de la voix
Text-to-Speech (TTS)
# vi ~/.hermes/config.yaml
Configuration par défaut :
...
tts:
provider: edge
edge:
voice: en-US-AriaNeural
...
Parmi les options gratuites et simples proposées par Hermes, Edge constitue probablement le meilleur choix par défaut. Il est toutefois recommandé de sélectionner une voix adaptée à la langue utilisée. Exemple pour le français :
...
tts:
provider: edge
edge:
voice: fr-FR-DeniseNeural
...
TTS via CrispASR
Voir CrispASR
CrispASR expose une API de synthèse vocale compatible avec l’API audio d’OpenAI. Hermes doit donc utiliser le fournisseur openai pour envoyer le texte au serveur TTS.
- Dans le fichier
~/.hermes/config.yaml:
...
tts:
provider: openai
...
openai:
model: qwen3-tts-12hz-0.6b-base-q8_0
voice: default
base_url: http://IP_CRISPASR:7981/v1
consent_attestation: "I have the speaker's consent"
...
Lorsque CrispASR est lancé avec une voix de référence fixe, la valeur default peut être utilisée pour l’option voice. La voix réellement utilisée dépend alors du fichier WAV et de sa transcription chargés par le serveur.
Le nom du modèle exposé peut être vérifié avec la commande suivante :
curl http://IP_CRISPASR:7980/v1/models
- Dans le fichier
~/.hermes/.env:
... VOICE_TOOLS_OPENAI_KEY=local ...
Speech-to-Text (STT)
# vi ~/.hermes/config.yaml
Configuration par défaut :
...
stt:
enabled: true
provider: local
local:
model: base
language:
openai:
model: whisper-1
mistral:
model: voxtral-mini-latest
elevenlabs:
model_id: scribe_v2
language_code:
tag_audio_events: false
diarize: false
...
Le Speech-to-Text permet de convertir les enregistrements vocaux en texte. Par défaut, Hermes utilise localement faster-whisper avec le modèle base. Cette solution est gratuite, ne nécessite aucune clé API et conserve les enregistrements sur la machine.
Lorsque le champ language reste vide, la langue est détectée automatiquement. Il est toutefois possible de préciser la langue afin de limiter les erreurs de détection, par exemple avec fr pour le français.
Le modèle base offre un bon compromis entre rapidité et consommation de ressources, mais il peut manquer de précision avec les noms propres, les nombres, les adresses IP ou les termes techniques. Il est alors possible d’utiliser un modèle local plus volumineux, par exemple small ou medium. Plus le modèle est grand, plus la transcription est généralement précise, mais plus elle demande de mémoire et de temps de traitement.
Exemple avec un modèle local plus précis configuré pour le français :
... stt: enabled: true provider: local local: model: small language: fr ...
Hermes peut également utiliser un service externe de reconnaissance vocale, par exemple OpenAI, Mistral ou ElevenLabs. Dans ce cas, il suffit de sélectionner le fournisseur souhaité avec l’option provider et de renseigner la clé API correspondante dans le fichier ~/.hermes/.env.
STT via CrispASR
Voir CrisASR
CrispASR expose une API compatible avec l’API audio d’OpenAI. Hermes doit donc utiliser le fournisseur openai pour envoyer les fichiers audio au serveur.
- Dans le fichier
~/.hermes/config.yaml(exemple avec parakeet-tdt-0.6b-v3) :
...
stt:
enabled: true
provider: openai
local:
model: small
language: 'fr'
openai:
model: parakeet-tdt-0.6b-v3-q8_0
...
- Dans le fichier
~/.hermes/.env:
... VOICE_TOOLS_OPENAI_KEY=local STT_OPENAI_BASE_URL=http://IP_CRISPASR:7980/v1
Après modification, on redémarre Hermes afin que la nouvelle configuration soit prise en compte.
Changer le mode d'approbation des commandes
# vi ~/.hermes/config.yaml
approvals: mode: manual
Remplacer manual par smart pour confier l’évaluation des commandes sensibles à un LLM. Les opérations jugées sûres sont automatiquement autorisées, les opérations dangereuses sont refusées et les cas incertains sont soumis à l’utilisateur. Par défaut, Hermes utilise le modèle principal pour cette évaluation, sauf si un modèle auxiliaire spécifique est configuré pour la tâche approval.
Commandes
- Lancer l’interface interactive :
# hermes
- Choisir le modèle et le provider LLM :
# hermes model
- Configurer les outils disponibles :
# hermes tools
- Modifier une configuration spécifique :
# hermes config set
- Démarrer le gateway (Telegram, Discord, etc.) :
# hermes gateway
- Lancer le script de configuration complet :
# hermes setup
- Migrer depuis OpenClaw :
# hermes claw migrate
- Mettre à jour Hermes :
# hermes update
- Diagnostiquer les problèmes :
# hermes doctor
Modules d’extension et d’intégration
Ressource :
- Awesome Hermes Agent : liste de différentes extensions classé par catégorie.
- Hermes Agent skills : top selon le site hermes atlas
Pour accéder a toutes les fonctionnalités sur une connexion distante il est préférable de se connecter via SSH, sur le serveur Hermes Agent :
# ssh-keygen -t ed25519 -f ~/.ssh/hermes_desktop
Ne PAS entrer de mot de passe :
Enter passphrase for "/root/.ssh/hermes_desktop" (empty for no passphrase): Enter same passphrase again:
Ensuite, ajouter la clé publique aux clés autorisées du compte auquel Hermes Desktop doit se connecter :
# cat ~/.ssh/hermes_desktop.pub >> ~/.ssh/authorized_keys # chmod 600 ~/.ssh/authorized_keys
Windows
On lance PowerShell et on récupère la clef :
> scp utilisateur@IP_DU_SERVEUR:~/.ssh/hermes_desktop "$env:USERPROFILE\.ssh\hermes_desktop"
Dans Private Key Path il faudra alors entrer :
C:\Users\NOM_UTILISATEUR\.ssh\hermes_desktop
Sur le serveur Hermes Agent :
# apt update && apt upgrade # apt install -y git python3 python3-venv # cd /opt/ # git clone https://github.com/nesquena/hermes-webui.git # cd hermes-webui # ./ctl.sh start
On arrête temporairement le serveur :
# ./ctl.sh stop
On crée un service systemd pour qu'il se lance automatiquement :
# vi /etc/systemd/system/hermes-webui.service
[Unit] Description=Hermes WebUI Wants=network-online.target After=network-online.target [Service] Type=simple User=root Group=root WorkingDirectory=/opt/hermes-webui Environment=HOME=/root Environment=HERMES_HOME=/root/.hermes Environment=HERMES_WEBUI_HOST=127.0.0.1 Environment=HERMES_WEBUI_PORT=8787 EnvironmentFile=-/opt/hermes-webui/.env ExecStart=/bin/bash /opt/hermes-webui/start.sh --foreground Restart=on-failure RestartSec=5 KillSignal=SIGTERM TimeoutStopSec=20 [Install] WantedBy=multi-user.target
Par défaut l'interface n'est accessible que depuis le serveur, pour autoriser l'écoute sur une IP remplacer HERMES_WEBUI_HOST=127.0.0.1 par 0.0.0.0 ou une interface IP du serveur.
Ensuite on ajoute un mot de passe :
# vi /opt/hermes-webui/.env
HERMES_WEBUI_PASSWORD=MOT_DE_PASSE
# chmod 600 /opt/hermes-webui/.env
(Recommandé) On peut également conserver 127.0.0.1 et passer par un proxy Caddy.
On active le service systemd :
# systemctl daemon-reload # systemctl enable --now hermes-webui.service
Pour pouvoir utiliser un reverse-proxy il faut ajouter :
# vi /opt/hermes-webui/.env HERMES_WEBUI_PASSWORD=MOT_DE_PASSE HERMES_WEBUI_SECURE=1 HERMES_WEBUI_ALLOWED_ORIGINS=https://hermes.exemple.net HERMES_WEBUI_TRUST_FORWARDED_HOST=1 HERMES_WEBUI_TRUST_FORWARDED_FOR=1 HERMES_WEBUI_TRUST_FORWARDED_PROTO=1
# systemctl restart hermes-webui
Exemple de vhost Nginx :
server {
listen 80;
listen [::]:80;
server_name hermes.exemple.net;
return 301 https://$host$request_uri;
}
server {
server_name hermes.exemple.net;
# protection
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000" always;
client_max_body_size 256m;
location / {
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_http_version 1.1;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_pass http<font color = red>s</font>://192.168.1.123:8787;
proxy_ssl_verify off;
proxy_ssl_server_name on;
proxy_ssl_name 192.168.1.123;
proxy_buffering off;
proxy_cache off;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/hermes.exemple.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hermes.exemple.net/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
}
Mise à jour
Mettre à jour Hermes Agent :
# hermes update
Mettre à jour Hermes WebUI :
# cd /opt/hermes-webui # git pull --ff-only # systemctl restart hermes-webui.service
Garder toutes les parties de réponse ouvertes (extension keep-expanded)
Par défaut, Hermes WebUI replie automatiquement les parties intermédiaires d'une réponse (le texte que l'IA écrit entre deux appels d'outils) dès qu'il y en a plus de 3 : un lien Show N earlier updates apparaît pour les retrouver. Ce comportement est codé en dur (INTERIM_COLLAPSE_THRESHOLD=3 dans static/messages.js) et ne propose aucune option. Les modèles qui produisent beaucoup de petites notes de progression (Qwen par exemple) le rendent vite pénible, car le bloc de code final peut se retrouver dans une partie repliée.
Le WebUI supporte les extensions CSS (voir docs/EXTENSIONS.md dans le dépôt). Voici une petite extension maison qui désactive ce repli.
- Étape 1 — Créer le fichier CSS :
# mkdir -p ~/.hermes/webui/extensions # vi ~/.hermes/webui/extensions/keep-expanded.css
Y coller :
/* Extension hermes-webui : garder depliee chaque segment de reponse
(desactive le repli automatique des notes intermediaires). */
.interim-collapsed { display: revert !important; }
.interim-collapse-toggle { display: none !important; }
- Étape 2 — Déclarer l'extension au service : le service systemd lit déjà
EnvironmentFile=-/opt/hermes-webui/.env(voir le service plus haut), on y ajoute donc deux lignes :
# vi /opt/hermes-webui/.env
HERMES_WEBUI_EXTENSION_DIR=/root/.hermes/webui/extensions HERMES_WEBUI_EXTENSION_STYLESHEET_URLS=/extensions/keep-expanded.css
- Étape 3 — Redémarrer et vérifier :
# systemctl restart hermes-webui.service # systemctl is-active hermes-webui.service
Puis recharger la page du WebUI dans le navigateur (F5) : toutes les parties des réponses restent ouvertes, et le lien Show N earlier updates a disparu.
Retour en arrière : supprimer les deux lignes de /opt/hermes-webui/.env (ou le fichier CSS), puis relancer le service — le repli automatique revient.
Résistance aux mises à jour : cette configuration survit aux mises à jour normales (git pull dans /opt/hermes-webui puis redémarrage) :
.envest listé dans le.gitignoredu projet : git ne le touche jamais ;- le CSS vit dans
~/.hermes/webui/extensions/, hors du dépôt git — c'est le répertoire officiellement recommandé pour les extensions.
Seuls une réinstallation complète (suppression + re-clone) ou un changement de nom des classes interim-collapsed / interim-collapse-toggle côté développeur pourraient casser l'extension. Si le repli revient tout seul après une mise à jour, il suffit de vérifier ces sélecteurs dans le CSS.
Un espace de travail complet : orchestrez vos agents, parcourez la mémoire, gérez les compétences et contrôlez l’ensemble depuis une interface unique.
Docker
# mkdir -p /opt/hermes-workspace/hermes-workspace-data # chown -R 1000:1000 /opt/hermes-workspace/hermes-workspace-data # vi /opt/hermes-workspace/docker-compose.yml
services:
hermes-workspace:
image: ghcr.io/outsourc-e/hermes-workspace:latest
container_name: hermes-workspace
restart: unless-stopped
environment:
#HERMES_HOME: /home/workspace/.hermes
#HERMES_WORKSPACE_DIR: /workspace
HERMES_API_URL: http://IP_HERMES:8642
HERMES_DASHBOARD_URL: http://IP_HERMES:9119
HERMES_API_TOKEN: ""
HERMES_PASSWORD: "change-moi"
HERMES_DASHBOARD_BASIC_AUTH_USERNAME: "admin"
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD: "MOT_DE_PASSE_DASHBOARD"
HERMES_UID: 1000
HERMES_GID: 1000
COOKIE_SECURE: "0"
TRUST_PROXY: "0"
volumes:
- ./hermes-workspace-data:/home/workspace/.hermes
- ./workspace:/workspace
ports:
- "3000:3000"
# docker compose -f /opt/hermes-workspace/docker-compose.yml --project-directory /opt/hermes-workspace up -d
Exemple de vhost :
server {
listen 80;
listen [::]:80;
server_name hermes.exemple.net;
return 301 https://$host$request_uri;
}
server {
server_name hermes.exemple.net;
# protection
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000" always;
client_max_body_size 256m;
location = /api/terminal-stream {
proxy_pass http://IP_SERVEUR_HERMES:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_http_version 1.1;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_pass http://IP_SERVEUR_HERMES:3000;
# proxy_buffering off;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/hermes.exemple.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hermes.exemple.net/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
}
Fix Temporaire
On construit une version patché du conteneur :
# cd /opt/ # git clone https://github.com/outsourc-e/hermes-workspace.git # cd hermes-workspace # git fetch origin pull/758/head:pr-758 # git fetch origin pull/735/head:pr-759 # git checkout -b hermes-fixed origin/main # git cherry-pick f7a50c5dcad8ba0f88e8d29e6f85c60b07681362 # git cherry-pick 36b7192 # docker build -t hermes-workspace:fixed .
Dans le fichier docker-compose.yml remplacer image: ghcr.io/outsourc-e/hermes-workspace:latest par image: hermes-workspace:fixed.
# docker compose -f /opt/hermes-workspace/docker-compose.yml --project-directory /opt/hermes-workspace up -d
Réglage voix
Pour le moment le plus simple est d'utiliser mon fork.
Catalogue des Skills et serveurs MCP dans le conteneur
Pour le moment le plus simple est d'utiliser mon fork.
Modification de Dockerfile pour référence
Le catalogue des Skills nécessite le script skills-search.py de Hermes Workspace ainsi que certains modules de Hermes Agent.
Pour les intégrer directement à l'image Docker :
# cd /opt/hermes-workspace # vi Dockerfile
Ajouter les éléments suivant en bleu :
...
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl tini python3 python3-httpx python3-yaml \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd -r workspace && useradd -r -g workspace -u 10010 -m workspace
COPY scripts/skills-search.py /app/scripts/skills-search.py
RUN curl -L \
https://codeload.github.com/NousResearch/hermes-agent/tar.gz/refs/heads/main \
-o /tmp/hermes-agent.tar.gz \
&& mkdir -p /hermes-agent \
&& tar -xzf /tmp/hermes-agent.tar.gz -C /hermes-agent --strip-components=1 \
&& rm /tmp/hermes-agent.tar.gz
ENV PYTHONPATH=/hermes-agent
...
Puis plus bas :
... COPY --from=build --chown=workspace:workspace /app/dist ./dist COPY --from=build --chown=workspace:workspace /app/node_modules ./node_modules COPY --from=build --chown=workspace:workspace /app/package.json ./package.json COPY --from=build --chown=workspace:workspace /app/server-entry.js ./server-entry.js COPY --from=build --chown=workspace:workspace /app/skills ./skills COPY --chown=workspace:workspace docker/entrypoint.sh /usr/local/bin/docker-entrypoint.sh COPY --chown=workspace:workspace assets/mcp-presets.seed.json ./assets/mcp-presets.seed.json ...
Reconstruire ensuite l'image et recréer le conteneur :
# docker build -t hermes-workspace:fixed . # docker compose up -d --force-recreate
On peut vérifier le fonctionnement avec :
# docker exec hermes-workspace python3 -c \
'import httpx, yaml, tools.skills_hub; print("Skills Hub OK")'
Le résultat attendu est :
Skills Hub OK
Les opérations se déroulent directement sur l'hôte Hermes.
La configuration présentée ici utilise DonSeTch avec SearXNG et Firecrawl comme services locaux. Il faut d’abord avoir installé une instance SearXNG et installé une instance Firecrawl.
- On installe et active le plugin :
# hermes plugins install web-search-plus --enable
Répondre y si l’installation des dépendances Node est proposée :
Install them into the plugin's own node_modules now? [y/N]: y
Répondre yes si une autorisation est demandée :
This is a privileged capability: an override can intercept everything the agent routes through that tool. Grant it?
On initialise le plugin avec le preset self-hosted :
# hermes web-search-plus setup --preset self-hosted
L’assistant propose ensuite d’activer Jev :
Enable optional Jev (TypeSafe) for search-type overlay, extract quality, and language fill? [y/N]:
Jev est un service extérieur optionnel utilisé pour améliorer la détection du type de recherche, l’évaluation des extractions et la détection de la langue. Il n’est pas nécessaire pour une configuration locale avec SearXNG, DonSeTch et Firecrawl. Répondre :
n
On renseigne l’adresse de l’instance SearXNG :
# hermes config set SEARXNG_INSTANCE_URL http://IP_PRIVEE_SEARXNG:PORT
Si le service SearXNG est accessible via une adresse IP privée, il faut l’autoriser explicitement :
# hermes config set SEARXNG_ALLOW_PRIVATE 1
Le preset self-hosted peut utiliser Keenable comme service de secours extérieur sans clé API. Pour l’autoriser :
# hermes config set KEENABLE_ALLOW_PUBLIC 1
Cette commande doit être omise pour conserver une configuration strictement locale.
Pour que Web Search Plus considère Firecrawl comme configuré, une valeur doit être renseignée dans FIRECRAWL_API_KEY. Si l’instance locale n’utilise aucune authentification, employer une valeur factice :
# hermes config set FIRECRAWL_API_KEY local-firecrawl
- On installe DonSeTch :
# npm install -g --allow-scripts=donsetch,@google/genai,protobufjs donsetch
Pour s'assurer que le service Hermes puisse trouver Node :
# test -e /usr/local/bin/node || ln -s /root/.local/bin/node /usr/local/bin/node
On installe Chromium et Xvfb pour les fonctions nécessitant un navigateur :
# apt update # apt install chromium xvfb
On vérifie le fonctionnement de DonSeTch :
# /root/.hermes/node/bin/donsetch --version # /root/.hermes/node/bin/donsetch doctor
On enregistre le chemin du binaire dans le profil Hermes :
# hermes config set DONSETCH_BIN /root/.hermes/node/bin/donsetch
Le preset self-hosted limite le routage automatique à SearXNG et Keenable. Pour utiliser DonSeTch en priorité pour la recherche et Firecrawl pour l’extraction, on réinitialise la configuration avec le profil standard :
# python3 ~/.hermes/plugins/web-search-plus/setup.py config reset --yes # python3 ~/.hermes/plugins/web-search-plus/setup.py config set-routing on
On désactive les fournisseurs inutilisés :
# python3 ~/.hermes/plugins/web-search-plus/setup.py config disable brave # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable exa # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable linkup # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable octen # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable parallel # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable querit # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable serpbase # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable serper # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable tavily # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable tinyfish # python3 ~/.hermes/plugins/web-search-plus/setup.py config disable you
On définit les priorités de recherche et d’extraction :
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-priority donsetch,searxng # python3 ~/.hermes/plugins/web-search-plus/setup.py config set-extract-priority donsetch,firecrawl
On autorise l’utilisation automatique de DonSeTch :
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-auto-allow donsetch on
Si Keenable a été activé, on le définit comme fournisseur de secours :
# python3 ~/.hermes/plugins/web-search-plus/setup.py config set-fallback keenable
Cette commande doit également être omise pour conserver une configuration strictement locale.
Le preset self-hosted ajoute l’autorisation d’utiliser le service public Keenable dans le fichier de routage du plugin. Ce réglage étant ignoré sous Hermes, il faut supprimer uniquement le bloc correspondant dans ce fichier.
On édite le fichier de routage :
# vi ~/.hermes/plugins/config.json
On supprime uniquement le bloc suivant :
"keenable": {
"allow_public": true
},
Il ne faut pas supprimer les autres occurrences de keenable, notamment celles qui le définissent comme fournisseur de secours.
On ajoute ou modifie ensuite l’objet firecrawl situé à la racine du fichier :
"firecrawl": {
"api_url": "http://IP_FIRECRAWL:3002/v2/search",
"scrape_url": "http://IP_FIRECRAWL:3002/v2/scrape"
},
L’option suivante n’est nécessaire que si web_extract_plus doit être autorisé à extraire des pages situées sur un réseau privé ou un intranet :
"extract": {
"allow_private_urls": true
},
Les objets doivent être séparés par une virgule afin de conserver un fichier JSON valide. Les valeurs booléennes JSON s’écrivent en minuscules : true et false.
Hermes peut réessayer automatiquement les appels Web qui échouent auprès de services externes anonymes comme Exa, Parallel, Firecrawl ou Keenable. Web Search Plus disposant déjà de son propre fournisseur de secours, on désactive ce second mécanisme :
# hermes config set web.keyless_rescue false
On vérifie la syntaxe du fichier de routage :
# python3 -m json.tool ~/.hermes/plugins/config.json >/dev/null && echo "JSON valide"
On vérifie la configuration finale :
# hermes web-search-plus status # python3 ~/.hermes/plugins/web-search-plus/setup.py config show --json
Provider Web pour les outils natifs Hermes
Web Search Plus peut servir directement de backend aux outils natifs web_search et web_extract de Hermes.
On active Web Search Plus pour la recherche et l’extraction :
# hermes config set web.search_backend wsp # hermes config set web.extract_backend wsp
Le backend wsp ne doit être sélectionné pour l’extraction que si au moins un fournisseur compatible est disponible, comme DonSeTch ou Firecrawl.
Les outils natifs nécessitent que le toolset web reste activé. Si celui-ci figure dans agent.disabled_toolsets, il faut le retirer.
On vérifie l’intégration :
# hermes web-search-plus fastpath # hermes web-search-plus status
Enfin, on redémarre Hermes :
# systemctl restart hermes-gateway.service
Test
On teste directement le fournisseur Firecrawl :
# cd ~/.hermes/plugins/web-search-plus # FIRECRAWL_API_KEY=local-firecrawl python3 search.py --query "Hermes Agent latest release" --provider firecrawl --quality-report
On lance ensuite Hermes :
# hermes
On lui demande d’effectuer une recherche avec Web Search Plus :
Recherche la dernière version de Hermes Agent en utilisant web_search_plus et indique le fournisseur utilisé.
On peut également demander un test explicite de DonSeTch :
Recherche la documentation de Hermes Agent avec web_search_plus en imposant le fournisseur donsetch.
Mise à jour
- Hermes Web Search Plus
# hermes plugins update web-search-plus
Si l’installation des dépendances Node est de nouveau proposée, répondre y.
Le scanner de sécurité de Hermes peut désactiver le plugin après une mise à jour. Si nécessaire, le réactiver :
# hermes plugins enable web-search-plus
Puis redémarrer Hermes :
# systemctl restart hermes-gateway.service
- DonSeTch
On met à jour DonSeTch vers la dernière version disponible :
# npm install -g --allow-scripts=donsetch,@google/genai,protobufjs donsetch@latest
On vérifie ensuite la version et le bon fonctionnement de DonSeTch :
# /root/.hermes/node/bin/donsetch --version # /root/.hermes/node/bin/donsetch doctor
Sources :
Mnemosyne est une couche de mémoire universelle, conçue en priorité pour Hermes, mais compatible avec n’importe quel framework d’agents.
- On installe le plugin :
# source ~/.hermes/hermes-agent/venv/bin/activate # python -m ensurepip --upgrade # python -m pip install --upgrade pip # python -m pip install mnemosyne-hermes # mkdir -p ~/.hermes/plugins/mnemosyne # ln -sfn "$(~/.hermes/hermes-agent/venv/bin/python -c 'import pathlib, mnemosyne_hermes; print(pathlib.Path(mnemosyne_hermes.__file__).resolve().parent)')"/* ~/.hermes/plugins/mnemosyne/ # hermes config set memory.provider mnemosyne
On édite ensuite la configuration de Hermes :
# vi ~/.hermes/config.yaml
... memory: memory_enabled: false user_profile_enabled: false ...
Ces deux options désactivent la mémoire native de Hermes (MEMORY.md et USER.md) afin d'utiliser Mnemosyne comme fournisseur de mémoire.
Embedding
Mnemosyne-Hermes est livré avec le support des embeddings locaux. Un modèle d'embedding est nécessaire au fonctionnement de la mémoire vectorielle ; il peut être exécuté localement ou fourni par un serveur externe.
Modèle local
Le modèle utilisé par défaut, BAAI/bge-small-en-v1.5, est principalement destiné à l'anglais. Pour un usage multilingue, on peut par exemple utiliser le modèle léger sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 :
# mnemosyne config set embedding_model sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 # mnemosyne config set embedding_dim 384 # mnemosyne config set embedding_api_url "" # mnemosyne config set embedding_api_key "" # mnemosyne config set embeddings_via_api false
Le modèle local est téléchargé automatiquement lors de sa première utilisation.
Voir la liste des modèles d'embedding disponibles.
Serveur d'embedding externe
Mnemosyne peut également utiliser un serveur d'embedding compatible avec l'API OpenAI :
# mnemosyne config set embedding_api_url "http://ADRESSE_SERVEUR:PORT/v1" # mnemosyne config set embedding_api_key "CLEF_API" # mnemosyne config set embedding_model "NOM_EXACT_DU_MODELE" # mnemosyne config set embedding_dim DIMENSION_DU_MODELE # mnemosyne config set embeddings_via_api true
La valeur de embedding_dim doit impérativement correspondre à la dimension produite par le modèle d'embedding utilisé.
Attention : changer de modèle d'embedding ou de dimension sur une base Mnemosyne contenant déjà des données peut nécessiter une reconstruction des embeddings existants.
Changer de modèle d'embedding ou de dimension
Pour changer de modèle d'embedding en toute sécurité, il faut d'abord enregistrer le nouveau modèle et, si nécessaire, sa dimension dans la configuration utilisée par Hermes après redémarrage.
On arrête ensuite Hermes ainsi que tout autre processus susceptible d'écrire dans la même base SQLite :
# systemctl stop hermes-gateway.service
On vérifie alors le plan de réindexation sans modifier la base :
# mnemosyne reindex --model NOM_EXACT_DU_MODELE --dry-run
La commande doit afficher le modèle et la dimension attendus. Il ne faut pas poursuivre si ces valeurs ne correspondent pas à la configuration qui sera utilisée après le redémarrage.
Une fois le résultat vérifié, on lance la réindexation :
# mnemosyne reindex --model NOM_EXACT_DU_MODELE --yes
Par défaut, Mnemosyne crée une sauvegarde, recalcule les embeddings des mémoires de travail et épisodiques et, lorsque sqlite-vec est disponible, reconstruit les tables vectorielles avec la dimension définie par la configuration effective.
Attention : l'option --model ne remplace pas une valeur explicite de embedding_dim. Si une dimension est configurée, elle doit correspondre à la dimension réellement produite par le nouveau modèle.
On redémarre ensuite Hermes :
# systemctl start hermes-gateway.service
LLM optionnel
Mnemosyne peut utiliser un LLM en complément du modèle d'embedding.
Ce LLM n'est pas nécessaire au fonctionnement de base de la mémoire. Lorsqu'il est activé, il est notamment utilisé pour :
- la consolidation et la synthèse des souvenirs lors des opérations de
sleep; - l'extraction structurée de faits ;
- certaines opérations avancées basées sur un LLM.
En l'absence de LLM disponible, Mnemosyne peut continuer à fonctionner en utilisant ses mécanismes de traitement non-LLM.
Aucun LLM
Par défaut dans la configuration déclarée de Mnemosyne, le LLM est désactivé.
Pour forcer explicitement ce fonctionnement :
# mnemosyne config set llm_enabled false # mnemosyne config set host_llm_enabled false # mnemosyne config set llm_base_url "" # mnemosyne config set llm_api_key "" # mnemosyne config set llm_model ""
Mnemosyne fonctionne alors sans LLM pour les opérations de consolidation et d'extraction.
Utiliser le LLM local
Mnemosyne possède une configuration par défaut pour un petit LLM local GGUF utilisé pour les opérations de consolidation, de synthèse et d'extraction de faits.
Le backend local n'est toutefois disponible que si ses dépendances optionnelles sont installées :
# source ~/.hermes/hermes-agent/venv/bin/activate # python -m pip install -U 'mnemosyne-memory[all]'
On active ensuite le support LLM de Mnemosyne et on désactive l'utilisation du LLM fourni par Hermes :
# mnemosyne config set llm_enabled true # mnemosyne config set host_llm_enabled false
Pour forcer l'utilisation du modèle local plutôt qu'un éventuel serveur LLM distant :
# mnemosyne config set force_local true
Par défaut, Mnemosyne utilise :
* Dépôt :openbmb/MiniCPM5-1B-GGUF* Modèle :MiniCPM5-1B-Q4_K_M.gguf* Contexte :2048tokens * Sortie maximale :2048tokens * Threads CPU :4* Cache :~/.hermes/mnemosyne/models
On peut enregistrer explicitement ces valeurs dans la configuration :
# mnemosyne config set llm_repo "openbmb/MiniCPM5-1B-GGUF" # mnemosyne config set llm_file "MiniCPM5-1B-Q4_K_M.gguf" # mnemosyne config set llm_n_ctx 2048 # mnemosyne config set llm_max_tokens 2048 # mnemosyne config set llm_n_threads 4 # mnemosyne config set model_cache_dir "~/.hermes/mnemosyne/models"
Le modèle GGUF est téléchargé dans le cache lors de sa première utilisation.
Les valeurs par défaut correspondantes sont :
MNEMOSYNE_LLM_ENABLED=true MNEMOSYNE_LLM_N_CTX=2048 MNEMOSYNE_LLM_MAX_TOKENS=2048 MNEMOSYNE_LLM_N_THREADS=4 MNEMOSYNE_LLM_REPO=openbmb/MiniCPM5-1B-GGUF MNEMOSYNE_LLM_FILE=MiniCPM5-1B-Q4_K_M.gguf MNEMOSYNE_MODEL_CACHE_DIR=~/.hermes/mnemosyne/models
Utiliser le modèle auxiliaire de Hermes
Mnemosyne peut déléguer ses opérations LLM au client auxiliaire de Hermes.
On active d'abord les opérations LLM de Mnemosyne ainsi que le backend fourni par Hermes :
# mnemosyne config set llm_enabled true # mnemosyne config set host_llm_enabled true
Pour utiliser directement la configuration auxiliaire de Hermes, on laisse les éventuelles surcharges Mnemosyne vides :
# mnemosyne config set host_llm_provider "" # mnemosyne config set host_llm_model ""
Pour utiliser le LLM auxiliaire de Hermes, le backend hôte doit également être activé dans l'environnement du service Hermes :
# systemctl edit hermes-gateway.service
[Service] Environment="MNEMOSYNE_HOST_LLM_ENABLED=true" Environment="MNEMOSYNE_LLM_ENABLED=true"
Puis :
# systemctl restart hermes-gateway.service
Mnemosyne utilise alors la configuration auxiliary.compression de Hermes. Si aucun modèle auxiliaire particulier n'est configuré dans Hermes, la configuration par défaut fait utiliser à Hermes son modèle principal pour cette tâche.
Utiliser un LLM via une API
Mnemosyne peut également utiliser directement un serveur compatible avec l'API OpenAI.
On désactive dans ce cas le backend LLM fourni par Hermes :
# mnemosyne config set host_llm_enabled false
Puis on active le LLM et on configure l'API :
# mnemosyne config set llm_enabled true # mnemosyne config set llm_base_url "http://ADRESSE_SERVEUR:PORT/v1" # mnemosyne config set llm_api_key "CLEF_API" # mnemosyne config set llm_model "NOM_EXACT_DU_MODELE"
Cette API peut être fournie par exemple par llama.cpp, vLLM, Ollama, LM Studio ou tout autre serveur proposant une interface compatible avec l'API OpenAI.
Si le serveur n'exige pas de clé API, llm_api_key peut rester vide :
# mnemosyne config set llm_api_key ""
Fin de la configuration
Après modification de la configuration, on redémarre Hermes :
# systemctl restart hermes-gateway.service
Mise à jour
# source ~/.hermes/hermes-agent/venv/bin/activate # python -m pip install --upgrade mnemosyne-hermes # systemctl restart hermes-gateway.service
Hermes-LCM est un plugin de gestion de contexte « lossless » pour Hermes Agent. Lorsqu’il est utilisé comme moteur de contexte, il remplace la compression ponctuelle du contexte actif par un système persistant basé sur SQLite et une structure hiérarchique en DAG.
On installe les fichiers du projet :
# git clone https://github.com/stephenschoettler/hermes-lcm \ ~/.hermes/plugins/hermes-lcm
Puis on exécute le script d'installation afin d'exposer également le skill Hermes-LCM :
# cd ~/.hermes/plugins/hermes-lcm # ./scripts/install.sh
On active la configuration de Hermes pour activer le plugin :
# vi ~/.hermes/config.yaml
Dans la sction plugins: ajouter :
...
plugins:
enabled:
- hermes-lcm
...
Puis rempalcer :
... context: engine: compressor ...
Par :
... context: engine: lcm ...
Enfin, on redémarre Hermes :
# systemctl restart hermes-gateway.service
Mise à jour
# cd ~/.hermes/plugins/hermes-lcm && git pull --ff-only
MCP
MCP pour remplacer les outils web natifs de Hermes
Désactiver Tool Search
Hermes utilise Tool Search pour éviter d'envoyer au modèle la description complète de tous les outils disponibles à chaque requête.
Lorsque Tool Search est activé, Hermes conserve directement dans le contexte les outils principaux, tandis qu'une partie des outils supplémentaires — notamment ceux provenant des serveurs MCP et de certains plugins — est placée dans une liste d'outils différés.
Le modèle doit alors retrouver l'outil dont il a besoin à l'aide de mécanismes comme :
tool_search tool_describe tool_call
Cela permet de réduire la taille du prompt lorsque des dizaines ou des centaines d'outils sont disponibles.
Dans :
# vi ~/.hermes/config.yaml
Ajouter ou modifier :
tools:
tool_search:
enabled: off
Puis redémarrer Hermes :
# systemctl restart hermes-gateway.service
# vi ~/.hermes/config.yaml
On inscrit le serveur MCP SearXNG (créer la section mcp_servers si absente) :
...
mcp_servers:
searxng:
url: http://IP_MCP:3000/mcp
...
On redémarre le service :
# systemctl restart hermes-gateway.service
Ou depuis Hermes :
/reload-mcp
Test :
# hermes mcp list # hermes mcp test searxng
Le serveur ihor-sokoliuk/mcp-searxng expose notamment les outils suivants :
searxng_web_search searxng_search_suggestions searxng_instance_info web_url_read
- Prompt système recommandé (voir Éditer le prompt système) :
... TOOLS: - For current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions, use searxng_web_search. - To read a specific URL, use web_url_read. - For search suggestions, use searxng_search_suggestions. - For SearXNG instance capabilities, categories, engines, locales, and plugins, use searxng_instance_info. - For system tasks, use terminal. RULES: - Respond in the same language as the user. - Do not invent tool results. - If a tool fails, say so explicitly. - Do not promise to continue later, follow up later, or say that results are still coming. - When the user asks multiple questions, use the tools needed, then answer all requested items in one final structured response. - Never answer current, recent, upcoming, time-sensitive, location-specific, or uncertain factual questions without using the required tool first. - This includes weather, news, prices, schedules, releases, availability, rankings, versions, and other facts that may have changed. - If no tool result is available, say you cannot verify and do not guess. - Use search categories when relevant. - For image searches, use searxng_web_search with categories=images. - For video searches, use searxng_web_search with categories=videos. - For image search results, use the `img_src` field as the direct image URL. - When displaying an image result, ALWAYS output the direct image URL exactly in this format:  - Do not output the image URL as a normal Markdown link. - For video results, output links in this format: 🎬 [Titre de la vidéo](URL) - Do not use tools for simple rewriting, translation, or opinion unless needed.
- Recommandation :
Il est recommandé de désactiver le service natif correspondant :
# hermes tools
Décocher pour les environnements concernés :
🔍 Web Search & Scraping (web_search, web_extract) [no API key]
Skill pour aider la recherche et l'affichage d'images
Dans SOUL.md on remplace :
- For image searches, use searxng_web_search with categories=images. - For image search results, use the `img_src` field as the direct image URL. - When displaying an image result, ALWAYS output the direct image URL exactly in this format:  - Do not output the image URL as a normal Markdown link.
Par :
- For any image or photo search, ALWAYS load and follow the `searxng-photo` skill before using any search, browser, or web tool.
Puis on crée le skill :
# mkdir -p ~/.hermes/skills/searxng-photo # vi ~/.hermes/skills/searxng-photo/SKILL.md
--- name: searxng-photo description: Find and display an image using the SearXNG MCP image search tool. --- Use this skill when asked to find, show, or search for an image or photo. Steps: 1. Call `mcp__searxng__searxng_web_search` with: - `query`: a concise image search query - `categories`: `"images"` - `num_results`: `5` - `response_format`: `"json"` 2. Select a relevant result containing `img_src`. 3. For each selected image result, output its direct `img_src` URL using this exact Markdown format:  Replace `DIRECT_IMAGE_URL` with the exact value of the result's `img_src` field. Rules: - `categories` must be the string `"images"`, not an array. - Use `num_results`, not `max_results`. - Use the exact returned `img_src`. - Once a usable `img_src` is found, do not call another tool. - If no usable `img_src` is found, retry once with a better query. - Do not output the image URL as a normal link.
Enfin on redémarre Hermes :
# systemctl restart hermes-gateway.service
On inscrit le serveur MCP CamoFox (créer la section mcp_servers si absente) :
...
mcp_servers:
camofox:
url: http://IP_MCP:3000/mcp
headers:
Authorization: Bearer UNE_CLE_ALEATOIRE_DE_32_CARACTERES_MINIMUM
...
On redémarre le service :
# systemctl restart hermes-gateway.service
Ou depuis Hermes :
/reload-mcp
Test :
# hermes mcp list # hermes mcp test camofox
- Prompt système recommandé (avec le MCP-SearXNG) (voir Éditer le prompt système) :
... TOOLS: - For browser navigation, clicking, typing, page interaction, snapshots, screenshots, or rendered page inspection, use the Camofox MCP tools. - Do not use Camofox web_search for general web searches; use searxng_web_search instead. ... RULES: - Do not use memory for ordinary factual lookups, web searches, image searches, or one-off questions unless the user explicitly asks to remember or recall something. - Do not search local files for ordinary factual or web questions unless the user explicitly asks about local files or documents.
- Recommandation :
Il est recommandé de désactiver le service natif correspondant :
# hermes tools
Décocher pour les environnements concernés :
[ ] 🌐 Browser Automation (navigate, click, type, scroll)
Désactiver les outils web natifs de Hermes
Afin d'être sûr qu'Hermes n'expose plus ses outils web natifs aux modèles, il faut modifier la section platform_toolsets :
# vi ~/.hermes/config.yaml
On supprime les occurrences de web et browser dans les sections souhaitées.
Il faut également éviter les toolsets composites susceptibles de les réintroduire, comme hermes_cli, et définir explicitement les outils souhaités.
Pour les requêtes effectuées via l'API Hermes, notamment depuis OpenWebUI, on crée également une section api_server.
Exemple :
...
platform_toolsets:
cli:
- clarify
- code_execution
- computer_use
- cronjob
- delegation
- file
- image_gen
- mcp
- memory
- messaging
- session_search
- skills
- terminal
- todo
- tts
- vision
telegram:
- hermes-telegram
discord:
- clarify
- code_execution
- computer_use
- cronjob
- delegation
- file
- image_gen
- mcp
- memory
- session_search
- skills
- terminal
- todo
- tts
- vision
api_server:
- clarify
- code_execution
- computer_use
- context_engine
- cronjob
- delegation
- discord
- discord_admin
- file
- homeassistant
- image_gen
- mcp
- memory
- session_search
- skills
- spotify
- stt
- terminal
- todo
- tts
- video
- video_gen
- vision
- x_search
- yuanbao
...
Enfin on redémarre Hermes :
# systemctl restart hermes-gateway.service
# vi ~/.hermes/config.yaml
On inscrit le serveur MCP RAGFlow (créer la section mcp_servers si absente) :
...
mcp_servers:
ragflow:
url: http://IP_MCP:9382/mcp
...
On redémarre le service :
# systemctl restart hermes-gateway.service
Ou depuis Hermes :
/reload-mcp
Test :
# hermes mcp list # hermes mcp test ragflow
Prompt système recommandé :
TOOLS: - For indexed documents, internal documentation, knowledge bases, or when the user asks to check the docs, use the RAGFlow MCP tools: ragflow_retrieval, ragflow_list_datasets, and ragflow_list_chats. RULES: - Do not use terminal/curl to query RAGFlow unless explicitly asked for a network diagnostic. - If no RAGFlow dataset exists or no relevant result is found, say so clearly.
Rerank
Il faut d’abord identifier l’identifiant complet du modèle de reranking.
Dans cet exemple, l’identifiant est :
/opt/models/jina-reranker-v3/Q8_0/jina-reranker-v3-Q8_0.gguf@Serveur Rerank@OpenAI-API-Compatible
Il faut ensuite créer un skill Hermes afin de demander l’utilisation systématique du reranker lors des appels à ragflow_retrieval.
- Créer le dossier du skill :
# mkdir -p ~/.hermes/skills/ragflow-search
- Créer le fichier principal du skill :
# vi ~/.hermes/skills/ragflow-search/SKILL.md
Y placer le contenu suivant :
--- name: ragflow-search description: Use this skill whenever querying RAGFlow datasets through the `ragflow_retrieval` MCP tool. Always include the configured reranker. version: 1.0.0 --- # RAGFlow Search Use this skill for every call to the `ragflow_retrieval` MCP tool. ## Tool Call the MCP tool: `ragflow_retrieval` Do not use a generic web search when the requested information is expected to be present in RAGFlow. ## Mandatory reranker For every call to `ragflow_retrieval`, always include this exact argument: ```yaml rerank_id: "/opt/models/jina-reranker-v3/Q8_0/jina-reranker-v3-Q8_0.gguf@Serveur Rerank@OpenAI-API-Compatible" ``` Do not omit, shorten, rename, translate, or modify this value. ## Dataset selection - Use `ragflow_list_datasets` when the relevant dataset ID is unknown. - Prefer selecting only the datasets relevant to the question. - Do not invent dataset IDs. - Omit `dataset_ids` only when searching across all datasets is appropriate. ## Recommended retrieval parameters Use these defaults unless the task requires otherwise: ```yaml page: 1 page_size: 10 top_k: 30 similarity_threshold: 0.2 vector_similarity_weight: 0.3 keyword: false ``` ## Verification Do not claim that reranking was used unless `rerank_id` was actually included in the tool call. If `ragflow_retrieval` is called without `rerank_id`, treat the call as invalid and retry it with the exact configured value.
Une fois le fichier enregistré, démarrer une nouvelle session Hermes afin que le skill soit détecté.