Tạo một ứng dụng Flutter để phân loại văn bản

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách thực hiện dự đoán phân loại văn bản từ một ứng dụng Flutter cùng với Luồng phân phát TensorFlow thông qua REST và gRPC.

Điều kiện tiên quyết

Kiến thức bạn sẽ học được

  • Cách xây dựng một ứng dụng Flutter đơn giản và phân loại văn bản thông qua phương thức Phân phát TensorFlow (REST và gRPC).
  • Cách hiển thị kết quả trong giao diện người dùng.

Bạn cần có

2. Thiết lập môi trường phát triển Flutter

Để phát triển Flutter, bạn cần có 2 phần mềm để hoàn thành phòng thí nghiệm này, đó là SDK Fluttertrình chỉnh sửa.

Bạn có thể chạy lớp học lập trình bằng bất kỳ thiết bị nào sau đây:

  • Trình mô phỏng iOS (yêu cầu cài đặt các công cụ Xcode).
  • Trình mô phỏng Android (yêu cầu thiết lập trong Android Studio).
  • Trình duyệt (cần có trình duyệt Chrome để gỡ lỗi).
  • Dưới dạng ứng dụng dành cho máy tính để bàn Windows, Linux hoặc macOS. Bạn phải phát triển trên nền tảng mà bạn dự định triển khai. Vì vậy, nếu muốn phát triển ứng dụng Windows dành cho máy tính, bạn phải phát triển trên Windows để truy cập vào chuỗi xây dựng thích hợp. Có các yêu cầu riêng của hệ điều hành được đề cập chi tiết trên docs.flutter.dev/desktop.

3. Bắt đầu thiết lập

Cách tải mã xuống cho lớp học lập trình này:

  1. Chuyển đến kho lưu trữ GitHub cho lớp học lập trình này.
  2. Nhấp vào Code > Download zip để tải tất cả mã xuống cho lớp học lập trình này.

2cd45599f51fb8a2.png

  1. Giải nén tệp zip đã tải xuống để giải nén thư mục gốc codelabs-main bằng tất cả tài nguyên mà bạn cần.

Đối với lớp học lập trình này, bạn chỉ cần các tệp trong thư mục con tfserving-flutter/codelab2 trong kho lưu trữ, nơi chứa hai thư mục:

  • Thư mục starter chứa mã dành cho người mới bắt đầu mà bạn xây dựng cho lớp học lập trình này.
  • Thư mục finished chứa mã đã hoàn tất cho ứng dụng mẫu đã hoàn thành.

4. Tải các phần phụ thuộc của dự án xuống

  1. Trong VS Code, hãy nhấp vào File > Open directory rồi chọn thư mục starter trong mã nguồn mà bạn đã tải xuống trước đó.
  2. Nếu bạn thấy một hộp thoại xuất hiện nhắc bạn tải xuống các gói bắt buộc cho ứng dụng dành cho người mới bắt đầu, hãy nhấp vào Nhận gói.
  3. Nếu bạn không thấy hộp thoại này, hãy mở thiết bị đầu cuối rồi chạy lệnh flutter pub get trong thư mục starter.

7ada07c300f166a6.png

5. Chạy ứng dụng khởi động

  1. Trong VS Code, hãy đảm bảo rằng Trình mô phỏng Android hoặc Trình mô phỏng iOS được thiết lập đúng cách và xuất hiện trong thanh trạng thái.

Ví dụ: đây là những thông tin bạn thấy khi sử dụng Pixel 5 với Trình mô phỏng Android:

9767649231898791.png

Dưới đây là những nội dung bạn thấy khi sử dụng iPhone 13 bằng Trình mô phỏng iOS:

95529e3a682268b2.png

  1. Nhấp vào a19a0c68bc4046e6.pngBắt đầu gỡ lỗi.

Chạy và khám phá ứng dụng

Ứng dụng sẽ khởi chạy trên Trình mô phỏng Android hoặc Trình mô phỏng iOS. Giao diện người dùng khá đơn giản. Có một trường văn bản cho phép người dùng nhập văn bản. Người dùng có thể chọn gửi dữ liệu tới phần phụ trợ bằng REST hoặc gRPC. Phụ trợ này sử dụng mô hình TensorFlow để thực hiện việc phân loại văn bản trên dữ liệu đầu vào được xử lý trước và trả lại kết quả phân loại cho ứng dụng khách. Ứng dụng này sẽ cập nhật giao diện người dùng.

