outputguard 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- outputguard-0.2.0/.github/workflows/ci.yml +84 -0
- outputguard-0.2.0/.gitignore +8 -0
- outputguard-0.2.0/.python-version +1 -0
- outputguard-0.2.0/CHANGELOG.md +38 -0
- outputguard-0.2.0/CONTRIBUTING.md +89 -0
- outputguard-0.2.0/LICENSE +21 -0
- outputguard-0.2.0/MARKETING.md +330 -0
- outputguard-0.2.0/PKG-INFO +395 -0
- outputguard-0.2.0/PROMPT.md +467 -0
- outputguard-0.2.0/README.md +366 -0
- outputguard-0.2.0/SPEC.md +210 -0
- outputguard-0.2.0/examples/README.md +20 -0
- outputguard-0.2.0/examples/basic_usage.py +41 -0
- outputguard-0.2.0/examples/batch_processing.py +90 -0
- outputguard-0.2.0/examples/custom_pipeline.py +65 -0
- outputguard-0.2.0/examples/retry_loop.py +69 -0
- outputguard-0.2.0/outputguard/__init__.py +53 -0
- outputguard-0.2.0/outputguard/cli.py +227 -0
- outputguard-0.2.0/outputguard/exceptions.py +38 -0
- outputguard-0.2.0/outputguard/guard.py +91 -0
- outputguard-0.2.0/outputguard/models.py +29 -0
- outputguard-0.2.0/outputguard/py.typed +0 -0
- outputguard-0.2.0/outputguard/repairer.py +102 -0
- outputguard-0.2.0/outputguard/report.py +110 -0
- outputguard-0.2.0/outputguard/retry.py +84 -0
- outputguard-0.2.0/outputguard/strategies/__init__.py +69 -0
- outputguard-0.2.0/outputguard/strategies/extract_json.py +48 -0
- outputguard-0.2.0/outputguard/strategies/fix_booleans.py +34 -0
- outputguard-0.2.0/outputguard/strategies/fix_closers.py +42 -0
- outputguard-0.2.0/outputguard/strategies/fix_commas.py +12 -0
- outputguard-0.2.0/outputguard/strategies/fix_ellipsis.py +106 -0
- outputguard-0.2.0/outputguard/strategies/fix_inner_quotes.py +87 -0
- outputguard-0.2.0/outputguard/strategies/fix_keys.py +44 -0
- outputguard-0.2.0/outputguard/strategies/fix_newlines.py +58 -0
- outputguard-0.2.0/outputguard/strategies/fix_quotes.py +61 -0
- outputguard-0.2.0/outputguard/strategies/fix_truncated.py +116 -0
- outputguard-0.2.0/outputguard/strategies/fix_unicode.py +131 -0
- outputguard-0.2.0/outputguard/strategies/fix_values.py +39 -0
- outputguard-0.2.0/outputguard/strategies/remove_comments.py +55 -0
- outputguard-0.2.0/outputguard/strategies/strip_fences.py +18 -0
- outputguard-0.2.0/outputguard/validator.py +56 -0
- outputguard-0.2.0/pyproject.toml +65 -0
- outputguard-0.2.0/tests/__init__.py +0 -0
- outputguard-0.2.0/tests/all_model_ids.json +307 -0
- outputguard-0.2.0/tests/conftest.py +38 -0
- outputguard-0.2.0/tests/fetch_all_models.py +66 -0
- outputguard-0.2.0/tests/fixtures/nested_schema.json +25 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/ai21__jamba-large-1.7__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/aion-labs__aion-1.0-mini__simple_object.txt +18 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/aion-labs__aion-1.0__simple_object.txt +19 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/aion-labs__aion-2.0__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/aion-labs__aion-rp-llama-3.1-8b__simple_object.txt +9 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/alibaba__tongyi-deepresearch-30b-a3b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/alpindale__goliath-120b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/amazon__nova-2-lite-v1__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/amazon__nova-lite-v1__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/amazon__nova-micro-v1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/amazon__nova-premier-v1__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/amazon__nova-pro-v1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthracite-org__magnum-v4-72b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3-haiku__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.5-haiku__boolean_fields.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.5-haiku__enum_values.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.5-haiku__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.5-haiku__nested_array.txt +20 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.5-haiku__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.7-sonnet-thinking__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-3.7-sonnet__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-haiku-4.5__boolean_fields.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-haiku-4.5__enum_values.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-haiku-4.5__large_response.txt +64 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-haiku-4.5__nested_array.txt +22 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-haiku-4.5__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4.1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4.6-fast__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4.6__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4.7__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-opus-4__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.6__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.6__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.6__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.6__nested_array.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4.6__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4__boolean_fields.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4__enum_values.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4__nested_array.txt +20 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/anthropic__claude-sonnet-4__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/arcee-ai__trinity-large-preview__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/arcee-ai__trinity-large-thinking__simple_object.txt +2 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/arcee-ai__trinity-mini__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/baidu__ernie-4.5-300b-a47b__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/baidu__ernie-4.5-vl-424b-a47b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/bytedance-seed__seed-1.6-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/bytedance-seed__seed-1.6__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/bytedance-seed__seed-2.0-lite__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/bytedance-seed__seed-2.0-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/cohere__command-a__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/cohere__command-r-08-2024__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/cohere__command-r-plus-08-2024__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/cohere__command-r7b-12-2024__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepcogito__cogito-v2.1-671b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3-0324__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3.1__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3.1__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3.1__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3.1__nested_array.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat-v3.1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat__boolean_fields.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat__enum_values.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat__large_response.txt +14 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat__nested_array.txt +22 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-chat__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-r1-0528__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-r1-distill-llama-70b__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-r1-distill-qwen-32b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-r1__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.1-terminus__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2-exp__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2-speciale__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2__boolean_fields.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2__enum_values.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2__nested_array.txt +13 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v3.2__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v4-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/deepseek__deepseek-v4-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/essentialai__rnj-1-instruct__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.0-flash-001__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.0-flash-lite-001__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash-lite-preview-09-2025__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash-lite__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash__nested_array.txt +22 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-pro-preview-05-06__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-pro-preview__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-2.5-pro__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-3-flash-preview__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-3.1-flash-lite-preview__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-3.1-flash-lite__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemini-3.1-pro-preview__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-2-27b-it__simple_object.txt +2 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-3-12b-it__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-3-27b-it__simple_object.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-3-4b-it__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-3n-e4b-it__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-4-26b-a4b-it__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/google__gemma-4-31b-it__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/gryphe__mythomax-l2-13b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/ibm-granite__granite-4.0-h-micro__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/ibm-granite__granite-4.1-8b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/inception__mercury-2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/inclusionai__ling-2.6-1t__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/inclusionai__ling-2.6-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/inflection__inflection-3-pi__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/inflection__inflection-3-productivity__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/kwaipilot__kat-coder-pro-v2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/liquid__lfm-2-24b-a2b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mancer__weaver__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3-70b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3-8b-instruct__simple_object.txt +4 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-70b-instruct__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-8b-instruct__boolean_fields.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-8b-instruct__enum_values.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-8b-instruct__large_response.txt +14 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-8b-instruct__nested_array.txt +20 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.1-8b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.2-11b-vision-instruct__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.2-1b-instruct__simple_object.txt +4 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.2-3b-instruct__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.3-70b-instruct__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.3-70b-instruct__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.3-70b-instruct__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.3-70b-instruct__nested_array.txt +22 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-3.3-70b-instruct__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-maverick__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-scout__boolean_fields.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-scout__enum_values.txt +11 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-scout__large_response.txt +14 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-scout__nested_array.txt +13 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/meta-llama__llama-4-scout__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/microsoft__phi-4-mini-instruct__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/microsoft__phi-4__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/microsoft__wizardlm-2-8x22b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m2-her__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m2.1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m2.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m2.7__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/minimax__minimax-m2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__codestral-2508__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__devstral-2512__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__devstral-medium__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__devstral-small__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__ministral-14b-2512__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__ministral-3b-2512__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__ministral-8b-2512__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-7b-instruct-v0.1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-large-2407__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-large-2411__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-large-2512__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-large__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3-5__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3-5__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3-5__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3-5__nested_array.txt +11 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3-5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3.1__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-medium-3__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-nemo__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-saba__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-small-24b-instruct-2501__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-small-2603__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-small-3.1-24b-instruct__simple_object.txt +4 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mistral-small-3.2-24b-instruct__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__mixtral-8x22b-instruct__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__pixtral-large-2411__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/mistralai__voxtral-small-24b-2507__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/moonshotai__kimi-k2-0905__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/moonshotai__kimi-k2-thinking__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/moonshotai__kimi-k2.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/moonshotai__kimi-k2.6__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/moonshotai__kimi-k2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/morph__morph-v3-fast__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/morph__morph-v3-large__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nex-agi__deepseek-v3.1-nex-n1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nousresearch__hermes-2-pro-llama-3-8b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nousresearch__hermes-3-llama-3.1-405b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nousresearch__hermes-3-llama-3.1-70b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nousresearch__hermes-4-405b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nousresearch__hermes-4-70b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nvidia__llama-3.3-nemotron-super-49b-v1.5__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nvidia__nemotron-3-nano-30b-a3b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nvidia__nemotron-3-super-120b-a12b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/nvidia__nemotron-nano-9b-v2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-3.5-turbo-0613__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-3.5-turbo-16k__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-3.5-turbo-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-3.5-turbo__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4-turbo__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-mini__boolean_fields.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-mini__enum_values.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-mini__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-mini__nested_array.txt +20 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-mini__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1-nano__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4.1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-2024-05-13__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-2024-08-06__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-2024-11-20__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini-2024-07-18__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini__boolean_fields.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini__enum_values.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini__nested_array.txt +20 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o-mini__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-4o__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-chat__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-codex__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-mini__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-mini__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-mini__large_response.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-mini__nested_array.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-nano__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.1-chat__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.1-codex-max__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.1-codex-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.1-codex__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.2-chat__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.2-codex__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.2-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.2__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.3-chat__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.3-codex__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.4-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.4-nano__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.4-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.4__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.5-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-5__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-chat-latest__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-oss-120b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__gpt-oss-20b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o1-pro__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o3-mini-high__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o3-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o3-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o3__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o4-mini-high__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/openai__o4-mini__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/perplexity__sonar-pro-search__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/perplexity__sonar-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/perplexity__sonar-reasoning-pro__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/perplexity__sonar__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/prime-intellect__intellect-3__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-72b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-7b-instruct__boolean_fields.txt +6 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-7b-instruct__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-7b-instruct__large_response.txt +62 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-7b-instruct__nested_array.txt +22 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-7b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-2.5-coder-32b-instruct__simple_object.txt +3 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-max__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-plus-2025-07-28-thinking__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-plus-2025-07-28__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-plus__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-turbo__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-vl-max__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen-vl-plus__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen2.5-vl-72b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-14b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-235b-a22b-2507__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-235b-a22b-thinking-2507__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-235b-a22b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-30b-a3b-instruct-2507__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-30b-a3b-thinking-2507__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-30b-a3b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-32b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-8b__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-8b__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-8b__large_response.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-8b__nested_array.txt +11 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-8b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-coder-30b-a3b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-coder-flash__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-coder-next__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-coder-plus__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-coder__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-max-thinking__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-max__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-next-80b-a3b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-next-80b-a3b-thinking__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-235b-a22b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-235b-a22b-thinking__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-30b-a3b-instruct__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-30b-a3b-thinking__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-32b-instruct__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-8b-instruct__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3-vl-8b-thinking__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-122b-a10b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-27b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-35b-a3b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-9b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-flash-02-23__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-plus-02-15__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.5-plus-20260420__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-27b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-35b-a3b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-flash__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-flash__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-flash__large_response.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-flash__nested_array.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-max-preview__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/qwen__qwen3.6-plus__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/rekaai__reka-edge__simple_object.txt +8 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/rekaai__reka-flash-3__simple_object.txt +9 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sao10k__l3-euryale-70b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sao10k__l3-lunaris-8b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sao10k__l3.1-70b-hanami-x1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sao10k__l3.1-euryale-70b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sao10k__l3.3-euryale-70b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/stepfun__step-3.5-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/summary.json +583 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/sweep_results.json +2164 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/tencent__hunyuan-a13b-instruct__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/tencent__hy3-preview__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/thedrummer__cydonia-24b-v4.1__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/thedrummer__rocinante-12b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/thedrummer__skyfall-36b-v2__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/thedrummer__unslopnemo-12b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/undi95__remm-slerp-l2-13b__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/writer__palmyra-x5__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-3-beta__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-3-mini-beta__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-3-mini__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-3__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4-fast__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.1-fast__boolean_fields.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.1-fast__enum_values.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.1-fast__large_response.txt +12 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.1-fast__nested_array.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.1-fast__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.20__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4.3__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-4__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/x-ai__grok-code-fast-1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/xiaomi__mimo-v2-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/xiaomi__mimo-v2-omni__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/xiaomi__mimo-v2-pro__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/xiaomi__mimo-v2.5-pro__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/xiaomi__mimo-v2.5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4-32b__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.5-air__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.5__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.5v__simple_object.txt +2 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.6__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.6v__simple_object.txt +7 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.7-flash__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-4.7__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-5-turbo__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-5.1__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-5__simple_object.txt +1 -0
- outputguard-0.2.0/tests/fixtures/real_outputs/z-ai__glm-5v-turbo__simple_object.txt +5 -0
- outputguard-0.2.0/tests/fixtures/simple_schema.json +9 -0
- outputguard-0.2.0/tests/real_model_runner.py +382 -0
- outputguard-0.2.0/tests/test_adversarial.py +787 -0
- outputguard-0.2.0/tests/test_api_contracts.py +985 -0
- outputguard-0.2.0/tests/test_cli.py +128 -0
- outputguard-0.2.0/tests/test_combinations.py +626 -0
- outputguard-0.2.0/tests/test_edge_cases.py +328 -0
- outputguard-0.2.0/tests/test_exceptions.py +55 -0
- outputguard-0.2.0/tests/test_guard.py +78 -0
- outputguard-0.2.0/tests/test_integration.py +148 -0
- outputguard-0.2.0/tests/test_llm_corpus.py +1147 -0
- outputguard-0.2.0/tests/test_real_models.py +261 -0
- outputguard-0.2.0/tests/test_repairer.py +35 -0
- outputguard-0.2.0/tests/test_report.py +107 -0
- outputguard-0.2.0/tests/test_retry.py +35 -0
- outputguard-0.2.0/tests/test_strategies/__init__.py +0 -0
- outputguard-0.2.0/tests/test_strategies/test_extract_json.py +26 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_booleans.py +30 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_closers.py +18 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_commas.py +21 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_ellipsis.py +40 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_keys.py +24 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_newlines.py +15 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_quotes.py +18 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_truncated.py +49 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_unicode.py +33 -0
- outputguard-0.2.0/tests/test_strategies/test_fix_values.py +24 -0
- outputguard-0.2.0/tests/test_strategies/test_remove_comments.py +25 -0
- outputguard-0.2.0/tests/test_strategies/test_strip_fences.py +27 -0
- outputguard-0.2.0/tests/test_strategy_exhaustive.py +895 -0
- outputguard-0.2.0/tests/test_stress.py +477 -0
- outputguard-0.2.0/tests/test_validator.py +60 -0
- outputguard-0.2.0/uv.lock +753 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main, master]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
20
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v4
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
run: uv python install ${{ matrix.python-version }}
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: uv sync --dev
|
|
30
|
+
- name: Run tests
|
|
31
|
+
run: uv run pytest tests/ -v --tb=short --cov=outputguard --cov-report=term-missing
|
|
32
|
+
|
|
33
|
+
lint:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- name: Install uv
|
|
38
|
+
uses: astral-sh/setup-uv@v4
|
|
39
|
+
- name: Set up Python
|
|
40
|
+
run: uv python install 3.12
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --dev
|
|
43
|
+
- name: Check formatting
|
|
44
|
+
run: uv run ruff format --check .
|
|
45
|
+
- name: Lint
|
|
46
|
+
run: uv run ruff check .
|
|
47
|
+
- name: Type check
|
|
48
|
+
run: uv run mypy outputguard/ --ignore-missing-imports
|
|
49
|
+
|
|
50
|
+
build:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
- name: Install uv
|
|
55
|
+
uses: astral-sh/setup-uv@v4
|
|
56
|
+
- name: Set up Python
|
|
57
|
+
run: uv python install 3.12
|
|
58
|
+
- name: Build package
|
|
59
|
+
run: uv build
|
|
60
|
+
- name: Verify dist contents
|
|
61
|
+
run: ls -la dist/
|
|
62
|
+
- name: Upload build artifacts
|
|
63
|
+
uses: actions/upload-artifact@v4
|
|
64
|
+
with:
|
|
65
|
+
name: dist
|
|
66
|
+
path: dist/
|
|
67
|
+
|
|
68
|
+
publish:
|
|
69
|
+
needs: [test, lint, build]
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
72
|
+
permissions:
|
|
73
|
+
id-token: write
|
|
74
|
+
environment:
|
|
75
|
+
name: pypi
|
|
76
|
+
url: https://pypi.org/project/outputguard/
|
|
77
|
+
steps:
|
|
78
|
+
- name: Download build artifacts
|
|
79
|
+
uses: actions/download-artifact@v4
|
|
80
|
+
with:
|
|
81
|
+
name: dist
|
|
82
|
+
path: dist/
|
|
83
|
+
- name: Publish to PyPI
|
|
84
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.10
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - Unreleased
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `fix_truncated` strategy: recovers JSON truncated by token limits
|
|
12
|
+
- `fix_ellipsis` strategy: replaces `...` placeholders with valid JSON
|
|
13
|
+
- `fix_unicode` strategy: fixes malformed Unicode escape sequences
|
|
14
|
+
- `fix_booleans` strategy: converts Python True/False/None to JSON true/false/null
|
|
15
|
+
- `parse()` convenience function: validate-repair-parse in one call, raises on failure
|
|
16
|
+
- `OutputGuard.parse()` method with same behavior
|
|
17
|
+
- Exception hierarchy: `OutputGuardError`, `ParseError`, `SchemaValidationError`, `RepairError`
|
|
18
|
+
- `RepairReport` with diff output, confidence scoring, and step-by-step strategy tracking
|
|
19
|
+
- `--diff` flag for CLI validate and repair commands
|
|
20
|
+
- `--verbose` flag for CLI showing each strategy's effect
|
|
21
|
+
- Strategy descriptions shown in `outputguard strategies` table
|
|
22
|
+
- GitHub Actions CI (Python 3.10-3.13, Linux/macOS/Windows)
|
|
23
|
+
- `py.typed` marker for PEP 561
|
|
24
|
+
- Comprehensive edge-case test suite
|
|
25
|
+
- Examples directory with usage patterns
|
|
26
|
+
- CONTRIBUTING.md guide
|
|
27
|
+
|
|
28
|
+
## [0.1.0] - 2025-01-01
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Initial release
|
|
32
|
+
- 9 core repair strategies: strip_fences, extract_json, remove_comments, fix_commas, fix_quotes, fix_keys, fix_values, fix_closers, fix_newlines
|
|
33
|
+
- JSON Schema validation with detailed error paths
|
|
34
|
+
- Validate-and-repair pipeline
|
|
35
|
+
- Retry prompt generation for LLM feedback loops
|
|
36
|
+
- Click CLI with validate, repair, retry-prompt, and strategies commands
|
|
37
|
+
- Library API: validate(), repair(), validate_and_repair(), retry_prompt()
|
|
38
|
+
- Configurable OutputGuard class with strategy selection
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Contributing to outputguard
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Here's how to get started.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Clone the repository:
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/ndcorder/outputguard.git
|
|
10
|
+
cd outputguard
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Install [uv](https://docs.astral.sh/uv/):
|
|
14
|
+
```bash
|
|
15
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Install dependencies:
|
|
19
|
+
```bash
|
|
20
|
+
uv sync --dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
4. Run the tests:
|
|
24
|
+
```bash
|
|
25
|
+
uv run pytest tests/ -v
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Making Changes
|
|
29
|
+
|
|
30
|
+
1. Create a branch: `git checkout -b feat/my-feature`
|
|
31
|
+
2. Make your changes
|
|
32
|
+
3. Run the test suite: `uv run pytest tests/ -v`
|
|
33
|
+
4. Commit with a descriptive message: `git commit -m "feat: add xyz"`
|
|
34
|
+
|
|
35
|
+
## Adding a Repair Strategy
|
|
36
|
+
|
|
37
|
+
outputguard's architecture makes it easy to add new repair strategies:
|
|
38
|
+
|
|
39
|
+
1. Create `outputguard/strategies/your_strategy.py`:
|
|
40
|
+
```python
|
|
41
|
+
NAME = "your_strategy"
|
|
42
|
+
DESCRIPTION = "What this strategy does"
|
|
43
|
+
|
|
44
|
+
def apply(text: str) -> str:
|
|
45
|
+
# Your repair logic here
|
|
46
|
+
# MUST: return text unchanged if nothing to fix
|
|
47
|
+
# MUST: never raise exceptions
|
|
48
|
+
return text
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Register it in `outputguard/strategies/__init__.py`:
|
|
52
|
+
- Import your module
|
|
53
|
+
- Add `(your_strategy.NAME, your_strategy.apply)` to `ALL_STRATEGIES`
|
|
54
|
+
- Add the description to `STRATEGY_DESCRIPTIONS`
|
|
55
|
+
|
|
56
|
+
3. Create tests in `tests/test_strategies/test_your_strategy.py`
|
|
57
|
+
|
|
58
|
+
4. Run the full suite to make sure nothing breaks
|
|
59
|
+
|
|
60
|
+
## Commit Messages
|
|
61
|
+
|
|
62
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
63
|
+
|
|
64
|
+
- `feat:` -- new feature
|
|
65
|
+
- `fix:` -- bug fix
|
|
66
|
+
- `docs:` -- documentation changes
|
|
67
|
+
- `test:` -- test additions or fixes
|
|
68
|
+
- `refactor:` -- code changes that neither fix a bug nor add a feature
|
|
69
|
+
- `chore:` -- maintenance tasks
|
|
70
|
+
|
|
71
|
+
## Code Style
|
|
72
|
+
|
|
73
|
+
- We use `ruff` for linting and formatting
|
|
74
|
+
- Type hints are encouraged
|
|
75
|
+
- No comments unless the WHY is non-obvious
|
|
76
|
+
- Keep functions focused and small
|
|
77
|
+
|
|
78
|
+
## Testing
|
|
79
|
+
|
|
80
|
+
- Every new feature needs tests
|
|
81
|
+
- Every bug fix needs a regression test
|
|
82
|
+
- Run `uv run pytest tests/ -v --tb=short` before submitting
|
|
83
|
+
|
|
84
|
+
## Pull Requests
|
|
85
|
+
|
|
86
|
+
- Keep PRs focused -- one feature or fix per PR
|
|
87
|
+
- Include a clear description of what changed and why
|
|
88
|
+
- Make sure all tests pass
|
|
89
|
+
- Update README.md if adding user-facing features
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 outputguard contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# outputguard — Launch Plan
|
|
2
|
+
|
|
3
|
+
Ready-to-post content for each platform. Copy, paste, adjust as needed.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Reddit
|
|
8
|
+
|
|
9
|
+
### r/Python (largest reach, most critical audience)
|
|
10
|
+
|
|
11
|
+
**Title:** `I built a library that fixes broken JSON from LLMs — 13 repair strategies, zero dependencies on any LLM provider`
|
|
12
|
+
|
|
13
|
+
**Body:**
|
|
14
|
+
|
|
15
|
+
If you've built anything with LLMs that expects JSON back, you know the pain. They wrap it in markdown fences. They use single quotes. They add trailing commas. They output Python `True` instead of `true`. They hit the token limit and give you truncated JSON. They add "Here's the JSON you requested!" before and after.
|
|
16
|
+
|
|
17
|
+
I got tired of writing the same `try/except json.loads` + regex cleanup in every project, so I built **outputguard**.
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import outputguard
|
|
21
|
+
|
|
22
|
+
# LLM gave you this mess:
|
|
23
|
+
llm_output = """```json
|
|
24
|
+
{name: 'Alice', age: 30, active: True,}
|
|
25
|
+
```"""
|
|
26
|
+
|
|
27
|
+
# One line to fix it:
|
|
28
|
+
data = outputguard.parse(llm_output, schema)
|
|
29
|
+
# → {'name': 'Alice', 'age': 30, 'active': True}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
It handles 13 different failure modes I've collected from real LLM outputs:
|
|
33
|
+
|
|
34
|
+
- Markdown code fences
|
|
35
|
+
- Commentary text before/after JSON
|
|
36
|
+
- JS-style comments inside JSON
|
|
37
|
+
- Trailing commas
|
|
38
|
+
- Single quotes instead of double
|
|
39
|
+
- Unquoted object keys
|
|
40
|
+
- `NaN`, `Infinity`, `undefined`
|
|
41
|
+
- Python `True`/`False`/`None`
|
|
42
|
+
- Truncated JSON (token limit cutoffs)
|
|
43
|
+
- `...` placeholders
|
|
44
|
+
- Malformed Unicode escapes
|
|
45
|
+
- Missing closing braces/brackets
|
|
46
|
+
- Unescaped newlines in strings
|
|
47
|
+
|
|
48
|
+
It also validates against JSON Schema, generates retry prompts you can send back to the LLM, and has a CLI with `--verbose` mode that shows you exactly what each strategy changed:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
$ echo '{name: \"Alice\", age: 30,}' | outputguard repair - --verbose
|
|
52
|
+
⚠ Repaired strategies: fix_commas, fix_keys
|
|
53
|
+
|
|
54
|
+
=== fix_commas ===
|
|
55
|
+
- {name: "Alice", age: 30,}
|
|
56
|
+
+ {name: "Alice", age: 30}
|
|
57
|
+
|
|
58
|
+
=== fix_keys ===
|
|
59
|
+
- {name: "Alice", age: 30}
|
|
60
|
+
+ {"name": "Alice", "age": 30}
|
|
61
|
+
|
|
62
|
+
Confidence: 72%
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Why not just use `json.loads` with some regex?** You can, and I did for a year. But the edge cases compound — single quotes with apostrophes inside, comments that look like URLs, braces inside string values. Each strategy handles these correctly.
|
|
66
|
+
|
|
67
|
+
Pure Python, 3 runtime deps (click, jsonschema, rich), works with any LLM provider. MIT licensed.
|
|
68
|
+
|
|
69
|
+
- GitHub: https://github.com/ndcorder/outputguard
|
|
70
|
+
- `pip install outputguard`
|
|
71
|
+
|
|
72
|
+
Happy to answer questions about the implementation. The repair strategies are each their own module if you want to look at how they work.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### r/LocalLLaMA
|
|
77
|
+
|
|
78
|
+
**Title:** `outputguard — automatically fixes broken JSON from local models (13 repair strategies for common failures)`
|
|
79
|
+
|
|
80
|
+
**Body:**
|
|
81
|
+
|
|
82
|
+
Local models are especially bad at producing valid JSON. Even with grammar-constrained generation, you still get trailing commas, Python-style booleans, truncated output from context limits, and markdown fences.
|
|
83
|
+
|
|
84
|
+
I built a Python library that catches and repairs all of these automatically:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import outputguard
|
|
88
|
+
|
|
89
|
+
# Your local model returned this:
|
|
90
|
+
llm_output = "{name: 'Alice', age: 30, active: True,}"
|
|
91
|
+
|
|
92
|
+
# Fix and validate in one call:
|
|
93
|
+
data = outputguard.parse(llm_output, your_schema)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
13 repair strategies, runs in <1ms, works offline, no API calls. Especially useful if you're building agents or tool-calling workflows where the model needs to return structured data.
|
|
97
|
+
|
|
98
|
+
Also has retry prompt generation — if repair isn't enough, it generates a correction prompt you can feed back to the model with specific error details.
|
|
99
|
+
|
|
100
|
+
`pip install outputguard` | https://github.com/ndcorder/outputguard
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### r/ChatGPTCoding / r/ClaudeAI
|
|
105
|
+
|
|
106
|
+
**Title:** `Stop fighting with broken JSON from LLMs — outputguard fixes it automatically`
|
|
107
|
+
|
|
108
|
+
**Body:**
|
|
109
|
+
|
|
110
|
+
Quick share — I built a Python library that handles the "LLM returned garbage JSON" problem.
|
|
111
|
+
|
|
112
|
+
You know when ChatGPT/Claude wraps JSON in markdown fences, adds helpful commentary around it, uses single quotes, or just truncates mid-output? This fixes all of that:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import outputguard
|
|
116
|
+
|
|
117
|
+
result = outputguard.validate_and_repair(llm_output, schema)
|
|
118
|
+
if result.valid:
|
|
119
|
+
print(result.data) # clean, validated dict
|
|
120
|
+
print(result.strategies_applied) # what it fixed
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
13 different repair strategies, JSON Schema validation, and if repair isn't enough, it generates a retry prompt you can send back to the model.
|
|
124
|
+
|
|
125
|
+
https://github.com/ndcorder/outputguard
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### r/ExperiencedDevs or r/programming
|
|
130
|
+
|
|
131
|
+
**Title:** `outputguard: a repair pipeline for LLM JSON output (13 strategies, schema validation, retry prompts)`
|
|
132
|
+
|
|
133
|
+
**Body:**
|
|
134
|
+
|
|
135
|
+
Structured output from LLMs is unreliable. Even with system prompts demanding "return only valid JSON," models produce markdown fences, trailing commas, JavaScript literals, Python-style booleans, and truncated output.
|
|
136
|
+
|
|
137
|
+
I built outputguard — a repair pipeline that applies 13 strategies in order, validates against JSON Schema, and optionally generates correction prompts for retry loops.
|
|
138
|
+
|
|
139
|
+
The architecture is intentionally simple: each strategy is a pure `str → str` function, applied in sequence. The repairer tries all strategies first, then falls back to one-at-a-time with parse attempts between each. There's a `RepairReport` that gives you diffs and a confidence score.
|
|
140
|
+
|
|
141
|
+
The interesting engineering decisions:
|
|
142
|
+
- Strategies must be string-safe (e.g., `remove_comments` can't strip `://` from URLs inside strings, `fix_values` can't replace `NaN` inside string values)
|
|
143
|
+
- `fix_truncated` handles the "ran out of tokens" case by closing open strings, completing partial key-value pairs, and balancing braces
|
|
144
|
+
- The CLI `--verbose` mode shows each strategy's diff — useful for debugging why a particular repair succeeded or failed
|
|
145
|
+
|
|
146
|
+
3 dependencies (click, jsonschema, rich). 162 tests. MIT.
|
|
147
|
+
|
|
148
|
+
https://github.com/ndcorder/outputguard
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Hacker News
|
|
153
|
+
|
|
154
|
+
**Title:** `Show HN: Outputguard – Fix broken JSON from LLMs (13 repair strategies)`
|
|
155
|
+
|
|
156
|
+
**URL:** `https://github.com/ndcorder/outputguard`
|
|
157
|
+
|
|
158
|
+
**Top comment (post immediately after submitting):**
|
|
159
|
+
|
|
160
|
+
Hi HN, I built this because every project I've worked on that uses LLMs for structured output eventually accumulates the same pile of JSON-fixing regexes.
|
|
161
|
+
|
|
162
|
+
The core idea: apply a pipeline of repair strategies (strip markdown fences → extract JSON from commentary → remove JS comments → fix trailing commas → fix quotes → quote keys → fix JS values → fix Python booleans → handle truncation → fix ellipsis placeholders → fix Unicode escapes → balance braces → escape newlines), validate against JSON Schema, and optionally generate a retry prompt.
|
|
163
|
+
|
|
164
|
+
Each strategy is a standalone module with a simple `apply(text: str) -> str` interface. The tricky parts were making them string-aware — you can't just regex-replace `NaN` if it appears inside a string value like `"NaN means Not a Number"`.
|
|
165
|
+
|
|
166
|
+
Works with any LLM provider, no vendor dependencies. 162 tests, runs in <1ms.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Twitter/X
|
|
171
|
+
|
|
172
|
+
### Launch tweet
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
Just released outputguard — a Python library that fixes broken JSON from LLMs.
|
|
176
|
+
|
|
177
|
+
13 repair strategies for the stuff LLMs actually do:
|
|
178
|
+
→ markdown fences
|
|
179
|
+
→ trailing commas
|
|
180
|
+
→ Python True/False/None
|
|
181
|
+
→ truncated output
|
|
182
|
+
→ commentary text
|
|
183
|
+
→ unquoted keys
|
|
184
|
+
→ and 7 more
|
|
185
|
+
|
|
186
|
+
One line: data = outputguard.parse(llm_output, schema)
|
|
187
|
+
|
|
188
|
+
pip install outputguard
|
|
189
|
+
https://github.com/ndcorder/outputguard
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Follow-up thread
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
The --verbose CLI mode shows exactly what each strategy changed:
|
|
196
|
+
|
|
197
|
+
[screenshot of the verbose output]
|
|
198
|
+
|
|
199
|
+
Useful for debugging why a repair succeeded or failed.
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
My favorite feature: retry prompt generation.
|
|
204
|
+
|
|
205
|
+
If repair isn't enough, outputguard generates a correction prompt with specific error details you can send back to the LLM.
|
|
206
|
+
|
|
207
|
+
The LLM gets told exactly what's wrong + what the schema expects.
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
162 tests. 3 dependencies. <1ms repair time. MIT licensed.
|
|
212
|
+
|
|
213
|
+
Works with OpenAI, Anthropic, local models, or anything that produces text.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## LinkedIn
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
I just open-sourced outputguard — a Python library that solves a problem every AI developer hits: broken JSON from LLMs.
|
|
222
|
+
|
|
223
|
+
When you ask an LLM to return structured JSON, you get:
|
|
224
|
+
• Markdown code fences wrapped around it
|
|
225
|
+
• Single quotes instead of double quotes
|
|
226
|
+
• Python True/False instead of JSON true/false
|
|
227
|
+
• Trailing commas
|
|
228
|
+
• Helpful commentary before and after the JSON
|
|
229
|
+
• Truncated output when the model hits token limits
|
|
230
|
+
|
|
231
|
+
outputguard automatically detects and repairs all of these (13 strategies total), validates against your JSON Schema, and generates retry prompts when repair isn't enough.
|
|
232
|
+
|
|
233
|
+
One line to go from broken LLM output to clean, validated data:
|
|
234
|
+
|
|
235
|
+
data = outputguard.parse(llm_output, schema)
|
|
236
|
+
|
|
237
|
+
It's provider-agnostic (works with OpenAI, Anthropic, local models), has 162 tests, and runs in under a millisecond.
|
|
238
|
+
|
|
239
|
+
If you're building AI applications that need reliable structured output, check it out:
|
|
240
|
+
https://github.com/ndcorder/outputguard
|
|
241
|
+
|
|
242
|
+
pip install outputguard
|
|
243
|
+
|
|
244
|
+
#Python #AI #LLM #OpenSource #DeveloperTools
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Dev.to / Hashnode blog post
|
|
250
|
+
|
|
251
|
+
**Title:** `I Fixed the "LLMs Can't Return Valid JSON" Problem — Here's How`
|
|
252
|
+
|
|
253
|
+
**Outline:**
|
|
254
|
+
|
|
255
|
+
1. **The problem** (2 paragraphs) — Every AI app needs structured output. LLMs are terrible at it. Show 5-6 real examples of broken JSON from different models.
|
|
256
|
+
|
|
257
|
+
2. **The naive solution** (1 paragraph) — `try/except json.loads` + growing pile of regexes. Works until it doesn't.
|
|
258
|
+
|
|
259
|
+
3. **The outputguard approach** (2 paragraphs) — Pipeline of 13 repair strategies, each handling one failure mode. Show the architecture diagram: strategies are composable `str → str` functions.
|
|
260
|
+
|
|
261
|
+
4. **Code walkthrough** (3 examples)
|
|
262
|
+
- Basic: `parse()` one-liner
|
|
263
|
+
- Intermediate: `validate_and_repair()` with strategy inspection
|
|
264
|
+
- Advanced: retry loop with prompt generation
|
|
265
|
+
|
|
266
|
+
5. **The hard parts** (2 paragraphs) — String awareness (can't replace tokens inside JSON strings), truncation recovery (closing open strings + partial values), strategy ordering.
|
|
267
|
+
|
|
268
|
+
6. **Results** — Before/after table. "Here's what 8 real LLM outputs looked like, and what outputguard did with them" (use the batch_processing.py example output).
|
|
269
|
+
|
|
270
|
+
7. **Try it** — `pip install outputguard`, link to GitHub.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Where to post (priority order)
|
|
275
|
+
|
|
276
|
+
| Platform | Subreddit/Section | When | Notes |
|
|
277
|
+
|---|---|---|---|
|
|
278
|
+
| Reddit | r/Python | Day 1 | Largest Python community. Post as "Show r/Python". |
|
|
279
|
+
| Hacker News | Show HN | Day 1 | Post the GitHub URL. Comment immediately with context. |
|
|
280
|
+
| Reddit | r/LocalLLaMA | Day 1-2 | Very active, loves tools for local models. |
|
|
281
|
+
| Twitter/X | Your account | Day 1 | Thread format. Tag #Python #AI #LLM. |
|
|
282
|
+
| Reddit | r/MachineLearning | Day 2-3 | Post as [P] project tag. More academic audience. |
|
|
283
|
+
| LinkedIn | Your profile | Day 1-2 | Professional audience. |
|
|
284
|
+
| Reddit | r/ChatGPTCoding | Day 2-3 | Practical coding audience. |
|
|
285
|
+
| Dev.to | Blog post | Day 3-5 | Longer-form content, good for SEO. |
|
|
286
|
+
| Reddit | r/artificial | Day 3-5 | Broader AI audience. |
|
|
287
|
+
| Reddit | r/OpenSource | Day 3-5 | OSS-focused community. |
|
|
288
|
+
|
|
289
|
+
**Timing tips:**
|
|
290
|
+
- Post on Tuesday-Thursday, 9-11am EST (peak Reddit/HN traffic)
|
|
291
|
+
- Don't post everywhere on the same day — spread over a week
|
|
292
|
+
- Engage with every comment. Answer questions thoroughly.
|
|
293
|
+
- If HN gets traction, don't post Reddit the same day (split your attention)
|
|
294
|
+
|
|
295
|
+
**What NOT to do:**
|
|
296
|
+
- Don't use marketing language ("revolutionary", "game-changing")
|
|
297
|
+
- Don't compare to paid products
|
|
298
|
+
- Don't post and disappear — respond to every comment
|
|
299
|
+
- Don't astroturf or ask friends to upvote
|
|
300
|
+
- Don't cross-post the exact same text
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Demo GIF / Screenshot
|
|
305
|
+
|
|
306
|
+
The single most impactful thing for social posts is a terminal screenshot or GIF showing the `--verbose` repair output. Run this and capture it with a tool like [vhs](https://github.com/charmbracelet/vhs) or just a screenshot:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
echo '{name: '"'"'Alice'"'"', age: 30, active: True,}' | outputguard repair - --verbose
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
This produces colorized output showing each strategy's diff — it's visually compelling and immediately communicates what the tool does.
|
|
313
|
+
|
|
314
|
+
For Reddit, a terminal screenshot in the post body gets 2-3x more engagement than text-only.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Responding to common objections
|
|
319
|
+
|
|
320
|
+
**"Why not just use Pydantic + instructor?"**
|
|
321
|
+
> Instructor is great if you're using OpenAI's API. outputguard works at a different layer — it fixes the raw text before parsing, works with any provider (including local models), and doesn't require you to change your LLM client. They're complementary, not competing.
|
|
322
|
+
|
|
323
|
+
**"Just use structured output / function calling"**
|
|
324
|
+
> Structured output modes help a lot but aren't available everywhere (local models, older APIs), don't prevent truncation, and some models still break the schema. outputguard is the safety net for when the LLM doesn't cooperate.
|
|
325
|
+
|
|
326
|
+
**"I just use a try/except with some regex"**
|
|
327
|
+
> That works until you hit apostrophes in single-quoted strings, URLs in comment-stripped JSON, or braces inside string values. Each of these is a 30-minute debugging session. outputguard has 162 tests for these edge cases.
|
|
328
|
+
|
|
329
|
+
**"Seems over-engineered for a simple problem"**
|
|
330
|
+
> The API is one function: `data = outputguard.parse(text, schema)`. The complexity is behind the scenes. You don't need to know about the 13 strategies unless you want to.
|