Skip to main content

Tactus

Standard Library / Generate Module

Generate Module

  • 4 specs
  • 2 classes

The `tactus.generate` module provides flexible text generation built on DSPy's modular architecture.

The tactus.generate module provides flexible text generation built on DSPy's modular architecture.

Overview

All generators extend BaseGenerator and share a common interface. The module supports multiple output formats and optional chain-of-thought reasoning via DSPy's native modules.

DSPy Module Integration

The generator uses DSPy's module system under the hood:

Mode DSPy Module Behavior
Default Raw No prompt modifications - passes your system prompt and user message directly to the LLM without any DSPy formatting
reasoning = true ChainOfThought Uses DSPy's native reasoning module - automatically adds step-by-step thinking

Why Raw Mode by Default?

Even DSPy's basic Predict module adds formatting delimiters (like [[ ## response ## ]]) to prompts. The Raw module bypasses all DSPy prompt modifications, giving you:

  • Clean prompts: Your system prompt goes to the LLM exactly as written
  • Predictable output: No unexpected formatting in responses
  • Full control: You decide what goes in the prompt

When to Use ChainOfThought

Enable reasoning = true when you want the model to:

  • Show its work on math problems
  • Explain multi-step reasoning
  • Provide transparent decision-making

The reasoning is captured separately from the final answer, so you can access both.

Output Formats

Format Description
text Plain text output (default)
json JSON-formatted response with validation
markdown Markdown-formatted response

Architecture

The module uses a proper Lua class hierarchy:

  • BaseGenerator - Abstract base with common interface
  • LLMGenerator - LLM-powered generation with all options

All generators return a consistent result format:

{
    output = "The generated text...",    -- Main output (final answer)
    reasoning = "Step-by-step...",       -- Reasoning steps (only if reasoning=true)
    format = "text",                     -- Format used
    retry_count = 0,                     -- Number of retries needed
    raw_response = "...",                -- Raw LLM response
    error = nil                          -- Error message if failed
}

Loading the Module

-- Load the main module
local generate = require("tactus.generate")

-- Or load specific generators (dependencies auto-load)
local LLMGenerator = require("tactus.generate.llm")

Examples

Basic Text Generation (Raw Mode)

By default, your prompt goes directly to the LLM without modification:

local generator = LLMGenerator:new {
    model = "openai/gpt-4o-mini"
}
local result = generator:generate("Write a haiku about programming")
print(result.output)

Chain-of-Thought Reasoning

Enable reasoning = true to use DSPy's ChainOfThought module. The reasoning is captured in a separate field:

local generator = LLMGenerator:new {
    model = "openai/gpt-4o-mini",
    reasoning = true
}
local result = generator:generate("What is 15% of 240?")

-- Access both the reasoning and the final answer
print("Reasoning:", result.reasoning)  -- "15% means 15/100 = 0.15. So 0.15 × 240 = 36"
print("Answer:", result.output)        -- "36"

JSON Output Format

local generator = LLMGenerator:new {
    model = "openai/gpt-4o-mini",
    output_format = "json"
}
local result = generator:generate("Return a JSON object with name, age, and city for a fictional person")
-- result.output will be valid JSON like: {"name": "Alice", "age": 28, "city": "Portland"}

Custom System Prompt

Your system prompt is passed directly to the LLM (no DSPy modifications):

local generator = LLMGenerator:new {
    model = "openai/gpt-4o-mini",
    system_prompt = "You are a helpful coding assistant specializing in Lua.",
    temperature = 0.3
}
local result = generator:generate("How do I iterate over a table in Lua?")

With Constraints

local generator = LLMGenerator:new {
    model = "openai/gpt-4o-mini",
    constraints = {"Keep response under 50 words", "Use simple language"}
}
local result = generator:generate("Explain quantum computing")

Parameters Reference

Parameter Type Default Description
model string required Model identifier (e.g., "openai/gpt-4o-mini")
temperature number 0.7 Generation randomness (0.0-1.0)
max_tokens number nil Maximum output tokens
reasoning boolean false Enable ChainOfThought mode (captures reasoning separately)
output_format string "text" Output format: "text", "json", "markdown"
system_prompt string nil Custom system prompt (passed directly, no modifications)
instructions string nil Additional generation instructions
constraints `string table` nil
max_retries number 2 Maximum retry attempts

Result Fields

Field Type Description
output string The main generated output (final answer)
reasoning string? Step-by-step reasoning (only when reasoning = true)
format string The output format used
retry_count number Number of retries that were needed
raw_response string The raw response from the LLM
error string? Error message if generation failed

Future Enhancements

Planned DSPy-inspired features:

  • Few-shot examples: Pass examples for in-context learning
  • Optimizers: Automatic prompt optimization with training data
  • Assertions: Output validation with automatic retry
  • Parallel generation: Multiple completions with selection

Extending Generators

You can extend BaseGenerator to create custom generators:

local base = require("tactus.generate.base")
local class = base.class
local BaseGenerator = base.BaseGenerator

MyGenerator = class(BaseGenerator)

function MyGenerator:init(config)
    BaseGenerator.init(self, config)
    -- Your initialization
end

function MyGenerator:generate(prompt)
    -- Your generation logic
    return {
        output = "...",
        format = self.output_format,
        retry_count = 0
    }
end

Classes

Quick Start

Load the module:

local generate = require("tactus.generate")

Run the specs:

tactus test tactus/stdlib/tac/tactus/generate.spec.tac

View source on GitHub →

Explore more modules

The standard library includes modules for classification, extraction, generation, and more.

View All Modules