← Back to Docs

20250715 SIGNATURE ENHANCEMENT PROPOSAL

Documentation for 20250715_SIGNATURE_ENHANCEMENT_PROPOSAL from the Dspex repository.

DSPex Signature Enhancement Proposal

Executive Summary

Based on analysis of the advanced signature implementation in ../elixir_ml/lib/dspex/signature.ex and related modules, this document proposes a phased enhancement of DSPex’s current signature system to achieve maximum DSPy compatibility while building toward future advanced capabilities.

Current State Analysis

Existing DSPex Signature System

Location: /home/home/p/g/n/dspex/lib/dspex/signature/signature.ex

The current implementation uses a basic compile-time macro approach:

signature question: :string -> answer: :string

Limitations:

  • No support for complex DSPy field definitions
  • Limited type annotation parsing
  • No constraint validation system
  • Basic field parsing that can’t handle DSPy’s comma-separated complex lists

Advanced Reference Implementation

Location: /home/home/p/g/n/elixir_ml/lib/dspex/signature.ex (896+ lines)

The ElixirML implementation provides sophisticated features:

  • Enhanced parser with constraint syntax
  • ML-specialized type system
  • Sinter integration for JSON schema generation
  • Backward compatibility detection
  • Complex field validation pipeline

Enhancement Strategy

Phase 1: Parser Foundation (Critical for DSPy)

1.1 Extract Enhanced Parsing Logic

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/enhanced_parser.ex:280-513

# Add to current DSPex signature system
defmodule DSPex.Signature.Parser do
  # Extract from enhanced_parser.ex:296-329
  defp split_fields_respecting_brackets(str) do
    # Handle complex DSPy field lists like:
    # "context, question:string -> answer:string, confidence:float"
  end
  
  # Extract from enhanced_parser.ex:430-445  
  defp parse_name_and_type(base_field) do
    # Parse DSPy type annotations: "field:type"
  end
  
  # Extract from enhanced_parser.ex:151-161
  def enhanced_signature?(signature_string) do
    # Detect DSPy signature complexity
  end
end

Implementation Priority: HIGH - Essential for DSPy compatibility

1.2 Add DSPy-Compatible Type System

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/enhanced_parser.ex:464-513

# Enhance current type system to match DSPy
defmodule DSPex.Signature.Types do
  # DSPy-compatible types from enhanced_parser.ex:483-512
  def parse_simple_type(type_str) do
    case type_str do
      "string" -> :string
      "integer" -> :integer
      "float" -> :float
      "boolean" -> :boolean
      "list" -> :list        # DSPy uses "list"
      "dict" -> :dict        # DSPy uses "dict"  
      "any" -> :any
      # Future: ML-specific types
      "embedding" -> :embedding
      "probability" -> :probability
    end
  end
end

1.3 Backward Compatibility Layer

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/enhanced_parser.ex:124-129

# Ensure existing DSPex signatures continue working
defmodule DSPex.Signature.Compatibility do
  def to_simple_signature({input_fields, output_fields}) do
    # Convert enhanced parsing back to current format
    input_names = Enum.map(input_fields, & &1.name)
    output_names = Enum.map(output_fields, & &1.name)
    {input_names, output_names}
  end
end

Phase 2: Validation Pipeline Enhancement

2.1 Field Validation Foundation

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/enhanced_parser.ex:795-894

# Add validation that mirrors DSPy's validation logic
defmodule DSPex.Signature.Validator do
  # Extract from enhanced_parser.ex:818-830
  def validate_enhanced_field(field) do
    # Validate constraint compatibility with type
    validate_constraints_for_type(field.type, field.constraints, field.name)
    
    # Validate default value compatibility (if present)
    if field.default != nil do
      validate_default_for_type(field.type, field.default, field.name)
    end
  end
end

2.2 Integration with Sinter

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/sinter.ex:1-50

# Bridge DSPex signatures to Sinter for validation
defmodule DSPex.Signature.SinterBridge do
  def to_sinter_schema(signature) do
    # Convert DSPex signature to Sinter schema format
    fields = extract_signature_fields(signature)
    Sinter.Schema.define(fields, title: signature.name || "DSPy Signature")
  end
  
  def validate_with_sinter(signature, data) do
    schema = to_sinter_schema(signature)
    Sinter.Validator.validate(schema, data)
  end
end

Phase 3: DSPy-Specific Features

3.1 Dynamic Signature Creation

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature.ex:98-120

# Support DSPy's runtime signature generation
defmodule DSPex.Signature.Dynamic do
  def create_from_fields(input_fields, output_fields, options \\ []) do
    # Similar to enhanced signature extension logic
    {new_inputs, new_outputs} = categorize_fields(input_fields, output_fields)
    
    signature_string = build_signature_string(new_inputs, new_outputs)
    create_signature_module(signature_string, options)
  end
  
  def merge_signatures(base_signature, additional_fields) do
    # For DSPy signature composition and ChainOfThought patterns
  end
