FEAT [`Generation`]: Introduce a centralized API to switch between cache implementations
Author: younesbelkada
Pull request: yes

# What does this PR do?

I would like to introduce a new API before the release to centralize switching between cache implementations ! 

Right now to load SInkCache one needs to do:

```python
from transformers import AutoTokenizer, AutoModelForCausalLM, SinkCache

tokenizer = AutoTokenizer.from_pretrained("TheBloke/LLaMa-7B-GPTQ")
model = AutoModelForCausalLM.from_pretrained("TheBloke/LLaMa-7B-GPTQ", device_map="auto")

cache = SinkCache(window_length=508, num_sink_tokens=4)

inputs = tokenizer(["Vaswani et al. (2017) introduced the Transformers"], return_tensors="pt").to(model.device)
gen_out = model.generate(**inputs, do_sample=False, max_new_tokens=300, past_key_values=cache)
decoded = tokenizer.batch_decode(gen_out, skip_special_tokens=True)
```

For static cache: 

```python
from transformers import AutoTokenizer, AutoModelForCausalLM, SinkCache

tokenizer = AutoTokenizer.from_pretrained("TheBloke/LLaMa-7B-GPTQ")
model = AutoModelForCausalLM.from_pretrained("TheBloke/LLaMa-7B-GPTQ", device_map="auto")

model.generation_config.cache_implementation = "static"

inputs = tokenizer(["Vaswani et al. (2017) introduced the Transformers"], return_tensors="pt").to(model.device)
gen_out = model.generate(**inputs, do_sample=False, max_new_tokens=300)
decoded = tokenizer.batch_decode(gen_out, skip_special_tokens=True)
```

With this PR: 


```diff
from transformers import AutoTokenizer, AutoModelForCausalLM, SinkCache

tokenizer = AutoTokenizer.from_pretrained("TheBloke/LLaMa-7B-GPTQ")
model = AutoModelForCausalLM.from_pretrained("TheBloke/LLaMa-7B-GPTQ", device_map="auto")

- cache = SinkCache(window_length=508, num_sink_tokens=4)
+ model.set_cache_implementation("sink", sink_window_length=508, num_sink_tokens=4)

inputs = tokenizer(["Vaswani et al. (2017) introduced the Transformers"], return_tensors="pt").to(model.device)
- gen_out = model.generate(**inputs, do_sample=False, max_new_tokens=300, past_key_value=cache)
+ gen_out = model.generate(**inputs, do_sample=False, max_new_tokens=300)
decoded = tokenizer.batch_decode(gen_out, skip_special_tokens=True)
```

```diff
from transformers import AutoTokenizer, AutoModelForCausalLM, SinkCache

tokenizer = AutoTokenizer.from_pretrained("TheBloke/LLaMa-7B-GPTQ")
model = AutoModelForCausalLM.from_pretrained("TheBloke/LLaMa-7B-GPTQ", device_map="auto")

- model.generation_config.cache_implementation = "static"
+ model.set_cache_implementation("static")

inputs = tokenizer(["Vaswani et al. (2017) introduced the Transformers"], return_tensors="pt").to(model.device)
gen_out = model.generate(**inputs, do_sample=False, max_new_tokens=300, past_key_values=cache)
decoded = tokenizer.batch_decode(gen_out, skip_special_tokens=True)
```

What do you think @gante @tomaarsen @ArthurZucker @amyeroberts  ?

If you are happy with the design and idea I can move forward with adding tests and docs !


Comments:
The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/transformers/pr_29030). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.