Skip to content

Instantly share code, notes, and snippets.

@savelee
Last active March 8, 2021 11:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save savelee/7068e6cea695088bcf06031d9e435b48 to your computer and use it in GitHub Desktop.
Save savelee/7068e6cea695088bcf06031d9e435b48 to your computer and use it in GitHub Desktop.
Dialogflow Flutter example
import 'package:meta/meta.dart';
import 'package:googleapis_auth/auth_io.dart' as auth;
import "package:googleapis/dialogflow/v2.dart";
import 'package:uuid/uuid.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';
class Dialogflow {
final String serviceAccountPath;
auth.ServiceAccountCredentials credentials;
auth.AuthClient sessionClient;
DialogflowApi df;
String projectId;
/// Create a Dialogflow instance
///
/// ```
/// var df = Dialogflow(serviceAccountPath: "assets/credentials.json");
/// var sessionPath = await df.getSession();
/// var request = Dialogflow.getRequestTextInput(query, "en-US");
/// var response = await df.detectIntent(request, sessionPath);
///
/// print(response.queryResult.fulfillmentText);
/// ```
Dialogflow({ @required this.serviceAccountPath});
Future<String> getSession() async {
const scopes = ["https://www.googleapis.com/auth/cloud-platform"];
// Load the service account the specified path (see pubspec.yaml)
String jsonCredentials = await _getJsonCredentials(this.serviceAccountPath);
// Set the projectId
Map jsonData = json.decode(jsonCredentials);
this.projectId = jsonData['project_id'];
try{
// Get the credentials from the service account json file
this.credentials = auth.ServiceAccountCredentials.fromJson(jsonCredentials);
// Create an authentication client
auth.AuthClient client = await auth.clientViaServiceAccount(this.credentials, scopes);
// Set the Dialogflow API instance
this.df = DialogflowApi(client);
} catch (e) {
print(e);
}
// Return the full Session path
return this._getSessionPath();
}
// Build a Dialogflow Text request
static GoogleCloudDialogflowV2DetectIntentRequest getRequestTextInput(String msg, String lang){
// Create a text input
final inputText = GoogleCloudDialogflowV2TextInput()
..text = msg
..languageCode = lang;
// Assign the inputText to the queryInput
final queryInput = GoogleCloudDialogflowV2QueryInput()
..text = inputText;
// Get the rest of the request
GoogleCloudDialogflowV2DetectIntentRequest request = _getRequest(queryInput);
return request;
}
// Build a Dialogflow Audio request
static detectAudioStream(String msg){
//TODO
}
Future<GoogleCloudDialogflowV2DetectIntentResponse> detectIntent(GoogleCloudDialogflowV2DetectIntentRequest request, String sessionPath) async {
// Get a session URL for detectIntent call
var session = "$sessionPath:detectIntent";
final response = await this.df.projects.agent.sessions.detectIntent(request, session);
return response;
}
String _getSessionPath() {
// Get a session path with a unique session id
var sessionId = new Uuid().v4();
return "projects/${this.projectId}/agent/sessions/$sessionId";
}
Future<String> _getJsonCredentials(String path) async {
var response;
try{
// Read the credentials from the JSON file as a String
response = await rootBundle.loadString(path);
} catch (e) {
print(e);
}
return response;
}
static GoogleCloudDialogflowV2DetectIntentRequest _getRequest(GoogleCloudDialogflowV2QueryInput queryInput) {
// Build the request
final request = new GoogleCloudDialogflowV2DetectIntentRequest()
..queryInput = queryInput;
return request;
}
}
import 'package:flutter/material.dart';
import 'package:flutter_dialogflow_agent/dialogflow_v2.dart';
import 'flutter_sound_recorder.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Dialogflow Agent',
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
debugShowCheckedModeBanner: false,
home: new HomePageDialogflow(),
);
}
}
class HomePageDialogflow extends StatefulWidget {
HomePageDialogflow({Key key, this.title}) : super(key: key);
final String title;
@override
_HomePageDialogflow createState() => new _HomePageDialogflow();
}
class _HomePageDialogflow extends State<HomePageDialogflow> {
int _selectedIndex = 0;
final List<ChatMessage> _messages = <ChatMessage>[];
final TextEditingController _textController = new TextEditingController();
Widget _buildTextComposer() {
return new IconTheme(
data: new IconThemeData(color: Theme.of(context).accentColor),
child: new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: new Row(
children: <Widget>[
new Flexible(
child: new TextField(
controller: _textController,
onSubmitted: _handleSubmitted,
decoration:
new InputDecoration.collapsed(hintText: "Send a message"),
),
),
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),
child: new IconButton(
icon: new Icon(Icons.send),
onPressed: () => _handleSubmitted(_textController.text)),
),
],
),
),
);
}
void response(query) async {
_textController.clear();
var df = Dialogflow(serviceAccountPath: "assets/credentials.json");
var sessionPath = await df.getSession();
var request = Dialogflow.getRequestTextInput(query, "en-US");
var response = await df.detectIntent(request, sessionPath);
ChatMessage message = new ChatMessage(
text: response.queryResult.fulfillmentText,
name: "Bot",
type: false,
);
setState(() {
_messages.insert(0, message);
});
}
void _handleSubmitted(String text) {
_textController.clear();
ChatMessage message = new ChatMessage(
text: text,
name: "You",
type: true,
);
setState(() {
_messages.insert(0, message);
});
response(text);
}
void _onNavItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
List<Widget> _widgetOptions = <Widget>[
Column(children: <Widget>[
new Flexible(
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)),
new Divider(height: 1.0),
new Container(
decoration: new BoxDecoration(color: Theme.of(context).cardColor),
child: _buildTextComposer(),
),
]),
AudioRecognize()
];
return new Scaffold(
appBar: new AppBar(
centerTitle: true,
title: new Text("Flutter Dialogflow Agent"),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.code),
label: 'Chatbot',
),
BottomNavigationBarItem(
icon: Icon(Icons.mic),
label: 'Speech',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onNavItemTapped,
),
);
}
}
class ChatMessage extends StatelessWidget {
ChatMessage({this.text, this.name, this.type});
final String text;
final String name;
final bool type;
List<Widget> otherMessage(context) {
return <Widget>[
new Container(
margin: const EdgeInsets.only(right: 16.0),
child: new CircleAvatar(child: new Text('B')),
),
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(this.name,
style: new TextStyle(fontWeight: FontWeight.bold)),
new Container(
margin: const EdgeInsets.only(top: 5.0),
child: new Text(text),
),
],
),
),
];
}
List<Widget> myMessage(context) {
return <Widget>[
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Text(this.name, style: Theme.of(context).textTheme.subtitle1),
new Container(
margin: const EdgeInsets.only(top: 5.0),
child: new Text(text),
),
],
),
),
new Container(
margin: const EdgeInsets.only(left: 16.0),
child: new CircleAvatar(
child: new Text(
this.name[0],
style: new TextStyle(fontWeight: FontWeight.bold),
)),
),
];
}
@override
Widget build(BuildContext context) {
return new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: this.type ? myMessage(context) : otherMessage(context),
),
);
}
}
# ...
dependencies:
uuid: 2.2.2
googleapis: ^1.0.0
googleapis_auth: any
flutter:
sdk: flutter
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/credentials.json
#...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment