Membuat aplikasi Flutter untuk mengklasifikasikan teks

1. Sebelum memulai

Dalam codelab ini, Anda akan mempelajari cara menjalankan inferensi klasifikasi teks dari aplikasi Flutter dengan TensorFlow Serving melalui REST dan gRPC.

Prasyarat

Yang akan Anda pelajari

  • Cara mem-build aplikasi Flutter sederhana dan mengklasifikasikan teks melalui TensorFlow Serving (REST dan gRPC).
  • Cara menampilkan hasilnya di UI.

Yang Anda butuhkan

2. Memulai persiapan

Untuk mendownload kode codelab ini:

  1. Buka repositori GitHub untuk codelab ini.
  2. Klik Code > Download zip guna mendownload semua kode untuk codelab ini.

2cd45599f51fb8a2.png

  1. Ekstrak file zip yang didownload untuk mengekstrak folder root codelabs-master dengan semua resource yang Anda butuhkan.

Untuk codelab ini, Anda hanya memerlukan file dalam subdirektori tfserving-flutter/codelab2 di repositori, yang berisi dua folder:

  • Folder starter berisi kode awal yang Anda buat untuk codelab ini.
  • Folder finished berisi kode yang sudah selesai untuk aplikasi contoh yang telah selesai.

3 Mendownload dependensi untuk project

  1. Di VS Code, klik File > Open folder, lalu pilih folder starter dari kode sumber yang Anda download sebelumnya.
  2. Jika muncul dialog yang meminta Anda mendownload paket yang diperlukan untuk aplikasi awal, klik Get packages.
  3. Jika Anda tidak melihat dialog ini, buka terminal lalu jalankan perintah flutter pub get di folder starter.

7ada07c300f166a6.png

4. Menjalankan aplikasi awal

  1. Di VS Code, pastikan Android Emulator atau Simulator iOS disiapkan dengan benar dan muncul di status bar.

Misalnya, berikut adalah tampilan yang Anda lihat saat menggunakan Pixel 5 dengan Android Emulator:

9767649231898791.png

Berikut adalah tampilan yang Anda lihat saat menggunakan iPhone 13 dengan Simulator iOS:

95529e3a682268b2.png

  1. Klik a19a0c68bc4046e6.png Start debugging.

Menjalankan dan menjelajahi aplikasi

Aplikasi akan diluncurkan di Android Emulator atau Simulator iOS. UI-nya cukup sederhana. Ada kolom teks yang dapat digunakan pengguna untuk mengetik teks. Pengguna dapat memilih apakah akan mengirim data ke backend dengan REST atau gRPC. Backend menggunakan model TensorFlow untuk melakukan klasifikasi teks pada input yang telah diproses sebelumnya dan menampilkan hasil klasifikasi ke aplikasi klien, yang kemudian akan mengupdate UI.

b298f605d64dc132.png d3ef3ccd3c338108.png

Jika Anda mengklik Classify, tidak akan terjadi apa-apa karena komunikasi dengan backend masih belum dapat dilakukan.

5. Men-deploy model klasifikasi teks dengan TensorFlow Serving

Klasifikasi teks adalah tugas machine learning yang sangat umum yang mengklasifikasikan teks ke dalam kategori yang telah ditentukan. Dalam codelab ini, Anda men-deploy model terlatih dari codelab Melatih model deteksi spam komentar dengan TensorFlow Lite Model Maker dengan TensorFlow Serving dan memanggil backend dari frontend Flutter Anda untuk mengklasifikasikan teks input sebagai spam atau bukan spam.

Memulai TensorFlow Serving

  • Di terminal Anda, mulai TensorFlow Serving dengan Docker, tetapi ganti placeholder PATH/TO/SAVEDMODEL dengan jalur absolut folder mm_spam_savedmodel di komputer Anda.
docker pull tensorflow/serving

docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/spam-detection" -e MODEL_NAME=spam-detection tensorflow/serving

