知識存放區中圖形和投影的詳細範例

本文提供詳細的範例,可逐步引導您完成完整表達知識存放區中豐富技能集輸出所需的成形和投影步驟,以補充高階概念和語法型文章。

如果您的應用程式需求呼叫多個技能和投影,則此範例可讓您更清楚圖形和投影如何交集。

設定範例數據

範例檔不包含在 Projections 集合中,但 AI 擴充示範數據檔 包含使用此範例中所述投影的文字和影像。

在 Azure 儲存體 中建立 Blob 容器,並上傳所有 14 個專案。

在 Azure 儲存體 中,複製 連接字串。

您可以使用 projections.rest 檔案來執行本文中的範例。

範例技能集

若要了解圖形和投影之間的相依性,請檢閱下列可建立擴充內容的技能集。 此技能集會處理原始影像和文字,產生將在圖形和投影中參考的輸出。

密切關注技能輸出(targetNames)。 寫入擴充檔樹狀結構的輸出會在投影和圖形中參考(透過Shaper技能)。

{
    "name": "projections-demo-ss",
    "description": "Skillset that enriches blob data found in "merged_content". The enrichment granularity is a document.",
    "skills": [
        {
            "@odata.type": "#Microsoft.Skills.Text.V3.EntityRecognitionSkill",
            "name": "#1",
            "description": null,
            "context": "/document/merged_content",
            "categories": [
                "Person",
                "Quantity",
                "Organization",
                "URL",
                "Email",
                "Location",
                "DateTime"
            ],
            "defaultLanguageCode": "en",
            "minimumPrecision": null,
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/merged_content"
                },
                {
                    "name": "languageCode",
                    "source": "/document/language"
                }
            ],
            "outputs": [
                {
                    "name": "persons",
                    "targetName": "people"
                },
                {
                    "name": "organizations",
                    "targetName": "organizations"
                },
                {
                    "name": "locations",
                    "targetName": "locations"
                }
            ]
        },
        {
            "@odata.type": "#Microsoft.Skills.Text.KeyPhraseExtractionSkill",
            "name": "#2",
            "description": null,
            "context": "/document/merged_content",
            "defaultLanguageCode": "en",
            "maxKeyPhraseCount": null,
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/merged_content"
                },
                {
                    "name": "languageCode",
                    "source": "/document/language"
                }
            ],
            "outputs": [
                {
                    "name": "keyPhrases",
                    "targetName": "keyphrases"
                }
            ]
        },
        {
            "@odata.type": "#Microsoft.Skills.Text.LanguageDetectionSkill",
            "name": "#3",
            "description": null,
            "context": "/document",
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/merged_content"
                }
            ],
            "outputs": [
                {
                    "name": "languageCode",
                    "targetName": "language"
                }
            ]
        },
        {
            "@odata.type": "#Microsoft.Skills.Text.MergeSkill",
            "name": "#4",
            "description": null,
            "context": "/document",
            "insertPreTag": " ",
            "insertPostTag": " ",
            "inputs": [
                {
                    "name": "text",
                    "source": "/document/content"
                },
                {
                    "name": "itemsToInsert",
                    "source": "/document/normalized_images/*/text"
                },
                {
                    "name": "offsets",
                    "source": "/document/normalized_images/*/contentOffset"
                }
            ],
            "outputs": [
                {
                    "name": "mergedText",
                    "targetName": "merged_content"
                }
            ]
        },
        {
            "@odata.type": "#Microsoft.Skills.Vision.OcrSkill",
            "name": "#5",
            "description": null,
            "context": "/document/normalized_images/*",
            "textExtractionAlgorithm": "printed",
            "lineEnding": "Space",
            "defaultLanguageCode": "en",
            "detectOrientation": true,
            "inputs": [
                {
                    "name": "image",
                    "source": "/document/normalized_images/*"
                }
            ],
            "outputs": [
                {
                    "name": "text",
                    "targetName": "text"
                },
                {
                    "name": "layoutText",
                    "targetName": "layoutText"
                }
            ]
        }
    ],
    "cognitiveServices": {
        "@odata.type": "#Microsoft.Azure.Search.CognitiveServicesByKey",
        "description": "An Azure AI services resource in the same region as Search.",
        "key": "<Azure AI services All-in-ONE KEY>"
    },
    "knowledgeStore": null
}

範例 Shaper 技能

Shaper 技能是一種公用程式,可用於處理現有的擴充內容,而不是建立新的擴充內容。 將 Shaper 新增至技能集可讓您建立可投影到數據表或 Blob 記憶體的自訂圖形。 如果沒有自定義圖形,投影僅限於參考單一節點(每個輸出的一個投影),這不適用於數據表。 建立自定義圖形會將各種元素匯總成可投影為單一數據表的新邏輯整體,或分割並分散到數據表集合。

