FlutterでDALL·E 3をAPI経由で使用してみた
こんにちは、ゲームソリューション部のsoraです。
今回は、FlutterでDALL·E 3をAPI経由で使用してみたことについて書いていきます。
実装した画面
生成したい画像の指示を入力して、DALL·E 3のAPIを実行して画像を生成するシンプルなアプリです。
前提
OpenAIにてAPIキーを作成して、利用可能なクレジットを準備しておいてください。
クレジットを準備しなくてもAPIキーは作成できますが、クレジットが0の状態で使用してもエラーになります。
状態管理には、Riverpod(flutter_riverpod)を使用しています。
flutter_riverpod | Flutter package
コードの解説
コードは以下です。
今回はテストのため、ファイル分けせずに全てmain.dart
に書いています。
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart' as http; class Response extends Notifier<String> { @override String build(){ return ''; } void clear() { state = ''; } void modify(String url) { state = url; } } final responseProvider = NotifierProvider<Response, String>(() { return Response(); }); // DALL·E 3 API実行 Future<void> apiRequest(String message, WidgetRef ref) async { String responseUrl; final providerNotifier = ref.watch(responseProvider.notifier); // 取得したAPIキーを入れる const apiKey = '{OpenAIのAPIキー}'; const domain = 'api.openai.com'; const path = 'v1/images/generations'; // モデルの指定 const model = 'dall-e-3'; // APIリクエスト http.Response response = await http.post( Uri.https(domain, path), headers: <String, String>{ 'Content-Type': 'application/json', 'Authorization': 'Bearer $apiKey', }, body: jsonEncode(<String, dynamic>{ // モデル "model": model, // 指示メッセージ "prompt": message, // 生成枚数 "n" : 1, // 画像サイズ "size": "1024x1024", // クオリティ "quality": "standard" }), ); if (response.statusCode == 200) { String responseData = utf8.decode(response.bodyBytes).toString(); final responseJsonData = jsonDecode(responseData); responseUrl = responseJsonData['data'][0]['url']; providerNotifier.modify(responseUrl); } else { throw Exception('Failed to load sentence'); } } void main() { runApp( const ProviderScope( child: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlueAccent), useMaterial3: true, ), home: MyHomePage(), ); } } class MyHomePage extends ConsumerWidget { MyHomePage({super.key}); final _messageController = TextEditingController(); @override Widget build(BuildContext context, WidgetRef ref) { final providerValue = ref.watch(responseProvider); final providerNotifier = ref.watch(responseProvider.notifier); return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: const Text('DALL·E 3 test'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( padding: const EdgeInsets.only( left: 25, right: 25, ), child: TextField( controller: _messageController, maxLines: 1, decoration: const InputDecoration( hintText: 'メッセージを入力', hintStyle: TextStyle(color: Colors.black54), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( child: const Text('AI画像生成実行'), onPressed: (){ var msg = _messageController.text.trim(); if(msg.isEmpty){ _messageController.clear(); return; } providerNotifier.clear(); apiRequest(msg, ref); }, ), ] ), const SizedBox(height: 30), Container( padding: const EdgeInsets.only( left: 25, right: 25, ), // 生成された画像の表示 child: providerValue == '' ? const Text('') : Image.network(providerValue), ), ], ), ), ); } }
DALL·E 3 API実行
OpenAIのAPIキーやモデルを指定して、POSTメソッドでリクエストを投げます。
それぞれのパラメータについては、コメントで記載しています。
ステータスコードが200だった場合は、レスポンスとして生成された画像のURLを取得できるため、そのURLを使用して表示しています。
ちなみに、APIキーについて、テストのためそのまま記述するコードになっていますが、本来であれば暗号化したりサーバ側で扱うようにしてください。
// 取得したAPIキーを入れる const apiKey = '{OpenAIのAPIキー}'; const domain = 'api.openai.com'; const path = 'v1/images/generations'; // モデルの指定 const model = 'dall-e-3'; // APIリクエスト http.Response response = await http.post( Uri.https(domain, path), headers: <String, String>{ 'Content-Type': 'application/json', 'Authorization': 'Bearer $apiKey', }, body: jsonEncode(<String, dynamic>{ // モデル "model": model, // 指示メッセージ "prompt": message, // 生成枚数 "n" : 1, // 画像サイズ "size": "1024x1024", // クオリティ "quality": "standard" }), ); if (response.statusCode == 200) { String responseData = utf8.decode(response.bodyBytes).toString(); final responseJsonData = jsonDecode(responseData); // レスポンスの中からURLを抜き出す responseUrl = responseJsonData['data'][0]['url']; providerNotifier.modify(responseUrl); } else { throw Exception('Failed to load sentence'); }
最後に
今回は、FlutterでDALL·E 3をAPI経由で使用してみたことを記事にしました。
どなたかの参考になると幸いです。