1. Antes de comenzar
Los motores de recomendaciones, también conocidos como recomendadores, son una aplicación muy importante del aprendizaje automático, ya que sugieren películas o restaurantes, y destacan videos entretenidos. Los recomendadores te ayudan a mostrar contenido atractivo a tus usuarios a partir de un gran grupo de candidatos. Por ejemplo, Google Play Store ofrece millones de apps para instalar, mientras que YouTube proporciona miles de millones de videos para mirar. Además, todos los días se agregan más apps y videos.
En este codelab, aprenderás a compilar un recomendador de pila completa con lo siguiente:
- TensorFlow Recommenders para entrenar un modelo de recuperación y clasificación para recomendaciones de películas
- TensorFlow Serving para entregar los modelos
- Flutter para crear una app multiplataforma que muestre películas recomendadas
Requisitos previos
- Conocimientos básicos sobre el desarrollo de Flutter con Dart
- Conocimientos básicos del aprendizaje automático con TensorFlow, como el entrenamiento y la implementación
- Conocimientos básicos sobre sistemas de recomendación
- Conocimientos básicos de Python, terminales y Docker
Qué aprenderás
- Cómo entrenar modelos de recuperación y clasificación con TensorFlow Recommenders
- Cómo entregar los modelos de recomendación entrenados con TensorFlow Serving
- Cómo crear una app multiplataforma de Flutter para mostrar los elementos recomendados
Requisitos
- SDK de Flutter
- Configuración de Android o iOS para Flutter
- Configuración de Flutter para computadoras
- Configuración de Flutter para la Web
- Configuración de Visual Studio Code (VS Code) para Flutter y Dart
- Docker
- Bash
- Python 3.7 o versiones posteriores
- Acceso a Colab
2. Configura tu entorno de desarrollo de Flutter
Para el desarrollo de Flutter, necesitas dos tipos de software para completar este codelab: el SDK de Flutter y un editor.
Puedes ejecutar el frontend del codelab con cualquiera de estos dispositivos:
- El simulador de iOS (requiere instalar las herramientas de Xcode)
- Android Emulator (requiere configuración en Android Studio)
- Un navegador (se requiere Chrome para la depuración)
- Como una aplicación para computadoras que ejecuten Windows, Linux o macOS (debes desarrollarla en la plataforma donde tengas pensado realizar la implementación; por lo tanto, si quieres desarrollar una app de escritorio para Windows, debes desarrollarla en ese SO a fin de obtener acceso a la cadena de compilación correcta; encuentra detalles sobre los requisitos específicos del sistema operativo en docs.flutter.dev/desktop).
Para el backend, necesitarás lo siguiente:
- Una máquina Linux o una Mac basada en Intel
3. Prepárate
Para descargar el código de este codelab, haz lo siguiente:
- Navega al repositorio de GitHub de este codelab.
- Haz clic en Code > Download ZIP para descargar todo el código de este codelab.

- Descomprime el archivo ZIP descargado para desempaquetar una carpeta raíz
codelabs-maincon todos los recursos que necesitas.
Para este codelab, solo necesitas los archivos del subdirectorio tfrs-flutter/ en el repositorio, que contiene varias carpetas:
- Las carpetas
step0astep5, que contienen el código de partida en el que se basa cada paso de este codelab. - La carpeta
finishedcontiene el código completado de la app de ejemplo finalizada. - Cada carpeta contiene una subcarpeta
backend, que incluye el código de backend del motor de recomendaciones, y una subcarpetafrontend, que incluye el código de frontend de Flutter.
4. Descarga las dependencias del proyecto
Backend
Usaremos Flask para crear nuestro backend. Abre la terminal y ejecuta lo siguiente:
pip install Flask flask-cors requests numpy
Frontend
- En VS Code, haz clic en Archivo > Abrir carpeta y, luego, selecciona la carpeta
step0del código fuente que descargaste antes. - Abre el archivo
step0/frontend/lib/main.dart. Si aparece un diálogo de VS Code en el que se te solicita que descargues los paquetes necesarios para la app de partida, haz clic en Get packages. - Si no ves este diálogo, abre la terminal y, luego, ejecuta el comando
flutter pub geten la carpetastep0/frontend.

5. Paso 0: Ejecuta la app de inicio
- Abre el archivo
step0/frontend/lib/main.darten VS Code y asegúrate de que Android Emulator o el simulador de iOS estén configurados correctamente y aparezcan en la barra de estado.
Por ejemplo, a continuación, se muestra lo que ves cuando usas un Pixel 5 con Android Emulator:

A continuación, se muestra lo que ves cuando usas un iPhone 13 con el simulador de iOS:

