Prompt Functions
Defining prompts as python functions is a great abstraction on top of chat pipelines, allowing you to leverage parsing logic and type hints to define a code-less function that will use a generator underneath.
A [Prompt
][rigging.prompt.Prompt] is typically created using one of the following decorators:
- [
@rg.prompt
][rigging.prompt.prompt] - Optionally takes a generator id, generator, or pipeline. - [
@generator.prompt
][rigging.generator.Generator.prompt] - Use this generator when executing the prompt. - [
@pipeline.prompt
][rigging.chat.ChatPipeline.prompt] - Use this pipeline when executing the prompt.
Prompt functions can be defined with or without the async
keyword, but they will always be
represented as async calls once wrapped based on their connection to chat pipelines.
In other words, wrapping a synchronous function with @rg.prompt
will result in an async
callable.
Prompts are optionally bound to a pipeline/generator underneath, hence the generator and pipeline
decorator variants, but they don’t have to be. We refer to bound prompts as “standalone”, because
they can be executed directly as functions. Otherwise, you are required first “bind” the prompt to
a specific generator id, generator, or pipeline to make it callable. Do this with
[Prompt.bind
][rigging.prompt.Prompt.bind] or related methods.
Templates and Docstrings
Underneath, the function signature will be analyzed for inputs and outputs, and the docstring
will be used to create a final jinja2 template which will be used as the prompt text. You can
always access this [.template
][rigging.prompt.Prompt.template] attribute to inspect how the prompt
will be formatted.
Here are the general processing docstring rules:
- Any docstring content will always be at the top of the prompt.
- If no docstring is provided, a generic one will be substituted.
- Any inputs not explicitly defined in the docstring will be appended after the docstring.
In other words, you can define how inputs will be included in the prompt by passing them inside the docstring in jinja2 formats, or let Rigging handle this for you by ommiting them.
Outputs and Context
In the example above, you’ll notice that defining our function to output a str
results in the following text be appended to the prompt template:
This is pretty light on context, and we can improve this by updating our signature
with a [Ctx
][rigging.prompt.Ctx] annotation:
We can apply [Ctx
][rigging.prompt.Ctx] annotations to any of the inputs and outputs
of a prompt. We can override the xml tag, provide an example, and add prefix text.
Output processing is optional, and can be omitted by returning a [Chat
][rigging.chat.Chat] object
from the wrapped function. This allows you to do with the generated output as you please.
Complex Outputs
You can also define more complex outputs by using a rigging model, list, tuple, or dataclass. Not every construction will be supported, and we attempt to pre-validate the output structure to ensure it can be processed correctly.
You can also embed a [Chat
][rigging.chat.Chat] object inside other objects, whichwill be excluded from any prompt guidance, but supplied the value when the prompt is executed. This is great for gathering both structured data and the original chat.
Rendering Prompts
In addition to templates, you can use [.render
][rigging.prompt.Prompt.render] with valid
inputs to view the exact prompt as it will be sent to a generator. You can also use this
to pass your prompt into pipelines at your discretion.
Running Prompts
Prompt objects expose the following methods for execution:
Prompt.run()
(Aliased with__call__
)Prompt.run_many()
Prompt.run_over()
(Available if the prompt was supplied/bonded to a pipeline or generator)
You can also bind a prompt at runtime with any of the following:
Prompt.bind()
Prompt.bind_many()
Prompt.bind_over()
“Pipeline Context”
Everything configured on a pipeline or generator will be used when running the prompt. Watch/Then/Map callbacks, tools, and generate params can all be used to alter the behavior of the prompt.
In general, you should consider prompts as producers of user messages, which
will be passed to [.fork()
][rigging.chat.ChatPipeline.fork], then handle
the parsing of outputs.