다음을 통해 공유


AdventureWorks 데이터 세트를 사용하는 AI 기술 예제(미리 보기)

이 문서에서는 AdventureWorks 데이터 세트에서 AI 기술을 구성하는 방법을 보여 줍니다.

Important

이 기능은 프리뷰로 제공됩니다.

필수 조건

AdventureWorksDW를 사용하여 레이크하우스 만들기

먼저 레이크하우스를 만들고 필요한 데이터로 채웁니다.

웨어하우스 또는 레이크하우스에 AdventureWorksDW 인스턴스가 이미 있는 경우 이 단계를 건너뛸 수 있습니다. 그렇지 않은 경우 Notebook에서 레이크하우스를 만듭니다. Notebook을 사용하여 레이크하우스를 데이터로 채웁니다.

  1. AI 기술을 만들려는 작업 영역에서 새 Notebook을 만듭니다.

  2. Explorer 창의 왼쪽에서 + 데이터 원본을 선택합니다. 이 옵션은 기존 레이크하우스를 추가하거나 새 레이크하우스를 만듭니다.

  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 업로드 코드가 있는 Notebook을 보여 주는 스크린샷

몇 분 후 레이크 하우스가 필요한 데이터로 채워집니다.

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을(를) 사용합니다.
  • 자세한 제품 정보를 보려면 항상 FactInternetSales을(를) DimProduct과(와) 조인합니다.
  • 다양한 홍보 캠페인의 효과를 분석하는 데 DimPromotion을(를) 사용합니다.
  • 재판매인 성과의 경우 판매된 제품 수뿐만 아니라 총 판매액에도 집중합니다.
  • 시간에 따른 추세를 분석할 때 월, 분기 또는 연도별로 데이터를 그룹화하는 데 FactInternetSales을(를) 사용하고 DimDate과(와) 조인합니다.
  • 항상 FactInternetSales을(를) 해당 차원 테이블과 조인하여 데이터 일관성을 확인합니다.
  • SUM을 사용하여 총 값을 정확하게 캡처할 수 있도록 판매 데이터를 집계합니다.
  • 재무 영향을 정확하게 측정하려면 주문 수량보다 판매 수익 메트릭의 우선 순위를 지정합니다.
  • 자세한 인사이트를 얻으려면 항상 관련 차원(예: 제품, 고객, 날짜)을 기준으로 그룹화합니다.
  • 고객 인구 통계에 대해 물으면 DimCustomer을(를) 관련 팩트 테이블과 조인합니다.
  • 프로모션별 판매의 경우 FactInternetSales을(를) DimPromotion과(와) 조인하고 프로모션 이름으로 그룹화합니다.
  • 다른 통화와 관련한 비교에 DimCurrency을(를) 사용하여 판매 수치를 정규화합니다.
  • ORDER BY 절을 사용하여 관심 메트릭(예: 판매 수익, 총 주문)을 기준으로 결과를 정렬합니다.
  • DimProductListPrice은(는) 제안된 판매 가격이며, FactInternetSalesFactResellerSalesUnitPrice은(는) 각 단위가 판매된 실제 가격입니다. 매출에 대한 대부분의 사용 사례의 경우 단가를 사용해야 합니다.
  • 판매액을 기준으로 상위 재판매인 순위를 매깁니다.

이 텍스트를 모델 입력란의 노트에 복사하는 경우 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, -1, 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 Notebook 내에서 프로그래밍 방식으로 AI 기술을 사용할 수 있습니다. AI 기술에 게시된 URL 값이 있는지 여부를 확인하려면 다음 스크린샷에서 보듯이 설정을 선택합니다.

AI 기술 설정 선택 영역을 보여 주는 스크린샷

다음 스크린샷에서 보듯이 AI 기술을 게시하기 전에는 게시된 URL 값이 없습니다.

AI 기술에 게시하기 전에 게시된 URL 값이 없음을 보여 주는 스크린샷

AI 기술의 성능 유효성을 검사한 후에는 AI 기술을 게시하기로 결정할 수 있습니다. 이 경우 다음 스크린샷에 나와 있듯이 게시를 선택합니다.

게시 옵션의 선택 영역을 보여 주는 스크린샷

이 스크린샷에 나와 있듯이 AI 기술에 대한 게시된 URL이 표시됩니다.

게시된 URL을 보여 주는 스크린샷

그러면 게시된 URL을 복사하여 Fabric Notebook에서 사용할 수 있습니다. 이러한 방식으로 Fabric Notebook에서 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"])