SQL(SQL 지표)

SQL(SQL 지표)

Ragas의 SQL 지표는 데이터베이스 대상 SQL 생성 쿼리를 평가하는 데 쓰여요. 쿼리를 실제로 실행해 결과를 비교하는 실행 기반 지표와, 실행 없이 쿼리 자체를 비교하는 비실행 기반 지표로 나뉘죠. 상황에 맞춰 골라 쓸 수 있어요.

출처: 문서

본문

실행 기반 지표(Execution based metrics)

이 지표들에서는 생성된 SQL을 데이터베이스에서 실행한 뒤 response를 기대 결과와 비교해요.

DataCompy 점수(DataCompy Score)

DataCompyScore 지표는 두 pandas DataFrame을 비교하는 Python 라이브러리인 DataCompy를 사용해요. 두 DataFrame을 비교하는 간단한 인터페이스를 제공하고 차이점에 대한 상세 보고서를 제공해요. 이 지표에서 response는 데이터베이스에서 실행되고, 그 결과 데이터가 기대 데이터(reference)와 비교돼요. 비교를 가능하게 하려면 responsereference 모두 예시에서 보듯이 Comma-Separated Values(CSV) 형태여야 해요.

DataFrame은 행(row) 단위 또는 열(column) 단위로 비교할 수 있어요. 이는 mode 파라미터로 구성할 수 있어요. mode가 row이면 비교가 행 단위로 이뤄져요. mode가 column이면 비교가 열 단위로 이뤄져요.

[ \text{Precision } = {|\text{Number of matching rows in response and reference}| \over |\text{Total number of rows in response}|} ]

[ \text{Recall } = {|\text{Number of matching rows in response and reference}| \over |\text{Total number of rows in reference}|} ]

기본적으로 mode는 row로 설정되고, 지표는 정밀도와 재현율의 조화 평균인 F1 점수예요.

from ragas.metrics.collections import DataCompyScore

data1 = """acct_id,dollar_amt,name,float_fld,date_fld
10000001234,123.45,George Maharis,14530.1555,2017-01-01
10000001235,0.45,Michael Bluth,1,2017-01-01
10000001236,1345,George Bluth,,2017-01-01
10000001237,123456,Bob Loblaw,345.12,2017-01-01
10000001238,1.05,Lucille Bluth,,2017-01-01
10000001238,1.05,Loose Seal Bluth,,2017-01-01
"""

data2 = """acct_id,dollar_amt,name,float_fld
10000001234,123.4,George Michael Bluth,14530.155
10000001235,0.45,Michael Bluth,
10000001236,1345,George Bluth,1
10000001237,123456,Robert Loblaw,345.12
10000001238,1.05,Loose Seal Bluth,111
"""

metric = DataCompyScore()
result = await metric.ascore(response=data1, reference=data2)
print(f"F1 Score: {result.value}")
print(f"Details: {result.reason}")

열 단위 비교로 바꾸려면 mode 파라미터를 column으로 설정해요.

metric = DataCompyScore(mode="columns", metric="recall")
result = await metric.ascore(response=data1, reference=data2)

DataCompyScore (레거시)

Deprecated ragas.metricsDataCompyScore는 사용이 중단됐으며 향후 버전에서 제거될 예정이에요. 위에서 보여준 ragas.metrics.collectionsDataCompyScore를 사용해주세요.

레거시 DataCompyScoreSingleTurnSample 스키마를 사용해요:

from ragas.metrics import DataCompyScore
from ragas.dataset_schema import SingleTurnSample

data1 = """acct_id,dollar_amt,name,float_fld,date_fld
10000001234,123.45,George Maharis,14530.1555,2017-01-01
10000001235,0.45,Michael Bluth,1,2017-01-01
10000001236,1345,George Bluth,,2017-01-01
10000001237,123456,Bob Loblaw,345.12,2017-01-01
10000001238,1.05,Lucille Bluth,,2017-01-01
10000001238,1.05,Loose Seal Bluth,,2017-01-01
"""

data2 = """acct_id,dollar_amt,name,float_fld
10000001234,123.4,George Michael Bluth,14530.155
10000001235,0.45,Michael Bluth,
10000001236,1345,George Bluth,1
10000001237,123456,Robert Loblaw,345.12
10000001238,1.05,Loose Seal Bluth,111
"""
sample = SingleTurnSample(response=data1, reference=data2)
scorer = DataCompyScore()
await scorer.single_turn_ascore(sample)