在此範例中,自定義圖形會結合 Blob 元數據和識別的實體和關鍵片語。 自定義圖形稱為 projectionShape ,且父系在下 /document

成形的其中一個目的是確保所有擴充節點都以格式正確的 JSON 表示,這是投影到知識存放區的必要專案。 當擴充樹狀結構包含格式不正確 JSON 的節點時,尤其如此(例如,當擴充父代為類似字串的基本類型時)。

請注意最後兩個節點和 KeyPhrasesEntities。 這些會包裝成有效的 JSON 物件與 sourceContext。 這是必要專案keyphrasesentities,而且是基本型別的擴充,而且必須先轉換成有效的 JSON,才能進行投影。

{
    "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
    "name": "ShaperForTables",
    "description": null,
    "context": "/document",
    "inputs": [
        {
            "name": "metadata_storage_content_type",
            "source": "/document/metadata_storage_content_type",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "metadata_storage_name",
            "source": "/document/metadata_storage_name",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "metadata_storage_path",
            "source": "/document/metadata_storage_path",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "metadata_content_type",
            "source": "/document/metadata_content_type",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "keyPhrases",
            "source": null,
            "sourceContext": "/document/merged_content/keyphrases/*",
            "inputs": [
                {
                    "name": "KeyPhrases",
                    "source": "/document/merged_content/keyphrases/*"
                }

            ]
        },
        {
            "name": "Entities",
            "source": null,
            "sourceContext": "/document/merged_content/entities/*",
            "inputs": [
                {
                    "name": "Entities",
                    "source": "/document/merged_content/entities/*/name"
                }

            ]
        }
    ],
    "outputs": [
        {
            "name": "output",
            "targetName": "projectionShape"
        }
    ]
}

將 Shapers 新增至技能集

本文開頭介紹的範例技能集不包含 Shaper 技能,但 Shaper 技能屬於技能集,而且通常會放在結尾。

在技能集內,Shaper 技能看起來可能如下所示:

{
    "name": "projections-demo-ss",
    "skills": [
        {
            <Shaper skill goes here>
            }
        ],
    "cognitiveServices":  "A key goes here",
    "knowledgeStore": []
}  

投影至數據表

在上述範例上繪製時,有一些已知的擴充和數據圖形可以在數據表投影中參考。 在下列數據表投影中,設定、 sourcegeneratedKeyName 屬性會定義tableName三個數據表。

這三個數據表都會透過產生的索引鍵和共用父 /document/projectionShape代 來關聯。

"knowledgeStore" : {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<Acct Name>;AccountKey=<Acct Key>;",
    "projections": [
        {
            "tables": [
                {
                    "tableName": "tblDocument",
                    "generatedKeyName": "Documentid",
                    "source": "/document/projectionShape"
                },
                {
                    "tableName": "tblKeyPhrases",
                    "generatedKeyName": "KeyPhraseid",
                    "source": "/document/projectionShape/keyPhrases/*"
                },
                {
                    "tableName": "tblEntities",
                    "generatedKeyName": "Entityid",
                    "source": "/document/projectionShape/Entities/*"
                }
            ],
            "objects": [],
            "files": []
        }
    ]
}

測試您的工作

您可以遵循下列步驟來檢查投影定義:

  1. 將知識存放區的 storageConnectionString 屬性設定為有效的 V2 一般用途記憶體帳戶 連接字串。

  2. 發出 PUT 要求來更新技能集。

  3. 更新技能集之後,請執行索引器。

您現在有一個具有三個數據表的工作投影。 將這些數據表匯入Power BI應該會導致Power BI 探索關聯性。

在繼續進行下一個範例之前,讓我們重新瀏覽數據表投影的各個層面,以瞭解切割和關聯數據的機制。

將數據表切割成多個子數據表

切割是一種技術,將整個合併形狀細分為組成部分。 結果是由個別但相關的數據表所組成,您可以個別使用。

在此範例中, projectionShape 是合併圖形 (或擴充節點)。 在投影定義中, projectionShape 會分割成其他數據表,這可讓您提取圖形的一部分, keyPhrases 以及 Entities。 在 Power BI 中,當多個實體和 keyPhrases 與每個文件相關聯時,這會很有用,而且如果您可以看到實體和 keyPhrases 分類數據,您將會取得更多見解。

配量會隱含地產生父數據表與子數據表之間的關聯性,使用 generatedKeyName 父數據表中的 ,在子數據表中建立具有相同名稱的數據行。

命名關聯性

generatedKeyNamereferenceKeyName 屬性可用來跨數據表,甚至是跨投影類型來關聯數據。 子數據表中的每個數據列都有指向父系的屬性。 子系中資料行或屬性的名稱是 referenceKeyName 父系中的 。 referenceKeyName未提供 時,服務會將預設為generatedKeyName父代的 。

