Skip to main content

Quaestionario

Intelligent questionnaire management for Python

Quaestionario is a powerful Python package for creating, managing, and analyzing questionnaires as directed acyclic graphs (DAGs). It provides a clean API for building complex surveys with conditional branching, multi-format support, and AI-powered analysis capabilities.


Features

Core Capabilities

  • 📊 DAG-based Structure - Questionnaires as weakly connected rooted directed acyclic graphs
  • ✅ Robust Validation - Type checking, range validation, and constraint enforcement
  • 🔀 Conditional Branching - Questions that appear based on previous answers
  • 🧠 AI-Powered Analysis - Path exploration, dependency tracking, and complexity metrics
  • 📝 Multi-Format Support - JSON, YAML, and QueCode (compact DSL)
  • 🔒 Type-Safe - Built on Pydantic v2 with full type hints
  • 🎯 LLM-Ready - Simple stateless API perfect for chatbots and conversational AI

Question Types

Support for 8 question types covering all common use cases:

  • Boolean (Yes/No)
  • Text (Short & Long)
  • Number
  • DateTime
  • Scale (with min/max/step)
  • Single Choice
  • Multi Choice

Quick Start

Installation

# Using pip
pip install -e .

# Using uv (recommended)
uv sync

Basic Usage

from quaestionario import Questionnaire, QuestionnaireAnalyzer, AnswerValidator

# Load a questionnaire (supports .json, .yaml, .qc)
from quaestionario import load_questionnaire
questionnaire = load_questionnaire("survey.yaml")

# Navigate through questions
analyzer = QuestionnaireAnalyzer(questionnaire)
answers = {}

while True:
    # Get next question
    next_q_id = analyzer.get_next_question(answers)
    if next_q_id is None:
        break  # Questionnaire complete

    question = questionnaire.get_question_by_id(next_q_id)

    # Validate answer
    validator = AnswerValidator()
    user_answer = get_user_input(question.text)

    result = validator.validate_answer(question, user_answer)
    if result.is_valid:
        answers[next_q_id] = user_answer
    else:
        print(f"Invalid: {result.errors[0]}")

print(f"Collected {len(answers)} answers!")

Format Support

Quaestionario supports three formats for defining questionnaires:

JSON

{
  "questionnaireId": "survey-v1",
  "startQuestion": "Q1",
  "questions": [
    {
      "id": "Q1",
      "type": "scale",
      "text": "How satisfied are you?",
      "min": 1,
      "max": 5
    }
  ]
}

YAML

questionnaireId: survey-v1
startQuestion: Q1
questions:
  - id: Q1
    type: scale
    text: How satisfied are you?
    min: 1
    max: 5

QueCode (Compact DSL)

quecode id="survey-v1" start=Q1

Q1 scale "How satisfied are you?"
  min 1
  max 5

QueCode is 35% smaller than YAML and 56% smaller than JSON!

All formats are fully interchangeable:

from quaestionario import convert_questionnaire

# Convert between formats
convert_questionnaire("input.yaml", "output.qc")
convert_questionnaire("input.json", "output.yaml")

LLM Integration

Quaestionario is designed for seamless integration with LLMs and conversational AI:

from quaestionario import Questionnaire, QuestionnaireAnalyzer

def next_question(schema: dict, answers: dict) -> dict:
    """Get next question - perfect for LLM function calling."""
    questionnaire = Questionnaire(**schema)
    analyzer = QuestionnaireAnalyzer(questionnaire)

    next_id = analyzer.get_next_question(answers)

    if next_id is None:
        return {"is_complete": True}

    question = questionnaire.get_question_by_id(next_id)
    return {
        "question_id": next_id,
        "question": {
            "text": question.text,
            "type": question.type,
            ...
        },
        "is_complete": False
    }

Why it works great for LLMs:

  • ✅ Stateless - just pass schema and current answers
  • ✅ JSON in/out - universal format
  • ✅ No session management needed
  • ✅ Automatic branching and validation
  • ✅ Clear error messages for user feedback

See examples/llm_tools_demo.py for complete examples.


Advanced Analysis

Quaestionario includes powerful AI-powered analysis capabilities:

from quaestionario import QuestionnaireAnalyzer

analyzer = QuestionnaireAnalyzer(questionnaire)

# Always required questions (appear in ALL paths)
required = analyzer.get_always_required_questions(answers)

# Optimal next questions (unblock the most dependencies)
optimal = analyzer.get_optimal_next_questions(answers, max_suggestions=3)

# Completion bounds
min_q, max_q = analyzer.get_completion_bounds(answers)
print(f"Between {min_q} and {max_q} questions remaining")

# Complexity metrics
complexity = analyzer.analyze_questionnaire_complexity()
print(f"Total questions: {complexity['total_questions']}")
print(f"Conditional questions: {complexity['conditional_questions']}")
print(f"Max depth: {complexity['max_depth']}")

# Simulate all possible paths
paths = analyzer.simulate_questionnaire_paths(max_paths=100)
print(f"Found {len(paths)} unique completion paths")

Architecture

Core Components

quaestionario/
├── models.py          # Pydantic models for questions and questionnaires
├── graph.py           # DAG validation and navigation
├── analyzer.py        # AI-powered path analysis
├── validation.py      # Answer validation
└── io/                # Multi-format import/export
    ├── json_format.py
    ├── yaml_format.py
    └── quecode_format.py

Key Concepts

Dual Navigation System:

  • default_next - Default next question
  • option.next - Option-specific navigation (takes precedence)

Conditional Logic:

  • Questions can have conditions based on previous answers
  • Supports operators: =, !=, <, <=, >, >=, contains, in, exists, etc.

Path-Aware Analysis:

  • Distinguishes between "reachable" and "always required"
  • Critical for understanding questionnaire completion requirements

See CLAUDE.md for detailed architecture documentation.


Examples

The examples/ directory contains comprehensive demonstrations:

Quick Start Examples

  • minimal_llm_example.py - 50-line minimal example
  • llm_tools_demo.py - Complete LLM integration demo
  • quick_start.py - Basic usage patterns

Feature Demonstrations

  • validation_demo.py - Answer validation examples
  • import_export_demo.py - Format conversion
  • quecode_demo.py - QueCode format guide
  • complete_workflow.py - Full interactive flow
  • interactive_flow.py - Step-by-step navigation

Sample Questionnaires

  • simple_survey.yaml - 3 questions, linear flow
  • athlete_habits.yaml - 17 questions, complex branching
  • product_recommendation.yaml - 8 questions, user-type routing
  • medical_screening.yaml - 13 questions, conditional logic

All samples available in .json, .yaml, and .qc formats!

Run Examples

# Minimal example (starts in seconds)
python examples/minimal_llm_example.py

# Full LLM tools demo
python examples/llm_tools_demo.py

# Validation demo
python examples/validation_demo.py

# Interactive questionnaire
python examples/interactive_flow.py

Documentation

Quick Reference Guides

  • examples/LLM_TOOLS_QUICK_START.md - LLM integration guide
  • examples/README_LLM_TOOLS.md - LLM tools overview
  • examples/QUECODE_GUIDE.md - QueCode format reference
  • examples/IMPORT_EXPORT_GUIDE.md - Format conversion guide
  • examples/IO_QUICK_REFERENCE.md - I/O API cheatsheet

Developer Documentation

  • CLAUDE.md - Project overview and architecture
  • schema.json - JSON schema definition
  • API Documentation - Inline docstrings throughout codebase

Development

Setup

# Clone and setup
git clone <repository-url>
cd Quaestionario
uv sync

# Or with pip
pip install -r requirements.txt

Testing

# Run all tests
python -m pytest tests/ -v

# Run without coverage
python -m pytest tests/ -v --no-cov

# Run specific test file
python -m pytest tests/test_models.py -v

# Run specific test
python -m pytest tests/test_models.py::test_basic_questionnaire_creation -v

Code Quality

# Format code
black quaestionario tests

# Sort imports
isort quaestionario tests

# Type check
mypy quaestionario

Build

# Build package
python -m build

# Install in development mode
pip install -e .

Use Cases

Quaestionario is perfect for:

  • 🤖 Chatbots & Conversational AI - LLM-friendly stateless API
  • 📋 Survey Platforms - Complex branching logic and validation
  • 🏥 Medical Screening - Conditional questions based on symptoms
  • 🎯 Product Recommendations - User profiling with dynamic paths
  • 📊 Research Studies - Multi-format export and analysis
  • 🔧 Form Builders - Type-safe schema validation
  • 🎤 Voice Assistants - Clean Q&A flow with validation

Requirements

  • Python 3.13+ (uses modern type hints)
  • Pydantic 2.0+ (for data validation)
  • PyYAML (for YAML support)

See requirements.txt for complete dependencies.


Project Status

Quaestionario is actively developed and feature-complete for core functionality:

  • ✅ All question types implemented
  • ✅ DAG validation and navigation
  • ✅ Multi-format support (JSON, YAML, QueCode)
  • ✅ Answer validation
  • ✅ AI-powered analysis
  • ✅ Comprehensive test coverage
  • ✅ LLM integration examples
  • ✅ Full documentation

Contributing

Contributions are welcome! Areas for contribution:

  • Additional question types
  • More analysis algorithms
  • Format converters for other systems
  • Documentation improvements
  • Example questionnaires
  • Bug reports and fixes

License

[Add your license here - e.g., MIT, Apache 2.0, etc.]


Related Projects

  • Pydantic - Data validation library
  • PyYAML - YAML parser for Python

Support

  • Examples: See examples/ directory
  • Documentation: Check CLAUDE.md and inline docstrings
  • Issues: [Report issues on GitHub]
  • Questions: [Add contact method or discussion forum]

Built with ❤️ for creating intelligent questionnaires

Release files for quaestionario 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for quaestionario 0.1.0
File Size Uploaded
quaestionario-0.1.0.tar.gz 37.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for quaestionario 0.1.0
File Interpreter ABI Platform
quaestionario-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 65.3 kB

Release files / quaestionario-0.1.0.tar.gz

Download URL quaestionario-0.1.0.tar.gz
Size 37.9 kB
Tags Source
SHA-256 checksum
How to use checksums
de266f299c52db05a1a17bd28d807652a1c50014b235f5c3e61170b8b121d567
BLAKE2b-256 checksum
How to use checksums
34645a66f9d0f9f656f55e661eacc3ffe01871552680b2d863680a1f4ee03338
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / quaestionario-0.1.0-py3-none-any.whl

Download URL quaestionario-0.1.0-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c73196289735a2befc34d1d3fa063033b9ee787bbfab6f8ab23244df841c269f
BLAKE2b-256 checksum
How to use checksums
164156aebf980e67fa1b82ae5ab2495b30f4aaf391bfd27aea41aea934ba02e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page