Defining Promptsο
Prompting is the fundamental input that gives LLMs their expressive power. LlamaIndex uses prompts to build the index, do insertion, perform traversal during querying, and to synthesize the final answer.
LlamaIndex uses a set of default prompt templates that works well out of the box. Users may also provide their own prompt templates to further customize the behavior of the framework.
Defining a custom promptο
Defining a custom prompt is as simple as creating a format string
from llama_index import Prompt
template = (
"We have provided context information below. \n"
"---------------------\n"
"{context_str}"
"\n---------------------\n"
"Given this information, please answer the question: {query_str}\n"
)
qa_template = Prompt(template)
Note: you may see references to legacy prompt subclasses such as
QuestionAnswerPrompt
,RefinePrompt
. These have been deprecated (and now are type aliases ofPrompt
). Now you can directly specifyPrompt(template)
to construct custom prompts. But you still have to make sure the template string contains the expected parameters (e.g.{context_str}
and{query_str}
) when replacing a default question answer prompt.
Passing custom prompts into the pipelineο
Since LlamaIndex is a multi-step pipeline, itβs important to identify the operation that you want to modify and pass in the custom prompt at the right place. At a high-level, prompts are used in 1) index construction, and 2) query engine execution
Modify prompts used in index constructionο
Different indices use different types of prompts during construction (some donβt use prompts at all).
For instance, TreeIndex
uses a SummaryPrompt
to hierarchically
summarize the nodes, and KeywordTableIndex
uses a KeywordExtractPrompt
to extract keywords.
There are two equivalent ways to override the prompts:
via the default nodes constructor
index = TreeIndex(nodes, summary_template=<custom_prompt>)
via the documents constructor.
index = TreeIndex.from_documents(docs, summary_template=<custom_prompt>)
For more details on which index uses which prompts, please visit Index class references.
Modify prompts used in query engineο
More commonly, prompts are used at query-time (i.e. for executing a query against an index and synthesizing the final response). There are also two equivalent ways to override the prompts:
via the high-level API
query_engine = index.as_query_engine(text_qa_template=<custom_prompt>)
via the low-level composition API
retriever = index.as_retriever()
synth = ResponseSynthesizer.from_args(text_qa_template=<custom_prompt>)
query_engine = RetrieverQueryEngine(retriever, response_synthesizer)
The two approaches above are equivalent, where 1 is essentially syntactic sugar for 2 and hides away the underlying complexity. You might want to use 1 to quickly modify some common parameters, and use 2 to have more granular control.
For more details on which classes use which prompts, please visit Query class references.
Full Exampleο
An example can be found in this notebook.
A corresponding snippet is below. We show how to define a custom prompt for question answer which
requires both a context_str
and query_str
field. The prompt is passed in during query-time.
from llama_index import Prompt, VectorStoreIndex, SimpleDirectoryReader
# load documents
documents = SimpleDirectoryReader('data').load_data()
# define custom Prompt
TEMPLATE_STR = (
"We have provided context information below. \n"
"---------------------\n"
"{context_str}"
"\n---------------------\n"
"Given this information, please answer the question: {query_str}\n"
)
QA_TEMPLATE = Prompt(TEMPLATE_STR)
# Build index
index = VectorStoreIndex.from_documents(documents)
# Configure query engine
query_engine = index.as_query_engine(text_qa_template=QA_TEMPLATE)
# Execute query
response = query_engine.query("What did the author do growing up?")
print(response)
Check out the reference documentation for a full set of all prompts.