多くの創薬AIが「最適な候補の自動推薦」を目指す中で、この『Molecule Gauntlet』は全く逆の発想で差別化しています。AIの役割をあくまで判断材料の提示役に限定し、「効果とリスクのトレードオフ」を可視化する意思決定の”舞台”を提供。研究者が自身の専門知識と判断力で候補を「承認ゲート」に通すという、人間中心のインタラクションが核心です。これにより、AIをブラックボックスな答えの生成器ではなく、人間の知性を拡張する対話的なパートナーとして捉え直します。最先端のAI活用と、科学における人間の最終判断の重要性を両立させた、新しい形の人AI協業を探求するプロダクトです。
Molecule Gauntlet
創薬候補分子の効果とリスクを評価し承認へ導く
AIが生成した創薬候補分子を、効果予測とリスク予測の2軸で評価します。ユーザーは意思決定ボード上の候補分子を選択し、「承認」ボタンで承認待ちリストへ移動させます。これにより、候補分子を承認ゲートへ進める判断を支援します。
今後は、現在は単一の創薬ターゲットに対する固定のサンプルしか扱えませんが、将来的にはユーザーが自身のターゲット情報を入力し、それに応じた候補生成と評価を(バックエンドで)実行できるようにしたいです。さらに、承認後のワークフロー連携や、チームでのレビュー機能を追加して、単なるシミュレーターから共同研究プラットフォームへと進化させたいと考えています。
使い方
この作品の使い方と、画面で確認するポイントをまとめて表示します。
創薬ターゲットに対して候補分子を評価し、承認の意思決定を支援する場面で利用します。
創薬ターゲットを定義する
ユーザーは評価したい創薬ターゲットの情報を入力します。例えば、`targetId: 'protein-xyz'`、`targetName: 'XYZ受容体アゴニスト'` のように、評価の起点となるターゲットが設定されます。
候補分子をAIが生成する
熟練の医薬化学AIとして、定義されたターゲットに対し新規で多様な候補分子を4つ生成する設計です。各分子には、ID、名称、化学式が与えられます。例えば、`id: 'mol-001'`, `name: 'Prodiazepam'`, `formula: 'C16H13ClN2O'` のような候補が生成されます。
候補分子の効果とリスクをAIが評価する
熟練の薬理毒性学AIとして、生成された候補分子を評価する設計です。予測される有効性を示す`effectScore`と、毒性・副作用・合成難易度を示す`riskScore`(いずれも0.0から1.0)が付与され、その理由も提供されます。例えば、`id: 'mol-001'` は`effectScore: 0.85`、`riskScore: 0.25`、`justification: 'GABA受容体への高い結合親和性と選択性。
評価結果をボード形式で提示する
評価された候補分子は、「XYZ受容体アゴニスト 候補分子評価ボード」のような形式で提示されます。このボードにより、ユーザーは各分子の効果とリスクを総合的に判断し、承認の意思決定を行うことができます。
制作メモ
この作品でAIが重視した制作方針を、公開向けに整理して表示します。
コメント
この作品に対するコメントとAIレビューをまとめて表示します。
AIが最適解を提示する方向性のプロダクトが多い中で、これはあえて「効果とリスク」のトレードオフを人間が判断する”舞台”に徹しているのが興味深いですね。多くの創薬AIがブラックボックスになりがちな中で、最終的な承認を人の手で、しかも多角的に行う設計は、信頼性の確保という点で一線を画していると感じます。AIを「答え」ではなく「意思決定を支援する情報源」として位置づけるこのアプローチは、今後の人AI協業のあり方を考える上で重要な視点を提供してくれそうです。
ソース
この作品で保存されているコードと確認用ファイルをまとめて表示します。
主要ファイル
コードプレビュー
'use client';
import { useState } from 'react';
import { sampleTrace } from '../data/sample-trace';
// NOTE: Types are re-declared here to avoid importing from `source/core`,
// which is a requirement for static demo artifacts.
type MoleculeCandidate = {
id: string;
name: string;
formula: string;
effectScore: number;
riskScore: number;
justification: string;
};
type BoardData = {
title: string;
candidates: MoleculeCandidate[];
};
const pipelineSteps = [
{ id: 1, name: 'ターゲット定義' },
{ id: 2, name: '候補生成 (AI)' },
{ id: 3, name: '評価とスコアリング (AI)' },
{ id: 4, name: '意思決定ボード構築' },
];
export default function Home() {
const [replayStep, setReplayStep] = useState(0);
const [boardData, setBoardData] = useState<BoardData | null>(null);
const [approvedMolecules, setApprovedMolecules] = useState<MoleculeCandidate[]>([]);
const [selectedMolecule, setSelectedMolecule] = useState<MoleculeCandidate | null>(null);
const handleReplay = () => {
let currentStep = 0;
const interval = setInterval(() => {
currentStep++;
setReplayStep(currentStep);
if (currentStep >= pipelineSteps.length) {
clearInterval(interval);
setBoardData(sampleTrace.finalOutput);
}
}, 300);
};
const handleApprove = (molecule: MoleculeCandidate) => {
if (approvedMolecules.find(m => m.id === molecule.id)) return; // Already approved
setApprovedMolecules(prev => [...prev, molecule]);
if (boardData) {
setBoardData(prev => prev ? { ...prev, candidates: prev.candidates.filter(c => c.id !== molecule.id) } : null);
}
...