You could just do
opt = torch.optim.Adam(list(model1.parameters()) + list(model2.parameters()), lr=3e-4)
...
    opt.zero_grad()
    out1 = model1(input)
    out2 = model2(out1)
    loss = loss(out2, target)
    loss.backward()
    opt.step()

(Or even stick the two models in a sequential if you want…)
This will cause loss.backward() to backpropagate through both model2 and model1’s computation.
Best regards
Thomas