LeetCode 1320: Minimum Distance to Type a Word Using Two Fingers II
Some remarks
A_DECIMAL and it's use
A_DECIMAL = 65
# [...]
indices = {char: divmod((ord(char) - A_DECIMAL), WIDTH) for char in string.ascii_uppercase}

there is nothing wrong with
ord('A')

which you can use inline without defining a global (which it is not in the required Solution context).
You can even get rid of the ord math by enumerating.
indices = {char: divmod(idx, WIDTH) for idx, char in enumerate(string.ascii_uppercase)}

Names
def get_coordinates(left: int, right: int) -&gt; int:
    if not left or not right:
        return 0

    x_left, y_left = indices[left]
    x_right, y_right = indices[right]

    return abs(x_left - x_right) + abs(y_left - y_right)

does in no way return coordinates, it returns a distance.
Also left and right was misleading me, I thought of the two finger positions.
Also you claim the parameters are ints. Actually you pass characters. That is sloppy.
dist_a = get_coordinates(word_a, chars[index]) + get_dp(index + 1, chars[index], word_b)

is near to obfuscation. get_coordinates delivers a distance, word_a is not a word but a character where one finger is on, and what get_dp delivers cannot be guessed from the name nor is a docstring existing.
Algorithm
You use depth first search (DFS) while for finding the shortest path typically breadth first (BFS) is the better approach. With DFS you have to search the whole tree. By introducing an lru cache you found a nice trick to shortcut some branches. Still you cannot find the shortest path early but have to check the whole tree.
While the fingers are exchangeable you handle them as if they could not be swapped. So you find two optimal paths, one starting with the left finger, one starting with the right. Identical sequence, only the fingers are swapped. Also the cache does not match swapped fingers.
Cache
As already said, your cache does not match swapped fingers. By sorting the fingers you could match them. You do the lru cache on a function in a function. As the inner function is only existing while the outer is running also your cache is working for a single word only. Another call with the same word cannot be served from cache. If you pull the function on class level and change the signature to hold the remaining word instead of the index you could reuse cached &quot;endgames&quot;.
A function that would greatly benefit from a lru cache is get_coordinates (read get_distance)
Hostile test cases
You should implement a BFS with priority queue. Then you do some logging and timing on tests like &quot;FY&quot;*150. While the minimum distance is 0, your DFS evaluates branches at a distance of near 2700. A BFS would register nodes at a max distance of 9 but would never follow them.
Other
The line
chars = ''.join(a for a, b in zip(word, word[1:] + ' ') if a != b)

would deserve an explanatory comment or a nice function name.