Complétion automatique d'un champ texte avec un corpus

Cas d'usage

Dans cet article nous verrons comment mettre en place un système de complétion automatique d'un champ texte d'une page web. Le système que nous développerons fonctionnera comme suit. L'utilisateur de notre application web (écrite en golang) accédera à une page web puis commencera à saisir du texte dans un champ (INPUT). À partir du quatrième caractère, le système complétera sa saisie en lui suggérant des possibilités sur la suite du mot qu'il est en train de taper.

  • Exemple de champ texte à complétion automatique

Mise en œuvre

Les mots possibles seront issus d'un corpus contenant presque exhaustivement tous les mots de la langue française. Dès la 4ème lettre entrée dans le champ, un script en JavaScript et jQuery interrogera en AJAX une application écrite en go avec les caractères déjà saisis. Cette application côté serveur interrogera un index avec la chaîne de caractères reçue et évaluera quel pourrait être le mot complet (celui que l'utilisateur a l'intention de saisir). En retour, ce code serveur enverra une liste de mots possibles et, pour chaque mot, un score de similitude entre ce qui a déjà été saisi et le mot proposé (la liste des mots sera classée en fonction de ce score de probabilité).

Solution technique

Corpus de mots

La liste des mots de la langue française est issue d'un travail universitaire : elle a été générée à partir du dictionnaire Francais-Gutenberg de Christophe Pythoud. Ce fichier est disponible ici et il contient 336531 entrées.

Il est préférable de convertir ce fichier de l'ANSI à l'UTF-8 sans BOM avant de commencer à l'utiliser.

Gestion de l'index et système de suggestion

Notre application go utilisera la bibliothèque gocleo. Il s'agit du portage en golang de la bibliothèque JAVA utilisée par LinkedIn dans son système de suggestion (lien vers le projet cleo).

Cette bibliothèque n'est pas encore complète, mais c'est une bonne base de code qui fonctionne et que vous pourrez facilement intégrer à vos projets en la modifiant. Par exemple, elle utilise un fichier texte pour construire l'index des mots à suggérer. Vous pourriez la modifier afin qu'elle tire le corpus d'une base de données.

Affichage du champ texte et des suggestions

Dans mon exemple, j'utilise Boostrap 2.3.1 ainsi le plug-in typeahead (voir le code source côté client). Le plug-in typeahead permet de créer une boîte de texte à complétion automatique. Le principe étant que l'utilisateur commence à saisir un texte et une liste de suggestion apparaît sous le champ.

Le code côté serveur

On peut faire plus minimal ou utiliser la bibliothèque Gorilla, voire un framework MVC. Il ne s'agit que d'un exemple. Le principe est d'importer la bibliothèque gocleo. Cette dernière contient une fonction init qui ajoutera un contrôleur cleo à votre application web. Il est de votre responsabilité de démarrer le serveur web. Le code ci-après répond à ces deux adresses :

  • http://localhost:9999/home pour servir la page d'exemple avec le champ de texte à complétion automatique.
  • http://localhost:9999/cleo pour répondre aux requêtes AJAX de demandes de suggestions de mots.
package main

import (
	"net/http"
	"html/template"
	"github.com/jamra/gocleo"
)
 
var templates = template.Must(template.ParseFiles("cleo.html"))
 
type Page struct {
	Title string
}
 
func main() {
	cleo.BuildIndexes("liste.txt", nil)
	http.HandleFunc("/home", homeHandler)
	err := http.ListenAndServe(":9999", nil)
	if err != nil {
        panic(err)
    }
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	p := Page{Title: "Test de Cleo"}
	err := templates.ExecuteTemplate(w, "cleo.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

Sous Windows, l'exécutable pèse environ 8 Mo et occupe 49Mo de RAM une fois le corpus chargé. Ce qui reste raisonnable pour une application web complète.

Le code côté client

Le code est assez simple : il scrute toute modification du champ texte et si le champ contient plus de quatre caractères, il interroge le serveur afin d'obtenir une liste de suggestions. Étant donné que le plug-in typeahead s'attend à avoir une liste de chaînes de caractères et que gocleo retourne un tableau listant les mots possibles et le score associé, on contruit une liste de chaînes de caractères en extrayant ce qui nous interrésse dans la réponse à notre requête AJAX.

J'utilise des CDN pour ne pas avoir à servir de ressources statiques.

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
	<title>{{ .Title }}</title>
	<link type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"/>
	<link type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet"/>
	<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js">
	<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
	<script type="text/javascript" src="http://cdn.jsdelivr.net/bootstrap/2.3.2/js/bootstrap-typeahead.js"></script>
  </head>
  <body>

  <div class="container-fluid">
    <div class="row-fluid">
      <div class="span12">      

        <label for="txtWord">Essayez-moi</label>
        <input id="txtWord" name="txtWord" type="text" class="typeahead" autocomplete="off" placeholder="commencez à saisir" />
      
        <script type="text/javascript">
          $(document).ready(function() {
            $('#txtWord').typeahead({
              source: function (query, process) {
                if ($("#txtWord").val().length >= 4) {
                  return $.ajax({
                    url: '/cleo',
                    type: 'get',
					data: { query: query },
                    dataType: 'json',
                    success: function (result) {
                      var index;
                      var resultList = [];
                      for (index = 0; index < result.length; index++) {
                        resultList.push(result[index].Word);
                      }
                      return process(resultList);
                    }
                  });
                }
              }  
            });
          });
        </script>
  
      </div>
    </div>
  </div>
    
  </body>
</html>

Étiquettes :   webapp   thirdparty   gocleo   texte 
Portrait de Benjamin BALET
Benjamin BALET
Consultant APM

Retrouvez mes cooordonées

Benjamin BALET sur viadeo






Vous aimerez aussi

Les lois de la réflexion

Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go.   Lire »

Gobs le format natif d'échange de données en Go

Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif   Lire »

Gérer les informations de session avec Gorilla

La bibliothèque standard de go ne gère pas les variables de session d'une application. Il existe une solution avec le toolkit Gorilla   Lire »

Canaux et go routines avec ou sans état

Exemples d'utilisation du type chan et des go routines stateful et stateless   Lire »

Comment gérer efficacement les erreurs en golang ?

Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover   Lire »

Commentaires

Soyez le premier à commenter cet article

Publier un commentaires

Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.

(requis)
(requis)
(requis, mais non publié)
(recommandé si vous souhaitez être publié)