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 questionoption.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 examplellm_tools_demo.py- Complete LLM integration demoquick_start.py- Basic usage patterns
Feature Demonstrations
validation_demo.py- Answer validation examplesimport_export_demo.py- Format conversionquecode_demo.py- QueCode format guidecomplete_workflow.py- Full interactive flowinteractive_flow.py- Step-by-step navigation
Sample Questionnaires
simple_survey.yaml- 3 questions, linear flowathlete_habits.yaml- 17 questions, complex branchingproduct_recommendation.yaml- 8 questions, user-type routingmedical_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 guideexamples/README_LLM_TOOLS.md- LLM tools overviewexamples/QUECODE_GUIDE.md- QueCode format referenceexamples/IMPORT_EXPORT_GUIDE.md- Format conversion guideexamples/IO_QUICK_REFERENCE.md- I/O API cheatsheet
Developer Documentation
CLAUDE.md- Project overview and architectureschema.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.mdand inline docstrings - Issues: [Report issues on GitHub]
- Questions: [Add contact method or discussion forum]
Built with ❤️ for creating intelligent questionnaires
Metadata
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)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| quaestionario-0.1.0.tar.gz | 37.9 kB | Without provenance | Details for quaestionario-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| quaestionario-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for quaestionario-0.1.0-py3-none-any.whl |
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
|
Security for quaestionario 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.