Construire nos applications d’agents est vraiment impressionnant, mais en tant que bons ingénieurs en IA, nous savons que chaque token exécuté coûte de l’argent. Et lorsque nous commençons à faire évoluer les agents, ce coût peut rapidement devenir ingérable.
Dans cette optique, j’ai décidé de créer cet article pour te montrer comment filtrer les messages à partir d’un réseau Perceptron, en veillant à ce que seulement ce qui compte soit traité par le modèle.
Avec un bon mécanisme de filtrage, nous pouvons:
- Réduire les coûts liés aux tokens.
- Éviter les appels inutiles au LLM.
- Améliorer les performances de votre système d’IA.
Dans ce contenu, nous allons explorer comment appliquer des filtres de messages, concrètement, en veillant à ce que seules les messages approuvés par vos critères parviennent à votre modèle, tout en préservant l’efficacité, le contrôle et l’économie.
Qu’est-ce que le réseau Perceptron (P)
Le réseau du type Perceptron est l’une des architectures les plus simples et les plus fondamentales de l’histoire des réseaux neuronaux, marquant une étape clé dans le développement de l’Intelligence Artificielle. Proposé par Frank Rosenblatt en 1957, ce réseau s’est inspiré du fonctionnement d’un neurone biologique, cherchant à simuler comment les signaux d’entrée sont traités pour générer une décision.

En sa forme la plus simple, le Perceptron peut être compris comme un classificateur linéaire, capable de séparer deux classes à partir d’une combinaison linéaire des entrées. De manière informelle, on peut même le comparer à une structure if/else, mais avec des poids ajustables appris à partir des données. Le réseau reçoit un vecteur d’entrées, multiplie chaque valeur par son poids correspondant, additionne les résultats et, ensuite, applique une fonction d’activation pour produire la sortie finale.

