import mlflow
from pyspark.sql import functions as F
catalog = spark.sql("SELECT current_catalog()").first()[0]
spark.sql(f"USE SCHEMA {catalog}.dbx_course")
mlflow.set_registry_uri("databricks-uc") # models go to Unity Catalog
Module 20: Databricks AI & Machine Learning
MLflow, model serving, vector search, RAG and agents.
Topics in this module
- Databricks Mosaic AI Overview
- MLflow Fundamentals
- Experiment Tracking
- Feature Engineering and Feature Management
- Model Training and Evaluation
- Model Registry and Unity Catalog
- Model Serving
- Vector Search
- Retrieval-Augmented Generation (RAG)
- AI Functions in SQL
- AI Agents and Agent Evaluation
- Model Monitoring and Governance
- MLOps and LLMOps
The AI and ML tools on Databricks, from tracking an experiment to serving a model. This is a tour, not a data science course. You run a small scikit-learn experiment, register it in Unity Catalog, and meet the rest as concept.
- Hands-on topics (2, 3, 5, 6) use MLflow and scikit-learn on serverless compute
- Several features (Model Serving, Vector Search, AI Functions, agents) need serverless endpoints, Foundation Model APIs or special entitlements. Free Edition support is not confirmed in the docs: try it, and treat it as reference if it's refused
- Product names move: Vector Search appears in current docs as Databricks AI Search. Both names are used below
- Setup:
Databricks Mosaic AI Overview
By the end: map the Databricks AI and ML platform.
| Area | Tool |
|---|---|
| Track and compare experiments | MLflow |
| Features | Feature tables in Unity Catalog |
| Model registry | Models in Unity Catalog, with versions and aliases |
| Real-time inference | Model Serving (REST endpoints) |
| Batch AI in SQL | AI Functions (ai_query and task functions) |
| Retrieval | Vector Search (AI Search) |
| Agents | Agent building, tracing and evaluation with MLflow |
| Foundation models | Foundation Model APIs (pay-per-token or provisioned) |
- Everything is governed by Unity Catalog: the same grants and lineage as tables
- Data engineers mostly build the data side: clean features, reliable pipelines, monitoring (topics 4 and 12)
MLflow Fundamentals
By the end: log your first MLflow run.
mlflow.set_experiment(f"/Users/{spark.sql('SELECT current_user()').first()[0]}/dbx_course_experiment")
with mlflow.start_run(run_name="first_run") as run:
mlflow.log_param("learning_rate", 0.1)
mlflow.log_metric("accuracy", 0.91)
mlflow.log_text("a note about this run", "notes.txt")
print(run.info.run_id)
| Concept | Meaning |
|---|---|
| Experiment | A named group of runs (one per project or question) |
| Run | One execution: parameters, metrics, artifacts |
| Parameter | An input setting (learning_rate) |
| Metric | A result number, can be logged over time |
| Artifact | A file: model, plot, text |
- Open Experiments in the sidebar to see the run
- Without
set_experiment, runs go to the notebook experiment - MLflow on Databricks is the managed version of the open-source project
Free Edition
MLflow tracking on serverless is expected to work. If the experiment path errors, use the notebook's built-in experiment by deleting the set_experiment line.
Experiment Tracking
By the end: track and compare runs with autologging.
from sklearn.datasets import load_diabetes
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
X, y = load_diabetes(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
mlflow.sklearn.autolog(log_models=False) # log params and metrics automatically
for depth in (3, 6, 10):
with mlflow.start_run(run_name=f"rf_depth_{depth}"):
model = RandomForestRegressor(max_depth=depth, n_estimators=50, random_state=42)
model.fit(X_train, y_train)
rmse = mean_squared_error(y_test, model.predict(X_test)) ** 0.5
mlflow.log_metric("test_rmse", rmse)
print(depth, round(rmse, 2))
- Each loop makes a run. In the experiment page, select runs → Compare to see parameters against
test_rmse - Autologging records parameters, training metrics and (optionally) the model without extra code
- Log what you need to reproduce: data version (table + Delta version), code version (Git commit), parameters, random seed
# record the data version used for training
mlflow.set_tag("data_table", "dbx_course.orders")
mlflow.set_tag("data_delta_version", spark.sql("DESCRIBE HISTORY orders_delta").first()["version"])
Seed everything
A run you can't repeat can't be trusted. Fix random_state and log the data version.
Feature Engineering and Feature Management
By the end: build and manage features.
- A feature table is a Delta table in Unity Catalog with a primary key (and a timestamp key for time series)
- A normal pipeline (Module 8, 9) keeps it fresh: features are data engineering
- Point-in-time joins build training sets using the feature values as they were at each label's time: no leakage from the future
- Automatic feature lookup at serving: the endpoint reads current features by key
- Online feature stores serve low-latency lookups to applications
# a feature table is just a table: customer-level features from the practice data
(spark.table("orders").groupBy("customer_id")
.agg(F.count("*").alias("orders_total"),
F.avg("quantity").alias("avg_quantity"),
F.max("order_ts").alias("last_order_ts"))
.write.mode("overwrite").saveAsTable("customer_features"))
%sql
ALTER TABLE customer_features ALTER COLUMN customer_id SET NOT NULL;
ALTER TABLE customer_features ADD CONSTRAINT customer_features_pk PRIMARY KEY (customer_id)
- Document features: definition, owner, freshness
- Use the Feature Engineering client and its docs for training sets and lookups: signatures change between versions
Leakage
A feature computed with data from after the label date makes a model look great in training and fail in production.
Model Training and Evaluation
By the end: train a model properly and judge it.
from sklearn.metrics import mean_absolute_error, r2_score
import mlflow.sklearn
with mlflow.start_run(run_name="rf_final") as run:
model = RandomForestRegressor(max_depth=6, n_estimators=100, random_state=42).fit(X_train, y_train)
pred = model.predict(X_test)
mlflow.log_metrics({
"test_rmse": mean_squared_error(y_test, pred) ** 0.5,
"test_mae": mean_absolute_error(y_test, pred),
"test_r2": r2_score(y_test, pred),
})
mlflow.sklearn.log_model(model, artifact_path="model", input_example=X_train.iloc[:2])
run_id = run.info.run_id
print(run_id)
| Step | Rule |
|---|---|
| Split | Hold out a test set you never tune on. Split by time when data is time-ordered |
| Baseline | Compare with a trivial model (the mean) first |
| Metric | Choose one that matches the business cost (MAE, precision at k...) |
| Check | Per segment, not only on average. Look at errors, not only scores |
| Log | Params, metrics, model with a signature and an input example |
input_examplealso gives the model a signature, which Unity Catalog requires- Keep training code in functions and files, so it can run as a job (Module 10, 26)
- Training big models needs GPU or classic ML runtimes: out of scope for Free Edition
Model Registry and Unity Catalog
By the end: register the model in Unity Catalog and promote it with an alias.
model_name = f"{catalog}.dbx_course.diabetes_rf"
result = mlflow.register_model(f"runs:/{run_id}/model", model_name)
print(result.version)
from mlflow import MlflowClient
client = MlflowClient()
client.set_registered_model_alias(model_name, "champion", result.version)
loaded = mlflow.pyfunc.load_model(f"models:/{model_name}@champion")
print(loaded.predict(X_test.iloc[:3]))
| Concept | Meaning |
|---|---|
| Registered model | A named, governed model: catalog.schema.model |
| Version | Each registration creates one |
| Alias | A movable label such as champion that points to a version |
- Promote by moving the alias. Consumers load
models:/name@championand pick up the new version next run - Stages (Staging/Production) are not supported in Unity Catalog: use aliases and catalog or schema per environment
- Permissions:
CREATE MODELon the schema,EXECUTEon the model to use it. Models are a kind of function in grants - Lineage links the model to the training data and the notebook or job
Free Edition
Registering in Unity Catalog needs CREATE MODEL on your schema. If registration fails, you have the permission or compute-mode restriction described in the docs.
Model Serving
By the end: serve a model behind a REST endpoint.
| Endpoint type | Hosts |
|---|---|
| Custom model | Your MLflow model |
| Foundation Model APIs | Databricks-hosted LLMs: pay-per-token or provisioned throughput |
| External model | A model hosted elsewhere (for example OpenAI), governed centrally |
| Agent | A deployed agent |
# calling an endpoint (shape only; needs a real endpoint, host and token)
import requests
resp = requests.post(
"https://<workspace-url>/serving-endpoints/<endpoint-name>/invocations",
headers={"Authorization": "Bearer <token>"},
json={"dataframe_split": {"columns": list(X_test.columns), "data": X_test.iloc[:1].values.tolist()}},
)
print(resp.json())
- Choose endpoints for real-time needs. For scoring a table, batch inference (load the model,
predictin a job, orai_query) is cheaper - Endpoints scale with demand. AI Gateway adds usage limits and monitoring
- Create via the Serving UI, API or SDK
- Authenticate with a service principal in production
Free Edition
Serving endpoints may not be available. Read as reference.
Vector Search
By the end: use Vector Search for similarity and retrieval.
| Term | Meaning |
|---|---|
| Embedding | A vector of numbers that represents meaning |
| Endpoint | The service that hosts indexes |
| Index | A searchable copy of a table's embeddings, governed by Unity Catalog |
| Delta Sync index | Stays in sync with a source Delta table |
| Direct access index | You write vectors through the API |
| Hybrid search | Combines keyword and vector similarity |
- Index types: Delta Sync with Databricks-computed embeddings (give it text), Delta Sync with your own embeddings, or direct access
- Standard endpoints need change data feed on the source table (row tracking enables it)
- Requirements: Unity Catalog and serverless compute
- Limits worth knowing: index capacity is set from the source size at creation, and row and column-level security isn't supported on indexes
- The product is named AI Search in the current docs. The Python client is
VectorSearchClientin older material andAISearchClientin the current SDK: check your version
Not hands-on
Needs an endpoint and an embedding model. Free Edition support isn't confirmed.
Retrieval-Augmented Generation (RAG)
By the end: build a retrieval-augmented generation (RAG) pipeline.
| Stage | Data engineering work |
|---|---|
| Ingest | Load documents into a volume (ai_parse_document extracts text from PDFs and more) |
| Chunk | Split by structure, with overlap, keeping metadata (source, page) |
| Embed and index | A Delta table of chunks feeds a Delta Sync index |
| Retrieve | Query by similarity, filter by metadata |
| Generate | Prompt = question + retrieved chunks |
| Evaluate | Check retrieval quality and answer quality separately |
# the data side: a chunk table (works on Free Edition)
docs = spark.createDataFrame(
[(1, "Delta tables support time travel with VERSION AS OF."),
(2, "Auto Loader ingests new files incrementally.")],
"chunk_id INT, text STRING"
).withColumn("source", F.lit("course_notes"))
docs.write.mode("overwrite").option("delta.enableChangeDataFeed", "true").saveAsTable("doc_chunks")
- Keep chunks as a governed Delta table: ownership, lineage, access control, refresh with a normal pipeline
- Most RAG failures are retrieval failures: bad chunks, missing metadata, stale data
- Re-index when documents change: a pipeline problem
- Respect access rights: an index doesn't apply per-user table security, so filter at query time or restrict the index
AI Functions in SQL
By the end: apply language models inside SQL with AI Functions.
%sql
-- general purpose: any supported foundation model endpoint (needs access to the endpoint)
SELECT ai_query(
'databricks-meta-llama-3-3-70b-instruct',
'Classify the sentiment of this review as positive, negative or neutral: ' || review) AS sentiment,
review
FROM (VALUES ('Fast delivery, great product'), ('Arrived broken')) AS t(review)
%sql
-- task-specific functions: no model name or prompt needed
SELECT ai_analyze_sentiment('I love this') AS sentiment,
ai_translate('Good morning', 'nl') AS dutch,
ai_summarize('Delta Lake adds transactions to data lakes.') AS summary
| Function | Use |
|---|---|
ai_query |
Any prompt, any supported endpoint, structured output possible |
ai_classify, ai_extract |
Label and extract fields |
ai_summarize, ai_translate, ai_fix_grammar, ai_mask |
Text transforms |
ai_analyze_sentiment, ai_similarity |
Analysis |
ai_parse_document |
Text and structure from documents |
ai_forecast |
Time-series forecasts |
- They run on serverless compute, SQL warehouses (not classic), notebooks, jobs and pipelines
- Cost: the compute plus inference charges for most of them. Estimate before running on millions of rows
- Test on a small sample first, check results, then run at scale. Write results to a table (never call the model twice for the same row)
- Model names change: take the current endpoint name from the Serving page
Free Edition
Foundation Model API access on Free Edition isn't confirmed. If the function fails, read it as reference.
AI Agents and Agent Evaluation
By the end: build agents and evaluate them.
- An agent = a language model + instructions + tools (functions, SQL, Vector Search, other services)
- Tracing (MLflow) records every step: prompt, tool call, result, latency. Read traces to debug
- Evaluation compares versions on a fixed dataset of questions:
mlflow.genai.evaluate()runs scorers over the dataset- LLM judges such as correctness, completeness and fluency score answers
- The same scorers can sample production traces for monitoring
- Keep a golden set of real questions and expected answers
- Version prompts, tools and models together. Compare before you ship
Evaluate before you ship
An agent with no evaluation set only looks like it works.
Model Monitoring and Governance
By the end: monitor and govern models.
| What to watch | Why |
|---|---|
| Input data drift | Features changed: the model sees unfamiliar data |
| Prediction drift | Outputs shifted |
| Quality | Accuracy against labels, once they arrive |
| Latency, errors, cost | Serving health and spend |
| Fairness, safety | Segments, toxic or private outputs |
- Data profiling (Data quality monitoring) can compute statistics and drift on tables, including inference tables of a served model
- AI Gateway adds usage limits, guardrails and logging for endpoints
- Governance in Unity Catalog: owners, versions and aliases, permissions, lineage from data to model, tags, comments
- Log who changed which alias and when
- Define a retraining trigger: drift beyond a threshold, or a schedule
- Treat personal data in training sets and prompts like any other personal data (Module 17)
MLOps and LLMOps
By the end: operate models and LLM apps like software.
| Practice | MLOps | LLMOps |
|---|---|---|
| Version | Code, data, model | Prompts, retrieval data, models |
| Test | Unit tests, data checks, metric thresholds | Evaluation datasets and judges |
| Deploy | Registered model, alias, endpoint | Agent version, endpoint |
| Promote | Move an alias after checks pass | Same |
| Monitor | Drift, quality | Traces, judge scores, cost per request |
- Deployment jobs (in MLflow) chain evaluation, approval and deployment with an audit trail
- Separate dev, staging, prod with catalogs or schemas (Module 15)
- Deploy with bundles and CI/CD: the same rules as any pipeline
- Models need rollback: keep the previous version and move the alias back
Remember
A model is code plus data. It needs versions, tests, deployment and monitoring like everything else.
What you can do now
- The AI and ML platform map; MLflow tracking and comparison
- Features, training, the Unity Catalog model registry
- Serving, Vector Search, RAG, AI Functions and agents
- Monitoring, governance, MLOps and LLMOps