Création rapide d'applications IA d'entreprise avec la plateforme low-code Dify

Présentation de Dify

Dify est une plateforme open-source pour le développement d'applications LLM, intégrant les paradigmes Backend as a Service et LLMOps. Elle permet de construire des solutions IA de niveau professionnel sans se concentrer sur les détails techniques des modèles.

  • Conception visuelle : interface glisser-déposer pour l'orchestration des workflows, évitant le code manuel
  • Modèles variés : prise en charge intégrée d'OpenAI, Claude, Qwen et DeepSeek avec basculement instantané
  • Architecture RAG : moteur intégré pour l'analyse de documents, la recherche vectorielle et le réordonnancement sémantique
  • Fonctionnalités corporatives : support multi-locataires, contrôle d'accès basé sur les rôles et traçabilité complète
  • Conception API-first : chaque capacité accessible via des points de terminaison RESTful pour une intégration flexible

Déploiement via Docker


# Récupérer le code source
git clone https://github.com/langgenius/dify.git

# Accéder au dossier de configuration Docker
cd dify/docker

# Préparer le fichier d'environnement
cp .env.example .env

# Lancer l'ensemble des conteneurs
docker compose up -d

# Vérifier le statut des services actifs
docker compose ps

# Finaliser l'installation via http://localhost/install

Construction d'un assistant virtuel client en 10 minutes

Initialisation de l'application

Dans l'interface d'administration, sélectionnez « Nouvelle application » → choisissez le modèle « Chatbot » → indiquez un nom tel que « Support client automatisé ».

Définition du système de prompts


## Persona
Vous êtes un spécialiste du service client, expert pour répondre aux interrogations sur les caractéristiques des produits, leur utilisation et la résolution des problèmes.

## Directives
1. Fournir des réponses concises, précises et courtoises
2. Orienter vers un agent humain en cas d'incertitude
3. Ne jamais inventer de fonctionnalités non documentées
4. S'appuyer en priorité sur les informations de la base de connaissances

## Séquence d'interaction
1. Accueillir l'utilisateur et clarifier sa demande
2. Générer une réponse basée sur les données disponibles
3. Vérifier si d'autres questions subsistent
4. Assurer un transfert vers un opérateur si requis

Alimentation de la base de connaissances

Naviguez vers « Base de connaissances » → créez un nouvel ensemble nommé « Documentation produit » → importez des fichiers PDF, Word ou TXT → configurez le traitement :


Mode de segmentation : automatique
Taille maximale des segments : 500 tokens
Chevauchement entre segments : 50 tokens
Méthode d'indexation : qualité élevée (utilisation d'un modèle d'embedding)
Stratégie de recherche : combinée (mots-clés et sémantique)
Réordonnancement : activé (optimisation de la pertinence)

Liaison avec l'application

Retournez à l'éditeur de l'application → dans la section « Contexte », intégrez la base de connaissances → activez l'option « Source des citations » → publiez l'application.

Automatisation par workflows

Pour des procesuss complexes, le mode Workflow de Dify offre des fonctionnalités avancées comme les branchements conditionnels, l'exécution parallèle et les boucles itératives.

Exemple : tri automatique des courriels


Architecture du workflow :

