Skip to main content

Overview

The ResponseGenerator class creates natural language responses from retrieved document sections. It extracts key information and includes inline citations with section titles and page numbers.

Class Definition

class ResponseGenerator:
    def generate(self, sections: List[Dict]) -> str

Methods

generate

Generates a response from document sections with inline citations.
def generate(self, sections: List[Dict]) -> str
sections
List[Dict]
required
Retrieved document sections from AgenticRetriever.retrieve(). Each section should contain:
title
str
Section title
content
str
Section content text
page_num
int
Page number where section appears
Returns: A string containing the generated response with inline citations.

Example

generator = ResponseGenerator()

sections = [
    {
        "title": "Late Payment Penalties",
        "content": "A late fee of 1.5% per month (18% annually) will apply to any outstanding balance not paid within 30 days of invoice receipt.",
        "page_num": 5
    },
    {
        "title": "Payment Terms",
        "content": "Payment is due within 30 days of invoice receipt. Invoices will be sent on the first business day of each month.",
        "page_num": 4
    }
]

response = generator.generate(sections)
print(response)
Output:
A late fee of 1.5% per month (18% annually) will apply to any outstanding balance not paid within 30 days of invoice receipt. (See Late Payment Penalties, page 5) Payment is due within 30 days of invoice receipt. (See Payment Terms, page 4)

Response Generation Strategy

The generator follows a simple but effective approach:
  1. Empty Check: Returns fallback message if no sections provided
  2. Key Info Extraction: Extracts the first sentence from each section
  3. Citation Addition: Appends inline citation with section title and page number
  4. Concatenation: Joins all parts with spaces

Fallback Handling

When no sections are provided:
if not sections:
    return "No relevant information found in the documents."

Key Information Extraction

Extracts the first sentence (or first 200 characters as fallback):
sentences = re.split(r'(?<=[.!?])\s+', content)
key_info = sentences[0] if sentences else content[:200]
Sentence Splitting Pattern: r'(?<=[.!?])\s+'
  • Splits on periods, exclamation marks, or question marks
  • Preserves the punctuation in the sentence
  • Requires whitespace after punctuation

Citation Format

Inline citations follow this format:
{key_info} (See {title}, page {page_num})
Example citations:
  • (See Late Payment Penalties, page 5)
  • (See Intellectual Property Rights, page 12)
  • (See Termination for Convenience, page 8)

Implementation Details

Full Source Code

def generate(self, sections: List[Dict]) -> str:
    if not sections:
        return "No relevant information found in the documents."
    
    response_parts = []
    
    for section in sections:
        title = section.get("title", "Unknown")
        page = section.get("page_num", "?")
        content = section.get("content", "")
        
        sentences = re.split(r'(?<=[.!?])\s+', content)
        key_info = sentences[0] if sentences else content[:200]
        
        response_parts.append(f"{key_info} (See {title}, page {page})")
    
    response = " ".join(response_parts)
    return response

Usage Examples

Example 1: Payment Query

from components import ResponseGenerator

generator = ResponseGenerator()

sections = [
    {
        "title": "Payment Terms",
        "content": "Payment is due within 30 days of invoice receipt. Invoices are sent monthly.",
        "page_num": 4
    }
]

response = generator.generate(sections)
# "Payment is due within 30 days of invoice receipt. (See Payment Terms, page 4)"

Example 2: Multiple Sections

sections = [
    {
        "title": "Scope of Services",
        "content": "The Vendor shall provide software development services. Services include design, coding, and testing.",
        "page_num": 2
    },
    {
        "title": "Deliverables",
        "content": "All deliverables must meet the specifications outlined in Exhibit A. Testing documentation is required.",
        "page_num": 3
    }
]

response = generator.generate(sections)
# "The Vendor shall provide software development services. (See Scope of Services, page 2) All deliverables must meet the specifications outlined in Exhibit A. (See Deliverables, page 3)"

Example 3: No Sections

response = generator.generate([])
# "No relevant information found in the documents."

Example 4: Missing Fields

sections = [
    {
        "title": None,
        "content": "This section has missing metadata.",
        "page_num": None
    }
]

response = generator.generate(sections)
# "This section has missing metadata. (See Unknown, page ?)"

Design Philosophy

Conciseness

Extracts only the first sentence to provide focused, relevant information without overwhelming the user.

Transparency

Every statement includes a citation showing exactly where the information came from.

Verifiability

Page numbers enable users to quickly locate and verify information in source documents.

Simplicity

No LLM calls or complex synthesis—just direct extraction and formatting for maximum reliability.

Integration

The generator sits between the retriever and the judge in the RAG pipeline:
from components import QueryDecomposer, AgenticRetriever, ResponseGenerator, LLMJudge
from mock_data import MockDocumentStore

# Initialize pipeline
decomposer = QueryDecomposer()
doc_store = MockDocumentStore()
retriever = AgenticRetriever(doc_store)
generator = ResponseGenerator()  # <- ResponseGenerator
judge = LLMJudge()

# Process query
query = "What are the payment terms?"
decomposition = await decomposer.decompose(query)
sections = await retriever.retrieve(query, decomposition)
response = generator.generate(sections)  # <- Generate response
verdict = await judge.evaluate(response, sections)

if verdict["should_return"]:
    print(response)

Performance Characteristics

  • Synchronous: No async operations required
  • Fast: Simple string operations and regex
  • Deterministic: Same sections always produce same response
  • No API calls: No dependency on external LLM services
  • Extraction-based: Uses source text directly (no generation)

Comparison with LLM-Based Generation

FeatureResponseGeneratorLLM-Based
SpeedFast (under 1ms)Slow (100-1000ms)
CostFree$$ per request
ReliabilityDeterministicStochastic
Hallucination RiskLow (extraction)High (generation)
SynthesisNoneAdvanced
CitationsAlways includedOften missing
The ResponseGenerator trades synthesis capability for reliability, transparency, and speed. For applications where accuracy is paramount, extraction-based generation is often preferable to LLM-based synthesis.

Build docs developers (and LLMs) love