Malgré sa simplicité, le Perceptron est étonnamment puissant pour résoudre des problèmes linéairement séparables. Il a établi les bases conceptuelles pour des architectures plus avancées, comme les réseaux neuronaux multicouches et les algorithmes de rétropropagation. Comprendre le Perceptron est essentiel pour comprendre comment les modèles apprennent des motifs à partir des données et comment ces idées ont évolué au fil du temps.
Dans notre cas pratique, nous utiliserons une liste de mots comme vecteur d’entrée pour déterminer une condition d’exécution — c’est-à-dire décider si une action doit être réalisée ou non. Cette approche peut facilement évoluer vers un scénario automatisé à l’avenir, où les entrées seraient générées dynamiquement à partir des données envoyées à l’agent. Pour cet exemple, toutefois, nous travaillerons avec une liste statique afin de faciliter la compréhension.
Création de notre filtre avec le Perceptron (P)
Maintenant que nous avons compris les notions de base, allons créer notre filtre en utilisant le Perceptron.
La première étape consiste à importer les bibliothèques qui seront utilisées tout au long du projet. Tout le développement se fera sur Google Colab, ce qui facilite l’exécution et la reproductibilité des expériences.
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
Agora, vamos criar a lista de palavras que será utilisée comme base pour l’entraînement du modèle. Ensuite, nous allons définir l’axe y de l’entraînement, en attribuant à chaque vecteur d’entrée une étiquette indiquant si cette question peut ou non être traitée par le modèle.
Ces étiquettes seront des valeurs binaires :
- 1 → requête autorisée (le modèle peut exécuter)
- 0 → requête non autorisée
Pour cet exemple, nous ne considérerons que deux requêtes autorisées :
- « Quel est mon solde ? »
- « Quel est le montant de la facture ? »
Ces questions seront représentées sous forme de vecteurs d’entrée (x) et associées à la valeur 1 sur l’axe y, tandis que toute autre variation ou question hors de ce cadre pourra être étiquetée comme 0.
texts_train = [
"oi",
"olá",
"bom dia",
"qual meu saldo?",
"qual o valor da fatura?",
"explique backpropagation",
"compare gpt e claude",
"como implementar um perceptron",
"asdfasdf",
"ajuda",
"implemente um algoritmo de gradiente descendente",
]
Dans l’étape suivante, nous créons un objet TfidfVectorizer, chargé de convertir les textes en vecteurs numériques pouvant être utilisés par notre modèle.
lowercase=TrueConvertit tout le texte en minuscules, évitant que des mots identiques soient traités comme différents en raison des majuscules.max_features=30Limite le vocabulaire à un maximum de 30 mots les plus pertinents, réduisant la dimensionalité et facilitant l’entraînement du modèle.
Après cela, nous entraînons notre modèle :
vectorizer = TfidfVectorizer(
lowercase=True,
max_features=30
)
X = vectorizer.fit_transform(texts_train).toarray()
print("X treino:", X.shape)
À présent, l’étoile du post arrive: nous allons créer une classe qui génère notre modèle et effectue une classification binaire. Elle fonctionne en ajustant des poids (w) et un biais (b) au cours des époques de notre entraînement, en fonction de l’erreur commise à chaque prédiction.
Pendant l’entraînement, le modèle calcule une combinaison linéaire des entrées, décide de la classe à l’aide d’un seuil (0) et, si la prédiction est incorrecte, met à jour les poids et le biais proportionnellement au taux d’apprentissage. À la fin, la méthode de prédiction utilise ces paramètres appris pour classer de nouvelles données, renvoyant 0 ou 1, indiquant si l’entrée appartient ou non à la classe autorisée.
class Perceptron:
def __init__(self, lr=0.1, epochs=40):
self.lr = lr
self.epochs = epochs
def fit(self, X, y):
self.w = np.zeros(X.shape[1])
self.b = 0
for _ in range(self.epochs):
for i in range(len(X)):
z = np.dot(X[i], self.w) + self.b
y_pred = 1 if z >= 0 else 0
error = y[i] - y_pred
self.w += self.lr * error * X[i]
self.b += self.lr * error
def predict(self, X):
z = np.dot(X, self.w) + self.b
return (z >= 0).astype(int)
Neste extrait suivant, nous créons une instance du modèle Perceptron et démarrons le processus d’entraînement en utilisant les données d’entrée (X) et leurs étiquettes respectives (y).
model = Perceptron()
model.fit(X, y)
print("Poids:", model.w.shape)
Enfin, nous créerons une fonction pour déterminer s’il faut ou non appeler un LLM :
def should_call_llm(text: str) -> bool:
x = vectorizer.transform([text]).toarray()
return bool(model.predict(x)[0])
Et voici le moment tant attendu : la fonction chargée de décider si un modèle LLM doit être exécuté ou non.
tests = [
"qual meu saldo?"
]
if should_call_llm(tests[0]) == True:
print("Chamar LLM")
else:
print("Não chamar LLM")
En fonction de ce qui a été appris pendant l’entraînement, cette fonction reçoit une nouvelle question, la transforme au même format vectoriel utilisé lors de l’entraînement et utilise le Perceptron pour effectuer la classification.
Le résultat est une décision binaire (0 ou 1), indiquant si la requête est valide et peut être traitée par le LLM ou si elle doit être bloquée, agissant ainsi comme un filtre intelligent d’entrée avant l’appel au modèle de langage.
Le mieux dans tout cela, c’est qu’il comprend les variations, telles que :
- Quel est mon solde
- Quel solde
- J’aimerais savoir quel est mon solde en fait ?
Notons que, même dans un exemple aussi simple que le nôtre, le réseau s’est déjà montré capable de résoudre le problème proposé, agissant comme un filtre intelligent pour décider si un modèle doit ou non être exécuté. Ce type d’approche est extrêmement puissant dans la construction d’agents, en permettant de former un modèle léger, d’exporter son binaire et de l’exécuter dans une API dédiée, en filtrant les messages avant même qu’ils n’atteignent l’agent ou le LLM. Pour aujourd’hui, c’est tout ce que j’aimerais partager.




