eval_ph1 — 코드 아키텍처 맵

AutoGen 멀티에이전트 팀을 trace DB로 평가·개선하는 시스템의 전체 코드 구조 (도식·표·workflow)

repo kiyaaa/eval_ph1100 py · 8,880 LOC12 migrations 11 CLI 명령49 팀7 도메인기준일 2026-06-16
🔬 한 단계 더 — 런타임 플로우 완전 해부 →  run_stream 한 건이 이벤트별로 mapping·logger·scorer를 지나 events/runs의 어느 컬럼에 떨어지는지, v1→v6 차이까지 raw 수준으로. 📈 v1→v6 개선 실제 과정 (실험 원장) →  각 버전이 겨냥한 실패·가설·1변수 개입·temp=0 A/B 측정·promoted/rejected 판정을 실제 experiments(EXP-37~148) 수치로. 🗃 데이터 라이프사이클 & 배치 카탈로그 →  어떤 컬럼이 phase별로 언제 저장되는지(시작 INSERT vs 종료 계산 vs 안 채움) + live DB 실제 배치 전수. 🔭 메트릭 발견 — 방법과 근거 (MAST·업계) →  더 유의미한 메트릭을 찾는 발견 루프 + corr 분리력 실측 + 왜 이 메트릭인지 내부증거×MAST/τ-bench 근거. 📊 전체 메트릭 카탈로그 (수집 + 도출) →  runs·events 원시 컬럼부터 집계 뷰·스코어러·검증 뷰 도출까지 ≈134개 신호를 5축(정확·비용·효율·근거·신뢰)으로 전수 정리 + 1순위 8종 + 겹침vs함의 통찰. 🧪 메트릭 가공·취합 레시피 (pass@1·k·p95) →  리포트 숫자 한 칸이 raw run/event→채점→runs UPDATE→REFRESH mv_* 4단계 중 어디서 어떤 SQL/코드로 만들어지는지 + mv vs live view 구분 + live DB 실측 검산.

1시스템 아키텍처 — 한 장

cli → runner → registry(AC9) → teams → AutoGen run_stream → logger → DB(events/runs) → 집계 뷰 → report/Grafana. 개선은 experiments 원장을 거쳐 1변수씩 팀으로 되먹임.

1변수 개입 → 새 team_id

cli.py · typer 11 commands
(run/score/report/compare/failures/load-*/export-team)

runner.run_batch
동시성 Semaphore · runs 수명주기

registry.build_registered_team
AC9 prompt_bundle_hash 가드

teams/ · 49 팀
P-E-C selector / RoundRobin / solo

AutoGen run_stream

tracing/logger (TraceLogger)
+ mapping (event→message_type)

events
이벤트 시퀀스 trace

도메인 scorer
gaia·research·analysis·cppx·extract·sql·roles

runs
success·tokens·latency

mv_batch_summary · mv_passk · mv_tool_summary
+ grounding 뷰 v_analysis_grounded 등

report.py · cli report/compare/failures

Grafana 대시보드

experiments
개선 원장

실행은 runner, 기록은 TraceLogger, 채점은 도메인 scorer, 집계는 mat view — 책임이 분리돼 있다
📋 ① 아키텍처 — 전체 용어 (도식 잘림 대비 텍스트 원문)
flowchart TD
  CLI["cli.py · typer 11 commands (run/score/report/compare/failures/load-* /export-team)"] --> RUN["runner.run_batch · 동시성 Semaphore · runs 수명주기"]
  RUN --> REG["registry.build_registered_team · AC9 prompt_bundle_hash 가드"]
  REG --> TEAM["teams/ · 49 팀 · P-E-C selector / RoundRobin / solo"]
  TEAM --> AG["AutoGen run_stream"]
  AG --> LOG["tracing/logger (TraceLogger) + mapping (event→message_type)"]
  LOG --> EV[("events · 이벤트 시퀀스 trace")]
  RUN --> SC["도메인 scorer · gaia·research·analysis·cppx·extract·sql·roles"]
  SC --> RUNS[("runs · success·tokens·latency")]
  EV --> MV["mv_batch_summary · mv_passk · mv_tool_summary + grounding 뷰 v_analysis_grounded 등"]
  RUNS --> MV
  MV --> REP["report.py · cli report/compare/failures"]
  MV --> GRAF["Grafana 대시보드"]
  REP --> EXP[("experiments · 개선 원장")]
  EXP -.->|1변수 개입 → 새 team_id| TEAM
