본문으로 건너뛰기
mcpd
데몬 없음
소스

점수와 피드백

점수는 기계가 생각한 것입니다. 피드백은 사람이 생각한 것입니다. mcpd는 둘을 두 개의 시그널로 두고, 한쪽을 다른 쪽에 평균으로 녹여 넣지 않습니다.

숫자 하나가 아니라 시그널 둘

점수는 기계가 내린 평가입니다. 판정 모델, 정규 표현식, 단위 테스트 등 실행에 대해 숫자를 낼 수 있는 것이면 무엇이든 여기에 듭니다. 피드백 레코드는 사람이 내린 판단입니다. 제품에서 누른 부정 평가, 검토자가 매긴 평점, 사람이 고쳐 준 답입니다.

둘 다 trace_id나 span_id에 붙고, 둘 다 그 자체로 하나의 시그널로 들어오며, 둘 다 자기 테이블에 저장됩니다. 둘은 결코 합쳐지지 않습니다. 관련성에 0.9를 준 판정 모델과 부정 평가를 누른 고객은 둘 다 참인 진술이고, 그 둘이 어긋난다는 사실이야말로 그 실행에서 가장 쓸모 있는 정보입니다. 평균은 바로 그것을 지워 버리고, 아무도 손쓸 수 없는 숫자 하나만 남깁니다.

  • Spans

    What ran, nested, with timings

  • Logs

    Lines the run emitted

  • Metrics

    Numbers, with exemplars back to a run

  • Scores

    Machine evaluation

  • Feedback

    What a person thought

  • Aspect notes

    A sentence a model wrote about the run

trace_id Store Search Export

점수는 자기 척도를 함께 밝힙니다

min과 max는 점수의 일부입니다. 이 둘이 없으면 값을 해석할 수 없습니다. 0.86은 0에서 1까지의 척도에서는 좋은 결과이고, 0에서 5까지의 척도에서는 나쁜 결과이며, 낮을수록 좋은 거리 값일 수도 있습니다. 여섯 달 뒤 같은 프로젝트에 스코어러가 둘이 되면 어느 쪽인지 아무도 알 수 없습니다. 명세는 기본값을 0과 1로 두지만, 모든 SDK는 호출 지점에서 이 둘을 요구합니다. 기본값이 실수로 받아들여지는 일이 없게 하기 위해서입니다.

필드무엇에 쓰는가
scorer_id 이 점수를 낸 스코어러입니다. 예를 들면 answer_relevance입니다. 필수입니다.
scorer_version 점수는 같은 버전에서 나온 점수하고만 비교됩니다. 판정 모델의 프롬프트를 바꿨다면 그것은 예전 스코어러의 연장이 아니라 새 스코어러입니다.
value 숫자입니다.
min, max 그 숫자가 놓인, 밝혀 둔 척도입니다.
label 스코어러가 숫자와 함께 범주형 결과를 낼 때, 그 결과입니다.
reason 이유입니다. 판정 모델이라면 그 모델이 내놓은 설명이며, 점수를 마법이 아니라 따져 볼 수 있는 것으로 만들어 주는 부분입니다.
source live, offline, experiment 또는 manual입니다.
score_trace_id 채점 실행 자체의 트레이스입니다. 수상한 점수는 다른 실행과 똑같이 열어서 읽어 볼 수 있습니다.
cost 그 점수를 내는 데 든 비용입니다.

점수 기록하기

SDK 헬퍼는 스팬을 큐에 넣는 것과 같은 방식으로 점수를 큐에 넣습니다. 그래서 호출은 블로킹하지 않고 예외를 던질 수도 없습니다. traceId를 주지 않으면 활성 스팬의 트레이스에 붙습니다.

점수와 피드백

// A machine evaluation of the run. `min` and `max` are required: 0.86 on an
// undeclared scale cannot be compared to anything.
mcpd.score({
  traceId,
  scorerId: 'answer_relevance',
  value: 0.86,
  min: 0,
  max: 1,
  reason: 'Answered the question and gave the delivery date.',
})

