Assertions로 수용 기준 자동화하기

Assertions로 수용 기준 자동화하기

리뷰어가 "정답이면 이런 내용을 담아야 해"라고 영어로 적어 둔 기준이 있다면, 그것을 자동 검사로 바꿔 볼 수 있어요. Assertions는 정답이 포함하거나 포함하지 말아야 할 내용에 대한 짧고 자유 형식의 주장이에요. 단일 run 주석 큐에서 run을 리뷰하면서 작성하면, LangSmith가 각각을 dataset example에 저장해요. 이후 어떤 오프라인 평가자든 애플리케이션의 새 출력이 각 주장을 충족하는지 확인할 수 있어요.

출처: Use assertions - 공식문서

Assertions는 이런 상황에서 쓰면 좋아요.

  • run의 실제 출력이 틀렸을 때, 정답을 직접 작성하는 대신 "올바른 답이 어떤 모습인지"를 설명하고 싶을 때
  • 리뷰 흐름에서 벗어나지 않고 자연어로 수용 기준을 캡처하고 싶을 때

참고로 Assertions는 단일 run 주석 큐run 항목에서만 사용할 수 있어요. thread 항목이나 pairwise 큐에서는 쓸 수 없고, LangSmith UI에서만 제공돼요.

추가로 LangSmith Engine은 반복 이슈로 플래그된 프로덕션 trace에 대해 assertions를 자동 제안할 수 있어요. 이슈의 오프라인 examples 흐름을 열어 Engine이 제안한 assertions를 데이터셋에 저장하기 전에 검토·편집·확장하면 돼요.

assertions 추가하기

  1. LangSmith UI 좌측 사이드바에서 Annotation Queues로 이동하고, 단일 run 큐를 열어 run을 선택해요.
  2. 사이드 패널에서 Feedback 아래의 Assertions 섹션을 찾아요.
  3. + Add를 클릭해 assertion 행을 만들어요.
  4. 주장을 요약하는 key(예: must_cite_source, must_not_invent_url)와 주장을 설명하는 한 문장의 comment를 입력해요. key는 자유 형식이고, must_ / must_not_ 접두사는 단지 명명 규칙일 뿐 LangSmith가 특별히 취급하지 않아요.
  5. 캡처할 각 기준마다 3·4 단계를 반복해요.

run 편집기는 run의 입력과 출력을 assertions 사이드 패널과 나란히 보여줘요. assertion을 하나 이상 추가하는 순간 run 편집기의 Outputs 패널은 run의 실제 출력에서, 추가한 assertions의 읽기 전용 미리보기로 전환돼요. 이 미리보기가 데이터셋에 저장되는 내용이에요. run의 실제 출력은 저장되지 않는데, assertions는 "이 run이 만든 것"이 아니라 "올바른 답이 무엇을 포함해야 하는지"를 설명하기 때문이에요.

run의 Inputs는 언제든 계속 편집할 수 있어요(예: example을 저장하기 전에 프롬프트를 다듬기). assertions가 남아 있는 동안 Outputs 패널은 assertion 미리보기에 잠긴 채 유지돼요.

  1. 사이드 패널 하단의 Add to Dataset & Next를 클릭해요(단축키: macOS는 ⌘ Enter, 그 외는 Ctrl Enter). LangSmith는 현재 run을 큐의 기본 데이터셋에 추가하거나, 기본값이 없으면 데이터셋을 고르라고 안내해요. 그러면 큐가 다음 run으로 넘어가요.

저장된 example의 outputs 필드는 JSON으로 저장돼요. 예:

{
  "assertions": [
    {
      "key": "must_cite_source",
      "comment": "The response cites the source URL it is drawing from."
    },
    {
      "key": "must_not_invent_url",
      "comment": "The response does not include URLs that do not appear in the inputs."
    }
  ]
}

example의 inputs 필드에는 run의 입력(수정했다면 편집 버전)이 저장돼요. 저장된 example의 전체 형태는 Example data format을 참고해요.

assertions를 기준으로 평가하기

저장된 assertions를 reference_outputs["assertions"]에서 읽어 assertion 하나당 피드백 점수 하나를 반환하는 오프라인 평가자를 작성해요. 최소 형태는 다음과 같아요.

def grade_against_assertions(outputs: dict, reference_outputs: dict) -> list[dict]:
    """Return one feedback score per assertion."""
    feedback = []
    for assertion in reference_outputs["assertions"]:
        # Replace with your scoring logic: LLM judge, regex, schema check, and so on.
        score = ...
        feedback.append({"key": assertion["key"], "score": score})
    return feedback

각 주장을 점수화하는 방법은 자유예요. 세 가지 패턴이 흔하고, 하나의 평가자에서 조합할 수도 있어요.

  • LLM-as-a-judge — 각 assertion마다 모델에 애플리케이션 출력과 assertion의 comment를 주고 점수를 받아요. 주장이 주관적이거나 기계적으로 검증하기 어려울 때 가장 좋아요.
  • 코드 기반 검사 — 각 assertion마다 assertion의 key를 이용해 정규식 매칭, 스키마 검증, 부분 문자열 존재 같은 결정적 검사를 실행해요. 주장에 명확하고 기계적인 답이 있을 때 가장 좋아요.
  • 부분 점수(Partial-credit) — 불리언 대신 숫자 점수(예: 0.0~1.0)를 반환해 척도로 등급을 매기고, 일부 주장만 충족한 출력에 "부분 점수"를 줄 수 있어요.

더 알아보기