{"id":108262,"date":"2026-02-09T13:52:11","date_gmt":"2026-02-09T13:52:11","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=108262"},"modified":"2026-04-08T10:25:00","modified_gmt":"2026-04-08T10:25:00","slug":"sql-server-2025-create-external-model-and-ai_generate_embeddings-commands-explained","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/sql-server-2025-create-external-model-and-ai_generate_embeddings-commands-explained\/","title":{"rendered":"SQL Server 2025 CREATE EXTERNAL MODEL and AI_GENERATE_EMBEDDINGS Commands Explained"},"content":{"rendered":"\n<p>When <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/sql-server-2025-is-in-public-preview\/\" target=\"_blank\" rel=\"noreferrer noopener\">SQL Server 2025 was announced<\/a>, Bob Ward mentioned that there would be some new commands for managing AI models and their definitions, as well as <a href=\"https:\/\/www.red-gate.com\/simple-talk\/t-sql-coding-basics\/\" target=\"_blank\" rel=\"noreferrer noopener\">T-SQL<\/a> functions to generate <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/ai-in-sql-server-2025-embeddings\/\" target=\"_blank\" rel=\"noreferrer noopener\">embeddings<\/a>, etc. I even made a guess that the command might be <code>CREATE AI MODEL<\/code>&#8230;<\/p>\n\n\n\n<p>Now that SQL Server 2025 has finally been released to the public, I was finally able to test and learn a lot about this command (named <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/statements\/create-external-model-transact-sql?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\"><code>CREATE EXTERNAL MODEL<\/code><\/a>), and I want to share my knowledge with you here. If you&#8217;re new to the world of AI, don&#8217;t worry, we&#8217;ll start with the basics and evolve to where this command fits in!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-what-s-an-ai-model\">What&#8217;s an AI Model?<\/h1>\n\n\n\n<p>Just as the term &#8220;database&#8221; in SQL Server can mean the &#8220;database itself&#8221;, a &#8220;SQL instance&#8221;, or a general definition, the term &#8220;model&#8221; has come to be used in many ways. If you talk to someone who lives only in the world of Machine Learning, they will have one definition. A mathematician will have another definition, as will a developer introducing AI to their product. To help you understand what SQL Server&#8217;s definition is for the <code>CREATE EXTERNAL MODEL<\/code> command, let&#8217;s dig deeper.<\/p>\n\n\n\n<p>An AI model is software that produces a result using AI algorithms and\/or libraries. You can access this software through an <a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/general\/api-monitoring-key-metrics-and-best-practices\/\" target=\"_blank\" rel=\"noreferrer noopener\">API<\/a>, whether in a cloud service, a virtual machine, a container, etc. This API can range from a simple HTTP call, to loading a <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/dlls\/dynamic-link-libraries\" target=\"_blank\" rel=\"noreferrer noopener\">DLL<\/a> and calling its functions. These AI models are created by companies, open-source teams, developers, and others around the world. For example, one of the most famous companies is <a href=\"https:\/\/openai.com\/about\/\" target=\"_blank\" rel=\"noreferrer noopener\">OpenAI<\/a>, which became popular with ChatGPT. However, there are lots of them: <a href=\"https:\/\/ai.google\/\" target=\"_blank\" rel=\"noreferrer noopener\">Google<\/a>, <a href=\"https:\/\/cohere.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cohere<\/a>, <a href=\"https:\/\/huggingface.co\" target=\"_blank\" rel=\"noreferrer noopener\">Hugging Face<\/a>, <a href=\"https:\/\/www.meta.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">Meta<\/a>, <a href=\"https:\/\/www.nomic.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">Nomic<\/a>, <a href=\"https:\/\/microsoft.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">Microsoft<\/a>, and <a href=\"https:\/\/www.forbes.com\/lists\/ai50\/\" target=\"_blank\" rel=\"noreferrer noopener\">many others<\/a>.<\/p>\n\n\n\n<p>There are AI models for various tasks, such as generating text, images, or audio &#8211; and these are likely the ones you have interacted with the most lately. However there are many others that, while they don&#8217;t necessarily produce a final interactive result, you can use for processing data. For example, there are models that can calculate trends from history (like a line on a graph).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-embeddings-model\">The Embeddings Model<\/h2>\n\n\n\n<p>One of these model types is very important in the world of text processing: embedding models. Embeddings are a sequence of numbers that can represent the meaning of a word, phrase, or entire text. They are generated by AI models, and you can use this to search for similar texts or group them. It&#8217;s an extremely powerful resource for those who need to compare texts.<\/p>\n\n\n\n<p>However, embeddings are not just limited to text: you can have embeddings that represent an image, audio, a binary document, etc. Likewise, they will represent the meaning of that content, and if you want to compare it with others, you just need to generate the embeddings again for the content you want to compare. Because they are a numerical sequence, there are some mathematical algorithms you can use to compare them, and see how similar they are.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"628\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-10-1024x628.png\" alt=\"An image showing some mathematical algorithms you can use to compare the meaning of content via the use of embeddings.\" class=\"wp-image-108263\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-10-1024x628.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-10-300x184.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-10-768x471.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-10.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>For example, <a href=\"https:\/\/platform.openai.com\/docs\/guides\/embeddings\" target=\"_blank\" rel=\"noreferrer noopener\">OpenAI has an embedding<\/a> model called <code>text-embedding-3-small<\/code>. To access and use it, I need to invoke it via API by passing the text I want, and it returns the embeddings to me:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"870\" height=\"788\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-11.png\" alt=\"An image showing a use case of OpenAI embedding 'text-embedding-3-small'.\" class=\"wp-image-108264\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-11.png 870w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-11-300x272.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-11-768x696.png 768w\" sizes=\"auto, (max-width: 870px) 100vw, 870px\" \/><\/figure>\n\n\n\n<p>If you want to do this locally, you can use <a href=\"https:\/\/ollama.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Ollama<\/a>, download lots of open-source models, and run them in your own GPU. Similarly, you access it via API:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"857\" height=\"1024\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-12-857x1024.png\" alt=\"An image showing how to access open-source models via API.\" class=\"wp-image-108265\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-12-857x1024.png 857w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-12-251x300.png 251w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-12-768x918.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-12.png 1011w\" sizes=\"auto, (max-width: 857px) 100vw, 857px\" \/><\/figure>\n\n\n\n<p>I can also load a model directly using <a href=\"https:\/\/www.python.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Python<\/a> code to generate these embeddings:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">import torch\nimport torch.nn.functional as F\nfrom transformers import AutoTokenizer, AutoModel, AutoImageProcessor\nimport torch\n\n#prepare the model\ntokenizer = AutoTokenizer.from_pretrained('nomic-ai\/nomic-embed-text-v1.5')\ntext_model = AutoModel.from_pretrained('nomic-ai\/nomic-embed-text-v1.5', trust_remote_code=True)\ntext_model.eval()\n\ndef mean_pooling(model_output, attention_mask):\n    token_embeddings = model_output[0]\n    input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()\n    return torch.sum(token_embeddings * input_mask_expanded, 1) \/ torch.clamp(input_mask_expanded.sum(1), min=1e-9)\n        \ntext = \"a car\"\nsentences = [text]\nencoded_input = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')\n \nwith torch.no_grad():\n   model_output = text_model(**encoded_input) # invoke the ai model!\n \n text_embeddings = mean_pooling(model_output, encoded_input['attention_mask'])\n text_embeddings = F.layer_norm(text_embeddings, normalized_shape=(text_embeddings.shape[1],))\n text_embeddings = F.normalize(text_embeddings, p=2, dim=1)\n\nprint (text_embeddings.tolist())[0]<\/pre><\/div>\n\n\n\n<p><em><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/ai-in-sql-server-2025-embeddings\/\" target=\"_blank\" rel=\"noreferrer noopener\">In this post<\/a> I provide a much more detailed explanation of what embeddings are and how to use them within SQL Server. From this point forward, I assume that you already understand what embeddings are and the vector data type, which are essential for use with SQL Server.<\/em><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-how-to-access-ai-models-in-sql-server-2025\">How to Access AI Models in SQL Server 2025<\/h1>\n\n\n\n<p>Now that you are familiar with the concept of AI models and what embeddings are, let&#8217;s use SQL Server to access them. As you noticed, we can access models using an HTTP API or directly in code by loading libraries. SQL Server allows both methods.<\/p>\n\n\n\n<p>Let&#8217;s start with an HTTP API first, which is the easiest way. Before using the <code>CREATE EXTERNAL MODEL<\/code> command, let&#8217;s use the new procedure <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/system-stored-procedures\/sp-invoke-external-rest-endpoint-transact-sql?view=sql-server-ver17&amp;tabs=request-headers\" target=\"_blank\" rel=\"noreferrer noopener\"><code>sp_invoke_external_rest_endpoint<\/code><\/a>. With this new procedure in SQL Server 2025, you can invoke APIs via HTTP, which is how most AI models are available.<\/p>\n\n\n\n<p><em>Before SQL Server 2025, it was possible to invoke HTTP using <a href=\"https:\/\/en.wikipedia.org\/wiki\/OLE_Automation\" target=\"_blank\" rel=\"noreferrer noopener\">OLE Automation<\/a>, <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/standard\/clr\" target=\"_blank\" rel=\"noreferrer noopener\">CLR<\/a>, or <a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/sql-server-and-undocumented-extended-procedures\/\" target=\"_blank\" rel=\"noreferrer noopener\">extended procedures<\/a>. However, all these methods enable more than just simple HTTP access, which might make DBAs hesitant to use them. With SQL Server 2025 you can now enable <strong>only<\/strong> the functionality to invoke HTTP APIs, which significantly reduces the amount of extra code enabled to run within your SQL instance.<\/em><\/p>\n\n\n\n<p>For these tests, we will use the API from the <a href=\"https:\/\/cohere.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cohere<\/a>, which allows you to create a free account. Cohere is one of the major developers of AI models. To create your account and generate an API KEY, <a href=\"https:\/\/dashboard.cohere.com\/welcome\/login\" target=\"_blank\" rel=\"noreferrer noopener\">Click here <\/a>and follow the steps to create a new account. Once your account is created, you will be redirected to your dashboard. Go to \u201cApi Keys\u201d:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"807\" height=\"624\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-13.png\" alt=\"An image showing where to click into API Keys in the Cohere dashboard.\" class=\"wp-image-108266\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-13.png 807w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-13-300x232.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-13-768x594.png 768w\" sizes=\"auto, (max-width: 807px) 100vw, 807px\" \/><\/figure>\n\n\n\n<p>Your key will be available in the \u201cTrial Keys\u201d section. Trial keys are limited (1000 calls per month), but this is more than enough for you to be able to perform the tests on this page. If you ever want Cohere in production, you can obtain a \u201cproduction key\u201d, which is unlimited, but you need to pay for its usage.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"558\" height=\"811\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-14.png\" alt=\"An image showing where to select the trial keys in Cohere.\" class=\"wp-image-108267\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-14.png 558w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-14-206x300.png 206w\" sizes=\"auto, (max-width: 558px) 100vw, 558px\" \/><\/figure>\n\n\n\n<p>To copy the trial key, click the eye icon in the \u201cKey\u201d column. <em>Soon, you will need to copy this key.<\/em> <\/p>\n\n\n\n<p>Next, we&#8217;re going to invoke the Cohere API to obtain the embeddings of a test text. Let&#8217;s create a new database where we will centralize all these tests:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">CREATE DATABASE AiTests;<\/pre><\/div>\n\n\n\n<p>Let&#8217;s enable the <code>sp_invoke_external_rest_endpoint<\/code> procedure:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">EXEC sp_configure 'external rest endpoint enabled',1\nRECONFIGURE\nGO\n<\/pre><\/div>\n\n\n\n<p>According to <a href=\"https:\/\/docs.cohere.com\/docs\/compatibility-api#embeddings\" target=\"_blank\" rel=\"noreferrer noopener\">the Cohere documentation<\/a>, we can invoke the generation of embeddings by sending an HTTP POST request to the address <a href=\"https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings<\/a>. At this address, we can pass the same format accepted by OpenAI (which is one of the formats acceptable by SQL Server). Translating this into the external rest endpoint call, this would be the code:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \" >USE AiTests\n\ndeclare @result nvarchar(max)\n\n\nexec sp_invoke_external_rest_endpoint 'https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings'\n,@payload = '{\"model\":\"embed-v4.0\", \"input\":\"Test direct from SQL Server\"}'\n,@response = @result output\n\nselect\n    HttpStatus = json_value(@result,'$.response.status.http.code')\n    ,errors =   json_value(@result,'$.result.message')\n    ,GeneratedEmbeddings = json_query(@result,'$.result.data[0].embedding')\n    ,FullResult = @result<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"166\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-15.png\" alt=\"An image showing that the code has returned a 401 error.\" class=\"wp-image-108268\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-15.png 963w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-15-300x52.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-15-768x132.png 768w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><\/figure>\n\n\n\n<p>However, when running the code above, the returned response is an http 401 error. To rectify this, you need to use the @credential parameter of this procedure and specify the credential with the Authentication data, which you can do using the <code>CREATE SCOPED DATABASE CREDENTIAL<\/code> command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\nCREATE DATABASE SCOPED CREDENTIAL [https:\/\/api.cohere.ai]\n    WITH IDENTITY = 'HTTPEndpointHeaders', secret = '{\"Authorization\":\"bearer APIKEY\"}';\nGO\n<\/pre><\/div>\n\n\n\n<p>Enter your account&#8217;s ApiKey where it says \u201cAPIKEY\u201d &#8211; note that the name of the credential must be the base URL you&#8217;ll use. When trying to run the command above, you may receive this error:<\/p>\n\n\n\n<p><strong>Msg 15581, Level 16, State 6, Line 37<br>Please create a master key in the database or open the master key in the session before performing this operation.<\/strong><\/p>\n\n\n\n<p>Since you&#8217;ll be storing sensitive data in your database, SQL requires it to be encrypted. In the case of scoped credentials, you need to create a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/security\/introduction-to-sql-server-security-part-5\/\" target=\"_blank\" rel=\"noreferrer noopener\">master key<\/a> in your database (the key used to encrypt this type of object.) So, re-run the command above, now with the master key created:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \" >USE AiTests\nGO\n\n-- Remember to save the master key password, in case you need to restore the database on another server, etc\nCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Colocar Uma senha Forte aqui Guardar no Cofre!' ;\n\n-- Now you can create the scoped credential. Remember to replace APIKEY with your trial key from your Cohere account\nCREATE DATABASE SCOPED CREDENTIAL [https:\/\/api.cohere.ai]\n    WITH IDENTITY = 'HTTPEndpointHeaders', secret = '{\"Authorization\":\"bearer APIKEY\"}';<\/pre><\/div>\n\n\n\n<p>Now we can repeat the command that invokes the Cohere API, using the @credential parameter:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \" >USE AiTests\n\nDECLARE @result nvarchar(max)\n\nexec sp_invoke_external_rest_endpoint 'https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings'\n,@payload = '{\"model\":\"embed-v4.0\", \"input\":\"Test direct from SQL Server\"}'\n,@response = @result output\n,@credential = 'https:\/\/api.cohere.ai' -- &gt; We just added that!\n\nselect\n    HttpStatus = json_value(@result,'$.response.status.http.code')\n    ,errors =   json_value(@result,'$.result.message')\n    ,GeneratedEmbeddings = json_query(@result,'$.result.data[0].embedding')\n    ,FullResult = @result<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"189\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-16-1024x189.png\" alt=\"An image showing the successful generation of embeddings using an AI model.\" class=\"wp-image-108269\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-16-1024x189.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-16-300x55.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-16-768x142.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-16.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Congratulations! You have finally generated your first embeddings using an AI model!<\/p>\n\n\n\n<p>For a simple test, this execution is okay. But what if you need to generate embeddings for texts stored in a table column?<\/p>\n\n\n\n<section id=\"my-first-block-block_1973b63a6608826c78b2c0bd620ab70b\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Write accurate SQL faster in SSMS with SQL Prompt AI<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Write or modify queries using natural language, get clear explanations for unfamiliar code, and fix and optimize SQL with ease &#8211; all without leaving SSMS.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/products\/sql-prompt\/#ai-powered-code\" class=\"btn btn--secondary btn--lg\" aria-label=\"Learn more and try for free: Write accurate SQL faster in SSMS with SQL Prompt AI\">Learn more and try for free<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-new-create-external-model-command-in-sql-server-2025\">The New CREATE EXTERNAL MODEL Command in SQL Server 2025<\/h2>\n\n\n\n<p>Now you know how to manually invoke the API of an AI provider, but SQL Server 2025 has introduced even more features that don&#8217;t require the use of a procedure directly.<\/p>\n\n\n\n<p>The first of these is the <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/statements\/create-external-model-transact-sql?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\">CREATE EXTERNAL MODEL<\/a><\/code> command, where you can create the definition of an AI model within your SQL database. Note that I am referring to \u201cthe definition,\u201d not the model itself. You don&#8217;t load the actual model into your SQL database, only the <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/sql-server-metadata-functions-the-basics\/\" target=\"_blank\" rel=\"noreferrer noopener\">metadata<\/a> that SQL requires to invoke the model&#8217;s API.<\/p>\n\n\n\n<p>Let&#8217;s create a model for the Cohere API using this command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\nCREATE EXTERNAL MODEL CohereTest\nWITH (\n      API_FORMAT = 'OpenAI',\n      LOCATION = 'https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings',\n      MODEL_TYPE = EMBEDDINGS,\n      MODEL = 'embed-v4.0',\n      CREDENTIAL = [https:\/\/api.cohere.ai]\n);<\/pre><\/div>\n\n\n\n<p>In <code>CREATE EXTERNAL MODEL CohereTest<\/code>, the segment <code>CohereTest<\/code> is an identifier, just like when you create a procedure or a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/sql-server-create-table-syntax-diagrams\/\" target=\"_blank\" rel=\"noreferrer noopener\">table<\/a>. You can name it whatever you want, and it follows the same identifier rules.<\/p>\n\n\n\n<p>Immediately following, we have the list of parameters defined within the <code>WITH (\u2026 )<\/code> (just like other commands have).<\/p>\n\n\n\n<p>The <code>API_FORMAT<\/code> parameter specifies which API format SQL should use when this model is invoked. I could list the acceptable formats here, but this might change over time. What you need to know is that this defines how SQL will send the data to the URL you provide; therefore, the format you choose must be compatible with what the service you are using accepts. <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/statements\/create-external-model-transact-sql?view=sql-server-ver17#api_format\" target=\"_blank\" rel=\"noreferrer noopener\">The official documentation is your primary source<\/a> for this. In our case, we are using the OpenAI format which is accepted by most AI tools and services, such as Cohere.<\/p>\n\n\n\n<p>The <code>LOCATION<\/code> parameter will depend on the <code>API_FORMAT<\/code>. In the case of OpenAI, it is the service URL. But in other formats, such as <a href=\"https:\/\/onnx.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">ONNX<\/a>, it is a directory where the files are located. Therefore, in these cases, it is always best to consult the documentation (and preferably keep an eye on the section on <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/statements\/create-external-model-transact-sql?view=sql-server-ver17#remarks\" target=\"_blank\" rel=\"noreferrer noopener\">remarks<\/a>).<\/p>\n\n\n\n<p><code>MODEL_TYPE<\/code> is the model type (of course). Remember our model definition? There are several types. For now, SQL Server only accepts <code>EMBEDDINGS<\/code> &#8211; however, it&#8217;s very likely that other models will be supported in future SQL updates or versions.<\/p>\n\n\n\n<p><code>MODEL<\/code> is the name of the model. Each AI provider may have several models, with various versions, costs, and quality. This parameter allows you to define which model name to use. In our case, we will use embed-v4.0, which is the most recent version from Cohere at the time this article was written. How do I know this? Cohere documentation: <a href=\"https:\/\/docs.cohere.com\/docs\/cohere-embed\" target=\"_blank\" rel=\"noreferrer noopener\">Cohere\u2019s Embed Models (Details and Application) | Cohere<\/a><\/p>\n\n\n\n<p>And finally we have the <code>CREDENTIAL<\/code> parameter which, just like you specified when directly invoking the API with <code>sp_invoke_external_rest_endpoint<\/code>, you need to specify here.<\/p>\n\n\n\n<p>Now that you have created the model, to use it you need the new function <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/functions\/ai-generate-embeddings-transact-sql?view=sql-server-ver17&amp;tabs=request-headers\" target=\"_blank\" rel=\"noreferrer noopener\"><code>AI_GENERATE_EMBEDDINGS<\/code><\/a>, where you specify the text and the model created with <code>CREATE EXTERNAL MODEL<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">SELECT\n    AI_GENERATE_EMBEDDINGS('Test direct from SQL Server' use model CohereTest)\n<\/pre><\/div>\n\n\n\n<p>Note that the name I passed there, <code>CohereTest<\/code>, is the same name I used when creating the external model via <code>CREATE EXTERNAL MODEL<\/code>. We can store this data in the new vector type:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">DECLARE\n    @embeddings vector(1536)\n\nset @embeddings =  AI_GENERATE_EMBEDDINGS('Test direct from SQL Server' use model CohereTest)\n\nselect @embeddings\n<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"299\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-17-1024x299.png\" alt=\"An image showing the data stored in the new vector type.\" class=\"wp-image-108270\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-17-1024x299.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-17-300x88.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-17-768x224.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-17.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Why did I use the value 1536? By default, the Cohere API generates embeddings with 1536 dimensions (read the article I pointed to about embeddings to understand what these dimensions are). We can control this quantity in several ways. You can change the default value of the <code>EXTERNAL MODEL<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">ALTER EXTERNAL MODEL CohereTest SET ( PARAMETERS = '{\"dimensions\": 256}' )<\/pre><\/div>\n\n\n\n<p>The <code>PARAMETERS<\/code> option allows you to specify a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/json-for-absolute-beginners-part-1-introduction\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSON<\/a> containing parameters that will be sent to the API. The supported value depends on each API, and thanks to the Cohere documentation, I know this. Now that I have changed the default parameter, if I repeat the same code above, this happens:<\/p>\n\n\n\n<p><strong>Msg 42204, Level 16, State 2, Line 69<br>The vector dimensions 1536 and 256 do not match.<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"353\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-18-1024x353.png\" alt=\"An image showing the error message displayed.\" class=\"wp-image-108271\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-18-1024x353.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-18-300x103.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-18-768x265.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-18.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now that we have altered the API, we need to adjust the value in the variable as well:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">DECLARE\n    @embeddings vector(256) -- changed (1536) to (256)\n\nset @embeddings =  AI_GENERATE_EMBEDDINGS('Test direct from SQL Server'  use model CohereTest)\n<\/pre><\/div>\n\n\n\n<p>And you can also adjust the parameter directly in the call to <code>AI_GENERATE_EMBEDDINGS<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">DECLARE\n    @embeddings vector(1024) -- vamos gerar agora embeddings de 1024 dimensoes\n\nset @embeddings =  AI_GENERATE_EMBEDDINGS('Test direct from SQL Server' use model CohereTest parameters convert(json,'{\"dimensions\": 1024}')  )\n<\/pre><\/div>\n\n\n\n<p>Note that I have now added the <code>PARAMETERS<\/code> option to <code>AI_GENERATE_EMBEDDINGS<\/code>. You need to pass a JSON type (hence the reason for converting it to the new JSON type, also added in SQL 2025).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Multiple Rows<\/h2>\n\n\n\n<p>For a more practical example, let&#8217;s create a script that generates the embeddings for 50 SQL Server <a href=\"https:\/\/www.red-gate.com\/simple-talk\/tag\/common-issues-in-sql-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">error messages<\/a> and stores them in a table (if you wish, you can adapt the script for another table of your preference, but remember that you are using a trial key and it has request limits):<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\ndrop table if exists #embeddings;\n\nselect top(50)\n\t text\n\t ,embeddings = convert(vector(256),AI_GENERATE_EMBEDDINGS(text use model CohereTest))\ninto\n\t#embeddings\nfrom\n\tsys.messages\n\nselect * from #embeddings;\n<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"745\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-19-1024x745.png\" alt=\"An image showing successful execution of the query.\" class=\"wp-image-108272\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-19-1024x745.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-19-300x218.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-19-768x559.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-19.png 1088w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note how you can use <code>AI_GENERATE_EMBEDDINGS<\/code> in places where any function is accepted. This makes the process much more flexible compared to using a procedure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-handling-errors-and-performance\">Handling Errors and Performance<\/h2>\n\n\n\n<p>Up until now, we have only worked with ideal and perfect cases. However, in the real world, the response won&#8217;t always be correct or fast like these examples. Therefore, I thought it prudent to present some scenarios so that you are prepared and know how to investigate.<\/p>\n\n\n\n<p>The first thing that can happen is errors. The API you choose to use can generate errors for various reasons: something wrong you passed, invalid or expired credentials, errors on the other side, the returned format not being what SQL Server expects, etc.<\/p>\n\n\n\n<p>For example, here&#8217;s the result returned with the HTTP 401 error, indicating authentication problems (which could be an incorrect or expired API key):<\/p>\n\n\n\n<p><strong>Msg 31742, Level 16, State 3, Line 77<br>Unrecoverable HTTP error 401 occurred.<\/strong><\/p>\n\n\n\n<p>Here is an error returned when a parameter specified in <code>PARAMETERS<\/code> is not accepted by the API:<\/p>\n\n\n\n<p><strong>Msg 31742, Level 16, State 3, Line 87<br>Unrecoverable HTTP error 422 occurred.<\/strong><\/p>\n\n\n\n<p>Note that the message will include the returned HTTP code. However, the API might return generic codes, such as 500. It is always best practice to consult the API documentation to understand what the returned code means. An important point is that the error codes above were returned by the Cohere API. Other providers may return different error codes, so it is always best to check the provider\u2019s API documentation to understand the codes it outputs and their meanings.<\/p>\n\n\n\n<p>SQL Server assumes that the API will return results in the same format it accepts according to the <code>API_FORMAT<\/code> parameter. For example, this is the error it generates when the result is not a valid JSON expected by the OpenAI format:<\/p>\n\n\n\n<p><strong>Msg 31744, Level 16, State 1, Line 87<br>The JSON path for embeddings could not be found in the response.<\/strong><\/p>\n\n\n\n<p>Another common scenario you will face is dealing with query performance. Invoking external services completely takes control away from SQL execution, and the only thing it has to do is wait. Therefore, in a scenario where you invoke it for every row in a table, you must be very careful. For one row, it&#8217;s fast, but for 10 rows, the time can change considerably. <\/p>\n\n\n\n<p>You can use the <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/system-dynamic-management-views\/sys-dm-exec-session-wait-stats-transact-sql?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\">DMV sys.dm_exec_sessions_wait_stats<\/a> and monitor the consumption of <code>AI_GENERATE_EMBEDDINGS<\/code>. For example, in the previous example we did with error messages, these were the session waits, ordered by what took the longest in total:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">select\n\t*\nfrom\n\tsys.dm_exec_session_wait_stats \nwhere\n\tsession_id = 58\norder by\n\twait_time_ms desc<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"231\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-20-1024x231.png\" alt=\"An image showing the session wait times.\" class=\"wp-image-108273\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-20-1024x231.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-20-300x68.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-20-768x173.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-20.png 1048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>What you primarily need to keep in mind is that using this within a transaction, for example, can cause many locks, especially if you are updating embeddings in a frequently altered table. You can use <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/temporary-tables-in-sql-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">temporary tables<\/a> to minimize the impact on concurrency. For example, suppose you want to update the embeddings of a products table. Instead of performing the update directly on the products table, you can use an auxiliary temporary table:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">drop table if exists #ProductsEmbeddings;\n\n-- get next set of rows to update!\nselect top 10\n\tProductId\n\t,ProductDescription\n\t,embeddings\ninto\n\t#ProductsEmbeddings\nfrom\n\tproducts_embeddings \nwhere\n\tembeddings is null\n\n-- generate the embeddings (locking just temporary rows)!\nupdate #ProductsEmbeddings\nset\n\tembeddingsembeddings = AI_GENERATE_EMBEDDINGS(ProductDescription use model CohereTest)\n\n-- Update back\nupdate p\nset \n\tembeddings = tp.embeddings\nfrom\n\t#ProductsEmbeddings tp\n\tjoin\n\tproducts_embeddings p\n\t\ton tp.ProductId = p.ProductId<\/pre><\/div>\n\n\n\n<p>A final, extremely valuable performance tip that can make a huge difference is sending a batch of embeddings. Many AI providers allow you to generate embeddings for multiple texts simultaneously, avoiding sending 1 HTTP request per row, which is the main bottleneck when using <code>AI_GENERATE_EMBEDDINGS<\/code>. <\/p>\n\n\n\n<p>The disadvantage is that your code might become more complex, but it can be very worthwhile if performance is crucial for you. For example, the code below shows a time comparison when generating embeddings for 50 error messages using row-by-row versus batch:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\ndrop table if exists #messages;\n\nselect top(50)\n\t id = row_number() over(order by (select null))\n\t,text = convert(nvarchar(max),text)\n\t,VectorSingle = convert(vector(1024),null)\n\t,VectorBatch = convert(vector(1024),null)\ninto\n\t#messages\nfrom\n\tsys.messages s\n\n\nselect * From #messages\n\n\n-- updating using row by row\n\tdeclare @Start datetime\n\t\tset @Start = getdate();\n\t\tupdate #Messages\n\t\tset\n\t\t\tVectorSingle = AI_GENERATE_EMBEDDINGS(text use model CohereTest parameters converT(json,'{\"dimensions\": 1024}') )\n\tselect ElapsedAiGenerated = datediff(ms,@Start,getdate())\nGO\n\n-- updating using batch\n\n\tdeclare @body nvarchar(max),@result nvarchar(max),@Start datetime\n\t\n\tselect \n\t\t@body = (\n\t\t\tselect \n\t\t\t\t input = JSON_QUERY(JSON_ARRAYAGG(text order by id))\n\t\t\t\t,model = 'embed-v4.0'\n\t\t\t\t,dimensions = 1024\n\t\t\tfor json path,without_array_wrapper\n\t\t)\n\tfrom #messages\n\n\tset @Start = getdate();\n\n\t\texec sp_invoke_external_rest_endpoint 'https:\/\/api.cohere.ai\/compatibility\/v1\/embeddings'\n\t\t,@payload = @body\n\t\t,@response = @result output\n\t\t,@credential = 'https:\/\/api.cohere.ai'\n\n\t\tdrop table if exists #embresult\n\t\tselect  \n\t\t\tr.[key],embeddings =JSON_QUERY(r.value,'$.embedding')\n\t\tinto\n\t\t\t#embresult\n\t\tfrom \n\t\t\topenjson(@result,'$.result.data') r\n\n\t\tupdate m\n\t\t\tset VectorBatch = embeddings\n\t\tfrom \n\t\t\t#embresult o\n\t\t\tjoin\n\t\t\t#Messages m\n\t\t\t\ton m.id = o.[key] + 1\n\n\tselect ElapsedBatched = datediff(ms,@Start,getdate())\n\n\nselect \n\t*\n\t,convert(decimal(30,29),VECTOR_DISTANCE('cosine',VectorSingle,VectorBatch))\nFrom \n\t#Messages<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"676\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-21-1024x676.png\" alt=\"An image showing the speed advantages of using batch.\" class=\"wp-image-108274\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-21-1024x676.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-21-300x198.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-21-768x507.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/01\/image-21.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>An absurd difference &#8211; from 12 seconds to 510 milliseconds using batch. However, as you can see, this method makes the code more complex. Hopefully, in future versions of SQL 2025 (or through updates), there will be an easier way to use batch mode.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">sp_AddEmbeddings<\/h4>\n\n\n\n<p>Until then, if you want an easier way, consider using this procedure I created: <a href=\"https:\/\/github.com\/rrg92\/sqlserver-lib\/blob\/main\/AI\/Embeddings\/sp_AddEmbeddings.sql\" target=\"_blank\" rel=\"noreferrer noopener\"><code>sp_AddEmbeddings<\/code><\/a>. By passing the table name and the model, it uses batching to generate the embeddings:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\ndrop table if exists #messages;\n\nselect top(50)\n\t id = row_number() over(order by (select null))\n\t,text = convert(nvarchar(max),text)\n\t,VectorBatch = convert(vector(1024),null)\ninto\n\t#messages\nfrom\n\tsys.messages s\n\ndeclare @Start datetime = getdate()\n\nexec sp_AddEmbeddings \n\t'#messages','text'\n\t,'openai'\n\t,@IdCol = 'id'\n\t,@model = 'CohereTest'\n\t,@IsExternal = 1\n\nselect ElapsedBatched = datediff(ms,@Start,getdate())\n\nselect * from #messages<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"779\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1024x779.png\" alt=\"An image showing the embeddings being created via batching.\" class=\"wp-image-108288\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1024x779.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-300x228.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-768x584.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><code>sp_AddEmbeddings<\/code> allows you to generate embeddings into a vector column, using a model you specify in the parameter and AI providers. You need to create both <code>sp_AddEmbeddings<\/code> and the respective provider procedure, for which I left three examples of <a href=\"https:\/\/github.com\/rrg92\/sqlserver-lib\/tree\/main\/AI\/Embeddings\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a> (scripts spAddemb.*.sql).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Metadata<\/h2>\n\n\n\n<p>Just like other objects you create, the <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/system-catalog-views\/sys-external-models-transact-sql?view=sql-server-ver17\">sys.external_model<\/a><a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/system-catalog-views\/sys-external-models-transact-sql?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\">s<\/a> view returns all models created with <code>CREATE EXTERNAL MODEL<\/code>. This way, you can query the current models and options.<\/p>\n\n\n\n<p>For example, <a href=\"https:\/\/github.com\/rrg92\/sqlserver-lib\/blob\/main\/AI\/ExternalModel\/InstanceModels.sql\" target=\"_blank\" rel=\"noreferrer noopener\">this script that I made available for free in my Git repository<\/a> uses <code>sys.external_models<\/code> to list the models created in all databases. This can be useful if you need to view something quickly:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"398\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1-1024x398.png\" alt=\"Image showing how using sys.external_models is useful if you need to view something quickly.\" class=\"wp-image-108289\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1-1024x398.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1-300x117.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1-768x299.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-1.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">ONNX<\/h2>\n\n\n\n<p>Now that you know how to connect your SQL to an AI model via an HTTP API, I will show you another way, which is not via HTTP but via a DLL, and the model will run directly on the same SQL Server machine. This is a useful scenario for environments that have strict data processing policies, cannot use external services like the ones we used, and need to process locally. This method uses <a href=\"https:\/\/onnx.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">ONNX.<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is ONNX?<\/h3>\n\n\n\n<p>AI models are like an audio file, for example an .mp3. There are several programs that can play an MP3, which is an open format that anyone can read and reproduce. With AI models, we have the same scenario. The basis is neural networks that have a standard and format, and the values of the hundreds of thousands of parameters found during training.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/onnxruntime.ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">ONNX<\/a>(<strong>O<\/strong>pen <strong>N<\/strong>eural <strong>N<\/strong>etwork E<strong>X<\/strong>change), which is <a href=\"https:\/\/azure.microsoft.com\/en-us\/blog\/onnx-runtime-is-now-open-source\" target=\"_blank\" rel=\"noreferrer noopener\">open source and was created by Microsoft, Facebook, and AWS<\/a>, defines exactly how the binary of these networks should be saved and can be read for processing. To note, there are other formats as well &#8211; such as GGUF, SafeTensors, etc. See <a href=\"https:\/\/huggingface.co\/blog\/ngxson\/common-ai-model-formats\" target=\"_blank\" rel=\"noreferrer noopener\">this post on Hugging Face<\/a> for more.<\/p>\n\n\n\n<p>As I mentioned, ONNX defines the format, which means you need software capable of &#8216;opening&#8217; and executing that format. ONNX models have the onnx extension. To <em>\u201copen and execute\u201d<\/em> these files, you need ONNX Runtime &#8211; software (or a library) with all the ONNX logic implemented. This runtime is available for <a href=\"https:\/\/onnxruntime.ai\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">various languages<\/a> but for SQL Server, we&#8217;ll use the runtime created for Windows, which is made available as a DLL, on its GitHub: <a href=\"https:\/\/github.com\/microsoft\/onnxruntime\/releases\" target=\"_blank\" rel=\"noreferrer noopener\">Releases \u00b7 microsoft\/onnxruntime<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"432\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-2-1024x432.png\" alt=\"Image showing how ONNX works\" class=\"wp-image-108290\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-2-1024x432.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-2-300x127.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-2-768x324.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-2.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In the case of SQL Server, Microsoft followed the same security standard as other services, such as Full Text Search or the execution of external scripts: the ONNX Runtime DLL is not loaded into sqlservr.exe, but rather into Launchpad.exe, which is started by the <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/machine-learning\/security\/sql-server-launchpad-service-account?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\">LaunchPad service<\/a> (formerly Machine Learning Services, used to run Python and R code.) The reason is simple: if there are any issues with the runtime, it does not stop the entire SQL database &#8211; only the runtime process suffers the consequences.<\/p>\n\n\n\n<section id=\"my-first-block-block_097ccfde20a9ee6a828940060c24fd38\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Enjoying this article? Subscribe to the Simple Talk newsletter<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Get selected articles, event information, podcasts and other industry content delivered straight to your inbox.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/simple-talk\/subscribe\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Subscribe: Enjoying this article? Subscribe to the Simple Talk newsletter\">Subscribe<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<h3 class=\"wp-block-heading\">Using the ONNX Runtime<\/h3>\n\n\n\n<p>Now that you have the background on what ONNX is and an idea of how it works, we can see this in practice. To use ONNX in SQL Server, firstly install Launchpad (if you haven&#8217;t already), by opening the same SQL installer, choosing <em>add features to existing<\/em>, and checking the option <em>Ai Services and Language Extensions:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"654\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-3-1024x654.png\" alt=\"Image showing how to install Launchpad to use ONNX in SQL Server\" class=\"wp-image-108291\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-3-1024x654.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-3-300x192.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-3-768x490.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-3.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Once installed, make sure it&#8217;s been started in <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/tools\/configuration-manager\/sql-server-configuration-manager?view=sql-server-ver17\" target=\"_blank\" rel=\"noreferrer noopener\">SQL Configuration Manager:<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"88\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-4-1024x88.png\" alt=\"An image showing SQL Server Launchpad running in SQL Server Configuration Manager.\" class=\"wp-image-108292\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-4-1024x88.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-4-300x26.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-4-768x66.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-4.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note the account name under \u201cLog On As\u201d &#8211; we will need it later.<\/p>\n\n\n\n<p>Now, let&#8217;s install the runtime:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>First, choose a directory of your preference on the machine where your SQL Server is located. For this post, I will use C:\\onnx as an example. It probably doesn&#8217;t exist, so create it.<br><br><\/li>\n\n\n\n<li>Create the following subdirectories:<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>C:\\onnx\\cpu<br>Here we will place the DLLs that will be loaded<\/li>\n\n\n\n<li>C:\\onnx\\models<br>Here we will place the binaries of the AI models that will generate the embeddings<br><br><\/li>\n<\/ul>\n<\/div><\/li>\n\n\n\n<li>Download <a href=\"https:\/\/github.com\/microsoft\/onnxruntime\/releases\/download\/v1.23.2\/onnxruntime-win-x64-1.23.2.zip\" target=\"_blank\" rel=\"noreferrer noopener\">this zip<\/a>, extract and copy only the file in lib\/onnxrutime.dll to C:\\onnx\\cpu. If the direct link to the zip does not work, see the latest version here:&nbsp;<a href=\"https:\/\/github.com\/microsoft\/onnxruntime\/releases\" target=\"_blank\" rel=\"noreferrer noopener\">Releases \u00b7 microsoft\/onnxruntime<\/a>. The important thing is to get the DLL mentioned above and place it in the C:\\onnx\\cpu directory.<br><br><\/li>\n\n\n\n<li>Now, <a href=\"https:\/\/github.com\/PARTHSQL\/tokenizers-cpp\/releases\/download\/v0.1.1\/tokenizers_cpp-release.dll\" target=\"_blank\" rel=\"noreferrer noopener\">Download the tokenizer-cpp.dll<\/a> and also place it in C:\\onnx\\cpu<br>This library is not part of ONNX, but it is important for use with models that involve text processing, which is the case for the embedding models we will use here. It helps convert text into tokens, and vice versa. Embedding models receive tokens and generate tokens, and tokenizers are the ones that help convert these tokens back into text, or the text into tokens.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>You&#8217;ll end up with a structure like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"663\" height=\"261\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-5.png\" alt=\"Image showing the structure you will end up with.\" class=\"wp-image-108293\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-5.png 663w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-5-300x118.png 300w\" sizes=\"auto, (max-width: 663px) 100vw, 663px\" \/><\/figure>\n\n\n\n<p>Now, to ensure the Launchpad service can access the directory, adjust the service account permissions on the C:\\onnx directory. Grant permissions to the Launchpad service user, as you observed earlier. In my case, it looked like this (it only worked with Full Control):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"783\" height=\"845\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-6.png\" alt=\"Image showing Launchpad with permissions granted in the ONNX directory.\" class=\"wp-image-108294\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-6.png 783w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-6-278x300.png 278w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-6-768x829.png 768w\" sizes=\"auto, (max-width: 783px) 100vw, 783px\" \/><\/figure>\n\n\n\n<p>Note that I only needed to grant permission on root C:\\onnx and, thanks to the NTFS inheritance feature, the subdirectories and files received the same permission.<\/p>\n\n\n\n<p>At this point, your ONNX runtime is ready. Now, we need an ONNX model. I will show you using two examples: the <a href=\"https:\/\/huggingface.co\/onnx-models\/all-MiniLM-L6-v2-onnx\" target=\"_blank\" rel=\"noreferrer noopener\">all-MiniLM-L6-v2-onnx<\/a> (the same one used in the <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/create-embeddings-in-sql-server-2025-rc0-with-a-local-onnx-model-on-windows\/\" target=\"_blank\" rel=\"noreferrer noopener\">official post<\/a>) and one from MixedBread AI, the&nbsp;<a href=\"https:\/\/huggingface.co\/mixedbread-ai\/mxbai-embed-xsmall-v1\" target=\"_blank\" rel=\"noreferrer noopener\">mixedbread-ai\/mxbai-embed-xsmall-v1 \u00b7 Hugging Face<\/a>, which is not officially mentioned but I tested and it works. <\/p>\n\n\n\n<p>There&#8217;s a small difference in the second example, and it&#8217;ll be useful to learn a bit more about this &#8211; but first, before we continue, <a href=\"https:\/\/git-scm.com\/install\/windows\" target=\"_blank\" rel=\"noreferrer noopener\">install git <\/a>if you haven&#8217;t already, to download the models from Hugging Face. Once installed, make sure it&#8217;s working correctly by opening a new command prompt or <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/\" target=\"_blank\" rel=\"noreferrer noopener\">PowerShell<\/a> session and typing \u201cgit\u201d. A &#8216;help&#8217; message should display &#8211; if not, review the installation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"382\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-7-1024x382.png\" alt=\"An image showing the installation.\" class=\"wp-image-108295\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-7-1024x382.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-7-300x112.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-7-768x287.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-7.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Using the all-MiniLM-L6-v2-onnx model<\/h4>\n\n\n\n<p>To download the model, open a command prompt or PowerShell and run these commands:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">cd C:\\onnx\\models\ngit clone https:\/\/huggingface.co\/nsense\/all-MiniLM-L6-v2-onnx<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"427\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-8-1024x427.png\" alt=\"An image showing the commands being run.\" class=\"wp-image-108296\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-8-1024x427.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-8-300x125.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-8-768x320.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-8.png 1061w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>This may take a few seconds or minutes. Upon completion, you will have this structure in C:\\onnx\\models:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"419\" height=\"211\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-9.png\" alt=\"An image showing the structure.\" class=\"wp-image-108297\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-9.png 419w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-9-300x151.png 300w\" sizes=\"auto, (max-width: 419px) 100vw, 419px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"439\" height=\"463\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-10.png\" alt=\"Another image showing the structure.\" class=\"wp-image-108298\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-10.png 439w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-10-284x300.png 284w\" sizes=\"auto, (max-width: 439px) 100vw, 439px\" \/><\/figure>\n\n\n\n<p>In this directory, there are various files containing the model&#8217;s \u201csource code\u201d in several formats, such as safetensors and onnx. Additionally, there are other metadata and configuration files, such as tokenizers.json. All we need to do now is point this out in SQL Server. First, let&#8217;s enable two features:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\nif exists(select * from sys.external_models where name = 'MiniLMv2')\n\tdrop external model [MiniLMv2];\n\nCREATE EXTERNAL MODEL [MiniLMv2]\nWITH (\n\tLOCATION = 'C:\\onnx\\models\\all-MiniLM-L6-v2-onnx',\n\tAPI_FORMAT = 'ONNX Runtime',\n\tMODEL_TYPE = EMBEDDINGS,\n\tMODEL = 'all-MiniLM-L6-v2-onnx',\n\tPARAMETERS = '{\"valid\":\"JSON\"}',\n\tLOCAL_RUNTIME_PATH = 'C:\\onnx\\cpu'\n);\n\n\nselect AI_GENERATE_EMBEDDINGS('test' use model [MiniLMv2])<\/pre><\/div>\n\n\n\n<p>Note that in <code>LOCATION<\/code>, you point to the model directory. For <code>API_FORMAT<\/code>, use ONNX Runtime. For <code>MODEL<\/code>, you can repeat the same name as the model, which is the same name as the directory. In parameters, include the JSON {\u201cvalid\u201d:\u201dJSON\u201d} and a new parameter we haven&#8217;t used yet: <code>LOCAL_RUNTIME_PATH<\/code>, where you specify where the ONNX runtime DLLs are located (in our case, they are in C:\\onnx\\cpu).<\/p>\n\n\n\n<p>Now, use <code>AI_GENERATE_EMBEDDINGS<\/code> as you have seen previously:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"237\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-11-1024x237.png\" alt=\"Image showing the use of AI_GENERATE_EMBEDDINGS like previously.\" class=\"wp-image-108299\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-11-1024x237.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-11-300x69.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-11-768x178.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-11.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>However, the following error will be returned if you don&#8217;t enable some particular options:<\/p>\n\n\n\n<p><strong>Msg 31733, Level 16, State 1, Line 27<br>The \u2018ai_generate_embeddings\u2019 with Local ONNX provider is not enabled.<\/strong><\/p>\n\n\n\n<p>The options you need to enable are:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">USE AiTests\nGO\n\n-- need enable server level (sysadmin)\nEXEC sp_configure 'external AI runtimes enabled', 1;\nRECONFIGURE WITH OVERRIDE;\n\n-- need enable preview features (db_owner)\nALTER DATABASE SCOPED CONFIGURATION SET PREVIEW_FEATURES = ON;<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"237\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-12-1024x237.png\" alt=\"An image showing the options you need to enable.\" class=\"wp-image-108302\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-12-1024x237.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-12-300x69.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-12-768x178.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-12.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>When you use <code>AI_GENERATE_EMBEDDINGS<\/code> referencing this model, SQL will now communicate with the launchpad, which will load the runtime, and the model, and execute the process &#8211; returning the embeddings. All this runs on the same server as your SQL (but in separate processes). <\/p>\n\n\n\n<p>To demonstrate this, using <a href=\"https:\/\/github.com\/ErikEJ\/SqlQueryStress\" target=\"_blank\" rel=\"noreferrer noopener\">SQLQueryStress<\/a> I monitored the CPU consumption of both processes: Launchpad (blue) and the SQL instance (red). During the stress test, the blue line (Launchpad) is the one that spikes:<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"600\" style=\"aspect-ratio: 1236 \/ 600;\" width=\"1236\" controls src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/video1.mp4\"><\/video><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Using the mxbai-embed-xsmall-v1 model<\/h4>\n\n\n\n<p>Now let&#8217;s test another model, different from the one mentioned in the official post: <a href=\"https:\/\/huggingface.co\/mixedbread-ai\/mxbai-embed-xsmall-v1\" target=\"_blank\" rel=\"noreferrer noopener\">mxbai-embed-xsmall-v1<\/a>, a model I&#8217;ve never seen mentioned anywhere as an example for use with SQL Server &#8211; so we&#8217;ll probably be the first ones here. <\/p>\n\n\n\n<p>We&#8217;ll basically repeat the same steps &#8211; first, open a command prompt and run it (it might take a few minutes):<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">cd C:\\onnx\\models\ngit clone https:\/\/huggingface.co\/mixedbread-ai\/mxbai-embed-xsmall-v1\n<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"396\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-13-1024x396.png\" alt=\"The command prompt after being run\" class=\"wp-image-108304\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-13-1024x396.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-13-300x116.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-13-768x297.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-13.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>You&#8217;ll now have this in C:\\onnx\\models:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"573\" height=\"225\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-14.png\" alt=\"\" class=\"wp-image-108305\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-14.png 573w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-14-300x118.png 300w\" sizes=\"auto, (max-width: 573px) 100vw, 573px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"456\" height=\"658\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-15.png\" alt=\"An image showing what will display.\" class=\"wp-image-108306\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-15.png 456w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-15-208x300.png 208w\" sizes=\"auto, (max-width: 456px) 100vw, 456px\" \/><\/figure>\n\n\n\n<p>Now, let&#8217;s try creating it in SQL:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:tsql decode:true \">if exists(select * from sys.external_models where name = 'MxbaiXSmall')\n\tdrop external model [MxbaiXSmall];\n\nCREATE EXTERNAL MODEL MxbaiXSmall\nWITH (\n\tLOCATION = 'C:\\onnx\\models\\mxbai-embed-xsmall-v1',\n\tAPI_FORMAT = 'ONNX Runtime',\n\tMODEL_TYPE = EMBEDDINGS,\n\tMODEL = 'mxbai-embed-xsmall-v1',\n\tPARAMETERS = '{\"valid\":\"JSON\"}',\n\tLOCAL_RUNTIME_PATH = 'C:\\onnx\\cpu'\n);\n\n\nselect AI_GENERATE_EMBEDDINGS('test' use model MxbaiXSmall)<\/pre><\/div>\n\n\n\n<p>When trying to run the <code>SELECT<\/code> statement, you will receive this error:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"194\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-16-1024x194.png\" alt=\"The error you'll receive when trying to run the SELECT statement\" class=\"wp-image-108307\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-16-1024x194.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-16-300x57.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-16-768x145.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-16.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><strong>Msg 31739, Level 17, State 1, Line 45<br>Generating embeddings from \u2018AIRuntimeHost\u2019 process with session ID \u2018B9806BB6-14C4-468F-AC15-AF73284AC936\u2019 failed with HRESULT 0x80004004.<\/strong><\/p>\n\n\n\n<p>It is a generic error, as the Launchpad failed somehow and SQL only reports the failure without further details. However, in this case, I know that something more is missing for this model:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"649\" height=\"945\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-17.png\" alt=\"\" class=\"wp-image-108308\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-17.png 649w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-17-206x300.png 206w\" sizes=\"auto, (max-width: 649px) 100vw, 649px\" \/><\/figure>\n\n\n\n<p>Note that there is no model.onnx file in the directory, unlike the previous one. It is in the \u201connx\u201d directory. Copy it to the root, as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"436\" height=\"752\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-19.png\" alt=\"An image showing how to copy the model.onnx file to the root.\" class=\"wp-image-108310\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-19.png 436w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-19-174x300.png 174w\" sizes=\"auto, (max-width: 436px) 100vw, 436px\" \/><\/figure>\n\n\n\n<p>Now, try again &#8211; and that&#8217;s it! With this, we can confirm that using ONNX Runtime expects a model.onnx file to be present in the directory so the launchpad can load it correctly.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"287\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-20-1024x287.png\" alt=\"An image showing that ONNX Runtime expects a model.onnx file to be present in the directory so the launchpad can load it correctly.\" class=\"wp-image-108311\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-20-1024x287.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-20-300x84.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-20-768x216.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2026\/02\/image-20.png 1090w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And there you have it! Another model loaded directly into the server&#8217;s memory, generating embeddings!<\/p>\n\n\n\n<p><a href=\"https:\/\/huggingface.co\/models?pipeline_tag=feature-extraction&amp;library=onnx&amp;other=text-embeddings-inference&amp;sort=trending\" target=\"_blank\" rel=\"noreferrer noopener\">Here is a filter<\/a> I usually use to find ONNX models on Hugging Face, but not all ONNX models will work with SQL. At the time of writing, there&#8217;s nothing officially documented by Microsoft about exactly which ONNX models from Hugging Face work with SQL. In some tests, I noticed that the model structure (inputs and outputs) must be specific, but, as I said, this is based on my observations and is not official. While we don&#8217;t have official documentation, you can use this space I created to check what I have already tested and for some updates:&nbsp;<a href=\"https:\/\/huggingface.co\/spaces\/sql-server\/onnx-check\">SQL ONNX Info \u2013 a Hugging Face Space by sql-server<\/a><\/p>\n\n\n\n<p><em>Suggestion for the MS and Hugging Face teams: create a \u201csql-server\u201d or \u201cmssql\u201d tag so we can filter models compatible with SQL Server directly from Hugging Face Hub UI. That would make things much easier, wouldn&#8217;t it?<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-conclusion-amp-next-steps\">Conclusion &amp; Next Steps<\/h2>\n\n\n\n<p>Before wrapping up, the question you might have is: when should I use ONNX and when should I use an external API? Will using ONNX compromise and compete with the machine&#8217;s memory and CPU resources, potentially disrupting SQL?<\/p>\n\n\n\n<p>And the simplest answer is (as with everything): it depends. ONNX is especially useful if your company&#8217;s data processing policy is so strict that you cannot even take the data out of the SQL server, so it becomes an option for you to use AI while keeping the data inside the server. Using external APIs is more flexible, from my point of view, but it might run into those kinds of security issues. There is also the option of using <a href=\"https:\/\/ollama.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Ollama<\/a>, but you would probably have to move the data to another server as well, and you might run into those security issues. Ultimately, I would summarize it like this:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>If you are starting out and testing, and security policies permit it, start with external APIs. Test them, see how they work with your data and which best options yield a good result.<br><br><\/li>\n\n\n\n<li>Consider moving to more complex options, such as Ollama or ONNX, if your company&#8217;s security policies demand a higher level of data protection. You will need to engage with your security team to discuss this and verify if reaching this level of complexity is necessary (and if it satisfies the requirements).<\/li>\n<\/ul>\n<\/div>\n\n\n<p>The fact is that SQL 2025 introduced a new command with various options, allowing you to finally invoke AI models to generate embeddings and assist in routines involving text search and comparison, all from within your SQL Server using simple T-SQL. This can be a huge leap for your applications and business.<\/p>\n\n\n\n<p>Thank you very much for reading, and if you have any questions, just leave a comment. I will continue studying and applying the new AI features in SQL, introducing you to them on Simple Talk along the way!<a href=\"https:\/\/huggingface.co\/spaces\/sql-server\/onnx-check\" target=\"_blank\" rel=\"noreferrer noopener\"><br><\/a><a href=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2026\/01\/image-17.png\"><\/a><\/p>\n\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>Frequently Asked Questions<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. What is CREATE EXTERNAL MODEL in SQL Server 2025?<\/h3>\n            <div class=\"faq-answer\">\n                <p><code data-start=\"685\" data-end=\"708\">CREATE EXTERNAL MODEL<\/code> is a new SQL Server 2025 command that registers an external AI model for use inside SQL Server. Instead of hosting the model itself, SQL Server stores connection metadata such as the model endpoint, API format, authentication credentials, and model name. This allows SQL Server to securely call external AI services for tasks like generating vector embeddings.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. What does \u201cexternal AI model\u201d mean in SQL Server?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"1135\" data-end=\"1439\">An external AI model is any AI model that runs outside SQL Server but can be accessed through an API. This includes cloud-hosted models, on-premises services, containerized models, or local runtimes. SQL Server uses the model\u2019s API to send input data and receive AI-generated results, such as embeddings.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. Which AI model types are supported in SQL Server 2025?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"1510\" data-end=\"1791\">SQL Server 2025 currently supports <code>EMBEDDINGS<\/code> models. These models convert text into numerical vectors that represent semantic meaning. Vector embeddings are the foundation for AI use cases such as semantic search, similarity matching, and retrieval-augmented generation (RAG).<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. What is the AI_GENERATE_EMBEDDINGS function used for?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"1863\" data-end=\"2171\"><code data-start=\"1863\" data-end=\"1887\">AI_GENERATE_EMBEDDINGS<\/code> is a T-SQL function that calls a registered external AI model to generate vector embeddings from input text. The function returns a vector representation of the text, which can be stored in a <code data-start=\"2080\" data-end=\"2088\">VECTOR<\/code> column and later used for similarity comparisons or semantic search in SQL Server.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">5. How do I configure an external AI model in SQL Server?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"2242\" data-end=\"2286\">When creating an external model, you define:<\/p>\n<ul data-start=\"2287\" data-end=\"2420\">\n<li data-start=\"2287\" data-end=\"2318\">\n<p data-start=\"2289\" data-end=\"2318\">The model endpoint location<\/p>\n<\/li>\n<li data-start=\"2319\" data-end=\"2355\">\n<p data-start=\"2321\" data-end=\"2355\">The API format used by the model<\/p>\n<\/li>\n<li data-start=\"2356\" data-end=\"2385\">\n<p data-start=\"2358\" data-end=\"2385\">The model name or version<\/p>\n<\/li>\n<li data-start=\"2386\" data-end=\"2420\">\n<p data-start=\"2388\" data-end=\"2420\">Credentials for authentication<\/p>\n<\/li>\n<\/ul>\n<p data-start=\"2422\" data-end=\"2548\">This configuration enables SQL Server to securely communicate with the AI model whenever <code data-start=\"2511\" data-end=\"2535\">AI_GENERATE_EMBEDDINGS<\/code> is executed.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">6. Does SQL Server generate embeddings internally?<\/h3>\n            <div class=\"faq-answer\">\n                <p>No. SQL Server does not generate embeddings itself. Instead, it sends requests to an external AI model and processes the returned embeddings. This approach allows SQL Server to integrate with a wide range of AI platforms while keeping AI workloads decoupled from the database engine.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">7. How are embeddings stored in SQL Server 2025?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"2957\" data-end=\"3210\">Embeddings are stored using the <strong data-start=\"2989\" data-end=\"2999\">VECTOR<\/strong> data type introduced in SQL Server 2025. Vector columns are designed to hold high-dimensional numeric data and can be queried using vector distance functions to support similarity search and AI-driven querying.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">8. What can I do with vector embeddings in SQL Server?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"3278\" data-end=\"3317\">Once stored, embeddings can be used to:<\/p>\n<ul data-start=\"3318\" data-end=\"3555\">\n<li data-start=\"3318\" data-end=\"3360\">\n<p data-start=\"3320\" data-end=\"3360\">Perform semantic search over text data<\/p>\n<\/li>\n<li data-start=\"3361\" data-end=\"3420\">\n<p data-start=\"3363\" data-end=\"3420\">Find similar records using vector distance calculations<\/p>\n<\/li>\n<li data-start=\"3421\" data-end=\"3482\">\n<p data-start=\"3423\" data-end=\"3482\">Rank results by meaning rather than exact keyword matches<\/p>\n<\/li>\n<li data-start=\"3483\" data-end=\"3555\">\n<p data-start=\"3485\" data-end=\"3555\">Support AI patterns such as recommendation systems and RAG pipelines<\/p>\n<\/li>\n<\/ul>\n<p data-start=\"3557\" data-end=\"3619\">These capabilities bring modern AI search directly into T-SQL.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">9. Where can the external AI models be hosted?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"3679\" data-end=\"3748\">External AI models can be hosted in multiple environments, including:<\/p>\n<ul data-start=\"3749\" data-end=\"3832\">\n<li data-start=\"3749\" data-end=\"3771\">\n<p data-start=\"3751\" data-end=\"3771\">Cloud AI platforms<\/p>\n<\/li>\n<li data-start=\"3772\" data-end=\"3795\">\n<p data-start=\"3774\" data-end=\"3795\">On-premises servers<\/p>\n<\/li>\n<li data-start=\"3796\" data-end=\"3810\">\n<p data-start=\"3798\" data-end=\"3810\">Containers<\/p>\n<\/li>\n<li data-start=\"3811\" data-end=\"3832\">\n<p data-start=\"3813\" data-end=\"3832\">Local AI runtimes<\/p>\n<\/li>\n<\/ul>\n<p data-start=\"3834\" data-end=\"3941\">As long as SQL Server can reach the model through a supported API, it can be used for embedding generation.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">10. Do I need API or REST knowledge to use these features?<\/h3>\n            <div class=\"faq-answer\">\n                <p data-start=\"4012\" data-end=\"4247\">Basic knowledge of REST APIs and authentication is helpful. Since SQL Server communicates with AI models via APIs, understanding endpoints, credentials, and request formats makes it easier to configure and troubleshoot external models.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Learn about the new CREATE EXTERNAL MODEL and AI_GENERATE_EMBEDDINGS commands in SQL Server 2025.&hellip;<\/p>\n","protected":false},"author":170434,"featured_media":108032,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143523,53,143524],"tags":[4168,4170,4150,4151,159319],"coauthors":[21049],"class_list":["post-108262","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-databases","category-featured","category-sql-server","tag-database","tag-database-administration","tag-sql","tag-sql-server","tag-sqlserver2025publicpreview"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/108262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/170434"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=108262"}],"version-history":[{"count":8,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/108262\/revisions"}],"predecessor-version":[{"id":108322,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/108262\/revisions\/108322"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/108032"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=108262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=108262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=108262"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=108262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}