async fn execute(
        &self,
        input_variables: PromptArgs,
    ) -> Result<HashMap<String, Value>, ChainError> {
        log::info!("Using default implementation");
        let result = self.call(input_variables.clone()).await?;
        let mut output = HashMap::new();
        let output_key = self
            .get_output_keys()
            .first()
            .unwrap_or(&DEFAULT_OUTPUT_KEY.to_string())
            .clone();
        output.insert(output_key, json!(result.generation));
        output.insert(DEFAULT_RESULT_KEY.to_string(), json!(result));
        Ok(output)
    }
Execute the `Chain` and return the result of the generation process
along with additional information like token consumption formatted as a `HashMap`.
The input is a set of variables passed as a `PromptArgs` hashmap.
The key for the generated output is specified by the `get_output_keys`
method (default key is `output`).

# Example

```rust,ignore
# use crate::my_crate::{Chain, ConversationalChainBuilder, OpenAI, OpenAIModel, SimpleMemory, PromptArgs, prompt_args};
# async {
let llm = OpenAI::default().with_model(OpenAIModel::Gpt35);
let memory = SimpleMemory::new();

let chain = ConversationalChainBuilder::new()
.llm(llm)
.memory(memory.into())
.output_key("name")
.build().expect("Error building ConversationalChain");

let input_variables = prompt_args! {
"input" => "Im from Peru",
};

match chain.execute(input_variables).await {
Ok(result) => {
println!("Result: {:?}", result);
},
Err(e) => panic!("Error executing Chain: {:?}", e),
};
# };
```
src/chain/chain_trait.rs