共用方式為


AdventureWorks 資料集的 AI 技能範例 (預覽)

本文說明如何使用 Lakehouse 作為數據源來設定 AI 技能。 為了說明此程式,我們會先建立 Lakehouse,然後將數據新增至其中。 然後,我們會建立 AI 技能,並將 Lakehouse 設定為其數據源。 如果您已經有Power BI語意模型(具有必要的讀取/寫入許可權)、倉儲或 KQL 資料庫,您可以在建立 AI 技能以新增數據源之後,遵循相同的步驟。 雖然此處顯示的步驟著重於 Lakehouse,但過程與其他資料來源類似,您只需根據您的特定選擇進行調整。

重要

這項功能處於預覽狀態

必要條件

使用 AdventureWorksLH 建立 Lakehouse

首先,建立 Lakehouse,並填入必要的資料。

如果您在 Lakehouse (或倉儲) 中已經有 AdventureWorksLH 的實例,您可以略過此步驟。 如果沒有,您可以使用 Fabric 筆記本中的下列指示,將數據填入湖倉中。

  1. 在您要在其中建立 AI 技能的工作區中建立新的筆記本。

  2. 在 [ 總管] 窗格的左側,選取 [+ 資料來源]。 此選項可讓您新增現有的 Lakehouse 或建立新的 Lakehouse。 為了清晰起見,請建立新的「Lakehouse」,並給它命名。

  3. 在頂端儲存格中,新增下列程式碼片段:

    import pandas as pd
    from tqdm.auto import tqdm
    base = "https://synapseaisolutionsa.blob.core.windows.net/public/AdventureWorks"
    
    # load list of tables
    df_tables = pd.read_csv(f"{base}/adventureworks.csv", names=["table"])
    
    for table in (pbar := tqdm(df_tables['table'].values)):
        pbar.set_description(f"Uploading {table} to lakehouse")
    
        # download
        df = pd.read_parquet(f"{base}/{table}.parquet")
    
        # save as lakehouse table
        spark.createDataFrame(df).write.mode('overwrite').saveAsTable(table)
    
  4. 選取 [全部執行]

    顯示具有 AdventureWorks 上傳程式碼的筆記本螢幕擷取畫面。

幾分鐘後,資料湖倉會填入必要的數據。

建立 AI 技能

若要建立新的 AI 技能,請流覽至您的工作區,然後選取 [+ 新增專案] 按鈕,如下列螢幕快照所示:

顯示建立 AI 技能位置的螢幕快照。

在 [所有項目] 索引標籤中,搜尋 AI 技能 以定位適當的選項。 選取之後,提示會要求您提供 AI 技能的名稱,如下列螢幕快照所示:

螢幕快照,其中顯示提供 AI 技能名稱的位置。

輸入名稱之後,請繼續進行下列步驟,讓 AI 技能符合您的特定需求。

選取資料

選取您在上一個步驟中建立的資料湖倉,然後選取 新增。 將 Lakehouse 新增為數據源之後,AI 技能頁面左側的 [Explorer] 窗格會顯示 Lakehouse 名稱。 選取 Lakehouse 以檢視所有可用的數據表。 使用複選框來選取您想要提供給 AI 使用的數據表。 在此案例中,請選取下列數據表:

  • dimcustomer
  • dimdate
  • dimgeography
  • dimproduct
  • dimproductcategory
  • dimpromotion
  • dimreseller
  • dimsalesterritory
  • factinternetsales
  • cactresellersales

螢幕快照,其中顯示您可以選取 AI 數據表的位置。

提供指示

若要新增 AI 指示,請選取 [AI 指示] 按鈕,以開啟右側的 [AI 指示] 窗格。 您可以新增下列指示。

AdventureWorksLH 資料來源包含來自三個資料表的資訊:

  • dimcustomer,以取得詳細的客戶人口統計和連絡資訊
  • dimdate,適用於日期相關資料 - 例如行事曆和會計資訊
  • dimgeography,以取得地理詳細數據,包括城市名稱和國家/地區代碼。

使用此數據源進行涉及客戶詳細數據、以時間為基礎的事件和地理位置的查詢和分析。

螢幕快照,其中顯示您可以在哪裡提供 AI 的指示。

提供範例

若要新增範例查詢,請選取 [範例查詢] 按鈕,以開啟右側的範例查詢窗格。 此窗格提供為所有支持的數據源新增或編輯範例查詢的選項。 針對每個數據源,您可以選取 [新增或編輯範例查詢] 輸入相關範例,如下列螢幕快照所示:

螢幕快照,其中顯示您可以在何處新增您提供給 AI 的範例。

在這裡,您應該為您所建立的 Lakehouse 數據源新增範例查詢。

Question: Calculate the average percentage increase in sales amount for repeat purchases for every zipcode. Repeat purchase is a purchase subsequent to the first purchase (the average should always be computed relative to the first purchase)

SELECT AVG((s.SalesAmount - first_purchase.SalesAmount) / first_purchase.SalesAmount * 100) AS AvgPercentageIncrease
FROM factinternetsales s
INNER JOIN dimcustomer c ON s.CustomerKey = c.CustomerKey
INNER JOIN dimgeography g ON c.GeographyKey = g.GeographyKey
INNER JOIN (
	SELECT *
	FROM (
		SELECT
			CustomerKey,
			SalesAmount,
            OrderDate,
			ROW_NUMBER() OVER (PARTITION BY CustomerKey ORDER BY OrderDate) AS RowNumber
		FROM factinternetsales
	) AS t
	WHERE RowNumber = 1
) first_purchase ON s.CustomerKey = first_purchase.CustomerKey
WHERE s.OrderDate > first_purchase.OrderDate
GROUP BY g.PostalCode;