- Haz clic en
Start debugging.
Ejecuta y explora la app
La app debe iniciarse en Android Emulator o el simulador de iOS. La IU es bastante sencilla. Hay un campo de texto que le permite al usuario escribir el texto como ID de usuario. La app de Flutter enviará la solicitud de búsqueda al backend, que ejecutará 2 modelos de recomendación y devolverá una lista clasificada de recomendaciones de películas. El frontend mostrará el resultado en la IU después de recibir la respuesta.

Si haces clic en Recommend ahora, no sucede nada porque la app aún no puede comunicarse con el backend.
6. Paso 1: Crea los modelos de recuperación y clasificación para el motor de recomendaciones
Los motores de recomendaciones del mundo real suelen constar de varias etapas:
- La etapa de recuperación es responsable de seleccionar un conjunto inicial de cientos de candidatos entre todos los posibles. El objetivo principal de este modelo es descartar de manera eficiente a todos los candidatos que no le interesan al usuario. Dado que el modelo de recuperación puede procesar millones de candidatos, debe ser eficiente desde el punto de vista computacional.
- En la etapa de clasificación, se toman los resultados del modelo de recuperación y se ajustan para seleccionar el mejor conjunto posible de recomendaciones. Su tarea es reducir el conjunto de elementos que pueden interesar al usuario a una lista de candidatos probables de cientos de elementos.
- La etapa posterior a la clasificación ayuda a garantizar la diversidad, la actualidad y la equidad, y reorganiza los elementos candidatos en un conjunto de recomendaciones útiles en el orden de decenas.

