LabHub
배우기 러닝패스 코스

AI Agents — A Graph, Not a Model

Accuracy Held, but Other Cases Broke

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

노드를 감싸 어디서 무엇을 했는지 장부에 남기고, 골든 세트로 정확도와 틀린 건의 목록을 낸다. 규칙을 고친 두 번째 판과 견주어 새로 깨진 것과 새로 고쳐진 것을 이름으로 가르고, 비용과 경로의 변화까지 잰다.

왜 중요한가

에이전트를 고친 뒤 "좋아졌나" 를 점수 하나로 묻는 것이 흔하다. 그런데 점수가 같아도 안에서 하나가 고쳐지고 하나가 깨졌다면 그것은 좋아진 것이 아니라 바뀐 것이다. 점수는 개수이고, 우리가 알아야 하는 것은 이름이다. 관측은 노드를 한 겹 감싸면 된다. 이때 중요한 선택이 하나 있다 — 시간도 재 두지만 판정에는 쓰지 않는다. 같은 코드·같은 입력이어도 시간은 기계와 부하에 따라 달라지고, 시간으로 판정하는 회귀 검사는 흔들리다가 결국 꺼진다. 판정에는 횟수와 크기를 쓴다. 골든 세트는 작아도 되지만 매번 같은 것이어야 한다. 그리고 지금 틀리는 건을 남겨 두어야 고쳤을 때 고쳐진 것이 보인다. 전부 맞는 골든 세트는 아무것도 잡아내지 못한다. 품질이 그대로여도 비용과 경로는 회귀할 수 있다. 노드 호출 수는 같은 입력에 늘 같은 값이라 회귀 지표로 쓸 수 있고, 발자국이 달라졌다면 답이 같아 보여도 다른 동작이다. 채점기는 여러분이 적어 둔 설명을 믿지 않는다. 여러분의 모듈을 실제로 불러 임의의 문의로 돌려 보고, 골든 세트의 판정과 두 판의 차이를 채점기가 따로 계산한 값과 대조한다.

