Repository: deepset-ai/haystack

Issue:
Add missing docstrings to PromptNode, PromptTemplate and PromptModel
**Is your feature request related to a problem? Please describe.**
[The API docs](https://docs.haystack.deepset.ai/reference/prompt-node-api#promptmodel) we currently generate for the Prompt components are very hard to understand as they miss any description of the init params for the respective classes: PromptNode, PromptTemplate and PromptModel.

As a user, it's hard to understand what params I can pass to a PromptNode, what models I can initialize or where I can pass my api key for OpenAI. 

**Describe the solution you'd like**
Add docstrings to all init methods describing the params (and providing example values where useful)
Optionally: Maybe it's also helpful to link [the guide](https://docs.haystack.deepset.ai/docs/prompt_node) from the API docs?

CC @vblagoje 


Discussion:

Resolving patch:
diff --git a/haystack/nodes/prompt/prompt_node.py b/haystack/nodes/prompt/prompt_node.py
--- a/haystack/nodes/prompt/prompt_node.py
+++ b/haystack/nodes/prompt/prompt_node.py
@@ -60,11 +60,21 @@ class PromptTemplate(BasePromptTemplate, ABC):
     the prompt_text. For example, in the above example, the prompt_params are ["documents"] and the prompt_text is
     "Please give a sentiment...".
 
-    The prompt_text contains a placeholder $documents. This variable will be filled in runtime with the non-keyword
-    or keyword argument `documents` passed to this PromptTemplate's fill() method.
+    The prompt_text contains a placeholder $documents. This variable is filled in runtime with the non-keyword
+    or keyword argument `documents` passed to this PromptTemplate's `fill()` method.
+
+    For more details on how to use PromptTemplate, refer to
+    the [documentation](https://docs.haystack.deepset.ai/docs/prompt_node).
     """
 
     def __init__(self, name: str, prompt_text: str, prompt_params: Optional[List[str]] = None):
+        """
+         Creates a PromptTemplate instance.
+
+        :param name: The name of the prompt template (for example, sentiment-analysis, question-generation).
+        :param prompt_text: The prompt text including placeholders for the prompt_params.
+        :param prompt_params: The optional parameters that need to be filled in the prompt text. If not specified, they're inferred from the prompt text.
+        """
         super().__init__()
         if not prompt_params:
             # Define the regex pattern to match the strings after the $ character
@@ -95,20 +105,20 @@ def __init__(self, name: str, prompt_text: str, prompt_params: Optional[List[str
 
     def fill(self, *args, **kwargs) -> Dict[str, Any]:
         """
-        Prepares the prompt text parameters from non-keyword and keyword arguments.
+        Fills the prompt text parameters from non-keyword and keyword arguments.
 
         In the case of non-keyword arguments, the order of the arguments should match the left-to-right
         order of appearance of the parameters in the prompt text. For example, if the prompt text is:
         `Please come up with a question for the given context and the answer. Context: $documents;
-        Answer: $answers; Question:` then the first non-keyword argument will fill the $documents placeholder
-        and the second non-keyword argument will fill the $answers placeholder.
+        Answer: $answers; Question:` then the first non-keyword argument fills the $documents placeholder
+        and the second non-keyword argument fills the $answers placeholder.
 
-        In the case of keyword arguments, the order of the arguments does not matter. Placeholders in the
+        In the case of keyword arguments, the order of the arguments doesn't matter. Placeholders in the
         prompt text are filled with the corresponding keyword argument.
 
-        :param args: non-keyword arguments to use for filling the prompt text
-        :param kwargs: keyword arguments to use for filling the prompt text
-        :return: a dictionary with the prompt text and the prompt parameters
+        :param args: Non-keyword arguments to use for filling the prompt text.
+        :param kwargs: Keyword arguments to use for filling the prompt text.
+        :return: A dictionary with the prompt text and the prompt parameters.
         """
         template_dict = {}
         # attempt to resolve args first
@@ -143,6 +153,15 @@ class PromptModelInvocationLayer:
     """
 
     def __init__(self, model_name_or_path: str, max_length: Optional[int] = 100, **kwargs):
+        """
+        Creates a new PromptModelInvocationLayer instance.
+
+
+        :param model_name_or_path: The name or path of the underlying model.
+        :param max_length: The maximum length of output text.
+        :param kwargs: Additional keyword arguments passed to the underlying model.
+
+        """
         if model_name_or_path is None or len(model_name_or_path) == 0:
             raise ValueError("model_name_or_path cannot be None or empty string")
 
@@ -151,10 +170,20 @@ def __init__(self, model_name_or_path: str, max_length: Optional[int] = 100, **k
 
     @abstractmethod
     def invoke(self, *args, **kwargs):
+        """
+        It takes a prompt and returns a list of generated text using the underlying model.
+        :return: A list of generated text.
+        """
         pass
 
     @classmethod
     def supports(cls, model_name_or_path: str) -> bool:
+        """
+        Checks if the given model is supported by this invocation layer.
+
+        :param model_name_or_path: The name or path of the model.
+        :return: True if this invocation layer supports the model, False otherwise.
+        """
         return False
 
 
@@ -163,8 +192,8 @@ class HFLocalInvocationLayer(PromptModelInvocationLayer):
     A subclass of the PromptModelInvocationLayer class. It loads a pre-trained model from Hugging Face and
     passes a prepared prompt into that model.
 
-    Note: kwargs other than init parameter names are ignored to enable reflective construction of the class
-    as many variants of PromptModelInvocationLayer are possible and they may have different parameters
+    Note: kwargs other than init parameter names are ignored to enable reflective construction of the class,
+    as many variants of PromptModelInvocationLayer are possible and they may have different parameters.
     """
 
     def __init__(
@@ -176,6 +205,24 @@ def __init__(
         devices: Optional[List[Union[str, torch.device]]] = None,
         **kwargs,
     ):
+        """
+        Creates an instance of HFLocalInvocationLayer used to invoke local Hugging Face models.
+
+
+        :param model_name_or_path: The name or path of the underlying model.
+        :param max_length: The maximum length of the output text.
+        :param use_auth_token: The token to use as HTTP bearer authorization for remote files.
+        :param use_gpu: Whether to use GPU for inference.
+        :param device: The device to use for inference.
+        :param kwargs: Additional keyword arguments passed to the underlying model. Due to reflective construction of
+        all PromptModelInvocationLayer instances, this instance of HFLocalInvocationLayer might receive some unrelated
+        kwargs. Only kwargs relevant to the HFLocalInvocationLayer are considered. The list of supported kwargs
+        includes: trust_remote_code, revision, feature_extractor, tokenizer, config, use_fast, torch_dtype, device_map.
+        For more details about these kwargs, see
+        Hugging Face [documentation](https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.pipeline).
+
+
+        """
         super().__init__(model_name_or_path, max_length)
         self.use_auth_token = use_auth_token
 
@@ -239,13 +286,17 @@ def invoke(self, *args, **kwargs):
         """
         It takes a prompt and returns a list of generated text using the local Hugging Face transformers model
         :return: A list of generated text.
+
+        Note: Only kwargs relevant to Text2TextGenerationPipeline are passed to Hugging Face as model_input_kwargs.
+        Other kwargs are ignored.
         """
         output = []
         if kwargs and "prompt" in kwargs:
             prompt = kwargs.pop("prompt")
 
-            # We might have some uncleaned kwargs, so we need to take only the relevant.
+            # Consider only Text2TextGenerationPipeline relevant, ignore others
             # For more details refer to Hugging Face Text2TextGenerationPipeline documentation
+            # TODO resolve these kwargs from the pipeline signature
             model_input_kwargs = {
                 key: kwargs[key]
                 for key in ["return_tensors", "return_text", "clean_up_tokenization_spaces", "truncation"]
@@ -269,20 +320,34 @@ def supports(cls, model_name_or_path: str) -> bool:
 
 class OpenAIInvocationLayer(PromptModelInvocationLayer):
     """
-    PromptModelInvocationLayer implementation for OpenAI's GPT-3 InstructGPT models. Invocations are made via REST API.
+    PromptModelInvocationLayer implementation for OpenAI's GPT-3 InstructGPT models. Invocations are made using REST API.
     See [OpenAI GPT-3](https://beta.openai.com/docs/models/gpt-3) for more details.
 
     Note: kwargs other than init parameter names are ignored to enable reflective construction of the class
-    as many variants of PromptModelInvocationLayer are possible and they may have different parameters
+    as many variants of PromptModelInvocationLayer are possible and they may have different parameters.
     """
 
     def __init__(
         self, api_key: str, model_name_or_path: str = "text-davinci-003", max_length: Optional[int] = 100, **kwargs
     ):
+        """
+         Creates an instance of OpenAIInvocationLayer for OpenAI's GPT-3 InstructGPT models.
+
+        :param model_name_or_path: The name or path of the underlying model.
+        :param max_length: The maximum length of the output text.
+        :param api_key: The OpenAI API key.
+        :param kwargs: Additional keyword arguments passed to the underlying model. Due to reflective construction of
+        all PromptModelInvocationLayer instances, this instance of OpenAIInvocationLayer might receive some unrelated
+        kwargs. Only the kwargs relevant to OpenAIInvocationLayer are considered. The list of OpenAI-relevant
+        kwargs includes: suffix, temperature, top_p, presence_penalty, frequency_penalty, best_of, n, max_tokens,
+        logit_bias, stop, echo, and logprobs. For more details about these kwargs, see OpenAI
+        [documentation](https://beta.openai.com/docs/api-reference/completions/create).
+
+        """
         super().__init__(model_name_or_path, max_length)
         if not isinstance(api_key, str) or len(api_key) == 0:
             raise OpenAIError(
-                f"api_key {api_key} has to be a valid OpenAI key. Please visit https://beta.openai.com/ to get one."
+                f"api_key {api_key} must be a valid OpenAI key. Visit https://beta.openai.com/ to get one."
             )
         self.api_key = api_key
         self.url = "https://api.openai.com/v1/completions"
@@ -311,15 +376,18 @@ def __init__(
 
     def invoke(self, *args, **kwargs):
         """
-        Invokes a prompt on the model. It takes in a prompt, and returns a list of responses using a REST invocation.
+        Invokes a prompt on the model. It takes in a prompt and returns a list of responses using a REST invocation.
 
         :return: The responses are being returned.
+
+        Note: Only kwargs relevant to OpenAI are passed to OpenAI rest API. Others kwargs are ignored.
+        For more details, see OpenAI [documentation](https://beta.openai.com/docs/api-reference/completions/create).
         """
         prompt = kwargs.get("prompt")
         if not prompt:
             raise ValueError(
-                f"No prompt provided. Model {self.model_name_or_path} requires prompt"
-                f"Make sure to provide prompt in kwargs"
+                f"No prompt provided. Model {self.model_name_or_path} requires prompt."
+                f"Make sure to provide prompt in kwargs."
             )
 
         kwargs_with_defaults = self.model_input_kwargs
@@ -373,9 +441,11 @@ class PromptModel(BaseComponent):
     the box, it supports two model invocation layers: Hugging Face transformers and OpenAI, with the ability to
     register additional custom invocation layers.
 
-    Although it is possible to use PromptModel to make prompt invocations on the underlying model, please use
+    Although it is possible to use PromptModel to make prompt invocations on the underlying model, use
     PromptNode for interactions with the model. PromptModel instances are the practical approach for multiple
     PromptNode instances to use a single PromptNode and thus save computational resources.
+
+    For more details, refer to the PromptModel [documentation](https://docs.haystack.deepset.ai/docs/prompt_node).
     """
 
     outgoing_edges = 1
@@ -390,6 +460,17 @@ def __init__(
         devices: Optional[List[Union[str, torch.device]]] = None,
         model_kwargs: Optional[Dict] = None,
     ):
+        """
+        Creates an instance of PromptModel.
+
+        :param model_name_or_path: The name or path of the underlying model.
+        :param max_length: The maximum length of the generated output text.
+        :param api_key: The API key to use for the model.
+        :param use_auth_token: The Hugging Face token to use.
+        :param use_gpu: Whether to use GPU or not.
+        :param devices: The devices to use where the model is loaded.
+        :param model_kwargs: Additional keyword arguments passed to the underlying model.
+        """
         super().__init__()
         self.model_name_or_path = model_name_or_path
         self.max_length = max_length
@@ -438,9 +519,9 @@ def invoke(self, prompt: Union[str, List[str]], **kwargs) -> List[str]:
         """
         It takes in a prompt, and returns a list of responses using the underlying invocation layer.
 
-        :param prompt: The prompt to use for the invocation, it could be a single prompt or a list of prompts
-        :param kwargs: Additional keyword arguments to pass to the invocation layer
-        :return: A list of model generated responses for the prompt or prompts
+        :param prompt: The prompt to use for the invocation, it could be a single prompt or a list of prompts.
+        :param kwargs: Additional keyword arguments to pass to the invocation layer.
+        :return: A list of model generated responses for the prompt or prompts.
         """
         output = self.model_invocation_layer.invoke(prompt=prompt, **kwargs)
         return output
@@ -519,21 +600,26 @@ def get_predefined_prompt_templates() -> List[PromptTemplate]:
 class PromptNode(BaseComponent):
     """
     The PromptNode class is the central abstraction in Haystack's large language model (LLM) support. PromptNode
-    supports multiple NLP tasks out of the box. PromptNode allows users to perform multiple tasks, such as
-    summarization, question answering, question generation etc., using a single, unified model within the Haystack
-    framework.
+    supports multiple NLP tasks out of the box. You can use it to perform multiple tasks, such as
+    summarization, question answering, question generation, and more, using a single, unified model within the Haystack framework.
 
-    One of the benefits of PromptNode is that it allows users to define and add additional prompt templates
-    that the model supports. Defining additional prompt templates enables users to extend the model's capabilities
-    and use it for a broader range of NLP tasks within the Haystack ecosystem. Prompt engineers define templates
+    One of the benefits of PromptNode is that you can use it to define and add additional prompt templates
+     the model supports. Defining additional prompt templates makes it possible to extend the model's capabilities
+    and use it for a broader range of NLP tasks in Haystack. Prompt engineers define templates
     for each NLP task and register them with PromptNode. The burden of defining templates for each task rests on
     the prompt engineers, not the users.
 
-    Using an instance of PromptModel class, we can create multiple PromptNodes that share the same model, saving
+    Using an instance of the PromptModel class, you can create multiple PromptNodes that share the same model, saving
     the memory and time required to load the model multiple times.
 
     PromptNode also supports multiple model invocation layers: Hugging Face transformers and OpenAI with an
-    ability to register additional custom invocation layers.
+    ability to register additional custom invocation layers. However, note that we currently support only
+    T5 Flan and OpenAI InstructGPT models.
+
+    We recommend using LLMs fine-tuned on a collection of datasets phrased as instructions, otherwise we find that the
+    LLM does not "follow" prompt instructions well. This is why we recommend using T5 flan or OpenAI InstructGPT models.
+
+    For more details, see the PromptNode [documentation](https://docs.haystack.deepset.ai/docs/prompt_node).
 
     """
 
@@ -550,6 +636,18 @@ def __init__(
         use_gpu: Optional[bool] = None,
         devices: Optional[List[Union[str, torch.device]]] = None,
     ):
+        """
+        Creates a PromptNode instance.
+
+        :param model_name_or_path: The name of the model to use or an instance of PromptModel.
+        :param default_prompt_template: The default prompt template to use for the model.
+        :param output_variable: The name of the output variable in which you want to store the inference results.
+        :param max_length: The maximum length of the generated text output.
+        :param api_key: The API key to use for the model.
+        :param use_auth_token: The authentication token to use for the model.
+        :param use_gpu: Whether to use GPU or not.
+        :param devices: The devices to use for the model.
+        """
         super().__init__()
         self.prompt_templates: Dict[str, PromptTemplate] = {pt.name: pt for pt in get_predefined_prompt_templates()}  # type: ignore
         self.default_prompt_template: Union[str, PromptTemplate, None] = default_prompt_template
@@ -604,8 +702,8 @@ def prompt(self, prompt_template: Optional[Union[str, PromptTemplate]], *args, *
         The optional prompt_template parameter, if specified, takes precedence over the default prompt
         template for this PromptNode.
 
-        :param prompt_template: The name of the optional prompt template to use
-        :return: A list of strings as model responses
+        :param prompt_template: The name of the optional prompt template to use.
+        :return: A list of strings as model responses.
         """
         results = []
         prompt_prepared: Dict[str, Any] = {}
@@ -685,13 +783,11 @@ def remove_prompt_template(self, prompt_template: str) -> PromptTemplate:
     def set_default_prompt_template(self, prompt_template: Union[str, PromptTemplate]) -> "PromptNode":
         """
         Sets the default prompt template for the node.
-        :param prompt_template: the prompt template to be set as default.
-        :return: the current PromptNode object
+        :param prompt_template: The prompt template to be set as default.
+        :return: The current PromptNode object.
         """
         if not self.is_supported_template(prompt_template):
-            raise ValueError(
-                f"{prompt_template} not supported, please select one of: {self.get_prompt_template_names()}"
-            )
+            raise ValueError(f"{prompt_template} not supported, select one of: {self.get_prompt_template_names()}")
 
         self.default_prompt_template = prompt_template
         return self
@@ -713,7 +809,7 @@ def get_prompt_template_names(self) -> List[str]:
     def is_supported_template(self, prompt_template: Union[str, PromptTemplate]) -> bool:
         """
         Checks if a prompt template is supported.
-        :param prompt_template: the prompt template to be checked.
+        :param prompt_template: The prompt template to be checked.
         :return: True if the prompt template is supported, False otherwise.
         """
         template_name = prompt_template if isinstance(prompt_template, str) else prompt_template.name
@@ -722,8 +818,8 @@ def is_supported_template(self, prompt_template: Union[str, PromptTemplate]) ->
     def get_prompt_template(self, prompt_template_name: str) -> PromptTemplate:
         """
         Returns a prompt template by name.
-        :param prompt_template_name: the name of the prompt template to be returned.
-        :return: the prompt template object.
+        :param prompt_template_name: The name of the prompt template to be returned.
+        :return: The prompt template object.
         """
         if prompt_template_name not in self.prompt_templates:
             raise ValueError(f"Prompt template {prompt_template_name} not supported")
@@ -732,13 +828,11 @@ def get_prompt_template(self, prompt_template_name: str) -> PromptTemplate:
     def prompt_template_params(self, prompt_template: str) -> List[str]:
         """
         Returns the list of parameters for a prompt template.
-        :param prompt_template: the name of the prompt template.
-        :return: the list of parameters for the prompt template.
+        :param prompt_template: The name of the prompt template.
+        :return: The list of parameters for the prompt template.
         """
         if not self.is_supported_template(prompt_template):
-            raise ValueError(
-                f"{prompt_template} not supported, please select one of: {self.get_prompt_template_names()}"
-            )
+            raise ValueError(f"{prompt_template} not supported, select one of: {self.get_prompt_template_names()}")
 
         return list(self.prompt_templates[prompt_template].prompt_params)
 
@@ -761,17 +855,17 @@ def run(
         meta: Optional[dict] = None,
     ) -> Tuple[Dict, str]:
         """
-        Runs the prompt node on these inputs parameters. Returns the output of the prompt model
+        Runs the PromptNode on these inputs parameters. Returns the output of the prompt model.
         Parameters file_paths, labels, and meta are usually ignored.
 
-        :param query: the query is usually ignored by the prompt node unless it is used as a parameter in the
+        :param query: The query is usually ignored by the prompt node unless it is used as a parameter in the
         prompt template.
-        :param file_paths: the file paths are usually ignored by the prompt node unless it is used as a parameter
+        :param file_paths: The file paths are usually ignored by the prompt node unless they are used as a parameter
         in the prompt template.
-        :param labels: the labels are usually ignored by the prompt node unless it is used as a parameter in the
+        :param labels: The labels are usually ignored by the prompt node unless they are used as a parameter in the
         prompt template.
-        :param documents: the documents to be used for the prompt.
-        :param meta: the meta to be used for the prompt. Usually not used.
+        :param documents: The documents to be used for the prompt.
+        :param meta: The meta to be used for the prompt. Usually not used.
         """
 
         if not meta:


Test patch: