{"id":2200,"date":"2023-06-04T11:24:16","date_gmt":"2023-06-04T18:24:16","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=2200"},"modified":"2024-11-12T08:55:14","modified_gmt":"2024-11-12T16:55:14","slug":"vector-similarity-search-with-azure-sql-database-and-openai","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/vector-similarity-search-with-azure-sql-database-and-openai\/","title":{"rendered":"Vector Similarity Search with Azure SQL database and OpenAI"},"content":{"rendered":"<h2>Latest update &#8211; 06 November 2024<\/h2>\n<p>Vector Support is now available as Public Preview! Read the announcement here: <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/exciting-announcement-public-preview-of-native-vector-support-in-azure-sql-database\/\">Public Preview of Native Vector Support in Azure SQL Database!<\/a> Access to full documentation here: <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/t-sql\/functions\/vector-functions-transact-sql?view=azuresqldb-current\">Vector functions<\/a>.<\/p>\n<h2>Vectors and Embeddings<\/h2>\n<p class=\"graf graf--p\">Vector databases are gaining quite a lot of interest lately. Using text embeddings and vector operations makes extremely easy to find similar \u201cthings\u201d. Things can be articles, photos, products&#8230;everything. As one can easily imagine, this ability is great to easily implement suggestions in applications. From providing suggestions on similar articles or other products that may be of interest, to quickly finding and grouping similar items, the applications are many.<\/p>\n<p>A great article to understand how embeddings work, is the following: <a href=\"https:\/\/openai.com\/blog\/introducing-text-and-code-embeddings\">Introducing text and code embeddings<\/a>.<\/p>\n<p>Reading the mentioned articles, you can learn that &#8220;embeddings are numerical representations of concepts converted to number sequences, which make it easy for computers to understand the relationships between those concepts.&#8221;<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/text-embeddings.png\" alt=\"text embeddings\" \/><\/p>\n<p>More specifically, embeddings are <em>vectors<\/em>&#8230;hence the great interest for vector databases.<\/p>\n<p>But are vector databases really needed? At the end of the day a vector is just a list of numbers and finding if two vectors represent similar object is as easy as calculating the <em>distance<\/em> between the vectors. One of the most common and useful distance metric is the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cosine_similarity#Cosine_Distance\">cosine distance<\/a> and, even better, the related <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cosine_similarity\/\">cosine similarity<\/a><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/cosine-distance.png\" alt=\"cosine distance\" \/><\/p>\n<p>The real complex part is calculating the embeddings, but thanks to Azure OpenAI, everyone has an easily accessible REST service that can used to get the embeddings using pre-trained ML models. In this article we will use <a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/cognitive-services\/openai\/concepts\/models#embeddings-models\">OpenAI to generate vectors for doing similarity search<\/a> and then use Azure SQL database to store and search for similar vectors.<\/p>\n<p>In this article we&#8217;ll build a sample solution to find Wikipedia articles that are related to any topic we may be interested in. As usual all the code is available in GitHub:<\/p>\n<p><a href=\"https:\/\/github.com\/Azure-Samples\/azure-sql-db-openai\">https:\/\/github.com\/Azure-Samples\/azure-sql-db-openai<\/a><\/p>\n<p>The pre-calculated embeddings, both for the title and the body, of a selection of Wikipedia articles, is made available by OpenAI here:<\/p>\n<p><a href=\"https:\/\/cdn.openai.com\/API\/examples\/data\/vector_database_wikipedia_articles_embedded.zip\">https:\/\/cdn.openai.com\/API\/examples\/data\/vector_database_wikipedia_articles_embedded.zip<\/a><\/p>\n<h2>Vectors in Azure SQL database<\/h2>\n<p>Vectors can be efficiently stored in Azure SQL database by <a href=\"https:\/\/learn.microsoft.com\/sql\/relational-databases\/indexes\/columnstore-indexes-overview?view=sql-server-ver16\">columnstore indexes<\/a>. There is no specific data type available to store a vector in Azure SQL database, but we can use some human ingenuity to realize that a vector is just a list of numbers. As a result, we can store a vector in a table very easily by creating a column to contain vector data. One row per vector element. We can then use a columnstore index to efficiently store and search for vectors.<\/p>\n<p>Using this Wikipedia article as starting point, you can see that there are two vectors, one to store title embeddings and one to store article embeddings:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341.png\"><img decoding=\"async\" class=\"alignnone wp-image-2206 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341.png\" alt=\"Image Screenshot 2023 06 03 164341\" width=\"1274\" height=\"87\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341.png 1274w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341-300x20.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341-1024x70.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/Screenshot-2023-06-03-164341-768x52.png 768w\" sizes=\"(max-width: 1274px) 100vw, 1274px\" \/><\/a><\/p>\n<p>The vectors can be more efficiently stored into a table like this:<\/p>\n<pre><code class=\"language-sql\">CREATE TABLE [dbo].[wikipedia_articles_embeddings_titles_vector]\r\n(\r\n    [article_id] [int] NOT NULL,\r\n    [vector_value_id] [int] NOT NULL,\r\n    [vector_value] [float] NOT NULL\r\n) \r\nGO<\/code><\/pre>\n<p>On that table we can create a column store index to efficiently store and search for vectors. Then it is just a matter of calculating the distance between vectors to find the closest. Thanks to the internal optimization of the columnstore (that uses <a href=\"https:\/\/en.wikipedia.org\/wiki\/Single_instruction,_multiple_data\">SIMD<\/a> <a href=\"https:\/\/www.intel.com\/content\/www\/us\/en\/architecture-and-technology\/avx-512-overview.html\">AVX-512 instructions<\/a> to speed up vector operations) the distance calculation is extremely fast.<\/p>\n<p>The most common distance is the cosine similarity, which can be calculated quite easily in SQL.<\/p>\n<h2>Calculating cosine similarity<\/h2>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Cosine_similarity\">Cosine similarity<\/a> can be calculated in SQL using the following formula, given two vectors <code>a<\/code> and <code>b<\/code>:<\/p>\n<pre><code class=\"language-sql\">SELECT \r\n    SUM(a.value * b.value) \/ (  \r\n        SQRT(SUM(a.value * a.value)) * SQRT(SUM(b.value * b.value))   \r\n    ) AS cosine_similarity\r\nFROM\r\n    vectors_values<\/code><\/pre>\n<p>Really easy. What is now left to do is to query the Azure OpenAI REST service so that, given any text, we can get the vector representation of that text. Then we can use that vector to calculate the cosine distance against <em>all<\/em> the wikipedia articles stored in the database and take only the closest ones which will return the article most likely connect to the topic we are interested in.<\/p>\n<h2>Querying OpenAI<\/h2>\n<p>Create an Azure OpenAI resource via the Azure portal. For this specific sample you have to deploy an Embedding model using the <code>text-embedding-ada-002<\/code> model, the same used for the Wikipedia articles source we are using in this sample. Once that is done, you need to get the API KEY and the URL of the deployed model (read the <a href=\"https:\/\/learn.microsoft.com\/azure\/cognitive-services\/openai\/reference#embeddings\">Embeddings REST API<\/a> documentation) and then you can use <a href=\"https:\/\/learn.microsoft.com\/sql\/relational-databases\/system-stored-procedures\/sp-invoke-external-rest-endpoint-transact-sql?view=azuresqldb-current\">sp_invoke_external_rest_endpoint<\/a> to call the REST API from Azure SQL database.<\/p>\n<pre><code class=\"language-sql\">declare @retval int, @response nvarchar(max);\r\ndeclare @payload nvarchar(max) = json_object('input': 'Isaac Asimov');\r\n\r\nexec @retval = sp_invoke_external_rest_endpoint\r\n    @url = 'https:\/\/&lt;your-app-name&gt;.openai.azure.com\/openai\/deployments\/&lt;deployment-id&gt;\/embeddings?api-version=2023-03-15-preview',\r\n    @method = 'POST',\r\n    @headers = '{\"api-key\":\"&lt;your api key&gt;\"}',\r\n    @payload = @payload,\r\n    @response = @response output;<\/code><\/pre>\n<p>The response is a vector of 1536 elements in JSON format. Vector values can be easily extracted using the following T-SQL code:<\/p>\n<pre><code class=\"language-sql\">select [key] as value_id, [value] from openjson(@response, '$.result.data[0].embedding')<\/code><\/pre>\n<h2>Source code<\/h2>\n<p>If you are interested in trying this amazing capability by yourself, you can find the source code here:<\/p>\n<p><a href=\"https:\/\/github.com\/Azure-Samples\/azure-sql-db-openai\">https:\/\/github.com\/Azure-Samples\/azure-sql-db-openai<\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>The provided sample is <em>not<\/em> optimized. For example, the square of the vectors: <code>SUM(a.value * a.value)<\/code> could be pre-calculated and stored in a table for even better efficiency and performance. The sample is purposely simple to make it easier to understand the concept. Even if the sample is also not optimized for performance, it is still quite fast. On an eight vCore Azure SQL database, the query takes only half of a second to return the fifty most similar articles. The cosine distance is calculated on 25,000 articles, for a total of 38 million vector values. Pretty cool, fast and useful!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/06\/azure-sql-cosine-similarity.gif\" alt=\"\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Latest update &#8211; 06 November 2024 Vector Support is now available as Public Preview! Read the announcement here: Public Preview of Native Vector Support in Azure SQL Database! Access to full documentation here: Vector functions. Vectors and Embeddings Vector databases are gaining quite a lot of interest lately. Using text embeddings and vector operations makes [&hellip;]<\/p>\n","protected":false},"author":24720,"featured_media":2193,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,561,569],"class_list":["post-2200","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sql","tag-columnstore","tag-openai","tag-vector"],"acf":[],"blog_post_summary":"<p>Latest update &#8211; 06 November 2024 Vector Support is now available as Public Preview! Read the announcement here: Public Preview of Native Vector Support in Azure SQL Database! Access to full documentation here: Vector functions. Vectors and Embeddings Vector databases are gaining quite a lot of interest lately. Using text embeddings and vector operations makes [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/2200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/24720"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=2200"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/2200\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/2193"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=2200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=2200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=2200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}