책임 분리 (핵심 설계). runner=runs 수명주기·동시성 · TraceLogger=events 적재·집계 · registry=팀 빌드·AC9 재현성 가드 · mapping=순수 변환 · 도메인 scorer=채점. 로깅 실패는 배치를 죽이지 않는다(fail-open).

2모듈 맵

패키지 / 모듈책임핵심 파일 (LOC)
cli.py진입점 — typer 11 명령cli.py (338)
runner.py배치 실행 · 동시성(Semaphore) · runs INSERT/UPDATE · view refreshrunner.py (381)
teams/49 피평가 팀 빌더 + registry(빌드·AC9·run 메시지)registry.py (284) · ~40 팀파일
tracing/events 적재·집계·비밀 마스킹 + 이벤트→message_type 매핑logger.py (719) · mapping.py (168)
{gaia,research,analysis,
cppx,extract,sql,roles}/
도메인별 loader(데이터) + scorer(채점)gaia/scorer (191)·loader (188), research/*, roles/* …
research/ (grounding)검색 도구 · 근거가드 · recency · 교차검증 · 코퍼스 생성web_tool (160)·grounding_guard·recency·claim_verify·generator (196)·corpus
db.py · config.pyasyncpg 풀·migration 멱등·view refresh · pydantic-settings(EVAL_*)db.py (117) · config.py
report.py · experiments.py리포팅(뷰 읽기) · 개선 원장 기록 헬퍼report.py (236) · experiments.py
workers/cli_verifier.pyClaude(`claude -p`) 이종 교차검증 (fail-open)cli_verifier.py (197)
migrations/*.sql · dashboards/*.sqlDDL 단일 진실원(SSOT) · Grafana 패널 쿼리000~011 (12) · grafana_panels.sql

3CLI 명령 (cli.py)

명령역할주요 옵션산출
run평가 배치 실행 (핵심 엔트리)--batch --team --benchmark --level --exclude-web --task-ids --limit --attempts --concurrency --retry-crashedruns+events 적재, mv refresh
init-dbmigrations 001+ 멱등 적용 (000은 DBA 수동)_schema_migrations 원장
load-gaia / load-research / load-cppx벤치마크 문제 → tasks 적재--dir --benchmark --level-dirtasks upsert
grounding-score / cppx-groundingresearch/cppx 배치 인용 grounding 채점--batchresearch_grounding / cppx_grounding
report배치 요약(pass@1·효율·p95·tool)--batch읽기전용 텍스트표
compare두 배치 레벨별 비교--batches(2+)읽기전용
failures실패 run 트랜스크립트 요약--batch --limit읽기전용
export-team팀 → AutoGen Studio 컴포넌트 JSON--team --out --baseline-toolJSON(+비밀 스크럽·날짜 동적화)

narrate(LLM 서사 리포트)는 SPEC §0.3대로 의도적 미구현(M6 이후).

4실행 라이프사이클 + 트레이싱

cli run
--team --batch --attempts

_select_tasks
tasks WHERE benchmark

Semaphore(concurrency)
task × attempt

_prepare_run_row
INSERT runs(status=running)

build_team +
build_run_message

TraceLogger.log_stream
← team.run_stream

events INSERT
final_answer·tokens·latency 집계

score_fn(answer, gold)
benchmark 분기

UPDATE runs(completed)
success·format_valid·tokens·latency

db.refresh_views
mv_* REFRESH

runs는 runner가 직접(running→completed), events는 TraceLogger 전담. 배치 종료 시 mv_* REFRESH
📋 ② 실행 라이프사이클 — 전체 용어 (도식 잘림 대비 텍스트 원문)
flowchart LR
  A["cli run · --team --batch --attempts"] --> B["_select_tasks · tasks WHERE benchmark"]
  B --> C["Semaphore(concurrency) · task × attempt"]
  C --> D["_prepare_run_row · INSERT runs(status=running)"]
  D --> E["build_team + build_run_message"]
  E --> F["TraceLogger.log_stream ← team.run_stream"]
  F --> G["events INSERT · final_answer·tokens·latency 집계"]
  G --> H["score_fn(answer, gold) · benchmark 분기"]
  H --> I["UPDATE runs(completed) · success·format_valid·tokens·latency"]
  I --> J["db.refresh_views · mv_* REFRESH"]

AutoGen 이벤트 → message_type 매핑 (tracing/mapping.py)

AutoGen 이벤트message_type비고
TaskResultfinal_answer클래스명으로 선판정
TextMessageagent_messagetotal_turns 증가 · FINAL ANSWER 추출
ToolCallRequestEventtool_callcall당 1행 (tool_call_id)
ToolCallExecutionEventtool_result / tool_error항목 is_error로 logger가 분기
SelectorEvent / SelectSpeakerEventselector_decision다음 발화자 라우팅
HandoffMessagehandoff
EvaluatorScoreEvent (외부 duck-typed)evaluator_scoreClaude 교차검증 판정
StreamingChunk / Thought / MemoryQuery저장 스킵None
logger.py 핵심 (719 LOC). events 20컬럼 INSERT(content/tool_args/result/error는 jsonb) · 비밀 마스킹 단일지점 _mask_secrets(tool_args) · tool_call↔result 짝call.id 전파로 보장(DB CHECK 아님) · content 8192/result 2048자 절단+sha256 · INSERT 실패는 warning만(fail-open).

5도메인 × 스코어러 매트릭스

러너가 benchmark로 score_fn 분기(runner.py:257). 공통 시그니처 ScoreResult(success, format_valid). 정답성과 근거(grounding)는 별도 축.

도메인로더(출처)채점 기준 / 공식success 판정
gaiagaia/loader ← metadata.jsonlextract FINAL ANSWER → normalize(통화/콤마/관사 제거, lower) → 리스트는 순서 보존, 숫자 ε비교format_valid AND norm(pred)==norm(gold)
researchresearch/loader ← tasks.jsonl(+코퍼스)인용 SOURCES doc_id set 비교 cite_f1=2PR/(P+R); 답정확도는 gaia 재사용exact-match (grounding 별도)
analysisscripts/load_analysisgold 없음 → 구조화 FINAL ANSWER: 리포트 생성 여부. count_sources는 참고만format_valid = 리포트 존재
cppxcppx/loader ← Expert 문제FINAL ANSWER + 4축 섹션(개요·개념·구성·공략) 모두 존재. grounding=gold 사실 인용비 + objective_correcthas_final AND sections==4
extractscripts/load_extractJSON 추출 → gold 필드 정규화 비교, field_accuracy(부분점수)format_valid AND 필드 100% 일치
sqlscripts/load_sqlpred·gold SQL을 같은 sqlite fixture에 실행 → 멀티셋(순서무관) 비교 = denotation/실행정확도에러없이 실행 AND exec_match
roles (meeting/ocr/coding/codetest)scripts/load_roles*meeting=액션아이템 커버리지≥0.5 · ocr=CER≤0.15 · coding=샌드박스 pytest · codetest=mutation kill≥0.5각 임계값

6grounding 파이프라인 — "호출"이 아니라 "성공"

전 도메인 공통 철학: success(형식/정답) ⊥ grounded(실검색 근거) ⊥ recency(최신처럼 보임). recency만으로는 "근거 없이 2026을 써넣은 환각"을 못 거른다.

성공 결과

실패·빈결과

analyst 검색 의도

web_tool.web_search
Firecrawl /v1/search
or DDG 폴백(키 없을 때)

events: tool_result

events: tool_error
또는 '(검색 실패)'

grounding_guard
is_grounded = n_search_ok≥1
AND not simulated

recency.py 약신호
as_of·current_year_ratio

hallucination_risk =
recency≥0.5 AND not grounded

v_analysis_grounded
grounded = 검색 성공(호출 아님)

score_analysis_grounding
배치 표 grounded%·risk

web_tool → events(tool_result/error) → grounding_guard(성공 기준) → v_analysis_grounded → 배치 채점. recency는 약신호로 hallucination_risk에만 기여
📋 ③ grounding 파이프라인 — 전체 용어 (도식 잘림 대비 텍스트 원문)
flowchart LR
  Q["analyst 검색 의도"] --> WT["web_tool.web_search · Firecrawl /v1/search · or DDG 폴백(키 없을 때)"]
  WT -->|성공 결과| TR["events: tool_result"]
  WT -->|실패·빈결과| TE["events: tool_error 또는 '(검색 실패)'"]
  TR --> GG["grounding_guard · is_grounded = n_search_ok≥1 AND not simulated"]
  TE --> GG
  REC["recency.py 약신호 · as_of·current_year_ratio"] --> HR
  GG --> HR["hallucination_risk = recency≥0.5 AND not grounded"]
  GG --> VW["v_analysis_grounded · grounded = 검색 성공(호출 아님)"]
  VW --> SCORE["score_analysis_grounding · 배치 표 grounded%·risk"]
이번 사건의 교훈 (코드에 반영됨). 키리스 DDG가 봇차단으로 실검색 0%였는데 모델이 2026을 환각 → migration 010v_analysis_grounded에서 grounded = n_search_ok≥1(호출이 아닌 성공)으로 재정의. grounding_guard.is_grounded = n_search_ok>0 AND not simulated, hallucination_risk = recency≥0.5 AND not grounded.

research 심화

7팀 카탈로그 — 49 피평가 팀

팀 = 피평가 단위(1급 객체). 모든 빌더 (settings, model_client)→(Team, meta). 1변수 개입 = 새 team_id(AC9). topology 분포: selector 11 · roundrobin-solo 9 · roundrobin-multi 27 · 어댑터 2 · swarm 0.

GAIA ladder (selector P-E-C)
team_id모듈도구1변수 차이
v1-baselinev1_baselineread_attached_file · python_calc기준점 (프롬프트/도구/selector 원천)
v2-attach-pathv2_attach_pathv1 동일코드 0변경 — run 메시지에 첨부 절대경로 주입
v3-prompt-fixv3_prompt_fixv1 동일플레이스홀더 리터럴 제거(실값 강제)
v4-prompt-fixv4_prompt_fixv1 동일한 단어 답도 FINAL ANSWER: 형식 강제
v5-multitoolv5_multitool멀티포맷 파서 + python_exec(샌드박스)도구 2개 교체 (UTF-8→멀티포맷, AST→격리실행)
v2-gaia-webgaia_web+ web_search(firecrawl)web 부여 (L2 웹 태스크)
v6-verify-gatev6_verify_gatev1 동일selector 라우팅으로 critic 강제 경유 (MAST FM-3.2)
research ladder (멀티홉 QA · search_corpus)
team_id클래스1변수 차이
v1-research-pipelineSelectorGroupChat P-R-C기준점 (FINAL ANSWER+SOURCES 규약)
v2-research-fastRoundRobin P-R-C토폴로지 selector→roundrobin (나머지 바이트동일) EXP-60 회귀
v2-research-cleanretSelector P-R-C도구: 비활성 decoy 강등(demote_inactive)
v2-research-disambigSelector P-R-C프롬프트: 정확 이름·활성 엔티티만
v2-research-groundedSelector P-R-C프롬프트: SOURCES 의무, 누락 반려
research-xverify-observe / -gate어댑터 + Claude 교차검증observe=판정만 / gate=unsupported면 1회 재생성(self-repair)
analyst flywheel (개방형 분석 · RoundRobin 4-agent)
team_id모듈도구1변수 차이
v1-analyst-soloanalyst_solo약한 베이스라인(solo)
v2-analyst-deepanalyst_deep구조: planner·analyst·synthesizer·critic 파이프라인
v3-analyst-webanalyst_webweb_searchdeep + 실시간 검색(턴당 5+)
v4-analyst-webanalyst_web_liteweb_search비용절감: 검색 1라운드
v5-analyst-webanalyst_web_citedweb_searchsynthesizer: 모든 출처 인용 강제
v6-analyst-webanalyst_web_dedupweb_search_deduped인용 품질: 도메인 dedup + 핵심 5~8개만 HQ 출발점

⚠️ v4/v5/v6-analyst-web은 team_id와 모듈명(lite/cited/dedup)이 어긋남 — 모듈 컬럼 참조.

HQ (정밀·무결성, RoundRobin) · metric-demo · role · cppx · sql/extract
계열team_id (대표)요지
HQhq-research-v1/v2 · hq-coding-v1 · hq-content-v1/v2 · hq-invest-v1무결성 게이트 강화(근거 바인딩·검색수행 검증·역할분리)
metric-demogaia-raw/fmt-solo · loop-base/stop · web-solo · retrieve-answer단일변수 A/B 데모(형식·종료조건·grounding·분업)
role (R1~R5)role-research(-v2) · meeting(-v2) · ocr(-v2/v3) · coding · codetestworker→reviewer 골격 고정, 역할·도구·벤치만 변형
cppxcppx-solo · cppx-panel(-v2)6-agent 패널 · synthesizer 사실보존
sql / extractv1-sql-solo→v2-executed→v3-grounded · v1-extract-solo→v2-validated자기검증(run_sql) · 검증자 추가
registry / AC9. TEAM_REGISTRY(team_id→빌더). ensure_team_record: DB hash ≠ 현재 prompt_bundle_hash즉시 TeamConfigMismatchError. config_full엔 도구 impl_sha까지 기록(같은 이름 다른 구현 v1 vs v5 read_attached_file 구분).

8DB 스키마 (PostgreSQL · 스키마 eval_ph1 · ORM 없음)

migration → 생성 객체

migration객체역할
000_provisionrole · schema (DDL 아님)DBA 수동 1회 (eval_v2와 격리)
001_initteams · tasks · runs · events · message_types · failure_stages · root_causes · claims · evidence핵심 테이블 (claims/evidence는 placeholder)
002_viewsmv_batch_summary · mv_passk · mv_tool_summary (MV)배치/passk/tool 집계
003_experimentsexperiments · v_experiment_annotations개선 원장 + Grafana 마커
004_team_configteams.config_full + v_team_config · v_team_orchestration팀 구성 전문 스냅샷
005_team_graphv_team_graph_nodes · _edgesGrafana Node Graph
006 / 008 / 010research_grounding · cppx_grounding · v_analysis_grounded(+summary)도메인별 grounding (010=성공 기준)
007_research_corpusresearch_corpus · v_research_corpus코퍼스 본문(decoy 라벨)
009_evaluator_scoreevents.eval_meta이종 교차검증 판정
011_failure_taxonomyfailure_stages(6) · root_causes(MAST 14모드) 시드수동 라벨 통제어휘

핵심 테이블 · 정합성 불변식

테이블핵심 컬럼CHECK / 불변식
runsrun_id · team_id · task_id · attempt · batch_id · status · success · format_valid · total/input/output_tokens · latency_ms · total_turns · temperature · seed · failure_stage · root_causestatus≠completed OR success NOT NULL · failure_stage→root_cause 필수 · UNIQUE(batch_id,task_id,attempt)
events(run_id,seq) PK · message_type · tool_call_id · tool_name · tool_args · tool_result(+hash) · tool_error · selector_reason · eval_meta · tokenstool_call→id+name 필수 · result→call_id 필수 · result·error 동시보유 금지
teamsteam_id PK · agents · topology · prompt_bundle_hash · config_fulltopology IN (selector/round_robin/swarm)
experimentsexp_id · hypothesis · intervention(1변수) · team_before/after · verdict · key_evidenceverdict IN (promoted/rejected/inconclusive); 있으면 concluded_at 필수
집계 패턴. 정확도(runs.success)와 독립적으로 근거품질(*_grounding)을 잰다. mv_*만 materialized → 배치 종료 시 REFRESH(안 하면 stale); v_* grounding 뷰는 일반 뷰(즉시 최신). "tool_call마다 result/error 존재"는 DB CHECK가 아니라 검증 SQL(NOT EXISTS=0행)로 보장.

9리포팅 · 개선 플라이휠

3계층: L1 Grafana(추이) → L2 experiments 원장(구조화) → L3 narrate(서사, 미구현).