There are two main ways to use Rigging: prompts and pipelines.

Prompts offer a simple entry point and cover a lot of ground, but pipelines are the core of Rigging’s power—prompts ultimately serve as a way to leverage pipelines.

Using Prompts

  1. Establish a function decorated with @prompt with the inference model you want to use.
  2. Call the function as you normally would and receive structured data back.
import rigging as rg

@rg.prompt(generator_id="claude-3-5-sonnet-latest")
async def get_authors(count: int = 3) -> list[str]:
    """Provide famous authors."""

print(await get_authors())

# ['William Shakespeare', 'J.K. Rowling', 'Jane Austen']

Underneath, Rigging will produce a Generator with get_generator("claude-3-5-sonnet-latest"), prepare a small template that will establish the required context and output structure, pass it into a new ChatPipeline, run the generation process, and parse the output into our structured list with ChatPipeline.then().

If you want to see the resulting Chat object, you can set that as your return value and no output parsing

@rg.prompt(generator_id="claude-3-5-sonnet-latest")
async def get_authors(count: int = 3) -> rg.Chat:
    ...

Now the prompt is only responsible for abstracting the generator, pipeline, and content for you. You can also use a nested object like a tuple and include both your structured data and the Chat object.

@rg.prompt(generator_id="claude-3-5-sonnet-latest")
async def get_authors(count: int = 3) -> tuple[list[str], rg.Chat]:
    """Provide famous authors."""

This will return a tuple with the parsed output as the first element and the raw Chat object as the second element.

You can learn more about the @prompt decorator in the Prompt Functions section.

Using Pipelines

  1. Get a Generator object - usually with get_generator().
  2. Call generator.chat()to produce a ChatPipeline and ready it for generation.
  3. Call pipeline.run() to kick off generation and get your final Chat object.

ChatPipeline objects hold any messages waiting to be delivered to an LLM in exchange for a new response message. These objects are also where most of the power in rigging comes from. You’ll build a generation pipeline with options, parsing, callbacks, etc. After preparation, this pipeline is used to make a final Chat which holds all messages prior to generation (.prev) and after generation (.next).

You should think of ChatPipeline objects like the configurable pre-generation step with calls like .with_(), .apply(), .until(), .using(), etc. Once you call one of the many .run()functions, the generator is used to produce the next message (or many messages) based on the prior context and any constraints you have in place. Once you have a Chat object, the interaction is complete and you can inspect and operate on the messages.

Rigging supports both Chat objects (messages with roles in a conversation format), as well as raw text completions. While we use Chat objects in most of our examples, you can check out the Completions section to learn more about their feature parity.

We often use functional styling chaining as most of our utility functions return the object back to you.

chat = (
    await
    generator.chat(...)
    .using(...)  # tools
    .then(...)   # follow up functions
    .with_(...)  # generation params
    .run()
)

Learn more about the ChatPipeline object in the Pipelines section.