Comment intégrer Grok dans une application Flutter


Avatar de Pierre Courtois

Dans ce guide, découvrez comment rendre votre application Flutter encore plus puissante en y ajoutant le modèle IA de Grok. Je vais vous montrer comment faire une requête, récupérer la réponse de Grok et connaître le nombre de tokens que vous avez utilisés.


Intégrer Grok dans une application Flutter

Intégrer Grok dans une application Flutter

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

Créer une clé API

La première étape est d’accéder à l’API de Grok via la plateforme xAI, afin de créer une clé API qui vous permettra d’effectuer des requêtes. Pour cela :

  1. Rendez-vous sur le site officiel de xAI et inscrivez-vous pour obtenir un compte développeur. Une fois votre compté créé, rendez-vous dans la console.
  2. Si ce n’est pas déjà fait, ajoutez votre adresse de facturation (Pas besoin d’être une entreprise) et une carte de paiement valide.
  3. Achetez du crédit pour pouvoir effectuer des appels avec l’API Grok (Vous pouvez commencer avec 10 dollars, pour faire des tests).
  4. Enfin, générez une clé API et copier-la pour plus tard

Tarifs de Grok

Grok propose plusieurs modèles avec des capacités et des tarifs spécifiques. Voici les prix pratiqués actuellement :

ModèleContexteEntrée TexteEntrée ImageSortie TexteImage Générée
grok-2-vision-121232 7682,00 $2,00 $10,00 $
grok-2-image-1212131 0720,07 $ (par image)
grok-2-1212131 0722,00 $10,00 $
grok-vision-beta8 1925,00 $5,00 $15,00 $
grok-beta131 0725,00 $15,00 $

Les modèles beta étant obsolètes et plus chers, je vous conseille plutôt d’utiliser les trois autres qui sont disponibles :

Explication des modèles et de leurs usages :

  • grok-2-vision-1212 : Ce modèle est conçu pour traiter à la fois du texte et des images en entrée. Il peut analyser une question textuelle ou interpréter une image (par exemple, décrire son contenu) et générer une réponse textuelle. Avec une fenêtre de contexte de 32 768 tokens, il est adapté aux tâches nécessitant une compréhension multimodale (texte + vision). Exemple : « Que voit-on sur cette photo ? ».
  • grok-2-image-1212 : Qui est spécialisé dans la génération d’images à partir de descriptions textuelles (facturées à 0,07 $ par image générée). Sa grande fenêtre de contexte (131 072 tokens) permet de gérer des prompts complexes pour obtenir un rendu détaillés Exemple : « Génère une image d’un coucher de soleil sur une plage ».
  • grok-2-1212 : Le modèle texte phare de Grok, idéal pour des conversations ou des tâches textuelles uniquement. Il prend du texte en entrée et génère du texte en sortie, avec une fenêtre de contexte de 131 072 tokens pour des échanges longs ou des analyses approfondies. C’est le modèle qui est le plus souvent utilisé. Par exemple : « Donne moi la date de découverte de l’Amérique ».

Donner les permissions dans Android et iOS

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

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

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

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

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>

Implémenter Grok dans une application

Voici comment intégrer Grok dans une application Flutter avec un exemple de code fonctionnel. Nous allons utiliser le package http pour effectuer des requêtes API et convert pour afficher correctement le message renvoyé par Grok.

J’utilise flutter_riverpod pour gérer l’état de l’application, mais vous pouvez tout aussi bien utiliser setState ou 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: GrokChatScreen(),
    );
  }
}

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

class GrokChatScreen extends ConsumerWidget {
  final GrokService _grokService = GrokService();

  @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 _grokService.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('Grok 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 GrokService {
  static const String _baseUrl = 'https://api.x.ai/v1';
  static const String _apiKey =
      'MA_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 test assistant.',
          },
          {
            'role': 'user',
            'content': userPrompt,
          },
        ],
        'model': 'grok-2-latest',
        'stream': false,
        'temperature': 0,
      }),
    );

    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']; // Structure typique des API de chat
    } else {
      throw Exception('Erreur API : ${response.statusCode} - ${response.body}');
    }
  }
}

Voici quelques explications de comment tout cela fonctionne :

Envoyer une demande à Grok :

La classe GrokService envoie une requête POST à l’API de Grok (https://api.x.ai/v1/chat/completions) avec les en-têtes nécessaires (clé API et type de contenu) et un corps JSON contenant le message que vous souhaitez envoyer.

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 test assistant.',
          },
          {
            'role': 'user',
            'content': userPrompt,
          },
        ],
        'model': 'grok-2-latest',
        'stream': false,
        'temperature': 0,
      }),
    );

Dans la méthode _sendRequest(), l’utilisateur entre un message dans le TextField. Lorsqu’il clique sur « Envoyer », la fonction appelle GrokService.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 de type String _response et affichée dans un widget Text.

En revanche 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']; // Structure typique des API de chat
    } else {
      throw Exception('Erreur API : ${response.statusCode} - ${response.body}');
    }

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

Afin de savoir combien de tokens sont consommés à chaque appel que vous faites appel à Grok, vous pouvez également récupérer les trois 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 Grok (sortie).
  • data[‘usage’][‘total_tokens’] : La somme des deux, représentant la consommation totale.

Convertir le message renvoyé par Grok

Quand l’API de Grok répond, elle envoie des données sous forme de « bytes » (comme une suite de chiffres bruts que l’ordinateur comprend). La ligne final String responseBody = utf8.decode(response.bodyBytes); transforme ces bytes en texte normal qu’on peut lire. Ensuite, grâce à jsonDecode(), on peut extraire les informations utiles, comme la réponse de Grok ou le nombre de tokens utilisés.

Avatar de Pierre Courtois