Power BI 依賴這些產生的密鑰來探索數據表內的關聯性。 如果您需要以不同的方式命名子數據表中的數據行,請在父數據表上設定 referenceKeyName 屬性。 其中一個範例是將 tblDocument 數據表上的 設定 generatedKeyName 為標識碼,並將 referenceKeyName 設定為 DocumentID。 這會導致 tblEntities 和 tblKeyPhrases 數據表中的數據行包含名為 DocumentID 的文件識別碼。

投影 Blob 檔

物件投影是可從任何節點來源之擴充樹狀結構的 JSON 表示法。 相較於數據表投影,物件投影比較簡單,可用來定義及投影整個檔。 物件投影僅限於容器中的單一投影,且無法進行配量。

若要定義物件投影,請使用 objects 投影屬性中的陣列。

來源是擴充樹狀結構節點的路徑,該節點是投影的根目錄。 雖然不需要,但節點路徑通常是Shaper技能的輸出。 這是因為大部分技能不會自行輸出有效的 JSON 物件,這表示需要某種形式的成形。 在許多情況下,建立表格投影的相同 Shaper 技能可用來產生物件投影。 或者,來源也可以設定為具有 內嵌成形 的節點,以提供 結構。

目的地一律是 Blob 容器。

下列範例會將個別旅館檔、每個 Blob 一份旅館檔投影到名為 hotels的容器中。

"knowledgeStore": {
  "storageConnectionString": "an Azure storage connection string",
  "projections" : [
    {
      "tables": [ ]
    },
    {
      "objects": [
        {
        "storageContainer": "hotels",
        "source": "/document/objectprojection",
        }
      ]
    },
    {
        "files": [ ]
    }
  ]
}

來源是 Shaper 技能的輸出,名為 "objectprojection"。 每個 Blob 都會有每個字位輸入的 JSON 表示法。

    {
      "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
      "name": "#3",
      "description": null,
      "context": "/document",
      "inputs": [
        {
          "name": "HotelId",
          "source": "/document/HotelId"
        },
        {
          "name": "HotelName",
          "source": "/document/HotelName"
        },
        {
          "name": "Category",
          "source": "/document/Category"
        },
        {
          "name": "keyPhrases",
          "source": "/document/HotelId/keyphrases/*"
        },
      ],
      "outputs": [
        {
          "name": "output",
          "targetName": "objectprojection"
        }
      ]
    }

投影圖像檔

檔案投影一律為二進位正規化影像,其中正規化是指在技能集執行中使用的可能重設大小和輪替。 檔案投影,類似於物件投影,會建立為 Azure 儲存體 中的 Blob,並包含影像。

若要定義檔案投影,請使用 files 投影屬性中的陣列。

來源一律 /document/normalized_images/*為 。 檔案投影只會對集合採取 normalized_images 動作。 索引器和技能集都不會通過原始的非正規化影像。

目的地一律是 Blob 容器,具有文件標識碼 base64 編碼值的資料夾前置詞。 檔案投影無法與物件投影共用相同的容器,而且必須投影到不同的容器中。

下列範例會將從擴充文件的文件節點擷取的所有標準化影像投影到名為 myImages的容器中。

"knowledgeStore" : {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<Acct Name>;AccountKey=<Acct Key>;",
    "projections": [
        {
            "tables": [ ],
            "objects": [ ],
            "files": [
                {
                    "storageContainer": "myImages",
                    "source": "/document/normalized_images/*"
                }
            ]
        }
    ]
}

投影至多個類型

更複雜的案例可能會要求您跨投影類型投影內容。 例如,將關鍵片語和實體投影到數據表、將文字和版面配置文字的 OCR 結果儲存為物件,然後將影像投影為檔案。

多個投影類型的步驟:

  1. 為每個檔建立一個數據列的數據表。
  2. 建立與文件數據表相關的數據表,並將每個關鍵片語識別為此數據表中的數據列。
  3. 建立與文件數據表相關的數據表,並將每個實體識別為此數據表中的數據列。
  4. 使用每個影像的配置文字建立物件投影。
  5. 建立檔案投影,投影每個擷取的影像。
  6. 建立包含文件數據表參考、具有版面配置文字的物件投影,以及檔案投影的交叉參照數據表。

交叉投影的圖形數據

若要取得這些投影所需的圖形,請從新增新的Shaper技能開始,以建立名為 crossProjection的成形物件。

{
    "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
    "name": "ShaperForCrossProjection",
    "description": null,
    "context": "/document",
    "inputs": [
        {
            "name": "metadata_storage_name",
            "source": "/document/metadata_storage_name",
            "sourceContext": null,
            "inputs": []
        },
        {
            "name": "keyPhrases",
            "source": null,
            "sourceContext": "/document/merged_content/keyphrases/*",
            "inputs": [
                {
                    "name": "KeyPhrases",
                    "source": "/document/merged_content/keyphrases/*"
                }

            ]
        },
        {
            "name": "entities",
            "source": null,
            "sourceContext": "/document/merged_content/entities/*",
            "inputs": [
                {
                    "name": "Entities",
                    "source": "/document/merged_content/entities/*/name"
                }

            ]
        },
        {
            "name": "images",
            "source": null,
            "sourceContext": "/document/normalized_images/*",
            "inputs": [
                {
                    "name": "image",
                    "source": "/document/normalized_images/*"
                },
                {
                    "name": "layoutText",
                    "source": "/document/normalized_images/*/layoutText"
                },
                {
                    "name": "ocrText",
                    "source": "/document/normalized_images/*/text"
                }
                ]
        }
 
    ],
    "outputs": [
        {
            "name": "output",
            "targetName": "crossProjection"
        }
    ]
}