// A human evaluation. Kept separate from a score, and never averaged with
// one, because the two answer different questions.
mcpd.feedback({
  traceId,
  kind: 'thumbs',
  value: 'up',
  comment: 'Exactly what the customer asked for.',
  authorKind: 'end_user',
})

// Anything you already count can travel with the trace.
mcpd.metric('support.tickets_handled', 1, 'counter', { labels: { queue: 'tier-1' } })

HTTP로는 POST /v1/api/scores이고, 본문으로 Score를 받습니다. 점수는 자기가 무엇에 대한 것인지 trace_id나 span_id로 밝혀야 합니다. 아무것에도 붙지 않은 점수는 영영 찾을 수 없는 자리에 저장되는 대신 400으로 거절됩니다. score_id를 빈 문자열로 보내면 서버가 하나 만들어 줍니다.

점수가 어디에서 왔는가

source가 scorer_id와 별개인 것은, 같은 스코어러가 한 맥락에서만 돌지 않고 그 맥락들이 서로 비교 가능하지 않기 때문입니다. 지난주의 트래픽을 오늘의 판정 모델로 다시 채점한 것은 품질이 좋아졌다는 증거가 아닙니다.

출처뜻
live트레이스가 남은 실행이 일어나는 동안 온라인으로 만들어졌습니다.
offline저장된 트레이스를 채점해 나중에 만들어졌습니다.
experiment데이터셋을 상대로 돌린 실험에서 만들어졌습니다.
manualAPI나 인터페이스를 통해 사람이 입력했습니다.

SDK를 통해 쓴 점수는 기본값이 live입니다. 나머지 셋은 직접 지정하십시오.

채점에는 돈이 들고, 그래서 기록합니다

판정 기반 평가는 대개 또 한 번의 모델 호출입니다. 프로덕션의 모든 실행을 큰 판정 모델로 채점하면 트래픽을 처리하는 것보다 더 많은 비용이 들 수 있고, 그런 청구서는 사람들이 뒤늦게 발견합니다. 그래서 Score는 스팬과 같은 모양의 cost를 싣습니다. 통화, 입력과 출력의 구분, 그리고 그 수치를 만들어 낸 가격표까지 함께입니다. HTTP API나 네이티브 수집 배치로 점수를 쓸 때 값을 채우십시오.

score_trace_id는 같은 생각의 나머지 절반입니다. 채점 실행 자체에 트레이스를 남기면 그 id가 점수에 붙습니다. 그래서 모든 것을 낮게 매기기 시작한 판정 모델은 열어서 읽고, 고장 났음을 보여 줄 수 있습니다.

사람의 피드백

피드백은 제품 쪽에서 씁니다. 사람이 실제로 누른 컨트롤에서 호출하면, 그 판단은 그 사람이 반응한 답을 만들어 낸 바로 그 트레이스에 내려앉습니다. kind가 value의 모양을 정합니다.

종류value
thumbsup 또는 down입니다.
rating숫자입니다. 척도는 그것을 만든 쪽이 밝힙니다.
correction올바른 답을 텍스트로 담습니다.
tag정해진 집합에서 고른 레이블입니다.
comment점수가 붙지 않은 자유로운 글입니다.

제품에서 올라온 부정 평가

// No traceId: it attaches to the active span's trace.
mcpd.feedback({
  kind: 'thumbs',
  value: 'down',
  comment: 'Named the wrong depot.',
  authorKind: 'end_user',
})

마스킹은 키 이름으로 맞춰 보며, 판단에 붙인 metadata에도 적용됩니다. author_id는 보낸 그대로 저장되므로, 이메일 주소 대신 가명 id를 보내십시오. 마스킹과 보존 기간을 보십시오.

나쁜 답을 찾아내는 질의

점수는 바로 이것을 위해 있습니다. has_score가 스코어러를 지목하고 score_below가 기준선을 세우면, 트레이스 목록은 그 스코어러가 그 아래에 둔 실행을 돌려줍니다. 비교는 엄격하므로 score_below=0.5는 정확히 0.5를 받은 실행을 빼놓습니다.

낮은 점수를 받은 실행 찾기

