AdventureWorks 数据集的 AI 技能示例(预览)

本文介绍如何在 AdventureWorks 数据集上配置 AI 技能。

重要

此功能目前为预览版

先决条件

使用 AdventureWorksDW 创建湖屋

首先,创建湖屋并使用必要的数据进行填充。

如果仓库或湖屋中已有 AdventureWorksDW 实例,则可以跳过此步骤。 如果没有,请从笔记本创建湖屋。 使用笔记本将数据填充到湖屋中。

  1. 在要在其中创建 AI 技能的工作区中创建新的笔记本。

  2. 在“资源管理器”窗格左侧,选择“+ 数据源”。 此选项可添加现有湖屋或创建新的湖屋。

  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 技能

  1. 若要创建新的 AI 技能,请转到“数据科学”体验并选择“AI 技能”。

    显示 AI 技能创建位置的屏幕截图。

  2. 输入名称以创建 AI 技能。

选择数据

选择你创建的湖屋,然后选择“连接”。 然后,必须选择希望 AI 技能可以访问的表。

本练习使用以下表:

  • DimCustomer
  • DimDate
  • DimGeography
  • DimProduct
  • DimProductCategory
  • DimPromotion
  • DimReseller
  • DimSalesTerritory
  • FactInternetSales
  • FactResellerSales

提供指令

使用所选列示表首次询问 AI 技能问题时,AI 技能会很好地回答这些问题。 例如,对于问题“最畅销的产品是什么?”,AI 技能返回:

  • Long-Sleeve Logo Jersey, L

但是,SQL 查询需要一些改进。 首先,它只查看 FactResellerSales 表。 它忽略表 FactInternetSales。 其次,当与产品关联的总销售收入是最重要的考虑因素时,它会按订单数量订购产品,如以下屏幕截图所示:

显示 AI 技能最高销量产品首个示例问题的屏幕截图。

若要改进查询生成,请提供部分指令,如以下示例所示:

  • 每当我询问“最畅销”的产品或商品时,应该关注的指标是总销售收入,而非订购数量。
  • 要使用的主表是 FactInternetSales。 仅当明确询问转售或总销售额时,才使用 FactResellerSales

再次提问后,系统将返回不同答案“Mountain-200 Black, 46”,如以下屏幕截图所示:

显示 AI 技能最高销量产品第二个示例问题的屏幕截图。

相应的 SQL 从 FactInternetSales 表提取,并按销售金额的总和进行排序。 AI 遵循了指令。

继续试验查询时,应添加更多指令。

此应用场景使用以下一组指令:

  • 每当我询问“最畅销”的产品或商品时,应该关注的指标是销售收入,而非订购数量。
  • 要使用的主表是 FactInternetSales。 仅当明确询问转售或总销售额时,才使用 FactResellerSales
  • 当询问促销的影响时,应询问对销售收入的增加,而不仅仅是销售单位的数量。
  • 对于客户见解,请专注于每个客户的总销售额,而非订单数。
  • 在执行基于时间的分析时,使用 DimDate 提取特定时间段(例如年份和月)。
  • 分析地理数据时,确定每个区域的总销售收入和平均销售额的优先级。
  • 对于产品类别见解,请始终使用 DimProductCategory 对产品进行相应分组。
  • 比较不同区域之间的销售额时,请使用 DimSalesTerritory 获取准确的区域详细信息。
  • 如果以不同的货币分析销售额,请使用 DimCurrency 规范化销售数据。
  • 有关详细的产品信息,请始终将 FactInternetSalesDimProduct 联接。
  • 使用 DimPromotion 分析不同促销活动的有效性。
  • 对于经销商业绩,请专注于总销售额,而不仅仅是售出的产品数。
  • 分析随时间推移的趋势时,请使用 FactInternetSales 并与 DimDate 联接,按月份、季度或年份对数据进行分组。
  • 始终通过将 FactInternetSales 与相应的维度表联接来检查数据一致性。
  • 使用 SUM 聚合销售数据,以确保准确捕获总值。
  • 将销售收入指标的优先级设为高于订单数量,以准确衡量财务影响。
  • 始终按相关维度(例如产品、客户、日期)分组,以获取详细见解。
  • 当询问客户人口统计数据时,请将 DimCustomer 与相关事实数据表进行联接。
  • 对于按促销销售,请将 FactInternetSalesDimPromotion 联接,并按促销名称分组。
  • 使用 DimCurrency 规范化销售数据,以进行涉及不同货币的数据比较。
  • 使用 ORDER BY 子句按兴趣指标(如销售收入、订单总数)对结果进行排序。
  • DimProduct 中的 ListPrice 是建议的销售价格,而 UnitPriceFactInternetSales 中的 FactResellerSales 是每个单位销售的实际价格。 对于收入的大多数用例,应使用单位价格。
  • 按销售金额对排名靠前的经销商排序。

如果将此文本复制到“模型的注释”文本框中,则 AI 会在生成其 SQL 查询时引用这些指令。

提供示例

除指令外,示例也可作为指导 AI 的另一有效方法。 如果对 AI 技能的常见接收信息存在疑问,或存在需要复杂联接的问题,请考虑为它们添加示例。

例如,问题“在 2013 年 6 月 1 日,我们有多少活跃客户”会生成部分有效的 SQL,如以下屏幕截图所示:

显示 AI 技能活跃客户计数首个问题示例的屏幕截图。

然而,这不是优秀答案。

部分问题是“活跃客户”无正式定义。 “模型的注释”文本框中的更多说明可能会有所帮助,但用户可能会经常提出此问题。 需要确保 AI 能够正确处理问题。 相关查询比较复杂,因此请选择“编辑”按钮提供示例。

显示可在何处编辑向 AI 所提供示例的屏幕截图。

然后,可以上传示例。

显示 AI 技能 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 技能是否具有已发布的 URL 值,请选择“设置”,如以下屏幕截图所示:

显示选择 AI 技能集的屏幕截图。

在发布 AI 技能之前,该技能没有已发布的 URL 值,如以下屏幕截图所示:

显示 AI 技能在发布前不存在已发布 URL 值的屏幕截图。

验证 AI 技能的性能后,你可能会决定予以发布。 在这种情况下,请选择“发布”,如以下屏幕截图所示:

显示选择“发布”选项的屏幕截图。

系统将显示 AI 技能的已发布 URL,如以下屏幕截图所示:

显示已发布 URL 的屏幕截图。

然后,可以复制已发布的 URL 并将其用于 Fabric 笔记本。 以此,就可以通过在 Fabric 笔记本中调用 AI 技能 API 来查询 AI 技能。 将复制的 URL 粘贴到此代码片段中。 然后,将问题替换为与 AI 技能相关的任何查询。 此示例使用 \<generic published URL value\> 作为 URL。

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"])