Artificial Intelligence
AI Azure Azure Blob Azure Storage REST Search

How to Create Knowledge Stores with the Azure AI Search Service

Welcome to today’s post.

In today’s post, I will be discussing what a knowledge store is, what their purpose is, and how to create them from an Azure AI Search Service.

In a previous post, I showed how to create an Azure AI Search Service, which we used to index some PDF documents from an Azure Blob Storage Container. In the same post, I showed how to add cognitive skills such as Image analysis (tag and caption extraction), or Entity Recognition using the indexing wizard for the Azure Search Service. 

In a subsequent post, I then showed how, using Azure Search Service HTTP REST API requests, how to extend the Azure Search instance by adding additional Azure AI Cognitive Skills, such as Sentiment Analysis.

In another post, I then showed how to execute indexed searches against the Azure AI Search instance within a web client application.

Knowledge Stores and Reporting

The other option for running searches is to use reporting tools that can return results based on keywords that are stored within JSON files, storage tables and image files that have been extracted from the Azure AI Search instance. What I will be showing is how to extend an existing Azure AI Search creation pipeline to extract many of the keywords, phrases, and properties from the unstructured file data sources, and store them in a more structured format within the storage container. The storage of the structured format within the storage container is known as a knowledge store.

The types of structured content that are in a knowledge store can include:

JSON files

Image files

Storage Tables

With the above content in a container, we will then be able to connect to the container as a data source and run reports. I will not go into the details of the reporting side of things, but only on the creation of the knowledge store.

In the next section, I will show the JSON structure of the skillset definition that is required for modification.

Structure of the Skillset to be Modified

Below is the structure of the Skillset definition with the skills sections and their details omitted for brevity.

Skillset.json

{
  "name": "parkdocs-skillset",
  "description": "Skillset created from the portal",
  "cognitiveServices": {
      "@odata.type": "#Microsoft.Azure.Search.CognitiveServicesByKey",
      "description": "Azure AI services",
      "key": "[your AI cognitive services multi-key]"
    },
  "skills": [
    {
      "@odata.type": "#Microsoft.Skills.Text.V3.EntityRecognitionSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.KeyPhraseExtractionSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.LanguageDetectionSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.MergeSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Vision.OcrSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Vision.ImageAnalysisSkill",
      …
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.V3.SentimentSkill",
      …
    },
    … Shaper Skill definition here …
  ],
  … Knowledge Store definition here …
  "encryptionKey": null
}

In the next section, I will show how to modify the skillset definition to define our new knowledge store.

Modifying the Skillset to provide a new Knowledge Store

Achieving our goal of creating the knowledge store will require us to modify the Skillset.json file to include two additional sections:

  1. A Shaper skill.
  2. A knowledge store section. knowledgeStore

The Shaper Skill

The Shaper Skill, which is of OData type Microsoft.Skills.Util.ShaperSkill is used to take the fields that were extracted during the index creation process and structure them into an output field, named knowledge_projection. The input fields include those from the following fields:

  1. metadata_* fields
  2. Extracted recognition entities
  3. Extracted key phrases
  4. Extracted image tags and captions
  5. Extracted cognitive skills

The definition of the Shaper Skill is below:

