molmim-nim について
molmim-nimは、MolMIMで小分子を扱うためのスキルです。ホステッド環境での生成と最適化に加え、分子表現のサンプリング、埋め込み、デコードを行うローカルワークフローを説明します。
主な機能
- 01小分子の生成と最適化
- 02シード分子周辺のサンプリング
- 03ローカルでの分子表現の埋め込みとデコード
- 04生成されたSMILESの検証
活用シーン
- 01シードSMILESからの分子生成
- 02QEDまたはplogPを基準とした候補の最適化
- 03ローカルな潜在空間ワークフローの利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia-bionemo/ bionemo-agent-toolkit --skill molmim-nimインストール後、Claude Code で/molmim-nimを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdskill-card.mdskill.oms.sigconfig/skillspector-baseline.ymlevals/config.ymlevals.jsontrigger_evals.jsonreferences/api.mdexamples.mdparameters.mdscience.mdvalidation.md詳細
MolMIM NIM
MolMIM を使って、小分子を生成、サンプリング、埋め込み、デコードします。このガイドでは、まずホスト型とローカルでの基本的な使い方を説明します。補足ファイルは必要に応じて参照してください。
references/api.md:エンドポイント、スキーマ、Docker フラグ、レスポンスフィールド。references/science.md:ユースケース、強み、制限、引き継ぎ。references/parameters.md:生成、サンプリング、最適化への影響。references/validation.md:SMILES、プロパティ、成果物のチェック。references/examples.md:ホスト型/ローカルの簡潔なリクエストパターン。
モードを選ぶ
コンテキストが不明確な場合にのみ確認します。
NVIDIA のホスト型 API とローカルの Docker NIM のどちらを使いますか?
ホスト型/ローカルのエンドポイント一覧については、references/api.md の Endpoints を参照してください。
モードの違い:ホスト型 API のリファレンスで公開されているのは /generate です。ローカルコンテナでは、潜在空間ワークフロー全般(/embedding、/hidden、/decode、/sampling、/generate)を利用できます。ホスト型の潜在空間エンドポイントを作り上げないでください。
ホスト型リクエストでは Authorization: Bearer $NGC_API_KEY を使用します。ローカル推論では、準備完了後に認証ヘッダーは不要です。
ローカル Docker
まずシェルの環境変数を使用し、リポジトリルートの .env は存在する場合にのみ読み込みます。キーを表示しないでください。MolMIM のドキュメントではローカルコンテナに NGC_CLI_API_KEY を使用します。このリポジトリでは NGC_API_KEY または NVIDIA_API_KEY を受け付け、起動時に NGC_CLI_API_KEY に割り当てます。
LOCAL_NIM_CACHE を /home/nvs/.cache/nim にマウントしてください。
NGC_API_KEY/NVIDIA_API_KEY から NGC_CLI_API_KEY への割り当て、docker login、および nvcr.io/nim/nvidia/molmim:1.0.0 の docker run を含む正確な起動前チェックについては、references/api.md の Local Docker にあるコマンドブロックをそのままコピーしてください。
準備状況の確認:
until curl -sf http://localhost:8000/v1/health/ready; do sleep 5; done
準備完了後に実行するローカル埋め込みのスモークテスト。ローカル推論では Authorization ヘッダーは不要です。
import requests
seed = "CN1C=NC2=C1C(=O)N(C(=O)N2C)C"
response = requests.post(
"http://localhost:8000/embedding",
headers={"Content-Type": "application/json"},
json={"sequences": [seed]},
timeout=60,
)
response.raise_for_status()
embedding_data = response.json()
embeddings = embedding_data["embeddings"]
print(f"received {len(embeddings)} embedding vector(s)")
ホスト型生成パターン
シード SMILES からの生成または最適化には、ホスト型の /generate を使用します。誘導プロパティ最適化には algorithm: "CMA-ES" を、シード周辺で誘導なしのサンプリングを行うには algorithm: "none" を使用します。
import os
import requests
hosted = True
url = (
"https://health.api.nvidia.com/v1/biology/nvidia/molmim/generate"
if hosted else "http://localhost:8000/generate"
)
headers = {"Content-Type": "application/json"}
if hosted:
headers["Authorization"] = f"Bearer {os.getenv('NGC_API_KEY')}"
payload = {
"smi": "CN1C=NC2=C1C(=O)N(C(=O)N2C)C",
"algorithm": "CMA-ES",
"num_molecules": 10,
"property_name": "QED",
"minimize": False,
"min_similarity": 0.4,
"particles": 8,
"iterations": 3,
}
response = requests.post(url, headers=headers, json=payload, timeout=180)
response.raise_for_status()
result = response.json()
生成時の注意点:
- フィールド名は
smilesではなくsmiです。 algorithmは"CMA-ES"または"none"です。property_nameは"QED"または"plogP"です。num_moleculesは 1~100、iterationsは 1~1000、particlesは 2~1000 です。- ホスト型 API のリファレンスでは
min_similarityは 0~1 です。ローカルのドキュメントでは、制約付き最適化でよく使われる値として 0.7 以下が強調されています。 scaled_radiusは 0~2 で、主にalgorithm: "none"またはローカルの/samplingと併用します。
ローカル潜在空間ワークフロー
埋め込み、隠れ状態の操作、デコードには、ローカル専用エンドポイントを使用します。誘導最適化のサンプルパッケージでも、これらのエンドポイントが使用されています。ローカルの潜在空間ワークフローについては、ホスト型 API のリファレンスで公開されているのは /generate であり、/embedding、/hidden、/decode、/sampling は現在のドキュメントではローカル専用であることを明記してください。
seed = "CC(Cc1ccc(cc1)C(C(=O)O)C)C"
base = "http://localhost:8000"
headers = {"Content-Type": "application/json"}
embedding = requests.post(
f"{base}/embedding",
headers=headers,
json={"sequences": [seed]},
timeout=60,
)
embedding.raise_for_status()
embedding_data = embedding.json()
embeddings = embedding_data["embeddings"]
print(f"received {len(embeddings)} embedding vector(s)")
hidden = requests.post(
f"{base}/hidden",
headers=headers,
json={"sequences": [seed]},
timeout=60,
)
hidden.raise_for_status()
hidden_data = hidden.json()
hiddens = hidden_data["hiddens"]
mask = hidden_data["mask"]
decoded = requests.post(
f"{base}/decode",
headers=headers,
json={"hiddens": hiddens, "mask": mask},
timeout=60,
)
decoded.raise_for_status()
sampled = requests.post(
f"{base}/sampling",
headers=headers,
json={"sequences": [seed], "num_molecules": 10, "scaled_radius": 0.7},
timeout=60,
)
sampled.raise_for_status()
出力の保存と検証
生成した SMILES を保存し、後続の用途で使用する前に検証してください。
from pathlib import Path
import json
def molmim_smiles(result):
values = []
if isinstance(result.get("generated"), list):
for item in result["generated"]:
if isinstance(item, str):
values.append(item)
elif isinstance(item, list):
values.extend(x for x in item if isinstance(x, str))
molecules = result.get("molecules")
if isinstance(molecules, str):
molecules = json.loads(molecules)
if isinstance(molecules, list):
for item in molecules:
if isinstance(item, dict) and isinstance(item.get("sample"), str):
values.append(item["sample"])
return values
generated = molmim_smiles(result)
if not generated:
raise RuntimeError(f"MolMIM returned no generated molecules: {result}")
Path("molmim_response.json").write_text(json.dumps(result, indent=2))
Path("molmim_generated.smi").write_text("\n".join(generated) + "\n")
for i, smiles in enumerate(generated, start=1):
print(i, smiles)
利用可能な場合は RDKit を使って、構文解析の可否、一意性、単純なプロパティの範囲、シードとの類似性制約が妥当かどうかを確認してください。生成された分子は候補であり、検証済みのヒットではありません。優先順位を決める前に、後続のプロパティ評価、ドッキング、親和性、毒性、合成可能性のチェックを行ってください。
トラブルシューティング
/embedding、/hidden、/decode、/samplingでホスト型の404が発生する場合:これらのエンドポイントはドキュメント上、ローカル専用です。401:ホスト型リクエストで NGC キーがないか、認証されていません。- ホスト型レスポンスの解析:実際のホスト型
/generateでは、moleculesが{sample, score}オブジェクトの JSON 文字列として返される場合があります。一方、ローカルエンドポイントではgeneratedが返される場合があります。どちらも解析してください。 422:SMILES が無効、algorithmが未対応、property_nameが無効、またはパラメーターがドキュメント記載の範囲外です。- ローカル起動時の認証:
NGC_CLI_API_KEYを設定するか、NGC_API_KEY/NVIDIA_API_KEYを設定し、上記のとおり割り当ててください。 - ローカル起動時にキャッシュが見つからない場合:
LOCAL_NIM_CACHEを/opt/nim/.cacheではなく/home/nvs/.cache/nimにマウントしてください。