-
-
Tool correctly diagnosing incorrect reasoning for an engine move
-
Trying Different move variations branching from an existing game, and get multi layered analysis grounded in objective feedback
-
Get extensive feedback grounded in chess principles
-
Filters to efficiently search past games with fuzzy search enabled
Inspiration
The inspiration for this came from our own experiences as a couple using many of the chess apps that are available online to improve our chess through online applications during the Lock-down. As relative beginners, a major roadblock that both of us ran into was that almost all the game review and game analysis tools available on these apps, even on paid apps, stopped at generic evaluations of moves by classifying them as blunders, good moves, excellent moves and so on. At best they offered the chance to try different moves, showing similar classifications for them as well.
What they fail to take into account, is the sheer amount of mental context that this takes up for a relatively new player, making a deeper understanding of the position next to impossible. This often results in players trying to move forward with a weaker understanding resulting in rating plateaus and often, loss of interest over time. While these apps provide tons of resources to acclimatize oneself with chess concepts and chess theory, we noticed a significant gap in their ability to tie this theory with the actual positions that a player might be exposed to. This is the gap that we seek to bridge with this Zugzwin. The name is a clever amalgamation of 'Zugzwang' which is a chess term for a position where any move by the player is detrimental and 'win'.
What it does
Zugzwin allows players to upload a PGN, either directly exporting it from their favorite applications or directly copy-pasting it as text into the box and receive a complete interactive review of their game. This includes analyzing every move with Stockfish, highlighting potential coaching signals which might be worth investigating, identifying openings, variations, and understanding where the game actually departs from theory. Further it provides options to explain mistakes using concrete engine backing as well as chess principles.
I think a standout feature of this application that demarcates it from any other application is that it actually allows you to chat with the coach. Most applications are unidirectional in their feedback. Not only does Zugzwin provide detailed feedback, it allows you to debug thinking in real time backed by Stockfish engine backing and concrete connections with chess principles.
Finally, it also allows the user to try out different variations from a game that they might have uploaded, allowing them to try different branching that might have happened. It also allows them to save the analysis of the games and come back to it at any time.
How we built it
The general architecture of Zugzwang is as follows:
- We used the Flask framework in Python for the backend.
- We used the Python chess library for reliable chess state and move validation.
- We used Postgres for users, games, coaching responses, and persistent sessions.
- We used Redis for rate limiting to prevent users from draining our API budgets.
- For the front end we used Vanilla JavaScript, HTML, and CSS.
- Lichess Opening Database for Openings Data
- We used Stockfish as a source of truth for evaluation, candidate moves, principle variations, and the strongest replies. This was done to ensure that there are no LLM-based hallucinations of the objective truths of the game.
- Overall we built it as an Agentic framework where the brain was the LLM, which was essentially Open AI's Responses API. It was given an array of tools that were written by us and provided to it. In order to prevent context bloat, we registered the tools them separately and stored it in a separate table, which had concise summaries. The LLM could then go through it and decide which relevant tool is needed for it. Additionally, we made sure only relevant context reached the LLM so it could make grounded opinions.
- The model used was OpenAI's GPT 5.6 luna-medium. We used it extensively throughout the process. We used Codex as the Agentic tool for code modification, review, debugging, etc. Further, we used planning mode extensively to lock down the architecture, making the model ask questions until complete clarity to prevent hallucinations and undesired implementations. In order to assist with better UI development we used a skill.
Challenges we ran into
One of the biggest challenges was definitely making the explanation grounded in Chess principles and objective evaluation of the engine and prevent hallucination. We constantly faced issues where either the model was too stuck on the Stockfish evaluation and just responded with numbers or gave very generic in-the-air explanations which weren't tying up directly to the evaluations by the engine. Both of them were problems that we had to fix.
Another problem that we faced was the model sometimes producing incomplete JSON objects, timing out or failing to select the right tools or failing to select any tool at all. In order to fix this we had to add bounded tool loops, structured responses, add validation, and provide deterministic feedback for cases when the LLM failed to provide an appropriate response. We initially tried for testing with the QEN model and we noticed that a lot of issues that we were facing with respect to tool calling were fixed when we moved to OpenAI's model. It was able to understand and invoke the right tools at the right time in a manner which was far superior and helped fix a lot of our issues right off the bat.
We also had some trouble deciding the split of the evaluation itself. What part should be handled by the Stockfish engine and what part should be handled by the LLM? We learned that it was better to make the model not trust objective facts, for instance: which pieces were move; the objective valuations of a position in comparison to a previous position; whether a particular piece was captured, et cetera. We noticed that it was best to offload the objective aspects to the Stockfish engine and the Python chess library. The LLM itself was more useful in sort of tying everything all together and giving a grounded explanation that adheres to the objective evaluation of the engine but also helps explain what exactly went wrong for the player.
We also had some challenges making sure that no particular user exploited or exhausted our API credits by spamming requests so we had to incorporate proper rate limiting infrastructure around it. We used Redis and we used the Token Bucket algorithm to make sure that users are able to make a reasonable number of requests while also making sure that a bad player doesn't exhaust our budget.
Lastly but not the least, tying all of these things together, making the board, the move timeline, the coaching panel, and the expression controls everything intuitive and tying it into a useful interface for the user was also a challenge. We basically did it with some good old trial and error. We took some feedback from our friends about what seemed ideal for a player of beginner to intermediate level to get maximum value out of the application .
Accomplishments that we're proud of
The first achievement that we are the most proud of is definitely having an evidence-based grounded coaching that works for intermediate beginners. We are proud to have been able to come up with a system that provides them with grounded explanations of what exactly went wrong or went well, which can help them speed in their learning incredibly.
We are also quite proud about being able to provide an avenue for users to actually provide their thought process and get feedback based on that. That is something that we haven't seen any of the tools in the market do and I think is one of the most useful aspects of the application.
Lastly we're also proud of some aspects at an engineering level that we added. For instance we added Zobrist-based hashing to make sure to compare openings. This was a good engineering challenge because we didn't want to rely on the engine when we had an opening. Zetabase is already available so we used clever techniques like Zobrist hashing, where we use XOR-based techniques to hash the positions and the moves and cleverly compare the state of the board in a very efficient way.
What we learned
The biggest legacy definitely was about understanding the sentiment of what exactly would help a player in this exact position: not a super grandmaster or grandmaster but someone who is an amateur or someone who's just started learning chess and is trying to understand the principles but does not have the theoretical foundations in their head quite yet. To be able to understand that a Stockfish evaluation or a centipawn loss or gain does not necessarily convey the meaning to a player at this level was one of the biggest learnings. We had to really understand a way to combine: 1) the intention of the player 2) the opponent's strongest response 3) changes in material 4) changes in pawn structure 5) piece activity and mobility 6) tactical threats 7) the practical decision that a player might consider the next time and tie it all together with an objective evaluation and deliver it in a way in which a player at this level can actually understand. Instead of getting confused by a barrage of chess terminology or a completely complicated tree of moves.
Additionally another learning that sort of was always something that we observed before while building with AI agents as well is that they are an incredible enhancer but strong engineering principles are at the core of any good product. We tried our best to adhere to them. Principles like : 1) rate limiting 2) appropriate caching 3) structured outputs using fallbacks 4) error logging 5) authentication 6) clear UI states are all just as important as the core idea itself.
What's next for Zugzwin
- Our next steps for Zugzwin would be to allow users to actually interact and share studies, or let's say the evaluations that they made, with each other. This would allow them to not have to use the AI tokens. Perhaps if someone has made an evaluation and it's been saved, they could probably share it with their friend and they could learn from it. It could create a better environment for beginners and intermediate beginners to learn better.
- Further we intend to add recording patterns or mistakes across uploads and allow users to make different playlists. For instance they might want to have a playlist of their own games and possibly we could have a tool to gather patterns or mistakes that they make and provide more feedback generalized across games.
- The long-term goal is essentially for this to become like a complete chess assistant system where people, especially people who cannot afford proper coaches, should not fall back. They should be able to get a way to learn and grow fast in chess and not have to give it up because they don't necessarily have the time or the money to spend on coaches and on expensive courses. Instead they can use a personalized AI that can give them very pointed specific feedback on where they can improve.
Built With
- codex
- css
- docker
- flask
- gpt
- html
- javascript
- oauth
- postgresql
- pytest
- python
- python-chess
- redis
Log in or sign up for Devpost to join the conversation.