AdventureWorks 資料集的 AI 技能範例 (預覽)
本文說明如何在 AdventureWorks 資料集上設定 AI 技能。
重要
這項功能處於預覽狀態。
必要條件
- 付費 F64 或更高 Fabric 容量資源。
- 已啟用 AI 技能租用戶切換。
- 已啟用 Copilot 租用戶切換。
- 如果相關,系統會啟用 AI 的跨地理位置共用。
使用 AdventureWorksDW 建立 Lakehouse
首先,建立 Lakehouse,並填入必要的資料。
如果您在倉儲或 Lakehouse 中已經有 AdventureWorksDW 的執行個體,您可以略過此步驟。 如果沒有,請從筆記本建立 Lakehouse。 使用筆記本以資料填入 Lakehouse。
在您要在其中建立 AI 技能的工作區中建立新的筆記本。
在 [ 總管] 窗格的左側,選取 [+ 資料來源]。 此選項可新增現有的 Lakehouse 或建立新的 Lakehouse。
在頂端儲存格中,新增下列程式碼片段:
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)
選取 [全部執行]。
幾分鐘之後,Lakehouse 就會填入必要的資料。
建立 AI 技能
選取資料
選取您建立的 Lakehouse,然後選取 [連線]。 然後,您必須選取您希望 AI 技能具有可用存取權的資料表。
本練習會使用這些資料表:
DimCustomer
DimDate
DimGeography
DimProduct
DimProductCategory
DimPromotion
DimReseller
DimSalesTerritory
FactInternetSales
FactResellerSales
提供指示
當您第一次詢問已選取資料表的 AI 技能問題時,AI 技能會相當妥善地回答。 例如,針對什麼是最暢銷產品?的問題,AI 技能會傳回:
Long-Sleeve Logo Jersey, L
不過,SQL 查詢需要一些改進。 首先,它只會查看 FactResellerSales
資料表。 它會忽略 FactInternetSales
資料表。 其次,當與產品相關的總銷售收入是最重要的考量因素時,它會依訂單數量來排序產品,如本螢幕擷取畫面所示:
若要改善查詢產生,請提供一些說明,如下列範例所示:
- 每當我詢問「銷售最多」的產品或項目時,我感興趣的計量是總銷售收入,而不是訂單數量。
- 要使用的主要資料表是
FactInternetSales
。 只有在明確詢問轉售或詢問總銷售額時,才使用FactResellerSales
。
再次詢問問題會傳回不同的答案,Mountain-200 Black, 46
,如下列螢幕擷取畫面所示:
對應的 SQL 會從 FactInternetSales
資料表中繪製,並依銷售金額的總和排序。 AI 遵循指示。
當您繼續實驗查詢時,應該新增更多指示。
此案例使用下列一組指示:
- 每當我詢問「銷售最多」的產品或項目時,我感興趣的計量是銷售收入,而不是訂單數量。
- 要使用的主要資料表是
FactInternetSales
。 只有在明確詢問轉售或詢問總銷售額時,才使用FactResellerSales
。 - 被問及促銷的影響時,請針對增加的銷售收入,而不只是銷售單位的數量。
- 針對客戶深入解析,請專注於每個客戶的總銷售金額,而非訂單數目。
- 使用
DimDate
以擷取執行以時間為基礎之分析時的特定時間週期 (例如年、月)。 - 分析地理資料時,請優先處理各區域的總銷售收入和每筆訂單的平均銷售額。
- 若要深入了解產品類別,請務必使用
DimProductCategory
來對產品進行相應的分組。 - 比較區域之間的銷售時,請使用
DimSalesTerritory
來取得精確的國家/地區詳細資料。 - 如果分析不同貨幣的銷售額,請使用
DimCurrency
將銷售資料正常化。 - 如需詳細的產品資訊,請一律將
FactInternetSales
與DimProduct
聯結。 - 使用
DimPromotion
來分析不同促銷行銷活動的有效性。 - 針對轉銷商效能,請專注於總銷售量,而不只是所銷售的產品數目。
- 分析一段時間的趨勢時,使用
FactInternetSales
並與DimDate
聯結以依月份、季或年分組資料。 - 請務必透過聯結
FactInternetSales
與相對應的維度資料表,檢查資料的一致性。 - 使用 SUM 彙總銷售資料,以確保您準確擷取總值。
- 將銷售收入指標優先於訂單數量,以準確評估財務影響。
- 請一律依相關維度分組 (例如產品、客戶、日期) 以取得詳細的深入解析。
- 被問及客戶人口統計資料時,請將
DimCustomer
與相關的事實資料表聯結。 - 若要依促銷取得銷售額,請將
FactInternetSales
與DimPromotion
聯結,並依促銷名稱分組。 - 在涉及不同貨幣的比較中,使用
DimCurrency
對銷售數字進行正常化。 - 使用
ORDER BY
子句可依您感興趣的計量 (例如:銷售收入、訂單總數) 對結果排序。 DimProduct
中的ListPrice
是建議銷售價格,而FactInternetSales
和FactResellerSales
中的UnitPrice
是每個單位的實際價格。 對於大多數關於收入的使用案例,應該使用單位價格。- 依銷售金額對頂級轉銷商進行排名。
如果您將這些文字複製到模型文字輸入框的備註中,AI 在產生 SQL 查詢時就會參考這些指示。
提供範例
除了指示之外,範例還可以作為引導 AI 的另一個有效方式。 如果您的問題屬於 AI 技能經常收到的問題,或需要複雜聯結的問題,請考慮為其新增範例。
例如,問題 2013 年 6 月 1 日我們有多少活躍客戶 會產生一些有效的 SQL,如本螢幕擷取畫面所示:
然而,這並非好的答案。
部分問題是「活躍客戶」並沒有正式的定義。 在 [模型] 文本框的附註中,更多指示可能會有所幫助,但使用者可能會經常提出這個問題。 您需要確定 AI 會正確處理問題。 相關的查詢相當複雜,請選取 [編輯] 按鈕來提供範例。
然後可以上傳範例。
重複該問題會傳回改進的答案。
您可以手動新增範例,但也可以從 JSON 檔案上傳。 您有許多 SQL 查詢要一次上傳,而不是手動逐一上傳查詢時,從檔案提供範例很有用。 對於此練習,請使用下列範例:
{
"how many active customers did we have June 1st, 2010?": "SELECT COUNT(DISTINCT fis.CustomerKey) AS ActiveCustomerCount FROM factinternetsales fis JOIN dimdate dd ON fis.OrderDateKey = dd.DateKey WHERE dd.FullDateAlternateKey BETWEEN DATEADD(MONTH, -6, '2010-06-01') AND '2010-06-01' GROUP BY fis.CustomerKey HAVING COUNT(fis.SalesOrderNumber) >= 2;",
"which promotion was the most impactful?": "SELECT dp.EnglishPromotionName, SUM(fis.SalesAmount) AS PromotionRevenue FROM factinternetsales fis JOIN dimpromotion dp ON fis.PromotionKey = dp.PromotionKey GROUP BY dp.EnglishPromotionName ORDER BY PromotionRevenue DESC;",
"who are the top 5 customers by total sales amount?": "SELECT TOP 5 CONCAT(dc.FirstName, ' ', dc.LastName) AS CustomerName, SUM(fis.SalesAmount) AS TotalSpent FROM factinternetsales fis JOIN dimcustomer dc ON fis.CustomerKey = dc.CustomerKey GROUP BY CONCAT(dc.FirstName, ' ', dc.LastName) ORDER BY TotalSpent DESC;",
"what is the total sales amount by year?": "SELECT dd.CalendarYear, SUM(fis.SalesAmount) AS TotalSales FROM factinternetsales fis JOIN dimdate dd ON fis.OrderDateKey = dd.DateKey GROUP BY dd.CalendarYear ORDER BY dd.CalendarYear;",
"which product category generated the highest revenue?": "SELECT dpc.EnglishProductCategoryName, SUM(fis.SalesAmount) AS CategoryRevenue FROM factinternetsales fis JOIN dimproduct dp ON fis.ProductKey = dp.ProductKey JOIN dimproductcategory dpc ON dp.ProductSubcategoryKey = dpc.ProductCategoryKey GROUP BY dpc.EnglishProductCategoryName ORDER BY CategoryRevenue DESC;",
"what is the average sales amount per order by territory?": "SELECT dst.SalesTerritoryRegion, AVG(fis.SalesAmount) AS AvgOrderValue FROM factinternetsales fis JOIN dimsalesterritory dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryRegion ORDER BY AvgOrderValue DESC;",
"what is the total sales amount by currency?": "SELECT dc.CurrencyName, SUM(fis.SalesAmount) AS TotalSales FROM factinternetsales fis JOIN dimcurrency dc ON fis.CurrencyKey = dc.CurrencyKey GROUP BY dc.CurrencyName ORDER BY TotalSales DESC;",
"which product had the highest sales revenue last year?": "SELECT dp.EnglishProductName, SUM(fis.SalesAmount) AS TotalRevenue FROM factinternetsales fis JOIN dimproduct dp ON fis.ProductKey = dp.ProductKey JOIN dimdate dd ON fis.ShipDateKey = dd.DateKey WHERE dd.CalendarYear = YEAR(GETDATE()) - 1 GROUP BY dp.EnglishProductName ORDER BY TotalRevenue DESC;",
"what are the monthly sales trends for the last year?": "SELECT dd.CalendarYear, dd.MonthNumberOfYear, SUM(fis.SalesAmount) AS TotalSales FROM factinternetsales fis JOIN dimdate dd ON fis.ShipDateKey = dd.DateKey WHERE dd.CalendarYear = YEAR(GETDATE()) - 1 GROUP BY dd.CalendarYear, dd.MonthNumberOfYear ORDER BY dd.CalendarYear, dd.MonthNumberOfYear;",
"how did the latest promotion affect sales revenue?": "SELECT dp.EnglishPromotionName, SUM(fis.SalesAmount) AS PromotionRevenue FROM factinternetsales fis JOIN dimpromotion dp ON fis.PromotionKey = dp.PromotionKey WHERE dp.StartDate >= DATEADD(MONTH, 0, GETDATE()) GROUP BY dp.EnglishPromotionName ORDER BY PromotionRevenue DESC;",
"which territory had the highest sales revenue?": "SELECT dst.SalesTerritoryRegion, SUM(fis.SalesAmount) AS TotalSales FROM factinternetsales fis JOIN dimsalesterritory dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey GROUP BY dst.SalesTerritoryRegion ORDER BY TotalSales DESC;",
"who are the top 5 resellers by total sales amount?": "SELECT TOP 5 dr.ResellerName, SUM(frs.SalesAmount) AS TotalSales FROM factresellersales frs JOIN dimreseller dr ON frs.ResellerKey = dr.ResellerKey GROUP BY dr.ResellerName ORDER BY TotalSales DESC;",
"what is the total sales amount by customer region?": "SELECT dg.EnglishCountryRegionName, SUM(fis.SalesAmount) AS TotalSales FROM factinternetsales fis JOIN dimcustomer dc ON fis.CustomerKey = dc.CustomerKey JOIN dimgeography dg ON dc.GeographyKey = dg.GeographyKey GROUP BY dg.EnglishCountryRegionName ORDER BY TotalSales DESC;",
"which product category had the highest average sales price?": "SELECT dpc.EnglishProductCategoryName, AVG(fis.UnitPrice) AS AvgPrice FROM factinternetsales fis JOIN dimproduct dp ON fis.ProductKey = dp.ProductKey JOIN dimproductcategory dpc ON dp.ProductSubcategoryKey = dpc.ProductCategoryKey GROUP BY dpc.EnglishProductCategoryName ORDER BY AvgPrice DESC;"
}
測試和修訂 AI 技能
已將指示和範例新增至 AI 技能。 隨著測試持續進行,更多的範例和指示可以進一步改善 AI 的技能。 請與您的同事合作,看看您提供的範例和指示是否涵蓋他們想要詢問的問題種類。
以程式設計方式使用 AI 技能
您可以在 Fabric 筆記本內以程式設計方式使用 AI 技能。 若要判斷 AI 技能是否有已發佈的網址值,請選取 [設定],如本螢幕擷取畫面所示:
在您發佈 AI 技能之前,它沒有已發佈的網址值,如本螢幕擷取畫面所示:
驗證 AI 技能的效能之後,您可能會決定發佈 AI 技能。 在此情況下,請選取 [發佈],如本螢幕擷取畫面所示:
AI 技能的已發佈網址隨即出現,如本螢幕擷取畫面所示:
然後,您可以複製已發佈的網址,並在 Fabric 筆記本中使用該網址。 如此一來,您就可以在 Fabric 筆記本中呼叫 AI 技能 API,以查詢 AI 技能。 將此程式碼片段中複製的網址貼上。 然後將問題取代為您的 AI 技能相關的任何查詢。 此範例使用 \<generic published URL value\>
作為網址。
import requests
import json
import pprint
from synapse.ml.mlflow import get_mlflow_env_config
# the URL could change if the workspace is assigned to a different capacity
url = "https://<generic published URL value>"
configs = get_mlflow_env_config()
headers = {
"Authorization": f"Bearer {configs.driver_aad_token}",
"Content-Type": "application/json; charset=utf-8"
}
question = "{userQuestion: \"what is an example product?\"}"
response = requests.post(url, headers=headers, data = question)
print("RESPONSE: ", response)
print("")
response = json.loads(response.content)
print(response["result"])