En este codelab, entrenarás un modelo de recuperación y un modelo de clasificación con el popular conjunto de datos de MovieLens. Puedes abrir el código de entrenamiento a continuación a través de Colab y seguir las instrucciones:
7. Paso 2: Crea el backend del motor de recomendaciones
Ahora que entrenaste los modelos de recuperación y clasificación, puedes implementarlos y crear un backend.
Inicia TensorFlow Serving
Dado que necesitas usar los modelos de recuperación y clasificación para generar la lista de películas recomendadas, los implementarás al mismo tiempo con TensorFlow Serving.
- En tu terminal, ve a la carpeta
step2/backenden tu computadora y, luego, inicia TensorFlow Serving con Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config
Docker descarga automáticamente la imagen de TensorFlow Serving primero, lo cual tarda un minuto. Luego, TensorFlow Serving debería iniciarse. El registro debería verse como este fragmento de código:
2022-04-24 09:32:06.461702: I tensorflow_serving/model_servers/server_core.cc:465] Adding/updating models.
2022-04-24 09:32:06.461843: I tensorflow_serving/model_servers/server_core.cc:591] (Re-)adding model: retrieval
2022-04-24 09:32:06.461907: I tensorflow_serving/model_servers/server_core.cc:591] (Re-)adding model: ranking
2022-04-24 09:32:06.576920: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: retrieval version: 123}
2022-04-24 09:32:06.576993: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577011: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577848: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.583809: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.583879: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.584970: I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-04-24 09:32:06.629900: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.634662: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2800000000 Hz
2022-04-24 09:32:06.672534: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.673629: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: ranking version: 123}
2022-04-24 09:32:06.673765: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: ranking version: 123}
2022-04-24 09:32:06.673786: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: ranking version: 123}
2022-04-24 09:32:06.674731: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.683557: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.683601: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.688665: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 110815 microseconds.
2022-04-24 09:32:06.690019: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/retrieval/exported-retrieval/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.693025: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: retrieval version: 123}
2022-04-24 09:32:06.702594: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.745361: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.772363: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 97633 microseconds.
2022-04-24 09:32:06.774853: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ranking/exported-ranking/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.777706: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: ranking version: 123}
2022-04-24 09:32:06.778969: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-04-24 09:32:06.779030: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-04-24 09:32:06.784217: 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-04-24 09:32:06.785748: 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 ...
Crea un extremo nuevo
Dado que TensorFlow Serving no admite la "encadenación" de varios modelos secuenciales, debes crear un servicio nuevo que conecte los modelos de recuperación y clasificación.
- Agrega este código a la función
get_recommendations()en el archivostep2/backend/recommendations.py:
user_id = request.get_json()["user_id"]
retrieval_request = json.dumps({"instances": [user_id]})
retrieval_response = requests.post(RETRIEVAL_URL, data=retrieval_request)
movie_candidates = retrieval_response.json()["predictions"][0]["output_2"]
ranking_queries = [
{"user_id": u, "movie_title": m}
for (u, m) in zip([user_id] * NUM_OF_CANDIDATES, movie_candidates)
]
ranking_request = json.dumps({"instances": ranking_queries})
ranking_response = requests.post(RANKING_URL, data=ranking_request)
movies_scores = list(np.squeeze(ranking_response.json()["predictions"]))
ranked_movies = [
m[1] for m in sorted(list(zip(movies_scores, movie_candidates)), reverse=True)
]
return make_response(jsonify({"movies": ranked_movies}), 200)
Inicia el servicio de Flask
Ahora puedes iniciar el servicio de Flask.
- En tu terminal, ve a la carpeta
step2/backend/y ejecuta el siguiente comando:
FLASK_APP=recommender.py FLASK_ENV=development flask run
Flask creará un nuevo extremo en http://localhost:5000/recommend. Deberías ver el registro como se muestra a continuación:
* Serving Flask app 'recommender.py' (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 705-382-264 127.0.0.1 - - [25/Apr/2022 19:44:47] "POST /recommend HTTP/1.1" 200 -
Puedes enviar una solicitud de muestra al extremo para asegurarte de que funcione según lo previsto:
curl -X POST -H "Content-Type: application/json" -d '{"user_id":"42"}' http://localhost:5000/recommend
El extremo devolverá una lista de películas recomendadas para el usuario 42:
{
"movies": [
"While You Were Sleeping (1995)",
"Preacher's Wife, The (1996)",
"Michael (1996)",
"Lion King, The (1994)",
"Father of the Bride Part II (1995)",
"Sleepless in Seattle (1993)",
"101 Dalmatians (1996)",
"Bridges of Madison County, The (1995)",
"Rudy (1993)",
"Jack (1996)"
]
}
Eso es todo. Compilaste correctamente un backend para recomendar películas según un ID de usuario.
8. Paso 3: Crea la app de Flutter para Android y iOS
El backend está listo. Puedes comenzar a enviarle solicitudes para consultar recomendaciones de películas desde la app de Flutter.
La app de frontend es bastante simple. Solo tiene un TextField que toma el ID del usuario y envía la solicitud (en la función recommend()) al backend que acabas de compilar. Después de recibir la respuesta, la IU de la app muestra las películas recomendadas en un ListView.
- Agrega este código a la función
recommend()en el archivostep3/frontend/lib/main.dart:
final response = await http.post(
Uri.parse('http://' + _server + ':5000/recommend'),
headers: <String, String>{
'Content-Type': 'application/json',
},
body: jsonEncode(<String, String>{
'user_id': _userIDController.text,
}),
);
Una vez que la app recibe la respuesta del backend, actualizas la IU para mostrar la lista de películas recomendadas para el usuario especificado.
- Agrega este código justo debajo del código anterior:
if (response.statusCode == 200) {
return List<String>.from(jsonDecode(response.body)['movies']);
} else {
throw Exception('Error response');
}
Ejecución
- Haz clic en
Start debugging y espera a que se cargue la app. - Ingresa un ID de usuario (es decir, 42) y, luego, selecciona Recomendar.

9. Paso 4: Ejecuta la app de Flutter en las plataformas de escritorio
Además de iOS y Android, Flutter también admite plataformas de computadoras, como Linux, macOS y Windows.
Linux
- Asegúrate de que el dispositivo de destino esté configurado como
en la barra de estado de VS Code. - Haz clic en
Start debugging y espera a que se cargue la app. - Ingresa un ID de usuario (es decir, 42) y, luego, selecciona Recomendar.

Mac
- En Mac, debes configurar los derechos adecuados, ya que la app enviará solicitudes HTTP al backend. Para obtener más información, consulta Derechos y zona de pruebas de apps.
Agrega este código a step4/frontend/macOS/Runner/DebugProfile.entitlements y step4/frontend/macOS/Runner/Release.entitlements, respectivamente:
<key>com.apple.security.network.client</key>
<true/>
- Asegúrate de que el dispositivo de destino esté configurado como
en la barra de estado de VS Code. - Haz clic en
Start debugging y espera a que se cargue la app. - Ingresa un ID de usuario (es decir, 42) y, luego, selecciona Recomendar.

Windows
- Asegúrate de que el dispositivo de destino esté configurado como
en la barra de estado de VS Code. - Haz clic en
Start debugging y espera a que se cargue la app. - Ingresa un ID de usuario (es decir, 42) y, luego, selecciona Recomendar.

10. Paso 5: Ejecuta la app de Flutter en la plataforma web
Otra cosa que puedes hacer es agregar compatibilidad web a la app de Flutter. De forma predeterminada, la plataforma web se habilita automáticamente para las apps de Flutter, por lo que solo debes iniciarla.
- Asegúrate de que el dispositivo de destino esté configurado como
en la barra de estado de VS Code. - Haz clic en
Start debugging y espera a que la app se cargue en el navegador Chrome. - Ingresa un ID de usuario (es decir, 42) y, luego, selecciona Recomendar.

11. Felicitaciones
Creaste una app de pila completa para recomendar películas a tus usuarios.
Si bien la app solo recomienda películas, aprendiste el flujo de trabajo general para compilar un potente motor de recomendaciones y dominaste la habilidad de consumir las recomendaciones en una app de Flutter. Puedes aplicar fácilmente lo que aprendiste a otros casos de uso (p.ej., comercio electrónico, comida y videos cortos).