From 891f79ef8c78e112b087f0284e397de18fe3494f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:23:40 +0000 Subject: [PATCH 1/8] Initial plan From 27165cf4d0d4b8e9466d776b57ce4e1a9c537682 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:25:31 +0000 Subject: [PATCH 2/8] Update devcontainer for Codespaces Docker workflow --- .devcontainer/devcontainer.json | 6 ++++-- README.md | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 14a6eb7..0c88853 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ { "name": "MLE Interview", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/python:1-3.10", + "image": "mcr.microsoft.com/devcontainers/python:1-3.10-bookworm", "customizations": { "vscode": { "settings": { @@ -18,9 +18,11 @@ }, "extensions": [ "charliermarsh.ruff", + "github.codespaces", "ms-azuretools.vscode-docker", "ms-python.black-formatter", "ms-python.python", + "ms-vscode-remote.remote-containers", "ms-toolsai.jupyter", "redhat.vscode-yaml", "vscode-icons-team.vscode-icons", @@ -29,7 +31,7 @@ } }, "features": { - "ghcr.io/devcontainers/features/docker-in-docker": {} + "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, "postCreateCommand": "make setup" } \ No newline at end of file diff --git a/README.md b/README.md index 5306772..c8dd6b1 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,13 @@ ## Setup 1. Install [Visual Studio Code](https://code.visualstudio.com/). Also the following plugins: - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + - [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) 2. Clone this repo 3. Open the repository in VSCode (`code .`) 4. VSCode will prompt you to install recommended extensions. Select `Yes` - If you missed this step, you can install recommended extensions using the extensions sidebar (`⇧⌘X`) 5. VSCode will prompt you to reopen the workspace in a Dev Container. Select `Yes`. - - If you missed this step, open the command prompt palette (`⇧⌘P`) and run the command `Remote-Containers: Rebuild and Reopen in Container` + - If you missed this step, open the command prompt palette (`⇧⌘P`) and run the command `Dev Containers: Rebuild and Reopen in Container` ## Make Commands @@ -20,7 +21,7 @@ Before you start, ensure you have all the necessary dependencies installed: make setup ``` -This command will install the Python dependencies listed in `requirements.txt`. +This command will install the Python dependencies listed in `requirements.txt`. The project is configured to run in the Dev Container's Python 3.10 environment for TensorFlow compatibility. ### Serve API From 29d62b8b856076cac8f39c82b073c02cf5d8c614 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:26:12 +0000 Subject: [PATCH 3/8] Refine devcontainer setup docs --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c8dd6b1..48e8673 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Setup 1. Install [Visual Studio Code](https://code.visualstudio.com/). Also the following plugins: - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - - [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) + - (Optional for local development) [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) 2. Clone this repo 3. Open the repository in VSCode (`code .`) 4. VSCode will prompt you to install recommended extensions. Select `Yes` @@ -21,7 +21,8 @@ Before you start, ensure you have all the necessary dependencies installed: make setup ``` -This command will install the Python dependencies listed in `requirements.txt`. The project is configured to run in the Dev Container's Python 3.10 environment for TensorFlow compatibility. +This command will install the Python dependencies listed in `requirements.txt`. +The project is configured to run in the Dev Container's Python 3.10 environment for TensorFlow compatibility. ### Serve API From 9e9a7c347e0955861073b9eebc04eb22d34dac35 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:26:43 +0000 Subject: [PATCH 4/8] Remove host-only extensions from container config --- .devcontainer/devcontainer.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0c88853..c337483 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -18,11 +18,9 @@ }, "extensions": [ "charliermarsh.ruff", - "github.codespaces", "ms-azuretools.vscode-docker", "ms-python.black-formatter", "ms-python.python", - "ms-vscode-remote.remote-containers", "ms-toolsai.jupyter", "redhat.vscode-yaml", "vscode-icons-team.vscode-icons", From d5e69f934047f948a439b5f0b16d6e9354bab2ec Mon Sep 17 00:00:00 2001 From: Edgar Pino Date: Wed, 3 Jun 2026 21:20:12 -0500 Subject: [PATCH 5/8] Update devcontainer configuration for Python 3.12 and Docker-in-Docker feature --- .devcontainer/devcontainer-lock.json | 9 +++++++++ .devcontainer/devcontainer.json | 6 ++++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .devcontainer/devcontainer-lock.json diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 0000000..fbc79c1 --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:3": { + "version": "3.0.1", + "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:ca2508495b01ba29eba93e8153772a2daa65eaa86471cc6863fe2a3d21933df9", + "integrity": "sha256:ca2508495b01ba29eba93e8153772a2daa65eaa86471cc6863fe2a3d21933df9" + } + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c337483..ed24b11 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ { "name": "MLE Interview", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/python:1-3.10-bookworm", + "image": "mcr.microsoft.com/devcontainers/python:3.12", "customizations": { "vscode": { "settings": { @@ -29,7 +29,9 @@ } }, "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": {} + "ghcr.io/devcontainers/features/docker-in-docker:3": { + "moby": false + } }, "postCreateCommand": "make setup" } \ No newline at end of file From 11edee435e1c0c1e3cd0f5373fa58b0260cd9cbf Mon Sep 17 00:00:00 2001 From: Edgar Pino Date: Wed, 3 Jun 2026 22:06:56 -0500 Subject: [PATCH 6/8] Add Dockerfile and update devcontainer configuration for Zscaler integration --- .devcontainer/Dockerfile | 9 +++++++++ .devcontainer/devcontainer.json | 11 ++++++----- .gitignore | 3 +++ INTERVIEW.md | 3 +-- 4 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..fe5f950 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,9 @@ +FROM mcr.microsoft.com/devcontainers/python:3.10 + +COPY zscaler-bundle.pem /tmp/zscaler.pem +RUN if [ -s /tmp/zscaler.pem ]; then \ + cp /tmp/zscaler.pem /usr/local/share/ca-certificates/zscaler.crt && \ + update-ca-certificates; \ + fi && rm -f /tmp/zscaler.pem + +RUN find /etc/apt /usr/share/keyrings -name "*yarn*" -delete 2>/dev/null || true diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ed24b11..4de17f2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ { "name": "MLE Interview", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/python:3.12", + "build": { "dockerfile": "Dockerfile" }, + "initializeCommand": "cp ~/.ssl/zscaler-bundle.pem .devcontainer/zscaler-bundle.pem 2>/dev/null || touch .devcontainer/zscaler-bundle.pem", "customizations": { "vscode": { "settings": { @@ -14,7 +14,7 @@ "source.organizeImports.ruff": true, "source.organizeImports": true } - }, + } }, "extensions": [ "charliermarsh.ruff", @@ -30,8 +30,9 @@ }, "features": { "ghcr.io/devcontainers/features/docker-in-docker:3": { - "moby": false + "moby": false, + "disableIp6tables": true } }, "postCreateCommand": "make setup" -} \ No newline at end of file +} diff --git a/.gitignore b/.gitignore index 3f83ee9..8d5a0af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Zscaler cert (machine-specific, copied by initializeCommand) +.devcontainer/zscaler-bundle.pem + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/INTERVIEW.md b/INTERVIEW.md index 534694b..46e3333 100644 --- a/INTERVIEW.md +++ b/INTERVIEW.md @@ -1,8 +1,7 @@ ## Coding Challenge -You can refer to Google or relevant documentation to guide you in addressing the issues below. -You are not allowed to use ChatGPT, Copilot, or any similar tools for assistance. +You can refer to Google or relevant documentation to guide you in addressing the issues below. 1. **Model Training Error Resolution:** - Begin by executing `make test` to identify any issues during model training. From 91f3646457ffeb7d8d1486c8e5138edae44ac80a Mon Sep 17 00:00:00 2001 From: Edgar Pino Date: Wed, 3 Jun 2026 22:16:00 -0500 Subject: [PATCH 7/8] Enhance interview documentation and Makefile with detailed task instructions and API features --- INTERVIEW.md | 119 +++++++++++++++++++++++++++++++++++++++++++-------- Makefile | 3 ++ README.md | 118 +++++++++++++++++++------------------------------- 3 files changed, 147 insertions(+), 93 deletions(-) diff --git a/INTERVIEW.md b/INTERVIEW.md index 46e3333..39bca5b 100644 --- a/INTERVIEW.md +++ b/INTERVIEW.md @@ -1,27 +1,108 @@ - ## Coding Challenge -You can refer to Google or relevant documentation to guide you in addressing the issues below. +You are working on a user interest recommendation system. It consists of: + +- A **TensorFlow model** trained on user content interactions, served via TF Serving (Docker) +- A **Flask API** that fetches user features, calls the model, and returns ranked interests +- A **feature store** backed by CSV files + +There are **6 tasks** to complete. Tasks 1–5 each have a failing test that tells you exactly what to fix. Task 6 is an open-ended feature implementation. You can refer to Google or relevant documentation — no AI-assisted coding tools. + +--- + +### Terminal setup (do this before task 3) + +Once the model is trained and served, you'll need **two terminals** running simultaneously inside the container: + +| Terminal | Command | Purpose | +|---|---|---| +| 1 | `make serve-model` | TF Serving on port 8501 | +| 2 | `make serve-api` | Flask API on port 5005 | + +Keep both running while working on tasks 3–6. + +--- + +### Tasks + +**1. Fix model training** + +Run `make test`. The `TestModel::test_model_build` test fails. + +Find and fix the bug in the model code, then verify: +``` +make test # TestModel::test_model_build must pass +``` + +Once passing, train the model and start the model server (leave it running): +``` +make train +make serve-model +``` + +--- + +**2. Fix the API startup** + +Run `make serve-api`. The Flask application fails to start. + +Find and fix the bug, then verify the server starts without errors: +``` +make serve-api +``` + +Leave the server running in its terminal. + +--- + +**3. Fix the interests count** + +With both servers running, run `make test`. This test fails: +``` +TestInterestsAPI::test_basic_response — AssertionError: Incorrect number of interests +``` + +Fix the API so it returns the correct number of interests. Verify: +``` +make test # test_basic_response must pass (interests count assertion) +``` + +--- + +**4. Fix response time** + +With both servers running, run `make test`. This test fails: +``` +TestInterestsAPI::test_basic_response — AssertionError: Request greater than 1 second +``` + +Find the performance bottleneck and fix it. Verify: +``` +make test # test_basic_response must pass (timing assertion) +``` + +--- + +**5. Add probability to the response** + +With both servers running, run `make test`. This test fails: +``` +TestInterestsAPI::test_with_probability_threshold +``` -1. **Model Training Error Resolution:** - - Begin by executing `make test` to identify any issues during model training. - - After passing the `TestModel::test_model_build` test, use `make train` followed by `make serve-model` to train and serve the model, preparing it for upcoming steps. +Update the API response so each interest includes a `probability` field. Verify: +``` +make test # test_with_probability_threshold must pass +``` -2. **API Startup Issue Fix:** - - Resolve the Flask API startup issue with `make serve-api`. - - Run `make serve-api` to start a development Flask server, then open a new terminal window without shutting down the server. +--- -3. **Data Return and Interests Length Correction:** - - Execute `make test` and resolve the `TestInterestsAPI::test_basic_response - AssertionError: Incorrect number of interests` test. - - Ensure the return data structure and interests array length meet the specifications, adjusting the API as necessary. +**6. Add probability threshold filtering** -4. **Response Time Optimization:** - - Run `make test` and fix the `TestInterestsAPI::test_basic_response - AssertionError: Request greater than 1 second` test. - - Enhance the API to achieve a response time of one second or less. +Implement a feature that lets API clients filter results by a minimum probability score. For example: -5. **Probability Field Inclusion:** - - Perform `make test` and correct the `TestInterestsAPI::test_with_probability` test. - - Update the API response to incorporate a 'probability' field. +``` +GET /interests/?min_probability=0.5 +``` -6. **Probability Score Filtering Implementation:** - - Create a feature allowing API clients to filter results by probability score, enabling users to specify a probability threshold for more targeted results. \ No newline at end of file +Should return only interests with probability ≥ 0.5. There is no automated test for this task — demonstrate it works with a curl request. diff --git a/Makefile b/Makefile index 80daa2d..9468596 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ serve-api: serve-model: docker compose up tf-serving +ping-model: + curl -s http://localhost:8501/v1/models/interests-model | python3 -m json.tool + train: TF_CPP_MIN_LOG_LEVEL=3 python -m model.main diff --git a/README.md b/README.md index 48e8673..c709418 100644 --- a/README.md +++ b/README.md @@ -1,122 +1,92 @@ -# MLE Interview: - +# MLE Interview ## Setup -1. Install [Visual Studio Code](https://code.visualstudio.com/). Also the following plugins: - - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - - (Optional for local development) [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) -2. Clone this repo -3. Open the repository in VSCode (`code .`) -4. VSCode will prompt you to install recommended extensions. Select `Yes` - - If you missed this step, you can install recommended extensions using the extensions sidebar (`⇧⌘X`) -5. VSCode will prompt you to reopen the workspace in a Dev Container. Select `Yes`. - - If you missed this step, open the command prompt palette (`⇧⌘P`) and run the command `Dev Containers: Rebuild and Reopen in Container` + +### Option A — GitHub Codespaces (recommended) + +Click **Code → Open with Codespaces** on the repository page. The environment builds automatically — no local installation needed. + +### Option B — Local Dev Container (VS Code) + +1. Install [Visual Studio Code](https://code.visualstudio.com/) and the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension +2. Install [Docker Desktop](https://www.docker.com/products/docker-desktop/) +3. Clone this repo and open it in VS Code (`code .`) +4. VS Code will prompt you to reopen in a Dev Container — select **Yes** + - If you miss the prompt: `⇧⌘P` → **Dev Containers: Rebuild and Reopen in Container** + +> **Note (corporate networks / Zscaler):** If your machine uses Zscaler SSL inspection, ensure your Zscaler certificate bundle exists at `~/.ssl/zscaler-bundle.pem` before building the container. The build handles this automatically. + +Once the container starts, dependencies are installed automatically via `make setup`. You do not need to run it manually. ## Make Commands -Before you start, ensure you have all the necessary dependencies installed: +### Test ``` -make setup +make test ``` -This command will install the Python dependencies listed in `requirements.txt`. -The project is configured to run in the Dev Container's Python 3.10 environment for TensorFlow compatibility. +Runs all tests in `./tests` with pytest. Use this to verify each task as you work through the interview. -### Serve API - -To start the Flask API, use the following command: +### Train ``` -make serve-api +make train ``` -This command launches the Flask application defined in `api/app` on port 5005, accessible via `0.0.0.0`. The `--debug` flag is included to enable debug mode, which provides useful debugging information in case of errors and automatically reloads the server on code changes. +Trains the model using `model/main.py` and exports a SavedModel to `serving/interests-model/1/`. ### Serve Model -If you're using a TensorFlow model served via Docker, you can start the TensorFlow serving using: - ``` make serve-model ``` -This command uses Docker Compose to spin up a container defined in the Docker configuration, specifically targeting the TensorFlow serving service (`tf-serving`). Ensure Docker is installed and running on your system before executing this command. +Starts TF Serving via Docker Compose on port 8501. Run this after `make train` — the model must be trained first. -### Train - -To train the model, execute: +### Serve API ``` -make train +make serve-api ``` -This command runs the main training script located at `model.main`. +Starts the Flask development server on port 5005. Requires the model server to be running for inference endpoints to work. -### Test -Finally, to run the tests for your project, use: +## API ``` -make test +GET http://localhost:5005/interests/ ``` -This command runs all the tests in the `./tests` directory using pytest. +Optional query parameters: +- `top_k` (int) — number of interests to return (default: 10) +- `min_probability` (float) — filter results below this probability score +Example response: -## API - -Route: GET: http://localhost:5005/interests/:userHandle - -API Response: - -``` +```json { "user_handle": "e337a675-46f5-437e-aa72-5d43643b5461", + "name": "Kisiza", + "type": "B2B", "interests": [ { "id": "29e020bb-7a02-41db-b21f-527a8ef4dfdf", - "label": "Accounting technician" + "label": "Accounting technician", + "probability": 0.94 }, { "id": "012abcd1-3a6a-4803-a47e-42f46b402024", - "label": "Field seismologist" + "label": "Field seismologist", + "probability": 0.87 }, { "id": "a1b028dd-8464-4c63-85e8-ae29ea184fc7", - "label": "Designer, industrial/product" - }, - { - "id": "686af7e4-6d58-4148-b227-3bf65ff10273", - "label": "Materials engineer" - }, - { - "id": "8d1526b9-a7bf-4972-be43-7b912f149667", - "label": "Fashion designer" - }, - { - "id": "d83a55a3-0143-4318-91c1-88f44ad59390", - "label": "Journalist, newspaper" - }, - { - "id": "cda4441f-dba6-495c-9e2e-7429bd5e0465", - "label": "Therapist, music" - }, - { - "id": "e9b23ad4-753b-4331-9cfa-525965fcf281", - "label": "Secretary, company" - }, - { - "id": "ca4b03b2-0ae2-440a-afc8-5469510b19cb", - "label": "Commissioning editor" - }, - { - "id": "fd3c41b8-8c15-47e2-a80d-cf3683b2d0da", - "label": "Copywriter, advertising" + "label": "Designer, industrial/product", + "probability": 0.81 } - ], - "name": "Kisiza", - "type": "B2B" + ] } -``` \ No newline at end of file +``` From c7e9f85bbef0d522c65ef3c56b99428ac03fc088 Mon Sep 17 00:00:00 2001 From: Edgar Pino Date: Thu, 4 Jun 2026 03:48:57 +0000 Subject: [PATCH 8/8] Update interview tasks and add probability score validation in tests --- INTERVIEW.md | 27 ++++++++++++++++++++------- tests/test_model.py | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/INTERVIEW.md b/INTERVIEW.md index 39bca5b..93360e8 100644 --- a/INTERVIEW.md +++ b/INTERVIEW.md @@ -6,11 +6,11 @@ You are working on a user interest recommendation system. It consists of: - A **Flask API** that fetches user features, calls the model, and returns ranked interests - A **feature store** backed by CSV files -There are **6 tasks** to complete. Tasks 1–5 each have a failing test that tells you exactly what to fix. Task 6 is an open-ended feature implementation. You can refer to Google or relevant documentation — no AI-assisted coding tools. +There are **7 tasks** to complete. Tasks 1–6 each have a failing test or a clear broken behaviour that tells you what to fix. Task 7 is an open-ended feature implementation. You can refer to Google or relevant documentation — no AI-assisted coding tools. --- -### Terminal setup (do this before task 3) +### Terminal setup (do this before task 4) Once the model is trained and served, you'll need **two terminals** running simultaneously inside the container: @@ -19,7 +19,7 @@ Once the model is trained and served, you'll need **two terminals** running simu | 1 | `make serve-model` | TF Serving on port 8501 | | 2 | `make serve-api` | Flask API on port 5005 | -Keep both running while working on tasks 3–6. +Keep both running while working on tasks 4–7. --- @@ -55,7 +55,20 @@ Leave the server running in its terminal. --- -**3. Fix the interests count** +**3. Fix the probability scores** + +The model's serving function returns raw logit scores, not probabilities. These values are not bounded between 0 and 1 and cannot be meaningfully compared or filtered. + +Find where the issue originates and fix it so that the scores returned represent proper probability values. There are two valid approaches — both are acceptable. + +Verify: +``` +make test # TestModel::test_probability_scores must pass +``` + +--- + +**4. Fix the interests count** With both servers running, run `make test`. This test fails: ``` @@ -69,7 +82,7 @@ make test # test_basic_response must pass (interests count assertion) --- -**4. Fix response time** +**5. Fix response time** With both servers running, run `make test`. This test fails: ``` @@ -83,7 +96,7 @@ make test # test_basic_response must pass (timing assertion) --- -**5. Add probability to the response** +**6. Add probability to the response** With both servers running, run `make test`. This test fails: ``` @@ -97,7 +110,7 @@ make test # test_with_probability_threshold must pass --- -**6. Add probability threshold filtering** +**7. Add probability threshold filtering** Implement a feature that lets API clients filter results by a minimum probability score. For example: diff --git a/tests/test_model.py b/tests/test_model.py index 5469061..541552c 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -32,6 +32,21 @@ def setup_method(self): hyper_params=hyper_params, ) + def test_probability_scores(self): + input_record = { + "USER_HANDLE": tf.constant([self.users[0]]), + "USER_TYPE": tf.constant(["B2B"]), + "CONTENT_TITLES_JOINED": tf.constant([self.content_titles[0]]), + } + top_k = tf.constant(1, dtype=tf.int64) + + result = self.model.serving_predict(input_record, top_k) + probabilities = result["probabilities"].numpy().flatten() + + assert all(0 <= p <= 1 for p in probabilities), ( + "Probabilities must be between 0 and 1" + ) + def test_model_build(self): interests_input = [self.interests_vocab[0], self.interests_vocab[3]]