// The same client reads. This is the query that finds bad answers: every run
// that a scorer put below the bar.
const suspect = await mcpd.listTraces({
  hasScore: 'answer_relevance',
  scoreBelow: 0.5,
  limit: 10,
})
console.log(`runs scoring under 0.5: ${suspect.traces.length}`)

const recent = await mcpd.listTraces({ limit: 5, sort: 'start_time', order: 'desc' })
for (const trace of recent.traces) {
  const seconds = ((trace.durationNs ?? 0) / 1e9).toFixed(2)
  console.log(
    `${trace.traceId.slice(0, 8)}  ${trace.name.padEnd(16)} ${trace.status.padEnd(6)} ` +
      `${seconds}s  ${trace.spanCount} spans  $${(trace.cost?.totalCost ?? 0).toFixed(6)}`,
  )
}

// One run, with every span in it, ordered so a waterfall renders directly.
const detail = await mcpd.getTrace(traceId, { include: ['scores', 'feedback'] })
for (const span of detail.spans) {
  console.log(`  ${span.kind.padEnd(18)} ${span.name}`)
}

score_below는 옆에 has_score가 있어야만 뜻이 생깁니다. 스코어러를 지목하지 않은 기준선은 아무것도 아닌 것에 대한 기준선입니다. 둘 다 GET /v1/api/traces의 파라미터이므로 거기 있는 다른 모든 필터와 함께 쓸 수 있습니다. 한 모델에서 나온, 프로덕션의, 지난 하루 동안의 나쁜 답은 요청 하나입니다.

다시 읽기

GET /v1/api/scores는 기계 평가를 나열하며, scorer_id, source, trace_id, experiment_id, min_value, max_value와 시간 구간으로 거를 수 있고 커서로 페이지를 넘깁니다. source는 live, offline, experiment, manual을 받습니다. 사람이 입력한 것을 빼고 판정 모델이 낸 점수만 다시 읽는 방법이 이것입니다. GET /v1/api/feedback은 trace_id를 받아 그 실행에 달린 판단을 돌려줍니다. 실행을 지목하지 않고 프로젝트의 피드백을 나열하는 것은 이 빌드에 구현되어 있지 않으며, 엔드포인트가 그렇게 말합니다. trace_id가 없으면 그 파라미터를 이름으로 짚어 400으로 거절합니다. 예전에는 빈 목록으로 답했는데, 그러면 아무도 아무것도 판단하지 않은 것처럼 읽힙니다.

점수 목록은 order를 받지 않습니다. 최신순이며, 그 커서는 한 방향으로만 비교합니다. 실행 목록과 스팬 목록은 받으므로, 여기서는 받아들이고 버리는 대신 이름을 짚어 거절합니다. 여러 SDK 클라이언트가 피드백 질의에 설정하게 해 주는 kind, from, to, cursor 필터도 마찬가지입니다. 넷 다 한 번도 적용된 적이 없고, 이제는 넷 다 거절됩니다.

실행과 거기 붙은 모든 것을 한 번에 읽으려면 부가 항목을 이름으로 요청하십시오. GET /v1/api/traces/{trace_id}?include=scores,feedback이고, 로그까지 받으려면 include=all입니다.

트레이스 목록이 싣는 것과 싣지 않는 것

저장된 트레이스는 저마다 집계 두 개를 들고 있어서 목록에 조인이 필요 없습니다. 하나는 스코어러별 평균값입니다. answer_relevance 안에서의 평균과 groundedness 안에서의 평균은 따로입니다. 다른 하나는 종류별 피드백 개수입니다. thumbs 세 개, correction 하나 하는 식입니다. 평균이 아니라 개수인 것은, 긍정 평가 하나와 수정 하나의 평균은 양이 아니기 때문입니다.

전체 품질 점수 같은 것은 없고, 앞으로도 없습니다. 판정 모델과 정규 표현식과 고객의 부정 평가를 하나로 합친 수치는 단위도 없고 따져 볼 방법도 없는 숫자가 됩니다. mcpd는 부분들을 보여 주고, 판단은 사람 몫으로 남깁니다.

다음