O mesmo quebra-cabeça, dois métodos
Resolvemos um quebra-cabeça fácil (35 casas vazias) duas vezes com o LoRA do 8B do post 3 (15 ciclos).
- 1ª rodada: para os dígitos de 1 a 9, em ordem, o VLM lista as casas onde o dígito não pode entrar, e as casas que são o único lugar que sobrou são preenchidas.
- 2ª rodada: o mesmo método, mas, sempre que uma casa é preenchida, o código preenche imediatamente qualquer caixa, linha ou coluna que tenha ficado com só uma casa vazia.
1ª rodada: parou com 2 casas vazias
Em 16 julgamentos, ele fez 38 jogadas, e 33 estavam corretas. Ele parou com 2 casas vazias, sem encontrar mais onde jogar. Dos 16 julgamentos, 9 listaram as casas impossíveis sem deixar nenhuma de fora.
As 5 jogadas erradas vieram todas de marcar por engano uma casa possível como impossível. Com um lugar a mais riscado, uma casa errada sobrava como único lugar. A demonstração não colocava as jogadas erradas no tabuleiro; apenas as registrava.
2ª rodada: completou em 10 julgamentos
A 2ª rodada preencheu as 35 casas em 10 julgamentos. Os julgamentos do VLM preencheram 15 casas, o código preencheu em seguida mais 20, e não houve nenhuma casa errada. Dos 10 julgamentos, 8 estavam completos, mas as casas que ficaram de fora não mudaram nenhuma resposta.
Quando o dígito 2 preencheu duas casas, surgiram caixas, linhas e colunas com uma só casa vazia, e o código preencheu cinco casas seguidas. Com o dígito 7 e com o dígito 3 da segunda volta, também foram cinco casas encadeadas em cada um. Com menos julgamentos a fazer, o modelo teve menos chances de errar.

As respostas anteriores criam as próximas
O modelo do post 1 preenchia na horizontal a partir do canto superior esquerdo e nunca usava as respostas anteriores como base para a próxima casa. A 2ª rodada preenche casas espalhadas pelo tabuleiro, e cada casa recém-preenchida vira a base para a próxima. É a mesma ordem em que as pessoas resolvem.

O código real desta etapa
Este é o código que roda depois de cada julgamento do VLM na 2ª rodada. Se uma caixa, linha ou coluna ficar com só uma casa vazia, ele a preenche com o dígito que falta.
vlm_digit_strategy.py
def _missing_one(values: list[int]) -> int | None:
present = {v for v in values if v != 0}
miss = [d for d in range(1, 10) if d not in present]
return miss[0] if len(miss) == 1 else None
def last_empty_unit_moves(
board: list[list[int]],
) -> list[tuple[int, int, int, str]]:
"""박스·행·열에 빈칸이 정확히 1개면 빠진 숫자로 채움."""
found: dict[tuple[int, int], tuple[int, str]] = {}
def add(r: int, c: int, digit: int, reason: str) -> None:
key = (r, c)
if key not in found:
found[key] = (digit, reason)
elif found[key][0] == digit:
prev = found[key][1]
if reason not in prev:
found[key] = (digit, f"{prev}+{reason}")
for br in range(3):
for bc in range(3):
cells = [
(r, c)
for r in range(br * 3, br * 3 + 3)
for c in range(bc * 3, bc * 3 + 3)
]
empties = [(r, c) for r, c in cells if board[r][c] == 0]
if len(empties) != 1:
continue
digit = _missing_one([board[r][c] for r, c in cells])
if digit is not None:
add(empties[0][0], empties[0][1], digit, "code_last_box")
for r in range(9):
empties = [(r, c) for c in range(9) if board[r][c] == 0]
if len(empties) != 1:
continue
digit = _missing_one([board[r][c] for c in range(9)])
if digit is not None:
add(empties[0][0], empties[0][1], digit, "code_last_row")
for c in range(9):
empties = [(r, c) for r in range(9) if board[r][c] == 0]
if len(empties) != 1:
continue
digit = _missing_one([board[r][c] for r in range(9)])
if digit is not None:
add(empties[0][0], empties[0][1], digit, "code_last_col")
return [
(r, c, digit, reason)
for (r, c), (digit, reason) in sorted(found.items())
]O próximo post é "5. Uma IA que ajuda as pessoas".
COMMENTS · CHAPTER 04
Comparando as resoluções antes e depois do treinamento 0 comentários
Ainda não há comentários. Deixe uma pergunta ou algo que queira acrescentar.
Para publicar um comentário, comece com o Google e registre um apelido e um e-mail.
Começar com o Google