b298f605d64dc132.png d3ef3ccd3c338108.png

Nếu bạn nhấp vào Phân loại, sẽ không có gì xảy ra vì chưa thể giao tiếp với phần phụ trợ.

6. Triển khai mô hình phân loại văn bản bằng TensorFlow Delivery

Phân loại văn bản là một thao tác máy học rất phổ biến, giúp phân loại văn bản thành các danh mục được xác định trước. Trong lớp học lập trình này, bạn triển khai mô hình đào tạo trước từ mô hình phát hiện mô hình phát hiện bình luận không liên quan bằng phương pháp lập trình mô hình TensorFlow Lite bằng phương pháp Phân phát TensorFlow và gọi phần phụ trợ từ giao diện người dùng Flutter để phân loại văn bản nhập là spam hoặc không phải nội dung vi phạm.

Bắt đầu phân phát TensorFlow

  • Trên thiết bị đầu cuối, hãy bắt đầu phân phát TensorFlow bằng Docker, nhưng thay thế trình giữ chỗ PATH/TO/SAVEDMODEL bằng đường dẫn tuyệt đối của thư mục mm_spam_savedmodel trên máy tính.
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, hệ thống sẽ tự động tải hình ảnh Phân phát TensorFlow xuống trước. Quá trình này sẽ mất một phút. Sau đó, Quá trình phân phát TensorFlow sẽ bắt đầu. Nhật ký sẽ trông giống như đoạn mã này:

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 ...

7. Mã thông báo đầu vào là câu

Phần phụ trợ này hiện đã sẵn sàng, vì vậy, bạn gần như đã sẵn sàng gửi yêu cầu của khách hàng đến Phân phát TensorFlow, nhưng trước tiên, bạn cần phải mã hóa câu đầu vào. Nếu kiểm tra cường độ đầu vào của mô hình, bạn có thể thấy rằng dự kiến sẽ có danh sách 20 số nguyên thay vì chuỗi thô. Mã hóa là khi bạn ánh xạ các từ riêng lẻ mà bạn nhập trong ứng dụng tới một danh sách số nguyên dựa trên từ điển từ vựng trước khi bạn gửi chúng đến phần phụ trợ để phân loại. Ví dụ: nếu bạn nhập buy book online to learn more, quá trình mã hoá sẽ liên kết mã đó với [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]. Những con số cụ thể có thể thay đổi dựa trên từ điển từ vựng.

  1. Trong tệp lib/main.dart, hãy thêm mã này vào phương thức predict() để tạo từ điển _vocabMap từ vựng.
// 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. Ngay sau đoạn mã trước, hãy thêm mã này để triển khai mã thông báo:
// 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;
  }
}

Mã này viết thường chuỗi câu, xóa các ký tự không phải chữ cái và liên kết các từ với 20 chỉ số nguyên dựa trên bảng từ vựng.

8. Kết nối ứng dụng Flutter với tính năng Phân phát TensorFlow thông qua REST

Có hai cách để gửi yêu cầu đến Phục vụ TensorFlow:

  • Kiến trúc chuyển trạng thái đại diện (REST)
  • gRPC

Gửi yêu cầu và nhận phản hồi thông qua REST

Có 3 bước đơn giản để gửi yêu cầu và nhận phản hồi thông qua REST:

  1. Tạo yêu cầu REST.
  2. Gửi yêu cầu REST tới TensorFlowServe.
  3. Trích xuất kết quả dự đoán từ phản hồi REST và hiển thị giao diện người dùng.

Bạn cần hoàn thành các bước này trong tệp main.dart.

Tạo và gửi yêu cầu REST tới TensorFlowServe

  1. Hiện tại, hàm predict() không gửi yêu cầu Kiến trúc chuyển trạng thái đại diện (REST) đến phục vụ TensorFlow. Bạn cần triển khai nhánh REST để tạo yêu cầu REST:
if (_connectionMode == ConnectionModeType.rest) {
  // TODO: Create and send the REST request.

}
  1. Thêm mã này vào nhánh 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],
  }),
);

