{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction to Translation with Transformers and MLflow\n", "\n", "In this tutorial, we delve into the world of language translation by leveraging the power of [Transformers](https://huggingface.co/docs/transformers) and MLflow. This guide is crafted for practitioners with a grasp of machine learning concepts who seek to streamline their translation model workflows. We will showcase the use of MLflow to log, manage, and serve a cutting-edge translation model - the `google/flan-t5-base` from the [🤗 Hugging Face](https://huggingface.co/) library." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "Download this Notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Learning Objectives\n", "\n", "Throughout this tutorial, you will:\n", "\n", "- Construct a translation **pipeline** using `flan-t5-base` from the Transformers library.\n", "- **Log** the translation model and its configurations using MLflow.\n", "- Determine the input and output **signature** of the translation model automatically.\n", "- **Retrieve** a logged translation model from MLflow for direct interaction.\n", "- Emulate the deployment of the translation model using MLflow's **pyfunc** model flavor for language translation tasks.\n", "\n", "By the conclusion of this tutorial, you'll gain a thorough insight into managing and deploying translation models with MLflow, thereby enhancing your machine learning operations for language processing.\n", "\n", "### Why was this model chosen?\n", "The [flan-t5-base](https://huggingface.co/google/flan-t5-base) offers a few benefits:\n", "\n", "- **Size**: it's a relatively small model for the comparatively powerful performance.\n", "- **Enhanced Language Coverage**: Expanding on the original [T5 model](https://huggingface.co/t5-base), the flan-t5 has a much larger breadth of languages that it supports." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setting Up the Translation Environment\n", "\n", "Begin by setting up the essential components for translation tasks using the google/flan-t5-base model.\n", " \n", "#### Importing Libraries\n", "We import the `transformers` library for access to the translation model and tokenizer. Additionally, `mlflow` is included for model tracking and management, creating a comprehensive environment for our translation tasks.\n", "\n", "#### Initializing the Model\n", "The `google/flan-t5-base` model, known for its translation effectiveness, is loaded from the Hugging Face repository. This pre-trained model is a key component of our setup.\n", "\n", "#### Setting Up the Tokenizer\n", "We initialize the tokenizer corresponding to our model. The tokenizer plays a critical role in processing text input, making it understandable for the model.\n", "\n", "#### Creating the Pipeline\n", "A translation pipeline for English to French is created. This pipeline streamlines the process, allowing us to focus on inputting text and receiving translations without managing model and tokenizer interactions directly." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "env: TOKENIZERS_PARALLELISM=false\n" ] } ], "source": [ "# Disable tokenizers warnings when constructing pipelines\n", "%env TOKENIZERS_PARALLELISM=false\n", "\n", "import warnings\n", "\n", "# Disable a few less-than-useful UserWarnings from setuptools and pydantic\n", "warnings.filterwarnings(\"ignore\", category=UserWarning)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import transformers\n", "\n", "import mlflow\n", "\n", "model_architecture = \"google/flan-t5-base\"\n", "\n", "translation_pipeline = transformers.pipeline(\n", " task=\"translation_en_to_fr\",\n", " model=transformers.T5ForConditionalGeneration.from_pretrained(\n", " model_architecture, max_length=1000\n", " ),\n", " tokenizer=transformers.T5TokenizerFast.from_pretrained(model_architecture, return_tensors=\"pt\"),\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Testing the Translation Pipeline\n", "\n", "We perform a preliminary check on our translation pipeline to ensure its proper functioning before logging it with MLflow.\n", "\n", "#### Model Verification\n", "A test translation allows us to verify that the model accurately translates text, in this case from English to French, ensuring the model's basic functionality.\n", "\n", "#### Error Prevention\n", "Identifying potential issues before model logging helps prevent future errors during deployment or inference, saving time and resources.\n", "\n", "#### Resource Management\n", "Testing minimizes wasteful use of resources, particularly important given the large size of these models and the resources needed to save and load them.\n", "\n", "#### Pipeline Validation\n", "This step confirms that both the model and tokenizer in the pipeline are correctly configured and capable of processing the input as expected." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'translation_text': \"J'ai apprécié mon sajour lente sur les Champs-Élysées.\"}]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Evaluate the pipeline on a sample sentence prior to logging\n", "translation_pipeline(\n", " \"translate English to French: I enjoyed my slow saunter along the Champs-Élysées.\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Evaluating the Translation Results\n", "\n", "Upon running our initial translation through the pipeline, we observed that the output, while generally accurate, exhibited areas for improvement.\n", "\n", "The initial translation output was:\n", "\n", "``` text\n", " `[{'translation_text': \"J'ai apprécié mon sajour lente sur les Champs-Élysées.\"}]`\n", "```\n", "\n", "This translation captures the essence of the original English sentence but shows minor grammatical errors and word choice issues. For instance, a more refined translation might be:\n", "\n", "``` text\n", " `\"J'ai apprécié ma lente promenade le long des Champs-Élysées.\"`\n", "```\n", "\n", "This version corrects grammatical gender and adds necessary articles, accentuation, and hyphenation. These subtle nuances enhance the translation quality significantly.\n", "The base model's performance is encouraging, indicating the potential for more precise translations with further fine-tuning and context. MLflow's tracking and management capabilities will be instrumental in monitoring the iterative improvements of such models.\n", "\n", "In summary, while the pursuit of perfection in machine translation is ongoing, the initial results are a promising step towards achieving natural and accurate translations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setting Model Parameters and Inferring Signature\n", "\n", "We establish crucial model parameters and infer the signature to ensure consistency and reliability in our model's deployment.\n", "\n", "#### Defining Model Parameters\n", "Setting key parameters like `max_length` is vital for controlling model behavior during inference. For example, a `max_length` of 1000 ensures the model handles longer sentences effectively, crucial for maintaining context in translations.\n", "\n", "#### Importance of Inferring Signature\n", "The signature, defining the model's input and output schema, is critical for MLflow's understanding of the expected data structures. By inferring this signature, we document the types and structures of data that the model works with, enhancing its reliability and portability.\n", "\n", "#### Benefits of This Process\n", "\n", "- **Enhanced Portability**: Properly defined parameters and signatures make the model more adaptable to different environments.\n", "- **Error Reduction**: This step minimizes the risk of encountering schema-related errors during deployment.\n", "- **Clear Documentation**: It serves as a clear guide for developers and users, simplifying the model's integration into applications.\n", "\n", "By establishing these parameters and signature, we lay a robust foundation for our model's subsequent tracking, management, and serving via MLflow." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Define the parameters that we are permitting to be used at inference time, along with their default values if not overridden\n", "model_params = {\"max_length\": 1000}\n", "\n", "# Generate the model signature by providing an input, the expected output, and (optionally), parameters available for overriding at inference time\n", "signature = mlflow.models.infer_signature(\n", " \"This is a sample input sentence.\",\n", " mlflow.transformers.generate_signature_output(translation_pipeline, \"This is another sample.\"),\n", " params=model_params,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reviewing the Model Signature\n", "\n", "After configuring the translation model and inferring its signature, it's crucial to review the signature to confirm it matches our model's input and output structures.\n", " \n", "The model signature serves as a blueprint for MLflow to interact with the model, encompassing:\n", "\n", "- **Inputs:** The expected input types, such as a string for the text to be translated.\n", "- **Outputs:** The output data types, which in our case is a string representing the translated text.\n", "- **Parameters:** Additional configurable settings like `max_length`, determining the maximum length of the translation output.\n", "\n", "Reviewing the signature through the `signature` command allows us to validate the data formats and ensure that our model will function as expected when deployed. This step is vital for consistent model performance and avoiding errors in a production environment.\n", "Furthermore, the inclusion of parameters in the signature with default values ensures that any modifications during inference are deliberate and well-documented, contributing to the model's predictability and transparency." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "inputs: \n", " [string]\n", "outputs: \n", " [string]\n", "params: \n", " ['max_length': long (default: 1000)]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Visualize the model signature\n", "signature" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Creating an experiment\n", "\n", "We create a new MLflow Experiment so that the run we're going to log our model to does not log to the default experiment and instead has its own contextually relevant entry." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# If you are running this tutorial in local mode, leave the next line commented out.\n", "# Otherwise, uncomment the following line and set your tracking uri to your local or remote tracking server.\n", "\n", "# mlflow.set_tracking_uri(\"http://127.0.0.1:8080\")\n", "\n", "mlflow.set_experiment(\"Translation\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Logging the Model with MLflow\n", "\n", "We are now set to log our translation model with MLflow, ensuring its trackability and version control.\n", " \n", "#### Starting an MLflow Run\n", "We initiate the logging process by starting an MLflow run. This encapsulates all the model information, including artifacts and parameters, within a unique run ID.\n", "\n", "#### Using `mlflow.transformers.log_model`\n", "This function is integral to logging our model in MLflow. It records various aspects of the model:\n", "\n", "- **Model Pipeline**: The complete translation model pipeline, encompassing the model and tokenizer.\n", "- **Artifact Path**: The directory path in the MLflow run where the model artifacts are stored.\n", "- **Model Signature**: The pre-defined signature indicating the model's expected input-output formats.\n", "- **Model Parameters**: Key parameters of the model, like `max_length`, providing insights into model behavior.\n", "\n", "#### Outcome of Model Logging\n", "Post logging, we obtain the `model_info` object, which encompasses all the essential metadata about the logged model, such as its storage location. This metadata is vital for future deployment and performance analysis." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "with mlflow.start_run():\n", " model_info = mlflow.transformers.log_model(\n", " transformers_model=translation_pipeline,\n", " artifact_path=\"french_translator\",\n", " signature=signature,\n", " model_params=model_params,\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inspecting the Loaded Model Components\n", "\n", "After loading the model from MLflow, we delve into its individual components to verify their setup and functionality.\n", "\n", "#### Component Breakdown\n", "The loaded model comprises several key components, each playing a crucial role in its operation:\n", "\n", "- **Task**: Defines the model's specific use-case, confirming its suitability for the intended task.\n", "- **Device Map**: Details the hardware configuration, important for performance optimization.\n", "- **Model Instance**: The core `T5ForConditionalGeneration` model, central to the translation process.\n", "- **Tokenizer**: The `T5TokenizerFast`, responsible for processing text inputs into a format understandable by the model.\n", "- **Framework**: Indicates the underlying deep learning framework, essential for compatibility considerations.\n", "\n", "#### Ensuring Component Integrity and Functionality\n", "Inspecting these components ensures that:\n", "\n", "- The model aligns with our task requirements.\n", "- Hardware resources are optimally utilized.\n", "- Text inputs are correctly preprocessed for model consumption.\n", "- The model's compatibility with the selected deep learning framework is confirmed.\n", "\n", "This verification step is vital for the successful application of the model in practical scenarios, reinforcing the robustness and flexibility of MLflow." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023/11/30 12:00:44 INFO mlflow.transformers: 'runs:/2357c12ca17a4f328b2f72cbb7d70343/french_translator' resolved as 'file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/translation/mlruns/996217394074032926/2357c12ca17a4f328b2f72cbb7d70343/artifacts/french_translator'\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "27c1be08b2254db391ae15c7150442fe", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Loading checkpoint shards: 0%| | 0/2 [00:00 str\n", "device_map -> str\n", "model -> T5ForConditionalGeneration\n", "tokenizer -> T5TokenizerFast\n", "framework -> str\n" ] } ], "source": [ "# Load our saved model as a dictionary of components, comprising the model itself, the tokenizer, and any other components that were saved\n", "translation_components = mlflow.transformers.load_model(\n", " model_info.model_uri, return_type=\"components\"\n", ")\n", "\n", "# Show the components that made up our pipeline that we saved and what type each are\n", "for key, value in translation_components.items():\n", " print(f\"{key} -> {type(value).__name__}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Understanding Model Flavors in MLflow\n", "\n", "The `model_info.flavors` attribute in MLflow provides insights into the model's capabilities and deployment requirements across various platforms.\n", " \n", "Flavors in MLflow represent different ways the model can be utilized and deployed. Key aspects include:\n", "\n", "- **Python Function Flavor:** Indicates the model's compatibility as a generic Python function, including model binary, loader module, Python version, and environment specifications.\n", "- **Transformers Flavor:** Tailored for models from the Hugging Face Transformers library, covering transformers version, code dependencies, task, instance type, source model name, pipeline model type, framework, tokenizer type, components, and model binary.\n", "\n", "This information guides how to interact with the model within MLflow, ensuring proper deployment with the right environment and dependencies, whether for inference or further model refinement." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'python_function': {'model_binary': 'model',\n", " 'loader_module': 'mlflow.transformers',\n", " 'python_version': '3.8.13',\n", " 'env': {'conda': 'conda.yaml', 'virtualenv': 'python_env.yaml'}},\n", " 'transformers': {'transformers_version': '4.34.1',\n", " 'code': None,\n", " 'task': 'translation_en_to_fr',\n", " 'instance_type': 'TranslationPipeline',\n", " 'source_model_name': 'google/flan-t5-base',\n", " 'pipeline_model_type': 'T5ForConditionalGeneration',\n", " 'framework': 'pt',\n", " 'tokenizer_type': 'T5TokenizerFast',\n", " 'components': ['tokenizer'],\n", " 'model_binary': 'model'}}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Show the model parameters that were saved with our model to gain an understanding of what is recorded when saving a transformers pipeline\n", "model_info.flavors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Evaluating the Translation Output\n", "\n", "After testing our pipeline with a challenging sentence, we assess the translation's accuracy.\n", "\n", "#### Assessing Translation Nuances\n", "The model impressively interprets \"Nice\" correctly as a city name, rather than an adjective. This shows its ability to discern context and proper nouns. Furthermore, it cleverly substitutes the English play on words with the French adjective \"bien,\" maintaining the sentence's intended sentiment.\n", "\n", "#### Contextual Understanding\n", "This translation exemplifies the model's strength in understanding context and language subtleties, which is essential for practical applications where precision and contextual accuracy are key.\n", "\n", "#### The Importance of Rigorous Testing\n", "Testing with linguistically complex sentences is vital. It ensures the model can handle various linguistic challenges, an important aspect of deploying models in real-world scenarios." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023/11/30 12:00:45 INFO mlflow.transformers: 'runs:/2357c12ca17a4f328b2f72cbb7d70343/french_translator' resolved as 'file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/translation/mlruns/996217394074032926/2357c12ca17a4f328b2f72cbb7d70343/artifacts/french_translator'\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "bdefabfef935484da1aed84ac32b2d0c", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Loading checkpoint shards: 0%| | 0/2 [00:00 \", \"\\n\").replace(\"\", \"\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tutorial Recap\n", "\n", "This tutorial provided insights into combining MLflow with advanced language translation models, emphasizing streamlined model management and deployment.\n", "\n", "We explored several key aspects:\n", "\n", " - Setting up and testing a translation pipeline using Transformers.\n", " - Logging the model and its configurations to MLflow for effective versioning and tracking.\n", " - Inferring and examining the model's signature for ensuring input and output consistency.\n", " - Interacting with logged model components for enhanced flexibility in deployment.\n", " - Discussing the nuances of language translation and the role of context in achieving accurate results.\n", "\n", "### The Power of MLflow and Model Metadata\n", "MLflow's integration proved instrumental in managing and deploying the translation model. The tutorial highlighted how MLflow's metadata, including the model's signature and flavors, aids in consistent and reliable deployment, catering to production needs.\n", "\n", "### Reflection on the Translation Output\n", "The final translation output, while not exact, captured the essence of the iconic French motto, highlighting the model's effectiveness and the importance of contextual understanding in translations. Further exploration on the cultural significance of the phrase can be found on its [Wikipedia Page](https://en.wikipedia.org/wiki/Libert%C3%A9,_%C3%A9galit%C3%A9,_fraternit%C3%A9).\n", "\n", "### Conclusion\n", "The combination of MLflow and advanced language models like Transformers offers a powerful approach to deploying sophisticated AI solutions. This tutorial aimed to empower your journey in machine learning, whether in translation tasks or other ML applications.\n", " \n" ] } ], "metadata": { "kernelspec": { "display_name": "mlflow-dev-env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" } }, "nbformat": 4, "nbformat_minor": 2 }