
方式
vlm_macro_client.py は Qt の画面につながり、新しいブロックが出るたびに一度尋ねます。
- 盤を1マス20ピクセルの絵に描きます。ブロックの種類ごとに色が違います。
- ブロックの名前(I、O、T…)と一緒に「平らに、穴なく、ラインを消せるように置く場所」を尋ねます。
- 答えは target_rot(0〜3)と target_x(0〜9)のJSONです。
- 回転を合わせて x まで動かした後、すぐに落とします。
結果
同じエンジンで2局回しました。
- ブロック12個と11個、0ライン、穴50個と46個
- 23回尋ねて、23回ともJSONの形式を守りました。
- target_x は23回すべて4でした。回転だけが1(17回)と0(6回)で変わりました。
- 1回尋ねるのに平均5.7秒かかりました。
結果はマクロ DQN と同じです。中央に塔を積み、12個前後で終わります。
なぜ x=4 しか出ないのか
- 絵に列番号や格子線がありません。20ピクセルのマスを数えて列を割り出す必要がありますが、3B のモデルには難しいことです。五目並べでも、VLM が絵だけを見て座標を選ぶと、石がある場所をよく選んでいました。
- 尋ねる瞬間、新しいブロックは隠し行にあって絵には見えません。ブロックは名前でしか伝えていません。
- プロンプトは target_x を「列」と説明していますが、エンジンの x は 4×4 の箱の左端です。正しい列を選んでも、縦のブロックは1〜2マス右に落ちます。3回目の記事の一番左の列の問題もそのまま残っています。
VLM に座標を作らせる代わりに、置ける場所をコードがすべて計算し、選ぶことだけを任せる方向に変えました。
この段階の実際のコード
VLM に送る質問です。
vlm_macro_client.py
def get_macro_action(self, obs: np.ndarray, current_piece_name: str) -> tuple[int, int]:
img = _grid_to_image(obs)
prompt = (
"You are an expert Tetris AI.\n"
f"A new piece ({current_piece_name}) has just appeared at the top of the board.\n"
"Look at the current board state and decide the best final resting position for this piece.\n"
"Return your decision strictly as JSON with two keys:\n"
'- "target_rot": an integer from 0 to 3 representing the number of clockwise rotations.\n'
'- "target_x": an integer representing the target column (0-9 for a standard board, from left to right).\n'
"Try to keep the stack flat, avoid creating holes, and clear lines if possible.\n"
"Return ONLY the JSON string. Do not output anything else."
)新しいブロックが出たときに一度尋ね、その後は目標まで低レベルの行動を送ります。
vlm_macro_client.py
if piece_index > current_piece_index:
# New piece spawned. Ask VLM for macro action
piece_name = name_piece(piece_type)
print(f"\n--- New Piece Spawned: {piece_name} (Index: {piece_index}) ---")
current_piece_index = piece_index
target_rot, target_x = agent.get_macro_action(grid, piece_name)
target_x = max(0, min(target_x, w - 1))
print(f"VLM Decision -> Target Rot: {target_rot}, Target X: {target_x}")
# Translate target macro state to next micro action
micro = next_micro_for_target(piece_type, cur_rot, cur_x, target_rot, target_x)次の記事は「5. 場所はコードが計算し、LLM は選ぶだけ」です。
COMMENTS · CHAPTER 04
VLM にブロックの場所を直接選ばせる コメント 0
まだコメントはありません。気になった点や補足があれば残してください。
コメントを登録するには、Googleで始めてニックネームとメールアドレスを登録してください。
Googleで始める