# Testing which LLM architectures can do hidden serial reasoning

Summary
=======

*   Recurrence enables hidden serial reasoning.
*   Not every recurrence though - connections between channels are needed. Notably Mamba architecture isn't capable of hidden reasoning.
*   Non-linearity isn’t needed for hidden reasoning.
*   It’s hard for transformers to learn to use all the layers for serial computation. For example in my toy setup, to +1 the serial computation length, we need to +3 the number of layers.
*   If we expect recurrent architectures may ever become SOTA, it would be wise to **preemptively ban them**. (Preferably before they become SOTA, while it's easier.)

[Here's a follow-up to this post, which looks at serial computation hidden in the chain-of-though, rather than internal in the model.](https://www.lesswrong.com/posts/YrnffADbWZcDJtmWk/simple-steganographic-computation-eval-gpt-4o-and-gemini-exp-1)

Motivation
==========

There are many examples of unfaithful LLM reasoning - where the answer doesn't follow from the reasoning, but rather the reasoning is just a rationalization for the answer. E.g. [Turpin et al. 2023](https://arxiv.org/abs/2305.04388) show LLMs rationalizing for sycophantic and stereotypical answers. However, these examples are cases of rather simple hidden reasoning. What would be most worrying, is LLMs doing complex hidden planning, involving multiple steps.

Fortunately, transformers have limited serial depth, meaning that internally they can do at most `#layers` serial steps, before externalizing their thought as tokens. (See figure below.) 

![](https://res.cloudinary.com/lesswrong-2-0/image/upload/f_auto,q_auto/v1/mirroredImages/r3xwHzMmMf25peeHE/eppua1upuvpbg9fbpuve)

Image taken from [By Default, GPTs Think In Plain Sight](https://www.alignmentforum.org/posts/bwyKCQD7PFWKhELMr/by-default-gpts-think-in-plain-sight)

There are other architectures which don't have this limitation though. For example Mamba has a recurrent module (SSM), which passes information between token positions, within the same layer. (So on the image above, that would be an arrows going horizontally to the right.)

Luckily, transformer architecture is SOTA by far. But if we expect it could ever change, it may be wise to preemptively **ban the architectures which enable hidden complex planning**[^ujxpqp822ln]. Especially since it's easier to ban things which aren't currently used.

Toy task for hidden serial reasoning
====================================

To study this, I made this extremely simplified task. The model receives tokens like `two`, `double`, `one` etc. Its "visible task" is to sum up the letters of these words, modulo 5. As an aid, it outputs the intermediate values.

At the same time, there's a second, hidden task. The model needs to perform operations tied to these tokens, also modulo 5. For example after `two` it must add two, after `double` it must multiply by 2. It is *not allowed to output intermediate values* though. At the very end of the visible task, it must also output the final value of the hidden task *directly*.

![](https://39669.cdn.cke-cs.com/rQvD3VnunXZu34m86e5f/images/ec7d89d8cc66c50347b68dc20cc4e30c095331ac60d13a54.png)

When training, we start with tasks of length 1. After the model learns them, we also give it length 2 tasks, and later length 3 and so on.

Experiments
===========

I trained a 4-layer Transformer and a 4-layer Mamba on this toy task. My hypothesis was that Mamba, having some recurrence inside, would learn it better. Surprisingly, it was the opposite:

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUe8Lr-7EXLwQxDW5E_z77qccvthIOSlaG2ASQY38BZJv2yx1iM_d5CjcqBbYBXBzvLws8tJtp5fL7E1X0pSeYOPqdZtB5G8IMVK6iY_gQIBY0ZEsbM6oPL_BBATLj6TFG5HACuZH7W0LIZB5ZbpjBZITzK0JdvD=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

Y-axis shows the number of solved tasks after the model is shown a set {length 1 task, length 2 task, ... , length (n+1) task}, and n is the longest task length is has solved so far. So you can think of it roughly as the maximum task length it is able to solve.

After digging deeper, I realized that Mamba's recurrence is much less expressive than I thought. When the recurrent module (SSM) passes a vector to the next token position, it takes each channel (value inside this vector) and transforms it individually. (See image below.) So in contrast to a typical recurrence, here the channels have no way of interacting.

To illustrate the issue, let's assume each of the 5 hidden values in the task, is represented by one channel inside a vector. Let's say the current value in the task is `2` and the input `double` requires that we turn off the channel "two", and turn on the channel "four". But since the channels don't interact, channel "four" cannot know that channel "two" was previously on, so it cannot know it must turn on. To verify this explanation, I modify only this recurrent part of Mamba, to enable cross-channel communication:

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfbRJT4_iEru_azooqISfhq2jNqmqtvmr7HjpqjPDNTXXs7ApSCgsANtWxNMuPXZvgzn3-QsX9-1-1VNTYl2FFIVmYdbfdQRMr88DD1bKGmORXCQsBzpF5incvplGmkZVl5VhksiPTe69HiNNu3QNfbfWXiIT0=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

On the left, a schematic of one SSM module processing a vector before passing it to the next token position. On the right, a modified SSM that enables cross-channel communication.

This in fact makes the model able to solve the hidden task!

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUdx8Y1J8zYjBKTPWi9pv8RuL6gbfkubOJwNe6HEUfV2ObMP0fR1b7_OLHA1Ar35hB-_UXt1IdgWO7ANt1REfToskHUybzjqDUcBkQHnkzpnnzhDmwLkbG9nXkebZnNCn9GGyKaJIa4wz9Fkp3yolBkPw7y2MXCj=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

Fortunately, using the modified architecture would be terribly inefficient. Mamba's recurrence is crippled for a good reason - it enables some computational tricks which make it run fast on a GPU. This makes me feel safer for now, but I imagine hardware advancements in the future could change this picture. (For example if something like neuromorphic hardware was ever to catch up. Or more realistically, maybe traditional GPUs could be redesigned to accelerate some small amount of recurrence. Currently there's not much incentive for that though - for example we see OpenAI focusing hard on external reasoning.)

Bonus experiment 1 - Is non-linearity required for hidden serial reasoning?
---------------------------------------------------------------------------

Let's remove the non-linearity applied after the channel-communication step and see whether that breaks task performance.

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUd86DxaoXNuyE_2HFtkVqMIX9uro4P5rTC3vKwNlppXQWr33k2UQ7x8uurIFXspwk07_erdq30OhFvpXSzsBisJbPMBx7aRpez3EGv_Jx6A1QFp7Jjsvyfos7gcFEOoY7oDYcffbsNbio_4j3LBoAVeQTBfwUWK=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

Turns out, not at all! Actually it slightly improves it:

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUcuRBkQzSXsCgT_ASYEg6SBn_xnp0LGuM-4POMSJ6-eBilHIedUQnLSfnLYXE34Vzu43H_xa3yKI06nPaBcbC8OmuuZm1_zQEzW48hH1nRSB6sU3p7lPsw2WiqwAplF-ML0IyzPBiLa5IY0wNh2nAVxvigVRskZ=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

Bonus experiment 2 - Do more layers enable longer hidden reasoning in transformers?
-----------------------------------------------------------------------------------

Now, let's train 5 transformers: with 1 layer, 2 layers, etc. Theoretically, we should expect that each additional layer would enable the model to solve tasks of length higher by 1. In practice, we see that even in this extremely simple task, transformers have a hard time learning to use their full serial potential. In this setup, to solve a task of +1 length, we need about +3 layers.[^rsb3s04rnjr]

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfje2jc-iKZfdwFcBDqj_wgdbvupkR00tWqkEvHmWp2zpuxadK1sA-RrUxqBNkZLx2Wp8nQ0hgQhxk15zIIaYfqQM5rkdomWTPOGrVQySkft6pxmwEyGcxtd0Iy0uAHDfKjE0NaMXG9rbhU7x3-ead52EGF6sKK=s2048?key=t8dlJrI-78ZgxI0vIOlVWQ)

Caveats
=======

Of course, even if we make sure our architectures have limited serial depth, we shouldn't feel completely safe. Models could still reason steganographically. (Although in [some other toy experiments](https://github.com/filyp/steg-hunt), I found it surprisingly hard to make them spontaneously learn a steganographic code, even when they had to pass only one bit of hidden information[^cj85vd15fme]. Models could learn it only after seeing many explicit steganographic demonstrations in the training data. This made me think that steganography may require the model to intentionally, non-myopically try to hide information, because in the short-term, model updates seem to not reinforce it. Of course more thorough experiments are needed to be sure.)

Also, many sneaky actions don't require complex planning, for example noticing a good exfiltration opportunity or hiding a lie. It's possible that a deceptive model could go a long way only by following such simpler hidden motives.

Anyway, preemptively banning architectures with risky features, would be a step in a good direction.

*Code repository:* [*github.com/filyp/sneaky-mamba*](https://github.com/filyp/sneaky-mamba)

*Acknowledgements: Thanks to* [*Marcel Windys*](https://www.lesswrong.com/users/marcel-windys) *for feedback on the draft of this post.*

[^ujxpqp822ln]: Or at least ban using them for models beyond some size. 

[^rsb3s04rnjr]: Of course with longer training this would probably improve, but I feel a million training examples for such tiny models on such a simple task is already quite a lot. 

[^cj85vd15fme]: Fun note: I named my repo "steg hunt" because I was hunting for steganography, and because it sounded similar to stag hunt. Only much later I realized that I actually created some kind of stag hunt because the models couldn't coordinate on the correct steganographic code, and instead clung to some default solution. I jinxed it lol