use std::collections::HashMap;
use anyhow::Result;
use parking_lot::RwLock;
use crate::Prompt;
use crate::PromptTemplate;
pub struct DocumentRetrievalPrompt {
instructions: RwLock<Vec<String>>,
}
impl DocumentRetrievalPrompt {
pub fn create() -> Self {
DocumentRetrievalPrompt {
instructions: RwLock::new(Vec::new()),
}
}
pub fn with_instructions(self, instructions: Vec<&str>) -> Self {
let instructs: Vec<_> = instructions.into_iter().map(|s| s.to_string()).collect();
self.instructions.write().extend(instructs);
self
}
}
impl Prompt for DocumentRetrievalPrompt {
fn template(&self) -> String {
let tpl = vec![
"Given the following contexts of a long document and a question, create a final answer with references (\"SOURCES\"). ",
"If you don't know the answer, just say that you don't know. Don't try to make up an answer. ",
"please follow these instructions:\n",
"{instructions}\n",
"=========\n",
"{contexts}\n",
"=========\n",
"QUESTION: {question}\n",
"FINAL ANSWER:",
];
tpl.join("")
}
fn variables(&self) -> Vec<String> {
vec!["contexts".to_string(), "question".to_string()]
}
fn format(&self, input_variables: HashMap<&str, &str>) -> Result<String> {
let instructions = self.instructions.read().join(" \n");
let prompt_template = self.template().replace("{instructions}", &instructions);
let prompt_template = PromptTemplate::create(&prompt_template, self.variables());
prompt_template.format(input_variables)
}
}