CertSafari
    Databricks Certified Data Engineer Professional - October 9 onwards· Lessons

    Domain 3 · Lesson 20/46

    ai_query in Lakeflow Pipelines: Enrichment and Classification at Scale

    Apply AI functions, including ai_query, to perform model inference within data pipelines for enrichment and classification tasks.

    11 min read
    3% of exam
    5 sources
    Published 2 Oct 2026
    Docs as of 30 Sep 2026

    What you will be able to do

    • Put ai_query inside a Lakeflow pipeline that ingests, classifies, validates and enriches data
    • Restrict LLM classification to fixed labels with a responseFormat enum, and validate the result before the next step
    • Choose between ai_classify and ai_query for a classification task
    • Apply production practices: failOnError, submitting the full dataset at once, batch-optimized models and query-profile monitoring

    1.Where inference sits in a batch pipeline

    For large-scale batch inference, you can put AI Functions straight into production pipelines, either task-specific functions or ai_query. You can write them in SQL or Python and deploy them as Lakeflow pipelines, as scheduled Databricks workflows, or as Structured Streaming jobs. Inference is one step in a longer flow, with ingestion before it and post-processing after it.

    The Databricks reference pipeline works on news articles. A streaming table, news_raw, ingests CSV files from a Unity Catalog volume. A materialized view, news_categorized, then calls ai_query on each article to extract a title and a category.

    The Python version of news_categorized, adding a meta_data column produced by ai_querypython
    @dp.materialized_view(
      comment="Extract category and title from news articles using LLM inference."
    )
    def news_categorized():
      # Limit the number of rows to 2 as in the SQL version
      df_raw = spark.read.table("news_raw").limit(2)
      # Inject the JSON schema variable into the ai_query call using an f-string.
      return df_raw.withColumn(
        "meta_data",
        expr(
          f"ai_query('system.ai.meta-llama-3-3-70b-instruct', "
          f"concat('Extract the category of the following news article: ', inputs), "
          f"responseFormat => '{news_extraction_schema}')"
        )
      )

    In Python, ai_query is a SQL expression wrapped in expr() inside withColumn. Nothing needs installing: the same SQL function runs from a DataFrame.

    Checkpoint 1 of 5· Put it in order

    Put the stages of the reference news pipeline in order

    1. 1.Validate the model's title and category in news_validated
    2. 2.Ingest raw articles from a volume into the news_raw streaming table
    3. 3.Classify each article with ai_query into news_categorized
    4. 4.Generate summaries with a second ai_query in news_summarized

    Sources12

    2.Classify with a schema, validate, then enrich

    The news_extraction_schema variable is a json_schema responseFormat with two properties. title is a free string. category is a string limited to an enum of six labels. That enum turns open-ended generation into classification: the model has to pick one of your labels. Because responseFormat returns a JSON string, later stages read individual fields with get_json_object(meta_data, '$.category').

    Model output is still data you didn't write, so the next table checks it before anything relies on it. news_validated declares expectations on the parsed fields. The title must have at least three words and the category must be one of the six labels. In the Python version the category rule uses @dp.expect_or_fail. How expectation actions behave is covered in the data quality lesson. What matters here is the pattern: check the inference output before the next step uses it.

    Expectations that check the fields ai_query extractedsql
    CREATE OR REFRESH MATERIALIZED VIEW news_validated (
      CONSTRAINT valid_title EXPECT (size(split(get_json_object(meta_data, '$.title'), ' ')) >= 3),
      CONSTRAINT valid_category EXPECT (get_json_object(meta_data, '$.category') IN ('Politics', 'Sports', 'Technology', 'Health', 'Entertainment', 'Business'))
    )
    COMMENT "Validated news articles ensuring the title has at least 3 words and the category is valid."
    AS
    SELECT *
    FROM news_categorized;

    The last stage, news_summarized, reads category and title out of meta_data and calls ai_query again with a plain prompt, "Summarize the following political news article in 2-3 sentences". One pipeline can chain several inference steps, and each adds columns to rows that passed the step before.

    When there is no schema to enforce, a few-shot prompt is another way to classify. The scheduled-workflow example tells the model it is an opinion-mining service, lists the allowed classifications (Quality, Service, Design, Safety, Efficiency, Usability, Price) and includes one worked DOCUMENT/RESULT pair. It then appends each REVIEW_TEXT.

    Checkpoint 2 of 5· Exam question

    A team deployed a custom fine-tuned classification model to a Databricks model-serving endpoint named `ticket_priority_classifier`, whose logged model signature expects two input features, `ticket_text` and `queue_name`. They want to call it from `ai_query` inside a Lakeflow pipeline to enrich an incoming streaming table. Which of the following are true about calling this endpoint correctly with ai_query?(Select 3)

    Sources2

    3.When ai_classify is the better tool

    If the job is just "put this text in one of these buckets," Databricks' advice to start with a task-specific function points to ai_classify. You supply labels, either as a JSON array of names or as a JSON object mapping each name to a description. Descriptions improve accuracy. You need at least 2 labels and no more than 500. The labels argument can be any expression that evaluates to a STRING, including a Delta table column, so the taxonomy can live in a table. The content can be raw text or a VARIANT produced by an upstream AI function such as ai_parse_document.

    Choosing a classification approach
    Needai_classifyai_query
    LabelsJSON array or label-to-description object, 2–500 labelsYour own prompt, or a responseFormat enum
    Model choiceManaged by DatabricksAny supported endpoint, including custom ML models
    Extra outputconfidence_score and rationale (version 2.1 options)Whatever your schema or prompt asks for
    Multiple labels per rowoptions multilabel set to "true"Must be designed into the prompt or schema

    Databricks recommends version 2.1. It adds enableConfidenceScores and enableRationales, and it changes the output shape. Each returned classification becomes an object with a value key instead of a plain label string. That change applies to every 2.1 call, even with the new options turned off, so moving from 2.0 to 2.1 breaks downstream code that reads the label directly. Pin the version with options => map('version', '2.1').

    Checkpoint 3 of 5· Check yourself

    A pipeline moves from ai_classify version 2.0 to 2.1 without enabling any new options. Downstream code that reads the label string directly starts failing. Why?

    Sources3

    4.Running inference at production scale

    By default one bad row can sink a large batch. failOnError is an optional boolean that defaults to true, and it needs Databricks Runtime 15.3 or above. With the default, ai_query returns the parsed response and a failed row fails the query. Set it to false and ai_query returns a STRUCT holding the response and an error message. A row that succeeds has a null errorMessage. A row that fails because of a model endpoint error has a null response. Errors of any other kind still fail the whole query.

    Checkpoint 4 of 5· Fill the gap

    Which argument keeps one failing row from stopping this summarization query?

    SELECT text, ai_query(
        "system.ai.meta-llama-3-3-70b-instruct",
        "Summarize the given text comprehensively, covering key points and main ideas concisely while retaining relevant details and examples. Ensure clarity and accuracy without unnecessary repetition or omissions: " || text,
     ?  => false
    ) AS summary
    FROM uc_catalog.schema.table;

    Databricks lists further practices for large workloads. Use Databricks-hosted system.ai model services rather than provisioned throughput endpoints, because they scale automatically. Pick a model that is optimized for batch inference, since other models can cut throughput. Submit the whole dataset in one query: AI Functions already handles parallelization, retries and scaling, and splitting the data into small batches by hand can lower throughput. To see progress, open the query profile and click AI Query. It shows how many inferences completed and how many failed.

    Checkpoint 5 of 5· Check yourself

    An engineer loops over 10,000-row slices of a 50-million-row table and calls ai_query once per slice, "to avoid overloading the model". What does the documentation recommend instead?

    Sources41

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.With failOnError => false, ai_query never fails the query.Why is that wrong?

      Only model endpoint errors become per-row error messages. Errors of any other kind still fail the whole query.

      Covered in Running inference at production scale

    2. 2.Splitting a large table into small manual batches makes ai_query faster and safer.Why is that wrong?

      AI Functions handles parallelization, retries and scaling itself. Databricks says to submit the full dataset in one query.

      Covered in Running inference at production scale

    3. 3.Upgrading ai_classify from version 2.0 to 2.1 is safe as long as you don't turn on confidence scores or rationales.Why is that wrong?

      The 2.1 output shape, an object with a value key for each label, applies to every 2.1 call. The upgrade is not output-compatible.

      Covered in When ai_classify is the better tool

    Practise it for real

    Enrich a sample table with ai_query, then make the query robust and tune it the way a production pipeline would

    1. 1.On a non-Classic SQL warehouse or Databricks Runtime 15.4 LTS+, run the documented query that calls ai_query with 'system.ai.meta-llama-3-3-70b-instruct' and a prompt joined to pickup_zip, against samples.nyctaxi.trips with LIMIT 10.

      Why: It confirms that a Databricks-hosted model works with no endpoint setup.

      You should see: Ten trip rows, each with an extra column holding the model's answer about the state for that ZIP code.

    2. 2.Add failOnError => false as a third argument to the same call.

      Why: Production batch jobs should keep the rows that succeed when some inferences fail.

      You should see: The new column is now a STRUCT with a response field and an errorMessage field, and errorMessage is null for successful rows.

    3. 3.Replace failOnError with modelParameters => named_struct('max_tokens', 100, 'temperature', 0.7).

      Why: It shows that model settings are constants passed through modelParameters, not per-row values.

      You should see: The query runs and the answers may vary more, since temperature is now above the 0.0 default.

    4. 4.Open the query profile from the results window and click AI Query.

      Why: This is where you monitor batch inference progress.

      You should see: Counts of completed and failed inferences, plus the total time the request took.

    Stuck? Get a nudge

    If ai_query is not recognized, check that you are not on a Classic SQL warehouse.

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “you can integrate task-specific AI Functions, or the general-purpose function ai_query into your production workflows, like Lakeflow pipelines, Databricks workflows and Structured Streaming.”
      ↩︎ Where inference sits in a batch pipeline
      “Click AI Query to see metrics for that particular query including the number of completed and failed inferences”
      ↩︎ Running inference at production scale
    2. 2.
      “Pipelines can be authored in SQL or Python and deployed as:”
      ↩︎ Where inference sits in a batch pipeline
      “Validated news articles ensuring the title has at least 3 words and the category is valid.”
      ↩︎ Classify with a schema, validate, then enrich
      “output an array of json results that extracts key user opinions, a classification, and a Positive, Negative, Neutral, or Mixed sentiment”
      ↩︎ Classify with a schema, validate, then enrich
      “end-to-end workflows that include ingestion, preprocessing, inference, and post-processing”
      ↩︎ Checkpoint
      “"enum": ["Politics", "Sports", "Technology", "Health", "Entertainment", "Business"]”
      ↩︎ Prediction
    3. 3.
      “labels must contain at least 2 labels, and no more than 500 labels.”
      ↩︎ When ai_classify is the better tool
      “To pin a version explicitly, pass options => map('version', '2.1').”
      ↩︎ When ai_classify is the better tool
      “This output shape change applies to all version 2.1 calls, even when the new options are disabled.”
      ↩︎ Exam trap 3
      “Update your queries and downstream code to read the label from the value key instead of reading it directly.”
      ↩︎ Checkpoint
    4. 4.
      “A boolean literal that defaults to true.”
      ↩︎ Running inference at production scale
      “If failOnError => false, the function returns a STRUCT object that contains the parsed response and the error message string.”
      ↩︎ Running inference at production scale
      “If the inference of the row fails due to other errors, the whole query fails.”
      ↩︎ Exam trap 1

    Also cited

    Spotted a mistake, or was something unclear? Tell us.