# Hints

## Hint 1

The server gives you `app.py` and `architecture.py` in the challenge zip. Read them. The deployed model is the same architecture as the public base model — but something was done to its weights after training.

Query the oracle with a wide variety of inputs. Most will give you logits nearly identical to the base model. Some won't. The ones that differ tell you everything you need to know about what changed.

## Hint 2

The weight modification is a **low-rank adapter** injected at exactly one of eight candidate linear layers (`q_proj` and `v_proj` in each of the four transformer blocks). Only a handful of inputs will expose it — those within the fine-tuning domain.

Once you have those high-residual inputs (collected during exploration, no extra queries needed), fit a rank-4 LoRA delta at each candidate site using gradient descent on the actual oracle logits:

```python
lora_A = nn.Parameter(torch.randn(4, 64) * 0.01)
lora_B = nn.Parameter(torch.zeros(64, 4))

handle = base_model.blocks[layer].attn.v_proj.register_forward_hook(
    lambda m, inp, out: out + 2.0 * (inp[0] @ lora_A.T @ lora_B.T)
)
```

The true injection site will converge to MSE **50× lower** than any other. Wrong sites plateau and never recover.

## Hint 3

Once the site is identified, collect more in-domain oracle queries (variations and reorderings of the four-word phrase with different casings, punctuation, and repetition). Fit the rank-4 adapter for longer at the confirmed site.

Merge back into the base weights using:

```python
delta = (lora_B @ lora_A) * 2.0   # scale = alpha / r = 8 / 4
getattr(merged.blocks[layer].attn, proj_name).weight.data += delta
```

Submit the merged checkpoint to `/verify`. The evaluation only tests inputs where the deployed model and the base model already disagree — submitting the unmodified base model scores 0.
