Changelog¶
All notable changes to smelt-ai.
v0.5.0 — 2026-07-22¶
Changed¶
- Graceful partial failure for
AggregateJobwithstop_on_exhaustion=False:- Tree mode: failed map batches are skipped and the aggregate is computed from the surviving rows (previously all successful work was discarded and
datacame back empty) - Tree mode: a failed merge step passes both operands through to the next tree level, where the merge is effectively retried with a different pairing; the run only aborts if a whole level makes no progress
- Sequential mode: a failed step is skipped and the fold continues with the accumulated result (previously the chain stopped and
datacame back empty) - In all partial-failure cases,
result.errorslists the failed batches andmetrics.failed_rowscounts the excluded rows
- Tree mode: failed map batches are skipped and the aggregate is computed from the surviving rows (previously all successful work was discarded and
- Validation-error retries no longer wait for exponential backoff — a malformed LLM response retries immediately (it's a fresh sample, not a capacity problem); API errors still back off exponentially
- Nested Pydantic models are now described recursively in prompts —
describe_output_schema()expands nested model fields (including insidelist[...],dict[...], and unions) instead of showing a bare class name, and renders generic types readably (list[Item],str | None,Literal['a', 'b'])
Fixed¶
- Retriable-error detection no longer false-positives on messages merely containing "rate" (e.g. "failed to generate"); it now matches specific phrases ("rate limit", "too many requests", …) and also honors a
status_codenested onexc.response
v0.4.2 — 2026-04-04¶
Added¶
- Sequential fold strategy for
AggregateJob—strategy="sequential"processes batches one at a time, feeding each step's output into the next as accumulated context
v0.4.1 — 2026-04-04¶
Fixed¶
- Aggregate bug fixes and additional test coverage for the tree-reduction engine
v0.4.0 — 2026-04-04¶
Added¶
AggregateJob— many-to-one aggregation via tree-parallel reduction- Map phase runs batches concurrently, merge phase combines outputs pairwise until one result remains
- Supports both structured output (
output_model=SummaryModel) and free-text mode (output_model=None) - New
execute_aggregate()engine insmelt.aggregatemodule - Aggregate-specific prompt templates for map and merge phases
build_aggregate_system_message()andbuild_aggregate_human_message()prompt builders- 60-company portfolio and 50-employee survey test datasets
- Live tests verifying aggregation accuracy against ground truth
v0.3.0 — 2026-04-03¶
Added¶
- Free-text output mode — set
output_model=None(or omit it) to get plainlist[str]responses instead of structured Pydantic models _TextRowinternal model for free-text row trackingcreate_text_batch_wrapper()in validation moduletext_modeparameter onbuild_system_message()for text-optimized promptsoutput_modelnow defaults toNone— zero-config free-text is the simplest path
Changed¶
Job.output_modelis nowOptional[Type[BaseModel]]with defaultNone(backward compatible — existing code with explicitoutput_model=MyModelworks unchanged)execute_batches()branches onoutput_model is Nonefor text vs structured pathsstrip_row_id()returnsstrwhenuser_model is None
v0.2.0 — 2026-03-07¶
Added¶
- Vision / image support — pass
PIL.Image.Imageobjects directly in data dicts for vision-capable LLMs - New
smelt.imagemodule with image detection, base64 encoding, and extraction utilities PILLOW_AVAILABLEflag exported fromsmeltpackage[vision]optional dependency extra (pip install smelt-ai[vision])has_imagesparameter onbuild_system_message()for image-aware prompts- Multimodal content blocks in
build_human_message()— auto-detects PIL images, replaces with placeholders, and appends base64-encoded image blocks UserWarningwhenbatch_size > 5with image data (large payloads)- Vision cookbook with ECG analysis example
Changed¶
build_system_message()now accepts optionalhas_imageskeyword argument (backward compatible)build_human_message()returns multimodal content blocks when images are detected, plain text otherwise (backward compatible)
v0.1.1 — 2025-02-18¶
Added¶
job.test()andjob.atest()methods for single-row validation before full runs- PyPI metadata: readme, authors, keywords, classifiers, project URLs
- Documentation URL in PyPI package metadata
Fixed¶
- Empty
datalist now raisesSmeltConfigErrorintest()/atest()instead of silently succeeding
v0.1.0 — 2025-02-18¶
Added¶
- Initial release
Modelclass wrapping LangChain'sinit_chat_modelwith lazy initialization and cachingJobclass withrun(),arun()for sync/async execution- Automatic batching with configurable
batch_size - Concurrent batch processing via
asyncio.Semaphorewith configurableconcurrency - Row ID tracking for guaranteed output ordering
- Automatic retry with exponential backoff and jitter
SmeltResult[T]with typed data, errors, and metricsSmeltMetricswith token counts, timing, retry countsBatchErrorwith per-batch diagnostic informationstop_on_exhaustionparameter for fail-fast vs collect-errors modesshuffleparameter for randomizing batch composition- Exception hierarchy:
SmeltError,SmeltConfigError,SmeltValidationError,SmeltAPIError,SmeltExhaustionError - Support for OpenAI, Anthropic, and Google Gemini providers
- Dynamic Pydantic model creation (inherits user validators)
- Pydantic v2 native validation