lichess-bot-devs / lichess-bot

A bridge between Lichess bots and chess engines
GNU Affero General Public License v3.0
769 stars 449 forks source link

Instantiating Custom Engine Outside of Class #599

Closed jerseyjosh closed 1 year ago

jerseyjosh commented 2 years ago

Instantiating my engine requires loading 6 .pth files, which currently is happening inside the class with the search method, so it is happening every time a move is made. This is slowing the engine down considerably.

Is there a way to instantiate the engine that keeps these variables in memory for the search method to call on for the duration of a game?

MarkZH commented 2 years ago

How are you currently instantiating your engine? Please post your code so we can offer advice.

jerseyjosh commented 2 years ago

the class is in strategies.py and currently looks something like:

class MoveMaker(MinimalEngine):
      def search(self, board, *args):
            engine = Mockfish() # PyTorch neural network architecture class
            engine.load_state_dict(torch.load(***FILE PATHS***))
            return PlayResult(engine.make_move, None)

Then I am just changing the engine in the config file to "MoveMaker" and it is making moves fine. The issue is in the fact that the engine.load_state_dict line requires opening 7 quite large .pth files each time a move is required, which I am hoping to find a workaround for.

AttackingOrDefending commented 2 years ago

You can use __init__.

class MoveMaker(MinimalEngine):
      def __init__(self):
            self.engine = Mockfish() # PyTorch neural network architecture class
            self.engine.load_state_dict(torch.load(***FILE PATHS***))
      def search(self, board, *args):
            return PlayResult(self.engine.make_move, None)

You will just have to replace engine with self.engine.

jerseyjosh commented 2 years ago

That was my initial approach but I can't seem to get the moves to go through if the MoveMaker class has an __init__ method. I will double check when I get home on the exact code to reproduce this.

MarkZH commented 2 years ago

I would think that super().__init__() needs to be called in the MoveMaker.__init__() method so lichess-bot can access the self.engine methods it expects. Perhaps something like this would work:

class MoveMaker(MinimalEngine):
      def __init__(self):
            super().__init__(None, {}, None, {})
            self.mockfish = Mockfish() # PyTorch neural network architecture class
            self.mockfish.load_state_dict(torch.load(***FILE PATHS***))
      def search(self, board, *args):
            return PlayResult(self.mockfish.make_move, None)

Notice the name change from self.engine to self.mockfish to prevent interference with MinimalEngine.engine.

AttackingOrDefending commented 2 years ago

You will also need to put *args and **kwargs in __init__ (def __init__(self, *args, **kwargs):), because lichess-bot will still try to pass parameters.

MarkZH commented 1 year ago

@jerseyjosh Any progress?

jerseyjosh commented 1 year ago

@jerseyjosh Any progress?

All working fine I think now, seems to be quicker, thanks. I think the solution ended up being something to do with calling super().init().

The engine plays at lichess.org/@/mockfishBOT