定義數據表、對象和檔案投影

從合併的 crossProjection 物件中,將物件分割成多個數據表、將 OCR 輸出擷取為 Blob,然後將映像儲存為檔案(也儲存在 Blob 記憶體中)。

"knowledgeStore" : {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<Acct Name>;AccountKey=<Acct Key>;",
    "projections": [
            {
            "tables": [
                {
                    "tableName": "crossDocument",
                    "generatedKeyName": "Id",
                    "source": "/document/crossProjection"
                },
                {
                    "tableName": "crossEntities",
                    "generatedKeyName": "EntityId",
                    "source": "/document/crossProjection/entities/*"
                },
                {
                    "tableName": "crossKeyPhrases",
                    "generatedKeyName": "KeyPhraseId",
                    "source": "/document/crossProjection/keyPhrases/*"
                },
                {
                    "tableName": "crossReference",
                    "generatedKeyName": "CrossId",
                    "source": "/document/crossProjection/images/*"
                }
                    
            ],
            "objects": [
                {
                    "storageContainer": "crossobject",
                    "generatedKeyName": "crosslayout",
                    "source": null,
                    "sourceContext": "/document/crossProjection/images/*/layoutText",
                    "inputs": [
                        {
                            "name": "OcrLayoutText",
                            "source": "/document/crossProjection/images/*/layoutText"
                        }
                    ]
                }
            ],
            "files": [
                {
                    "storageContainer": "crossimages",
                    "generatedKeyName": "crossimages",
                    "source": "/document/crossProjection/images/*/image"
                }
            ]
        }
    ]
}

物件投影需要每個投影的容器名稱。 物件投影和檔案投影無法共用容器。

數據表、對象和檔案投影之間的關聯性

此範例也會反白顯示投影的另一個功能。 藉由在相同的投影物件中定義多個投影類型,就會在不同類型的 (數據表、物件、檔案) 之間表示關聯性。 這可讓您從檔的表格列開始,並在物件投影中尋找該檔內影像的所有 OCR 文字。

如果您不想讓數據相關,請在不同的投影群組中定義投影。 例如,下列代碼段會導致數據表相關,但數據表與物件 (OCR 文字) 投影之間沒有關聯性。

當您想要針對不同需求以不同圖形投影相同的數據時,投影群組很有用。 例如,Power BI 儀錶板的投影群組,以及另一個投影群組,用來擷取用來定型包裝在自定義技能中的機器學習模型的數據。

建置不同類型的投影時,會先產生檔案和物件投影,並將路徑新增至數據表。

"knowledgeStore" : {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<Acct Name>;AccountKey=<Acct Key>;",
    "projections": [
        {
            "tables": [
                {
                    "tableName": "unrelatedDocument",
                    "generatedKeyName": "Documentid",
                    "source": "/document/projectionShape"
                },
                {
                    "tableName": "unrelatedKeyPhrases",
                    "generatedKeyName": "KeyPhraseid",
                    "source": "/document/projectionShape/keyPhrases"
                }
            ],
            "objects": [
                
            ],
            "files": []
        }, 
        {
            "tables": [],
            "objects": [
                {
                    "storageContainer": "unrelatedocrtext",
                    "source": null,
                    "sourceContext": "/document/normalized_images/*/text",
                    "inputs": [
                        {
                            "name": "ocrText",
                            "source": "/document/normalized_images/*/text"
                        }
                    ]
                },
                {
                    "storageContainer": "unrelatedocrlayout",
                    "source": null,
                    "sourceContext": "/document/normalized_images/*/layoutText",
                    "inputs": [
                        {
                            "name": "ocrLayoutText",
                            "source": "/document/normalized_images/*/layoutText"
                        }
                    ]
                }
            ],
            "files": []
        }
    ]
}

下一步

本文中的範例示範如何建立投影的常見模式。 既然您已充分瞭解概念,您就更有能力針對特定案例建置投影。