단계

  1. /root/work/ageval/evalkit.pyLABELS·ANSWER·classify_v1·State·노드 다섯(normalize·refund·shipping·other·finishROUTE·build_graph(version="v1")·run_one(text, version="v1") 을 만드세요.
  2. PROFILE·reset_profile()·instrument(name, fn) 을 더하고 build_graph 가 모든 노드를 감싸서 더하게 하세요.
  3. hotspots(texts, version="v1") 을 더해 노드별 호출 수와 가장 바쁜 노드를 내게 하세요.
  4. GOLDENevaluate(version="v1") 을 더해 정확도와 틀린 건의 목록을 내게 하세요.
  5. classify_v2compare(old="v1", new="v2") 를 더해 새로 깨진 건과 새로 고쳐진 건을 가르게 하세요.
  6. cost_delta(old="v1", new="v2") 를 더해 노드 호출 수의 변화를 재게 하세요.
  7. path_changes(old="v1", new="v2") 를 더해 발자국이 달라진 건을 찾게 하세요.
  8. /root/work/ageval/eval_report.json/root/work/ageval/eval_report.md 에 잰 것을 기록하세요.

참고

문의를 갈래로 보낸다

/root/work/ageval/evalkit.pyLABELS·ANSWER·classify_v1·State·노드 다섯·ROUTE·build_graph(version="v1")·run_one(text, version="v1") 을 만드세요.

normalize 가 만든 clean 을 보고 분류합니다. 조건 함수는 라벨을 돌려주고 ROUTE 가 어느 노드로 갈지 정합니다 — 라벨 이름과 노드 이름을 같게 두지 않은 것은 경로 지도가 하는 일을 분명히 보이려는 것입니다. version 인자는 지금은 "v1" 하나만 받습니다.

노드를 감싸 장부를 남긴다

PROFILE·reset_profile()·instrument(name, fn) 을 더하고 build_graph 가 다섯 노드를 모두 감싸서 더하게 하세요. 장부에는 calls·written·ms 를 남깁니다.

감싸는 함수는 원래 노드를 부르고 그 결과를 그대로 돌려주면서 옆에 숫자를 적습니다. written 은 그 노드가 돌려준 딕셔너리의 열쇠 수입니다. 시간도 함께 재 두되 판정에는 쓰지 않는다는 것을 주석으로 적어 두세요 — 왜 그런지가 이 단계의 핵심입니다.

어느 노드가 제일 바쁜가

hotspots(texts, version="v1") 을 더해 {"calls": {...}, "total_calls": 정수, "busiest": 문자열, "timed": [...]} 를 내게 하세요. 부를 때마다 장부를 새로 폅니다.

장부를 비우지 않으면 앞 실행의 숫자가 섞여 무엇을 재고 있는지 알 수 없게 됩니다. busiest 는 호출 수가 가장 많은 노드이고 동점이면 이름 오름차순으로 갈라 매번 같은 답이 나오게 하세요. timed 는 시간이 기록된 노드의 이름 목록입니다.

손으로 정답을 붙인 여섯 건

GOLDEN 여섯 쌍과 evaluate(version="v1") 을 더해 {"total", "correct", "accuracy", "wrong"} 을 내게 하세요. wrong 에는 text·gold·got 를 담습니다.

골든 세트는 작아도 되지만 매번 같은 것이어야 합니다. 그리고 지금 틀리는 건을 남겨 두어야 고쳤을 때 고쳐진 것이 보입니다 — 전부 맞는 골든 세트는 아무것도 잡아내지 못합니다. 정확도만 내지 말고 틀린 건의 이름을 함께 내세요.

점수는 같은데 다른 건이 틀린다

classify_v2compare(old="v1", new="v2") 를 더하세요. 답은 {"old_accuracy", "new_accuracy", "newly_broken", "newly_fixed"} 이고 두 목록은 정렬합니다.

classify_v2"반품" 을 환불로 보게 하면서 검사 순서를 바꾼 판입니다. 두 판의 정확도를 먼저 재 보고, 그 숫자만으로 판단이 되는지 물어보세요. 옛 판에서 맞던 것이 새 판에서 틀리는 건과 그 반대를 각각 모으면 점수가 감추던 것이 보입니다.

품질이 같아도 비용이 달라진다

cost_delta(old="v1", new="v2") 를 더해 {"old_calls", "new_calls", "delta"} 를 내게 하세요. 골든 세트 전체를 한 번씩 돌린 뒤의 노드 호출 수입니다.

호출 수는 같은 입력에 늘 같은 값이라 회귀 지표로 쓸 수 있습니다 — 시간과 다른 점이 그것입니다. 앞 단계에서 만든 hotspots 를 그대로 쓰면 됩니다. 이 그래프에서는 어느 갈래로 가든 노드 수가 같은데, 그렇다면 delta 가 무엇을 말해 주는지도 생각해 보세요.

같은 답이 다른 길로 나왔다

path_changes(old="v1", new="v2") 를 더해 발자국이 달라진 건만 [{"text", "old", "new"}, ...]text 오름차순으로 내게 하세요.

라벨이 같아도 지나온 노드가 다르면 다른 동작입니다. 지금은 답이 같아 보여도 다음 변경에서 다르게 갈라집니다. 발자국이 같은 건은 담지 마세요 — 목록이 짧아야 사람이 봅니다.

무엇을 내보낼지 판단한다

/root/work/ageval/eval_report.jsonold_accuracy·new_accuracy·newly_broken·newly_fixed·cost·path_changes·busiest·total_calls 를, /root/work/ageval/eval_report.md## 어디서 무엇을 했는지 어떻게 기록했나 ## 점수만 보면 놓치는 것 ## 비용과 경로도 회귀한다 ## 다음에 무엇을 하겠는가 네 절로 쓰세요.

costcost_delta 의 답 그대로, path_changes 는 달라진 건의 개수입니다. busiest·total_calls 는 골든 세트 전체를 v1 으로 돌렸을 때의 값입니다. 네 번째 절에는 이 결과를 보고 어느 판을 내보낼지 여러분의 판단을 적으세요 — 정답이 하나는 아닙니다.