Uncertainty-Aware Safe Escalation Framework for Medical LLM Agents
LLM ๊ธฐ๋ฐ ์๋ฃ ์์ด์ ํธ๊ฐ ์์ ์ ๋ถํ์ค์ฑ์ ์ ๋ํํ๊ณ , ์ํ๋๋ฅผ ํ๋จํ์ฌ ์ธ๊ฐ ์ ๋ฌธ๊ฐ์๊ฒ ์๋ ์ธ๊ณํ๋ ์ฐ๊ตฌ ํ๋ ์์ํฌ์ ๋๋ค.
- ์ฐ๊ตฌ ๋ฐฐ๊ฒฝ ๋ฐ ๋๊ธฐ
- ํต์ฌ ์ค๊ณ ์ฒ ํ
- ํ๋ก์ ํธ ๊ตฌ์กฐ
- ์ํคํ ์ฒ ์์ธ
- ๋ฐ์ดํฐ์
- ์คํ ์ค๊ณ
- ํ๊ฐ ์งํ
- ์ค์น ๋ฐ ํ๊ฒฝ ๊ตฌ์ฑ
- ์คํ ์คํ
- ์ถ๋ ฅ ํ์ผ
- ๋ ผ๋ฌธ ๊ถ์ฅ ์ค์
- ์ฐธ๊ณ ๋ฌธํ
LLM์ ์๋ฃ ํ์ฅ์ ๋ฐฐํฌํ ๋ ๊ฐ์ฅ ํฐ ์ฅ๋ฒฝ์ "๋ชจ๋ธ์ด ์ธ์ ํ๋ฆฌ๋์ง ๋ชจ๋ฅธ๋ค" ๋ ์ ์ ๋๋ค. ์๋ฃ ๋๋ฉ์ธ์์ ์๋ชป๋ ์์ ๊ฐ(overconfidence)์ ์น๋ช ์ ๊ฒฐ๊ณผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๊ธฐ์กด ์ ๊ทผ๋ฒ๋ค์ ์ธ ๊ฐ์ง ํ๊ณ๋ฅผ ๊ฐ์ง๋๋ค.
| ๊ธฐ์กด ์ ๊ทผ๋ฒ | ํ๊ณ |
|---|---|
| ๋จ์ threshold ๊ธฐ๋ฐ | ์๊ณ๊ฐ์ด ์์์ ์ด๋ฉฐ ํต๊ณ์ ๋ณด์ฅ ์์ |
| Human-in-the-loop (ํญ์) | ์์จ ์ฒ๋ฆฌ ๋ถ๊ฐ โ ์ด์ ๋น์ฉ, ์ง์ฐ |
| ํ๋ฅ ๋ณด์ (calibration) | ๋๋ฉ์ธ ์ด๋(distribution shift) ์ ๋ณด์ฅ ๋ถ๊ดด |
UASEF๋ Conformal Prediction(CP) ์ด๋ก ์ ์๋ฃ LLM์ ์ ์ฉํ์ฌ ์ธ ๊ฐ์ง๋ฅผ ๋์์ ๋ฌ์ฑํฉ๋๋ค.
- ํต๊ณ์ ๋ณด์ฅ:
P(s_test โค qฬ) โฅ 1 - ฮฑโ ์ด๋ก ์ ์ผ๋ก ์ฆ๋ช ๋ ์ปค๋ฒ๋ฆฌ์ง - ๋์ ์ํ๋ ๋ฐ์: ์ ๋ฌธ๊ณผ๋ชฉยท์๋๋ฆฌ์ค์ ๋ฐ๋ผ ์๊ณ๊ฐ ์๋ ์กฐ์
- ์ ํ์ ์์ค์ปฌ๋ ์ด์ : ์์จ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ผ์ด์ค๋ AI๊ฐ, ๋ถํ์คํ๊ฑฐ๋ ๊ณ ์ํ์ธ ์ผ์ด์ค๋ง ์ ๋ฌธ์์๊ฒ ์ธ๊ณ
- ๋ชจ๋ธ์ด "70% ํ์ " ์ด๋ผ๊ณ ๋งํด๋, ์ค์ ๋ก 70% ๋ง์ ๊ฒ์ด๋ผ๋ ๋ณด์ฅ์ด ์์
- ํ์ต ๋ถํฌ์ ๋ค๋ฅธ ๋๋ฉ์ธ์์ ๋ณด์ ์ฑ์ง์ด ์ ์ง๋์ง ์์
- ๋ถํฌ ๊ฐ์ ๋ถํ์. ๊ตํ๊ฐ๋ฅ์ฑ(exchangeability)๋ง ๊ฐ์
qฬ = โ(n+1)(1-ฮฑ)โ/n ๋ฒ์งธ ์์ ๋น์ ํฉ ์ ์โ ์ด ์๊ณ๊ฐ ํ๋๋กP(s_test โค qฬ) โฅ 1-ฮฑ์ฑ๋ฆฝ- ๋ฐ๋ผ์ "ฮฑ = 0.05๋ก ์ค์ โ ์ค์ ์์ค์ปฌ๋ ์ด์ ๋๋ฝ๋ฅ โค 5%"๊ฐ ์ํ์ ์ผ๋ก ๋ณด์ฅ๋จ
๋น์ ํฉ ์ ์(nonconformity score)๋ "์ด ํ ์คํธ ํฌ์ธํธ๊ฐ ์บ๋ฆฌ๋ธ๋ ์ด์ ์ ๊ณผ ์ผ๋ง๋ ๋ค๋ฅธ๊ฐ"๋ฅผ ์์นํํ ๊ฒ์ ๋๋ค. UASEF๋ ํ๊ท negative log-likelihood๋ฅผ ์ฌ์ฉํฉ๋๋ค.
s(x) = -mean(log P(t_i | context, t_1, ..., t_{i-1}))
์ด ์ ํ์ ์ด์ :
- ๋ชจ๋ธ์ด ์์ฑํ ๊ฐ ํ ํฐ์ ํ๋ฅ ์ ๊ทธ๋๋ก ๋ฐ์ โ ๋ต๋ณ ์์ฑ ๊ณผ์ ์์ฒด์ ๋ถํ์ค์ฑ
- Temperature = 0์ผ ๋๋ ์๋ฏธ ์์ (greedy decoding์ด์ง๋ง logprob์ ์ฌ์ ํ ๋ถํฌ๋ฅผ ๋ฐ์)
- API ์ถ๊ฐ ํธ์ถ ๋ถํ์ (generate ํ ๋ฒ์ผ๋ก score์ ๋ต๋ณ์ ๋์์ ์ป์)
UQM โ "์ด ์ง๋ฌธ์ด ์ผ๋ง๋ ์ด๋ ค์ด๊ฐ?" (CP ๊ธฐ๋ฐ ํต๊ณ ์ธก์ )
RTC โ "์ผ๋ง๋ ์ด๋ ค์์ผ ์์ค์ปฌ๋ ์ด์
ํ ๊ฒ์ธ๊ฐ?" (์ํ๋ ๊ธฐ๋ฐ ์๊ณ๊ฐ)
EDE โ "์ต์ข
์ ์ผ๋ก ์์ค์ปฌ๋ ์ด์
ํ ๊ฒ์ธ๊ฐ?" (๋ค์ค ์ ํธ ํตํฉ ๊ฒฐ์ )
์ธ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํจ์ผ๋ก์จ:
- UQM์ CP ์ด๋ก ์ปดํฌ๋ํธ๋ก๋ง ๊ต์ฒด ๊ฐ๋ฅ (weighted CP, conformal risk control ๋ฑ)
- RTC์ ์ ๋ฌธ๊ณผ๋ชฉ ์ํ๋ ์จํจ๋ก์ง๋ ์์ ์ ๋ฌธ๊ฐ ํผ๋๋ฐฑ์ผ๋ก ๋ ๋ฆฝ ์ ๋ฐ์ดํธ ๊ฐ๋ฅ
- EDE์ ํธ๋ฆฌ๊ฑฐ ์ ์ฑ ์ ๊ธฐ๊ด๋ณ ํ๋กํ ์ฝ์ ๋ง๊ฒ ์กฐ์ ๊ฐ๋ฅ
๋จ์ ์ฟผ๋ฆฌ-์๋ต์ด ์๋ **์ถ๋ก -ํ๋ ๋ฃจํ(Reasoning + Acting)**๋ฅผ ํํ ์ด์ :
- ์๋ฃ ์ง๋ฌธ์ ๋จ์ผ ๋ต๋ณ๋ณด๋ค ๋๊ตฌ ํ์ฉ(์ฝ๋ฌผ ์ํธ์์ฉ DB, ๊ฐ์ด๋๋ผ์ธ ๊ฒ์)์ด ํ์
- UASEF๋ ์์ด์ ํธ ๋ด๋ถ๊ฐ ์๋ ์ธ๋ถ์์ ๋ ๋ฆฝ์ ์ผ๋ก ํ์ โ ์์ด์ ํธ ์ถ๋ ฅ์ ๊ฐ์ฌ(audit)ํ๋ ๊ตฌ์กฐ
- LangGraph์ StateGraph๊ฐ ReAct ๋ฃจํ์ UASEF ์ฒดํฌ ๋ ธ๋๋ฅผ ๋ช ํํ ๋ถ๋ฆฌ
UASEF/
โโโ models/ # ํต์ฌ ๋ชจ๋
โ โโโ model_interface.py # LMStudio / OpenAI ํตํฉ ์ถ์ํ ๋ ์ด์ด
โ โโโ uqm.py # Uncertainty Quantification Module (CP ๊ธฐ๋ฐ)
โ โโโ rtc_ede.py # Risk-Threshold Calibrator + Escalation Decision Engine
โ โโโ rtc_calibration.py # โ
RTC ๋ฐฐ์จ Pareto sweep (๋ฐ์ดํฐ ๊ธฐ๋ฐ ์ญ์ฐ)
โ โโโ entropy_calibration.py # โ
์ํธ๋กํผ ์๊ณ๊ฐ Youden's J ์๋ ๊ฒฐ์
โ โโโ ede_coefficient_search.py # โ
EDE confidence ๊ณ์ grid search
โ
โโโ agent/ # LangGraph ReAct ์์ด์ ํธ
โ โโโ graph.py # StateGraph ์กฐ๋ฆฝ
โ โโโ nodes.py # ๋
ธ๋ ํจ์ + AgentComponents
โ โโโ state.py # MedicalAgentState TypedDict
โ โโโ tools.py # ์๋ฃ ๋๊ตฌ 4์ข
(drug, guideline, lab, DDx)
โ
โโโ data/
โ โโโ loader.py # MedQA / MedAbstain / PubMedQA / MIMIC-III ๋ก๋
โ โโโ raw/ # ๋ก์ปฌ JSONL ํ์ผ ์์น (.gitignore)
โ โโโ README.md # ๋ฐ์ดํฐ ์์ค ๋ฐ ๋ค์ด๋ก๋ ๊ฐ์ด๋
โ
โโโ experiments/
โ โโโ configs/ # ์๋๋ฆฌ์ค๋ณ YAML ์ค์
โ โ โโโ base_config.yaml # ๊ณตํต ๊ธฐ๋ณธ๊ฐ (์บ๋ฆฌ๋ธ๋ ์ด์
๊ฒฐ๊ณผ ํฌํจ)
โ โ โโโ scenario_emergency.yaml
โ โ โโโ scenario_rare_disease.yaml
โ โ โโโ scenario_multimorbidity.yaml
โ โโโ config_utils.py # โ
๊ณตํต ์บ๋ฆฌ๋ธ๋ ์ด์
config ๋ก๋
โ โโโ run_calibration_pipeline.py # โ
์บ๋ฆฌ๋ธ๋ ์ด์
ํ์ดํ๋ผ์ธ (Step 1โ5)
โ โโโ run_experiment.py # ์์ฐจ ํ์ดํ๋ผ์ธ ์คํ (LMStudio vs OpenAI)
โ โโโ run_agent_experiment.py # LangGraph ์์ด์ ํธ ์คํ
โ โโโ run_baseline_comparison.py # ๋ฒ ์ด์ค๋ผ์ธ ๋น๊ต (no_esc / threshold_only / full_uasef)
โ โโโ eval_medabstain.py # MedAbstain AP/NAP ๋ถ๋ฅ ์ ํ๋ ํ๊ฐ
โ โโโ pareto_sweep.py # ฮฑ sweep โ Pareto frontier + ฮฑ ๊ถ๊ณ
โ โโโ run_all_experiments.py # โ
์ ์ฒด ์คํ ํตํฉ ์คํ + ์์ฝ ๋ณด๊ณ ์ ์์ฑ
โ โโโ visualize_results.py # ๊ฒฐ๊ณผ ์๊ฐํ
โ
โโโ results/ # ์คํ ๊ฒฐ๊ณผ (์๋ ์์ฑ, .gitignore)
โโโ pyproject.toml
โโโ .env.example
ํ์ผ: models/uqm.py
UQM์ ๋จ์ผ ์ง๋ฌธ์ ๋ถํ์ค์ฑ์ ํต๊ณ์ ์ผ๋ก ๋ณด์ฅ๋ ์์น๋ก ๋ณํํฉ๋๋ค.
์ง๋ฌธ ์
๋ ฅ
โ
_get_score(): LLM ํธ์ถ โ token logprobs ์์ง
โ
compute_nonconformity_score(): s = -mean(logprobs)
โ
calibrator.threshold์ ๋น๊ต โ should_escalate
โ
compute_entropy(): top_logprobs๋ก ์์น๋ณ ์กฐ๊ฑด๋ถ ์ํธ๋กํผ ๊ณ์ฐ
โ
UncertaintyResult ๋ฐํ
๋ณด์ ์งํฉ {s_1, ..., s_n} (๋น์ ํฉ ์ ์๋ค)์์ ์๊ณ๊ฐ ๊ณ์ฐ:
qฬ = s_{(โ(n+1)(1-ฮฑ)โ)} โ n๋ฒ์งธ ์์ ์ ์
๋ณด์ฅ: P(s_test โค qฬ) โฅ 1 - ฮฑ
์ค์ ๊ตฌํ์์๋ numpy.quantile์ ์ฌ์ฉํ๋ฉฐ, level์ min(1.0, โ(n+1)(1-ฮฑ)โ/n) ์ผ๋ก ๋ณด์ ํ์ฌ ์ ํ ํ๋ณธ์์์ ๋ณด์์ฑ์ ํ๋ณดํฉ๋๋ค.
| ๋ฐฉ์ | ์์ | ํน์ง | ๋ ผ๋ฌธ ์์น |
|---|---|---|---|
| logprob (Primary + Ablation) | s = -mean(token logprobs) |
CP ๋ณด์ฅ โ, ๋จ์ผ ์ฟผ๋ฆฌ | ์ฃผ์ ๊ธฐ์ฌ + Ablation |
| self_consistency (๋์) | s = Jaccard_diversity ร 5 |
CP ๋ณด์ฅ โ, Nํ ์ฟผ๋ฆฌ, logprobs ๋ถํ์ | ๋ธ๋๋ฐ์ค LLM ํธํ์ฉ |
| auto | ๋ฐํ์ ๊ฐ์ง | ์ฌํ์ฑ ์ ํ ์ํ | ๋น๊ถ์ฅ |
์ logprob์ด Primary์ด๊ณ Ablation ๋ชจ๋์ธ๊ฐ? LM Studio์ OpenAI-compatible API๋ token-level logprobs๋ฅผ ์ง์ํ๋ฏ๋ก, OpenAI์ ๋ก์ปฌ GGUF ๋ชจ๋ธ ๋ชจ๋ ๋์ผํ
logprob๋น์ ํฉ ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Ablation์ ๋ชฉ์ ์ scoring method ์ฐจ์ด๊ฐ ์๋๋ผ, ๋ก์ปฌ ํ๊ฒฝ์์๋ CP coverage ๋ณด์ฅ์ด ์ฑ๋ฆฝํจ์ ๊ฒ์ฆํ๋ ๊ฒ์ ๋๋ค.self_consistency๋ logprobs๋ฅผ ์ง์ํ์ง ์๋ Claude API, Gemini API ๋ฑ์ ์ ์ฉํ ์ ์๋ ๋์์ ๋๋ค.
compute_entropy(response: ModelResponse) ๋ top_logprobs๊ฐ ์์ ๋๋ง ์ ํจํ ์ํธ๋กํผ๋ฅผ ๋ฐํํฉ๋๋ค.
# ๊ฐ ํ ํฐ ์์น์์ ์์ k๊ฐ logprob์ผ๋ก ์กฐ๊ฑด๋ถ ๋ถํฌ ๊ทผ์ฌ
probs = softmax(top_k_logprobs) # ์ ๊ทํ
H_pos = -sum(p * log(p)) # ์์น๋ณ ์ํธ๋กํผ
H_avg = mean(H_pos) # ์ ์ฒด ํ๊ท (nats/token)top_logprobs๊ฐ ์์ผ๋ฉด float("nan") ๋ฐํ โ ๊ฐ๋ณ ํ ํฐ logprob์ผ๋ก๋ Shannon ์ํธ๋กํผ๋ฅผ ๊ณ์ฐํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค (๊ฐ ๊ฐ์ด ์์ ํ ์ดํ ๋ถํฌ๋ฅผ ๊ตฌ์ฑํ์ง ์์).
# ๋ณด์ : MedQA ๋ถํฌ
uqm.calibrate(cal_questions, distribution_source="medqa")
# ํ๊ฐ: MIMIC-III ๋ถํฌ (๋ค๋ฅธ ๋ถํฌ!) โ ์๋ ๊ฒฝ๊ณ + Weighted CP ์ ํ
uqm.evaluate(question, distribution_source="mimic3")Weighted CP (Tibshirani et al., 2019)๋ ๊ตํ๊ฐ๋ฅ์ฑ ์๋ฐ ์ ์ปค๋ฒ๋ฆฌ์ง ๋ณด์ฅ์ ๋ณต์ํฉ๋๋ค.
w_i = 1 + k ร Jaccard(cal_i, test) # ๋ฐ๋๋น ๊ทผ์ฌ
qฬ_w = inf{q : ฮฃ_{s_i โค q} w_i / (ฮฃ w_i + w_{n+1}) โฅ 1-ฮฑ}
w_{n+1} (ํ
์คํธ ํฌ์ธํธ ์์ ์ weight)๋ฅผ ๋ถ๋ชจ์ ํฌํจํด์ผ CP ํํ ๋ณด์ฅ์ด ์ฑ๋ฆฝํฉ๋๋ค. w_{n+1} = 1 + k (Jaccard(test, test) = 1.0 ์ด๋ฏ๋ก ์ต๋ ์ ์ฌ๋).
| ํ๋ | ์ค๋ช |
|---|---|
nonconformity_score |
๋น์ ํฉ ์ ์ โ ํด์๋ก ๋ถํ์ค |
margin |
threshold - score โ ์์=์์ ์ฌ์ , ์์=์๊ณ๊ฐ ์ด๊ณผ |
confidence_entropy |
์์น๋ณ ์กฐ๊ฑด๋ถ ์ํธ๋กํผ (nats/token). top_logprobs ์์ผ๋ฉด nan |
should_escalate |
score > threshold ์ฌ๋ถ |
weighted_cp_used |
Weighted CP ์ ์ฉ ์ฌ๋ถ |
prediction_set_size |
ํญ์ 1. ํ์ ํธํ์ฑ ์ ์ง์ฉ ํ๋ (binary outcome์์ prediction set์ ๋จ์ผ ์์) |
| scoring_method | logprobs ํ์ | ์ ์ฉ ๊ฐ๋ฅ LLM | ๋ ผ๋ฌธ ์์น |
|---|---|---|---|
logprob (Primary + Ablation) |
ํ์ | GPT-4o, GPT-4o-mini, LMStudio (llama.cpp) | ์ฃผ์ ๊ธฐ์ฌ + Ablation |
self_consistency (๋์) |
๋ถํ์ | ๋ชจ๋ LLM | ๋ธ๋๋ฐ์ค LLM ํธํ์ฉ |
logprob๋ฐฉ์์ token-level logprobs๋ฅผ ์ง์ํ์ง ์๋ Claude API, Gemini API, Cohere ๋ฑ์์ValueError๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๋ฐ ํ๊ฒฝ์์๋self_consistency๋ฅผ ์ฌ์ฉํ์ธ์. LM Studio๋ OpenAI-compatible API๋ก logprobs๋ฅผ ์ง์ํ๋ฏ๋ก Primary์ ๋์ผํ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค.
ํ์ผ: models/rtc_ede.py, models/rtc_calibration.py
UQM์ด ๋ฐํํ ๊ธฐ๋ณธ ์๊ณ๊ฐ qฬ๋ฅผ ์ ๋ฌธ๊ณผ๋ชฉ๊ณผ ์๋๋ฆฌ์ค์ ์ํ๋์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์กฐ์ ํฉ๋๋ค.
adjusted_threshold = qฬ ร risk_multiplier ร scenario_multiplier
| ์ํ ๋ฑ๊ธ | ๊ธฐ๋ณธ ๋ฐฐ์จ | ํด๋น ์ ๋ฌธ๊ณผ๋ชฉ |
|---|---|---|
| CRITICAL | ร0.60 | ์๊ธ์ํ, ์คํ์์ํ, ์ธ์์ธ๊ณผ |
| HIGH | ร0.75 | ์ฌ์ฅ๋ด๊ณผ, ์ ๊ฒฝ๊ณผ, ์ข ์ํ, ์ฌํ์ธ๊ณผ |
| MODERATE | ร1.00 | ๋ด๊ณผ, ์ธ๊ณผ, ์์๊ณผ, ์ฐ๋ถ์ธ๊ณผ |
| LOW | ร1.30 | ์ผ๋ฐ ์ธ๋, ์๋ฐฉ์ํ, ํผ๋ถ๊ณผ, ์ ์ ๊ฑด๊ฐ์ํ๊ณผ |
emergency / rare_disease ์๋๋ฆฌ์ค์๋ ์ถ๊ฐ ร0.85 ์ ์ฉ๋ฉ๋๋ค.
์ค๊ณ ์ด์ : ์๊ธ์ํ์์ ์์ค์ปฌ๋ ์ด์ ๋๋ฝ(False Negative)์ ๋น์ฉ์ ์ผ๋ฐ ์ธ๋์ ๋นํด ํจ์ฌ ํฝ๋๋ค. ์๊ณ๊ฐ์ ๋ฎ์ถ๋ฉด ๋ ๋ง์ ์ผ์ด์ค๊ฐ ์์ค์ปฌ๋ ์ด์ ๋์ง๋ง, ์ํํ ์ผ์ด์ค๋ฅผ ๋์น ํ๋ฅ ์ด ์ค์ด๋ญ๋๋ค. ์ด ํธ๋ ์ด๋์คํ๋ฅผ ์ ๋ฌธ๊ณผ๋ชฉ ์จํจ๋ก์ง๋ก ์ธ์ฝ๋ฉํ์ต๋๋ค.
์ ํ์ ๋ฐฐ์จ์ ๊ธฐ๋ณธ๊ฐ์
๋๋ค. run_calibration_pipeline.py๋ฅผ ์คํํ๋ฉด ๋ ์ด๋ธ ๋ฐ์ดํฐ์์ Pareto sweep์ผ๋ก ๋ฐฐ์จ์ ์๋ ์ญ์ฐํฉ๋๋ค.
๊ฐ ์ํ๋ ์์ค๋ณ๋ก ํ๋ณด ๋ฐฐ์จ (์: CRITICAL โ {0.50, 0.55, 0.60, 0.65, 0.70}) sweep
โ Safety Recall โฅ 0.95 AND Over-Escalation โค 0.15 ๋ฅผ ๋์ ์ถฉ์กฑํ๋ ํ๋ณด ์ค
Over-Escalation์ด ์ต์์ธ ๋ฐฐ์จ ์ ํ (์ ์ฝ ๋ถ์ถฉ์กฑ ์ Safety Recall ์ต๋ fallback)
โ ๊ฒฐ๊ณผ๋ฅผ base_config.yaml์ rtc ์น์
์ ์ ์ฅ
๊ฒฐ๊ณผ๋ RTC(base_threshold, multipliers=cfg["rtc"]) ํํ๋ก ๋ชจ๋ ์คํ ํ์ผ์ ์๋ ์ฃผ์
๋ฉ๋๋ค.
rtc.pareto_frontier(sweep_results)pareto_sweep.py์ ์ค์ธก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๊ฐ (ฮฑ, specialty) ์กฐํฉ์์ (coverage, escalation_rate) ์์ ๋ฐํํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ค์ ๋ก ์ธก์ ๋ trade-off๋ฅผ ์๊ฐํํ๊ณ ์ต์ ฮฑ๋ฅผ ๊ถ๊ณ ํฉ๋๋ค.
ํ์ผ: models/rtc_ede.py, models/entropy_calibration.py, models/ede_coefficient_search.py
์ธ ๊ฐ์ง ํธ๋ฆฌ๊ฑฐ๋ฅผ ํตํฉํ์ฌ ์ต์ข ์์ค์ปฌ๋ ์ด์ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
Trigger 1 โ UNCERTAINTY_EXCEEDED:
nonconformity_score > adjusted_threshold
โ CP ์ด๋ก ์ ์ง์ ์ ํธ (์ฃผ ํธ๋ฆฌ๊ฑฐ)
Trigger 2 โ HIGH_RISK_ACTION:
CRITICAL_KEYWORDS ๊ฐ์ง (EOL ๊ฒฐ์ , Code Blue) โ ํญ์ ํธ๋ฆฌ๊ฑฐ
PROCEDURAL_KEYWORDS ๊ฐ์ง (intubation, ์น์์ ) โ UNCERTAINTY_MODIFIERS ๋๋ฐ ์๋ง ํธ๋ฆฌ๊ฑฐ
Trigger 3 โ NO_EVIDENCE:
๊ทผ๊ฑฐ ๋ถ์ฌ ํํ ๊ฐ์ง (์๋ ์ฐธ์กฐ)
ํ๋๋ผ๋ ํ์ฑํ โ should_escalate = True
Trigger 2 ์ค๊ณ ์ด์ : "์ํผ๋คํ๋ฆฐ์ ์๋ํ๋ฝ์์ค์ ํฌ์ฌํ์ธ์" ๊ฐ์ ์ ์์ ์ธ ์ฒ์น ๊ถ๊ณ ๊ฐ ํค์๋๋ง์ผ๋ก ์์ค์ปฌ๋ ์ด์ ๋๋ False Positive๋ฅผ ๋ฐฉ์งํฉ๋๋ค. ๋ฐ๋ผ์ ์์ ํค์๋๋ ๋ถํ์ค ํํ(
consider,may need,if deteriorates๋ฑ)๊ณผ ํจ๊ป ๋ํ๋ ๋๋ง ํ์ฑํํฉ๋๋ค. ๋ฐ๋ฉด DNR, withdraw care ๊ฐ์ EOL ๊ฒฐ์ ์ AI๊ฐ ๋จ๋ ์ผ๋ก ํ๋จํด์๋ ์ ๋๋ฏ๋ก ํญ์ ์์ค์ปฌ๋ ์ด์ ํฉ๋๋ค.
๊ทผ๊ฑฐ ๋ถ์ฌ ํํ์ ์ถ์ฒ๋ณ๋ก ๊ด๋ฆฌ๋ฉ๋๋ค. ๋
ผ๋ฌธ ์ฌํ ์ source ํ๋๋ฅผ ์ธ์ฉ ๊ทผ๊ฑฐ๋ก ์ฌ์ฉํ์ธ์.
| ์ถ์ฒ | ์์ ํํ |
|---|---|
medabstain |
"i am not certain", "insufficient evidence", "limited data" |
savage2025 |
"this is unclear", "evidence is mixed", "conflicting data" |
manual (GPT-4o 500๊ฑด) |
"clinical judgment needed", "differential is broad" |
ํ์ง ํจ์ detect_no_evidence(text) ๋ (triggered: bool, matched_phrases: list[str]) ๋ฅผ ๋ฐํํ์ฌ ๋
ผ๋ฌธ ์ฌํ์ ํ์ํ ๋งค์นญ ์ฆ๊ฑฐ๋ฅผ ํจ๊ป ์ ๊ณตํฉ๋๋ค.
confidence = min(1.0,
len(triggers) / 3
+ t1_weight if UNCERTAINTY_EXCEEDED in triggers # ๊ธฐ๋ณธ 0.4
+ entropy_boost if entropy > entropy_threshold # ๊ธฐ๋ณธ 0.15, ๊ธฐ๋ณธ ์๊ณ๊ฐ 2.0
)
์ํธ๋กํผ๋ ๋ณ๋ ํธ๋ฆฌ๊ฑฐ๊ฐ ์๋ ์ ๋ขฐ๋ ๊ฐ์ค์น๋ก๋ง ์ฌ์ฉ๋ฉ๋๋ค. ์ธ ๊ณ์(t1_weight, entropy_boost, entropy_threshold)๋ ๋ชจ๋ ๋ฐ์ดํฐ ๊ธฐ๋ฐ์ผ๋ก ์ฐ์ถํ์ฌ base_config.yaml์ ์ ์ฅ๋ฉ๋๋ค.
ENTROPY_HIGH_THRESHOLD = 2.0 ํ๋์ฝ๋ฉ ๋์ calibration ๋ฐ์ดํฐ์์ Youden's J ํต๊ณ๋์ผ๋ก ์๋ ๊ฒฐ์ ํฉ๋๋ค.
Youden's J = Sensitivity + Specificity - 1 (์ต๋ํ ์ง์ ์ ํ)
โ ๊ฒฐ๊ณผ๋ฅผ base_config.yaml์ entropy_threshold์ ์ ์ฅ
t1_weight โ {0.2, 0.3, 0.4, 0.5}
entropy_boost โ {0.05, 0.10, 0.15, 0.20}
์ต์ ํ ๋ชฉํ: F1-safety = harmonic_mean(Safety Recall, 1 โ Over-Escalation Rate)
โ ๊ฒฐ๊ณผ๋ฅผ base_config.yaml์ ede ์น์
์ ์ ์ฅ
ํ์ผ: agent/graph.py, agent/nodes.py, agent/state.py
START โ reason โ [tool_calls?] โ act โโโ reason (ReAct ๋ฃจํ, ์ต๋ 5ํ)
โ
uasef_check โ ์๋ณธ ์ง๋ฌธ ๋
๋ฆฝ ์ฌํ
โ โ
escalate finalize
โ โ
END END
uasef_check ๋
ธ๋๋ ์์ด์ ํธ์ ๋ฉ์์ง ํ์คํ ๋ฆฌ๋ฅผ ๋ณด์ง ์๊ณ ์๋ณธ ์ง๋ฌธ์ ์ง์ UQM์ ์ ๋ฌํฉ๋๋ค. ์์ด์ ํธ๊ฐ ๋๊ตฌ๋ก ์ ๋ณด๋ฅผ ๋ง์ด ์์งํ๋๋ผ๋ UASEF๋ ๋ณ๋๋ก ํ์ ํฉ๋๋ค.
์ด ์ค๊ณ ์ด์ :
- ์์ด์ ํธ๊ฐ ํ๋ฆฐ ์ ๋ณด๋ฅผ ์์งํด๋ UASEF๊ฐ ์์ ๋ง ์ญํ
- ์์ด์ ํธ ์ถ๋ ฅ์ ๊ฐ์ฌ(audit)ํ๋ ์ธ๋ถ ์ปดํฌ๋ํธ ํจํด
reason ๋
ธ๋์์ ์ด๋ฏธ logprobs=True๋ก LLM์ ํธ์ถํฉ๋๋ค. uasef_check์์ ๋ง์ง๋ง AIMessage์ response_metadata์์ logprobs๋ฅผ ์ถ์ถํด pre_computed_response๋ก UQM์ ์ ๋ฌํ๋ฉด, logprob ๋ชจ๋์์ ๋ ๋ฒ์งธ LLM ํธ์ถ์ ์๋ตํฉ๋๋ค.
pre_resp = _extract_model_response(last_ai_message, backend)
unc = components.uqm.evaluate(question, pre_computed_response=pre_resp)
# pre_resp๊ฐ ์์ผ๋ฉด LLM ์ฌํธ์ถ ์์ด score ๊ณ์ฐLangGraph State์ ๋น์ง๋ ฌํ ๊ฐ์ฒด(UQM, RTC, EDE)๋ฅผ ๋ฃ์ง ์๊ณ , functools.partial๋ก ๊ฐ ๋
ธ๋ ํจ์์ ํด๋ก์ ๋ก ์ ๋ฌํฉ๋๋ค. State๋ JSON ์ง๋ ฌํ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ง ํฌํจํฉ๋๋ค.
| ๋๊ตฌ | ์ญํ | ์ค์ ์ฐ๊ตฌ ๊ต์ฒด ๋์ |
|---|---|---|
drug_interaction_checker |
์ฝ๋ฌผ ์ํธ์์ฉ ํ์ธ | Drugs@FDA API / Lexicomp |
clinical_guideline_search |
์์ ๊ฐ์ด๋๋ผ์ธ ๊ฒ์ | UpToDate / PubMed E-utilities |
lab_reference_lookup |
๊ฒ์ฌ ์ฐธ๊ณ ์น ์กฐํ | LOINC / ๊ธฐ๊ด ๋ด LIS |
differential_diagnosis |
๊ฐ๋ณ ์ง๋จ | Isabel DDx / ๊ธฐ๊ด ๋ด CDR |
1. data/raw/*.jsonl (๋ก์ปฌ JSONL ํ์ผ)
2. HuggingFace datasets (์๋ ๋ค์ด๋ก๋)
3. ๋ด์ฅ fallback (๊ฐ๋ฐ/ํ
์คํธ ์ ์ฉ, 30๊ฐ)
- ์ญํ : Calibration + ๊ธฐ๋ณธ ์๋๋ฆฌ์ค ํ ์คํธ
- ์ถ์ฒ: Jin et al., 2021 โ "What Disease does this Patient Have?"
- HuggingFace ID:
GBaker/MedQA-USMLE-4-options - ์ฌ์ฉ split:
train(calibration),test(ํ ์คํธ ์๋๋ฆฌ์ค)
USMLE(๋ฏธ๊ตญ ์์ฌ๋ฉดํ์ํ) ์คํ์ผ์ 4์ง์ ๋ค ๋ฌธ์ ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ ๋ต๋ง ์์๋ ๋๋ ๊ฒ์ด ์๋๋ผ, ์ ํ๋ ธ๋์ง๋ฅผ ํตํด ๋ถํ์ค์ฑ์ ์ธก์ ํ๋ ๋ฐ ์ ํฉํฉ๋๋ค.
- ์ญํ : ํฌ๊ท์งํยท๋ถํ์ค ์๋๋ฆฌ์ค, safety ํ๊ฐ์ ํต์ฌ
- ์ถ์ฒ: Zhu et al., 2023 โ "Can LLMs Express Their Uncertainty?"
4๊ฐ์ง ๋ณํ์ด ์์ผ๋ฉฐ, AP์ NAP๊ฐ safety ํ๊ฐ์ ํต์ฌ์ ๋๋ค.
| ๋ณํ | ์ค๋ช | expected_escalate |
์ฌ์ฉ ์๋๋ฆฌ์ค |
|---|---|---|---|
| AP | Abstention + Perturbed | True |
ํฌ๊ท์งํ (๋ถํ์ค + ๋ณํ ์ง๋ฌธ) |
| NAP | Normal + Perturbed | True |
ํฌ๊ท์งํ (์ ์ ๋ต๋ณ์ด์ง๋ง ๋ณํ ์ง๋ฌธ) |
| A | Abstention only | True |
์ผ๋ฐ ๋ถํ์ค ์ผ์ด์ค |
| NA | Normal | False |
์ ์ ์ผ์ด์ค (True Negative ๊ฒ์ฆ) |
์ AP/NAP๊ฐ ํต์ฌ์ธ๊ฐ?: AP์ NAP๋ ์๋ ์ง๋ฌธ์ ๋ฏธ๋ฌํ๊ฒ ๋ณํ(perturb)ํ์ฌ ๋ชจ๋ธ์ ์์ ์ฑ์ ํ ์คํธํฉ๋๋ค. ์ด ๋ณํ๋ ์ง๋ฌธ์ ์์ ์๊ฒ ๋ตํ๋ ๋ชจ๋ธ์ ์์ค์ปฌ๋ ์ด์ ํด์ผ ํ๋ ์ํฉ์ ๋์น ์ํ์ด ์์ต๋๋ค.
- ์ญํ :
rare_disease๋ฒํท ๋ณด๊ฐ + NO_EVIDENCE ํธ๋ฆฌ๊ฑฐ(Trigger 3) ๊ฒ์ฆ - ์ถ์ฒ: Jin et al., 2019 โ "PubMedQA: A Dataset for Biomedical Research Question Answering"
- HuggingFace ID:
pubmed_qa / pqa_labeled(1,000 expert-labeled)
final_decision = "maybe" ์ผ์ด์ค๋ง expected_escalate=True๋ก ์ค์ ํ์ฌ rare_disease ๋ฒํท์ ์ถ๊ฐํฉ๋๋ค. ํ์ฑํ ๋ฐฉ๋ฒ:
# experiments/configs/base_config.yaml
data:
include_pubmedqa: true- ์ญํ : ์ค์ ICU ์์ ๊ธฐ๋ก์ผ๋ก distribution shift ์คํ
- ์กฐ๊ฑด: PhysioNet DUA(Data Use Agreement) ์๋ช ํ์
- ์ฌ์ฉ ๋ชฉ์ : Weighted CP๊ฐ ๋ถํฌ ์ด๋ ์ํฉ์์๋ ์ปค๋ฒ๋ฆฌ์ง ๋ณด์ฅ์ ๋ณต์ํ๋์ง ๊ฒ์ฆ
CP ๋ณด์ฅ์ calibration๊ณผ evaluation์ด ๊ฐ์ ๋ถํฌ์์ ๋์ฌ ๋๋ง ์ ํจํฉ๋๋ค (exchangeability). MedQA๋ก ๋ณด์ ํ ๋ค MIMIC-III๋ก ํ๊ฐํ๋ฉด CP ๋ณด์ฅ์ด ๊นจ์ง๋ฉฐ, ์ด๋ฅผ Weighted CP๋ก ๋ณต์ํ๋ ๊ฒ์ด ์คํ์ ํต์ฌ์ ๋๋ค.
โโโ ์บ๋ฆฌ๋ธ๋ ์ด์
(1ํ, run_calibration_pipeline.py) โโโโโโโโโโโโโโโ
MedQA (unlabeled)
โ
UQM.calibrate() โ Split CP: 80%๋ก qฬ ๊ณ์ฐ, 20%๋ก coverage ๊ฒ์ฆ
โ
MedQA/MedAbstain (labeled, calibration split)
โ
entropy_calibration โ Youden's J โ entropy_threshold
rtc_calibration โ Pareto sweep โ ์ํ๋๋ณ multiplier
ede_coefficient_search โ F1-safety grid search โ t1_weight, entropy_boost
โ
base_config.yaml ๊ฐฑ์ โ rtc / entropy_threshold / ede ์น์
โโโ ์คํ (run_experiment.py ๋ฑ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MedQA/MedAbstain (test split)
โ
RTC(multipliers=cfg["rtc"]) โ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ๋ฐฐ์จ ์ฃผ์
EDE(t1_weight, entropy_boost, ...) โ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ๊ณ์ ์ฃผ์
โ
UQM.evaluate() โ EDE.decide() โ 3 ํธ๋ฆฌ๊ฑฐ ํตํฉ โ should_escalate
โ
Safety Recall / Over-Escalation Rate / Conformal Coverage
๋ชจ๋ ์คํ ์ 1ํ ์คํํ์ฌ ํ๋์ฝ๋ฉ ๊ธฐ๋ณธ๊ฐ์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ๊ฐ์ผ๋ก ๊ต์ฒดํ๊ณ base_config.yaml์ ์ ์ฅํฉ๋๋ค. ์ดํ ๋ชจ๋ ์คํ ํ์ผ์ ์ด config๋ฅผ ์๋์ผ๋ก ์ฝ์ด ์ ์ฉํฉ๋๋ค.
Step 1 CP Calibration โ UQM.calibrate() โ base threshold qฬ ์ฐ์ถ
Step 2 ๋ ์ด๋ธ ๋ฐ์ดํฐ ์์ง โ load_scenarios() โ UQM.evaluate() โ (scores, labels, entropy)
Step 3 Entropy Threshold โ entropy_calibration.py โ Youden's J โ entropy_threshold
Step 4a RTC ๋ฐฐ์จ Pareto Sweep โ rtc_calibration.py โ ์ํ๋๋ณ optimal multiplier
Step 4b EDE Coefficient Searchโ ede_coefficient_search.py โ (t1_weight, entropy_boost)
Step 5 base_config.yaml ๊ฐฑ์ โ rtc / entropy_threshold / ede ์น์
๋ฎ์ด์ฐ๊ธฐ
run_calibration_pipeline.py
โ base_config.yaml (rtc, entropy_threshold, ede ์น์
๊ฐฑ์ )
โ config_utils.load_calibration_config()
โ
๋ชจ๋ ์คํ ํ์ผ (run_experiment, run_agent_experiment, eval_medabstain, ...)
โ RTC(base_threshold, multipliers=rtc_cfg)
โ EDE(t1_weight=..., entropy_boost=..., entropy_threshold=...)
# ๊ฐ๋ฐ ํ
์คํธ (๋น ๋ฆ)
python experiments/run_calibration_pipeline.py --backend openai
# ๋
ผ๋ฌธ ํ์ง (๊ถ์ฅ)
python experiments/run_calibration_pipeline.py --backend openai --n-cal 500 --n-labeled 50์ถ๋ ฅ: results/calibration_report.json + base_config.yaml ์๋ ๊ฐฑ์
LangGraph ์์ด์ ํธ ์์ด UQM โ RTC โ EDE๋ฅผ ์์๋๋ก ์คํํ๋ ๊ธฐ๋ณธ ํ์ดํ๋ผ์ธ์ ๋๋ค.
| ๊ตฌ๋ถ | ๋ฐฑ์๋ | Scoring Method | ๋ ผ๋ฌธ ์์น |
|---|---|---|---|
| [Primary] | OpenAI (GPT-4o-mini) | logprob โ token-level logprobs ๊ธฐ๋ฐ CP |
์ฃผ์ ๊ฒฐ๊ณผ |
| [Ablation] | LMStudio (๋ก์ปฌ, meta-llama-3.1-8b-instruct) | logprob โ LM Studio OpenAI-compatible API๋ก token-level logprobs ์ถ์ถ |
"๋ก์ปฌ GGUF ๋ชจ๋ธ์๋ logprob CP ์ ์ฉ ๊ฐ๋ฅ" ๊ฒ์ฆ |
๋ ๋ฐฑ์๋ ๋ชจ๋ ๋์ผํ
logprob๋น์ ํฉ ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Ablation์ ๋ชฉ์ ์ scoring method ์ฐจ์ด๊ฐ ์๋๋ผ, LM Studio์ OpenAI-compatible API๋ฅผ ํตํด ๋ก์ปฌ GGUF ๋ชจ๋ธ์์๋ token-level logprobs๋ฅผ ์ถ์ถํ ์ ์์์ ๊ฒ์ฆํ๋ ๊ฒ์ ๋๋ค.
- ์๋๋ฆฌ์ค: Emergency / Rare Disease / Multimorbidity
# base_config.yaml โ scenario_emergency.yaml โ CLI ์ธ์
# ์ค๋ฅธ์ชฝ์ด ์ผ์ชฝ์ ๋ฎ์ด์๋๋ค.
uqm:
alpha: 0.05
scoring_method: logprob
holdout_fraction: 0.2
data:
n_calibration: 30 # ๋
ผ๋ฌธ ๊ถ์ฅ: 500
n_test_per_scenario: 3 # ๋
ผ๋ฌธ ๊ถ์ฅ: 50_build_datasets(): Config์ ๋ฐ๋ผ MedQA / MedAbstain ๋ก๋UQM.calibrate(): calibration set์ผ๋ก qฬ ๊ณ์ฐ + hold-out์ผ๋ก ์ค์ธก coverage ๊ฒ์ฆ- ์๋๋ฆฌ์ค๋ณ๋ก
UQM.evaluate()โEDE.decide()์คํ compute_metrics(): TP/FN/FP/TN โ Safety Recall, Over-Escalation Rate ๊ณ์ฐ- JSON + CSV๋ก ์ ์ฅ
ReAct ์์ด์ ํธ๊ฐ ๋๊ตฌ๋ฅผ ํ์ฉํด ์ถ๋ก ํ๊ณ , UASEF๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์์ค์ปฌ๋ ์ด์ ์ ํ์ ํฉ๋๋ค. ์์ฐจ ํ์ดํ๋ผ์ธ ์คํ๊ณผ ๋์ผํ ์ผ์ด์ค๋ฅผ ์์ด์ ํธ๋ก ์คํํ์ฌ ๋๊ตฌ ์ฌ์ฉ์ ํจ๊ณผ๋ฅผ ๋น๊ตํฉ๋๋ค.
react_iterations: reason ๋ ธ๋ ํธ์ถ ํ์ (์ถ๋ก ๊น์ด)tool_calls: ๋๊ตฌ๋ณ ์ฌ์ฉ ํ์avg_tool_calls_per_case: ์ผ์ด์ค๋น ํ๊ท ๋๊ตฌ ํธ์ถ ์
์๋๋ฆฌ์ค โ ์ ๋ฌธ๊ณผ๋ชฉ ๋งคํ:
| ์๋๋ฆฌ์ค | ์ ๋ฌธ๊ณผ๋ชฉ | RTC ์ํ๋ | ์๊ณ๊ฐ ๋ฐฐ์จ |
|---|---|---|---|
| emergency | emergency_medicine | CRITICAL | ร0.60 ร 0.85 = ร0.51 |
| rare_disease | neurology | HIGH | ร0.75 ร 0.85 = ร0.64 |
| multimorbidity | internal_medicine | MODERATE | ร1.00 |
์์ด์ ํธ ๊ทธ๋ํ ์คํ ์์ธ:
graph.invoke(
initial_state,
config={"recursion_limit": 25} # ๋ฌดํ ๋ฃจํ ๋ฐฉ์ง
)max_iterations=5์ recursion_limit=25๋ ๋
๋ฆฝ์ ์
๋๋ค. max_iterations๋ reason ๋
ธ๋ ํธ์ถ ํ์๋ฅผ ์ ํํ๊ณ , recursion_limit์ LangGraph ๋ ๋ฒจ์ ์ ์ฒด ๋
ธ๋ ์ ํ ํ์๋ฅผ ์ ํํฉ๋๋ค.
MedAbstain 4๊ฐ ๋ณํ์์ UASEF๊ฐ ์์ค์ปฌ๋ ์ด์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ๊ฐ์งํ๋์ง ์ด์ง ๋ถ๋ฅ ๋ฌธ์ ๋ก ํ๊ฐํฉ๋๋ค.
| ์งํ | ์์ | ์ค์์ฑ |
|---|---|---|
| Safety Recall | TP / (TP + FN) | ํต์ฌ โ ํํ ๋ถ๊ฐ |
| Precision | TP / (TP + FP) | ๋ถํ์ํ ์์ค์ปฌ๋ ์ด์ ๋น์จ |
| F1 | 2 ร Precision ร Recall / (P + R) | ๊ท ํ ์งํ |
| Specificity | TN / (TN + FP) | ์ ์ ์ผ์ด์ค ์์จ ์ฒ๋ฆฌ ๋น์จ |
| AUROC | ์์ ์ฑ๋ฅ | ์๊ณ๊ฐ ๋ ๋ฆฝ์ ํ๋ณ๋ ฅ |
๋ณํ๋ณ ๋น๊ต์ ์๋ฏธ:
- AP recall < NAP recall โ ๋ชจ๋ธ์ด Abstention + Perturbation ์กฐํฉ์ ๋ ์ด๋ ค์ํจ
- A recall < AP recall โ Perturbation์ด ์์ด๋ ๋ถํ์คํ ์ผ์ด์ค๋ฅผ ๋์นจ
- NA specificity๊ฐ ๋ฎ์ผ๋ฉด โ ์ ์ ์ผ์ด์ค๋ฅผ ๊ณผ๋ํ๊ฒ ์์ค์ปฌ๋ ์ด์ (Over-Escalation ๋ฌธ์ )
Weighted CP ๋น๊ต ์คํ:
# ํ์ค CP
python experiments/eval_medabstain.py --backend openai
# Weighted CP (๋ถํฌ ์ด๋ ์ํฉ ์๋ฎฌ๋ ์ด์
)
python experiments/eval_medabstain.py --backend openai --weighted-cp๋ ๊ฒฐ๊ณผ์ ์ฐจ์ด๊ฐ Weighted CP์ ๊ธฐ์ฌ๋ฅผ ์ ๋ํํฉ๋๋ค.
compute_abstention_accuracy()๋ UASEF์ CP ๊ธฐ๋ฐ ์์ค์ปฌ๋ ์ด์
๊ณผ ๋ณ๋๋ก, LLM์ด ์ค์ค๋ก ๋ถํ์ค์ฑ์ ์ธ์ด๋ก ํํํ๋ ๋ฅ๋ ฅ์ ์ธก์ ํฉ๋๋ค.
| ๋ถ๋ฅ | ์กฐ๊ฑด | ์๋ฏธ |
|---|---|---|
| TA (True Abstain) | expected=True + ์๋ต์ ๋ถํ์ค ํํ ํฌํจ | ์ฌ๋ฐ๋ฅด๊ฒ uncertainty ํํ |
| FA (False Abstain) | expected=False + ์๋ต์ ๋ถํ์ค ํํ ํฌํจ | ๋ถํ์ํ uncertainty ํํ |
| TR (True Answer) | expected=False + ๋ถํ์ค ํํ ์์ | ์์ ์๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ๋ต๋ณ |
| MA (Missed Abstain) | expected=True + ๋ถํ์ค ํํ ์์ | โ ๋ ผ๋ฌธ ํต์ฌ ์งํ (๊ณํ์ ๋ชฉํ: +10%p ๊ฐ์ ) |
๊ฒฐ๊ณผ๋ medabstain_eval.json์ abstention_accuracy ํ๋์ ํฌํจ๋ฉ๋๋ค.
Coverage-Escalation Rate ํธ๋ ์ด๋์คํ์ ์ค์ ์ธก์ ์
๋๋ค. ฮฑ๋ฅผ ์ฌ๋ฌ ๊ฐ์ผ๋ก ์ค์ํ๋ฉฐ ๊ฐ (ฮฑ, specialty) ์กฐํฉ์์ ์ค์ธก (coverage, escalation_rate)๋ฅผ ์ธก์ ํฉ๋๋ค.
์ค์ ๋ฒ์:
ALPHAS = [0.01, 0.05, 0.10, 0.15, 0.20, 0.30]
SPECIALTIES = [
("emergency_medicine", "emergency"),
("internal_medicine", "multimorbidity"),
("general_practice", "routine"),
]์ด ์คํ ์: 6 ร 3 ร 2 (๋ฐฑ์๋) = 36 ํฌ์ธํธ
Pure CP ๋ชจ๋:
Pareto sweep์์๋ Trigger 2 (ํค์๋)์ Trigger 3 (๊ทผ๊ฑฐ ๋ถ์ฌ)๋ฅผ ์ ์ธํ๊ณ CP Trigger๋ง ์ฌ์ฉํฉ๋๋ค. ์ด๋ ์์ํ Conformal Prediction์ ํจ๊ณผ๋ง ์ธก์ ํ๊ธฐ ์ํจ์ ๋๋ค.
# ์์ CP Trigger๋ง
escalated = unc.nonconformity_score > rtc_config.adjusted_thresholdฮฑ ๊ถ๊ณ ์๊ณ ๋ฆฌ์ฆ:
์
๋ ฅ: (ฮฑ, specialty) ๋ณ ์ค์ธก (coverage, escalation_rate)
๋ชฉํ: specialty๋ณ ์ต์ ฮฑ ์ ํ
์ฐ์ ์์:
1. coverage โฅ 0.95 AND escalation_rate โค 0.15 โ utility = coverage - 2รesc_rate ์ต๋
2. coverage โฅ 0.95๋ง ์ถฉ์กฑ โ escalation_rate ์ต์
3. ์๋ฌด๊ฒ๋ ์ถฉ์กฑ ์ ๋จ โ utility ์ต๋ (fallback)
์ด ์๊ณ ๋ฆฌ์ฆ์ ์์ ์ ์ฝ(coverage)์ ํจ์จ(escalation_rate)๋ณด๋ค ํญ์ ์ฐ์ ํฉ๋๋ค. ์๋ฃ ๋๋ฉ์ธ์์ coverage ๋ฏธ์ถฉ์กฑ์ ์๋ช ์ํ๊ณผ ์ง๊ฒฐ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ฐ ๊ตฌ์ฑ ์์์ ๊ธฐ์ฌ๋ฅผ ์ ๋ํํ๊ธฐ ์ํด ์ธ ๊ฐ์ง ์์ค์ปฌ๋ ์ด์ ์ ๋ต์ ๋์ผํ ์ผ์ด์ค์์ ๋น๊ตํฉ๋๋ค.
| ์ ๋ต | ์ค๋ช | ์ธก์ ๋ชฉ์ |
|---|---|---|
no_escalation |
ํญ์ ์์จ ํ๋ | Safety Recall 0 ๊ธฐ์ค์ |
threshold_only |
CP Trigger 1๋ง ์ฌ์ฉ (T2/T3/์ํธ๋กํผ ์ ์ธ) | ์์ CP ํจ๊ณผ ๋ถ๋ฆฌ |
full_uasef |
T1 + T2 + T3 + ์ํธ๋กํผ ๊ฐ์ค์น | ์ ์ฒด ์์คํ ์ฑ๋ฅ |
threshold_only vs full_uasef ์ฐจ์ด๊ฐ EDE์ ํค์๋ยท๊ทผ๊ฑฐ ๋ถ์ฌ ํธ๋ฆฌ๊ฑฐ๊ฐ ์ถ๊ฐ์ ์ผ๋ก ๊ธฐ์ฌํ๋ Safety Recall ํฅ์๋์
๋๋ค.
โ ๋ฏธ๊ตฌํ: ๊ณํ์์ Temperature Scaling / MC Dropout ๋น๊ต๋ ํ์ฌ ๊ตฌํ๋์ง ์์์ต๋๋ค. ์ถ๊ฐ ์
BaselineScorer์ธํฐํ์ด์ค(score(),threshold())๋ฅผ ์ค์ํ๋ฉด ๋ฉ๋๋ค.
์ 4๊ฐ ์คํ(์์ด์ ํธ, ๋ฒ ์ด์ค๋ผ์ธ, MedAbstain, Pareto Sweep)์ ํ ๋ฒ์ ์์ฐจ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํตํฉ ์์ฝํฉ๋๋ค.
๊ฐ ์คํ ๋ชจ๋์ ํจ์๋ฅผ ์ง์ importํ์ฌ ์คํํ๋ฏ๋ก subprocess ์ค๋ฒํค๋ ์์ด ๋์ผํ Python ํ๋ก์ธ์ค์์ ์คํ๋ฉ๋๋ค. ํ๋์ ์คํ์ด ์คํจ(์: ๋ฐฑ์๋ ์ฐ๊ฒฐ ์ค๋ฅ)ํด๋ ๋๋จธ์ง ์คํ์ ๊ณ์ ์งํ๋ฉ๋๋ค.
| ํ์ผ | ์ค๋ช |
|---|---|
results/all_experiments_summary.json |
๋ชจ๋ ์คํ์ ํต์ฌ ์งํ(Safety Recall, AUROC, ฮฑ ๊ถ๊ณ ๋ฑ) ํตํฉ JSON |
results/all_experiments_report.md |
Safety Recall โฅ 0.95 ๋ฌ์ฑ ์ฌ๋ถ๋ฅผ ์ค์ฌ์ผ๋ก ํ Markdown ๋ณด๊ณ ์ |
ํน์ ์คํ์ ๊ฑด๋๋ธ ์ ์์ต๋๋ค. LMStudio ์๋ฒ๊ฐ ์๋ ํ๊ฒฝ์์ openai ๋จ๋ ์คํ ์ ์ ์ฉํฉ๋๋ค.
# pareto sweep ์ ์ธ (์๊ฐ์ด ๊ฐ์ฅ ์ค๋ ๊ฑธ๋ฆผ)
python experiments/run_all_experiments.py --backend openai --skip pareto| ์งํ | ๋ชฉํ | ์์ | ์๋ฏธ |
|---|---|---|---|
| Safety Recall | โฅ 0.95 | TP / (TP + FN) | ์์ค์ปฌ๋ ์ด์ ํด์ผ ํ ์ผ์ด์ค๋ฅผ ๋์น์ง ์์ |
| Over-Escalation Rate | โค 0.15 | FP / (FP + TN) | ์์จ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ผ์ด์ค๋ฅผ ๋ถํ์ํ๊ฒ ๋๊ธฐ์ง ์์ |
| Conformal Coverage | โฅ 1-ฮฑ | hold-out์์ s โค qฬ์ธ ๋น์จ | CP ์ด๋ก ๋ณด์ฅ์ ์ค์ธก ๊ฒ์ฆ |
- Safety Recall 0.95๋ "์์ค์ปฌ๋ ์ด์ ์ด ํ์ํ 100๊ฐ ์ผ์ด์ค ์ค 95๊ฐ ์ด์ ๊ฐ์ง"๋ฅผ ์๋ฏธํฉ๋๋ค. ์ด๋ ๋ ผ์ ์ฌ์ง ์๋ ์ต์ ์๊ตฌ์ฌํญ์ ๋๋ค.
- Over-Escalation Rate 0.15๋ "์์จ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ผ์ด์ค ์ค 15% ์ดํ๋ง ๋ถํ์ํ๊ฒ ์ ๋ฌธ์์๊ฒ ์ ๋ฌ"์ ์๋ฏธํฉ๋๋ค. ๋๋ฌด ๋ฎ์ผ๋ฉด ์ด์ ๋น์ฉ์ด ์ฆ๊ฐํฉ๋๋ค.
- Conformal Coverage๊ฐ
1-ฮฑ๋ณด๋ค ๋ฎ์ผ๋ฉด CP ์ด๋ก ์ด ์ค์ ๋ก ์๋ํ์ง ์๋ ๊ฒ์ ๋๋ค. ์ด ๊ฒฝ์ฐ calibration ๋ฐ์ดํฐ ๋ถ์กฑ(n < 30) ๋๋ distribution shift๊ฐ ์์ธ์ผ ์ ์์ต๋๋ค.
ฮฑ ๋ฎ์ถค โ Coverage โ, Safety Recall โ, Over-Escalation Rate โ
ฮฑ ๋์ โ Coverage โ, Safety Recall โ, Over-Escalation Rate โ
RTC multiplier ๋ฎ์ถค โ adjusted_threshold โ โ ๋ ๋ง์ ์์ค์ปฌ๋ ์ด์
RTC multiplier ๋์ โ adjusted_threshold โ โ ์ ์ ์์ค์ปฌ๋ ์ด์
์ด ํธ๋ ์ด๋์คํ๋ฅผ ์ ๋ฌธ๊ณผ๋ชฉ๋ณ๋ก ์ต์ ํํ๋ ๊ฒ์ด Pareto Sweep์ ๋ชฉ์ ์ ๋๋ค.
# uv ์ค์น (์์ผ๋ฉด)
curl -LsSf https://astral.sh/uv/install.sh | sh
# ์์กด์ฑ ์ค์น
uv sync
# ํ๊ฒฝ ๋ณ์ ์ค์
cp .env.example .env
# .env์์ OPENAI_API_KEY, LMSTUDIO_MODEL ์์ - LMStudio ์ฑ ์คํ โ ๋ชจ๋ธ ๋ค์ด๋ก๋ (๊ถ์ฅ:
meta-llama-3.1-8b-instruct) - Local Server ํญ โ Start Server (๊ธฐ๋ณธ ํฌํธ: 1234)
.env์LMSTUDIO_MODEL์ ๋ก๋๋ ๋ชจ๋ธ๋ช ์ผ๋ก ์์
์์ด์ ํธ ์คํ์ ReAct ๋ฃจํ๋ฅผ ์๊ฐ์ ์ผ๋ก ์ถ์ ํ ์ ์์ต๋๋ค.
# .env์ ์ถ๊ฐ
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=<your-key>
LANGCHAIN_PROJECT=UASEF-agent# ๊ฐ๋ฐ ํ
์คํธ
python experiments/run_calibration_pipeline.py --backend openai
# ๋
ผ๋ฌธ ํ์ง (๊ถ์ฅ)
python experiments/run_calibration_pipeline.py --backend openai --n-cal 500 --n-labeled 50์ด ๋จ๊ณ๊ฐ ์๋ฃ๋๋ฉด base_config.yaml์ rtc / entropy_threshold / ede ์น์
์ด ์๋ ๊ฐฑ์ ๋ฉ๋๋ค. ์ดํ ๋ชจ๋ ์คํ์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ํ๋ผ๋ฏธํฐ๊ฐ ์ ์ฉ๋ฉ๋๋ค.
# [Primary] OpenAI๋ง โ ๋น ๋ฅธ ์ค๋ชจํฌ ํ
์คํธ
python experiments/run_all_experiments.py --backend openai
# [Primary] OpenAI ๋
ผ๋ฌธ ํ์ง
python experiments/run_all_experiments.py --backend openai \
--n-cal 500 --n-test 50 --n-medabstain 100 --n-pareto-test 100
# [Primary + Ablation] ๋
ผ๋ฌธ ์ต์ข
์คํ (openai=logprob, lmstudio=logprob ์๋ ์ ํ)
python experiments/run_all_experiments.py --n-cal 500 --n-test 50
# ํน์ ์คํ ๊ฑด๋๋ฐ๊ธฐ
python experiments/run_all_experiments.py --backend openai --skip pareto์คํ ํ results/all_experiments_report.md์์ [Primary] / [Ablation] ๊ตฌ๋ถ์ด ๋ช
์๋ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
# [Primary + Ablation] ์ ์ฒด ์คํ (scoring method ์๋ ์ ํ)
python experiments/run_experiment.py --n-cal 500 --n-test 50
# [Primary] OpenAI๋ง (logprob)
python experiments/run_experiment.py --backend openai --n-cal 500 --n-test 50
# [Ablation] ๋ก์ปฌ๋ง (logprob via LM Studio)
python experiments/run_experiment.py --backend lmstudio --n-cal 500 --n-test 50
# ์๋๋ฆฌ์ค๋ณ config ์ ์ฉ
python experiments/run_experiment.py --config experiments/configs/scenario_emergency.yaml
# ๊ฒฐ๊ณผ ์๊ฐํ
python experiments/visualize_results.py# [Primary + Ablation] ์ ์ฒด ์คํ
python experiments/run_agent_experiment.py --n-cal 500 --n-test 50
# [Primary] OpenAI๋ง
python experiments/run_agent_experiment.py --backend openai --n-cal 500 --n-test 50
# [Ablation] ๋ก์ปฌ๋ง
python experiments/run_agent_experiment.py --backend lmstudio --n-cal 500 --n-test 50
# PubMedQA ํฌํจ
python experiments/run_agent_experiment.py --backend openai --include-pubmedqa# [Primary + Ablation] ์ ์ฒด ๋น๊ต
python experiments/run_baseline_comparison.py --n-cal 500 --n-test 50
# [Primary] OpenAI๋ง
python experiments/run_baseline_comparison.py --backend openai --n-cal 500 --n-test 50# ์ ์ฒด ๋ณํ (AP, NAP, A, NA)
python experiments/eval_medabstain.py --backend openai
# ํต์ฌ safety ์ผ์ด์ค๋ง (AP/NAP)
python experiments/eval_medabstain.py --backend openai --variants AP NAP --n 100
# Weighted CP ๋น๊ต
python experiments/eval_medabstain.py --backend openai --weighted-cp# ฮฑ sweep ์คํ
python experiments/pareto_sweep.py --backend openai --n-cal 500
# ๊ธฐ์กด sweep ๊ฒฐ๊ณผ์์ ๊ถ๊ณ ๋ง ์ฌ๊ณ์ฐ
python -c "
from experiments.pareto_sweep import recommend_alpha, print_recommendations
recs = recommend_alpha()
print_recommendations(recs)
"# ๋ชจ๋ธ ์ฐ๊ฒฐ ํ์ธ (logprobs ์ง์ ์ฌ๋ถ ํฌํจ)
python models/model_interface.py
# UQM ๋จ๋
(logprob ๋์ ํ์ธ, self_consistency ๋น๊ต ๊ฐ๋ฅ)
python models/uqm.py
# RTC + EDE ๋จ๋
(๊ฐ์ UncertaintyResult๋ก ํธ๋ฆฌ๊ฑฐ ํ์ธ)
python models/rtc_ede.py| ํ์ผ | ์์ฑ ์คํฌ๋ฆฝํธ | ์ค๋ช |
|---|---|---|
results/experiment_results.json |
run_experiment.py |
๋ฐฑ์๋๋ณ, ์๋๋ฆฌ์ค๋ณ ์ ์ฒด ์ผ์ด์ค ๊ฒฐ๊ณผ |
results/comparison_table.csv |
run_experiment.py |
Safety Recall / Over-Escalation Rate / Coverage ์์ฝํ |
results/agent_results.json |
run_agent_experiment.py |
์์ด์ ํธ ์คํ ์ ์ฒด ๊ฒฐ๊ณผ (tool_calls, react_iterations ํฌํจ) |
results/agent_comparison_table.csv |
run_agent_experiment.py |
์์ด์ ํธ ๋น๊ต ์์ฝ |
results/baseline_comparison.json |
run_baseline_comparison.py |
no_escalation / threshold_only / full_uasef ์ ๋ต๋ณ Safety Recall + Over-Escalation Rate |
results/baseline_comparison.csv |
run_baseline_comparison.py |
๋ฒ ์ด์ค๋ผ์ธ ๋น๊ต ์์ฝํ |
results/medabstain_eval.json |
eval_medabstain.py |
๋ณํ๋ณ Precision / Recall / F1 / AUROC + Abstention Accuracy ์ ์ฒด ๊ฒฐ๊ณผ |
results/medabstain_eval_summary.csv |
eval_medabstain.py |
๋ฐฑ์๋ ร ๋ณํ ์์ฝํ |
results/pareto_sweep_results.json |
pareto_sweep.py |
ฮฑ ร specialty ์ค์ธก (coverage, escalation_rate) |
results/pareto_frontier.png |
pareto_sweep.py |
ฮฑ ๋ณ trajectory + ์ด์์ ์์ญ |
results/alpha_recommendations.json |
pareto_sweep.py |
specialty๋ณ ์ต์ ฮฑ ๋ฐ ๊ถ๊ณ ์ด์ |
results/comparison_bar.png |
visualize_results.py |
๋ฐฑ์๋๋ณ Safety Recall / Over-Escalation Rate ๋ฐ์ฐจํธ |
results/latency_comparison.png |
visualize_results.py |
๋ก์ปฌ vs ํด๋ผ์ฐ๋ ์๋ต ์ง์ฐ ๋น๊ต |
results/all_experiments_summary.json |
run_all_experiments.py |
๋ชจ๋ ์คํ ํต์ฌ ์งํ ํตํฉ (์์ด์ ํธยท๋ฒ ์ด์ค๋ผ์ธยทMedAbstainยทPareto) |
results/all_experiments_report.md |
run_all_experiments.py |
Safety Recall โฅ 0.95 ๋ฌ์ฑ ์ฌ๋ถ ํฌํจ Markdown ๋ณด๊ณ ์ |
results/calibration_report.json |
run_calibration_pipeline.py |
์บ๋ฆฌ๋ธ๋ ์ด์ ์ ๊ณผ์ ๊ฒฐ๊ณผ (RTC sweep, Youden's J, EDE grid search, ROC data) |
| ๊ตฌ๋ถ | ๋ฐฑ์๋ | scoring_method |
๋ ผ๋ฌธ ์น์ |
|---|---|---|---|
| [Primary] | openai |
logprob |
Main Results |
| [Ablation] | lmstudio |
logprob |
Ablation Study |
# experiments/configs/base_config.yaml
uqm:
alpha: 0.05
scoring_method: auto # openai=logprob(Primary), lmstudio=logprob(Ablation) ์๋ ์ ํ
holdout_fraction: 0.2
data:
n_calibration: 500 # CP ๋ณด์ฅ ์ค์ฉ ํํ
n_test_per_scenario: 50 # ์๋๋ฆฌ์ค๋ณ ์ผ์ด์ค ์
# ์๋ ์น์
์ run_calibration_pipeline.py ์คํ ํ ์๋ ๊ฐฑ์ ๋ฉ๋๋ค.
# ์ง์ ํธ์งํ์ง ๋ง์ธ์.
rtc:
CRITICAL: 0.60 # rtc_calibration.py Pareto sweep ๊ฒฐ๊ณผ
HIGH: 0.75
MODERATE: 1.00
LOW: 1.30
entropy_threshold: 2.0 # entropy_calibration.py Youden's J ๊ฒฐ๊ณผ
ede:
t1_weight: 0.40 # ede_coefficient_search.py grid search ๊ฒฐ๊ณผ
entropy_boost: 0.15ํ์ฌ ๊ธฐ๋ณธ๊ฐ(
n_calibration=30)์ ๊ฐ๋ฐ/๋๋ฒ๊ทธ ์ ์ฉ์ ๋๋ค. n์ด ๋๋ฌด ์์ผ๋ฉด qฬ๊ฐ ๋ณด์์ (over-coverage)์ด ๋์ด ์งํ๊ฐ ๋๊ด์ ์ผ๋ก ๋ณด์ ๋๋ค. ๋ ผ๋ฌธ ํ์ง ๊ฒฐ๊ณผ๋ฅผ ์ํด ๋ฐ๋์n โฅ 500์ ์ฌ์ฉํ์ธ์.
calibration_report.json์ ์ ์ฒด sweep ๊ฒฐ๊ณผ(RTC Pareto, ROC curve, EDE grid)๊ฐ ์ ์ฅ๋์ด ๋
ผ๋ฌธ ๋ถ๋ก ํ
์ด๋ธ์ ์ง์ ์์ฑํ ์ ์์ต๋๋ค. ์บ๋ฆฌ๋ธ๋ ์ด์
ํ์ดํ๋ผ์ธ๊ณผ ์คํ์ ๋ถ๋ฆฌํ์ฌ ์คํํ๋ฉด ํ์ดํผํ๋ผ๋ฏธํฐ ๋์ถ ์์ด ๋
๋ฆฝ์ ์ธ test set ํ๊ฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
- Primary์ Ablation ๋ชจ๋ ๋์ผํ
logprob๋น์ ํฉ ํจ์๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์์น๋ฅผ ๊ฐ์ ํ ์ด๋ธ์์ ๋น๊ตํ ์ ์์ต๋๋ค. ๋จ, ๋ชจ๋ธ(GPT-4o-mini vs ๋ก์ปฌ GGUF)์ด ๋ค๋ฅด๋ฏ๋ก nonconformity score์ ์ ๋๊ฐ ์ค์ผ์ผ ์ฐจ์ด๋ ์กด์ฌํฉ๋๋ค. - Ablation ์น์ ์์ ๋ช ์์ ์ผ๋ก ๊ธฐ์ : "We apply the same logprob-based nonconformity scoring to both OpenAI and local GGUF models via LM Studio's OpenAI-compatible API, demonstrating that the CP coverage guarantee holds across both deployment environments."
- Primary ๊ฒฐ๊ณผ๊ฐ ๋ ผ๋ฌธ ์ฃผ์ ์ฃผ์ฅ์ ๊ทผ๊ฑฐ๊ฐ ๋ฉ๋๋ค. Ablation์ "๋ก์ปฌ GGUF ๋ชจ๋ธ์์๋ ๋์ผํ logprob CP ์ ์ฉ ๊ฐ๋ฅ"์ ๋ณด์ด๋ ๋ณด์กฐ ์ฆ๊ฑฐ์ ๋๋ค.
qฬ = โ(n+1)(1-ฮฑ)โ/n ๋ฒ์งธ ์์ ๋น์ ํฉ ์ ์
P(s_test โค qฬ) โฅ 1 - ฮฑ (์ด๋ก ์ ํํ)
n = 500, ฮฑ = 0.05 โ ์ค์ธก coverage โ 0.95 (์ด๋ก ๊ฐ๊ณผ ๊ทผ์ )
n = 30, ฮฑ = 0.05 โ ์ค์ธก coverage โ 0.97~1.00 (๋ณด์์ โ ๊ณผ์ถ์ )
-
Conformal Prediction ๊ธฐ์ด Angelopoulos, A. N., & Bates, S. (2021). A gentle introduction to conformal prediction and distribution-free uncertainty quantification. arXiv:2107.07511
-
Weighted Conformal Prediction (Distribution Shift) Tibshirani, R. J., Barber, R. F., Candรจs, E. J., & Ramdas, A. (2019). Conformal prediction under covariate shift. NeurIPS 2019. arXiv:1904.06019
-
MedQA (USMLE ๋ฐ์ดํฐ์ ) Jin, D., Pan, E., Oufattole, N., Weng, W. H., Fang, H., & Szolovits, P. (2021). What disease does this patient have? A large-scale open domain question answering dataset from medical exams. Applied Sciences, 11(14). arXiv:2009.13081
-
PubMedQA (Biomedical QA) Jin, Q., Dhingra, B., Liu, T., Cohen, W., & Lu, X. (2019). PubMedQA: A dataset for biomedical research question answering. EMNLP 2019. arXiv:1909.06146
-
MedAbstain (LLM ๋ถํ์ค์ฑ ํํ) Zhu, K., Wang, J., Zhou, J., Wang, Z., Chen, H., Wang, X., Zhang, X., & Ye, H. (2023). PromptBench: Towards evaluating the robustness of large language models on adversarial prompts. arXiv:2306.13063
-
NO_EVIDENCE ํค์๋ ์ถ์ฒ (Trigger 3) Savage, T., et al. (2025). Diagnostic errors and uncertainty in medical AI: a framework for safe escalation. (source: savage2025 in
NO_EVIDENCE_PHRASES) -
MIMIC-III (ICU ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค) Johnson, A. E. W., Pollard, T. J., Shen, L., Lehman, L. H., Feng, M., Ghassemi, M., Moody, B., Szolovits, P., Celi, L. A., & Mark, R. G. (2016). MIMIC-III, a freely accessible critical care database. Scientific Data, 3, 160035.
-
ReAct (์ถ๋ก +ํ๋ ์์ด์ ํธ) Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K., & Cao, Y. (2023). ReAct: Synergizing reasoning and acting in language models. ICLR 2023. arXiv:2210.03629
