DSPy adapter for Snakepit - provides high-performance DSPy integration with both pooled and direct interfaces.
SnakepitDspy bridges the gap between Elixir and Python's DSPy library, offering:
- Pooled Interface: High-performance DSPy operations via Snakepit's concurrent worker pool
- Direct Interface: Simple DSPy access without pooling overhead
- Session Management: Automatic program and context management
- Error Handling: Robust error handling and recovery
- Type Safety: Validated command and argument handling
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Your App │ │ SnakepitDspy │ │ Snakepit │
│ │ │ │ │ │
│ - Business │───▶│ - DSPy Adapter │───▶│ - Pool Manager │
│ Logic │ │ - Direct Interface│ │ - Workers │
│ - DSPy Calls │ │ - Validation │ │ - Sessions │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ dspy_bridge.py │ │ Python Workers │
│ │ │ │
│ - DSPy Programs │ │ - Concurrent │
│ - Signatures │ │ - Isolated │
│ - Execution │ │ - Managed │
└──────────────────┘ └─────────────────┘
Add to your mix.exs:
def deps do
[
{:snakepit, "~> 0.0.1"},
{:snakepit_dspy, "~> 0.0.1"}
]
endConfigure Snakepit to use the DSPy adapter:
# config/config.exs
config :snakepit,
pooling_enabled: true,
adapter_module: SnakepitDspy.Adapter,
pool_config: %{
pool_size: 4
}
# Optional DSPy-specific configuration
config :snakepit_dspy,
dspy_config: %{
default_lm: "openai/gpt-3.5-turbo"
}# For Gemini API (optional)
export GEMINI_API_KEY="your-gemini-api-key"
# For OpenAI (if using OpenAI models)
export OPENAI_API_KEY="your-openai-api-key"Use Snakepit's high-performance pooling:
# Start your application (Snakepit starts automatically)
{:ok, _} = Application.ensure_all_started(:your_app)
# Create a DSPy program
{:ok, result} = SnakepitDspy.execute_in_session("my_session", "create_program", %{
id: "qa_program",
signature: %{
inputs: [
%{name: "question", type: "str", description: "Question to answer"}
],
outputs: [
%{name: "answer", type: "str", description: "Answer to the question"}
]
},
instructions: "Answer questions accurately and concisely"
})
# Execute the program
{:ok, result} = SnakepitDspy.execute_in_session("my_session", "execute_program", %{
program_id: "qa_program",
inputs: %{question: "What is DSPy?"}
})
answer = get_in(result, ["outputs", "answer"])For simpler use cases or when you don't need pooling:
# Start a direct worker
{:ok, worker} = SnakepitDspy.Direct.start_link()
# Create a program
{:ok, _} = SnakepitDspy.Direct.create_program(worker, %{
id: "sentiment_analyzer",
signature: %{
inputs: [%{name: "text", type: "str"}],
outputs: [%{name: "sentiment", type: "str"}]
},
instructions: "Analyze sentiment as positive, negative, or neutral"
})
# Execute the program
{:ok, result} = SnakepitDspy.Direct.execute_program(worker, %{
program_id: "sentiment_analyzer",
inputs: %{text: "I love this!"}
})
# Clean up
SnakepitDspy.Direct.stop(worker)create_program- Create a new DSPy programexecute_program- Execute a program with inputsget_program- Get program informationlist_programs- List all programs in sessiondelete_program- Delete a programclear_session- Clear all programs from session
ping- Health check and system information
See the demo application for comprehensive examples including:
- Q&A programs with complex signatures
- Sentiment analysis
- Performance comparisons
- Error handling patterns
- Session management
cd examples/demo_app
elixir run_demo.exs
# For performance comparison
elixir run_demo.exs --performanceSnakepitDspy leverages Snakepit's concurrent worker initialization for significant performance improvements:
- 1000x+ faster startup compared to sequential initialization
- Concurrent execution across multiple Python workers
- Session affinity for stateful program execution
- Automatic scaling based on system resources
All operations return {:ok, result} or {:error, reason} tuples:
case SnakepitDspy.execute_in_session(session, "execute_program", args) do
{:ok, result} ->
# Handle success
process_result(result)
{:error, {:validation_failed, reason}} ->
# Handle validation errors
IO.puts("Validation failed: #{reason}")
{:error, reason} ->
# Handle other errors
IO.puts("Execution failed: #{inspect(reason)}")
end- Elixir 1.18+
- Python 3.8+
- DSPy library (
pip install dspy-ai) - API Keys for your chosen language model (Gemini, OpenAI, etc.)
# Get dependencies
mix deps.get
# Run tests
mix test
# Run the demo
cd examples/demo_app && elixir run_demo.exs- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
MIT