Xử lý phản hồi REST (Phân phát) của TensorFlow

  • Thêm mã này ngay sau đoạn mã trước để xử lý phản hồi 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');
}

Mã xử lý hậu kỳ trích xuất xác suất mà câu nhập là thông báo spam từ phản hồi và hiển thị kết quả phân loại trong giao diện người dùng.

Chạy

  1. Nhấp vào a19a0c68bc4046e6.png Bắt đầu gỡ lỗi rồi đợi ứng dụng tải.
  2. Nhập một số văn bản rồi chọn REST > Phân loại.

8e21d795af36d07a.png e79a0367a03c2169.png

9. Kết nối ứng dụng Flutter với tính năng Phân phát TensorFlow thông qua gRPC

Ngoài REST, việc phân phát TensorFlow cũng hỗ trợ gRPC.

b6f4449c2c850b0e.png

gRPC là một khung lệnh gọi từ xa, nguồn mở hiện đại, hiệu suất cao, có thể chạy trong mọi môi trường. API này có thể kết nối các dịch vụ trong và trên các trung tâm dữ liệu một cách hiệu quả với khả năng hỗ trợ dễ dàng để cân bằng tải, theo dõi, kiểm tra tình trạng và xác thực. Theo quan sát, gRPC có hiệu suất cao hơn REST trong thực tế.

Gửi yêu cầu và nhận phản hồi bằng gRPC

Có 4 bước đơn giản để gửi yêu cầu và nhận phản hồi bằng gRPC:

  1. Không bắt buộc: Tạo mã mã ứng dụng gRPC.
  2. Tạo yêu cầu gRPC.
  3. Gửi yêu cầu gRPC đến TensorFlowServe.
  4. Trích xuất kết quả dự đoán từ phản hồi gRPC và hiển thị giao diện người dùng.

Bạn cần hoàn thành các bước này trong tệp main.dart.

Không bắt buộc: Tạo mã mã ứng dụng gRPC

Để sử dụng gRPC với TensorFlowServe, bạn cần phải tuân theo quy trình làm việc của gRPC. Để tìm hiểu thêm về các chi tiết, hãy xem tài liệu gRPC.

a9d0e5cb543467b4.png

TensorFlow và TensorFlow xác định các tệp .proto cho bạn. Kể từ TensorFlow và TensorFlow phân phát 2.8, .proto tệp này là những tệp cần thiết:

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
  • Trong thiết bị đầu cuối, hãy chuyển đến thư mục starter/lib/proto/ và tạo mã trang:
bash generate_grpc_stub_dart.sh

Tạo yêu cầu gRPC

Tương tự như yêu cầu REST, bạn tạo yêu cầu gRPC trong chi nhánh gRPC.

if (_connectionMode == ConnectionModeType.rest) {

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

}
  • Thêm mã này để tạo yêu cầu 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});

Lưu ý: Tên biến thể đầu vào và đầu ra có thể khác nhau theo mô hình, ngay cả khi kiến trúc mô hình giống nhau. Hãy nhớ cập nhật mô hình đó nếu bạn tự đào tạo mô hình của mình.

Gửi yêu cầu gRPC đến TensorFlowServe

  • Thêm mã này sau đoạn mã trước để gửi yêu cầu gRPC đến TensorFlowServe:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);

Xử lý phản hồi gRPC từ TensorFlowServe

  • Thêm mã này sau đoạn mã trước để triển khai các hàm gọi lại để xử lý phản hồi:
// 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');
}

Bây giờ, mã xử lý hậu kỳ trích xuất kết quả phân loại từ phản hồi và hiển thị kết quả đó trên giao diện người dùng.

Chạy

  1. Nhấp vào a19a0c68bc4046e6.png Bắt đầu gỡ lỗi rồi đợi ứng dụng tải.
  2. Nhập một số văn bản rồi chọn gRPC > Classify.

e44e6e9a5bde2188.png 92644d723f61968c.png

10. Xin chúc mừng

Bạn đã dùng tính năng Phân phát TensorFlow để thêm tính năng phân loại văn bản vào ứng dụng của bạn!

Trong lớp học lập trình tiếp theo, bạn sẽ cải thiện mô hình này để có thể phát hiện những tin nhắn rác cụ thể mà ứng dụng hiện tại không phát hiện được.

Tìm hiểu thêm