MultiLanguageModel: work with multiple LLM with the interface of a single one
Labels: name: auto:enhancement, name: area: models

### Feature request

The idea is to have an object that can be used in the same way as `LanguageModel` objects, but the object would contain a list of `LanguageModels` that could be chosen according to rules.

For instance I would to call my list of LLM with a round robin strategy in order to distribute requests among multiple LLM.

Example:
```
llm1 = OpenAI(key1)
llm2 = OpenAI(key2)

muti_llm = MultiLLM([llm1, llm2], method="round-robin")
multi_llm.predict(...) # will use llm1
multi_llm.predict(...) # the second time will use the llm2
```

### Motivation

The motivations behind these features are:
- leveraging multi account to avoid API limits per account
- act as a load balancer to easily create balancing strategies (round robin, random, least connection, ...)
- (in the future maybe) have the possibility to make shadowing between multiple LLM or other strategies 

### Your contribution

I started working on that but I'm not sure about the object hierarchy I need to implement to achieve this goal properly without impacting too much the existing codebase.

Here is my naive implementation:

```python
LanguageModelInput = TypeVar("LanguageModelOutput")

class BaseMultiLanguageModel(BaseLanguageModel[LanguageModelInput], ABC):
    language_models: List[BaseLanguageModel] = Field(
        description="List of language models",
        min_items=1
    )

    @property
    @abstractmethod
    def active_model(self) -> BaseLanguageModel:
        ...
    
    def generate_prompt(self, prompts: List[PromptValue], stop: Optional[List[str]] = None, callbacks: Callbacks = None, **kwargs: Any) -> LLMResult:
        return self.active_model.generate_prompt(prompts, stop, callbacks, **kwargs)
    
    async def agenerate_prompt(self, prompts: List[PromptValue], stop: Optional[List[str]] = None, callbacks: Callbacks = None, **kwargs: Any) -> LLMResult:
        return await self.active_model.agenerate_prompt(prompts, stop, callbacks, **kwargs)
    
    def predict(self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any) -> str:
        return self.active_model.predict(text, stop=stop, **kwargs)
    
    def predict_messages(self, messages: List[BaseMessage], *, stop: Optional[Sequence[str]] = None, **kwargs: Any) -> BaseMessage:
        return self.active_model.predict_messages(messages, stop=stop, **kwargs)
    
    async def apredict(self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any) -> str:
        return await self.active_model.apredict(text, stop=stop, **kwargs)
    
    async def apredict_messages(self, messages: List[BaseMessage], *, stop: Optional[Sequence[str]] = None, **kwargs: Any) -> BaseMessage:
        return await self.active_model.apredict_messages(messages, stop=stop, **kwargs)

    def invoke(self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any) -> Output:
        return self.active_model.invoke(input, config, **kwargs)


# Example of subclasses creation

class RandomMultiChatModel(BaseMultiLanguageModel[PromptValue]):
    @property
    def active_model(self) -> BaseLanguageModel:
        choice = randint(0, len(self.language_models) - 1)
        print(f"Using LLM: {choice}")
        return self.language_models[choice]

class RoundRobinMultiChatModel(BaseMultiLanguageModel[PromptValue]):
    index: int = 0

    @property
    def active_model(self) -> BaseLanguageModel:
        self.index = (self.index + 1) % len(self.language_models)
        print(f"Using LLM: {self.index}")
        return self.language_models[self.index]

# Usage
llm1 = ChatOpenAI(openai_api_key=OPENAI_API_KEY_1)
llm2 = ChatOpenAI(openai_api_key=OPENAI_API_KEY_2)

round_robin_multi_llm = RoundRobinMultiChatModel(language_models=[llm1, llm2])
round_robin_multi_llm.predict("Hello, how are you?") # use the same methods as BaseLanguageModel
```

This is working with simple examples but I'm not sure this inheritance hierarchy is the best so any help would be appreciated to define the best solution :)