Skip to main content

migrate-from-model-serving

Migrate an MLflow ResponsesAgent from Databricks Model Serving to Databricks Apps. Use when: (1) User wants to migrate from Model Serving to Apps, (2) User has a ResponsesAgent with predict()/predict_stream() methods, (3) User wants to convert to @invoke/@stream decorators.

Aller à l'installation

Informations de source

Dépôt
databricks-solutions/lakebase-for-ai-developers
Dernière activité de la source
30 juillet 2026 à 18:26
Langue détectée de SKILL.md
anglais
Étoiles
0
Forks
2

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
migrate-from-model-serving
description
Migrate an MLflow ResponsesAgent from Databricks Model Serving to Databricks Apps. Use when: (1) User wants to migrate from Model Serving to Apps, (2) User has a ResponsesAgent with predict()/predict_stream() methods, (3) User wants to convert to @invoke/@stream decorators.
# Model Serving to Databricks Apps Migration Guide This guide instructs LLM coding agents how to migrate an MLflow ResponsesAgent from Databricks Model Serving to Databricks Apps. --- ## Overview **Goal:** Migrate an agent deployed on Databricks Model Serving (using `ResponsesAgent` with `predict()`/`predict_stream()`) to Databricks Apps (using MLflow GenAI Server with `@invoke`/`@stream` decorators). **Key Transformation:** - Model Serving: Synchronous `predict()` and `predict_stream()` methods on a class - Apps: Functions with `@invoke` and `@stream` decorators (sync or async, based on user preference) **Deliverables:** After migration is complete, you will have: ``` <working-directory>/ ├── original_mlflow_model/ # Downloaded artifacts from Model Serving │ ├── MLmodel │ ├── code/ │ │ └── agent.py │ ├── input_example.json │ └── requirements.txt │ └── <app-name>/ # New Databricks App (ready to deploy) ├── agent_server/ │ ├── agent.py # Migrated agent code │ └── ... ├── databricks.yml # Bundle config with resources ├── pyproject.toml ├── uv.lock └── ... ``` > **`<app-name>`** is the name the user provides at the start of the migration. It is used as both the directory name and the Databricks App name at deploy time. --- ## Before You Begin: Gather User Inputs **Before doing anything else, ask the user three questions.** Use structured user input when available to collect all answers at once; otherwise ask directly, then execute the rest of the migration autonomously. **Questions to ask:** 1. **Databricks profile:** Which Databricks CLI profile should be used for the workspace where the Model Serving endpoint lives? (Run `databricks auth profiles` first to list available profiles and their workspaces, then present the options to the user.) 2. **App name:** What should the new Databricks App be named? (Must be lowercase, can contain letters, numbers, and hyphens, and must be unique within the workspace.) 3. **Async migration:** Would you like to migrate your agent code to be fully async? - **Yes (Recommended):** Converts all I/O operations to async (`await`/`async for`), enabling higher concurrency on smaller compute — no more threads sitting idle while waiting for LLM responses or long-running tool calls. - **No:** Keeps your existing synchronous code with minimal changes — just extracts the logic from the `ResponsesAgent` class and wraps it with `@invoke`/`@stream` decorators. Simpler migration, but each request blocks a thread while waiting for I/O. Store the answers as: - `<profile>` — used for ALL `databricks` CLI commands throughout the migration (via `--profile <profile>`) - `<app-name>` — used as both the directory name for the migrated app AND the app name when deploying with `databricks bundle deploy` - `<async>` — `yes` or `no`, determines whether to convert the agent code to async or keep it synchronous ### Validate Authentication After receiving the user's answers, validate the selected profile: ```bash databricks current-user me --profile <profile> ``` If this fails with an authentication error, prompt the user to re-authenticate: ```bash databricks auth login --profile <profile> ``` > **Important:** Remember to include `--profile <profile>` on every `databricks` CLI command throughout the migration. ### Create the App Directory Copy all scaffold files from the current working directory into a new directory named `<app-name>/`. Exclude instruction files (`AGENTS.md`, `CLAUDE.md`), hidden directories (`.agents/`, `.claude/`, `.git/`), and any migration artifacts (e.g., `original_mlflow_model/`, `.migration-venv/`). Do NOT search for or copy scaffold files from other directories or templates — everything you need is right here. All subsequent migration steps operate inside the `<app-name>/` directory. > **Note:** The `agent_server/agent.py` scaffold is intentionally framework-agnostic — it contains the `@invoke`/`@stream` decorator pattern with TODO placeholders. Step 3 (Migrate the Agent Code) will replace these placeholders with the actual agent logic from the original Model Serving endpoint. ### Create Task List **Create a task list to track progress.** This helps the user follow along and see what's completed, in progress, and pending. > **User tip:** Press `Ctrl+T` to toggle the task list view in your terminal. The display shows up to 10 tasks at a time with status indicators. Create the following tasks using the `TaskCreate` tool: | Task | Description | |------|-------------| | **Authenticate to Databricks** | Verify Databricks CLI authentication and validate the selected profile | | **Download original agent artifacts** | Download the MLflow model artifacts from Model Serving endpoint | | **Analyze and understand agent code** | Examine the original agent code, identify tools, resources, and dependencies | | **Migrate agent code to Apps format** | Transform ResponsesAgent class to @invoke/@stream decorated functions | | **Set up and configure the app** | Install dependencies, run quickstart, configure environment | | **Test agent locally** | Start local server and verify the agent works correctly | | **Deploy to Databricks Apps** | Configure databricks.yml resources and deploy with Databricks Asset Bundles | | **Test deployed app** | Verify the deployed app responds correctly | Update task status as you progress: - Mark tasks as `in_progress` when starting each step - Mark tasks as `completed` when finished - This gives the user visibility into migration progress --- ## Step 1: Download the Original Agent Code > **Task:** Mark "Authenticate to Databricks" as `completed`. Mark "Download original agent artifacts" as `in_progress`. > > **Note:** The `<profile>` and `<app-name>` values were collected from the user in the "Before You Begin" section. Use them throughout. Download the original agent code from the Model Serving endpoint. This requires setting up a virtual environment with MLflow to access the model artifacts. ### 1.1 Get Model Info from Endpoint If you have a serving endpoint name, extract the model details: ```bash # Get endpoint info (remember to include --profile if using non-default) databricks serving-endpoints get <endpoint-name> --profile <profile> --output json ``` Look for `served_entities[0].entity_name` (model name) and `entity_version` in the response. Find the entity with 100% traffic in `traffic_config.routes`. ### 1.2 Download Model Artifacts Use `uv run --with` to download artifacts without creating a separate virtual environment. The `mlflow[databricks]` extra includes `boto3` for Unity Catalog artifact access: ```bash DATABRICKS_CONFIG_PROFILE=<profile> uv run --no-project \ --with "mlflow[databricks]>=2.15.0" \ --with "databricks-sdk>=0.30.0" \ python3 << 'EOF' import mlflow mlflow.set_tracking_uri("databricks") # Replace with actual values from step 1.1 MODEL_NAME = "<model-name>" VERSION = "<version>" print(f"Downloading model: models:/{MODEL_NAME}/{VERSION}") mlflow.artifacts.download_artifacts( artifact_uri=f"models:/{MODEL_NAME}/{VERSION}", dst_path="./original_mlflow_model" ) print("Download complete! Artifacts saved to ./original_mlflow_model") EOF ``` ### 1.3 Verify Downloaded Artifacts Check that the key files exist and understand the full structure: ```bash # List all downloaded files recursively find ./original_mlflow_model -type f | head -50 # Check for MLmodel file (contains resource requirements) cat ./original_mlflow_model/MLmodel # Check for input example (useful for testing) cat ./original_mlflow_model/input_example.json 2>/dev/null ``` **Examine the `/code` folder** - contains all code dependencies logged via `code_paths=["..."]`: ```bash # List all code files ls -la ./original_mlflow_model/code/ # The main agent is typically agent.py, but there may be additional modules find ./original_mlflow_model/code -name "*.py" -type f ``` **Examine the `/artifacts` folder** (if present) - contains artifacts logged via `artifacts={...}`: ```bash # Check for artifacts folder ls -la ./original_mlflow_model/artifacts/ 2>/dev/null # List all artifacts find ./original_mlflow_model/artifacts -type f 2>/dev/null ``` > **Important:** Take note of ALL files in `/code` and `/artifacts`. You will need to copy these to the migrated app and ensure imports still work correctly. ### Expected Output Structure After successful download, you should have: ``` ./original_mlflow_model/ ├── MLmodel # Model metadata and resource requirements ├── code/ # Code logged via code_paths=["..."] │ ├── agent.py # Main agent implementation │ ├── utils.py # (optional) Helper modules │ ├── tools.py # (optional) Custom tool definitions │ └── ... # Any other code dependencies ├── artifacts/ # (optional) Artifacts logged via artifacts={...} │ ├── config.yaml # (optional) Configuration files │ ├── prompts/ # (optional) Prompt templates │ └── ... # Any other artifacts (data files, etc.) ├── input_example.json # Sample request for testing ├── requirements.txt # Original dependencies └── ... ``` ### Key Files to Examine 1. **`code/agent.py`** - Contains the `ResponsesAgent` class with `predict()` and `predict_stream()` methods 2. **`code/*.py`** - Any additional Python modules the agent imports 3. **`MLmodel`** - Contains the `resources` section listing required Databricks resources 4. **`artifacts/`** - Any configuration files, prompts, or data files the agent uses 5. **`input_example.json`** - Use this to test the migrated agent ### Troubleshooting Model Download **"Unable to import necessary dependencies to access model version files in Unity Catalog"** This means `boto3` is missing. Ensure you're using `mlflow[databricks]` (not just `mlflow`) in the `--with` flag — the `[databricks]` extra includes `boto3`. **"INVALID_PARAMETER_VALUE" or authentication errors** Re-authenticate with Databricks (include profile if non-default): ```bash databricks auth login --profile <profile> ``` **Wrong workspace / Model not found** Make sure you're using the correct profile that corresponds to the workspace where the model is deployed: ```bash # List profiles to see which workspace each points to databricks auth profiles # Verify you can access the workspace databricks current-user me --profile <profile> # List models in that workspace databricks registered-models list --profile <profile> databricks model-versions list --name "<model-name>" --profile <profile> ``` --- ## Step 2: Understand the Key Transformations > **Task:** Mark "Download original agent artifacts" as `completed`. Mark "Analyze and understand agent code" as `in_progress`. ### Entry Point Transformation In both cases, the `ResponsesAgent` class is replaced with decorated functions. The difference is whether those functions are async or sync. **Model Serving (OLD):** ```python from mlflow.pyfunc import ResponsesAgent, ResponsesAgentRequest, ResponsesAgentResponse class MyAgent(ResponsesAgent): def predict(self, request: ResponsesAgentRequest, params=None) -> ResponsesAgentResponse: # Synchronous implementation ... return ResponsesAgentResponse(output=outputs) def predict_stream(self, request: ResponsesAgentRequest, params=None): # Synchronous generator for chunk in ...: yield ResponsesAgentStreamEvent(...) ``` **Apps — Async (if `<async>` = yes):** ```python from mlflow.genai.agent_server import invoke, stream from mlflow.types.responses import ( ResponsesAgentRequest, ResponsesAgentResponse, ResponsesAgentStreamEvent, ) @invoke() async def non_streaming(request: ResponsesAgentRequest) -> ResponsesAgentResponse: # Async implementation - typically calls streaming() and collects results outputs = [ event.item async for event in streaming(request) if event.type == "response.output_item.done" ] return ResponsesAgentResponse(output=outputs) @stream() async def streaming(request: ResponsesAgentRequest) -> AsyncGenerator[ResponsesAgentStreamEvent, None]: # Async generator async for event in ...: yield event ``` **Apps — Sync (if `<async>` = no):** ```python from mlflow.genai.agent_server import invoke, stream from mlflow.types.responses import ( ResponsesAgentRequest, ResponsesAgentResponse, ResponsesAgentStreamEvent, ) @invoke() def non_streaming(request: ResponsesAgentRequest) -> ResponsesAgentResponse: # Same sync logic from original predict(), extracted from the class ... return ResponsesAgentResponse(output=outputs) @stream() def streaming(request: ResponsesAgentRequest): # Same sync generator from original predict_stream(), extracted from the class for chunk in ...: yield ResponsesAgentStreamEvent(...) ``` ### Key Differences | Aspect | Model Serving | Apps (async) | Apps (sync) | |--------|--------------|------|------| | Structure | `class MyAgent(ResponsesAgent)` | Decorated functions | Decorated functions | | Functions | `def predict()` / `def predict_stream()` | `async def` with `await` | `def` (same as original) | | Streaming | Sync generator (`yield`) | Async generator (`async for` / `yield`) | Sync generator (`yield`) | | Server | MLflow Model Server | MLflow GenAI Server (FastAPI) | MLflow GenAI Server (FastAPI) | | Deployment | `databricks_agents.deploy()` | `databricks bundle deploy` + `bundle run` | `databricks bundle deploy` + `bundle run` | ### Async Patterns (only if `<async>` = yes) > **Skip this section if the user chose synchronous migration.** The sync path keeps all original I/O calls as-is. All I/O operations must be converted to async: ```python # OLD (sync) response = client.chat(messages) # NEW (async) response = await client.achat(messages) # OLD (sync iteration) for chunk in stream: yield chunk # NEW (async iteration) async for chunk in stream: yield chunk ``` --- ## Step 3: Migrate the Agent Code > **Task:** Mark "Analyze and understand agent code" as `completed`. Mark "Migrate agent code to Apps format" as `in_progress`. ### 3.1 Copy Code Dependencies and Artifacts The original MLflow model may contain multiple code files and artifacts that need to be migrated. **Copy all code files from `/code` to `agent_server/`:** ```bash # Copy all Python files from original code folder cp ./original_mlflow_model/code/*.py ./<app-name>/agent_server/ # If there are subdirectories with code, copy those too # cp -r ./original_mlflow_model/code/submodule ./<app-name>/agent_server/ ``` **Copy artifacts (if present):** ```bash # Create an artifacts directory in the migrated app if needed mkdir -p ./<app-name>/agent_server/artifacts # Copy all artifacts
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub