에이전트·도구 사용 평가(Agentic or Tool use)

에이전트·도구 사용 평가(Agentic or Tool use)

에이전트형 또는 도구 사용 워크플로는 여러 차원에서 평가할 수 있어요. 주제 준수(Topic Adherence), 도구 호출 정확도(Tool Call Accuracy), 도구 호출 F1(Tool Call F1), 에이전트 목표 달성도(Agent Goal Accuracy) 같은 지표들이죠. 각각이 어떤 측면을 보는지, 어떤 기준(순서·파라미터·결과)으로 평가하는지에 따라 골라 쓸 수 있어요.

출처: 문서

본문

에이전트형 또는 도구 사용 워크플로는 여러 차원에서 평가할 수 있어요. 주어진 작업에서 에이전트 또는 도구의 성능을 평가하는 데 사용할 수 있는 몇 가지 지표를 소개할게요.

주제 준수(Topic Adherence)

실제 애플리케이션에 배포된 AI 시스템은 사용자와 상호작용할 때 관심 도메인을 준수할 것으로 기대돼요. 하지만 LLM은 이 제한을 무시하고 일반 질문에 답할 때가 있어요. 주제 준수 지표는 상호작용 중 AI가 사전 정의된 도메인에 머무르는 능력을 평가해요. 이 지표는 AI가 사전 정의된 도메인과 관련된 쿼리에만 도움을 제공할 것으로 기대되는 대화형 AI 시스템에서 특히 중요해요.

TopicAdherence는 AI 시스템이 준수해야 할 사전 정의된 주제 집합을 요구하며, 이는 reference_topics와 함께 user_input으로 제공돼요. 이 지표는 주제 준수의 정밀도(precision), 재현율(recall), F1 점수를 계산할 수 있으며 다음과 같이 정의돼요:

[ \text{Precision } = {|\text{Queries that are answered and are adheres to any present reference topics}| \over |\text{Queries that are answered and are adheres to any present reference topics}| + |\text{Queries that are answered and do not adheres to any present reference topics}|} ]

[ \text{Recall } = {|\text{Queries that are answered and are adheres to any present reference topics}| \over |\text{Queries that are answered and are adheres to any present reference topics}| + |\text{Queries that were refused and should have been answered}|} ]

[ \text{F1 Score } = {2 \times \text{Precision} \times \text{Recall} \over \text{Precision} + \text{Recall}} ]

예시(Example)

import asyncio
from openai import AsyncOpenAI
from ragas.llms.base import llm_factory
from ragas.metrics.collections import TopicAdherence
from ragas.messages import HumanMessage, AIMessage, ToolMessage, ToolCall

async def evaluate_topic_adherence():
    # Setup LLM
    client = AsyncOpenAI()
    llm = llm_factory("gpt-4o-mini", client=client)

    user_input = [
        HumanMessage(
            content="Can you provide me with details about Einstein's theory of relativity?"
        ),
        AIMessage(
            content="Sure, let me retrieve the relevant information for you.",
            tool_calls=[
                ToolCall(
                    name="document_search",
                    args={"query": "Einstein's theory of relativity"},
                )
            ],
        ),
        ToolMessage(
            content="Found relevant documents: 1. Relativity: The Special and the General Theory, 2. General Theory of Relativity by A. Einstein."
        ),
        AIMessage(
            content="I found some documents on Einstein's theory of relativity. Which one would you like to know more about: 'Relativity: The Special and the General Theory' or 'General Theory of Relativity by A. Einstein'?"
        ),
        HumanMessage(content="Tell me about the 'General Theory of Relativity'."),
        AIMessage(
            content="Got it! Let me fetch more details from 'General Theory of Relativity by A. Einstein'.",
            tool_calls=[
                ToolCall(
                    name="document_retrieve",
                    args={"document": "General Theory of Relativity by A. Einstein"},
                )
            ],
        ),
        ToolMessage(
            content="The document discusses how gravity affects the fabric of spacetime, describing the relationship between mass and spacetime curvature."
        ),
        AIMessage(
            content="The 'General Theory of Relativity' explains how gravity affects the fabric of spacetime and the relationship between mass and spacetime curvature. Would you like more details or a specific explanation?"
        ),
        HumanMessage(
            content="No, that's perfect. By the way, do you know any good recipes for a chocolate cake?"
        ),
        AIMessage(
            content="Sure! Let me find a simple and delicious recipe for a chocolate cake.",
            tool_calls=[ToolCall(name="recipe_search", args={"query": "chocolate cake recipe"})]
        ),
        ToolMessage(
            content="Here's a popular recipe for a chocolate cake: Ingredients include flour, sugar, cocoa powder, eggs, milk, and butter. Instructions: Mix dry ingredients, add wet ingredients, and bake at 350°F for 30-35 minutes."
        ),
        AIMessage(
            content="I found a great recipe for chocolate cake! Would you like the full details, or is that summary enough?"
        ),
    ]

    # Evaluate with precision mode
    metric = TopicAdherence(llm=llm, mode="precision")
    result = await metric.ascore(
        user_input=user_input,
        reference_topics=["science"],
    )
    print(f"Topic Adherence (precision): {result.value}")

if __name__ == "__main__":
    asyncio.run(evaluate_topic_adherence())

출력(Output)

Topic Adherence (precision): 0.6666666666444444

mode를 recall로 바꾸려면 mode 파라미터를 recall로 설정해요.

metric = TopicAdherence(llm=llm, mode="recall")

출력(Output)

0.99999999995

레거시 API(Legacy API, 사용 중단)

폐지 공지(Deprecation Notice) ragas.metrics의 레거시 TopicAdherenceScore는 사용이 중단됐으며 v1.0에서 제거될 예정이에요. 동일 기능을 현대 API로 제공하는 ragas.metrics.collections.TopicAdherence로 마이그레이션해주세요.

레거시 API는 여전히 사용할 수 있지만 MultiTurnSample이 필요해요:

from ragas.dataset_schema import MultiTurnSample
from ragas.messages import HumanMessage, AIMessage, ToolMessage, ToolCall
from ragas.metrics import TopicAdherenceScore  # Legacy import
from ragas.llms import LangchainLLMWrapper
from langchain_openai import ChatOpenAI

evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))

sample = MultiTurnSample(
    user_input=[...],  # conversation messages
    reference_topics=["science"],
)
scorer = TopicAdherenceScore(llm=evaluator_llm, mode="precision")
score = await scorer.multi_turn_ascore(sample)

도구 호출 정확도(Tool call Accuracy)

ToolCallAccuracy는 LLM 에이전트가 기대되는 도구 호출과 비교해 도구를 얼마나 정확하게 호출하는지 측정해요. 도구 호출의 시퀀스와 인자의 정확성 모두를 평가해요. 이 지표는 다단계 워크플로에서 에이전트가 올바른 도구를 올바른 파라미터로 호출하는지 검증하는 데 특히 유용해요.

이 지표는 user_input(대화 메시지)과 reference_tool_calls(기대 도구 호출)을 요구해요. 0과 1 사이의 점수를 반환하며, 값이 높을수록 성능이 좋다는 뜻이에요.

주요 기능(Key Features)

두 가지 평가 모드(Two Evaluation Modes):

  1. 엄격한 순서(Strict Order, 기본값): 도구 호출이 시퀀스에서 정확히 일치해야 해요.

    사용처: 순서가 중요한 순차 워크플로 예: 결과를 필터링하기 전에 먼저 검색해야 함

  2. 유연한 순서(Flexible Order): 도구 호출이 어떤 순서든 상관없어요.

    사용처: 순서가 중요하지 않은 병렬 연산 예: 여러 도시의 날씨를 동시에 가져오기

점수 매기기(Scoring):

  • 시퀀스 정렬을 평가해요(올바른 순서의 올바른 도구)
  • 인자 정확성을 평가해요(각 도구에 대한 올바른 파라미터)
  • 최종 점수 = (인자 정확성) × (시퀀스 정렬 ? 1 : 0)

예시: 기본 사용법(Example: Basic Usage)

import asyncio
from ragas.metrics.collections import ToolCallAccuracy
from ragas.messages import AIMessage, HumanMessage, ToolCall

async def evaluate_tool_call_accuracy():
    # Define the conversation with tool calls
    user_input = [
        HumanMessage(content="What's the weather like in New York right now?"),
        AIMessage(
            content="The current temperature in New York is 75°F and it's partly cloudy.",
            tool_calls=[ToolCall(name="weather_check", args={"location": "New York"})],
        ),
        HumanMessage(content="Can you translate that to Celsius?"),
        AIMessage(
            content="Let me convert that to Celsius for you.",
            tool_calls=[
                ToolCall(
                    name="temperature_conversion", args={"temperature_fahrenheit": 75}
                )
            ],
        ),
    ]

    # Define expected tool calls
    reference_tool_calls = [
        ToolCall(name="weather_check", args={"location": "New York"}),
        ToolCall(name="temperature_conversion", args={"temperature_fahrenheit": 75}),
    ]

    # Evaluate
    metric = ToolCallAccuracy()
    result = await metric.ascore(
        user_input=user_input,
        reference_tool_calls=reference_tool_calls,
    )
    print(f"Tool Call Accuracy: {result.value}")

if __name__ == "__main__":
    asyncio.run(evaluate_tool_call_accuracy())

출력(Output):

Tool Call Accuracy: 1.0

예시: 유연한 순서 모드(Example: Flexible Order Mode)

도구 호출이 병렬로 일어날 수 있는 시나리오의 경우:

# Enable flexible order mode
metric = ToolCallAccuracy(strict_order=False)

user_input = [
    HumanMessage(content="Get weather for Paris and London"),
    AIMessage(
        content="Fetching weather data...",
        tool_calls=[
            ToolCall(name="weather_check", args={"location": "London"}),
            ToolCall(name="weather_check", args={"location": "Paris"}),
        ],
    ),
]

reference_tool_calls = [
    ToolCall(name="weather_check", args={"location": "Paris"}),
    ToolCall(name="weather_check", args={"location": "London"}),
]

result = await metric.ascore(
    user_input=user_input,
    reference_tool_calls=reference_tool_calls,
)
print(f"Score: {result.value}")  # 1.0 (order doesn't matter)

채점 예시(Scoring Examples)

완벽 일치(Perfect match):

# All tools called correctly with correct arguments
Expected: [weather_check(location="Paris"), translate(text="hello")]
Got:      [weather_check(location="Paris"), translate(text="hello")]
Score: 1.0

부분 인자 일치(Partial argument match):

# Some arguments incorrect
Expected: [search(query="python", limit=10, sort="date")]
Got:      [search(query="python", limit=10, sort="relevance")]
Score: 0.66 (2 out of 3 arguments match)

잘못된 순서(엄격 모드, Wrong order):

# Correct tools but wrong sequence
Expected: [search(...), filter(...)]
Got:      [filter(...), search(...)]
Score: 0.0 (sequence not aligned)

사용 사례(Use Cases)

  1. 에이전트 검증(Agent Validation): 에이전트가 도구를 올바르게 사용하는지 테스트해요
  2. 회귀 테스트(Regression Testing): 변경 후에도 도구 호출이 퇴화하지 않도록 해요
  3. 다단계 워크플로(Multi-Step Workflows): 복잡한 순차 연산을 검증해요
  4. 도구 선택(Tool Selection): 에이전트가 많은 옵션에서 올바른 도구를 고르는지 확인해요

다른 지표를 언제 사용할까(When to Use Different Metrics)

Metric Use When
ToolCallAccuracy You care about exact tool sequence and arguments
ToolCallF1 You want precision/recall metrics for tool calling
AgentGoalAccuracy You care about outcome, not the specific tools used

예시: "Book me a flight to Paris"의 경우, 예약이 성공하는지만 신경 쓴다면(어떤 중간 도구가 호출됐는지가 아니라) AgentGoalAccuracyWithReference를 사용하세요.

레거시 API(Legacy API, 사용 중단)

폐지 공지(Deprecation Notice) ragas.metrics의 레거시 ToolCallAccuracy는 사용이 중단됐으며 v1.0에서 제거될 예정이에요. 동일 기능을 현대 API로 제공하는 ragas.metrics.collections.ToolCallAccuracy로 마이그레이션해주세요.

레거시 API는 여전히 사용할 수 있지만 MultiTurnSample이 필요해요:

from ragas.dataset_schema import MultiTurnSample
from ragas.messages import AIMessage, HumanMessage, ToolCall
from ragas.metrics import ToolCallAccuracy  # Legacy import

sample = MultiTurnSample(
    user_input=[
        HumanMessage(content="What's the weather in New York?"),
        AIMessage(
            content="Checking weather...",
            tool_calls=[ToolCall(name="weather_check", args={"location": "New York"})],
        ),
    ],
    reference_tool_calls=[
        ToolCall(name="weather_check", args={"location": "New York"}),
    ],
)

scorer = ToolCallAccuracy()
score = await scorer.multi_turn_ascore(sample)

레거시 버전은 커스텀 인자 비교 지표도 지원했어요:

from ragas.metrics._string import NonLLMStringSimilarity
from ragas.metrics._tool_call_accuracy import ToolCallAccuracy

metric = ToolCallAccuracy()
metric.arg_comparison_metric = NonLLMStringSimilarity()

도구 호출 F1(Tool Call F1)

ToolCallF1은 에이전트가 만든 도구 호출의 정밀도와 재현율을 기반으로 F1 점수를 반환하는 지표로, 기대 호출(reference_tool_calls) 집합과 비교해요. ToolCallAccuracy가 정확한 순서와 내용 일치에 기반한 이진 점수를 제공하는 반면, ToolCallF1은 온보딩과 반복에 유용한 더 부드러운 평가를 제공해 이를 보완해요. 에이전트가 기대 동작에 얼마나 가까웠는지(과다 또는 과소 호출이 있어도) 정량화하는 데 도움을 줘요.

공식(Formula)

ToolCallF1은 고전적인 IR(정보 검색) 지표를 기반으로 해요. 순서 없는 일치를 사용하므로 도구가 호출된 순서는 결과에 영향을 주지 않고, 오직 도구 이름과 파라미터의 존재와 정확성만 고려해요.

[ \text{Precision} = \frac{\text{tool calls that match both name and parameters}}{\text{tool calls that match both name and parameters} + \text{extra tool calls that were not expected}} ]

[ \text{Recall} = \frac{\text{tool calls that match both name and parameters}}{\text{tool calls that match both name and parameters} + \text{expected tool calls that were not made}} ]

[ \text{F1} = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} ]

Topic Adherence와 어떻게 다른가(How is it different from Topic Adherence?)

ToolCallF1TopicAdherenceScore 둘 다 precision, recall, F1 점수를 사용하지만 평가하는 측면이 달라요: | Metric | Evaluates | Based on | |---|---|---| | ToolCallF1 | Correctness of tool executions | Structured tool call objects | | TopicAdherenceScore | Whether the conversation stays on-topic | Comparison of domain topics |

에이전트가 도구를 올바르게 실행했는지 추적하고 싶을 때 ToolCallF1을 사용하세요. 내용이나 의도가 허용 주제 안에 머무는지 평가할 때는 TopicAdherenceScore를 사용하세요.

예시: 기본 사용법(Example: Basic Usage)

import asyncio
from ragas.metrics.collections import ToolCallF1
from ragas.messages import HumanMessage, AIMessage, ToolCall

async def evaluate_tool_call_f1():
    # Define the conversation with tool calls
    user_input = [
        HumanMessage(content="What's the weather like in Paris today?"),
        AIMessage(
            content="Let me check that for you.",
            tool_calls=[ToolCall(name="weather_check", args={"location": "Paris"})],
        ),
        HumanMessage(content="And the UV index?"),
        AIMessage(
            content="Sure, here's the UV index for Paris.",
            tool_calls=[ToolCall(name="uv_index_lookup", args={"location": "Paris"})],
        ),
    ]

    # Define expected tool calls
    reference_tool_calls = [
        ToolCall(name="weather_check", args={"location": "Paris"}),
        ToolCall(name="uv_index_lookup", args={"location": "Paris"}),
    ]

    # Evaluate
    metric = ToolCallF1()
    result = await metric.ascore(
        user_input=user_input,
        reference_tool_calls=reference_tool_calls,
    )
    print(f"Tool Call F1: {result.value}")

if __name__ == "__main__":
    asyncio.run(evaluate_tool_call_f1())

출력(Output):

Tool Call F1: 1.0

예시: 추가 도구 호출(Example: Extra Tool Called)

에이전트가 reference에 없는 추가 도구 호출을 만들 때:

user_input = [
    HumanMessage(content="What's the weather like in Paris today?"),
    AIMessage(
        content="Let me check that for you.",
        tool_calls=[ToolCall(name="weather_check", args={"location": "Paris"})],
    ),
    HumanMessage(content="And the UV index?"),
    AIMessage(
        content="Sure, here's the UV index and air quality for Paris.",
        tool_calls=[
            ToolCall(name="uv_index_lookup", args={"location": "Paris"}),
            ToolCall(name="air_quality", args={"location": "Paris"}),  # extra call
        ],
    ),
]

