Flexible numeric extraction supporting both integers and floats with optional min/max constraints.
The answer is 42 [[number:value]]
Returns: value: 42 (int)
The price is $19.99 [[number:price]]
Returns: price: 19.99 (float)
Your score: 85 [[number:score|min=0,max=100]]
Returns: score: 85 (int)
Validation: Ensures the extracted value is between 0 and 100 (inclusive).
Test scores: 85, 92, 78, 95 [[number*:scores]]
Returns: scores: [85, 92, 78, 95] (list)
Ratings: 4.5, 3.8, 4.9 [[number*:ratings|min=0,max=5]]
Returns: ratings: [4.5, 3.8, 4.9] (list)
The general syntax for number extraction is:
[[number:varname|options]]
Or with quantifiers for lists:
[[number*:varname|options]]
[[number{n}:varname|options]]
[[number{min,max}:varname|options]]
min=X - Minimum value (e.g., min=0)max=Y - Maximum value (e.g., max=100)min=X,max=Y - Both constraints (e.g., min=0,max=100)required - Makes the field required and enforces strict validationValidation Behavior:
By default (required not specified):
None or cannot extract a number, returns None (no error)None (lenient mode)With required flag:
None, raises ValueErrorValueError (strict mode)* - Zero or more numbers (e.g., [[number*:values]])+ - One or more numbers (e.g., [[number+:values]])? - Zero or one number (e.g., [[number?:value]]){n} - Exactly n numbers (e.g., [[number{3}:rgb]]){min,max} - Between min and max numbers (e.g., [[number{2,5}:scores]]){min,} - At least min numbers (e.g., [[number{2,}:values]])See /Users/benwhalley/dev/struckdown/examples/13_number_extraction.sd for 15 practical examples.
LLM Extraction: The LLM extracts numeric values (int or float) from the text based on the prompt and hints provided in the constraints.
Type Selection: The response model accepts Union[int, float] for single values or List[Union[int, float]] for lists, allowing the LLM to choose the most appropriate type.
Post-Extraction Validation: After extraction, Python code validates that all values satisfy the min/max constraints. If any value is out of range, a ValueError is raised with a helpful error message.
Run the comprehensive test suite with:
uv run python examples/number_test_cases.py
Options:
--verbose or -v: Show detailed output for each test--stop-on-error or -x: Stop on first failureThe test suite includes 43 test cases covering:
required flag (strict validation)required flag (returns None for violations)Current Test Results: 43/43 passed (100% success rate)
struckdown/return_type_models.py - Contains number_response_model() factory functionstruckdown/__init__.py - Post-extraction validation logic (lines 374-413)Union Type: Using Union[int, float] allows the LLM to choose the most natural type for each value.
int TypeThe number type is more flexible than the existing int type:
| Feature | int |
number |
|---|---|---|
| Integers | ✓ | ✓ |
| Floats | ✗ | ✓ |
| Min/max constraints | ✗ | ✓ |
| Lists | ✗ | ✓ |
| Quantifiers | ✗ | ✓ |
The int type remains available for backward compatibility and cases where you specifically need an integer.
Q1 Revenue: $1,234,567.89
Q2 Revenue: $1,456,789.01
Extract quarterly revenues [[number*:revenues]]
Product: 4.7 out of 5 stars [[number:rating|min=0,max=5]]
Exam scores: 85, 92, 78, 95 [[number*:scores|min=0,max=100]]
Current: -12.5°C [[number:temp]]
Progress: 67.5% complete [[number:progress|min=0,max=100]]
If a value violates constraints, a ValueError is raised with a clear error message:
ValueError: Numeric value -10 for field 'score' is below minimum 0.0
ValueError: Numeric value 150 for field 'score' exceeds maximum 100.0
required FlagThe constraints are provided as hints to the LLM, and validation behavior depends on the required flag:
required not set)Give me a number greater than 10 [[number:mynum|max=10]]
The LLM will likely return a number > 10 (following the prompt), but since it violates max=10:
mynum = None (no error raised)None instead of raising errorsrequired flag)Give me a number greater than 10 [[number:mynum|max=10,required]]
With the required flag, constraint violations raise errors:
ValueError: Numeric value 11 for field 'mynum' exceeds maximum 10.0requiredrequired (default): For optional extractions where you want graceful handling
None instead of crashingrequired: When you need guaranteed valid data
This two-stage approach (hints + validation) ensures:
Potential improvements:
step=5 for multiples of 5)mean, std, outliers)