열 단위 비교로 바꾸려면 mode 파라미터를 column으로 설정해요.

scorer = DataCompyScore(mode="column", metric="recall")

비실행 기반 지표(Non Execution based metrics)

SQL 쿼리를 데이터베이스에서 실행하는 것은 시간이 오래 걸리고 때로는 실행이 불가능할 수도 있어요. 이런 경우 비실행 기반 지표로 SQL 쿼리를 평가할 수 있어요. 이 지표들은 데이터베이스에서 실행하지 않고 SQL 쿼리를 직접 비교해요.

SQL 의미적 동등성(SQL Semantic Equivalence)

SQLSemanticEquivalence는 생성된 SQL 쿼리가 reference 쿼리와 의미적으로 동등한지 평가하는 지표예요. 이 지표는 LLM을 사용해 제공된 데이터베이스 스키마 컨텍스트에서 두 쿼리를 분석하고, 같은 결과를 생성할지 결정해요.

이진 지표예요:

  • 1.0: SQL 쿼리가 의미적으로 동등함
  • 0.0: SQL 쿼리가 동등하지 않음

이 지표는 정확한 동등성 판단을 위해 데이터베이스 스키마 컨텍스트를 고려하며, 의미에 영향을 주지 않는 구문적 차이(예: active = 1 vs active = true)도 반영해요.

from openai import AsyncOpenAI
from ragas.llms.base import llm_factory
from ragas.metrics.collections import SQLSemanticEquivalence

# Initialize the LLM
client = AsyncOpenAI()
llm = llm_factory("gpt-4o-mini", client=client)

# Create the metric
metric = SQLSemanticEquivalence(llm=llm)

# Evaluate SQL equivalence
result = await metric.ascore(
    response="""
        SELECT p.product_name, SUM(oi.quantity) AS total_quantity
        FROM order_items oi
        JOIN products p ON oi.product_id = p.product_id
        GROUP BY p.product_name;
    """,
    reference="""
        SELECT products.product_name, SUM(order_items.quantity) AS total_quantity
        FROM order_items
        INNER JOIN products ON order_items.product_id = products.product_id
        GROUP BY products.product_name;
    """,
    reference_contexts=[
        """
        Table order_items:
        - order_item_id: INT
        - order_id: INT
        - product_id: INT
        - quantity: INT
        """,
        """
        Table products:
        - product_id: INT
        - product_name: VARCHAR
        - price: DECIMAL
        """
    ]
)

print(f"Equivalent: {result.value == 1.0}")
print(f"Explanation: {result.reason}")

결과에는 두 쿼리에 대한 설명과 동등성 판단의 근거가 포함돼요.


LLMSQLEquivalence (레거시)

Deprecated LLMSQLEquivalence는 사용이 중단됐으며 향후 버전에서 제거될 예정이에요. 위에서 보여준 ragas.metrics.collectionsSQLSemanticEquivalence를 사용해주세요.

LLMSQLEquivalence는 SQL 의미적 동등성 평가를 위한 레거시 지표예요. SingleTurnSample 스키마를 사용하며 LLM을 별도로 설정해야 해요.

from ragas.metrics import LLMSQLEquivalence
from ragas.dataset_schema import SingleTurnSample

sample = SingleTurnSample(
    response="""
        SELECT p.product_name, SUM(oi.quantity) AS total_quantity
        FROM order_items oi
        JOIN products p ON oi.product_id = p.product_id
        GROUP BY p.product_name;
    """,
    reference="""
        SELECT p.product_name, COUNT(oi.quantity) AS total_quantity
        FROM order_items oi
        JOIN products p ON oi.product_id = p.product_id
        GROUP BY p.product_name;
    """,
    reference_contexts=[
        """
        Table order_items:
        - order_item_id: INT
        - order_id: INT
        - product_id: INT
        - quantity: INT
        """,
        """
        Table products:
        - product_id: INT
        - product_name: VARCHAR
        - price: DECIMAL
        """
    ]
)

scorer = LLMSQLEquivalence()
scorer.llm = openai_model
await scorer.single_turn_ascore(sample)