{
      "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
      "name": "define-projection",
      "description": "Prepare projection fields",
      "context": "/document",
      "inputs": [
        {
          "name": "file_id",
          "source": "/document/metadata_storage_path"
        },
        {
          "name": "file_name",
          "source": "/document/metadata_storage_name"
        },
        {
          "name": "url",
          "source": "/document/url"
        },
        {
          "name": "language",
          "source": "/document/language"
        },
        {
          "name": "sentiment",
          "source": "/document/sentimentLabel"
        },
        {
          "name": "key_phrases",
          "source": null,
          "sourceContext": "/document/merged_content/keyphrases/*",
          "inputs": [
            {
                "name": "phrase",
                "source": "/document/merged_content/keyphrases/*"
            }
          ]
        },
        {
          "name": "locations",
          "source": null,
          "sourceContext": "/document/merged_content/locations/*",
          "inputs":[
            {
              "name": "location", 
              "source": "/document/merged_content/locations/*"
            }
          ]
        },
        {
          "name": "image_tags",
          "source": null,
          "sourceContext": "/document/normalized_images/*/imageTags/*",
          "inputs":[
            {
              "name": "tag", 
              "source": "/document/normalized_images/*/imageTags/*/name"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "output",
          "targetName": "knowledge_projection"
        }
      ]
}

In the next section, I will show how to define the knowledge store to project the output of the shaper skill into our Azure storage container.

Defining the Knowledge Store

In this section, I will show how to define the knowledge store to project the output of the shaper skill into our Azure storage container.

Each projection into the Azure storage container is required to be moved into one of three types of project destination:

objects

files

tables

There can only be one projection defined for each of the above types of projection.

The destinations for the objects are JSON files.

The destinations for the files are images files.

The destinations for the tables are Azure storage tables.

To define the knowledge store, we require the following:

  1. A connection to the Azure storage container.
  2. Projections for the objects, files and tables.

With object and file projection types, we will need to specify a storage container and a source document projection folder.

{
    "storageContainer": "[storage container name]",
    "source": "/document/[sub-folder name]"
}

With table projection types, we will need to specify a table name, generated key name, and a source document projection folder.  

{
    "tableName": "[storage table name]",
    "generatedKeyName": "[table key name]",
    "source": "/document/[sub-folder name]"
}

Below is our knowledge store definition with the document subfolders specified for our projections:

"knowledgeStore": { 
    "storageConnectionString": "[azure storage connection string] ", 
    "projections": [
      {
        "objects": [
          {
            "storageContainer": "parkdocs-knowledge",
            "source": "/document/knowledge_projection"
          }
        ],
        "tables": [],
        "files": []
      },
      {
        "objects": [],
        "tables": [],
        "files": [
          {
            "storageContainer": "parkdocs-images",
            "source": "/document/normalized_images/*"
          }
        ]
      },
      {
        "objects": [],
        "tables": [  
          {
            "tableName": "KeyPhrases",
            "generatedKeyName": "keyphrase_id",
            "source": "/document/knowledge_projection/key_phrases/*"
          },
          {
            "tableName": "Locations",
            "generatedKeyName": "location_id",
            "source": "/document/knowledge_projection/locations/*"
          }, 
          {
            "tableName": "ImageTags",
            "generatedKeyName": "tag_id",
            "source": "/document/knowledge_projection/image_tags/*"
          },
          {
            "tableName": "docs",
            "generatedKeyName": "document_id", 
            "source": "/document/knowledge_projection" 
          }
        ],
        "files": []
      }
    ]     
},

In the next section, I will show how we apply the skillset definition with the above shaper skill and knowledge store definitions.

Updating the Knowledge Store with the REST API

To update the knowledge store, we will need to first execute the skillset, index and indexer REST API methods to update the Azure AI Search instance. We will then need to execute the reset and run REST API methods to reset and run the search instance.

We execute the same REST API requests that were run when updating the skillsets and indexes. The only difference is in the definition within the skillset.json file.

Below is the REST API request for the skillset method:

curl -X PUT https://[search-service-name].search.windows.net/skillsets/parkdocs-skillset?api-version=2024-07-01
 -H "Content-Type: application/json" 
-H "api-key: [azure search resource key]" -d @skillset.json

Below is the REST API request for the indexes method:

curl -X PUT https://[search-service-name].search.windows.net/indexes/parkdocs-index?api-version=2024-07-01 
-H "Content-Type: application/json" 
-H "api-key: [azure search resource key]" -d @index.json

Below is the REST API request for the indexers method:

curl -X PUT https://[search-service-name].search.windows.net/indexers/parkdocs-indexer?api-version=2024-07-01 
-H "Content-Type: application/json" 
-H "api-key: [azure search resource key]" -d @indexer.json

Below is the REST API request for the reset method:

curl -X POST https://[search-service-name].search.windows.net/indexers/parkdocs-indexer/reset?api-version=2024-07-01 
-H "Content-Type: application/json" -H "Content-Length: 0" 
-H "api-key: [azure search resource key]"

Below is the REST API request for the run method:

curl -X POST https://[search-service-name].search.windows.net/indexers/parkdocs-indexer/run?api-version=2024-07-01 
-H "Content-Type: application/json" -H "Content-Length: 0" 
-H "api-key: [azure search resource key]"

After completing the execution of the above CURL commands, you will then be able to inspect the storage container for the knowledge store.

In the next section, I will show how the storage container data source used by the Azure Search Service instance is populated with the data extracted from the document sources.

Viewing Outputs of the Knowledge Store within the Blob Storage Container

To view the results of the knowledge store in the Azure Portal, open the Storage Browser in the Storage Account resource overview.

Storage Tables

The table names are defined from the tableName propertywithin the tables array objects within the knowledgeStore definition, which you can review in the two previous sections.

docs Table

When viewing the docs storage table, you will see a document_id for each of the PDF documents, the file_name field, with the language and sentiment columns. 

The above fields are defined within the ShaperSkill definition’s name property within the inputs array, which you can review in the two previous sections.

The above record values are obtained from the following input source contexts (mapped column name in parentheses):

/document/metadata_storage_path (file_id)
/document/metadata_storage_name (file_name)
/document/language (language)
/document/sentimentLabel (sentiment)

A typical PDF file URL within the storage account is of the form:

https://[storage-account-name].blob.core.windows.net/parkdocs/[file-name].pdf

Image Tags Table

When viewing the ImageTags storage table, you will see a document_id for each of the tags and tag and tag_id columns. 

The ImageTags table column, tag is derived from the name property within the inputs array of the image_tags object in the ShaperSkill definition.

The above record values are obtained from the following input source context:

/document/normalized_images/*/imageTags/* 

Key Phrases Table

When viewing the KeyPhrases storage table, you will see a document_id for each of the phrases, and keyphrase_id and phrase columns. 

The KeyPhrases table field, phrase is derived from the name property within the inputs array of the key_phrases object in the ShaperSkill definition.

The above record values are obtained from the following input source context:

/document/merged_content/keyphrases/*

Locations Table

When viewing the locations storage table, you will see a document_id for each of the locations, and the location and location_id columns.

The Locations table field, location is derived from the name property within the inputs array of the location object in the ShaperSkill definition.

The above record values are obtained from the following input source context:

/document/merged_content/locations/*

File, Image and Object Projection Outputs

To view the knowledge store images and structured JSON object (file), you can expand the Blob containers node as shown:

You will notice there are three blob storage containers:

parkdocs

parkdocs-images

parkdocs-knowledge

The parkdoc container contains the source PDF documents extracted during the indexing process, the parkdoc-images container contains the images extracted from the documents, and the parkdocs-knowledge contains the data extracted from the documents in a structured JSON format in a file.

I will now explain each blob container output.

Blob Container File parkdocs

After selection of the parkdocs container, which is a projection of the data from the following input document source:

/document/knowledge_projection

you will see the following rows of data:

After clicking on one of the above rows of data corresponding to one of the extracted PDF files, you will see the file (a Block blob) that can be downloaded:

Each output PDF file is accessible with a URL of the form:

https://[storage-account-name].blob.core.windows.net/parkdocs/[document-id]/[file-name].pdf

Blob Container Image parkdocs-images

After selection of the parkdocs-image container, which is a projection of the data from the input document source:

/document/normalized_images/*

you will see the following rows of data:

After clicking on one of the above rows of data, you will see the JSON file (a Block blob) that contains the extracted JPEG image file:

Each output image file is accessible with a URL of the form:

https://[storage-account-name].blob.core.windows.net/parkdocs-images/[document-id]/normalized_images_0.jpg

Blob Container Object parkdocs-knowledge

After selection of the parkdocs-knowledge container, which is a projection of the data from the input document sources:

/document/knowledge_projection/key_phrases/*
/document/knowledge_projection/locations/*
/document/knowledge_projection/image_tags/*
/document/knowledge_projection

you will see the following rows of data:

After clicking on one of the above rows of data, you will see the JSON file (a Block blob) that contains a structured projection of the data within the above input document projections:

/document/knowledge_projection/*

The JSON file, which is of type Block blob is shown below:

Each JSON projection file is accessible with a URL of the form:

https://[storage-account-name].blob.core.windows.net/parkdocs-knowledge/[document-id]/knowledge_projection.json

Structure of the Knowledge Projection JSON File

A knowledge projection file is generated for each of the PDF files.

Below is the knowledge projection file for the first PDF file, which is a JSON file, knowledge_projection.json. It consists of the key phrases, locations, and image tags. I have included only a handful of entries for each projection for brevity.

{
    "file_id":"aHR0c...GRm0",
    "file_name":"Blue Mountains National Park - NSW.pdf",
    "language":"en",
    "sentiment":"positive",
    "key_phrases":
    [
        {"phrase":"World Heritage-listed Blue Mountains National Park"},
        {"phrase":"impressive blue gum forest"},
        {"phrase":"iconic Blue Mountains views"},
        …
        {"phrase":"three-sisters"},
        {"phrase":"village"},
        {"phrase":"Leura"}
    ],
    "locations":
    [
        {"location":"Blue Mountains National Park"},
        {"location":"park"},
        {"location":"Katoomba"},
        …
        {"location":"Govetts Leap lookout"},
        {"location":"Grose"},
        {"location":"Valley"}
    ],
    "image_tags":
    [
        {"tag":"landscape"},
        {"tag":"outdoor"},
        {"tag":"mountain"},
        …
        {"tag":"canyon"},
        {"tag":"cliff"},
        {"tag":"rock"}
    ]
}

The above has been an overview of how to define a share skill and knowledge store, then output the knowledge store from an existing indexed query built from an Azure Search Service instance.

The resulting outputs from the knowledge store, which include PDF documents, image files, JSON files, and Azure Storage tables, can be used for producing useful reports on the analysed documents.

That is all for today’s post.

I hope that you have found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial