What you will be able to do
- Generate embeddings with AI_EMBED, store them in a VECTOR column of matching dimension, and compare them with vector similarity functions
- Build a semantic search and a retrieval-augmented generation (RAG) query in SQL
- Decide when to fine-tune, then prepare data for, launch, monitor and pay for a Cortex Fine-tuning job
1.Vector embeddings with AI_EMBED
An embedding reduces high-dimensional data such as free text to a vector of numbers. Its geometry preserves meaning: semantically similar texts produce vectors that point in roughly the same direction. Take a help desk that wants to surface already-resolved cases similar to a new one. Matching on embeddings finds related cases even when they share no keywords.
In Snowflake you create embeddings with AI_EMBED(model, input). It is the updated version of EMBED_TEXT_768 and EMBED_TEXT_1024, so treat those names as legacy. The function returns a value of the VECTOR data type. The model you pick fixes the vector's dimension, so it also fixes the column type you store it in.
| Model | Output dimensions | Context window | Language support |
|---|---|---|---|
| snowflake-arctic-embed-m-v1.5 | 768 | 512 | English-only |
| snowflake-arctic-embed-m | 768 | 512 | English-only |
| e5-base-v2 | 768 | 512 | English-only |
| snowflake-arctic-embed-l-v2.0 | 1024 | 512 | Multilingual |
| voyage-multilingual-2 | 1024 | 32000 | Multilingual |
| nv-embed-qa-4 | 1024 | 512 | English-only |
Three practical points follow from the table and the AI_EMBED reference. First, models may cost different amounts, so the cheapest model that fits your language needs and text length is usually the right choice. Second, for multilingual text, choose a model marked Multilingual. voyage-multilingual-2 also has a far longer context window than the others. Third, images need a different model: for image input the only option is voyage-multimodal-3, with the image passed as a FILE via TO_FILE. Calling AI_EMBED requires a role with SNOWFLAKE.CORTEX_USER or the narrower SNOWFLAKE.CORTEX_EMBED_USER database role.
To search documents semantically, you first store their embeddings in a VECTOR column and keep them current as documents are added or edited:
Checkpoint 1 of 5· Fill the gap
The issues are embedded with snowflake-arctic-embed-m. Which dimension must the new column declare?
ALTER TABLE issues ADD COLUMN issue_vec VECTOR(FLOAT, ? );
UPDATE issues
SET issue_vec = AI_EMBED('snowflake-arctic-embed-m', issue_text);snowflake-arctic-embed-m outputs 768-dimensional vectors, so the VECTOR column must be VECTOR(FLOAT, 768). The value 512 is that model's context window, not its output size.
Source: docs.snowflake.com2.Similarity functions, semantic search and RAG
Once you have vectors, you compare them with one of four vector similarity functions: VECTOR_INNER_PRODUCT, VECTOR_L1_DISTANCE, VECTOR_L2_DISTANCE and VECTOR_COSINE_SIMILARITY. Two client details come up in practice. The Python Connector supports the VECTOR type from version 3.6, and Snowpark Python from version 1.11. However, Snowpark Python has no VECTOR_COSINE_SIMILARITY function; its example uses vector_l2_distance instead.
A semantic search has two steps. Embed the search term with the same model used for the documents. Then rank the documents by similarity, using ORDER BY and LIMIT to keep the top k and, optionally, a minimum-similarity threshold.
The reason is cost. A similarity call in SELECT is evaluated only for rows that pass the other WHERE conditions, such as "logged in the last 90 days". Put it in WHERE and it can end up running across the whole table.
Retrieval-augmented generation (RAG) builds on this search. You find the documents most similar to the user's question, then pass the best match to an LLM together with the question as context for its completion. This can improve how appropriate the answer is significantly. In the example below, the wiki articles were already embedded into a vec column. The query embeds the question, retrieves the closest article, and builds the AI_COMPLETE prompt with CONCAT:
-- Embed incoming query
SET query = 'in which year was Snowflake Computing founded?';
CREATE OR REPLACE TABLE query_table (query_vec VECTOR(FLOAT, 768));
INSERT INTO query_table SELECT AI_EMBED('snowflake-arctic-embed-m', $query);
-- Do a semantic search to find the relevant wiki for the query
WITH result AS (
SELECT
w.content,
$query AS query_text,
VECTOR_COSINE_SIMILARITY(w.vec, q.query_vec) AS similarity
FROM wiki w, query_table q
ORDER BY similarity DESC
LIMIT 1
)
-- Pass to large language model as context
SELECT AI_COMPLETE('mistral-7b',
CONCAT('Answer this question: ', query_text, ' using this text: ', content)) FROM result;Checkpoint 2 of 5· Put it in order
Put the steps of a SQL RAG pipeline in order
- 1.Embed the documents with AI_EMBED into a VECTOR column
- 2.Embed the user's question with the same model
- 3.Pass the question and the retrieved text to AI_COMPLETE
- 4.Rank documents by VECTOR_COSINE_SIMILARITY and keep the top match
Documents are embedded once and stored. Each query is then embedded, matched by similarity, and the top document goes to the LLM as context.
“The top document is then passed to a large language model (LLM) along with the user”Source: docs.snowflake.com
Checkpoint 3 of 5· Exam question
A pipeline inserts embeddings into a table with the column `emb VECTOR(FLOAT, 768)` using the statement below, and the insert fails with a type error. ```sql INSERT INTO docs(id, emb) SELECT id, SNOWFLAKE.CORTEX.EMBED_TEXT_1024('snowflake-arctic-embed-l-v2.0', body) FROM raw_docs; ``` Select TWO changes that resolve the failure.(Select 2)
Correct answers: A, B — Redefine the column as `VECTOR(FLOAT, 1024)` so its declared dimension matches what the 1024-dimension embedding function returns.; Switch to `EMBED_TEXT_768` with `snowflake-arctic-embed-m-v1.5` so generated vectors have the 768 dimensions the column declares.
- A. A VECTOR column's dimension is fixed at creation, so it must equal the 1024 dimensions the function returns.
- B. Using a 768-dimension model aligns the generated vectors with the existing column definition, at the cost of multilingual support.
- C. Snowflake does not truncate vectors on insert, and truncated embeddings would no longer be valid points in the model's space.
- D. Warehouse size affects speed, not type compatibility, so the dimension mismatch persists.
- E. VARIANT storage would lose the VECTOR type that similarity functions require, and it does not make a fixed-dimension column flexible.
Sources1
3.Cortex Fine-tuning with FINETUNE
Prompt engineering and RAG change what the model is given. Fine-tuning changes the model itself. Cortex Fine-tuning uses parameter-efficient fine-tuning (PEFT): it trains customized adaptors on top of a pre-trained model rather than training a large model from scratch. It is the option for when you need better latency and results than prompting or RAG deliver, and it runs as a fully managed service inside Snowflake. The base model documented for tuning is llama3.1-8b, with a 24k context window split into 20k for the prompt and 4k for the completion.
Everything goes through one function, SNOWFLAKE.CORTEX.FINETUNE, and its first argument selects the action:
- CREATE starts a job and returns a fine-tuned model ID. - SHOW lists all fine-tuning jobs in the account. - DESCRIBE reports a job's progress and status. - CANCEL stops a job.
You can also start a job from Snowsight under AI & ML » AI Studio. Jobs are long-running and are not tied to your worksheet session, so you check on them with SHOW or DESCRIBE.
Checkpoint 4 of 5· Fill the gap
Which argument starts a new fine-tuning job?
SELECT SNOWFLAKE.CORTEX.FINETUNE(
' ? ',
'my_tuned_model',
'llama3.1-8b',
'SELECT prompt, completion FROM my_training_data',
'SELECT prompt, completion FROM my_validation_data'
);CREATE starts the job and returns a model ID. DESCRIBE and SHOW only report status, and CANCEL terminates a job.
Source: docs.snowflake.comTraining data comes from a table or view, through a query whose result has columns named prompt and completion. If your columns have other names, alias them (SELECT a AS prompt, d AS completion ...). Any other columns are ignored. Each pair should show the exact response you want for that prompt. Start with a few hundred examples: many more can lengthen tuning drastically for little gain. Pairs longer than the context allotment are truncated, which can hurt model quality. The row limit falls as epochs rise. llama3.1-8b allows 150k rows for one epoch but 50k at the default of three, because the effective limit is the one-epoch limit divided by the number of epochs.
Privileges. The role creating the job needs USAGE on the database the data is read from and CREATE MODEL (or OWNERSHIP) on the schema the model is saved to. It also needs SNOWFLAKE.CORTEX_USER, which ACCOUNTADMIN grants. Other roles need a usage grant on the model before they can call it.
Cost. Training is billed per trained token, which equals input tokens multiplied by epochs. Inference with AI_COMPLETE on the tuned model is billed per token processed. Storage for the adaptors and warehouse time for the SQL commands are charged on top. SNOWFLAKE.ACCOUNT_USAGE.CORTEX_FINE_TUNING_USAGE_HISTORY shows credit and token consumption. Once the job finishes, you call the model by its returned name in AI_COMPLETE.
Checkpoint 5 of 5· Check yourself
A job trains on 2 million input tokens for 3 epochs. How many trained tokens are billed for training?
Trained tokens equal input tokens multiplied by the number of epochs: 2M × 3 = 6M. Inference, storage and warehouse costs are billed separately.
“Fine-tuning trained tokens = number of input tokens * number of epochs trained”Source: docs.snowflake.com
Sources3
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Snowpark Python DataFrames can call VECTOR_COSINE_SIMILARITY just like SQL.Why is that wrong?
Snowpark Python supports the VECTOR type but not the cosine similarity function. Its example uses vector_l2_distance; otherwise use SQL or the Python Connector.
2.Put the similarity threshold directly in WHERE so non-matching rows are skipped early.Why is that wrong?
Compute similarity in SELECT under an alias and filter on the alias. The function then runs only on rows that pass the other WHERE conditions.
3.Load as many training rows as possible into a fine-tuning job; more data always gives a better model.Why is that wrong?
Snowflake advises starting with a few hundred examples. Many more can lengthen tuning drastically for minimal improvement, and row limits fall as epochs rise.
Covered in Cortex Fine-tuning with FINETUNE
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“The advantage of using embedding vectors in this application is that it goes beyond keyword matching to semantic similarity”
↩︎ Vector embeddings with AI_EMBED“Keep the embeddings up to date when documents are added or edited.”
↩︎ Vector embeddings with AI_EMBED“Support for the VECTOR type was introduced in version 3.6 of the Snowflake Python Connector.”
↩︎ Similarity functions, semantic search and RAG“This can improve the appropriateness of the response significantly.”
↩︎ Similarity functions, semantic search and RAG“The Snowpark Python library does not support the VECTOR_COSINE_SIMILARITY function.”
↩︎ Exam trap 1“Generally, the call to the vector similarity function should appear in the SELECT clause, not in the WHERE clause.”
↩︎ Exam trap 2“Generally, the call to the vector similarity function should appear in the SELECT clause, not in the WHERE clause.”
↩︎ Prediction“The top document is then passed to a large language model (LLM) along with the user”
↩︎ Checkpoint - 2.
“AI_EMBED is the updated version of EMBED_TEXT_1024 and EMBED_TEXT_768.”
↩︎ Vector embeddings with AI_EMBED“You must use a role that has been granted the SNOWFLAKE.CORTEX_USER database role or the SNOWFLAKE.CORTEX_EMBED_USER database role to call this function.”
↩︎ Vector embeddings with AI_EMBED - 3.
“Cortex Fine-tuning allows users to leverage parameter-efficient fine-tuning (PEFT) to create customized adaptors for use with pre-trained models on more specialized tasks.”
↩︎ Cortex Fine-tuning with FINETUNE“the query result must contain columns named prompt and completion”
↩︎ Cortex Fine-tuning with FINETUNE“Fine-tuning jobs are often long running and are not attached to a worksheet session.”
↩︎ Cortex Fine-tuning with FINETUNE“the ACCOUNTADMIN role must grant the SNOWFLAKE.CORTEX_USER database role to the user who will call the function.”
↩︎ Cortex Fine-tuning with FINETUNE“Starting with too many examples may increase tuning time drastically with minimal improvement in performance.”
↩︎ Exam trap 3“Fine-tuning trained tokens = number of input tokens * number of epochs trained”
↩︎ Checkpoint