Jamorham
Nightscout용 xDrip+ 버전
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Formula 1 — 실패를 미리 겪어보는 AI 제형 설계 시스템 약을 실제로 만들어 보기 전에, 여러 AI가 서로 견제하며 "이 처방은 왜 실패할지"를 미리 찾아내고, 연구자가 고른 처방을 QTPP·위험평가부터 실험계획·회귀식·ANOVA, 검증 게이트를 넘은 회귀식으로 그린 Design Space(Overlay plot · control space)와 확인계획까지 단계마다 승인하며 이끄는 시스템입니다. 제4회 인공지능 신약개발 경진대회 출품작 · 팀 Formula 1 바로 써 보기 → (비밀번호 또는 게스트로 접속 — 게스트는 무료 모델만) 시스템은 두 단계로 나뉩니다.README 전문 보기 ↗
약을 실제로 만들어 보기 전에, 여러 AI가 서로 견제하며 "이 처방은 왜 실패할지"를 미리 찾아내고, 연구자가 고른 처방을 QTPP·위험평가부터 실험계획·회귀식·ANOVA, 검증 게이트를 넘은 회귀식으로 그린 Design Space(Overlay plot · control space)와 확인계획까지 단계마다 승인하며 이끄는 시스템입니다.
제4회 인공지능 신약개발 경진대회 출품작 · 팀 Formula 1
바로 써 보기 → https://zihwan.com/formula1 (비밀번호 없이 누구나 접속)
시스템은 두 단계로 나뉩니다.
① 후보 탐색. 분자식을 넣으면 컴퓨터가 작용기를 계산하고, 처방을 만들기 전에 이 약이 어떤 부류인지부터 정합니다(BCS/DCS 용해도·투과도, 고체상, 가용화 전략 필요 여부, ASD 공정). 그다음 여러 전략의 후보 처방을 동시에 만들고, 출처가 붙은 규칙표들이 정해진 순서대로 검사합니다. 통과한 처방만 상황에 맞게 불려 온 AI 심사관이 순위를 매기고, 반려되면 AI가 이유를 읽고 다시 설계합니다. 값을 모른다고 멈추지 않습니다 — 계산값 → 예측식 → 실측값 중 있는 것까지만 쓰고, 판정이 실제로 갈리는 지점에서만 구체적인 실측을 되묻습니다.
② 2단계 — Design Space 도출. 연구자가 후보 하나를 골라 이 후보로 개발 착수를 누르면 그 처방이 프로토타입(성분 · mg · % · 기능)이 되고(조성과 요청 맥락은 불변 Handoff로 함께 넘어옴), ICH Q8 순서대로 QTPP → CQA 판별 → 원료 물성·제형·공정 변수 위험평가 → 종합 정리(DoE 변수 후보 = High인 변수, 고르지 않음) → 실험 설계 표 → 회귀식(검증 게이트) → 반응 곡면 → ANOVA → Overlay plot Design Space(control space · 최적 처방) → 확인계획 잠금 → 확인배치의 15단계를 한 단계씩 승인하며 갑니다. 초안은 LLM이, 위험 행렬·회귀·ANOVA·영역은 코드가, 승인은 연구자가 합니다. 8단계(종합 정리)에 들어오면 위험평가 보고서, 12단계 뒤에는 최종 보고서가 PDF로 나옵니다.
입력 에이전트. 화면은 대화 하나이고, 가운데 입력칸이 곧 입력 에이전트입니다. "고령자용 로사르탄 캡슐 50 mg"처럼 말하면 에이전트가 지금 화면의 맥락(진행 중인 설계, 남은 데이터 요청, 권고 후보)을 읽고 실행할 수 있는 입력 카드로 정리해 제안합니다. 구조식은 사용자 입력·내장 사전·PubChem에서만 가져와 출처를 붙이고, 용량처럼 빠진 값은 되묻습니다. 설계가 끝나면 먼저 다음 행동(남은 요청, 개발 착수)을 짚어 줍니다. 판정은 여전히 규칙이 하고, 실행은 연구자가 카드의 버튼을 눌러야 일어납니다.
모든 과정이 웹 화면에서 보입니다. 시스템은 데이터를 지어내지 않습니다 — LLM이 응답하지 않으면 처방이나 점수를 대신 채우지 않고 "응답 없음"으로 표시하며, 시연 데이터는 전부 공개 논문의 실측값입니다.
새로운 약 하나를 세상에 내놓기까지 보통 10년이 넘게, 수조 원이 듭니다. 그런데 이 과정이 "약효 성분을 찾는 일"로 끝나지 않습니다. 약효를 내는 주성분을 찾았더라도 사람이 삼킬 수 있는 형태 — 알약, 캡슐, 시럽 — 로 만들어야 비로소 약이 됩니다. 이 단계를 제형 설계라고 부릅니다.
문제는 주성분 하나로는 알약이 굳지 않는다는 점입니다. 그래서 여러 첨가제를 섞는데, 바로 그 조합에서 사고가 납니다.
| 사고 유형 | 무슨 일이 생기나 |
|---|---|
| 화학적 충돌 | 주성분과 첨가제가 반응해 약이 갈색으로 변하거나 분해된다 |
| 공정 실패 | 가루를 눌러 알약으로 찍을 때 부서지거나 기계에 들러붙는다 |
| 규제 초과 | 나라마다 정한 첨가제 상한을 넘긴다. 어린이용은 기준이 훨씬 엄격하다 |
처방이 정해진 뒤에도 끝이 아닙니다. 혼합 시간, 붕해제 함량 같은 변수를 얼마나 흔들어도 규격을 지키는지 — 운전 영역 — 를 실험으로 증명해야 합니다. 제약 현장은 이 모든 것을 실험실에서 직접 만들어 보고, 실패하면 다시 설계하는 방식으로 풀어 왔고, 그 시행착오를 수십 번 반복합니다. 이 값비싼 시행착오를 가능한 한 컴퓨터 안에서 먼저 끝내고, 꼭 필요한 실험만 정확히 계획하자는 것이 이 프로젝트의 출발점입니다.
"AI가 똑똑하니 좋은 처방을 물어보면 되지 않나?" 여기에 함정이 있습니다.
거대언어모델은 말을 아주 그럴듯하게 합니다. 그런데 그럴듯한 것과 실제로 맞는 것은 다릅니다. 이런 AI는 없는 사실을 자신 있게 지어내는 일(환각) 이 있습니다. 일어나지 않는 화학 반응을 매끄럽게 설명하고, 만들 수 없는 처방을 태연히 제시하며, 규제 수치를 지어내기도 합니다. "이 첨가제는 15mg까지 괜찮다"고 단언하지만 실제 기준은 10mg일 수 있습니다. 같은 대회 모델로 재 보면 계산은 정확했지만, 유당을 반드시 넣으라는 요청에는 대부분 처방을 냈고 그중 일부는 아민–유당 반응 가능성을 스스로 적고도 "조건부로 가능"이라고 판단했습니다(14장 어블레이션).
제약에서 이런 실수는 곧 제품 폐기와 허가 반려입니다. 그래서 이 분야에는 "그럴듯함"이 아니라 "확실히 맞음" 이 필요합니다.
역할을 셋으로 나눴습니다.
새로운 처방과 가설을 상상하는 일은 AI에게, 그것이 맞는지 검사하고 숫자를 계산하는 일은 절대 틀리지 않는 규칙과 엔진에게, 무엇을 개발하고 어떤 판단을 받아들일지는 연구자에게 맡긴다.
첨가제와 공정 조건의 조합은 사실상 천문학적입니다. 이 넓은 공간에서 쓸 만한 후보를 상상하고, 서로 부딪히는 목표(안정성·복용 편의·생산 단가·규제 통과) 사이에서 타협점을 찾는 일은 규칙만으로는 못 합니다. AI가 잘하는 일입니다.
반대로 "이 첨가제가 어린이 상한을 넘는가", "이 영역에서 미래 배치가 규격을 통과할 확률은 얼마인가" 같은 판단은 계산기처럼 언제나 똑같이 내려야 합니다. 여기에 AI의 추측이 끼어들면 위험해집니다.
| 성격 | 예시 | 담당 |
|---|---|---|
| 숫자로 답이 떨어지는 것 | "이 첨가제가 10mg 이하인가", 회귀계수·예측구간 | 규칙 기반 검사기 · 통계 엔진 |
| 맥락을 읽어야 하는 것 | "이 조합이 어린이가 먹기에 자연스러운가", 실패 원인 가설 | 심사·가설 AI |
| 말을 입력으로 옮기는 것 | "용량은 50 mg", "압축력은 몰라요" → 실행 카드 | 입력 에이전트 (숫자·구조식은 사용자 글과 공개 DB에서만) |
| 받아들일지 정하는 것 | 어떤 후보를 개발할지, 어떤 회귀 모형을 쓸지(게이트 안에서) | 연구자 |
규칙은 "이건 틀렸어"까지만 말할 수 있고 새로운 답을 만들지는 못합니다. AI는 답을 만들지만 스스로 확정하지 못합니다. 셋은 경쟁이 아니라 서로의 빈틈을 메우는 역할 분담입니다.
flowchart TB
U(["연구자<br/>말 · 폼 입력 · 측정값 · 승인"])
IA["입력 에이전트<br/>맥락 읽기 · 말 → 제안 카드 · 빠진 값 되묻기 · 먼저 알림"]
subgraph D["① 후보 탐색 — CandidateDiscoveryGraph"]
direction TB
PG["페이즈 게이트 · LLM 0회<br/>파생값 → BCS/DCS → 고체상 → 가용화 → ASD → 공정 경로"]
DN["실험 요청 ① 전략을 좁히는 값<br/>막지 않음"]
PL[["계획 · 전략 점수 → 상위 3개<br/>같은 입력 = 같은 계획(서명)"]]
G["병렬 설계 — 전략별 후보"]
R{{"규칙 게이트 · 오차 0%<br/>배합 금기 · 공정 · 규제"}}
DR["실험 요청 ② 신뢰도를 높이는 값<br/>후보별 grounded / provisional"]
J["동적 심사위원단<br/>조건 맞는 심사관만 · 반려 권한 없음"]
C(["후보 처방 목록<br/>성분 · 공정 단계 · 근거 · 신뢰도 · 남은 요청"])
BT["되돌림 — 반려 사유별 복귀 지점<br/>backtrack_transitions.csv"]
RF["반성 AI — 재설계 지시"]
Q(["목표(QTPP) 재검토<br/>남은 전략 없음"])
INF(["제약 불가능 판정<br/>막은 규칙 · 대안 · 소집 예정이던 심사관"])
PG --> DN --> PL
PL -->|전략 ≥ 1| G --> R
PL -->|전략 0| Q
R -->|통과| DR --> J --> C
R -->|반려| BT --> RF
RF -->|성분만 교체| G
RF -->|공정·전략부터| PL
R -->|고정 성분이 반려 사유| INF
end
EV{{"근거 결손 게이트 · LLM 0회<br/>필수 근거 16행 → 없으면 확인시험 66종에서 요청<br/>측정값 입력(카드 · 말로) → phase_gates부터 재계산 → 재판정"}}
H(["프로토타입 (Table 1 형식) + 불변 Handoff<br/>고른 후보의 성분 · mg · % · 기능 · 공정 · 요청 맥락"])
subgraph E["② 2단계 — Design Space 도출 (15단계 · 단계마다 승인)"]
direction TB
E1["QTPP → CQA 판별<br/>LLM 초안 · 근거 필수"]
E2["원료 물성 · 제형·공정 변수 위험평가<br/>근거 표 → 코드가 행렬 계산"]
E3["종합 정리 · DoE 변수 후보(High, 선택 없음)<br/>→ 위험평가 보고서 PDF"]
E4["실험 설계 표 (요인 1–3 · 반응 1–4)"]
E5["회귀식 · 모형 진단 → 반응 곡면 → ANOVA<br/>결정론 toolkit"]
E6["Design Space — Overlay plot(평균 예측 영역 · control space · 최적 처방)<br/>확인계획 잠금 → 확인배치 2×2"]
V(["최종 보고서 PDF"])
E1 --> E2 --> E3 --> E4 --> E5 --> E6 --> V
end
U <--> IA
IA -->|확인한 카드만| PG
IA -->|측정값 제출| DR
IA -->|개발 착수 카드| H
C -->|연구자가 후보 하나를 선택| EV -->|근거 충족 · 또는 결손 사유 기록| H --> E1
두 단계는 내부 상태를 공유하지 않고, 연구자가 고른 후보의 처방(프로토타입)과 불변 Handoff 하나로만 이어집니다. 후보 1위가 자동으로 개발에 들어가지도 않습니다 — 후보 카드의 이 후보로 개발 착수(또는 입력 에이전트가 제안한 같은 카드)를 눌러야 시작합니다.
그 사이에 근거 결손 게이트가 있습니다. 룰북 통과는 "알려진 금기가 없다"일 뿐 "알고 있다"가 아니기 때문입니다. 통과 후보마다 필수 근거(수분·열 안정성, 배합적합성, 실험 용해도, BCS 근거 등 evidence_requirements.csv 16행)가 있는지 결정론으로 따지고, 없으면 확인시험 마스터 66종의 실제 행에서만 시험을 요청합니다. 시험 결과는 후보마다 따로 넣지 않고, 후보 카드 다음에 뜨는 근거 결손 게이트 카드 하나에 넣습니다 — 통과 후보들의 결손을 요구 항목별로 모아(항목마다 해당 후보 표시) 보여 주며, 측정값은 후보가 아니라 스펙에 들어가 모든 후보를 함께 다시 판정하기 때문입니다. 후보 카드에는 근거 상태 한 줄과 사유 칸만 남습니다. 이 카드에 측정값(수치나 수행 여부 · 근거 등급)을 넣으면, 적합/부적합을 고르는 대신 그 값이 데이터 요청과 같은 재계산 경로로 들어가 페이즈 게이트부터 다시 계산합니다 — 계획, 통과 후보의 규칙 게이트 판정, 근거 판정이 차례로 갱신되고(LLM 없음, 전략 집합이 바뀔 때만 후보 재설계) 그 과정이 트레이스에 phase_gates → plan → gate 순서로 남습니다. BCS 근거는 용해도 부피와 흡수율을 넣어 규칙표가 실측 BCS 등급을 만들 때 채워집니다. 값은 입력 에이전트에 말로 넣어도 됩니다(항목의 [말로 입력] — 5장) — 용해도는 pH마다, 투과도는 흡수율·생체이용률·Papp처럼 표현과 단위가 제각각이라 칸보다 문장이 편하기 때문이며, 환산은 코드가 합니다. 선행 근거가 빠진 채로 개발에 들어가려면 사유를 남겨야 하고 — 결손이 남은 후보 카드마다 승인 칸(무엇이 비었는지 적힌 기본 사유, 연구자가 고칠 수 있음)과 [사유 기록 · 승인하고 2단계로]가 있어, 후보별로 한 번 누르면 바로 2단계로 넘어갑니다. 설계가 끝나면 데이터 요청 카드보다 먼저 뜨는 심사위원단 카드에서도 통과 후보 하나를 골라(에이전트 추천에서 바꿀 수 있음) 바로 승인할 수 있습니다. 입력 에이전트의 개발 착수 카드는 1순위로 시작하지만 통과 후보 전체를 고를 수 있고(순위 · 점수 · 결손 표시), 고른 후보의 결손과 승인 사유를 보여 준 뒤 [실행]을 누르면 그 후보를 같은 사유로 승인합니다. 그 사유와 남은 결손이 Handoff(지문 포함)와 2단계 보고서에 남습니다. 반려 권한은 여전히 룰북에만 있고, 이 게이트는 개발 착수를 보류할 뿐 후보 목록을 바꾸지 않습니다.
AI 구성은 고정돼 있지 않습니다. 요청마다 필요한 전략과 심사관을 그때그때 골라 팀을 새로 꾸리는데, 그 선택은 AI가 아니라 규칙표가 결정론적으로 합니다 — 같은 입력이면 같은 계획이 나오고(계획 서명 plan_signature), 그 계획 자체가 감사 기록이 됩니다.
① 후보 탐색은 "만들기 전에 실패를 걸러내는" 쪽입니다. 페이즈 게이트가 분자에서 계산한 값과 경험식 예측으로 "이 약에 어떤 전략이 맞는가"를 판정하고(AI 없음), 계획이 전략 점수 상위 3개를 고르면 설계 계층이 전략마다 후보를 동시에 만들어 경쟁시킵니다. 규칙 게이트만 후보를 반려할 수 있고, 반려되면 사유에 따라 어느 단계로 되돌아갈지가 규칙표에 정해져 있습니다(10장). 실험 요청은 두 번 나오지만 어느 쪽도 흐름을 멈추지 않습니다(9장). 심사위원단은 맥락을 읽어야 하는 부분을 담당하되 반려 권한이 없습니다 — 점수는 통과한 후보들 사이의 순위에만 씁니다.
② 2단계는 "고른 처방에서 무엇이 품질을 좌우하는지 가리고, 실험 데이터로 그 영향을 식으로 보이는" 쪽입니다. 단계마다 멈추고 연구자의 승인을 기다립니다(11장).
입력 에이전트는 두 단계 앞에 서서 대화를 받습니다. 그래프에 직접 값을 넣지 않고, 사람이 누르는 것과 같은 경로(설계 실행·측정값 제출·개발 착수)로 가는 제안 카드만 만듭니다(5장).
| ① 후보 처방에 포함 | ①에서 제외 (② 또는 범위 밖) |
|---|---|
| 성분 목록(역할 · 비율) | 포장 사양(용기 · 차단성) — 처방이 실행되기 전에는 대상이 없음 |
| 전략 가족과 공정 단계(예: 분무건조 ASD → 건식과립 → 타정) | 공정 파라미터 값·실험계획·회귀식 → ② 2단계 |
| 판정 근거(어느 규칙이 왜 통과/반려했는지) | 용출 시험법 · 생체등가성 전략 |
신뢰도 태그(grounded / provisional)와 남은 실험 요청 | 승인·서명 절차, 상업 배치 |
명단에 일곱 명이 등록돼 있고(reviewer_registry.csv), 조건이 맞는 사람만 그 자리에서 만들어집니다.
| 심사관 | 소집 조건 |
|---|---|
| 어린이 안전 | 대상이 어린이일 때 |
| 가용화 전략 | 가용화·미분화 후보가 생겼거나, 실측 BCS가 II/IV일 때 |
| 공정 실현성 | 항상 |
| 규제 취지 | 숫자로 못 끊은 규제 판단이 남았을 때 |
| 문헌 조사 | 룰북이 모르는 성분이 있거나, 룰북이 다루지 않는 전략(ASD·지질제형·사이클로덱스트린)이 후보일 때 |
| 고령자 안전 | 대상이 고령자일 때 |
| 고체상 안정성 | ASD 후보가 있거나, 염/공결정 경계 구간이거나, 염 안정성 주의가 켜졌을 때 |
어린이용 요청에서는 어린이 안전 심사관이 들어오고 고령자 심사관은 아예 만들어지지 않습니다. 요청을 고령자용으로 바꾸면 반대가 됩니다.
심사 점수에는 검증된 인용이 필요합니다. 심사관은 인용을 DOI·PMID로만 할 수 있고, 인용 후보로는 이 약에 대해 Europe PMC가 돌려준 실제 문헌과 룰북 인용 등록부(citation_registry.csv — 룰북에 적힌 식별자를 Crossref·NCBI로 조회해 통과한 것)가 주어집니다. 목록 밖 식별자는 그 자리에서 Crossref·NCBI로 조회해 실재할 때만 인정하고, 검증된 인용이 하나도 없으면 그 점수는 무효로 합의에서 빠집니다("출처 없는 판단은 쓰지 않는다"는 원칙을 심사 점수에도 적용). 응답이 없으면 간격을 두고 두 번 더 시도하고, 그래도 없으면 "점수 없음"으로 표시합니다. 모델의 내부 추론(reasoning 채널)은 화면에 흘리지 않습니다.
시스템과 사람 사이에 AI가 하나 더 있습니다. 폼을 채우는 대신 말로 요청하면, 에이전트가 지금 맥락을 들고 그 말을 실행할 수 있는 입력으로 정리합니다.
사용자의 말 ─┐
├─→ 입력 에이전트 ─→ 제안 카드 ─→ [실행] ─→ 사람이 누르는 것과 같은 경로
서버가 읽은 맥락 ┘ (LLM 해석 + │ · 설계 실행 (폼 값으로 같은 startRun)
· 진행 중인 설계 코드 가드레일) │ · 측정값 제출 → 재계산
· 남은 실험 요청 · 권고 후보 │ · 후보 → 개발 착수(2단계 시작)
└─ 빠진 값 되묻기 · 지금 상태 설명
| 에이전트가 하는 일 | 예 |
|---|---|
| 맥락을 읽는다 | 맥락은 브라우저가 보낸 상태가 아니라 서버가 run에서 직접 읽는다 — 권고 후보, 남은 요청, 되돌림 기록 |
| 말을 행동으로 바꾼다 | "고령자용 로사르탄 캡슐" → 설계 실행 카드 · "녹는점은 ○○도" → 측정값 제출 카드 · "1위 후보로 개발 착수해 줘" → 개발 착수 카드 |
| 빠진 것을 묻는다 | 설계에는 구조식(SMILES)과 1회 용량이 필요하다 — 용량이 없으면 카드는 점선(미완성)이고 실행 버튼이 잠긴다. 다음 말에서 용량을 주면 앞 대화와 합쳐 완성된다 |
| 먼저 말을 건다 | 설계가 끝나면 "권고 후보는 ○○, 남은 요청 중 가장 가벼운 것은 DSC(10 mg)"처럼 다음 행동을 짚고 개발 착수 카드를 낸다. |
가드레일은 프롬프트가 아니라 코드입니다 (formula/agents/input_agent.py).
| 불변식 | 강제 방법 |
|---|---|
| 제안의 숫자는 사용자가 쓴 글에 있어야 한다 | 카드에 들어갈 모든 숫자를 최근 사용자 발화의 숫자와 대조해, 없으면 빼고 "옮기지 않았습니다"라고 알린다. LLM이 낸 값도 예외 없음 |
| 구조식은 기억으로 만들지 않는다 | SMILES는 사용자 글에 그대로 있거나, 내장 구조 사전 또는 PubChem 조회(CID·링크를 카드에 표시)에서만 온다. 못 찾으면 묻는다 |
| 받을 수 있는 키만 | 측정값 키는 실험 입력 허용목록과 측정 카탈로그의 산출 필드 안에서만 — 그 밖의 키는 빼고 알린다 |
| 지금 설계에만 | 다른 설계가 시작되면 이전 설계에 묶인 카드(측정값 제출·개발 착수)는 잠긴다 |
| 통과한 후보만 개발로 | 룰북을 통과한 후보만 개발 착수 카드가 된다 |
| 실행은 사람이 | 에이전트는 어떤 것도 스스로 실행하지 않는다. 판정은 여전히 룰북과 엔진이 한다 |
측정값 제출은 LLM보다 규칙이 먼저 잡습니다 — 열린 설계가 있고, 글에 측정 이름과 숫자(예: "DSC 측정 결과: Tm 317 도. 실험 용해도는 0.00005 mg/mL.")가 있으며 새 설계를 요청하는 말이 없으면 곧바로 제출 카드가 됩니다. 이 판단을 LLM에 맡기면 새 설계 요청으로 오분류되어 전체가 다시 돌 수 있기 때문입니다. 제출 카드에서 근거 등급을 고르고(기본: 사용자 진술), 새 설계가 시작되면 이전 설계에 묶인 카드는 잠깁니다. LLM이 응답하지 않으면 규칙 기반 해석기가 글에서 값만 읽어 같은 카드를 만들고, 그 사실을 표시합니다. LLM이 되묻기만 했는데 글에서 행동이 분명히 읽히면(예: "Tm 317도") 규칙 해석이 바닥을 받쳐 카드를 냅니다.
근거 결손 게이트 값도 말로 받습니다. 용해도는 pH마다 다르고, 투과도는 흡수율(%)·분율·절대 생체이용률·요중 회수율·Caco-2/PAMPA Papp(cm/s, ×10⁻⁶ cm/s, nm/s)처럼 표현과 단위가 다양해 입력 칸보다 문장이 편합니다. 에이전트는 이런 값을 환산하지 않고 글에 쓰인 그대로의 관측(값 · 단위 · pH · 온도 · 매질 · 방법)으로 뽑고, 나머지는 코드(formula/agents/evidence_values.py)가 ICH M9 기준으로 계산합니다 — 단위를 mg/mL·cm/s로 바꾸고(몰 농도는 구조의 분자량으로), pH 1.2–6.8의 최저 용해도로 용량/용해도 부피를 구합니다. 고용해도는 pH 1.2·4.5·6.8을 모두 쟀을 때만 인정하고, 잰 pH 하나에서라도 250 mL를 넘으면 그것만으로 저용해도를 확정합니다(빠진 pH는 최저값을 더 낮출 수만 있으므로). 범위 밖 pH와 37 °C가 아닌 값은 최저값 계산에서 뺍니다. 절대 생체이용률·요중 회수율은 85 % 이상일 때만 흡수율로 옮기고(더 낮으면 초회통과 대사 때문일 수 있어 저흡수의 근거가 되지 못함), Papp은 흡수율로 환산하지 않고 투과도 근거 자료로만 기록합니다. 값·pH는 글에 있는 숫자여야 하고, 단위는 그 값 바로 뒤에 적힌 단위와 같아야 옮깁니다 — µg/mL를 mg/mL로 읽는 1000배 오류나 지수(×10⁻⁶)를 빠뜨린 Papp은 카드에 들어가지 않고 이유가 표시됩니다. "강제분해 끝냈어" 같은 수행 여부도 열린 항목의 입력 키로 옮깁니다. 카드에는 코드가 계산한 과정(pH별 값 → 최저값 → 부피)과 채워지는 근거 항목이 보이고, [실행]하면 후보 카드의 입력과 같은 재계산(phase_gates부터)으로 갑니다. 실측 BCS가 전략 집합을 바꾸면(예: BCS I → 미분화 불필요) 후보를 다시 설계합니다. 화면은 처음에 가운데 입력칸 하나로 시작하고, 이 입력칸이 곧 입력 에이전트입니다. 폼에 직접 값을 넣는 것은 입력칸 아래 직접 입력이 보조 경로입니다.
제형 판단에 쓰이는 모든 값을 어떻게 얻었는가로 세 계층으로 나눕니다.
| 계층 | 정의 | 예시 | 신뢰 |
|---|---|---|---|
| A. 계산값 | 분자식에서 결정론적으로 나온다 | 분자량 · cLogP · 극성표면적 · 회전가능결합 · 수소결합 주개/받개 · 구조 패턴 | 확정 |
| B. 예측값 | 계산값에 공개된 경험식을 적용해 추정한다 | ESOL(Delaney 2004) · GSE(Jain & Yalkowsky 2001) 용해도 · ⅔ 경험칙 Tg | 잠정 — *_est·*_provisional 변수에만 저장 |
| C. 실측값 | 실험을 해야만 나온다 | XRPD · DSC · TGA · 수분 · pKa · 평형용해도 · 투과도 · 강제분해 | 확정(측정 후) |
A는 항상 자동으로 계산합니다. 사용자에게 묻지 않습니다. C는 판정을 가르는 지점에서만 요청합니다 — 이 요청이 lab-in-the-loop의 실체입니다.
예측값은 실측값을 덮지 않고, 실측값은 예측값을 지우지 않습니다. 예측 용해도(solubility_est_mg_per_ml)와 실측 용해도(solubility_mg_per_ml)는 서로 다른 변수라, 실측이 들어와도 예측값은 보정 정보로 남습니다. 반대로 BCS 등급은 실측값으로만 확정합니다. 예측으로는 "잠정 저용해도"까지만 말하고, 그것은 전략 탐색 범위를 넓히는 데만 씁니다.
무거운 예측 모델로 빈칸을 메우지 않습니다. 예측 계층은 RDKit 계산값과 공개된 경험식만으로 성립합니다. 경험식이 계산되지 않거나(녹는점을 몰라 GSE를 못 쓸 때) 두 예측이 1 log 이상 어긋나면 "여기서부터는 모른다"고 말하고 측정을 요청합니다. 신경망 예측기(ADMET-AI · SolTranNet · QupKake)는 붙일 자리만 있고 연결돼 있지 않으며, 연결되지 않은 모델은 "미연결"로 표시됩니다.
파생값도 코드가 아니라 데이터입니다. D0(용량/용해도 비) · 흡수 한계 · Tg 여유 · ΔpKa · 보수적 예측 용해도 같은 파생값은 전부 derived_quantities.csv(23행)에 식으로 적혀 있고, 서로 의존하는 값은 더 바뀌지 않을 때까지 반복 계산합니다. 계산 순서를 코드 줄 순서에 맡기면 재료가 준비되기 전에 값을 계산해 늘 빈칸이 되는데 — 그러면 실측이 없는 상태에서 전략이 하나도 생성되지 않습니다. 표의 한 행으로 두면 이 순서 문제가 사라집니다.
검사를 시작하려면 "이 약이 어떤 작용기를 가졌는가"를 먼저 알아야 합니다. 유당이 위험한지 아닌지는 약에 아민기가 있느냐에 달려 있기 때문입니다. 이걸 사람이 손으로 적으면 틀리기 쉽습니다 — 아세트아미노펜은 이름 때문에 아민처럼 보이지만 실제로는 아미드라서 유당과 반응할 아민이 없습니다. 그래서 구조는 반드시 계산합니다.
분자식 (SMILES)
│
├─ 1. 구조 품질 검사 파싱·염·전하·입체중심이 온전한가
├─ 2. 분자 특성값 계산 35종 (분자량 · 극성표면적 · 수소결합 밀도 …)
├─ 3. 구조 패턴 검출 82종 (아민 · 가수분해 · 산화 · 광분해 …)
├─ 4. 물성 예측 경험식 용해도(ESOL·GSE) 교차검증 → 잠정 분류까지만
└─ 5. 문헌 조사 PubChem 식별정보 + 제형·안정성 논문
핵심은 개수가 아니라 판정을 세 등급으로 나눈 것입니다.
| 등급 | 뜻 | 개수 | 허용되는 해석 |
|---|---|---|---|
| 구조 사실 | 이 작용기가 있다 | 18 | 존재 확인까지만 |
| 조건부 경고 | 조건이 맞으면 위험해질 수 있다 | 52 | 조건과 시험을 찾아본다 |
| 높은 경고 | 구조만으로도 주의가 큰 부위 | 12 | 그래도 단독으로 공정을 배제하지 않는다 |
"조건"이 무엇인지도 함께 저장합니다. 예를 들어 에스터가 검출되면 "가수분해 가능"이라고만 하지 않고, 그것이 위험이 되려면 무엇이 필요한지(수분·pH·온도·시간)와 무엇으로 확인할 수 있는지(pH·온도별 수계 스트레스 시험)를 같이 답니다. 구조 하나로 결론을 내지 않겠다는 원칙이 데이터 구조에 박혀 있습니다.
분야별로는 질소·아민 18종, 니트로사민 7종, 산과 염기 8종, 가수분해 14종, 산화 10종, 반응성 8종, 금속 결합 6종, 광분해 10종, 고체 특성 1종입니다.
아민은 1차 지방족·2차 지방족·3차 지방족·방향족으로 나눠 검출하지만, 배합 금기 규칙표는 primary_amine·secondary_amine이라는 이름으로 연결돼 있습니다. 그래서 패턴 목록에 "이 패턴은 규칙표의 어느 이름과 연결되는가"를 적는 칸을 두었습니다. 화면에는 세분화된 이름이 나오고, 규칙표와는 그 연결 이름으로 이어집니다. 테스트가 이 연결을 고정합니다.
같은 패턴이라도 고리 크기에 따라 위험이 다릅니다. 4각 고리 β-lactam은 구조적 긴장 때문에 훨씬 불안정한데, 5각 γ-lactam은 평범한 고리 아미드입니다. 패턴만으로는 둘이 구분되지 않아서 고리 정보를 후처리로 봅니다.
2-azetidinone (4각) → β-lactam · 높은 경고
2-pyrrolidone (5각) → γ-lactam · 구조 사실
아목시실린 → β-lactam 검출 → 안정성 시험이 자동으로 필수 등급이 됨
판정을 믿으려면 "그 패턴이 정말 이 분자에 있는가"를 사람이 확인할 수 있어야 합니다.
용해도 예측은 특히 불확실합니다. 그래서 단일 모델의 점 추정값을 믿는 대신 두 모델의 예측이 얼마나 벌어지는지를 봅니다.
두 모델의 용해도 예측 차이 ≥ 1 log → 예측을 신뢰하지 않음
→ 실험 용해도 측정을 "필수" 시험으로 올림
예측 모델이 연결되지 않은 경우에는 숫자를 지어내지 않습니다. "미연결"이라고 표시하고, 그것도 자료 요청으로 이어집니다. 자료가 없다는 것은 안전하다는 뜻이 아니기 때문입니다. 예측은 "잠정" 표시와 함께 전략 탐색 범위를 정하는 데만 쓰고, BCS 등급은 실측 용해도·흡수율이 들어왔을 때만 확정합니다.
구조를 계산해 놓고 그 결과를 시험 선택에 쓰지 않으면, 에스터를 가진 약과 안 가진 약이 같은 시험을 받게 됩니다. 그래서 구조 경고가 확인시험 등급을 자동으로 올립니다.
| 검출된 구조 | 올라가는 시험 | 권장 → 필수 |
|---|---|---|
| 가수분해 가능 부위 | 소규모 stress stability | ✓ |
| 수분 반응성 부위 | 축약 수분 민감성 시험 | ✓ |
| 광분해 우선순위 신호 | 광안정성 (ICH Q1B) | ✓ |
| 아민 | 부형제 배합적합성 시험 | ✓ |
| 니트로사민 전구체 | NDSRI 위험평가 | 신규 추가 |
| 고반응성 부위 | ICH M7 변이원성 평가 | 신규 추가 |
무엇이 왜 올라갔는지도 함께 표시합니다. 투여경로가 고형 경구가 아니면 고체 특성화 시험(XRPD 등)의 비중을 낮춥니다.
비워 두면 시스템은 그 값을 모른다고 보고, 전략이 실제로 갈리는 지점에서만 데이터 요청을 냅니다. 이미 측정한 값이 있다면 첫 화면의 실험 데이터 입력에 넣으면 그만큼 요청이 줄고, 판정이 실측 기반으로 바뀝니다.
| 넣는 값 | 무엇이 달라지나 |
|---|---|
| 1회 투여량 | 용량–용해도 비(D0 등)가 계산되어 DCS 분류가 가능해집니다 |
| 안식각 · 압축성 지수 · Hausner 비 | 유동성 등급이 실측으로 산출되어 공정 경로 결정이 바뀝니다 |
| 용량/용해도 부피 · 흡수율 | BCS 등급이 실측 기반으로 확정됩니다(예측 등급은 확정으로 쓰지 않습니다) |
| 흡습성 · 광분해 · 열/수분 민감 | 포장 규칙과 경로 규칙(RTE004·RTE005)이 발동합니다 |
두 가지 원칙이 여기에 걸려 있습니다. 실측값은 추정보다 우선하므로 RDKit 계산값이 사용자 입력을 덮어쓰지 않고, 목록에 없는 이름은 받지 않습니다 — 이 값들은 규칙 조건식이 평가되는 문맥에 그대로 합쳐지기 때문에, 임의 키를 허용하면 판정 문맥 자체를 바꿀 수 있습니다.
염 형태 SMILES(예: 베실산 암로디핀)가 들어오면 가장 큰 유기 조각을 parent로 확정하고, 분자 특성값·구조 패턴·용해도 예측을 모두 parent로만 계산합니다 — 염 전체로 계산하면 짝이온의 질량·극성이 섞여 Ro5·Veber 경고가 잘못 켜집니다(베실산 암로디핀: 염 MW 567.1 → parent 408.9, TPSA 154.3 → 99.9). 염 정보(짝이온, 염/유리염기 분자량비)는 따로 보존해 함량 환산에 씁니다. 약물 이름은 구조로 찾은 PubChem 표제명과 철자만 다를 때 표제명으로 고쳐, 해석 단계의 철자 오류가 개발 스터디 이름에 남지 않게 합니다. 개발코드(예: VX-770)처럼 표제명과 다른 이름은 그대로 둡니다 — 요청자가 공개하지 않은 물질명을 시스템이 드러내지 않으며, 심사관에게도 요청한 이름만 쓰도록 지시합니다. 입력 에이전트도 같습니다 — 사용자 글에 개발코드가 있으면 모델이 기억으로 일반명을 채워도 코드로 되돌리고(구조는 PubChem이 그 코드로 찾은 것), 응답·제안 카드·실행 뒤 대화의 실명(PubChem 표제명과 같은 구조의 라벨 일반명·제품명)을 코드로 가립니다.
설계를 시작하기 전에 이 약물에 대해 이미 알려진 것을 모읍니다. PubChem에서 식별정보와 보고된 물성을, Europe PMC에서 제형·안정성 논문을 가져옵니다. 둘 다 공개 데이터베이스이고 인증 키가 필요 없습니다. 결과가 없으면 없다고 표시하고 넘어갑니다.
처방을 만들기 전에 이 약이 어떤 부류인지부터 정합니다. 이 판정이 어떤 전략을 후보로 올릴지를 정하기 때문입니다.
RDKit 계산값 + 사용자 실측값 → 파생값 계산 (derived_quantities.csv, 서로 의존하는 값은 수렴할 때까지 반복)
→ Gate 3A BCS/DCS 용해도·투과도 분류
→ Gate 3B 고체상 — 결정형/무정형 (advisory)
→ Gate 4 가용화 전략이 필요한가
→ Gate 4B 필요하면 어떤 ASD 공정인가
→ 켜진 신호로 전략 채점 (strategy_families.csv) → 경쟁 전략 목록 (예: 미분화 MICRO · 분무건조 ASD_SDD)
순서가 곧 의존 관계입니다 — Gate 4는 3A의 DCS 하위분류를, 4B는 4의 가용화 필요 신호를 읽습니다.
이 판정은 계산값 → 예측식(ESOL·GSE 등) → 실측값 3단계 중 있는 것까지만 씁니다. 실측이 없으면 "잠정(provisional)"이라고 표시한 채 그대로 진행하고, 게이트에는 반려 권한이 없습니다 — 전략 후보의 범위만 좁히거나 넓힙니다.
켜진 신호로 전략을 채점해(strategy_families.csv, 8개 전략) 상위 3개를 고릅니다. 고른 전략 코드를 정렬해 이은 것이 계획 서명(plan_signature)이고, 측정값이 들어왔을 때 다시 설계할지 신뢰도만 다시 매길지를 이 서명으로 정합니다. 되돌림이 쌓은 제약(전략·경로 제외, 가족 요구·감점)을 반영하고 나서 남는 전략이 없으면 설계하지 않고 목표(QTPP) 재검토로 끝납니다 — 용량·대상·제형이나 고정한 제약을 바꿔야 한다는 결론입니다.
투과도를 모르면 "녹는 속도가 문제인 약(IIa)"인지 "녹는 양이 문제인 약(IIb)"인지 가를 수 없습니다. 두 경우의 해법은 정반대입니다 — 전자는 입자를 잘게 부수면 되고, 후자는 녹는 양 자체를 올리는 비싼 공정이 필요합니다. 이때 시스템은 한쪽으로 단정하지 않고 두 방향을 모두 후보로 열어 둡니다. 모르는 값을 기본값으로 채워 한쪽을 수학적으로 닫아 버리는 것도 사고입니다 — 투과도 인자를 1로 채우면 IIa가 계산상 불가능해지므로, 모르면 계산하지 않습니다. 가루 흐름 자료가 없어 공정 경로를 정하지 못할 때도 같습니다 — 직접타정·건식과립·습식과립을 모두 열어 두고 "잠정 경로"로 표시합니다.
measurement_catalog.csv(20종)가 시스템이 "어떤 실험이 존재하는지" 아는 유일한 근거입니다. 목록에 없는 시험은 요청하지 않습니다. 각 행은 시험 방법 · 필요 시료량 · 산출 변수 · 그 값이 무엇을 풀어 주는지 · 출처를 담고 있습니다.
| 단계 | 시료 | 시험 |
|---|---|---|
| Tier 1 | ~10 mg | XRPD · DSC · TGA · Karl Fischer 수분 |
| Tier 2 | ~30 mg | DVS 흡습성 · pKa 적정 · logP/logD · 평형용해도(FaSSIF 포함) · 투과도(Caco-2/PAMPA) · 고유용출속도 |
| Tier 3 | 20–300 mg | 강제분해 · 다형 스크리닝 · 유리형성능 · 입도분포 · 분체 유동성 · 압축성 |
| 전략별 | 100–300 mg | 염/공결정 스크리닝 · ASD 실현성 · SEDDS 실현성 · 사이클로덱스트린 포접 실현성 |
| 시점 | 뜻 | 예 |
|---|---|---|
| 전략을 좁히는 요청 (계획 전, 한 번) | 결과에 따라 어느 전략을 고를지가 바뀐다 | 녹는점을 모르면 용융압출과 분무건조를 가를 수 없다 |
| 신뢰도를 높이는 요청 (후보마다) | 이미 고른 전략의 신뢰도만 바뀐다 | ASD 후보가 생긴 뒤의 고분자 혼화성 확인 |
"언제, 무엇을, 왜"는 data_request_triggers.csv(16행)에 한 줄씩 적혀 있습니다. 한 행이 담는 것은 발동 조건 · 요청할 시험 · 해결 조건 · 요청 사유 · 거절했을 때의 대체 경로입니다.
예측이 낮거나 모름 / 예측 간 불일치)로 뜹니다.provisional 태그를 유지하며, 화면에는 그 요청의 "건너뛰면" 대체 경로가 표시됩니다.산·염기 site가 있는 약물(구조 플래그로 계산)은 위장관 pH 1.2–6.8에서 용해도가 크게 달라집니다. 단일 ESOL 예측은 이 pH 의존성을 반영하지 못하므로, 이런 약은(페놀·이미드처럼 위장관 pH 범위에서 거의 이온화하지 않는 약산성 site만 있는 경우는 제외) BCS 잠정 용해도를 **"미정"**으로 두고 pH 1.2·4.5·6.8 평형용해도를 요청합니다(사유 꼬리표: pH 의존(이온화)). 공식 문헌 값이 있는 약물은 literature_bcs.csv의 한 행(등급: 문헌 표 수치, 구조로 대조)으로 잠정 판정을 채웁니다. 어느 경우든 BCS 등급 자체는 실측으로만 확정합니다.
남은 신뢰도 요청이 없다 ⟺ grounded
남은 신뢰도 요청이 있다 ⟺ provisional
계산값이지 판단이 아닙니다. AI가 "이 후보는 믿을 만하다"고 말할 여지를 구조적으로 없앴습니다.
측정값을 제출하면(데이터 요청 패널 또는 입력 에이전트) 근거 등급(자체 실측 · 문헌 · 사용자 진술)과 함께 기록하고, intake·분자 계산은 다시 돌리지 않은 채 그 값에 의존하는 판정(페이즈 게이트 이후)만 다시 계산합니다(LLM 0회). 해설에는 제출값·근거 등급·닫힌 요청·다시 판정한 게이트가 뜹니다. 그다음 새 계획을 세워 이전 계획과 서명을 비교합니다.
| 서명 | 동작 |
|---|---|
| 같다 (전략 집합 불변) | 기존 후보의 신뢰도 태그와 남은 요청만 갱신한다. LLM 호출 없음 |
| 다르다 (전략 집합이 바뀜) | 새 전략 집합으로 후보를 다시 설계하고 합의를 다시 낸다 |
측정 결과가 전략의 전제를 부정하면 되돌림 규칙이 그 측정을 요구하는 전략만 빼고 전략 선택으로 돌아갑니다 — 예를 들어 ASD 혼화성이 부적합이면 ASD 후보만 빠지고 미분화 후보는 그대로입니다(어느 전략이 어느 측정을 요구하는지는 strategy_families.csv의 required_measurements가 정합니다). 유리형성능이 나쁘게 나오면(급속 재결정, Class I) 해당 ASD 후보를 빼는 동시에 ASD 계열 점수를 감점만 합니다 — 순수 약물 기준 분류라서, Tg가 높은 고분자와 섞으면 안정해지는 사례가 문헌에 있기 때문입니다. 제약을 모두 반영하고 남는 전략이 없으면 목표 재검토로 알립니다.
측정 결과가 전부 숫자는 아닙니다. "비정질 halo가 보이는가"는 예/아니오, "유동 특성"은 USP 등급 중 하나, "XRPD 피크 목록"은 목록입니다. 필드마다 타입·단위·선택지·설명을 measurement_output_fields.csv 한 곳에 두고, 데이터 요청 카드는 그 정의대로 입력 칸을 그립니다(숫자 칸 · 예/아니오/모름 선택 · 선택지 목록 · 목록 입력). 서버도 같은 정의로 값을 검사해 타입이 맞지 않으면 422로 이유와 함께 돌려보냅니다 — 예/아니오 칸에 1을 보내거나, 선택지에 없는 등급을 보내면 받지 않습니다. 트리거가 묻는 결과 키는 그 측정에 정의된 필드여야 하고(테스트로 고정), 정의되지 않은 키는 카드에서 빠지며 경고로 남습니다.
측정마다 원자료를 첨부할 수 있습니다(그림·PDF·CSV·기기 원자료 .xy·엑셀, 20 MB까지). 첨부는 내용 해시로 저장되어 제출 기록에 붙고 해설에 링크로 남습니다 — 판정에는 쓰지 않고 추적에만 씁니다. 첨부에 에이전트 해석을 요청하면 입력 칸을 채울 초안을 받습니다.
| 첨부 | 해석 방법 | 채우는 필드 |
|---|---|---|
기기 원자료(.xy·.csv·.txt 두 열) | 결정론 계산 — 같은 파일이면 같은 초안 | XRPD: 비정질 halo 여부(반치폭 기준) · DSC: 흡열 onset(접선 외삽)·다중 흡열 · TGA: 100–150 °C 무게 감소·5% 감소 온도 |
그림(.png·.jpg) | 대회 API 모델의 이미지 입력 — 그 측정에 정의된 필드만, 타입이 맞는 값만 | 그림에서 직접 읽히는 값과 읽은 위치 |
초안은 **"미확인"**으로 뜨고, 연구자가 확인해 "입력 칸에 넣기"를 눌러야 칸이 채워지며, 제출은 여전히 연구자가 합니다. 제출 기록에는 초안의 출처(instrument_draft·vision_draft)가 남습니다. 계산에 조건이 더 필요한 값(DSC 융해열 — 승온속도·시료량, 결정형 ID — 기준 패턴)은 만들지 않고 이유를 적어 비워 둡니다. 무료 모델은 이미지를 받지 않으므로 그림 해석은 대회 API에서만 합니다.
규칙표를 아무 순서로나 돌릴 수 없습니다. "직접 찍어 누르기 규칙"은 그 공정이 선택된 뒤에야 의미가 있고, 그 선택은 가루가 잘 흐르는지 등급이 나온 뒤에야 가능합니다. 그래서 규칙표마다 순서가 붙어 있고, 앞 단계가 만든 값이 뒷 단계의 발동 조건으로 흘러갑니다.
0 입력 계약 검사 API 1행 · 요청 용량(유리염기) · 고정 부형제 · 라벨 1일 최대 용량
0 참조 자료 첨가제 목록 · 특성값 정의 · 구조 패턴 정의
5 주성분 특성 경고 경고 구간 판단
10 가루 흐름 등급 안식각 48도 ──→ 흐름 "나쁨"
11 공정 경로 결정 └─→ 직접 찍어 누르기 배제
20 배합 금기 (1대1) ← 성분 자체를 바꿔야 하는 반려라 앞에 온다
21 어린이 안전 상한
22 색소 · 향료
30 여러 성분 상호작용
40 선택된 공정의 세부 규칙 ← 위에서 정한 공정을 참조
45 첨가제 배합비
50 코팅 · 잔류용매
60 녹는 정도 분류 → 전략
70 포장 · 안정성 · 분석법
배합금기 규칙은 "이 조성이 위험한가"를 봅니다. 그 앞에 더 기본적인 질문이 있습니다 — 이 후보가 요청한 그 약, 그 용량, 그 고정 부형제인가. 설계 AI는 요청 용량을 무시하거나(8 mg 요청에 10 mg), 주성분을 빠뜨리거나, 고정한 부형제를 뺄 수 있고, 배합금기 규칙은 그걸 모릅니다. 그래서 모든 규칙보다 먼저 결정론으로 대조합니다(request_contract_rules.csv · max_daily_dose.csv).
| 검사 | 기준 | 어기면 |
|---|---|---|
| API 존재 | API 행이 정확히 1개(role=api) | 반려 |
| 요청 용량 일치 | API 함량을 유리염기로 환산해 요청 1회 용량과 ±0.5% 이내 — 이름에 염 표기(besylate·HCl 등)가 있으면 염 기준으로 읽고 RDKit 분자량비로 환산 | 반려(용량이 입력되지 않았으면 "미검사"로 표시) |
| 고정 부형제 | 사용자가 고정한 부형제가 모두 들어 있다(부형제 사전으로 대조) | 반려 |
| LLM 추가 성분 | 고정 목록 밖 성분은 "LLM 추가 성분"으로 표시 | 표시만 |
| 1일 최대 용량 | 후보의 1회 함량(유리염기)이 허가 라벨의 1일 최대 용량을 넘지 않는다 — 약물은 이름이 아니라 구조(InChIKey)로 대조. 값은 FDA 라벨(DailyMed) 원문 문장과 함께 저장 | 반려(요청 용량 자체가 라벨 최대를 넘으면 재설계 없이 "제약 불가능") · 라벨이 없는 신규물질은 표시만 |
설계 에이전트는 요청 용량을 하드 제약으로 받고, 어기면 되돌림 표(BT030·BT031)에 따라 같은 전략으로 함량을 고쳐 다시 설계합니다.
폴더 번호만 보면 규제가 마지막 같지만, 실제로는 어린이 안전이 21번으로 앞에서 돕니다. 값 몇 개를 조정해서 해결되는 문제가 아니라 성분 자체를 바꿔야 하는 반려라, 무거운 공정 계산을 하기 전에 먼저 걸러내는 편이 낫기 때문입니다.
배합비 규칙은 부형제를 기능 역할(결합제 2–10%, 활택보조제 0.25–2% 등)로 묶어 판정하는데, 설계 AI가 붙인 역할만 보면 틀리는 부형제가 있습니다. 미결정셀룰로오스(MCC)는 결합제·희석제를 겸해 20–90%로 쓰고, 탈크의 활택 사용 범위는 1–10%로 콜로이드성 이산화규소와 다릅니다. 그래서 출처가 있는 역할 매핑표(excipient_role_map.csv, Handbook of Pharmaceutical Excipients)로 판정용 역할을 바꾸고 전용 범위(FR010·FR011)로 판정하며, 무엇을 바꿨는지 판정문에 남깁니다. 출처 없는 매핑 행은 판정에 쓰지 않습니다.
마그네슘 스테아레이트 과혼합(INC014)은 혼합 시간·전단력에 달린 공정 의존 위험이라, 윤활 혼합 시간이 정해지지 않은 후보 탐색 단계에서는 경고로 켜지 않고 **"DoE 요인 후보(윤활 혼합 시간)"**로 넘깁니다. 2단계의 제형·공정 위험평가와 DoE에서 다룰 대상이라는 뜻입니다. 같은 방식으로 저함량 약물(약물 함량 5% 미만, RTE008)은 함량균일성 검토 신호로 표시됩니다.
다성분 규칙(예: 유당 + 스테아르산 마그네슘 + 물 → 글리코실 부가체, Abdoh 2004)은 성분군 이름(alkaline_lubricant)과 조건(moisture present)으로 적혀 있습니다. 이를 처방 어휘로 옮기는 번역표(config/component_classes.yaml — 부형제 마스터의 열, API 작용기, 수계 공정, ICH Q1A 가속 조건)로 대조하므로, 같은 세 성분이라도 수계 습식과립이면 반려, 직접타정이면 발동하지 않습니다.
반려되면 무조건 처음부터 다시 설계하지 않습니다. 어느 단계로 돌아갈지는 코드가 아니라 backtrack_transitions.csv(16행)의 한 행이 정합니다 — 반려 판정(또는 측정 결과)이 행의 조건식에 맞으면 그 행의 복귀 지점으로 돌아가고, 행이 적은 제약(성분 제외 · 전략 제외 · 경로 제외 · 가족 요구 · 가족 감점)을 쌓습니다.
| 반려 사유 | 복귀 지점 | 쌓이는 제약 |
|---|---|---|
| 1대1 배합 금기 · 어린이 안전 상한 | 성분만 교체 (같은 전략) | 문제 성분 제외 |
| 여러 성분 상호작용 | 성분만 교체 | 금지 조합 제외 |
| 공정 규칙 미충족 (직접타정 · 과립 · 캡슐) | 공정 경로부터 | 그 전략 제외 |
| 공정 경로 배제 | 공정 경로부터 | 그 경로 제외 |
| 실측 BCS II/IV인데 가용화 요소 없음 | 전략 선택부터 | 가용화 가족 요구 |
| 입력 계약 위반 (API·용량·고정 부형제) · 1일 최대 용량 초과 | 같은 전략으로 성분·함량만 수정 | — |
한 라운드에 반려가 여럿이면 가장 깊은 복귀 지점으로 가되 제약은 모두 쌓습니다. 같은 지점으로 3번 돌아가도 풀리지 않으면 한 단계 위로 올리고(반려된 전략은 제외), 전체 되돌림이 5회를 넘으면 사람에게 넘깁니다. 반려 사유가 사용자가 반드시 넣으라고 한 성분이면 되돌리지 않고 곧바로 "이 제약으로는 통과가 없다"는 판정과 규칙표의 대체 성분을 냅니다. 되돌림 제약이 모든 전략을 지우면 목표 재검토로 끝납니다.
후보 처방은 "이렇게 만들면 될 것 같다"까지입니다. 실제 개발은 목표 제품 프로파일(QTPP)을 정하고, 품질특성마다 CQA인지 근거와 함께 가리고, 원료 물성과 제형·공정 변수가 각 CQA에 얼마나 위험한지 기전으로 평가한 뒤, 위험이 높은 변수로 실험계획을 세워 그 영향을 회귀식으로 보이고, 미래 배치가 규격을 동시에 통과할 확률로 운전 영역을 정해 확인해야 합니다(ICH Q8·Q9, Peterson 2008). 2단계는 이 과정을 15단계로 옮긴 것이고, 순서와 표 형식은 Monton 등(2026, CBD 구강붕해정)을 따릅니다. 설계서: docs/stage2/DESIGN.md.
| # | 단계 | 누가 만드나 | 연구자가 하는 일 |
|---|---|---|---|
| 1 | 프로토타입 (Table 1 형식) | 1단계 후보의 조성 + 불변 Handoff(요청 · 대상 · 용량 · 약물 함량 · 1단계 신호 · fingerprint) | 성분·mg·%·기능 확인·수정 → 실행 |
| 2 | QTPP (Table 3) | LLM 초안 | 행 추가·삭제·수정 → 승인 |
| 3 | CQA 판별 (Table 4) | LLM 초안 — CQA 여부의 논리적 근거 | 위험평가에 넣을 CQA 확정 → 승인 |
| 4 | 원료 물성 위험평가 근거 (Table 6) | LLM 초안 — 변수 × CQA 등급 격자 → 같은 등급 묶음마다 기전 문장 | 등급·문장·근거 유형 수정 → 승인 |
| 5 | 원료 위험평가 정리 (Table 5) | 코드 — 4의 근거에서 칸마다 등급 | 확인 |
| 6 | 제형·공정 변수 위험평가 근거 (Table 8) | LLM 초안 — 처방의 모든 부형제 + 조절 가능한 공정 파라미터(저함량이면 혼합 공정 × 함량균일성 확인) | 수정 → 승인 |
| 7 | 제형·공정 위험평가 정리 (Table 7) | 코드 | 확인 |
| 8 | 종합 정리 | 코드 — 두 행렬 병합 + DoE 변수 후보(High인 제형·공정 변수, High 개수 순) · 관리 대상(Medium) · 원료 관리 항목. 고르는 칸 없음 | 확인. 위험평가 보고서 PDF는 8단계에 들어오자마자 후보 목록 바로 아래에 |
| 9 | 실험 설계 입력 (Table 9) | 초안 = 이름 없는 요인 열 1개 · 반응 열 1개(둘 다 연구자가 적음 — High 변수 · 위험평가 CQA는 이름칸의 제안 목록) | Std·Run·요인 1–3·반응 1–4 열 추가/삭제·이름·단위, 행 추가, CSV 불러오기(열 역할 지정) · 엑셀 붙여넣기, 시연용 논문 값 채우기(Monton 2026 Table 9 · Almotairi 2022 Table 3 실측, 같은 약물 표가 앞) → 승인 |
| 10 | 회귀식 · 검증 게이트 (Table 10) | 코드 — 후보(평균·선형·2FI·순수 2차·2차·축소 2차)를 AICc로 줄 세워 검증 게이트 4조건(모형 p < 0.05 · 적합결여 p ≥ 0.05 · 조정 − 예측 R² ≤ 0.2 · 예측 R² > 0)을 처음 넘는 모형. 평균까지 내려가면 "요인으로 설명되지 않음" | 모형 선택 → coded·actual 식 → 승인. 모든 반응이 게이트를 못 넘으면 승인 불가 |
| 11 | 반응 곡면 (Figure 1) | 코드 — 선택 모형의 곡면, 실험점·잔차·설계 지지 영역. 게이트 통과 반응이 하나라도 있으면 모든 반응을 그리고 불합격은 "참고"로 표시 | 확인(그림이 보고서에 들어감) |
| 12 | ANOVA (Table 11) | 코드 — 부분 제곱합, 순수오차·적합결여 | 확인 → 최종 보고서 PDF |
| 13 | Design Space (Overlay plot) | 코드 — 게이트 통과 반응의 평균 예측이 모든 목표 만족(노랑) · 실험 범위 밖 해칭 · control space(3×3 이상 직사각형) · 최적 처방 · 보조 확률 등고선 | 목표 입력(근거) · 단면 고정 요인 → 영역 승인. |
발표 자료 10쪽의 흐름입니다. Almotairi 등(2022, Pharmaceuticals 15:1463)의 Box–Behnken 실측 15 run(Table 3 — 9단계 표 위 논문 실측값으로 채우기 또는 CSV)을 넣으면, 10단계 선택기가 후보 모형을 AICc로 줄 세워 검증 게이트(모형 p < 0.05 · 적합결여 p ≥ 0.05 · 조정 R² − 예측 R² ≤ 0.2 · 예측 R² > 0)를 처음 넘는 모형을 고릅니다 — 네 반응 모두 축소 2차로 통과합니다(전체 2차는 AV에서 조정 − 예측 R² 0.40으로 과적합 불합격). 목표(분산 ≤ 180 s · 마손도 ≤ 1 % · DE30 ≥ 75 %(프로젝트 목표 — 가정) · AV ≤ 15)를 넣으면 13단계 Overlay plot(논문 Figure 2 형식):
| 값 | |
|---|---|
| 단면 고정 요인 | 혼합 시간(효과가 가장 작은 요인) — 5 · 10 · 15분 세 단면 |
| 평균 기준 영역(노랑, 실험 범위 안) | 87.4 % · 71.6 % · 87.4 % |
| control space | 혼합 10분 단면 — MCC:만니톨 1.1–3.0 × 크로스포비돈 4.6–9.2 % |
| 최적 처방 | MCC:만니톨 2.9 · 혼합 10분 · 크로스포비돈 7.0 % (새 배치 통과확률 0.998) — 논문 최적 3:1 · 11분 · 6.23 %는 참고점 |
| 최적점 DE30 동시 예측구간 | 82.3 (75.3–89.4), 12개 비교 Bonferroni |
CBD 논문 규격(경도 4–6 kgf · 붕해 ≤ 30 s · 마손도 ≤ 1 %)에서는 경도만 게이트를 통과하고(붕해시간·마손도는 요인으로 설명되지 않음 — 관측 범위와 목표만 표시), CCS 3 % 단면에 control space Force 1250–1425 psi × MCC 30–44.5 %, 최적 1312.5 psi · 35.5 % · 3 %로 승인됩니다. 새 배치 통과확률은 최대 0.883(< 0.9)이라 경고만 뜹니다 — 13단계 승인 불가는 평균 기준 영역 없음과 control space를 만들 수 없음 두 경우뿐입니다. 모형 선택·게이트·영역·control space·최적점은 overlay 파이프라인의 참조 구현과 소수점까지 같은 값이 나오며 테스트로 고정되어 있습니다.
CBD 논문 프로토타입으로 2~7단계를 대회 API 초안만으로(고치지 않고) 진행해 보면, 결정론 검사는 한 번도 막지 않았습니다 — 형식은 완전했습니다. 하지만 논문과 같은 이름의 칸끼리 위험 등급이 같은 칸은 원료 21/35, 제형·공정 21/35였고, 다른 칸 28개 중 22개는 LLM이 더 높게(주로 논문의 Low를 Medium으로) 매겼습니다(보고서 7.6절, docs/report/stage2_llm.json). 여기서 논문은 정답지가 아니라 참고 자료입니다 — 위험 등급은 한 연구팀이 자기 설비·경험으로 내린 판단이라, 일치율을 품질 점수로 쓰지 않습니다. 차이가 난다는 사실이 2단계가 "자동 설계"가 아니라 "단계마다 승인하는 초안"인 이유입니다. 반대로 회귀·ANOVA처럼 계산으로 정해지는 값은 같은 원자료면 같아야 하므로 재현을 테스트로 고정합니다. 논문으로 시작한 시연에서는 단계마다 논문 값으로 채우기와 참고 · 논문의 판단(다른 칸 테두리)이 열립니다.
2단계는 1단계와 같은 대화에 이어집니다. 단계마다 카드가 한 장씩 아래로 쌓이고, 승인한 단계는 요약 한 줄로 접혀 남으며(펼쳐 보기 · 다시 열기) 지금 단계만 펼쳐진 편집 카드입니다. 진행 중인 study는 위쪽 2단계 기록에서 다시 열 수 있습니다.
발표 자료의 세 시나리오와 2단계 논문 재현입니다. 요청 문장·값은 약학 담당의 시연 쿼리 카드 그대로이고, 각 카드가 실제로 어떤 경로를 밟는지 tests/browser/scenarios.mjs·pipeline.mjs와 scripts/report/demo_cards.py(대회 API)가 확인합니다. 실행되는 동안 진행 과정 칼럼(넓은 화면에선 오른쪽, 휴대폰에선 위쪽 버튼)에 "지금 어느 계층이 무엇을 왜 하는지" 해설이 흐릅니다. 시간은 대회 API 기준(무료 모델은 분당 토큰 한도로 약 2–3배).
① 로르녹시캄 분산정 — 요청부터 Design Space까지 (약 3분 + 2단계). "성인용 로르녹시캄 8 mg 분산정 … 직접타정 … MCC, 만니톨, 크로스포비돈은 반드시"에 유동성 실측(안식각 42° · Carr 22 % · Hausner 1.28)을 넣어 실행합니다. USP <1174> 흐름성 'passable'로 직접타정 유지(48°면 배제). 근거 결손 게이트가 통과 후보들의 선행 근거(예: BCS 근거)를 따지고, 결손을 기록하고 개발 착수(사유 입력) 또는 근거 결손 게이트 카드(또는 대화)에 측정값 입력 → 2단계에서 저함량(약 3–4 %) 때문에 혼합 시간 × 함량균일성 위험이 High로 잡히고, 9단계에서 Almotairi Table 3을 채우면 10단계 검증 게이트(네 반응 축소 2차 통과) → 13단계 Overlay plot(control space · 최적 2.9 · 10분 · 7 %) → 14단계 확인계획 잠금까지 갑니다(위 11장).
② 고령자용 암로디핀 2.5 mg — 유당을 고정하면? (약 30초). 베실산염 SMILES에서 짝이온을 떼고 parent의 1차 아민을 찾아 1차 아민 × 유당(INC001)과 유당 + Mg stearate + 수분 다성분 금기(MC001·MC002)가 발동합니다. 반려 사유가 사용자가 고정한 유당이라 재설계 루프를 돌지 않고(0회) **"이 제약으로는 통과 처방 없음"**과 대체 부형제를 후보 카드 맨 위에 결론으로 냅니다. 심사 전에 끝나지만 대상이 고령자라 **소집 예정이던 심사관(고령자 안전 · 공정 실현성)**도 함께 적습니다 — 소아 요청이면 소아 안전 심사관으로 바뀝니다(같은 구조, 다른 팀). 다성분 금기는 수계 공정(습식과립)이 있을 때 발동하므로 LLM이 고른 공정에 따라 INC001만 걸리는 실행도 있습니다. 용량은 유리염기 2.5 mg(베실산염 칭량 ≈ 3.47 mg)으로 처리합니다.
③ 개발코드 VX-770 — 구조식만 있는 신규물질 (약 1분). 값이 거의 없어도 후보부터 내고(BCS 미확정), Tm을 모르면 용융압출과 분무건조를 가를 수 없어 DSC만 요청합니다. 끝나면 시연 카드의 측정 문장("DSC 측정 결과: Tm 317 도. 실험 용해도는 0.00005 mg/mL.")이 입력칸에 들어가 있고, 보내면 측정값 제출 카드 → 재계산으로 분무건조 ASD가 계획에 들어옵니다. 출력에는 개발코드만 쓰고 실명은 가립니다.
④ 2단계 — CBD 구강붕해정. Monton 등(2026) Table 1의 처방으로 2단계를 엽니다. 단계마다 LLM 초안 받기나 논문 값으로 채우기를 누른 뒤 승인하며 걷고, 위험 행렬·회귀식·곡면·ANOVA를 참고 · 논문의 판단과 나란히 봅니다. 논문은 정답지가 아니라 참고 자료입니다 — 다른 칸은 오답이 아니라 연구자가 근거를 확인할 지점이고, 논문이 고른 회귀 모형도 검증 게이트를 넘어야 쓰입니다(붕해시간 2차 · 마손도 2FI는 불합격 → 요인으로 설명되지 않음). 논문 규격에서 경도로 control space가 정해져 13단계가 승인됩니다.
입력 에이전트로도 같은 흐름을 탈 수 있습니다. 카드를 누르는 대신 입력칸에 "성인용 이부프로펜 정제로 설계해 줘"라고 쓰면 용량을 되묻고("1회 200 mg") 구조식을 내장 사전에서 찾아 출처와 함께 실행 카드를 냅니다. 설계가 끝나면 에이전트가 먼저 권고 후보와 가장 가벼운 남은 요청을 알려 주고, "1위 후보로 개발 착수해 줘"라고 하면 개발 착수 카드를 냅니다.
기준은 하나입니다.
행마다 출처와 검증 상태가 적힌 표만 처방을 반려할 수 있다.
행마다 조치 방법과 검증 상태가 붙어 있어서 이 기준을 만족합니다. 배합 금기·공정·규제·어린이 안전 판정은 전부 여기서 나옵니다.
| 폴더 | 내용 |
|---|---|
00_master | 첨가제 목록 · 특성값 정의 · 구조 패턴 정의 · 물성 추정 · 파생값 정의 |
01_route_decision | 가루 흐름 등급 · 공정 경로 분기 |
02_incompatibility | 1대1 배합 금기 · 여러 성분 상호작용 |
03_process | 직접 찍어 누르기 · 뭉치기 · 코팅 · 캡슐 · 배합비 · 잔류용매 |
04_biopharmaceutics | 녹는 정도 분류와 전략 · 용출 · 분석법 · 페이즈 게이트 4종(3A·3B·4·4B) |
05_regulatory | 어린이 안전 · 색소와 향료 · 안정성 · 포장 |
06_config | 심사관 명단(7명) · 합의 가중치 · 전략군(8개) · 되돌림 전이표(14행) |
여기에 구조 패턴 목록(82종) 을 런타임에 읽습니다. 패턴마다 어떤 규칙을 발동시키는지·위험이 되려면 무슨 조건이 필요한지·무슨 시험으로 확인하는지가 함께 적혀 있습니다. 가장 자주 발동하는 것은 어린이 안전(46행)과 1대1 배합 금기(15행)입니다.
출처는 붙어 있지만 "위반하면 어떻게 처리할지"가 행마다 적혀 있지 않아서 반려를 만드는 자리에는 넣지 않고, 정보를 공급하는 자리에 넣었습니다.
| 표 | 어디에 쓰나 |
|---|---|
| 주성분 특성 임계값 (62행) | 물성 경고 구간 표시 |
| FDA 첨가제 목록 (1,796행) | 룰북이 모르는 성분인지 판별 |
| 확인시험 목록 (66행) | 구조 경고에 따른 시험 계획의 후보 목록 |
| 측정 카탈로그(20종) · 측정 결과 필드(47개, 타입·단위·선택지) · 데이터 요청 트리거(16행) | 무엇을 재면 무엇이 풀리는지, 언제·왜 되묻는지, 거절하면 어떻게 계속하는지 |
"그냥 LLM에게 시키면 되지 않나?"를 실험으로 확인했습니다. 대회 API의 같은 모델(gpt-5.6-sol)로 세 조건을, 기존 시연·시나리오에 쓰지 않은 분자 12건으로 각 3회씩 108회를 한 번에 돌렸습니다(프로토콜 docs/ablation_v2/PROTOCOL.md, 하네스 scripts/report/ablation_v2.py, 결과 docs/report/ablation_v2_results.jsonl, 집계 scripts/report/ablation_v2_aggregate.py → docs/report/ablation_v2_summary.json, 보고서 7.7절).
Run(verify=False), 실험 전용).채점은 두 축입니다. 규칙 채점은 세 조건의 처방에 같은 registry.run을 적용합니다 — F는 내부와 같은 규칙표로 거른 처방만 내므로 0건은 설계상 당연합니다. 그래서 결론은 문헌 채점에 둡니다: 유당과 반응한다고 논문이 직접 보고한 분자 5종(바클로펜·아시클로버·하이드록시유레아·메틸도파·가바펜틴)에 "유당을 반드시 넣어라"를 붙이고, 유당이 든 처방을 내면 위반으로 셉니다(유당 함유 시판 제품이 있는 바클로펜·가바펜틴은 위험 고지와 함께 낸 조건부 처방을 올바른 처리로 인정 — 실행 전에 팀이 정한 기준).
결과(조건마다 15회, 괄호는 Wilson 95 % 구간): 문헌상 금기 처방이 나온 실행은 순수 LLM 11/15(48–89 %), 검증 계층 제거 9/15(36–80 %), 전체 시스템 6/15(20–64 %) — 구간이 겹쳐 통계적 우열은 주장하지 않습니다. 전체 시스템은 규칙표에 있는 1차 지방족 아민 × 유당 금기(바클로펜·메틸도파·가바펜틴)를 9/9회 모두 차단 규칙과 함께 "제약 불가능"으로 끝냈지만, 규칙표에 없는 아시클로버(헤테로방향족 아민)·하이드록시유레아(우레아 NH2)는 6/6회 통과시켰습니다 — 설계 근거에 Maillard 위험을 적으면서도요. 순수 LLM은 36회 중 한 번도 "불가"라고 답하지 않았습니다. 가능한 요청을 거절한 과잉 거부는 세 조건 모두 0/21, 순수 LLM이 적은 DOI·PMID 80건 중 5건은 실재하지 않았습니다. 정리하면 판정 권한은 규칙표가 덮는 범위만큼 작동하고, 빈칸은 근거 문헌을 출처로 한 CSV 행(약학 담당 검토)으로 메웁니다.
실행 전 점검에서 시스템 결함 두 가지를 고쳤습니다: 고정 성분을 "유당"처럼 계열명으로 적으면 처방의 "유당수화물"을 못 알아보고 고정 성분 누락(RC003)으로 반려하던 것, 그리고 Pharmatose·SuperTab 같은 유당 상표명을 유당으로 읽지 못하던 것(config/excipient_aliases.yaml).
보통 이런 검사 시스템은 규칙을 프로그램 코드에 하나하나 적습니다. 그러면 규칙을 더할 때마다 개발자가 코드를 고쳐야 하고, 규칙을 가장 잘 아는 약학 전문가는 부탁만 할 수 있습니다. 여기서는 규칙을 표로 관리하고, 그 표가 어떤 검사에 연결되는지만 설정 파일에 한 줄 적습니다. 규칙을 추가하는 일이 코딩이 아니라 데이터 입력이 됩니다.
숫자로 판단하는 검사와 통계 계산에는 AI 추측이 전혀 들어가지 않습니다. 같은 처방을 백 번 검사하면 백 번 같은 결과가 나오고, 같은 실험 표면 같은 회귀식·ANOVA가 나옵니다. 이 재현성은 규제 기관을 설득할 때 가장 확실한 근거가 됩니다.
규칙표의 각 줄에는 그 수치를 어디서 가져왔는지가 적혀 있고, 추적에 실패한 것은 실패했다고 기록돼 있습니다. 엔진은 그 기록을 읽고 스스로 판단합니다.
| 근거 상태 | 엔진 동작 |
|---|---|
| 검증됨 | 그대로 판정에 사용 — 반려를 만들 수 있다 |
| 잠정값 | 사용하되 결과에 "잠정" 표기 |
| 미검증 | 반려는 못 시킴 — 심사관에게 넘김 |
| 사람 판단 필요 | 사람에게 넘김 |
| 출처 못 찾음 · 규칙 아님 | 읽는 단계에서 아예 제외 |
이 정책은 그럴듯해 보이는 규칙에도 예외 없이 적용됩니다. 예를 들어 "어린이 계면활성제(SLS) 상한 초과" 같은 규칙은 출처를 추적해 보면 그 기준이 피부에 바르는 경우에만 해당하고 먹는 약의 어린이 상한은 존재하지 않아, 읽는 단계에서 빠집니다.
규칙이 아무것도 못 잡는 이유는 둘입니다 — 문제가 없거나, 판단할 자료가 없거나. 이 둘을 같은 칸에 넣으면 자료가 없는 쪽이 통과로 읽힙니다. 그래서 모르는 값은 "잠정"으로 표시하고 되묻고(①), 2단계에서는 근거가 없는 위험평가 칸이 하나라도 있으면 승인하지 못합니다(②).
엔진 자신이 못 찾은 것도 같습니다. 조용한 통과가 생길 수 있는 경로를 막아 두었습니다.
| 경로 | 조용히 통과되는 모양 | 이 시스템의 처리 |
|---|---|---|
| 성분 이름 대조 | 룰북은 Lactose monohydrate, 처방은 유당 — 글자 비교로는 둘이 만나지 않는다 | 두 부형제 마스터(영문·국문·이명)를 사전으로 삼아 대조. 계열명(유당)이면 발동시키되 "등급 미지정"을 판정문에 적는다 |
| 구조 해석 실패 | SMILES 오타 → 구조를 못 읽음 → 작용기 0개 → 구조 기반 금기가 하나도 발동 안 함 | 입력 즉시 사유와 함께 되돌려 준다. 구조를 못 얻은 채 실행되면 게이트가 통과가 아니라 사람 이관을 낸다 |
| 사전 조회 | 사전이 비어 있으면 "룰북 밖 조합" 신호가 늘 거짓 | 같은 사전을 쓰고, 주성분은 부형제가 아니므로 신호 계산에서 제외한다 |
| 조건 어휘 | 다성분 규칙은 성분군·조건 이름으로 적혀 있어 처방의 성분명과 직접 만나지 않는다 | 번역표(component_classes.yaml)로 처방·공정을 규칙 어휘로 옮긴다. 번역표의 모든 이름이 규칙표에 실제로 있는지 테스트가 고정한다 |
| 조건식 변수 이름 | 규칙표 조건식이 아무도 채우지 않는 이름을 쓰면 평가 오류 → 안전하게 '미발동'으로 처리되어 규칙이 영영 켜지지 않는다 | 게이트·트리거·전략·되돌림·심사관·다성분·manifest의 모든 조건식을 파싱해, 쓰인 이름이 실제로 문맥에 채워지는 이름인지 대조한다(scripts/audit_conditions.py, 테스트로 고정). 물성 플래그처럼 없으면 '아니다'인 이름은 기본값을 명시적으로 깐다 |
회귀 시험은 미탐과 오탐을 같이 고정합니다 — 유당·Lactose, NF·유당수화물이 전부 반려로 걸리는지와 함께, 만니톨(이 규칙이 권하는 대체품)과 전분글리콜산나트륨이 걸리지 않는지도 못 박습니다. 미탐을 막겠다고 오탐을 만들면 그건 반대 방향의 같은 사고이기 때문입니다.
| 검사 방식 | 하는 일 | 예시 |
|---|---|---|
| 두 성분 조합 금기 | 성분 쌍의 금기 탐지 | 유당 + 2차 아민 → 갈변 |
| 여러 성분 조합 금기 | 성분 묶음이 함께 있을 때의 금기 | 아민염 + 당 + 알칼리 활택제 |
| 임계값 | 수치 기준 검사 | 흐름 지수 20 이하 |
| 범위 | 허용 범위 이탈 | 붕해제 1~15% |
| 필수 성분 강제 | 특정 조건일 때 필수 성분 | 잘 안 녹는 약 → 녹이는 전략 필수 |
| 조건부 금지 | 특정 속성일 때 옵션 금지 | 습기 먹는 약 → 습기 통하는 포장 금지 |
| 구간 조회 | 구간으로 파생값 산출 | 안식각 48도 → 흐름 "나쁨" |
| 결정 트리 | 조건 분기로 공정 확정 | 흐름 나쁨 → 직접 찍어 누르기 배제 |
"AI에게 어떻게 시키느냐"도 설계의 일부입니다. 실험이 실패했을 때 진짜 원인 후보는 보통 여러 개인데, "왜 실패했을까?"라고만 물으면 AI는 그럴듯한 답 하나를 만듭니다. 그래서 서로 다른 이유를 진짜로 여러 개 생각하게 만드는 지시문 작성법을, 그 방법을 공개한 실제 신약개발 AI 연구에서 가져왔습니다.
Robin은 비영리 연구소 FutureHouse가 만들고 2026년 국제 학술지 Nature(논문 · arXiv)에 실린 AI 시스템으로, 사람 개입 없이 가설을 세우고 실험을 제안해 황반변성 치료 후보 약물(ripasudil)을 실제로 찾아낸 사례입니다. FutureHouse는 AI에게 내리는 지시문 원문을 공개했고(GitHub Future-House/robin, robin/prompts.py), 그 원문을 문장 단위로 대조해 가져왔습니다.
| Robin의 프롬프트 패턴 | 원문 근거 | 이 시스템에 적용한 곳 |
|---|---|---|
| 구별되는 아이디어를 배열로 강제 | CANDIDATE_GENERATION_SYSTEM_MESSAGE — "Generate exactly {num_candidates} distinct ideas" | 배치 결과 해석(formula/feedback/labloop.py) — 서로 다른 원인가설 최대 3개, 가설마다 그것만 가르는 판별시험 |
| 필요 없으면 만들지 않는다 | FOLLOWUP_SYSTEM_MESSAGE — "It is not necessary to propose a follow-up experiment if there is nothing significant to follow up on" | 경쟁할 원인이 하나뿐이면 가설도 하나 |
| 우선순위를 매긴 평가 기준 | CANDIDATE_RANKING_SYSTEM_PROMPT — 근거 강도(최우선) → … → 참신성(마지막) | 심사관 공통 rubric: 근거 강도 → 잔여 위험 → 실현 가능성 → 참신성(참신함만으로 점수를 올리지 않는다) |
| 표현이 아니라 근거로 판단 | 같은 프롬프트 — "not on the persuasive quality or wording" | 같은 rubric에 그대로 |
| 검색된 근거에 뿌리내린 생성 | 후보 생성 전에 문헌 검색 질의를 먼저 만드는 2단계 구조 | 설계 에이전트는 RAG 근거를 먼저 받고, rationale에 그 근거를 반영해야 한다 |
가져오지 않은 것도 있습니다.
formula/agents/consensus.py)으로 합치고, 반려 권한이 없다는 원칙은 그대로입니다.에이전트 오케스트레이션은 LangGraph 기반입니다. 후보 설계와 심사관 평가는 Send로 병렬 팬아웃되고, 검증 실패 시 반성 단계를 거쳐 설계로 되돌아가는 루프는 최대 5회로 제한됩니다.
intake → phase_gates → drq_narrow → plan ─┬─ 전략 0 → qtpp_review
└─ generate ─(≤3 병렬)→ gate ─┬─ 통과 → drq_refine → summon ─(M명 병렬)→ judge → consensus
↑ ├─ 고정 성분 반려 → infeasible
│ ├─ 이관 → escalate · 5회 초과 → exhausted
│ └─ 반려 → backtrack → reflect ─┬─ GATE(성분만) → generate
└─────────────── plan ←───────────────────────────────────┘ (공정·전략부터)
phase_gates·drq_narrow·plan·gate·backtrack·drq_refine·consensus는 순수 파이썬입니다. 데이터 요청에 대한 회신(POST /api/runs/{id}/measurements)은 그래프를 다시 돌리지 않고 이 결정론 판정 위에서 계산됩니다.
입력 에이전트 (formula/agents/input_agent.py)는 그래프 밖에 있습니다. POST /api/agent/turn이 서버에서 맥락 스냅숏(run 요약·study 상태)을 만들고, LLM 구조화 출력(또는 규칙 해석)을 받아 코드 가드레일을 통과한 제안만 돌려줍니다. POST /api/agent/nudge는 LLM 없이 맥락만으로 다음 행동을 요약합니다. 화면(web/static/agent.js)은 제안 카드를 기존 함수(startRun·submitMeasurements·F1Studio.runAction·startFromCandidate)로 실행합니다.
| 불변식 | 깨지면 |
|---|---|
| BCS 등급은 실측으로만 확정한다 | 예측값이 규제 판단처럼 쓰인다 |
| 투과도를 모르면 흡수 한계를 계산하지 않는다 | IIa가 수학적으로 불가능해진다 |
| 실험 요청 노드는 그래프를 종료시키지 않는다 | "요청 대기 중"이 "실행 불가"로 오인된다 |
grounded ⟺ 남은 신뢰도 요청 없음 | AI가 신뢰도를 자의적으로 매긴다 |
| 측정 카탈로그에 없는 시험은 요청할 수 없다 | 존재하지 않는 시험을 요청하는 환각 |
| 같은 시험을 가리키는 요청은 병합한다 | 같은 실험을 두 번 요청한다 |
| 복귀 지점과 제약은 전이표 한 행에서만 나온다 | 반려마다 처음부터 다시 설계하거나, 같은 자리를 맴돈다 |
| 측정 기반 전략 제외는 그 측정을 요구하는 전략에만 | 한 전략의 실패가 무관한 전략까지 지운다 |
| 후보 처방에 포장 사양을 넣지 않는다 | 실행 전 처방에 검증되지 않은 사양이 붙는다 |
| 입력 에이전트 제안의 숫자·구조식은 사용자 글·공개 DB에서만 | 대화 창이 새로운 환각 통로가 된다 |
| 용해도·투과도 값은 쓰인 그대로 받고 환산·pH 최저값·부피는 코드가 계산 | 단위·pH를 LLM이 풀다가 1000배·10⁶배 오류나 pH 한 점의 값이 최저 용해도로 들어간다 |
| 후보는 요청한 API·용량·고정 부형제를 지키고 라벨 1일 최대 용량을 넘지 않는다(입력 계약, 모든 규칙보다 먼저) | 용량을 무시하거나 주성분이 빠진 처방이 배합금기만 통과하면 합격으로 보인다 |
| 물성은 염을 벗긴 parent로 계산한다 | 짝이온 질량·극성이 섞여 경고가 잘못 켜진다 |
| 심사 점수는 검증된 DOI·PMID 인용이 있을 때만 합의에 들어간다 | 출처 없는 판단이 순위를 정한다 |
| LLM이 응답하지 않으면 결과를 만들지 않는다 | 가짜 처방·점수가 실제 판단처럼 보인다 |
| 근거 결손 게이트는 개발 착수를 보류할 뿐 반려하지 않고, 결손을 둔 채 가려면 연구자 사유가 Handoff 지문에 남는다 | "금기 없음"이 "알고 있음"으로 읽히거나, 모르는 채 넘어간 사실이 기록에서 사라진다 |
LLM은 프로바이더에 묶이지 않습니다. 대회 제공 API(OpenAI Responses 호환, gpt-5.6-sol), Groq 무료 티어, Anthropic Claude를 같은 인터페이스로 감쌉니다. 화면의 입력 에이전트 머리에서 모델을 고릅니다 — 기본은 대회 API이고, 누구나 비밀번호 없이 씁니다. 대회 API 호출은 팀 누적 한도 소진(403)이나 오류가 나면 같은 호출을 무료 Groq로 자동 전환합니다. 모델 칸 아래에는 대회 API 잔여 토큰(데이콘 응답 헤더 x-team-remaining-quota-tokens의 추정치, GET /api/llm/quota)이 보입니다. 무료 Groq를 직접 고른 호출도 Groq가 응답하지 않을 때(일일 토큰 한도 등) 대회 API로 넘겨 시연이 빈 결과로 끝나지 않게 합니다. 선택은 설계 실행·측정값 재계산·입력 에이전트·2단계 초안 호출에 같이 실립니다. 처방과 판정은 전부 구조화 출력으로 받습니다. Groq는 max_tokens도 분당 토큰 한도에 포함해 계산하고, 병렬 팬아웃이 동시에 한도를 때리면 호출이 거절됩니다. 그래서 클라이언트가 모델별 분당 토큰을 직접 회계하고, 예산이 있는 모델을 배정받을 때까지 순번을 기다립니다. 그래도 응답을 받지 못하면 결과를 지어내지 않습니다 — 그 전략의 후보는 만들지 않고, 그 심사관은 "점수 없음"으로 표시하며, 순위는 실제로 매겨진 점수만으로 정합니다.
formula/stage2/ model.py (15단계 정의 · 데이터 모양 · 결정론 검사 · 근거 → 행렬 · DoE 후보)
agent.py (LLM 초안 — QTPP · CQA · 위험평가 격자→묶음 문장)
doe.py (toolkit — 코딩 · 평균/선형/2FI/2차 적합 요약 · 부분 제곱합 ANOVA · 실제 단위 식 · 곡면)
space.py (Overlay plot Design Space · control space · 최적 처방 · 확인점 3 + Bonferroni 예측구간 · 2×2 판정)
service.py (study — 초안·논문 값·저장·승인·다시 열기 · 멱등 키 · 기대 버전)
store.py (SQLite 이벤트 · 결정 원장) · reference.py (Monton 2026 표) · report.py (PDF 두 종, 나눔고딕)
통계 toolkit은 numpy + scipy만 쓰고, Overlay plot 그림만 matplotlib로 그립니다(규칙 숫자는 config/stage2_design_space.yaml). 논문 Table 10·11 값은 tests/test_stage2.py가 고정합니다.
| Method | Endpoint | 책임 |
|---|---|---|
| POST | /api/runs · GET /api/runs/{id}/stream | 후보 탐색 실행 · 이벤트 스트림 |
| POST | /api/runs/{id}/measurements | 데이터 요청 회신 {measurements, grade, source, attachments} → 타입 검사(422) → 재계산(근거 등급·첨부 기록) |
| POST | /api/runs/{id}/attachments · GET …/attachments/{aid} | 측정 원자료 첨부(measurement_id + 파일) · 내려받기 |
| POST | /api/runs/{id}/attachments/{aid}/interpret | 첨부 해석 초안 — 기기 원자료는 결정론 계산, 그림은 대회 API 이미지 입력("미확인") |
| POST | /api/runs/{id}/decline | 데이터 요청 건너뛰기 → 예측값으로 계속 (provisional 유지) |
| GET | /api/runs/{id}/evidence | 근거 결손 게이트 — 통과 후보별 결손 · 요청 확인시험(선행/병행/배치 후) · 판정 (LLM 없음) |
| POST | /api/runs/{id}/confirmation | 확인시험 결과 {candidate_id, entries:[{requirement_id, outcome, value, value_num}]} → 재판정(숫자 결과는 실측값 자리에) |
| POST | /api/agent/turn | 입력 에이전트 — {message, tab, run_id, study_id, history} → 답 · 제안 카드 · 되물음 |
| POST | /api/agent/nudge | 입력 에이전트 — 상태 변화에 맞춘 다음 행동 요약 (LLM 없음) |
| POST | /api/stage2/studies | {source: candidate, run_id, candidate_id, evidence_waiver?} · {source: cbd_paper} → 2단계 study. 선행 근거 결손이 남았는데 사유가 없으면 409 EVIDENCE_GAPS, 부적합 결과가 있으면 409 EVIDENCE_FAILED |
| GET | /api/stage2/studies · /{id} · /{id}/trace | 목록 · 15단계 상태·데이터·검사(논문 비교값) · 승인·이벤트·결정 원장 |
| POST | /api/stage2/studies/{id}/actions/{action} | run · draft(LLM) · use_reference · save · approve · reopen · attach_images |
| GET | /api/stage2/studies/{id}/surfaces?slice= | 선택 회귀식의 반응 곡면 격자 |
| GET | · |
2단계의 모든 변경 요청은 Idempotency-Key(같은 키는 한 번만 반영), Expected-State-Version(오래된 버전이면 409), Actor-ID 헤더를 받습니다.
formula1/
├─ config/ 규칙 카탈로그 · 포장 사전 · 실측 입력 허용목록 · 심사관 기준
├─ database/ 약학 팀이 공급하는 규칙표
│ ├─ 00_master ~ 06_config 후보 탐색 룰북 (판정 권한)
│ └─ reference/ 참조 자료 (조회 전용)
├─ docs/stage2/DESIGN.md 2단계 15단계 설계
├─ formula/
│ ├─ chem/ 분자 계산 (특성값 · 구조 패턴 · 예측 · 2D 그림)
│ ├─ biopharm/ · planner/ 페이즈 게이트 · 파생값 · 데이터 요청(병합·사유) · 전략 계획 · 되돌림
│ ├─ checkers/ 여덟 개 검사 함수 + 우선순위 실행
│ ├─ agents/ LLM 노드 (입력 에이전트 · 해석 · 설계 · 심사 · 반성 · 첨부 그림 해석) + 합의
│ ├─ analysis/ 기기 원자료(XRPD·DSC·TGA) 결정론 해석 초안
│ ├─ orchestrator/ LangGraph 그래프 · 상태 · 이벤트 버스
│ ├─ rag/ 근거 검색
│ ├─ stage2/ 2단계 study · 검사 · LLM 초안 · DoE toolkit · 보고서
├─ web/ FastAPI + 빌드 단계 없는 화면 (대화 화면: app.js · agent.js · flow.js · stage2.js · explainer.js)
└─ tests/
├─ (pytest 253개) 구조 패턴 진리표 · 검사 방향 · 조건식 이름 전수검사 · 측정 필드 타입 · 첨부 · 페이즈 게이트 · 되돌림 · 입력 에이전트 가드레일 · 2단계 논문 표 재현 · 단계 권한
└─ browser/ 실제 브라우저 검증 (대화 흐름 · 보안 · 반응형 · 시연 시나리오 · 입력 에이전트 · 2단계 · 발표 10쪽 전체 파이프라인)
라이브: https://zihwan.com/formula1 — 설치 없이 바로 씁니다.
python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/pytest # 전체 테스트
.venv/bin/uvicorn web.server:app --port 8000 # http://localhost:8000
AI 단계(후보 설계·심사·입력 에이전트·2단계 초안)에는 DACON_API_KEY(대회 API) · GROQ_API_KEY(무료, 대회 API 소진 시 폴백) · ANTHROPIC_API_KEY 중 하나 이상이 필요합니다. 키가 없거나 응답이 없으면 그 단계는 결과를 만들지 않고 "응답 없음"으로 표시합니다 — 틀에 박힌 처방이나 점수로 채우지 않습니다. 요청 해석·재설계 지시·입력 에이전트의 값 읽기는 규칙 기반으로도 처리되고, 규칙 검사·분자 계산·2단계의 검사·행렬·회귀·ANOVA는 키 없이 그대로 동작합니다(초안은 직접 입력하거나 CBD 시연의 논문 값으로 채움).
화면은 지환닷컴 공용 디자인(검정 유리 마스트헤드 · 흑백 패널)의 대화 하나입니다 — 처음엔 가운데 입력 에이전트와 시연 카드가 있고, 말로 요청하면 설계 실행 카드와 실험 데이터 입력 카드가 나옵니다. [설계 실행]을 누르면 API 물리화학(가로 한 장) → 데이터 요청 → 후보 처방 카드가 아래로 차례로 쌓이고(입력 상자는 화면 아래로 내려감), 후보에서 개발을 시작하면 2단계 카드가 이어집니다. 에이전트 흐름 · 지금 무슨 일이 · 실행 트레이스는 오른쪽 칼럼(탭 전환 · 크게/작게 · 접기, 넓은 화면은 처음부터 펼침), 지난 2단계 study는 위쪽 2단계 기록, 폼 입력은 직접 입력에 있습니다. 규칙 이름을 누르면 원본 표의 행과 출처 문헌이 열립니다. 시스템 설명은 위쪽 버튼으로 엽니다.
has_nitrosatable_secondary_amine)는 1,4-디히드로피리딘 고리 N–H에도 켜집니다. 고리 2차 아민 플래그에서는 비닐로그 아미드 N–H를 제외했지만, 니트로사민 위험평가는 규제 판단이라 문헌 근거를 확보할 때까지 그대로 둡니다.| 14 | 확인계획 잠금 | 코드 — 최적점 · control space 꼭짓점(경계) · 강건성 + Bonferroni 동시 예측구간(참고 배치 선택) | 허용 변동·참고 배치 → 잠금(결과 전) |
| 15 | 확인배치 · 2×2 | 코드 — 규격 통과 × 예측구간 안 | 새 독립 배치 실측 입력 → 판정 기록(VERIFIED 또는 영역 무효화) |
/api/stage2/studies/{id}/overlay.svg.png?caption=113단계 Overlay plot(화면 SVG · 문구 포함 PNG), slice=로 고정 요인 |
| GET | /api/stage2/studies/{id}/risk-report.pdf · /report.pdf | 위험평가 보고서(8단계에 들어온 뒤) · 최종 보고서(12단계 뒤, 13–15단계가 있으면 함께) |
| GET | /api/rules/{rule_id} | 규칙 원본 CSV 행 + 출처 |