211_ELIXACT.md: DSPEx Elixact Integration Requirements & Implementation Plan
Executive Summary
Based on comprehensive analysis of the current DSPEx codebase and the Pydantic usage patterns in DSPy (documented in 210_PYDANTIC_INTEG.md), this document outlines specific technical requirements and implementation strategies for integrating Elixact into DSPEx.
Key Finding: DSPEx already has a solid foundation for Elixact integration, with existing bridge modules, enhanced parsers, and comprehensive test coverage. The integration path is low-risk and builds on working code.
Current DSPEx Architecture Analysis
Existing Foundation (✅ Already Implemented)
1. Elixact Bridge Module (/lib/dspex/elixact_bridge.ex
)
- Status: 820 lines, fully implemented and tested
- Functionality:
- Signature to Elixact schema conversion
- Type mapping (string, integer, float, boolean, list, map)
- Basic validation integration
- Error handling with structured feedback
2. Enhanced Signature Parser (/lib/dspex/signature/enhanced_parser.ex
)
- Status: 837 lines, production-ready
- Functionality:
- Type annotations support:
question:string -> answer:string, confidence:float
- Constraint parsing:
count:integer(min=1,max=100)
- Nested type definitions
- Rich field metadata extraction
- Type annotations support:
3. Configuration Schema System (/lib/dspex/config/schema.ex
)
- Status: 480 lines, comprehensive validation
- Functionality:
- Type-safe configuration validation
- Nested configuration schemas
- Default value handling
- Error reporting with field paths
4. Test Infrastructure
- Status: 13 integration tests passing, full unit test coverage
- Coverage:
- Bridge functionality validation
- Parser integration testing
- Configuration schema validation
- Error handling scenarios
Current Signature System Architecture
DSPEx.Signature (behavior)
├── DSPEx.Signature.Parser (basic: "question -> answer")
├── DSPEx.Signature.EnhancedParser (typed: "question:string -> answer:string")
└── DSPEx.ElixactBridge (convert to Elixact schemas)
Current Validation Points
Input Validation (
/lib/dspex/predict.ex:45-67
)- Basic field presence checking
- Type coercion for simple types
- Manual validation logic
Output Validation (
/lib/dspex/predict.ex:112-134
)- Response parsing validation
- Field extraction and verification
- Basic type checking
Adapter Validation (
/lib/dspex/adapters/instructor_lite_gemini.ex:89-156
)- Manual JSON schema construction
- Response format validation
- Error handling for malformed responses
Configuration Validation (
/lib/dspex/config/schema.ex
)- Comprehensive config validation using existing schema system
- Nested configuration support
- Type-safe parameter handling
Integration Opportunities & Requirements
Priority 1: Enhanced JSON Schema Generation
Current State
File: /lib/dspex/adapters/instructor_lite_gemini.ex
Lines: 89-156 (67 lines of manual schema construction)
# Current manual approach
defp build_json_schema(signature) do
output_fields = signature.output_fields()
properties = output_fields
|> Enum.map(fn field -> {to_string(field), %{"type" => "string"}} end)
|> Enum.into(%{})
%{
"type" => "object",
"properties" => properties,
"required" => output_fields |> Enum.map(&to_string/1),
"additionalProperties" => false
}
end
Enhancement Required
Integration Point: Use Elixact for automatic schema generation with constraints
# Enhanced approach with Elixact
defp build_json_schema(signature) do
case DSPEx.ElixactBridge.signature_to_schema(signature) do
{:ok, elixact_schema} ->
Elixact.JsonSchema.from_schema(elixact_schema)
{:error, _} ->
# Fallback to manual schema
build_json_schema_legacy(signature)
end
end
Benefits:
- Support for complex types (nested objects, arrays, unions)
- Automatic constraint validation (min/max, patterns, formats)
- Rich field descriptions and examples
- Comprehensive type safety
Priority 2: Validation Pipeline Integration
Current State
File: /lib/dspex/predict.ex
Lines: 45-67 (input validation), 112-134 (output validation)
# Current basic validation
defp validate_inputs(signature, inputs) do
required_fields = signature.input_fields()
provided_fields = Map.keys(inputs)
missing_fields = required_fields -- provided_fields
if missing_fields == [] do
:ok
else
{:error, {:missing_fields, missing_fields}}
end
end
Enhancement Required
Integration Point: Add comprehensive Elixact validation
# Enhanced validation with Elixact
defp validate_inputs(signature, inputs) do
case DSPEx.ElixactBridge.signature_to_schema(signature) do
{:ok, elixact_schema} ->
input_fields = extract_input_fields(elixact_schema)
input_data = Map.take(inputs, input_fields)
case Elixact.validate(input_data, elixact_schema) do
{:ok, validated} -> {:ok, validated}
{:error, errors} -> {:error, {:validation_failed, format_errors(errors)}}
end
{:error, reason} ->
# Fallback to basic validation
validate_inputs_basic(signature, inputs)
end
end
Benefits:
- Rich type validation (strings, numbers, booleans, complex types)
- Constraint enforcement (length, range, format)
- Structured error reporting with field paths
- Type coercion and normalization
Priority 3: Enhanced Type System Support
Current State
File: /lib/dspex/signature/enhanced_parser.ex
Lines: 200-350 (type annotation parsing)
# Current type support (basic)
defp parse_type_annotation("string"), do: {:ok, :string}
defp parse_type_annotation("integer"), do: {:ok, :integer}
defp parse_type_annotation("float"), do: {:ok, :float}
defp parse_type_annotation("boolean"), do: {:ok, :boolean}
Enhancement Required
Integration Point: Add complex type support via Elixact
# Enhanced type support
defp parse_type_annotation("string(min=1,max=100)") do
{:ok, {:string, [min_length: 1, max_length: 100]}}
end
defp parse_type_annotation("array(string)") do
{:ok, {:array, :string}}
end
defp parse_type_annotation("object{name:string,age:integer}") do
{:ok, {:object, [name: :string, age: :integer]}}
end
Benefits:
- Complex nested object support
- Array and union type support
- Rich constraint specifications
- Compile-time type checking
Specific Technical Requirements
1. Elixact Feature Requirements
Based on the Pydantic patterns analysis, Elixact needs to support:
Core Requirements (Must Have)
Runtime Schema Generation
- Dynamic schema creation from parsed signatures
- Configuration-based schema modification
- Schema composition and merging
Advanced Validation
- Field-level constraint validation
- Cross-field validation rules
- Custom validator functions
- Conditional validation logic
JSON Schema Generation
- Complete JSON Schema Draft 7 support
- OpenAI/Anthropic/Gemini compatibility
- Reference resolution for nested schemas
- Schema manipulation utilities
Error Handling
- Structured error reporting with field paths
- Error code categorization
- Detailed validation failure information
- Integration with DSPEx error handling
Advanced Requirements (Should Have)
Type Coercion
- String to number conversion
- Flexible type casting
- Format-based parsing (dates, URLs)
- Safe type coercion with validation
Configuration Support
- Schema configuration options
- Validation mode selection (strict/lax)
- Custom type definitions
- Extension points for custom logic
2. DSPEx Integration Points
A. Signature System Enhancement
Target: /lib/dspex/signature.ex
defmodule DSPEx.Signature do
# Add Elixact-aware signature behavior
@callback to_elixact_schema() :: {:ok, Elixact.Schema.t()} | {:error, term()}
@callback validate_with_elixact(data :: map()) :: {:ok, map()} | {:error, term()}
# Enhanced signature creation
def create_with_elixact(signature_string, opts \\ []) do
with {:ok, parsed} <- EnhancedParser.parse(signature_string),
{:ok, schema} <- ElixactBridge.signature_to_schema(parsed) do
create_signature_module(schema, opts)
end
end
end
B. Predict Module Enhancement
Target: /lib/dspex/predict.ex
defmodule DSPEx.Predict do
# Enhanced validation in forward/3
defp validate_inputs_with_elixact(program, inputs) do
case program.signature.to_elixact_schema() do
{:ok, schema} ->
input_schema = extract_input_schema(schema)
Elixact.validate(inputs, input_schema)
{:error, _} ->
# Fallback to current validation
validate_inputs_basic(program.signature, inputs)
end
end
end
C. Adapter Enhancement
Target: /lib/dspex/adapters/instructor_lite_gemini.ex
defmodule DSPEx.Adapters.InstructorLiteGemini do
# Enhanced schema generation
defp build_json_schema_with_elixact(signature) do
case signature.to_elixact_schema() do
{:ok, schema} ->
output_schema = extract_output_schema(schema)
Elixact.JsonSchema.generate(output_schema)
{:error, _} ->
build_json_schema_basic(signature)
end
end
end
3. Configuration Integration
Enhanced Configuration Schema
Target: /lib/dspex/config/schema.ex
defmodule DSPEx.Config.Schema do
# Use Elixact for configuration validation
use Elixact.Schema
schema "DSPEx Configuration" do
field :signatures, {:array, SignatureConfig}
field :validation, ValidationConfig
field :adapters, {:map, AdapterConfig}
end
defmodule SignatureConfig do
use Elixact.Schema
schema "Signature Configuration" do
field :type_checking, :boolean, default: true
field :constraint_validation, :boolean, default: true
field :error_detail_level, :atom, enum: [:basic, :detailed, :verbose]
end
end
end
Implementation Strategy
Phase 1: Core Integration (2-3 weeks)
Enhance Elixact Bridge (Week 1)
- Add missing Pydantic pattern support
- Implement TypeAdapter equivalent
- Add schema reference resolution
Update Validation Pipeline (Week 1-2)
- Integrate Elixact validation in Predict module
- Enhance error handling and reporting
- Add validation configuration options
Adapter Enhancement (Week 2-3)
- Replace manual JSON schema generation
- Add constraint-aware schema building
- Test with OpenAI/Anthropic/Gemini APIs
Phase 2: Advanced Features (2-3 weeks)
Enhanced Type System (Week 3-4)
- Add complex type parsing support
- Implement nested object schemas
- Add union and array type support
Configuration Enhancement (Week 4-5)
- Type-safe configuration schemas
- Validation mode configuration
- Custom type definitions
Testing and Optimization (Week 5-6)
- Comprehensive test coverage
- Performance optimization
- Documentation and examples
Phase 3: Advanced Patterns (2-3 weeks)
Advanced Pydantic Patterns (Week 6-7)
- Implement remaining patterns from 210_PYDANTIC_INTEG.md
- Add wrapper model support
- Implement custom serialization
Migration Tools (Week 7-8)
- Signature migration utilities
- Automated conversion tools
- Documentation and guides
Risk Assessment & Mitigation
Low Risk Areas ✅
- Foundation Integration: Existing bridge module provides solid base
- Test Coverage: Comprehensive test infrastructure already in place
- Backward Compatibility: Current signature system continues to work
- Performance: Minimal overhead with existing validation patterns
Medium Risk Areas ⚠️
- Elixact Feature Gaps: Some Pydantic patterns may need Elixact enhancement
- Complex Type Support: Advanced types require careful implementation
- API Compatibility: JSON schema generation must work with LLM providers
High Risk Areas 🔴
- Migration Complexity: Large signatures may be complex to migrate
- Performance Impact: Validation overhead needs monitoring
- External Dependencies: Elixact evolution and compatibility
Mitigation Strategies
- Incremental Integration: Build on existing working foundation
- Fallback Support: Maintain current validation as fallback
- Comprehensive Testing: Extensive test coverage for all integration points
- Performance Monitoring: Benchmark validation overhead
- Migration Tools: Automated tools for signature conversion
Success Metrics
Technical Metrics
- ✅ Zero Breaking Changes: All existing signatures continue to work
- ✅ Enhanced Validation: Rich type checking and constraint validation
- ✅ JSON Schema Quality: Full constraint support in generated schemas
- ✅ Error Reporting: Structured errors with field paths and details
- ✅ Performance: <10% validation overhead
User Experience Metrics
- ✅ Migration Ease: Simple signature migration process
- ✅ Documentation Quality: Clear guides and examples
- ✅ Error Messages: Actionable and informative error reporting
- ✅ Type Safety: Compile-time and runtime type checking
- ✅ IDE Support: Rich development experience
Conclusion
DSPEx is exceptionally well-positioned for Elixact integration, with a solid foundation already in place. The existing bridge module, enhanced parser, and comprehensive test coverage provide a low-risk path to adding substantial type safety and validation capabilities.
The integration strategy builds incrementally on working code, maintaining backward compatibility while adding powerful new features. The specific technical requirements identified here provide a clear roadmap for implementation, with well-defined integration points and success metrics.
By following this plan, DSPEx will achieve comprehensive Pydantic feature parity while leveraging Elixir’s strengths for superior performance, reliability, and developer experience.