Déploiement
Ce guide met en place un pipeline de conversation pour la production. Sa mémoire de conversation Redis persiste entre les redémarrages et les workers, chiffre chaque valeur stockée, et lit ses secrets dans l'environnement. Si un seul processus vous suffit et que rien ne doit survivre à sa sortie, la mémoire en RAM convient et vous pouvez passer directement à Pipeline conversationnel.
Le pipeline lit sa forme dans un fichier de configuration. Le déploiement porte donc un fichier TOML et une poignée de variables d'environnement. Aucun code de pipeline n'est écrit à la main.
Installer les extras
La mémoire Redis tire trois extras au-delà de la couche de configuration, plus un pour le hacheur Argon2 utilisé plus bas.
uv add "piighost[config,redis,crypto,argon2]"pip install "piighost[config,redis,crypto,argon2]"L'extra config lit le fichier, redis parle au serveur Redis, crypto fournit le cipher AES-GCM, et argon2 fournit le hacheur Argon2id. Retirez argon2 si vous dérivez les clés avec HMAC-SHA256 à la place.
Écrire le fichier de configuration
Une section [memory] transforme le pipeline en pipeline de conversation gardant un état par conversation. Dans cette section, type = "redis" nomme le stockage. [memory.hasher] transforme chaque message en sa clé de stockage, et [memory.cipher] chiffre chaque valeur stockée.
[detector]
type = "regex"
catalogs = ["catalog:piighost/generic"]
[memory]
type = "redis"
url = "redis://redis.internal:6379/0"
namespace = "piighost"
ttl = 3600
[memory.hasher]
type = "argon2"
[memory.cipher]
type = "aesgcm"namespace préfixe chaque clé pour que piighost partage une instance Redis avec d'autres applications sans collision. ttl est le nombre de secondes qu'un message stocké vit avant que Redis ne l'évince. Omettez-le pour garder les entrées jusqu'à ce que Redis décide de les supprimer. Le fichier ne déclare ni linker ni anonymiseur, qui gardent leurs valeurs par défaut. L'anonymiseur par défaut émet <<PERSON:1>>, un jeton qui porte l'identité, c'est-à-dire qui désigne une seule valeur. Le middleware a besoin de cette identité pour restaurer la valeur.
Le catalogue complet des sections, chaque type de composant, et la forme JSON du même fichier se trouvent dans la référence de configuration.
Poser les secrets dans l'environnement
Le pepper du hacheur et la clé du cipher sont des secrets lus dans l'environnement à la construction du pipeline, jamais dans le fichier. Un fichier contenant un secret le laisserait fuiter par le gestionnaire de versions.
export PIIGHOST_HASH_PEPPER="a-long-random-string"
export PIIGHOST_CIPHER_KEY="$(openssl rand -base64 32)"PIIGHOST_HASH_PEPPER est n'importe quelle chaîne non vide. PIIGHOST_CIPHER_KEY est le base64 de 16, 24 ou 32 octets, donc openssl rand -base64 32 donne une clé AES-256. Si un guard de modération est configuré, son MISTRAL_API_KEY suit la même règle et ne vit que dans l'environnement.
Charger et exécuter
load_thread_pipeline lit le fichier, construit chaque composant, et renvoie le pipeline de conversation. Il lève ConfigError si le fichier ne déclare pas de [memory], de sorte qu'une configuration sans état ne peut pas être chargée ici par erreur.
import asyncio
from piighost.config import load_thread_pipeline
pipeline = load_thread_pipeline("pipeline.toml")
async def main() -> None:
result = await pipeline.anonymize(
"Write to alice@corp.com from 10.0.0.7.", thread_id="user-42"
)
print(result.text)
asyncio.run(main())La sortie doit être :
Write to <<EMAIL:1>> from <<IPV4:1>>.Le thread_id cadre la conversation. La même valeur dans un message ultérieur de user-42 garde son jeton. Un autre thread_id ne la voit jamais, si bien que deux utilisateurs restent isolés. En coulisses, le pipeline hache le message en une clé Redis et stocke les détections chiffrées. Une fuite du disque Redis ne révèle donc ni le message ni les données confidentielles.
Borner la mémoire du processus
La mémoire par défaut, InMemoryConversationMemory, garde chaque conversation dans un dictionnaire local au processus. Ce dictionnaire est borné à 10 000 conversations et à un jour d'inactivité. Ainsi, un processus de longue durée qui n'appelle jamais forget_thread ne garde pas toutes les valeurs qu'il a vues. Ajustez max_threads pour plafonner le nombre de conversations gardées. Au-delà, la conversation la moins récemment utilisée est évincée. Ajustez ttl pour expirer une conversation ce nombre de secondes après sa dernière écriture. La conversation expirée n'est retirée qu'au prochain accès.
[memory]
type = "in_memory"
max_threads = 1000
ttl = 3600Pour un déploiement durable ou multi-worker, utilisez plutôt un backend persistant, et oubliez une conversation avec forget_thread quand elle se termine.
Comment le stockage protège les données
Deux protections se combinent à chaque écriture. Toutes deux reposent sur un secret que le stockage ne détient jamais.
- La clé est hachée. Le hacheur dérive une empreinte du message à l'aide du pepper.
argon2(Argon2id) est lent et coûteux en mémoire. C'est le bon choix quand le pepper lui-même peut fuiter.sha256(HMAC-SHA256) est rapide et convient à un chemin d'appel très sollicité. Les deux sont déterministes, donc le même message tombe toujours sur la même clé. - La valeur est chiffrée.
aesgcm(AES-GCM) chiffre les détections avant écriture, avec un nonce neuf par message. Le déchiffrement échoue sur un texte chiffré altéré, donc une altération est détectée.
Le thread_id reste en clair, comme préfixe de clé. C'est ce qui permet d'énumérer et d'oublier toute une conversation avec forget_thread. Le modèle de menace et la comparaison des backends sont dans Sécurité.
Utiliser une base SQL à la place
Si votre stack exécute déjà PostgreSQL, type = "sqlalchemy" offre le même stockage durable et multi-worker sur n'importe quel driver SQLAlchemy async. Installez piighost[config,sqlalchemy,crypto,argon2], et pointez la config vers une variable d'environnement pour l'URL, afin que le mot de passe reste hors du fichier.
[memory]
type = "sqlalchemy"
url_env = "PIIGHOST_DATABASE_URL"
[memory.hasher]
type = "argon2"
[memory.cipher]
type = "aesgcm"export PIIGHOST_DATABASE_URL="postgresql+asyncpg://user:pass@db.internal/piighost"L'URL doit utiliser un driver async (postgresql+asyncpg://..., sqlite+aiosqlite://...). Créez la table une fois au démarrage avec await pipeline.memory.create_schema(). Le hacheur et le cipher protègent les valeurs stockées exactement comme pour Redis.
Le servir en HTTP avec piighost-api
Si plusieurs applications partagent le pipeline, ou si une application qui n'est pas écrite en Python en a besoin, servez le même fichier avec piighost-api, le serveur compagnon. Son image Docker est ghcr.io/athroniaeth/piighost-api. Un premier serveur hors Docker est construit pas à pas dans Serveur d'API.
services:
piighost-api:
image: ghcr.io/athroniaeth/piighost-api:latest
ports:
- "8000:8000"
environment:
- PIIGHOST_CONFIG=/app/pipeline.toml
- API_KEY_DEFAULT=${API_KEY_DEFAULT}
- SECRET_PEPPER=${SECRET_PEPPER}
- PIIGHOST_HASH_PEPPER=${PIIGHOST_HASH_PEPPER}
- PIIGHOST_CIPHER_KEY=${PIIGHOST_CIPHER_KEY}
- EXTRA_PACKAGES=piighost[crypto]
volumes:
- ./pipeline.toml:/app/pipeline.toml
- cache:/root/.cache
depends_on:
- redis
redis:
image: redis:7-alpine
volumes:
cache:Le pipeline.toml monté est le fichier ci-dessus, avec son url posée à redis://redis:6379/0, l'adresse du service redis. API_KEY_DEFAULT porte une clé imprimée par keyshield generate, et le serveur refuse de démarrer sans clé. L'image embarque le client Redis et le hacheur Argon2, et EXTRA_PACKAGES ajoute le cipher AES-GCM. Le volume cache garde les références du catalogue épinglées sur un commit, les poids du modèle et les paquets de EXTRA_PACKAGES d'un redémarrage de conteneur à l'autre.
L'image lit ces variables :
| Variable | Défaut | Effet |
|---|---|---|
PIIGHOST_CONFIG | /app/pipeline.toml | Le fichier de config ou la référence du catalogue à servir. L'image embarque une config par défaut, qui charge tous les groupes de regex du catalogue. Un fichier monté ou une référence du catalogue la remplace |
API_HOST | 0.0.0.0 | Hôte d'écoute |
API_PORT | 8000 | Port d'écoute |
LOG_LEVEL | info | Niveau de log |
EXTRA_PACKAGES | vide | Paquets installés avec uv pip install au démarrage du conteneur, comme piighost[gliner2] pour une configuration qui exécute GLiNER2 |
Pour servir une configuration du catalogue plutôt qu'un fichier, posez PIIGHOST_CONFIG à sa référence et ajoutez la mémoire Redis avec une variable PIIGHOST_MEMORY, comme le montre CLI du serveur. Chaque conteneur exécute un seul processus serveur, donc passez à l'échelle en ajoutant des conteneurs sur la même mémoire Redis. Chaque route, proxys compris, est listée dans Endpoints de l'API.
Voir aussi
- Référence de configuration : chaque section et chaque
typede composant, en TOML et en JSON. - Déploiement multi-instance : pourquoi la mémoire Redis partagée est requise derrière un load balancer.
- Sécurité : le modèle de menace au repos et la comparaison des backends.
- Pipeline conversationnel : l'API du pipeline de conversation que le middleware pilote.
- Stocker les conversations et protéger les traces : les règles de stockage, de
BR-STO-01àBR-STO-08, écrites pour un DPO ou un exploitant.