reference_tool_calls = [
    ToolCall(name="weather_check", args={"location": "Paris"}),
    ToolCall(name="uv_index_lookup", args={"location": "Paris"}),
]

result = await metric.ascore(
    user_input=user_input,
    reference_tool_calls=reference_tool_calls,
)
print(f"F1 Score: {result.value}")

출력(Output):

F1 Score: 0.67

이 경우:

  • TP = 2 (weather_check, uv_index_lookup)
  • FP = 1 (air_quality)
  • FN = 0
  • Precision = 2/3 = 0.67, Recall = 2/2 = 1.0, F1 = 0.67

채점 예시(Scoring Examples)

완벽 일치(Perfect match):

# All tools called correctly
Reference: [weather_check(location="Paris"), uv_index_lookup(location="Paris")]
Got:       [weather_check(location="Paris"), uv_index_lookup(location="Paris")]
F1 Score: 1.0

누락된 도구 호출(Missing tool call):

# One expected tool not called
Reference: [weather_check(...), uv_index_lookup(...)]
Got:       [weather_check(...)]
F1 Score: 0.67 (TP=1, FP=0, FN=1)

잘못된 인자(Wrong arguments):

# Tool name matches but args differ
Reference: [weather_check(location="Paris")]
Got:       [weather_check(location="London")]
F1 Score: 0.0 (no match, arguments must be exact)

레거시 API(Legacy API, 사용 중단)

폐지 공지(Deprecation Notice) ragas.metrics의 레거시 ToolCallF1은 사용이 중단됐으며 v1.0에서 제거될 예정이에요. 동일 기능을 현대 API로 제공하는 ragas.metrics.collections.ToolCallF1로 마이그레이션해주세요.

레거시 API는 여전히 사용할 수 있지만 MultiTurnSample이 필요해요:

from ragas.metrics import ToolCallF1  # Legacy import
from ragas.dataset_schema import MultiTurnSample
from ragas.messages import HumanMessage, AIMessage, ToolCall

sample = MultiTurnSample(
    user_input=[
        HumanMessage(content="What's the weather like in Paris today?"),
        AIMessage(
            content="Let me check that for you.",
            tool_calls=[ToolCall(name="weather_check", args={"location": "Paris"})],
        ),
    ],
    reference_tool_calls=[
        ToolCall(name="weather_check", args={"location": "Paris"}),
    ],
)

scorer = ToolCallF1()
score = await scorer.multi_turn_ascore(sample)

에이전트 목표 정확도(Agent Goal Accuracy)

에이전트 목표 정확도는 사용자의 목표를 식별하고 달성하는 LLM의 성능을 평가하는 데 사용할 수 있는 지표예요. 이진 지표로, 1은 AI가 목표를 달성했음을, 0은 목표를 달성하지 못했음을 나타내요.

reference와 함께(With Reference)

AgentGoalAccuracyWithReference는 워크플로의 종료 상태를 제공된 reference 결과와 비교해 에이전트가 사용자 목표를 달성했는지 평가해요. reference는 기대/이상적인 결과를 나타내요.

import asyncio
from openai import AsyncOpenAI
from ragas.llms.base import llm_factory
from ragas.metrics.collections import AgentGoalAccuracyWithReference
from ragas.messages import AIMessage, HumanMessage, ToolCall, ToolMessage

async def evaluate_agent_goal_accuracy_with_reference():
    # Setup LLM
    client = AsyncOpenAI()
    llm = llm_factory("gpt-4o-mini", client=client)

    user_input = [
        HumanMessage(
            content="Hey, book a table at the nearest best Chinese restaurant for 8:00pm"
        ),
        AIMessage(
            content="Sure, let me find the best options for you.",
            tool_calls=[
                ToolCall(
                    name="restaurant_search",
                    args={"cuisine": "Chinese", "time": "8:00pm"},
                )
            ],
        ),
        ToolMessage(
            content="Found a few options: 1. Golden Dragon, 2. Jade Palace"
        ),
        AIMessage(
            content="I found some great options: Golden Dragon and Jade Palace. Which one would you prefer?"
        ),
        HumanMessage(content="Let's go with Golden Dragon."),
        AIMessage(
            content="Great choice! I'll book a table for 8:00pm at Golden Dragon.",
            tool_calls=[
                ToolCall(
                    name="restaurant_book",
                    args={"name": "Golden Dragon", "time": "8:00pm"},
                )
            ],
        ),
        ToolMessage(content="Table booked at Golden Dragon for 8:00pm."),
        AIMessage(
            content="Your table at Golden Dragon is booked for 8:00pm. Enjoy your meal!"
        ),
        HumanMessage(content="thanks"),
    ]

    metric = AgentGoalAccuracyWithReference(llm=llm)
    result = await metric.ascore(
        user_input=user_input,
        reference="Table booked at one of the chinese restaurants at 8 pm",
    )
    print(f"Agent Goal Accuracy: {result.value}")