Question: Show the monthly total and year-to-date total sales. Order by year and month.

SELECT
    Year,
	Month,
	MonthlySales,
	SUM(MonthlySales) OVER (PARTITION BY Year ORDER BY Year, Month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CumulativeTotal
FROM (
	SELECT
	   YEAR(OrderDate) AS Year,
	   MONTH(OrderDate) AS Month,
	   SUM(SalesAmount) AS MonthlySales
	FROM factinternetsales
	GROUP BY YEAR(OrderDate), MONTH(OrderDate)
) AS t

顯示新增 SQL 範例的螢幕快照。

備註

Power BI 語意模型數據源目前不支援新增範例查詢/問題組。

測試和修訂 AI 技能

既然您已設定 AI 技能、新增 AI 指示,並為 Lakehouse 提供範例查詢,您可以藉由詢問問題和接收答案來與其互動。 當您繼續測試時,您可以新增更多範例,並精簡指示,以進一步改善 AI 技能的效能。 與您的同事共同作業以收集意見反應,並根據其輸入,確保提供的範例查詢和指示符合他們想要詢問的問題類型。

以程式設計方式使用 AI 技能

您可以在 Fabric 筆記本內以程式設計方式使用 AI 技能。 若要判斷 AI 技能是否有已發佈的網址值,請選取 [設定],如本螢幕擷取畫面所示:

顯示選取 AI 技能設定的螢幕擷取畫面。

在您發佈 AI 技能之前,它沒有已發佈的網址值,如本螢幕擷取畫面所示:

顯示 AI 技能在發行前沒有已發佈網址值的螢幕擷取畫面。

驗證 AI 技能的效能之後,您可能會決定發布它,以便與想要對數據執行 Q&A 的同事共用。 在此情況下,請選取 [發佈],如本螢幕擷取畫面所示:

顯示選取 [發佈] 選項的螢幕擷取畫面。

AI 技能的已發佈網址隨即出現,如本螢幕擷取畫面所示:

顯示已發佈網址的螢幕擷取畫面。

然後,您可以複製已發佈的網址,並在 Fabric 筆記本中使用該網址。 如此一來,您就可以在 Fabric 筆記本中呼叫 AI 技能 API,以查詢 AI 技能。 將此程式碼片段中複製的網址貼上。 然後,將問題取代為您 AI 技能相關的任何查詢。 此範例使用 \<generic published URL value\> 作為網址。

%pip install "openai==1.14.1"
%pip install httpx==0.27.2
import requests
import json
import pprint
import typing as t
import time
import uuid

from openai import OpenAI
from openai._exceptions import APIStatusError
from openai._models import FinalRequestOptions
from openai._types import Omit
from openai._utils import is_given
from synapse.ml.mlflow import get_mlflow_env_config
from sempy.fabric._token_provider import SynapseTokenProvider
 
base_url = "https://<generic published base URL value>"
question = "What datasources do you have access to?"

configs = get_mlflow_env_config()

# Create OpenAI Client
class FabricOpenAI(OpenAI):
    def __init__(
        self,
        api_version: str ="2024-05-01-preview",
        **kwargs: t.Any,
    ) -> None:
        self.api_version = api_version
        default_query = kwargs.pop("default_query", {})
        default_query["api-version"] = self.api_version
        super().__init__(
            api_key="",
            base_url=base_url,
            default_query=default_query,
            **kwargs,
        )
    
    def _prepare_options(self, options: FinalRequestOptions) -> None:
        headers: dict[str, str | Omit] = (
            {**options.headers} if is_given(options.headers) else {}
        )
        options.headers = headers
        headers["Authorization"] = f"Bearer {configs.driver_aad_token}"
        if "Accept" not in headers:
            headers["Accept"] = "application/json"
        if "ActivityId" not in headers:
            correlation_id = str(uuid.uuid4())
            headers["ActivityId"] = correlation_id

        return super()._prepare_options(options)

# Pretty printing helper
def pretty_print(messages):
    print("---Conversation---")
    for m in messages:
        print(f"{m.role}: {m.content[0].text.value}")
    print()

fabric_client = FabricOpenAI()
# Create assistant
assistant = fabric_client.beta.assistants.create(model="not used")
# Create thread
thread = fabric_client.beta.threads.create()
# Create message on thread
message = fabric_client.beta.threads.messages.create(thread_id=thread.id, role="user", content=question)
# Create run
run = fabric_client.beta.threads.runs.create(thread_id=thread.id, assistant_id=assistant.id)

# Wait for run to complete
while run.status == "queued" or run.status == "in_progress":
    run = fabric_client.beta.threads.runs.retrieve(
        thread_id=thread.id,
        run_id=run.id,
    )
    print(run.status)
    time.sleep(2)

# Print messages
response = fabric_client.beta.threads.messages.list(thread_id=thread.id, order="asc")
pretty_print(response)

# Delete thread
fabric_client.beta.threads.delete(thread_id=thread.id)