How to Configure DSPy, Outlines, LangChain, and GLiNER 2 Backends in Sieves
Sieves provides a unified ModelWrapper abstraction that lets you swap between DSPy, Outlines, LangChain, GLiNER 2, and HuggingFace backends by changing a single model instantiation line while keeping your task logic identical.
The mantisai/sieves library decouples task definitions from model implementations through a consistent configuration API. Whether you need DSPy for chain-of-thought reasoning, Outlines for structured JSON generation, or GLiNER 2 for zero-shot NER, you configure each backend using the ModelSettings class and ModelType enum system implemented in the model wrapper layer.
Core Architecture
The backend configuration system in Sieves rests on three foundational components defined in sieves/model_wrappers/:
ModelWrapper Base Class
The abstract ModelWrapper class in sieves/model_wrappers/core.py handles initialization, inference-mode selection, few-shot support, token-usage tracking, and strict parsing across all backends. Every concrete wrapper inherits from this base, ensuring consistent behavior for batching, error handling, and metadata extraction.
ModelSettings Configuration
The ModelSettings dataclass in sieves/model_wrappers/types.py (lines 8-25) acts as the configuration container for any backend. It accepts:
inference_mode: String matching the backend's supported modes (e.g.,"chain_of_thought","json")strict: Boolean controlling whether parsing failures raise errors or returnNonebatch_size: Integer for controlling execution batchinginference_kwargs: Dictionary of backend-specific generation parametersinit_kwargs: Dictionary of backend-specific initialization parameters
ModelType Enumeration
The ModelType enum in sieves/model_wrappers/model_type.py (lines 21-29) maps symbolic names to concrete wrapper implementations:
dspy→sieves/model_wrappers/dspy_.pyoutlines→sieves/model_wrappers/outlines_.pylangchain→sieves/model_wrappers/langchain_.pygliner→sieves/model_wrappers/gliner_.pyhuggingface→sieves/model_wrappers/huggingface_.py
Sieves determines the appropriate wrapper automatically via ModelType.get_model_type() when you pass a model instance to a task.
Backend Configuration Examples
Each backend follows the same three-step pattern: instantiate the native model, optionally configure ModelSettings, and pass both to a Sieves task.
DSPy Backend
Configure DSPy for chain-of-thought reasoning or standard completion via inference_mode:
import dspy
from sieves import tasks, ModelSettings
# 1. Create native DSPy model
dspy_model = dspy.LM("openai/gpt-4o-mini", api_key="your-key")
# 2. Configure settings for chain-of-thought with non-strict parsing
dspy_settings = ModelSettings(
inference_mode="chain_of_thought", # Maps to DSPy.InferenceMode.chain_of_thought
strict=False,
inference_kwargs={"max_new_tokens": 256}
)
# 3. Initialize task
sentiment_task = tasks.SentimentAnalysis(model=dspy_model, model_settings=dspy_settings)
# Execute
from sieves import Doc
doc = Doc(text="I love this product!")
result = sentiment_task([doc])[0]
print(result.results[sentiment_task.id])
The DSPy wrapper in sieves/model_wrappers/dspy_.py implements build_executable() to handle async execution and token usage extraction from DSPy completions.
Outlines Backend
Outlines excels at structured generation with JSON, regex, or choice constraints:
import outlines
from transformers import AutoModelForCausalLM, AutoTokenizer
from sieves import tasks, ModelSettings
# 1. Load HuggingFace checkpoint into Outlines
model_name = "HuggingFaceTB/SmolLM2-135M-Instruct"
outlines_model = outlines.models.from_transformers(
AutoModelForCausalLM.from_pretrained(model_name),
AutoTokenizer.from_pretrained(model_name),
)
# 2. Request JSON output mode
outlines_settings = ModelSettings(inference_mode="json", strict=True)
# 3. Build task
sentiment_task = tasks.SentimentAnalysis(
model=outlines_model,
model_settings=outlines_settings
)
# Execute
doc = Doc(text="The movie was boring.")
sentiment_task([doc])
print(doc.results[sentiment_task.id])
The Outlines wrapper in sieves/model_wrappers/outlines_.py supports InferenceMode values including "text", "choice", "regex", and "json".
LangChain Backend
LangChain integration works with any chat model following the LangChain interface:
from langchain_openai import ChatOpenAI
from sieves import tasks, ModelSettings
# 1. Initialize LangChain model
langchain_model = ChatOpenAI(model="gpt-4o-mini", api_key="your-key")
# 2. Default settings work for most tasks
langchain_settings = ModelSettings(strict=True)
# 3. Build task
sentiment_task = tasks.SentimentAnalysis(
model=langchain_model,
model_settings=langchain_settings
)
# Execute
doc = Doc(text="What a wonderful day!")
sentiment_task([doc])
print(doc.results[sentiment_task.id])
Implementation details reside in sieves/model_wrappers/langchain_.py.
GLiNER 2 Backend
GLiNER 2 specializes in zero-shot named entity recognition and classification:
import gliner2
from sieves import tasks, ModelSettings
# 1. Load GLiNER2 model
gliner_model = gliner2.GLiNER2.from_pretrained("fastino/gliner2-base-v1")
# 2. Standard settings (extraction mode only)
gliner_settings = ModelSettings(strict=True)
# 3. Build NER task with custom entity types
ner_task = tasks.NER(
entities=["PERSON", "LOC"],
model=gliner_model,
model_settings=gliner_settings,
)
# Execute
doc = Doc(text="Barack Obama was born in Hawaii.")
ner_task([doc])
print(doc.results[ner_task.id])
The wrapper in sieves/model_wrappers/gliner_.py handles GLiNER 2's specific extraction interface.
HuggingFace Backend
For zero-shot classification using HuggingFace pipelines:
import transformers
from sieves import tasks, ModelSettings
# 1. Build zero-shot pipeline
hf_pipeline = transformers.pipeline(
"zero-shot-classification",
model="MoritzLaurer/xtremedistil-l6-h256-zeroshot-v1.1-all-33",
)
# 2. Configure (pipelines never raise parsing errors)
hf_settings = ModelSettings(strict=False)
# 3. Create classification task
clf_task = tasks.Classification(
labels=["positive", "negative"],
model=hf_pipeline,
model_settings=hf_settings,
)
# Execute
doc = Doc(text="The service was terrible.")
clf_task([doc])
print(doc.results[clf_task.id])
See sieves/model_wrappers/huggingface_.py for the pipeline integration logic.
Advanced Configuration Patterns
Switching Inference Modes
Each wrapper exposes specific InferenceMode enums. For example, DSPy supports "chain_of_thought" while Outlines supports "json". Pass these via ModelSettings.inference_mode:
settings = ModelSettings(
inference_mode="json", # Valid for Outlines, invalid for GLiNER
strict=True,
batch_size=4
)
Backend Agnostic Task Definitions
Because tasks accept any ModelWrapper compatible instance, you can swap backends without touching task logic:
# Simply change the model line; task code remains identical
# model = dspy.LM(...) # For DSPy
# model = outlines.models... # For Outlines
# model = ChatOpenAI(...) # For LangChain
task = tasks.SentimentAnalysis(model=model, model_settings=settings)
Token Usage and Metadata
All wrappers automatically extract token usage and raw outputs, storing them in Doc.meta after execution. The ModelWrapper base class in sieves/model_wrappers/core.py standardizes this metadata collection across DSPy, LangChain, and other backends.
Summary
- Unified API: The
ModelWrapperabstraction insieves/model_wrappers/core.pyprovides consistent initialization, execution, and error handling across all backends. - Configuration Layer: Use
ModelSettings(defined insieves/model_wrappers/types.py) to controlinference_mode,strictparsing,batch_size, and backend-specific kwargs. - Automatic Detection: The
ModelTypeenum insieves/model_wrappers/model_type.pymaps model instances to correct wrappers automatically viaget_model_type(). - Backend Files: Concrete implementations reside in
dspy_.py,outlines_.py,langchain_.py,gliner_.py, andhuggingface_.pyundersieves/model_wrappers/. - Zero Code Changes: Swap between DSPy, Outlines, LangChain, GLiNER 2, and HuggingFace by changing only the model instantiation line; task definitions remain unchanged.
Frequently Asked Questions
What is the difference between strict and non-strict mode in Sieves?
Strict mode (strict=True) forces the wrapper to raise an exception when structured output parsing fails, while non-strict mode returns None for failed parses and continues processing. Configure this in ModelSettings.strict when initializing any task. This setting is particularly important for production pipelines where you want to ensure data quality (strict) versus exploratory workflows where partial failures are acceptable.
Can I use different inference modes for the same backend?
Yes. Each wrapper defines its supported InferenceMode enum in its implementation file. For example, the Outlines wrapper supports "text", "choice", "regex", and "json" modes, while the DSPy wrapper supports standard generation and "chain_of_thought". Pass the desired mode as a string to ModelSettings.inference_mode, and the wrapper's build_executable() method configures the backend accordingly.
How does Sieves handle token usage tracking across backends?
The abstract ModelWrapper class in sieves/model_wrappers/core.py defines token extraction methods that each concrete wrapper implements for its specific backend. After execution, token counts appear in Doc.meta alongside raw model outputs. This works uniformly whether you're using DSPy, LangChain, or HuggingFace pipelines, allowing consistent cost monitoring across different model providers.
Is it possible to mix multiple backends in the same pipeline?
Yes. Because each task carries its own model and model_settings, you can chain tasks using different backends in a single pipeline. For example, use GLiNER 2 for NER extraction in one task, then pass the documents to a DSPy-powered classification task. Each task independently manages its wrapper initialization through ModelType.get_model_type(), keeping the backends isolated despite operating on the same Doc objects.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →