Repository: huggingface/peft

Issue:
huggingface_hub.utils._validators.HFValidationError when AutoPeftModelForCausalLM.from_pretrained
### System Info

peft                     0.8.2
transformers             4.37.2
torch                    2.2.0
accelerate               0.26.1

### Who can help?

_No response_

### Information

- [ ] The official example scripts
- [X] My own modified scripts

### Tasks

- [ ] An officially supported task in the `examples` folder
- [X] My own task or dataset (give details below)

### Reproduction

When load a pretrained model without tokenizer and passing in the local absolute path(more than two "/" in path) will throw HFValidationError

```
import torch
from peft import AutoPeftModelForCausalLM
dir = "/nas/lili/codes/pt/ft/trl/sftoutput/final_checkpoint"
model = AutoPeftModelForCausalLM.from_pretrained(dir, device_map="auto", torch_dtype=torch.bfloat16)
```

the pretrained dir has no tokenizer config:
```
ll final_checkpoint/
total 9164
drwxrwxr-x 2 ubuntu ubuntu      96 Feb  2 16:29 ./
drwxrwxr-x 3 ubuntu ubuntu      93 Feb  2 16:29 ../
-rw-rw-r-- 1 ubuntu ubuntu     609 Feb  2 16:29 adapter_config.json
-rw-rw-r-- 1 ubuntu ubuntu 8405600 Feb  2 16:29 adapter_model.safetensors
-rw-rw-r-- 1 ubuntu ubuntu    5110 Feb  2 16:29 README.md
```

if I change dir to path less than two "/", it's ok :

```
import torch
from peft import AutoPeftModelForCausalLM
dir = "final_checkpoint"
model = AutoPeftModelForCausalLM.from_pretrained(dir, device_map="auto", torch_dtype=torch.bfloat16)
```

And I debug into the code and find the executing path of failure:

```
        tokenizer_exists = False
        if os.path.exists(os.path.join(pretrained_model_name_or_path, TOKENIZER_CONFIG_NAME)):
            tokenizer_exists = True
        else:
            token = kwargs.get("token", None)
            if token is None:
                token = kwargs.get("use_auth_token", None)

            tokenizer_exists = file_exists(
                repo_id=pretrained_model_name_or_path,
                filename=TOKENIZER_CONFIG_NAME,
                revision=kwargs.get("revision", None),
                repo_type=kwargs.get("repo_type", None),
                token=token,
            )
```

If tokenizer does not exist, it will call file_exists and pass in repo_id with "/nas/lili/codes/pt/ft/trl/sftoutput/final_checkpoint", which is annotated by validate_hf_hub_args

```
    @validate_hf_hub_args
    def file_exists(
        self,
        repo_id: str,
        filename: str,
        *,
        repo_type: Optional[str] = None,
        revision: Optional[str] = None,
        token: Optional[str] = None,
    ) -> bool:
```

which validate any functions whose parameter name is repo_id:

```
    signature = inspect.signature(fn)

    # Should the validator switch `use_auth_token` values to `token`? In practice, always
    # True in `huggingface_hub`. Might not be the case in a downstream library.
    check_use_auth_token = "use_auth_token" not in signature.parameters and "token" in signature.parameters

    @wraps(fn)
    def _inner_fn(*args, **kwargs):
        has_token = False
        for arg_name, arg_value in chain(
            zip(signature.parameters, args),  # Args values
            kwargs.items(),  # Kwargs values
        ):
            if arg_name in ["repo_id", "from_id", "to_id"]:
                validate_repo_id(arg_value)
```

it goes into validate_repo_id:

```
    if repo_id.count("/") > 1:
        raise HFValidationError(
            "Repo id must be in the form 'repo_name' or 'namespace/repo_name':"
            f" '{repo_id}'. Use `repo_type` argument if needed."
        )
```

So it throws Repo id must be in the form 'repo_name' or 'namespace/repo_name'.

### Expected behavior

fix bug


Discussion:
As far as I know, there is no such issue in version 0.7.1
Thanks for reporting, this is indeed a bug. I'll work on a bugfix.

In the meantime, could you load the model using this approach:

```python
from peft import PeftModel
base_model = ...
model = PeftModel.from_pretrained(base_model, dir)
```

Resolving patch:
diff --git a/src/peft/auto.py b/src/peft/auto.py
--- a/src/peft/auto.py
+++ b/src/peft/auto.py
@@ -19,6 +19,7 @@
 from typing import Optional
 
 from huggingface_hub import file_exists
+from huggingface_hub.utils import HfHubHTTPError, HFValidationError
 from transformers import (
     AutoModel,
     AutoModelForCausalLM,
@@ -111,13 +112,16 @@ def from_pretrained(
             if token is None:
                 token = kwargs.get("use_auth_token", None)
 
-            tokenizer_exists = file_exists(
-                repo_id=pretrained_model_name_or_path,
-                filename=TOKENIZER_CONFIG_NAME,
-                revision=kwargs.get("revision", None),
-                repo_type=kwargs.get("repo_type", None),
-                token=token,
-            )
+            try:
+                tokenizer_exists = file_exists(
+                    repo_id=pretrained_model_name_or_path,
+                    filename=TOKENIZER_CONFIG_NAME,
+                    revision=kwargs.get("revision", None),
+                    repo_type=kwargs.get("repo_type", None),
+                    token=token,
+                )
+            except (HfHubHTTPError, HFValidationError):  # not on the Hub, so probably local repo
+                pass
 
         if tokenizer_exists:
             tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path)


Test patch:
diff --git a/tests/test_auto.py b/tests/test_auto.py
--- a/tests/test_auto.py
+++ b/tests/test_auto.py
@@ -43,7 +43,7 @@ def test_peft_causal_lm(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForCausalLM.from_pretrained(model_id)
+            model = AutoPeftModelForCausalLM.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForCausalLM))
 
         # check if kwargs are passed correctly
@@ -79,7 +79,7 @@ def test_peft_seq2seq_lm(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForSeq2SeqLM.from_pretrained(model_id)
+            model = AutoPeftModelForSeq2SeqLM.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForSeq2SeqLM))
 
         # check if kwargs are passed correctly
@@ -100,7 +100,7 @@ def test_peft_sequence_cls(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForSequenceClassification.from_pretrained(model_id)
+            model = AutoPeftModelForSequenceClassification.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForSequenceClassification))
 
         # check if kwargs are passed correctly
@@ -123,7 +123,7 @@ def test_peft_token_classification(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForTokenClassification.from_pretrained(model_id)
+            model = AutoPeftModelForTokenClassification.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForTokenClassification))
 
         # check if kwargs are passed correctly
@@ -146,7 +146,7 @@ def test_peft_question_answering(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForQuestionAnswering.from_pretrained(model_id)
+            model = AutoPeftModelForQuestionAnswering.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForQuestionAnswering))
 
         # check if kwargs are passed correctly
@@ -169,7 +169,7 @@ def test_peft_feature_extraction(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModelForFeatureExtraction.from_pretrained(model_id)
+            model = AutoPeftModelForFeatureExtraction.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModelForFeatureExtraction))
 
         # check if kwargs are passed correctly
@@ -192,7 +192,7 @@ def test_peft_whisper(self):
         with tempfile.TemporaryDirectory() as tmp_dirname:
             model.save_pretrained(tmp_dirname)
 
-            model = AutoPeftModel.from_pretrained(model_id)
+            model = AutoPeftModel.from_pretrained(tmp_dirname)
             self.assertTrue(isinstance(model, PeftModel))
 
         # check if kwargs are passed correctly