Guide pour intégrer ChatGPT dans une application Flutter


Avatar de Pierre Courtois

Vous souhaitez ajouter chatgpt à votre application Flutter pour la rendre plus vivante ? Dans ce guide, je vous explique comment très rapidement le mettre en place.


Intégrer ChatGPT dans une application Flutter

Voici les étapes à suivre pour intégrer ChatGPT à l’une de vos applications Flutter.

Créer une clé API

La première étape consiste à accéder à l’API de ChatGPT via la plateforme OpenAI pour créer une clé API qui permettra d’effectuer des requêtes. Pour cela :

  1. Rendez-vous sur le site officiel d’OpenAI et inscrivez-vous si vous n’avez pas déjà un compte.
  2. Une fois connecté, rendez-vous dans la section « API keys » et créez une nouvelle clé. Vous pouvez modifier ses droits selon vos besoins, mais le plus simple pour faire des tests est de lui donner toutes les permissions dans un premier temps.
  3. Enfin, pensez à ajoutant une méthode de paiement valide à votre compte, sans quoi l’API ne pourra pas fonctionner.
    • Pour cela, rendez-vous sur « Your Profile » en haut à droite, puis sur Billing dans le menu à gauche.
    • Ajoutez une méthode de paiement et un peu de crédit pour faire fonctionner l’API.
    • Pensez également à fixer des limites d’usage dans « Limits » pour éviter les mauvaises surprises.

Ne partagez jamais votre clé API publiquement, car elle donne accès à votre compte OpenAI. Dans un autre article, je vous explique comment protéger vos clés d’API en les stockant dans le backend Firebase.

Tarifs de ChatGPT

OpenAI propose une gamme de modèles et de fonctionnalités, chacun avec des capacités spécifiques et des tarifs basés sur le nombre de tokens (environ 750 mots pour 1 000 tokens) ou sur des unités spécifiques (images, minutes, etc.). Voici les prix actuels pour les modèles et outils les plus utilisés dans les applications Flutter, qui sont la plupart du temps indiqués en million de tokens.

Modèle/FonctionnalitéContexteEntrée TexteSortie TexteBatch API (Réduction 50%)
gpt-4o (2024-08-06)128 0002,50 $10,00 $1,25 $ (entrée), 5,00 $ (sortie)
gpt-4o-mini (2024-07-18)128 0000,15 $0,60 $0,075 $ (entrée), 0,30 $ (sortie)
gpt-3.5-turbo (0125)16 3840,50 $1,50 $0,25 $ (entrée), 0,75 $ (sortie)
Whisper (Transcription)0,006 $ par minute
DALL·E 3 (Génération d’images)0,04 $ par image (1024×1024, standard)

Explication des modèles et de leurs usages :

gpt-4o : Modèle le plus connu d’OpenAI, capable de traiter du texte et des images en entrée, avec une sortie textuelle. Vous pouvez l’utiliser pour des tâches complexes comme l’analyse de documents ou la génération de contenu détaillé. Par exemple : « Résume un rapport de 10 000 mots » ou « Décris cette image ».

gpt-4o-mini : Version économique de gpt-4o, qui offre des performances assez similaires, mais pour un coût bien inférieur. Il va être plus adapté pour des applications Flutter qui nécessitent des réponses courtes, comme « Quelle est la capitale de la France » ou « Génère un court paragraphe sur ce sujet ».

gpt-3.5-turbo : Modèle encore plus rapide et abordable que gpt-4o-mini, il est optimisé pour les dialogues et les tâches textuelles très simples. La fenêtre de contexte est limitée à 16 384 tokens, donc il convient mieux aux applications de chat ou aux réponses courtes. Exemple : « Explique un concept en 100 mots ».

Whisper : Outil de transcription audio-texte, qui permet de convertir des enregistrements vocaux en texte. Vous pouvez par exemple l’utiliser pour retranscrire une interview.

DALL·E 3 : Générateur d’images à partir de descriptions textuelles, parfait pour les applications nécessitant du contenu visuel (marketing, design). Exemple : « Crée une image d’un paysage de campagne ».

Donner les permissions dans Android et iOS

Pour que votre application Flutter puisse communiquer avec l’API de ChatGPT, vous devez configurer les permissions réseau sur Android et iOS :

Pour Android

Modifiez le fichier AndroidManifest.xml situé dans android/app/src/main/ pour y inclure la permission suivante :

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
  <uses-permission android:name="android.permission.INTERNET" /> <!-- Ajouter cette ligne -->
</manifest>

Cette ligne permet à votre application Android d’effectuer des requêtes HTTP vers l’API.

Pour iOS

Ouvrez le fichier Info.plist dans ios/Runner/ et ajoutez cette clé pour autoriser les connexions réseau :

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

ChatGPT devrait maintenant être accessible pour votre application Flutter, sur IOS et Android.

Implémenter ChatGPT dans une application

Voici comment intégrer ChatGPT dans une application Flutter avec un exemple de code fonctionnel. Nous utiliserons le package http pour effectuer des requêtes API et dart:convert pour traiter les réponses de ChatGPT.

Ici, j’utilise flutter_riverpod pour gérer l’état de l’application, mais vous pouvez utiliser setState ou un autre gestionnaire d’état comme Provider.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ChatGPTScreen(),
    );
  }
}

final _controller = StateProvider<TextEditingController>((ref) => TextEditingController());
final _isLoading = StateProvider<bool>((ref) => false);
final _response = StateProvider<String>((ref) => '');