if __name__ == "__main__":
    asyncio.run(evaluate_agent_goal_accuracy_with_reference())

출력(Output)

Agent Goal Accuracy: 1.0

reference 없이(Without Reference)

AgentGoalAccuracyWithoutReference는 reference를 요구하지 않고 에이전트가 사용자 목표를 달성했는지 평가해요. 이 지표는 대화에서 사용자의 의도한 목표와 달성된 결과를 모두 추론한 다음 이를 비교해요.

import asyncio
from openai import AsyncOpenAI
from ragas.llms.base import llm_factory
from ragas.metrics.collections import AgentGoalAccuracyWithoutReference
from ragas.messages import AIMessage, HumanMessage, ToolCall, ToolMessage

async def evaluate_agent_goal_accuracy_without_reference():
    # Setup LLM
    client = AsyncOpenAI()
    llm = llm_factory("gpt-4o-mini", client=client)

    user_input = [
        HumanMessage(
            content="Hey, book a table at the nearest best Chinese restaurant for 8:00pm"
        ),
        AIMessage(
            content="Sure, let me find the best options for you.",
            tool_calls=[
                ToolCall(
                    name="restaurant_search",
                    args={"cuisine": "Chinese", "time": "8:00pm"},
                )
            ],
        ),
        ToolMessage(
            content="Found a few options: 1. Golden Dragon, 2. Jade Palace"
        ),
        AIMessage(
            content="I found some great options: Golden Dragon and Jade Palace. Which one would you prefer?"
        ),
        HumanMessage(content="Let's go with Golden Dragon."),
        AIMessage(
            content="Great choice! I'll book a table for 8:00pm at Golden Dragon.",
            tool_calls=[
                ToolCall(
                    name="restaurant_book",
                    args={"name": "Golden Dragon", "time": "8:00pm"},
                )
            ],
        ),
        ToolMessage(content="Table booked at Golden Dragon for 8:00pm."),
        AIMessage(
            content="Your table at Golden Dragon is booked for 8:00pm. Enjoy your meal!"
        ),
        HumanMessage(content="thanks"),
    ]

    metric = AgentGoalAccuracyWithoutReference(llm=llm)
    result = await metric.ascore(user_input=user_input)
    print(f"Agent Goal Accuracy: {result.value}")

if __name__ == "__main__":
    asyncio.run(evaluate_agent_goal_accuracy_without_reference())

출력(Output)

Agent Goal Accuracy: 1.0

레거시 API(Legacy API, 사용 중단)

폐지 공지(Deprecation Notice) ragas.metrics의 레거시 AgentGoalAccuracyWithReferenceAgentGoalAccuracyWithoutReference는 사용이 중단됐으며 v1.0에서 제거될 예정이에요. 동일 기능을 현대 API로 제공하는 ragas.metrics.collections로 마이그레이션해주세요.

레거시 API는 여전히 사용할 수 있지만 MultiTurnSample이 필요해요:

from ragas.dataset_schema import MultiTurnSample
from ragas.messages import AIMessage, HumanMessage, ToolCall, ToolMessage
from ragas.metrics import AgentGoalAccuracyWithReference  # Legacy import
from ragas.llms import LangchainLLMWrapper
from langchain_openai import ChatOpenAI

evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))

sample = MultiTurnSample(
    user_input=[...],  # conversation messages
    reference="Table booked at one of the chinese restaurants at 8 pm",
)
scorer = AgentGoalAccuracyWithReference(llm=evaluator_llm)
score = await scorer.multi_turn_ascore(sample)