Issue: Issue with MutliPromptRouter with memory destination chains
Labels: name: auto:bug, name: auto:improvement

### Issue you'd like to raise.

Hi I found myself having to do a "hack" when using MultiPromptChain.
In particular when ny destination chains take more than one parameter into the template at runtime for example "{current"_timestamp}"
I was getting the following exception
```

  File "/home/xxx/venv/lib/python3.10/site-packages/langchain/chains/base.py", line 149, in __call__
    inputs = self.prep_inputs(inputs)
  File "/home/xxx/venv/lib/python3.10/site-packages/langchain/chains/base.py", line 258, in prep_inputs
    self._validate_inputs(inputs)
  File "/home/xyz/venv/lib/python3.10/site-packages/langchain/chains/base.py", line 103, in _validate_inputs
    raise ValueError(f"Missing some input keys: {missing_keys}")
ValueError: Missing some input keys: {'current_timestamp'}
```

I had the below configuration:

```
            destinations = [f"{p['name']}: {p['description']}" for p in tools.prompt_infos]
            destinations_str = "\n".join(destinations)
            router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str,
                                                                  current_timestamp=datetime.now().isoformat())
            router_prompt = PromptTemplate(
                template=router_template,
                input_variables=["input"],
                output_parser=RouterOutputParser(),
            )
            router_chain = LLMRouterChain.from_llm(llm, router_prompt)
            chain = MultiPromptChain(
                router_chain=router_chain,
                destination_chains=tools.chains,
                default_chain=default_chain
                verbose=True,
            )

```

which had to be modified

first:

I used modified router template

```

MY_MULTI_PROMPT_ROUTER_TEMPLATE = """\
Given a raw text input to a language model select the model prompt best suited for \
the input. You will be given the names of the available prompts and a description of \
what th
MY_MULTI_PROMPT_ROUTER_TEMPLATE = """\
Given a raw text input to a language model select the model prompt best suited for \
the input. You will be given the names of the available prompts and a description of \
what the prompt is best suited for. You may also revise the original input if you \
think that revising it will ultimately lead to a better response from the language \
model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
```json
{{{{
    "destination": string \\ name of the prompt to use or "DEFAULT"
    "next_inputs": dict \\ dictionary of the with two fields "input" containing original input and current_timestamp containing {current_timestamp}

}}}}
```

REMEMBER: "destination" MUST be one of the candidate prompt names specified below OR
it can be "DEFAULT" if the input is not well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input if you don't think any \
modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT >>
"""e prompt is best suited for. You may also revise the original input if you \
think that revising it will ultimately lead to a better response from the language \
model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
```json
{{{{
    "destination": string \\ name of the prompt to use or "DEFAULT"
    "next_inputs": dict \\ dictionary of the with two fields "input" containing original input and current_timestamp containing {current_timestamp}

}}}}
```

REMEMBER: "destination" MUST be one of the candidate prompt names specified below OR
it can be "DEFAULT" if the input is not well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input if you don't think any \
modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT >>
"""
```

I also had to change the implementation of RouterOutputParser where I changed

 line 102 from
```
parsed["next_inputs"] = {self.next_inputs_inner_key: parsed["next_inputs"]}
to
parsed["next_inputs"] = parsed["next_inputs"]
```

This has allowed me to return and pass the desired next_inputs dict including current_timestamp into the destination chain

my chain initialization has changed to the following

```
destinations = [f"{p['name']}: {p['description']}" for p in tools.prompt_infos]
            destinations_str = "\n".join(destinations)
            router_template = MY_MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str,
                                                                  current_timestamp=datetime.now().isoformat())
            router_prompt = PromptTemplate(
                template=router_template,
                input_variables=["input"],
                output_parser=MyRouterOutputParser(next_inputs_inner_key="input", next_inputs_type=dict),
            )
            router_chain = LLMRouterChain.from_llm(llm, router_prompt)
            chain = MultiPromptChain(
                router_chain=router_chain,
                destination_chains=tools.chains,
                default_chain=tools.chains[ConversationStage.CASUAL.value],
                verbose=True,
            )

```
so I managed to pass the correct parameters to the destination chain but then I faced a new issue which was

  File "/home/xxx/venv/lib/python3.10/site-packages/langchain/memory/utils.py", line 21, in get_prompt_input_key
    raise ValueError(f"One input key expected got {prompt_input_keys}")
ValueError: One input key expected got ['current_timestamp', 'input']

after investigation I had to define a new MyConversationBufferMemory

```
class MyConversationBufferMemory(ConversationBufferMemory):
    other_keys: list = []

    @property
    def memory_variables(self) -> List[str]:
        """Will always return list of memory variables.

        :meta private:
        """
        return [self.memory_key] + self.other_keys
```

and instead of creating my memory in this way

`memory = ConversationBufferMemory(memory_key="chat_history", chat_memory=get_history(user_id))
`
I have created it in this way

`memory = MyConversationBufferMemory(memory_key="chat_history", chat_memory=get_history(user_id),other_keys=['current_timestamp'])`

this has finally allowed me to get get the response from the destination chain.

If someone has followed, would you thing that there is a better way of doing it?


### Suggestion:

_No response_