返回首页

Python 上使用 LLM 的国际象棋,无幻觉

本文描述了基于 LLM 的国际象棋 AI 实现,使用 python-chess 进行验证。FEN/PGN/UCI 用于提示和后备以确保稳定性。通过 OpenRouter 免费访问。

在 Llama 上创建无错误的国际象棋 AI
Advertisement 728x90

用LLM和Python打造无成本无幻觉的国际象棋AI

开发者常需将大语言模型集成到游戏应用中,但OpenAI API费用较高。一个经济实惠的替代方案是OpenRouter,它提供免费的开源模型(标签为:free)。这让你可免费调用Llama 4模型,仅受消息数量限制。

客户端初始化使用标准的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

设置base_url确保与现有代码兼容。每次走子时,模型接收一个提示,有效降低计算负担。

Google AdInline article slot

将棋盘状态传入提示词

大语言模型无法处理视觉棋盘,因此必须以文本形式构建上下文。标准的FEN和PGN格式结合python-chess提供的合法走法列表,可有效防止幻觉。

上下文构建代码:

# 获取当前局面的FEN格式
fen = board.fen()

# 获取走法历史的PGN格式
pgn_moves = []
temp_board = chess.Board()

# 历史走法
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 "起始局面"

# 获取合法走法列表
legal_moves = [move.uci() for move in board.legal_moves]
legal_moves_str = ", ".join(legal_moves)

系统提示词限定响应必须为UCI格式(4字符,如e2e4):

Google AdInline article slot
prompt = f"""你正在以{'白方' if board.turn == chess.WHITE else '黑方'}下棋。

当前局面(FEN):{fen}
走法历史:{pgn_history}
第{self.move_count}步

可用走法(UCI格式):{legal_moves_str}
从可用选项中选择最佳走法,并仅返回UCI走法代码(例如e2e4、g1f3、e7e8q)。
不要添加解释、分析或额外文字。
响应内容只能包含UCI走法代码。"""

结合FEN(当前状态)、PGN(历史记录)和UCI列表(约束条件),相比基础提示词,准确率提升80–90%。

走法验证与备用机制

大语言模型可能忽略指令,返回文本或非法走法。解决方案?采用“AI裁判”模式:由python-chess在应用前验证UCI走法。

UI循环逻辑:

Google AdInline article slot
if move_uci:
    try:
        move = chess.Move.from_uci(move_uci)
        if move in self.board.legal_moves:
            # 执行走法前动画
            self.animate_move(move)
            self.board.push(move)
            self.move_history.append(move.uci())
            self.last_ai_response = f"LLM走了:{move.uci()}"
            print(self.last_ai_response)
        else:
            # 备用:随机走法
            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失败,随机走法:{move.uci()}"
            print(self.last_ai_response)
    except ValueError:
        # 备用:随机走法
        move = random.choice(list(self.board.legal_moves))

示例日志:

  • 请求1:LLM返回'e7e5' → 合法走法。
  • 请求2:LLM回复'不错,我认为最佳走法是d7d5' → 触发备用机制,走a7a6。

此设计确保游戏流畅运行,避免崩溃。

核心架构组件

该项目依赖以下核心组件:

  • python-chess:棋盘管理、走法验证、FEN/PGN/UCI处理。
  • pygame:棋盘渲染、走法动画。
  • openai-client + OpenRouter:大语言模型推理调用。
  • 备用逻辑random.choice保障系统韧性。

模块化设计:LLMAI类将大语言模型交互与UI隔离,仅传递已验证的走法。该架构易于扩展至其他规则类游戏,如围棋或跳棋。

| 组件 | 功能 | 库 |

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

| 棋盘 | 状态管理与验证 | python-chess |

| LLM | 走法选择 | OpenRouter Llama 4 |

| UI | 渲染与输入 | pygame |

| 裁判 | 验证 | try/except |

最关键的几点

  • OpenRouter为原型开发提供强大大语言模型的免费访问,仅设请求量上限。
  • 使用FEN、PGN和UCI列表构建严格提示词,可将幻觉率降至10–20%。
  • “AI裁判”模式配合备用机制确保系统稳定:LLM提供建议,库负责验证并执行。
  • python-chess是Python中国际象棋逻辑的事实标准,涵盖所有规则,包括王车易位和吃过路兵。
  • 本项目展示了如何将非确定性模型融入确定性应用中。

— Editorial Team

Advertisement 728x90

继续阅读