How to use AI models of OpenAI inside your Flutter app

·

4 min read

OpenAI has emerged as a prominent player in the tech industry, offering a suite of cutting-edge artificial intelligence (AI) technologies. Among its most notable contributions are realistic image generators, 3D-model creators, and the renowned ChatGPT and GPT models.

As developers, the REST APIs provided by OpenAI enable direct utilization of these models in your applications, adding significant value to your products. And as Flutter developers, incorporating these APIs can greatly enhance the functionality of your projects and apps.

For instance, consider the potential of offering an AI chatbot within your app that can provide immediate and accurate responses to users inquiries. Similarly, integrating an AI detector for unsafe content and messages can greatly improve the moderation capabilities of your social networking app. With OpenAI’s advanced AI technologies, the possibilities for enhancing your app’s functionality are vast.

Get Started:

OpenAI provides developers with the convenience of using REST APIs that can be easily accessed using http or dio Dart Packages. However, implementing and managing these APIs can be time-consuming and error-prone, resulting in unnecessary requests that can lead to increased billing. To address these challenges, a Dart/Flutter package already exists that provides a seamless experience while working with OpenAI APIs which is dart_openai.

This package handles all the necessary details, ensuring that developers can focus on implementing the functionality they need without worrying about the underlying details of the API. By using this package, developers can enjoy a 100% Dart development experience that is optimized for their workflow.

When working with OpenAI APIs, it’s important to keep your API keys secure to prevent unauthorized access. A recommended approach in Flutter is to store your keys in an .env file and read them at runtime using the envied package or any other package you're familliar with. This approach ensures that your API keys remain confidential and are only accessible when needed:

.env file:

OPEN_AI_API_KEY=<REPLACE WITH YOUR API KEY>

lib/env/env.dart file:

import 'package:envied/envied.dart';
part 'env.g.dart';

@Envied(path: ".env")
abstract class Env {
  @EnviedField(varName: 'OPEN_AI_API_KEY') // the .env variable.
  static const apiKey = _Env.apiKey;
}

main.dart file:

void main() {
 OpenAI.apiKey = Env.apiKey; // Initializes the package with that API key
 runApp(MyApp());
}

When using the dart_openai package, you only need to initialize it with your API key once as the example above. After that, you can use the package throughout your entire application without having to re-initialize it repeatedly. All subsequent requests to the OpenAI API will automatically use the same key that you initially provided during the initialization process.

This not only saves time but also ensures consistency and avoids errors that could occur if the key were to be re-entered multiple times. Once the package is set up, developers can easily integrate OpenAI functionality into their applications, unlocking the power of advanced AI technologies without having to worry about the underlying implementation details.

The package now will offer you direct, easy-to-call methods that you can check all of them from the package’s documentation, in order to make AI requests, as example let’s create a simple flutter app that takes an input from the user and then generate an AI response from it that will be shown in the app:

import 'package:dart_openai/openai.dart';
import 'package:flutter/material.dart';

void main() {
  OpenAI.apiKey = Env.apiKey;

  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'OpenAI flutter demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: App(),
    );
  }
}

class App extends StatefulWidget {
  const App({super.key});

  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  String _result = "";
  TextEditingController? _controller;
  @override
  void initState() {
    _controller = TextEditingController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        padding: const EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            TextField(
              controller: _controller,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                _result = "";

                OpenAI.instance.completion
                    .createStreamText(
                  model: "text-davinci-003",
                  prompt: _controller!.text,
                  maxTokens: 140,
                  temperature: 0.9,
                )
                    .listen((result) {
                  setState(() {
                    _result += result;
                  });
                });
              },
              child: const Text("click"),
            ),
            const SizedBox(height: 40),
            Text(
              _result,
              textAlign: TextAlign.center,
              style: Theme.of(context).textTheme.labelLarge?.copyWith(
                    color: Colors.black,
                    fontWeight: FontWeight.bold,
                  ),
            ),
          ],
        ),
      ),
    );
  }
}

And this is the result of the app that we build:

dart_openai:

https://pub.dev/packages/dart_openai

https://github.com/anasfik/openai