Docker akan otomatis mendownload image TensorFlow Serving terlebih dahulu, yang memerlukan waktu sebentar. Setelah itu, TensorFlow Serving akan dimulai. Log akan terlihat seperti cuplikan kode berikut:

2022-02-25 06:01:12.513231: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-02-25 06:01:12.585012: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 3000000000 Hz
2022-02-25 06:01:13.395083: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ssd_mobilenet_v2_2/123
2022-02-25 06:01:13.837562: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 1928700 microseconds.
2022-02-25 06:01:13.877848: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ssd_mobilenet_v2_2/123/assets.extra/tf_serving_warmup_requests
2022-02-25 06:01:13.929844: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: spam-detection version: 123}
2022-02-25 06:01:13.985848: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-02-25 06:01:13.985987: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-02-25 06:01:13.988994: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
2022-02-25 06:01:14.033872: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ...
[evhttp_server.cc : 245] NET_LOG: Entering the event loop ...

6. Membuat token kalimat input

Backend sudah siap, sehingga Anda akan dapat mengirim permintaan klien ke TensorFlow Serving. Namun, Anda perlu membuat token kalimat input terlebih dahulu. Jika Anda memeriksa tensor input model, Anda dapat melihat bahwa tensor meminta daftar 20 bilangan bulat, bukan string mentah. Tokenisasi adalah proses saat Anda memetakan setiap kata yang diketik di aplikasi ke daftar bilangan bulat berdasarkan kamus kosakata sebelum mengirimkannya ke backend untuk tahap klasifikasi. Misalnya, jika Anda mengetik buy book online to learn more, proses tokenisasi akan memetakannya ke [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]. Angka spesifiknya dapat bervariasi berdasarkan kamus kosakata.

  1. Dalam file lib/main.dart, tambahkan kode ini ke metode predict() untuk membuat kamus kosakata _vocabMap.
// Build _vocabMap if empty.
if (_vocabMap.isEmpty) {
  final vocabFileString = await rootBundle.loadString(vocabFile);
  final lines = vocabFileString.split('\n');
  for (final l in lines) {
    if (l != "") {
      var wordAndIndex = l.split(' ');
      (_vocabMap)[wordAndIndex[0]] = int.parse(wordAndIndex[1]);
    }
  }
}
  1. Segera setelah cuplikan kode sebelumnya, tambahkan kode ini untuk menerapkan tokenisasi:
// Tokenize the input sentence.
final inputWords = _inputSentenceController.text
    .toLowerCase()
    .replaceAll(RegExp('[^a-z ]'), '')
    .split(' ');
// Initialize with padding token.
_tokenIndices = List.filled(maxSentenceLength, 0);
var i = 0;
for (final w in inputWords) {
  if ((_vocabMap).containsKey(w)) {
    _tokenIndices[i] = (_vocabMap)[w]!;
    i++;
  }

  // Truncate the string if longer than maxSentenceLength.
  if (i >= maxSentenceLength - 1) {
    break;
  }
}

Kode ini akan membuat string kalimat menggunakan huruf kecil, menghapus karakter non-alfabet, dan memetakan kata ke 20 indeks bilangan bulat berdasarkan tabel kosakata.

7. Menghubungkan aplikasi Flutter dengan TensorFlow Serving melalui REST

Ada dua cara untuk mengirim permintaan ke TensorFlow Serving:

  • REST
  • gRPC

Mengirim permintaan dan menerima respons melalui REST

Ada tiga langkah sederhana untuk mengirim permintaan dan menerima respons melalui REST:

  1. Buat permintaan REST.
  2. Kirim permintaan REST ke TensorFlow Serving.
  3. Ekstrak hasil prediksi dari respons REST dan render UI-nya.

Anda dapat menyelesaikan langkah-langkah ini di file main.dart.

Membuat dan mengirim permintaan REST ke TensorFlow Serving

  1. Saat ini, fungsi predict() tidak mengirimkan permintaan REST ke TensorFlow Serving. Anda perlu mengimplementasikan cabang REST untuk membuat permintaan REST:
if (_connectionMode == ConnectionModeType.rest) {
  // TODO: Create and send the REST request.

}
  1. Tambahkan kode ini ke cabang REST:
//Create the REST request.
final response = await http.post(
  Uri.parse('http://' +
      _server +
      ':' +
      restPort.toString() +
      '/v1/models/' +
      modelName +
      ':predict'),
  body: jsonEncode(<String, List<List<int>>>{
    'instances': [_tokenIndices],
  }),
);

Memproses respons REST dari TensorFlow Serving

  • Tambahkan kode ini tepat setelah cuplikan kode sebelumnya untuk menangani respons REST:
// Process the REST response.
if (response.statusCode == 200) {
  Map<String, dynamic> result = jsonDecode(response.body);
  if (result['predictions']![0][1] >= classificationThreshold) {
    return 'This sentence is spam. Spam score is ' +
        result['predictions']![0][1].toString();
  }
  return 'This sentence is not spam. Spam score is ' +
      result['predictions']![0][1].toString();
} else {
  throw Exception('Error response');
}

Kode pascapemrosesan mengekstrak probabilitas bahwa kalimat input adalah pesan spam dari respons dan menampilkan hasil klasifikasi di UI.

Menjalankan aplikasi

  1. Klik a19a0c68bc4046e6.png Start debugging, lalu tunggu aplikasi dimuat.
  2. Masukkan beberapa teks, lalu pilih REST > Classify.

8e21d795af36d07a.png e79a0367a03c2169.png

8 Menghubungkan aplikasi Flutter dengan TensorFlow Serving melalui gRPC

Selain REST, TensorFlow Serving juga mendukung gRPC.

b6f4449c2c850b0e.png

gRPC adalah framework Remote Procedure Call (RPC) modern, open source, dan berperforma tinggi yang dapat berjalan di lingkungan apa pun. Framework ini dapat menghubungkan layanan di dalam dan di seluruh pusat data secara efisien dengan dukungan yang dapat dicocokkan untuk load balancing, tracing, health checking, dan autentikasi. Berdasarkan pengamatan dalam praktiknya, performa gRPC lebih tinggi daripada REST.

Mengirim permintaan dan menerima respons dengan gRPC

Ada empat langkah sederhana untuk mengirim permintaan dan menerima respons dengan gRPC:

  1. Opsional: Buat kode stub klien gRPC.
  2. Buat permintaan gRPC.
  3. Kirim permintaan gRPC ke TensorFlow Serving.
  4. Ekstrak hasil yang diprediksi dari respons gRPC dan render UI-nya.

Anda dapat menyelesaikan langkah-langkah ini di file main.dart.

Opsional: Membuat kode stub klien gRPC

Untuk menggunakan gRPC dengan TensorFlow Serving, Anda harus mengikuti alur kerja gRPC. Untuk mempelajari detailnya lebih lanjut, baca dokumentasi gRPC.

a9d0e5cb543467b4.png

TensorFlow Serving dan TensorFlow menentukan file .proto untuk Anda. Mulai dari TensorFlow dan TensorFlow Serve 2.8, file .proto berikut adalah file yang diperlukan:

tensorflow/core/example/example.proto
tensorflow/core/example/feature.proto
tensorflow/core/protobuf/struct.proto
tensorflow/core/protobuf/saved_object_graph.proto
tensorflow/core/protobuf/saver.proto
tensorflow/core/protobuf/trackable_object_graph.proto
tensorflow/core/protobuf/meta_graph.proto
tensorflow/core/framework/node_def.proto
tensorflow/core/framework/attr_value.proto
tensorflow/core/framework/function.proto
tensorflow/core/framework/types.proto
tensorflow/core/framework/tensor_shape.proto
tensorflow/core/framework/full_type.proto
tensorflow/core/framework/versions.proto
tensorflow/core/framework/op_def.proto
tensorflow/core/framework/graph.proto
tensorflow/core/framework/tensor.proto
tensorflow/core/framework/resource_handle.proto
tensorflow/core/framework/variable.proto

