quaestionario 0.1.0
A Python package for managing questionnaires as weakly connected rooted directed acyclic graphs
License: MIT
Requires Python: >=3.12

# 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

```bash
# Using pip
pip install -e .

# Using uv (recommended)
uv sync
```

### Basic Usage

```python
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
```json
{
  "questionnaireId": "survey-v1",
  "startQuestion": "Q1",
  "questions": [
    {
      "id": "Q1",
      "type": "scale",
      "text": "How satisfied are you?",
      "min": 1,
      "max": 5
    }
  ]
}
```

### YAML
```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:

```python
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:

```python
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:

```python
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

```bash
# 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

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

# Or with pip
pip install -r requirements.txt
```

### Testing

```bash
# 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

```bash
# Format code
black quaestionario tests

# Sort imports
isort quaestionario tests

# Type check
mypy quaestionario
```

### Build

```bash
# 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**