[Entrée] -> [LLM : Analyse d'intention] -> [Décision]
                              |--- Demande d'information -> [LLM : Réponse générée]
                              |--- Réclamation -> [API HTTP : Création de ticket]
                              +--- Autre cas   -> [API HTTP : Escalade humaine]

Paramètres de chaque étape :
- Correspondance des variables d'entrée
- Structure du prompt
- Récupération des variables de sortie

Invocation du workflow via API


curl -X POST http://localhost/v1/workflows/run 
  -H "Authorization: Bearer {clé_api}" 
  -H "Content-Type: application/json" 
  -d '{"inputs":{"texte_email":"Bonjour, mon produit ne démarre pas et je souhaite un remboursement","identifiant_client":"CLI-789"},"response_mode":"blocking","user":"systeme-automatise"}'

Intégration avec Spring Boot

Ajout des bibliothèques nécessaires


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Configuration du client Dify


@Configuration
public class ConfigDify {
    
    @Value("${dify.endpoint}")
    private String endpointDify;
    
    @Value("${dify.token}")
    private String tokenDify;
    
    @Bean
    public WebClient clientWeb() {
        return WebClient.builder()
            .baseUrl(endpointDify)
            .defaultHeader("Authorization", "Bearer " + tokenDify)
            .defaultHeader("Content-Type", "application/json")
            .build();
    }
}

Service de messagerie conversationnelle


@Service
@RequiredArgsConstructor
public class ServiceConversation {
    
    private final WebClient clientWeb;
    
    public ResultatChat envoyerMessage(String identifiantUtilisateur, String contenu) {
        Map<String, Object> parametres = Map.of(
            "inputs", Map.of(),
            "query", contenu,
            "response_mode", "blocking",
            "conversation_id", "",
            "user", identifiantUtilisateur
        );
        
        return clientWeb.post()
            .uri("/v1/chat-messages")
            .bodyValue(parametres)
            .retrieve()
            .bodyToMono(ResultatChat.class)
            .block();
    }
    
    public Flux<String> envoyerMessageStream(String identifiantUtilisateur, String contenu, String idSession) {
        Map<String, Object> parametres = Map.of(
            "inputs", Map.of(),
            "query", contenu,
            "response_mode", "streaming",
            "conversation_id", idSession,
            "user", identifiantUtilisateur
        );
        
        return clientWeb.post()
            .uri("/v1/chat-messages")
            .bodyValue(parametres)
            .retrieve()
            .bodyToFlux(String.class)
            .filter(segment -> segment.startsWith("data:"))
            .map(segment -> segment.substring(5))
            .filter(texte -> !texte.equals("[DONE]"));
    }
}

Point d'accès REST


@RestController
@RequestMapping("/api/chat")
@RequiredArgsConstructor
public class ControleurMessage {
    
    private final ServiceConversation serviceChat;
    
    @PostMapping
    public ResponseEntity<Map<String, Object>> traiterMessage(
            @RequestParam String utilisateur,
            @RequestBody Map<String, String> corps) {
        ResultatChat resultat = serviceChat.envoyerMessage(utilisateur, corps.get("texte"));
        return ResponseEntity.ok(Map.of(
            "statut", 200,
            "contenu", resultat.getAnswer(),
            "session", resultat.getConversationId()
        ));
    }
    
    @GetMapping(value = "/flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> traiterMessageFlux(
            @RequestParam String utilisateur,
            @RequestParam String texte,
            @RequestParam(required = false) String session) {
        return serviceChat.envoyerMessageStream(utilisateur, texte, 
            session != null ? session : "");
    }
}

Gestion des bases de connaissances via API


@Service
@RequiredArgsConstructor
public class ServiceBaseConnaissances {
    
    private final WebClient clientWeb;
    
    public String creerCollection(String titre, String description) {
        Map<String, Object> parametres = Map.of(
            "name", titre,
            "description", description,
            "permission", "only_me"
        );
        
        Map reponse = clientWeb.post()
            .uri("/v1/datasets")
            .bodyValue(parametres)
            .retrieve()
            .bodyToMono(Map.class)
            .block();
        
        return (String) reponse.get("id");
    }
    
    public String ajouterDocument(String collectionId, String chemin) {
        MultipartBodyBuilder constructeur = new MultipartBodyBuilder();
        constructeur.part("data", Map.of(
            "indexing_technique", "high_quality",
            "process_rule", Map.of(
                "mode", "automatic",
                "rules", Map.of(
                    "segmentation", Map.of(
                        "separator", "\n",
                        "max_tokens", 500
                    )
                )
            )
        ));
        constructeur.part("file", new FileSystemResource(chemin));
        
        Map reponse = clientWeb.post()
            .uri("/v1/datasets/" + collectionId + "/document/create_by_file")
            .body(BodyInserters.fromMultipartData(constructeur.build()))
            .retrieve()
            .bodyToMono(Map.class)
            .block();
        
        return "Document ajouté avec succès";
    }
}

Commutation entre modèles d'IA

La plateforme permet de modifier dynamiquement le modèle sous-jacent utilisé par une application, sans changement de code :


# Interface d'administration -> Paramètres -> Fournisseurs de modèles

# Configuration OpenAI
clé_api: sk-xxx
nom_du_modele: gpt-4o

# Configuration pour Qwen
clé_api: sk-xxx
nom_du_modele: qwen-max

# Configuration DeepSeek
clé_api: sk-xxx
nom_du_modele: deepseek-chat

# Dans l'éditeur d'application, sélection directe du modèle
# Utilisation de différents modèles selon les étapes
# Exemple : modèle léger pour l'analyse d'intention, modèle avancé pour la génération

Recommandations pour la mise en production

  • Résilience : déployer au minimum deux instances des services criitques, avec réplication de la base de données
  • Passerelle de modèles : utiliser Nginx comme proxy inverse pour centraliser les appels aux API d'IA, facilitant la mise en cache et le monitoring
  • Séparation des données : isoler les bases de connaissances par client dans les architectures multi-locataires
  • Observabilité : intégrer des outils comme Prometheus et Grafana pour surveiller la consommation de tokens et les performances
  • Cache intelligent : implémenter un cache sémantique pour les requêtes répétitives, réduisant les coûts d'inférence
  • Sécurité renforcée : rotation périodique des clés API, chiffrement obligatoire des communications, validation des entrées utilisateur

Étiquettes: Dify Docker Spring Boot rag LLM

Publié le 22 juin à 02h13