end

3.2 JSON Schema Generation for LLM Providers

Source: /home/home/p/g/n/elixir_ml/lib/dspex/signature/sinter.ex:183-210

# Generate LLM-compatible schemas
defmodule DSPex.Signature.JsonSchema do
  def generate_for_provider(signature, provider) do
    sinter_schema = DSPex.Signature.SinterBridge.to_sinter_schema(signature)
    Sinter.JsonSchema.for_provider(sinter_schema, provider)
  end
  
  def optimize_for_dspy(signature, options \\ []) do
    # DSPy-specific optimizations
    sinter_schema = DSPex.Signature.SinterBridge.to_sinter_schema(signature)
    
    # Remove computed fields for input validation
    # Include all fields for output validation
    case options[:mode] do
      :input -> remove_computed_fields(sinter_schema)
      :output -> sinter_schema
      _ -> sinter_schema
    end
  end
end

Implementation Plan

Phase 1: Foundation (Week 1-2)

Goal: Get complex DSPy signatures parsing correctly

  1. Extract and adapt parser logic from enhanced_parser.ex:280-513

    • split_fields_respecting_brackets/1
    • parse_name_and_type/1
    • enhanced_signature?/1
  2. Add DSPy type system from enhanced_parser.ex:464-513

    • Basic types: :string, :integer, :float, :boolean, :list, :dict
    • Future ML types: :embedding, :probability
  3. Maintain backward compatibility

    • Existing signatures continue to work unchanged
    • New parser handles both simple and complex formats

Phase 2: Validation Integration (Week 3-4)

Goal: Reliable validation using Sinter

  1. Create Sinter bridge from sinter.ex:1-50

    • Convert DSPex signatures to Sinter schemas
    • Leverage Sinter’s validation pipeline
  2. Add field validation from enhanced_parser.ex:795-894

    • Type compatibility checking
    • Constraint validation (basic set)
  3. JSON Schema generation for LLM providers

    • OpenAI Function Calling format
    • Anthropic Tool Use format
    • Generic format

Phase 3: DSPy Features (Week 5-6)

Goal: Full DSPy compatibility

  1. Dynamic signature creation from signature.ex:98-120

    • Runtime signature generation
    • Signature composition and merging
  2. DSPy-specific optimizations

    • Input vs output schema handling
    • LLM provider-specific optimizations
  3. Integration testing with existing DSPy examples

File Modifications Required

New Files to Create:

  1. lib/dspex/signature/parser.ex - Enhanced parsing logic
  2. lib/dspex/signature/sinter_bridge.ex - Sinter integration
  3. lib/dspex/signature/dynamic.ex - Runtime signature creation
  4. lib/dspex/signature/json_schema.ex - LLM schema generation

Existing Files to Modify:

  1. lib/dspex/signature/signature.ex - Add enhanced parsing hooks
  2. lib/dspex/signature/compiler.ex - Support new parsing logic
  3. lib/dspex/signature/validator.ex - Integrate Sinter validation

Benefits of This Approach

Immediate (Phase 1):

  • DSPy compatibility: Handle complex DSPy signature formats
  • Type annotations: Support field:type syntax DSPy uses
  • Backward compatibility: Existing code continues working

Short-term (Phase 2-3):

  • Reliable validation: Leverage Sinter’s proven validation engine
  • LLM integration: Generate provider-specific JSON schemas
  • Dynamic signatures: Support DSPy’s runtime signature creation

Long-term:

  • Extensibility: Foundation for advanced constraint system
  • Integration path: Clear upgrade to Exdantic for complex ML pipelines
  • Performance: Optimized validation pipeline through Sinter

Code References Summary

Primary Sources:

  • /home/home/p/g/n/elixir_ml/lib/dspex/signature/enhanced_parser.ex (896 lines) - Core parsing logic
  • /home/home/p/g/n/elixir_ml/lib/dspex/signature.ex (106 lines) - Signature extension patterns
  • /home/home/p/g/n/elixir_ml/lib/dspex/signature/sinter.ex (444 lines) - Sinter integration patterns

Key Functions to Extract:

  • Lines 296-329: split_fields_respecting_brackets/1 - Complex field parsing
  • Lines 430-445: parse_name_and_type/1 - Type annotation parsing
  • Lines 151-161: enhanced_signature?/1 - Format detection
  • Lines 464-513: Type system parsing functions
  • Lines 795-894: Field validation logic

This enhancement proposal provides a clear path to DSPy compatibility while maintaining architectural flexibility for future advanced features.