Powrót do strony głównej

Szachy z LLM na Pythonie bez halucynacji

Artykuł opisuje implementację szachowego AI na bazie LLM z użyciem python-chess do walidacji. Stosowane są FEN/PGN/UCI w promptach i fallback dla stabilności. Darmowy dostęp przez OpenRouter.

Stwórz szachowego AI na Llama bez błędów
Advertisement 728x90

Szachy z LLM w Pythonie bez kosztów — kompletna implementacja

Programiści często muszą integrować modele językowe (LLM) z grami, ale API OpenAI może być bardzo kosztowne. Alternatywą jest OpenRouter z darmowymi modelami open source oznaczonymi tagiem :free. Pozwala to uruchamiać zapytania do Llama 4 bez wydatków, przy ograniczeniu liczby zapytań.

Inicjalizacja klienta używa standardowego interfejsu openai:

class LLMAI:
    def __init__(self, model_name="meta-llama/llama-4-maverick-17b-128e-instruct:free"):
        self.client = openai.OpenAI(
            base_url="https://openrouter.ai/api/v1",
            api_key=OPENROUTER_API_KEY,
        )
        self.model_name = model_name
        self.move_count = 0

Zmiana base_url zapewnia kompatybilność z istniejącym kodem. Model otrzymuje zapytanie na każdy ruch, co minimalizuje obciążenie.

Google AdInline article slot

Przekazywanie stanu planszy do promptu

LLM nie rozumie wizualnej planszy, dlatego kontekst tworzony jest w formacie tekstowym. Standardy FEN i PGN są uzupełniane listą prawidłowych ruchów z biblioteki python-chess, aby uniknąć halucynacji.

Kod budowania kontekstu:

# pobieramy aktualną pozycję w formacie FEN
fen = board.fen()

# historia ruchów w formacie PGN
pgn_moves = []
temp_board = chess.Board()

# historia ruchów
for move in board.move_stack:
    pgn_moves.append(temp_board.san(move))
    temp_board.push(move)

pgn_history = " ".join(pgn_moves) if pgn_moves else "Początkowa pozycja"

# lista prawidłowych ruchów
legal_moves = [move.uci() for move in board.legal_moves]
legal_moves_str = ", ".join(legal_moves)

Systemowy prompt ogranicza odpowiedź notacją UCI (4 znaki, np. e2e4):

Google AdInline article slot
prompt = f"""Jesteś graczem w szachy jako {'białe' if board.turn == chess.WHITE else 'czarne'}.

Aktualna pozycja (FEN): {fen}
Historia ruchów: {pgn_history}
Numer ruchu: {self.move_count}

Dostępne ruchy w notacji UCI: {legal_moves_str}
Wybierz NAJLEPSZY ruch spośród dostępnych i zwróć TYLKO kod UCI ruchu (np. e2e4, g1f3, e7e8q).
Nie dodawaj żadnych wyjaśnień, analiz ani dodatkowego tekstu.
Odpowiedź powinna zawierać tylko kod UCI ruchu."""

Połączenie FEN (stan), PGN (historia) i listy UCI (ograniczenia) zwiększa dokładność o 80–90% w porównaniu do prostych promptów.

Weryfikacja ruchów i mechanizm rezerwy

LLM może ignorować instrukcje i zwracać tekst lub niestandardowe ruchy. Rozwiązaniem jest wzorzec «AI-Referee»: biblioteka python-chess sprawdza UCI przed zastosowaniem do planszy.

Logika w pętli UI:

Google AdInline article slot
if move_uci:
    try:
        move = chess.Move.from_uci(move_uci)
        if move in self.board.legal_moves:
            # animacja przed wykonaniem ruchu
            self.animate_move(move)
            self.board.push(move)
            self.move_history.append(move.uci())
            self.last_ai_response = f"LLM wykonał ruch: {move.uci()}"
            print(self.last_ai_response)
        else:
            # Rezerwa – losowy ruch
            move = random.choice(list(self.board.legal_moves))
            self.animate_move(move)
            self.board.push(move)
            self.move_history.append(move.uci())
            self.last_ai_response = f"LLM się pomylił, losowy ruch: {move.uci()}"
            print(self.last_ai_response)
    except ValueError:
        # Rezerwa – losowy ruch
        move = random.choice(list(self.board.legal_moves))

Przykład logu:

  • Zapytanie #1: LLM odpowiedział 'e7e5' → poprawny ruch.
  • Zapytanie #2: LLM odpowiedział 'Dobrze, myślę, że najlepszy ruch to d7d5' → rezerwa a7a6.

To zapewnia ciągłość gry bez awarii.

Kluczowe elementy architektury

Projekt oparty jest na:

  • python-chess: zarządzanie planszą, weryfikacja ruchów, FEN/PGN/UCI.
  • pygame: rysowanie planszy, animacje ruchów.
  • openai-client + OpenRouter: zapytania do LLM.
  • Logika rezerwy: random.choice dla odporności na błędy.

Integracja modułowa: klasa LLMAI izoluje LLM od interfejsu użytkownika, przekazując tylko zweryfikowane ruchy. Skalowalna na inne gry z zasadami (go, damki).

| Komponent | Rola | Biblioteka |

|-----------|------|------------|

| Plansza | Stan + weryfikacja | python-chess |

| LLM | Wybór ruchu | OpenRouter Llama 4 |

| UI | Rysowanie + wprowadzanie | pygame |

| Referee | Sprawdzanie | try/except |

Co warto wiedzieć

  • OpenRouter oferuje darmowy dostęp do mocnych LLM do prototypów, z limitem zapytań.
  • Ścisły prompt z FEN, PGN i listą UCI minimalizuje halucynacje do 10–20% przypadków.
  • Wzorzec «AI-Referee» z rezerwą zapewnia stabilność: LLM proponuje, biblioteka sprawdza i stosuje.
  • python-chess to standard do logiki szachowej w Pythonie, obejmuje wszystkie zasady, w tym roszadę i bicie en passant.
  • Projekt ilustruje podejście do integracji niedeterministycznych modeli w deterministyczne aplikacje.

— Editorial Team

Advertisement 728x90

Czytaj dalej