class ChatGPTScreen extends ConsumerWidget {
  final ChatGPTService _chatGPTService = ChatGPTService();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _currentController = ref.watch(_controller);
    final _currentIsLoading = ref.watch(_isLoading);
    final _currentResponse = ref.watch(_response);

    void _sendRequest() async {
      ref.read(_isLoading.notifier).state = true;

      try {
        final response = await _chatGPTService.sendPrompt(_currentController.text);
        ref.read(_response.notifier).state = response;
        ref.read(_isLoading.notifier).state = false;
      } catch (e) {
        ref.read(_isLoading.notifier).state = false;
        ref.read(_response.notifier).state = 'Erreur : $e';
        ref.read(_controller.notifier).state.clear();
      }
    }

    return Scaffold(
      appBar: AppBar(title: Text('ChatGPT Chat')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _currentController,
              decoration: InputDecoration(labelText: 'Entrez votre message'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _sendRequest,
              child: Text('Envoyer'),
            ),
            SizedBox(height: 20),
            _currentIsLoading
                ? CircularProgressIndicator()
                : Text(
                    _currentResponse.isEmpty
                        ? 'Aucune réponse'
                        : _currentResponse,
                    style: TextStyle(fontSize: 16),
                  ),
          ],
        ),
      ),
    );
  }
}

class ChatGPTService {
  static const String _baseUrl = 'https://api.openai.com/v1';
  static const String _apiKey = 'VOTRE_CLÉ_API'; // Remplacez par votre clé API

  Future<String> sendPrompt(String userPrompt) async {
    final response = await http.post(
      Uri.parse('$_baseUrl/chat/completions'),
      headers: {
        'Authorization': 'Bearer $_apiKey',
        'Content-Type': 'application/json',
      },
      body: jsonEncode({
        'messages': [
          {
            'role': 'system',
            'content': 'You are a helpful assistant.',
          },
          {
            'role': 'user',
            'content': userPrompt,
          },
        ],
        'model': 'gpt-3.5-turbo',
        'stream': false,
        'temperature': 0.7,
      }),
    );

    if (response.statusCode == 200) {
      final String responseBody = utf8.decode(response.bodyBytes);
      final data = jsonDecode(responseBody);
      final promptTokens = data['usage']['prompt_tokens'];
      final completionTokens = data['usage']['completion_tokens'];
      final totalTokens = data['usage']['total_tokens'];
      print(
          'Tokens utilisés : Entrée = $promptTokens, Sortie = $completionTokens, Total = $totalTokens');
      return data['choices'][0]['message']['content'];
    } else {
      throw Exception('Erreur API : ${response.statusCode} - ${response.body}');
    }
  }
}

Voici quelques explications de comment tout cela fonctionne :

Envoyer une demande à ChatGPT

La classe ChatGPTService envoie une requête POST à l’API de ChatGPT (https://api.openai.com/v1/chat/completions) avec les en-têtes nécessaires (clé API et type de contenu) et un corps JSON contenant le message de l’utilisateur.

Future<String> sendPrompt(String userPrompt) async {
  final response = await http.post(
    Uri.parse('$_baseUrl/chat/completions'),
    headers: {
      'Authorization': 'Bearer $_apiKey',
      'Content-Type': 'application/json',
    },
    body: jsonEncode({
      'messages': [
        {
          'role': 'system',
          'content': 'You are a helpful assistant.',
        },
        {
          'role': 'user',
          'content': userPrompt,
        },
      ],
      'model': 'gpt-3.5-turbo',
      'stream': false,
      'temperature': 0.7,
    }),
  );

Dans la méthode _sendRequest(), l’utilisateur entre un message dans le TextField. Lorsqu’il clique sur « Envoyer », la fonction appelle ChatGPTService.sendPrompt() avec le texte saisi.

Récupérer et afficher la réponse

Si la requête réussit (code 200), la réponse de l’API est décodée et extraite depuis le champ choices[0].message.content. Cette réponse est ensuite stockée dans la variable _response et affichée dans un widget Text.

En cas d’erreur, un message d’erreur est affiché, et le champ de texte est vidé.

if (response.statusCode == 200) {
  final String responseBody = utf8.decode(response.bodyBytes);
  final data = jsonDecode(responseBody);
  final promptTokens = data['usage']['prompt_tokens'];
  final completionTokens = data['usage']['completion_tokens'];
  final totalTokens = data['usage']['total_tokens'];
  print(
      'Tokens utilisés : Entrée = $promptTokens, Sortie = $completionTokens, Total = $totalTokens');
  return data['choices'][0]['message']['content'];
} else {
  throw Exception('Erreur API : ${response.statusCode} - ${response.body}');
}

Récupérer le nombre de tokens consommés

Pour suivre la consommation de tokens lors de chaque appel à l’API, vous pouvez récupérer les valeurs suivantes :

  • data[‘usage’][‘prompt_tokens’] : Le nombre de tokens utilisés pour le message envoyé (entrée).
  • data[‘usage’][‘completion_tokens’] : Le nombre de tokens générés dans la réponse de ChatGPT (sortie).
  • data[‘usage’][‘total_tokens’] : La somme des deux, représentant la consommation totale.

Convertir le message renvoyé par ChatGPT

Quand l’API de ChatGPT répond, elle envoie des données sous forme de bytes. La ligne final String responseBody = utf8.decode(response.bodyBytes); transforme ces bytes en texte lisible. Ensuite, jsonDecode() extrait les informations utiles, comme la réponse de ChatGPT ou le nombre de tokens utilisés.

Avatar de Pierre Courtois