1. قبل البدء
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية تنفيذ استنتاج تصنيف النص من تطبيق Flutter باستخدام خدمة TensorFlow Works من خلال REST وgRPC.
المتطلّبات الأساسية
- المعرفة الأساسية بتطوير Flutter باستخدام Dart
- المعرفة الأساسية بتعلُّم الآلة باستخدام TensorFlow، مثل التدريب مقابل النشر
- معرفة أساسية حول محطات الدفع وقاعدة الإرساء
- تدريب نموذج رصد التعليقات غير المرغوب فيها باستخدام TensorFlow Lite Lite Maker Maker
ما ستتعرَّف عليه
- كيفية إنشاء تطبيق Flutter بسيط وتصنيف النصوص من خلال TensorFlow للعرض (REST وgRPC)
- كيفية عرض النتائج في واجهة المستخدم.
الأشياء التي تحتاج إليها
- حزمة تطوير البرامج (Fltter)
- إعداد Android أو iOS لـ Flutter
- إعداد رمز Visual Studio (VS Code) لكل من Flutter وDart
- الدوكر
- البش
- مجمِّع المخزن المؤقت للبرمولات والمكوِّن الإضافي gRPC Dart للمكوِّن الإضافي للبروتوكول (مطلوب فقط إذا كنت تريد إعادة إنشاء كائن gRPC بنفسك)
2. إعداد بيئة تطوير Flutter
لتطوير Flutter، تحتاج إلى برنامجَين لإكمال هذا الدرس التطبيقي، وهما Fltter SDK ومحرّر.
يمكنك تشغيل الدرس التطبيقي باستخدام أي من الأجهزة التالية:
- محاكي iOS (يتطلب تثبيت أدوات Xcode).
- محاكي Android (يتطلب الإعداد في "استوديو Android")
- المتصفح (يكون Chrome مطلوبًا لتصحيح الأخطاء).
- كتطبيق متوافق مع نظام التشغيل Windows أو Linux أو macOS. عليك تطويرها على النظام الأساسي الذي تخطط لنشره. لذلك، إذا كنت ترغب في تطوير تطبيق سطح المكتب على Windows، يجب عليك تطويره على Windows للوصول إلى سلسلة الإصدار المناسبة. هناك متطلبات متعلقة بنظام التشغيل يتم تناولها بالتفصيل في docs.flutter.dev/desktop.
3- الإعداد
لتنزيل الرمز في هذا الدرس التطبيقي حول الترميز:
- انتقِل إلى مستودع GitHub لهذا الدرس التطبيقي حول الترميز.
- انقر على رمز > تنزيل ملف zip لتنزيل كل رموز هذا الدرس التطبيقي حول الترميز.
- يمكنك فك ضغط ملف ZIP الذي تم تنزيله لفك ضغط مجلد الجذر
codelabs-main
الذي يتضمّن جميع الموارد التي تحتاجها.
بالنسبة إلى هذا الدرس التطبيقي حول الترميز، تحتاج فقط إلى الملفات في دليل tfserving-flutter/codelab2
الفرعي في المستودع، الذي يحتوي على مجلدَين:
- يتضمّن المجلد
starter
رمز التفعيل الذي تستند إليه في هذا الدرس التطبيقي حول الترميز. - يحتوي مجلد
finished
على الرمز المكتمل لنموذج التطبيق المكتمل.
4. تنزيل تبعيات المشروع
- في رمز VS، انقر على File > افتح المجلد ثم اختَر المجلد
starter
من رمز المصدر الذي نزّلته سابقًا. - إذا ظهر مربع حوار يطلب منك تنزيل الحزم المطلوبة للتطبيق للمبتدئين، انقر على الحصول على الحزم.
- إذا لم يظهر لك مربع الحوار هذا، افتح محطّة الدفع، ثم شغِّل الأمر
flutter pub get
في المجلدstarter
.
5. تشغيل تطبيق إجراء التفعيل
- في رمز VS، تأكَّد من إعداد محاكي Android أو محاكي iOS بشكلٍ صحيح ويظهر في شريط الحالة.
على سبيل المثال، إليك ما تراه عند استخدام هاتف Pixel 5 مع محاكي Android:
في ما يلي ما يظهر لك عند استخدام iPhone 13 مع محاكي iOS:
- انقر على بدء تصحيح الأخطاء.
تشغيل التطبيق واستكشافه
يجب تشغيل التطبيق على محاكي Android أو محاكي iOS. واجهة المستخدم سهلة جدًا. هناك حقل نصي يسمح للمستخدم بكتابة النص. يمكن للمستخدم اختيار ما إذا كان سيتم إرسال البيانات إلى الخلفية باستخدام REST أو gRPC. تستخدم الخلفية نموذج TensorFlow لإجراء تصنيف نصي على الإدخال الذي تتم معالجته مسبقًا وعرض نتيجة التصنيف إلى تطبيق العميل الذي يحدّث واجهة المستخدم بدوره.
إذا نقرت على التصنيف، لن يحدث شيء لأنه لا يمكن التواصل مع الخلفية بعد.
6- نشر نموذج تصنيف نصي باستخدام TensorFlow
يُعدّ تصنيف النص مهمة شائعة جدًا لتعلُّم الآلة وتصنّف النصوص ضمن فئات محدّدة مسبقًا. في هذا الدرس التطبيقي حول الترميز، يمكنك نشر النموذج الذي تم تدريبه مسبقًا من تدريب نموذج رصد التعليقات غير المرغوب فيها باستخدام TensorFlow Lite Maker Maker Code (برنامج الترميز) باستخدام TensorFlow Works والاستدعاء للخلفية من الواجهة الأمامية لتطبيق Flutter لتصنيف نص الإدخال على أنه رسائل غير مرغوب فيها أو ليس محتوى غير مرغوب فيه.
بدء عرض TensorFlow
- في الوحدة الطرفية، ابدأ تشغيل TensorFlow للعرض باستخدام docker، ولكن استبدِل العنصر النائب
PATH/TO/SAVEDMODEL
بالمسار المطلق للمجلدmm_spam_savedmodel
على جهاز الكمبيوتر.
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 تلقائيًا صورة العرض TensorFlow أولاً، الأمر الذي يستغرق دقيقة واحدة. بعد ذلك، من المفترض أن يبدأ عرض TensorFlow. يجب أن يظهر السجل مثل مقتطف الرمز هذا:
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- إنشاء جملة مميّزة من إدخال الإدخال
الخلفية جاهزة الآن، لذا أنت مستعد تقريبًا لإرسال طلبات العميل إلى TensorFlow Works، ولكن تحتاج أولاً إلى إنشاء رمز مميز لجملة الإدخال. إذا أجريت فحصًا لموتر الإدخال للنموذج، يمكنك ملاحظة أنّه يتوقع قائمة من 20 رقمًا صحيحًا بدلاً من سلاسل أولية. يتم إنشاء الرمز المميّز عند ربط الكلمات الفردية التي تكتبها في التطبيق بقائمة من الأعداد الصحيحة استنادًا إلى قاموس المفردات قبل إرسالها إلى الخلفية للتصنيف. على سبيل المثال، إذا كتبت buy book online to learn more
، ستربطه عملية الترميز بالرمز [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
. ويمكن أن تختلف الأرقام باختلاف قاموس المفردات.
- في ملف
lib/main.dart
، أضِف هذا الرمز إلى طريقةpredict()
لإنشاء قاموس_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]);
}
}
}
- مباشرةً بعد مقتطف الرمز السابق، أضِف هذا الرمز لتنفيذ الترميز:
// 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;
}
}
يؤدي هذا الرمز إلى كتابة سلسلة الجملة بأحرف صغيرة، وإزالة الأحرف غير أبجدية، وتعيين الكلمات إلى 20 فهرسًا لطول العدد الصحيح استنادًا إلى جدول المفردات.
8- ربط تطبيق Flutter بخدمة TensorFlow من خلال خدمات REST
تتوفّر طريقتان لإرسال الطلبات إلى TensorFlow Driving:
- استراحة
- gRPC
إرسال طلبات وتلقّي ردود من خلال REST
هناك ثلاث خطوات بسيطة لإرسال الطلبات وتلقّي الردود من خلال خدمة REST:
- إنشاء طلب REST.
- يُرجى إرسال طلب REST إلى TensorFlow serving.
- استخرِج النتيجة المتوقعة من استجابة REST واعرض واجهة المستخدم.
يمكنك إكمال هذه الخطوات في ملف main.dart
.
إنشاء طلب REST وإرساله إلى TensorFlow العرض
- لا ترسل دالة
predict()
في الوقت الحالي طلب REST إلى TensorFlow العرض. عليك تنفيذ فرع REST لإنشاء طلب REST:
if (_connectionMode == ConnectionModeType.rest) {
// TODO: Create and send the REST request.
}
- إضافة هذا الرمز إلى فرع 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],
}),
);
معالجة استجابة REST من TensorFlow العرض
- أضف هذا الرمز مباشرةً بعد مقتطف الرمز السابق لمعالجة استجابة 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');
}
يعمل رمز المعالجة اللاحقة على استخراج احتمالية أن تكون جملة الإدخال رسالة غير مرغوب فيها من الاستجابة وتعرض نتيجة التصنيف في واجهة المستخدم.
التشغيل
- انقر على بدء تصحيح الأخطاء ثم انتظر حتى يتم تحميل التطبيق.
- أدخِل نصًا ثم اختَر REST > Classify.
9- ربط تطبيق Flutter بخدمة TensorFlow من خلال gRPC
بالإضافة إلى REST، تتوافق خدمة TensorFlow أيضًا مع gRPC.
gRPC هو إطار عمل حديث ومفتوح المصدر وعالي الأداء للإجراءات عن بُعد يمكن تشغيله في أي بيئة. وتستطيع هذه الخدمة توصيل الخدمات بكفاءة في مراكز البيانات وفي مناطق أخرى مع دعم قابل للتوصيل لموازنة الحِمل وتتبُّع الحالة الصحية والمصادقة. لقد لاحظنا أن gRPC هو أكثر أداءً من REST من الناحية العملية.
إرسال الطلبات وتلقّي الردود باستخدام gRPC
هناك أربع خطوات بسيطة لإرسال الطلبات وتلقّي الردود باستخدام gRPC:
- اختياري: أنشئ رمز كائن gRPC للعميل.
- إنشاء طلب gRPC.
- أرسِل طلب gRPC إلى TensorFlow العرض.
- استخرِج النتيجة المتوقعة من استجابة gRPC وعرض واجهة المستخدم.
يمكنك إكمال هذه الخطوات في ملف main.dart
.
اختياري: إنشاء رمز كائن gRPC للعميل
لاستخدام gRPC مع عرض TensorFlow، عليك اتّباع طريقة عمل gRPC. لمعرفة المزيد من التفاصيل، يُرجى الاطّلاع على وثائق gRPC.
يشكّل TensorFlow للعرض وTensorFlow ملفات .proto
بالنيابة عنك. اعتبارًا من TensorFlow وTensorFlow العرض 2.8، يجب توفير الملفات التالية .proto
:
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
- في الوحدة الطرفية، انتقِل إلى المجلد
starter/lib/proto/
وأنشِئ التنويه الموجز:
bash generate_grpc_stub_dart.sh
إنشاء طلب gRPC
على غرار طلب REST، يمكنك إنشاء طلب gRPC في فرع gRPC.
if (_connectionMode == ConnectionModeType.rest) {
} else {
// TODO: Create and send the gRPC request.
}
- أضِف هذا الرمز لإنشاء طلب 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});
ملاحظة: قد تختلف أسماء موتّر الإدخال والإخراج من نموذج إلى نموذج، حتى إذا كانت بنيات النموذج متماثلة. واحرص على تعديلها إذا تدريبت نموذجك.
إرسال طلب gRPC إلى TensorFlow العرض
- يمكنك إضافة هذا الرمز بعد مقتطف الرمز السابق لإرسال طلب gRPC إلى TensorFlow Driving:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);
معالجة استجابة gRPC من TensorFlow
- يمكنك إضافة هذا الرمز بعد مقتطف الرمز السابق لتنفيذ وظائف رد الاتصال في التعامل مع الاستجابة:
// 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');
}
والآن يستخرج رمز ما بعد المعالجة نتيجة التصنيف من الاستجابة ويعرضها في واجهة المستخدم.
التشغيل
- انقر على بدء تصحيح الأخطاء ثم انتظر حتى يتم تحميل التطبيق.
- أدخِل نصًا ثم اختَر gRPC > Classify.
10- تهانينا
لقد استخدمت منصة TensorFlow للعرض لإضافة إمكانات تصنيف النص إلى تطبيقك.
في الدرس التطبيقي القادم حول الترميز، سيتم تحسين النموذج بحيث يمكنك رصد رسائل معيّنة غير مرغوب فيها لا يمكن رصدها في التطبيق الحالي.