You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS集成ChessKitEngine时Stockfish NNUE文件加载失败求助

使用ChessKitEngine集成Stockfish时NNUE文件加载失败问题

背景

我正在使用ChessKitEngine将Stockfish集成到iOS应用中,已将从Stockfish官网下载的nn-1111cefa1111.nnue文件添加到项目根目录并纳入编译目标,未修改文件名。

问题

无论如何指定NNUE文件(仅文件名、完整路径、转义空格等),引擎均无法加载该文件并崩溃。

我的代码

import Foundation
import ChessKitEngine

final class StockfishEngine {
    static let shared = StockfishEngine()
    private let engine = Engine(type: .stockfish)
    private var isReady = false
    private var pendingCompletionHandlers: [(String?) -> Void] = []

    init() {
        startEngine()
    }

    func startEngine() {
        print("Starting engine initialization...")
        engine.loggingEnabled = true
        engine.start {
            self.engine.send(command: .uci)
            
            // 尝试设置NNUE文件
            self.engine.send(command: .setoption(id: "EvalFile", value: "nn-1111cefa1111.nnue"))
            
            let threadCount = min(ProcessInfo.processInfo.processorCount - 1, 7)
            self.engine.send(command: .setoption(id: "Threads", value: String(threadCount)))
            self.engine.send(command: .setoption(id: "Skill Level", value: "10"))
            
            self.engine.send(command: .isready)
            
            self.engine.receiveResponse = { response in
                if "\(response)".contains("readyok") {
                    self.isReady = true
                    print("Stockfish Engine Started!")
                    self.processPendingRequests()
                    self.setupMoveResponseHandler()
                }
            }
        }
    }
}

错误日志

Starting engine initialization...
uci
Stockfish 17 by the Stockfish developers (see AUTHORS file)
minemine
x
<id> <name> Stockfish 17
<id> <author> the Stockfish developers (see AUTHORS file)
option name Debug Log File type string default <empty>
option name Clear Hash type button
option name Ponder type check default false
option name EvalFile type string default nn-1111cefa1111.nnue
option name EvalFileSmall type string default nn-37f18f62d772.nnue
<uciok>
isready
<readyok>
setoption name EvalFile value /Users/myname/Library/Developer/CoreSimulator/Devices/D1F042AC-7361-4EBC-86B7-6FA9050F68A9/data/Containers/Bundle/Application/885F453B-3219-475A-9786-14C7DF2BFBB1/App%20Name.app/nn-1111cefa1111.nnue
setoption name Threads value 7
setoption name MultiPV value 1
uci
setoption name EvalFile value nn-1111cefa1111.nnue
setoption name Threads value 7
setoption name Skill Level value 10
isready
Stockfish Engine Started!
<info> <string> Using 7 threads
<id> <name> Stockfish 17
<id> <author> the Stockfish developers (see AUTHORS file)
option name Debug Log File type string default <empty>
option name EvalFile type string default nn-1111cefa1111.nnue
option name EvalFileSmall type string default nn-37f18f62d772.nnue
<uciok>
<info> <string> Using 7 threads
<readyok>
setoption name Skill Level value 0
ucinewgame
position fen rnbqkbnr/pppppppp/8/8/8/3P4/PPP1PPPP/RNBQKBNR b KQkq - 0 1
go depth 15
rnbqkbnr/pppppppp/8/8/8/3P4/PPP1PPPP/RNBQKBNR b KQkq - 0 1
<info> <string> Available processors: 0-7
<info> <string> Using 7 threads
<info> <string> ERROR: Network evaluation parameters compatible with the engine must be available.
<info> <string> ERROR: The network file nn-1111cefa1111.nnue was not loaded successfully.
<info> <string> ERROR:
The UCI option EvalFile might need to specify the full path, including the directory name, to the network file.
<info> <string> ERROR: The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/nn-1111cefa1111.nnue
<info> <string> ERROR: The engine will be terminated now.

已尝试方案

  • 指定仅文件名:"nn-1111cefa1111.nnue"
  • 使用完整路径:
    let path = Bundle.main.path(forResource: "nn-1111cefa1111", ofType: "nnue")
    self.engine.send(command: .setoption(id: "EvalFile", value: path ?? ""))
    
  • 转义路径中的空格
  • 验证文件已存在于应用包内

解决方案

1. 确认NNUE文件与Stockfish版本匹配

你使用的是Stockfish 17,必须确保下载的nn-1111cefa1111.nnue是对应Stockfish 17的版本,版本不匹配会直接导致加载失败。

2. 修正UCI命令发送顺序

UCI协议要求必须在收到<uciok>响应后才能设置引擎选项,你的代码在发送.uci后立刻发送setoption,违反了协议流程。调整代码逻辑:

func startEngine() {
    print("Starting engine initialization...")
    engine.loggingEnabled = true
    engine.start {
        self.engine.send(command: .uci)
        
        self.engine.receiveResponse = { response in
            let responseStr = "\(response)"
            // 先处理uciok响应,再设置选项
            if responseStr.contains("<uciok>") {
                // 获取应用包内NNUE文件的正确路径
                if let nnuePath = Bundle.main.path(forResource: "nn-1111cefa1111", ofType: "nnue") {
                    self.engine.send(command: .setoption(id: "EvalFile", value: nnuePath))
                }
                
                let threadCount = min(ProcessInfo.processInfo.processorCount - 1, 7)
                self.engine.send(command: .setoption(id: "Threads", value: String(threadCount)))
                self.engine.send(command: .setoption(id: "Skill Level", value: "10"))
                
                self.engine.send(command: .isready)
            } else if responseStr.contains("readyok") {
                self.isReady = true
                print("Stockfish Engine Started!")
                self.processPendingRequests()
                self.setupMoveResponseHandler()
            }
        }
    }
}

3. 检查文件的打包配置

  • 在Xcode中选中nnue文件,确认Target Membership已勾选你的应用目标。
  • 进入项目的Build Phases,检查Copy Bundle Resources列表中是否包含该nnue文件,确保它会被打包到应用包内。

4. 避免重复发送命令

从错误日志可以看到,代码重复发送了uci和setoption命令,导致引擎状态混乱。确保命令只发送一次,流程逻辑清晰。


内容的提问来源于stack exchange,提问作者Avadhesh18

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:57:37