tensorflow_serving/apis/inference.proto
tensorflow_serving/apis/classification.proto
tensorflow_serving/apis/predict.proto
tensorflow_serving/apis/regression.proto
tensorflow_serving/apis/get_model_metadata.proto
tensorflow_serving/apis/input.proto
tensorflow_serving/apis/prediction_service.proto
tensorflow_serving/apis/model.proto

google/protobuf/any.proto
google/protobuf/wrappers.proto
  • Di terminal Anda, buka folder starter/lib/proto/ dan buat stub:
bash generate_grpc_stub_dart.sh

Membuat permintaan gRPC

Serupa dengan permintaan REST, Anda membuat permintaan gRPC di cabang gRPC.

if (_connectionMode == ConnectionModeType.rest) {

} else {
  // TODO: Create and send the gRPC request.

}
  • Tambahkan kode ini untuk membuat permintaan gRPC:
//Create the gRPC request.
final channel = ClientChannel(_server,
    port: grpcPort,
    options:
        const ChannelOptions(credentials: ChannelCredentials.insecure()));
_stub = PredictionServiceClient(channel,
    options: CallOptions(timeout: const Duration(seconds: 10)));

ModelSpec modelSpec = ModelSpec(
  name: 'spam-detection',
  signatureName: 'serving_default',
);

TensorShapeProto_Dim batchDim = TensorShapeProto_Dim(size: Int64(1));
TensorShapeProto_Dim inputDim =
    TensorShapeProto_Dim(size: Int64(maxSentenceLength));
TensorShapeProto inputTensorShape =
    TensorShapeProto(dim: [batchDim, inputDim]);
TensorProto inputTensor = TensorProto(
    dtype: DataType.DT_INT32,
    tensorShape: inputTensorShape,
    intVal: _tokenIndices);

// If you train your own model, update the input and output tensor names.
const inputTensorName = 'input_3';
const outputTensorName = 'dense_5';
PredictRequest request = PredictRequest(
    modelSpec: modelSpec, inputs: {inputTensorName: inputTensor});

Catatan: Nama tensor input dan output dapat berbeda dari model ke model, meskipun arsitektur modelnya sama. Pastikan untuk memperbaruinya jika Anda melatih model sendiri.

Mengirim permintaan gRPC ke TensorFlow Serving

  • Tambahkan kode ini setelah cuplikan kode sebelumnya untuk mengirim permintaan gRPC ke TensorFlow Serving:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);

Memproses respons gRPC dari TensorFlow Serving

  • Tambahkan kode ini setelah cuplikan kode sebelumnya untuk menerapkan fungsi callback guna menangani respons:
// Process the response.
if (response.outputs.containsKey(outputTensorName)) {
  if (response.outputs[outputTensorName]!.floatVal[1] >
      classificationThreshold) {
    return 'This sentence is spam. Spam score is ' +
        response.outputs[outputTensorName]!.floatVal[1].toString();
  } else {
    return 'This sentence is not spam. Spam score is ' +
        response.outputs[outputTensorName]!.floatVal[1].toString();
  }
} else {
  throw Exception('Error response');
}

Kode pascapemrosesan sekarang akan mengekstrak hasil klasifikasi dari respons dan menampilkannya di UI.

Menjalankan aplikasi

  1. Klik a19a0c68bc4046e6.png Start debugging, lalu tunggu aplikasi dimuat.
  2. Masukkan beberapa teks, lalu pilih gRPC > Classify.

e44e6e9a5bde2188.png 92644d723f61968c.png

9. Selamat

Anda telah menggunakan TensorFlow Serving untuk menambahkan kemampuan klasifikasi teks ke aplikasi Anda.

Di codelab berikutnya, Anda akan meningkatkan kualitas model agar dapat mendeteksi pesan spam tertentu yang tidak dapat dideteksi oleh aplikasi saat ini.

Pelajari lebih lanjut