Maison > Article > développement back-end > Création d'une bibliothèque de machines d'état avec l'aide d'outils d'IA
Par ennui, en attendant mes séances d'entretiens de suivi, j'ai construit une bibliothèque de machines à états, alimentée par genruler. J'en ai construit un dans le passé, pour être exact, lors de mon premier emploi après l'obtention de mon diplôme. Cette implémentation est vaguement basée sur la conception rédigée par mon superviseur à l'époque. Le projet visait également à montrer comment la règle DSL peut être utilisée.
D'après le résumé utile renvoyé par une recherche Google sur la machine à états finis (c'est moi qui souligne)
Une « machine à états finis » désigne un modèle informatique dans lequel un système ne peut être que dans un nombre limité d'états distincts à un moment donné, et les transitions entre ces états sont déclenchées par des entrées spécifiques, permettant essentiellement il traite des informations sur la base d'un ensemble de conditions définies sans possibilité d'avoir un nombre infini d'états ; « fini » fait ici référence à l'ensemble limité d'états possibles dans lesquels le système peut exister.
La bibliothèque reçoit un dictionnaire qui représente le schéma de la machine à états finis. Par exemple, nous souhaitons construire un système de suivi des commandes
Diagramme de machine à états finis généré par Graphviz
Et le schéma ressemblerait à ceci (sous forme YAML tronquée pour plus de clarté)
machine: initial_state: pending_payment states: pending_payment: name: pending payment transitions: order_authorization: name: order is authorized destination: authorized rule: (condition.equal (basic.field "is_authorized") (boolean.tautology)) authorized: name: authorized action: authorize_order transitions: order_partially_paid: name: order is partially paid destination: partially_paid rule: (boolean.tautology) order_fully_paid: name: order is fully paid destination: paid rule: (boolean.tautology) ...
Par conséquent, pour tout mettre en place, nous appelons
import genstates import yaml import order_processor with open("states.yaml") as schema: machine = genstates.Machine(yaml.safe_load(schema), order_processor)
Donc, dans cet exemple fictif, nous recevrons une charge utile chaque fois qu'il y aura un changement dans la commande. Par exemple, lorsque le vendeur accuse réception de la commande, nous obtenons
{ "is_authorized": true, ... }
On pourra alors vérifier dans la bibliothèque
state = machine.initial # assume the order is created transition = machine.get_transition(state, "order_authorization") assert transition.check_condition(payload)
Le contrôle exécute également un contrôle de validation supplémentaire s'il est défini dans le schéma. Ceci est utile si vous avez l'intention de renvoyer un message d'erreur à l'appelant.
try: assert transition.check_condition(payload) except ValidationFailedError as e: logger.exception(e)
Parfois, on sait qu’à chaque fois que la charge utile arrive, elle doit déclencher une transition, mais on ne sait pas toujours laquelle. Par conséquent, nous le transmettons simplement dans Machine.progress
try: state = machine.progress(state, payload) except ValidationFailedError as e: logger.exception(e)
Une fois que nous savons dans quel état la commande doit progresser, nous pouvons commencer à écrire du code pour travailler sur la logique
# fetch the order from database order = Order.get(id=payload["order_id"]) current_state = machine.states[order.state] # fetch next state try: new_state = machine.progress(current_state, payload) except ValidationFailedError as e: # validation failed, do something logger.exception(e) return except MissingTransitionError as e: # can't find a valid transition from given payload logger.exception(e) return except DuplicateTransitionError as e: # found more than one transition from given payload logger.exception(e) return # do processing (example) log = Log.create(order=order, **payload) log.save() order.state = new_state.key order.save()
Idéalement, je peux également extraire la logique de traitement, c'est la raison pour laquelle j'ai importé order_processor au début. Dans la définition de l'état d'autorisation, nous avons également défini une action
authorized: name: authorized action: authorize_order ...
Donc dans le module order_processor, on définit une nouvelle fonction appelée approved_order
def authorize_order(payload): # do the processing here instead pass
De telle sorte que ce qui suit est possible, où le code de gestion de l'état est séparé du reste de la logique de traitement
machine: initial_state: pending_payment states: pending_payment: name: pending payment transitions: order_authorization: name: order is authorized destination: authorized rule: (condition.equal (basic.field "is_authorized") (boolean.tautology)) authorized: name: authorized action: authorize_order transitions: order_partially_paid: name: order is partially paid destination: partially_paid rule: (boolean.tautology) order_fully_paid: name: order is fully paid destination: paid rule: (boolean.tautology) ...
Cependant, je travaille toujours dessus et je devrais le faire dans la prochaine version. Parallèlement, il est également capable de faire quelque chose de similaire, comme cartographier et réduire si chaque État a défini une action. N'hésitez pas à vérifier le projet pour connaître l'avancement du développement. Et Genruler et Genstates sont désormais disponibles sur PyPI, ouais !
J'ai téléchargé Codeium Windsurf après que la bibliothèque soit quelque peu utilisable. Je l'ai finalement utilisé pour supprimer ma dépendance de Genruler et j'ai ajouté de la documentation et un fichier README au projet. Pour les états générateurs, j'ai utilisé cascade pour générer de la documentation, du README, ainsi que des tests. Dans l'ensemble, j'ai l'impression d'avoir un programmeur intermédiaire à senior pour m'aider dans les tâches que j'attribuerais à mes stagiaires ou même à mes juniors.
La majeure partie de la logique de base vient toujours de mon côté, aussi intelligent que soit le modèle de langage pour le moment, ils font toujours des erreurs ici et là et nécessitent donc une supervision. J'ai également expérimenté le modèle qwen2.5-coder:7b, et cela fonctionne plutôt bien, bien qu'assez lent à cause de mon poste de travail de mauvaise qualité. Je trouve que le prix demandé par Codeium est juste, si je veux créer mon propre produit et que je parviens à en tirer profit.
Bien que les parties de génération fonctionnent bien, l'écriture du code réel n'est pas aussi géniale. Je ne sais pas si Pylance fonctionne correctement là-bas, considéré comme propriétaire, ou si cela est dû à l'achèvement de Magic Windsurf, mon éditeur n'est plus en mesure d'importer automatiquement les bibliothèques lorsque j'écris du code. Par exemple, lorsque je complète automatiquement la fonction réduire() dans mon code, dans vscode, elle s'insérerait automatiquement depuis functools import réduire dans mon code. Cependant, ce n’est pas le cas en planche à voile, ce qui la rend un peu irritante. Cependant, étant donné qu'il s'agit d'une nouveauté, l'expérience de codage devrait être corrigée au fil du temps.
Par contre, je suis toujours à la recherche d'un éditeur plus léger, et zed attire mon attention. Cependant, depuis que mon Surface Book 2 est mort récemment, il ne me reste qu'un Samsung Galaxy Tab S7FE lorsque je suis loin de mon bureau à domicile. Par conséquent, vscode avec une interface Web (et il est étonnamment utilisable) connecté à mon poste de travail est toujours mon éditeur principal (il fonctionne même avec l'extension neovim).
L’IA générative propulsée par LLM change rapidement nos vies, il ne sert à rien d’y résister. Cependant, à mon humble avis, nous devrions également faire preuve d’une certaine retenue pour ne pas l’utiliser pour tout. Il devrait vraiment être utilisé comme complément au travail innovant ou créatif, et non comme substitut à l’innovation et à la créativité.
Nous devrions également savoir ce qu'il produit, au lieu d'accepter aveuglément ce qu'il fait. Par exemple, dans Genruler, je l'ai fait améliorer mon README original avec des exemples plus complets. Au lieu de l'accepter tel quel, je l'ai fait générer des tests pour tous les exemples qu'il génère dans le README, afin que l'exemple de code passe et fonctionne comme je le souhaitais.
Dans l'ensemble, oui, je pense que ces éditeurs améliorés par l'IA générative valent l'argent qu'ils demandent. En fin de compte, ce sont des outils, ils sont destinés à offrir une aide au travail, et non à remplacer la personne qui frappe le clavier.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!