Langchain AutoLLM class
Labels: name: auto:enhancement, name: area: models

### Feature request

With more incoming of newer LLMs and LLM providers, either through APIs (like Open AI, Anthropic), or Local providers (like gpt4all, ctransformers, llama cpp etc). It becomes hard to keep track of and there is no uniform way os instantiating the LLM class.

For example:

```python
from langchain.llms.autollm import AutoLLM

model = AutoLLM.from_path(provider_name="gpt4all", model="orca-mini-3b.ggmlv3.q4_0.bin")
print(model)
```

In this example, I can simply just plug and play different providers and their different arguments that providers, by just instantiating one class. I took this inspiration from Hugging Face. 

### Motivation

The problem arises when we are doing quick prototyping. We have to import different llms for different usage. So why not have a common interface that can solve that? Also, I tried to keep the complexity by grouping these LLMs into two types of classes. 

```python
langchain.llms.AutoLLM.from_path
```
For all the local LLM providers. And 
```
langchain.llms.AutoLLM.from_api
```
For all the online cloud LLM providers. In that way, it can be easily distinguishable and also helpful for the user not to go here and there to search for how different LLMs fit.  

### Your contribution

I tried to come up with a very small prototype of the same. We can have a `utils.py` where we can keep these helper functions. Here is what the utils.py looks like

```python
import importlib

class LLMRegistry:
    llm_providers = {}

    @classmethod
    def register(cls, name, provider_class_name):
        cls.llm_providers[name] = provider_class_name

    @classmethod
    def get_provider(self, name):
        return self.llm_providers.get(name) 

class LLMLazyLoad:
    @staticmethod
    def load_provider(provider_name, *args, **kwargs):
        provider_class_name = LLMRegistry.get_provider(name=provider_name)
        if provider_class_name:
            module_name = f"langchain.llms.{provider_name}"
            module = importlib.import_module(module_name)
            provider_class = getattr(module, provider_class_name)
            return provider_class(*args, **kwargs)
        else:
            raise ValueError(f"Provider '{provider_name}' not found")

```

Now here is the `autollm.py` Where I created a very simple AutoLLM class. I made it simple just for a simple prototype purpose. 

```python
from langchain.llms.base import LLM
from utils import LLMLazyLoad, LLMRegistry

LLMRegistry.register("anthropic", "Anthropic")
LLMRegistry.register("ctransformers", "CTransformers")
LLMRegistry.register("gpt4all", "GPT4All")

class AutoLLM:
    @classmethod
    def from_api(cls, api_provider_name, *args, **kwargs) -> LLM:
        return LLMLazyLoad.load_provider(api_provider_name, *args, **kwargs)

    @classmethod
    def from_path(cls, provider_name, *args, **kwargs) -> LLM:
        # return me the specific LLM instance 
        return LLMLazyLoad.load_provider(provider_name=provider_name, *args, **kwargs)
```

Here is the `main.py` file when we use the `AutoLLM` class. 

```python
from autollm import AutoLLM

model = AutoLLM.from_path(provider_name="gpt4all", model="orca-mini-3b.ggmlv3.q4_0.bin")
print(model)

```

Also we can have a generic readme where we can provide all the basic info to load the local and cloud LLM providers. Here is what came in my mind. 

`Readme.md`

### Langchain AutoLLM class 

#### `from_path`

The `from_path` is a class method that helps us to instantiate different local LLMs. Here are the list of local LLM providers and the required arguments for each of them

#### GPT4All

Required arguments:

    - `model`: This path where the model exists

Optional arguments:

    - verbose: Whether to stream or not
    - callbacks: Streaming callbacks 

Here it is how we use with autollm class.

```python
from autollm import AutoLLM

model = AutoLLM.from_path(provider_name="gpt4all", model="orca-mini-3b.ggmlv3.q4_0.bin")
print(model("Hello world"))
```

For more information please visit the langchain-gpt4all page. 

(Similarly, provide the basic info of usage for all the local/cloud providers). Well, of course, we might need a lot of improvements to provide the best user experience. However, do let me your thoughts on whether we can implement this or not.