Feature Model–Guided Synthetic Data Generator
Project description
Generate synthetic text classification datasets whose structure is governed by a FeatureIDE feature model. Domain constraints are formalized, validated, and enforced — before any text is produced.
What Can You Do
- Generate constrained synthetic data from a feature model that defines valid attribute combinations for your domain — no real data required.
- Optimize prompts with PACE (Prompt Actor-Critic Editing) to maximize diversity and text-attribute alignment before generation.
- Verify alignment with an NLI-based quality gate that checks each instance against its conditioning attributes, with automatic retry on mismatch.
- Use compatible LLMs through OpenAI, OpenRouter, Ollama (local), or Hugging Face Inference API.
- Export results as CSV, pandas DataFrames, or artifact directories.
Architecture
Synthline follows the two-phase paradigm of Software Product Line Engineering. A feature model is built once per domain; datasets are derived per generation run.
The generation pipeline translates valid FM configurations into prompts, optionally optimizes them via PACE, generates text through an LLM, and optionally verifies alignment with an NLI scorer.
Installation
pip install synthline
From source:
git clone https://github.com/abdelkarim-elhajjami/Synthline.git
cd Synthline
pip install -e .
Quick Start
from synthline import Synthline
sl = Synthline(
fm="path/to/fm.xml",
llm="openrouter/meta-llama/llama-3.3-70b-instruct",
glossary="path/to/glossary.yaml", # optional
)
# 1. Build prompts from feature selection (no LLM call)
prompts = sl.build_prompts(
label="Security",
label_definition="Degree to which a product protects information and data.",
samples_per_prompt=50,
features={
"RequirementType": ["Quality"],
"Domain": ["Healthcare Information System"],
"AbstractionLevel": ["HighLevel", "DetailedLevel"],
"DescriptionType": ["ProseNL"],
"Context": ["Usage", "ITSystem"],
"Language": ["EN"],
},
)
# 2. Generate
output = await sl.generate(prompts=prompts, samples=1000)
# 3. Export
output.save("output/") # data.csv, metadata.json
df = output.to_dataframe() # pandas DataFrame
With PACE Optimization
optimized = await sl.optimize(prompts, alpha=0.5, iterations=1, actors=4, candidates=2)
output = await sl.generate(prompts=optimized, samples=1000)
With Alignment Verification
output = await sl.generate(prompts=prompts, samples=1000, verify=True, verify_threshold=0.6)
All SDK methods are async except build_prompts (no LLM call).
CLI
# Validate a feature model
synthline validate --fm fm.xml
# Build and inspect prompts
synthline build-prompts --fm fm.xml --label Security --label-def "..." --features features.yaml
# Optimize prompts with PACE
synthline optimize --fm fm.xml --llm openrouter/... --label Security --features features.yaml --output optimized/
# Generate synthetic data
synthline generate --fm fm.xml --llm openrouter/... --samples 1000 --verify --output out/
# Generate from a config file
synthline generate --config run.yaml --output out/
LLM Providers
| Provider | Prefix | Environment variable |
|---|---|---|
| OpenAI | openai/... |
OPENAI_API_KEY |
| OpenRouter | openrouter/... |
OPENROUTER_API_KEY |
| Ollama | ollama/... |
OLLAMA_BASE_URL (local) |
| HuggingFace | huggingface/... |
HF_TOKEN |
Keys can also be passed directly via api_keys={"openrouter": "sk-or-..."}.
For Ollama, set OLLAMA_BASE_URL to the server root, such as
http://localhost:11434; Synthline automatically uses its OpenAI-compatible /v1 API.
Reasoning models are not supported. Synthline is designed for predictable, high-throughput synthetic data sampling. Reasoning models are generally slower and costlier, and many reject the
temperatureandtop_pcontrols Synthline uses. Select a standard chat or instruct model; known reasoning families and explicit reasoning options fail immediately with an actionable error.
Required: The selected LLM must support strict structured outputs with JSON Schema (
response_format.type = "json_schema"). JSON mode alone is not sufficient. Synthline does not fall back to plaintext or suppress provider/schema errors. Choosing a compatible model is the user's responsibility.
Alignment verification also fails loudly if its NLI scorer cannot run. Infrastructure failures are never treated as low-scoring samples.
Compatibility is determined by the model + provider + endpoint combination. The same model can support structured outputs through one serving stack and not through another.
The Web UI lists only OpenRouter models that advertise strict structured outputs and every standard sampling parameter Synthline sends, and removes known reasoning-model families. Generation requests require OpenRouter to route only through providers that support the requested parameters. OpenAI, Hugging Face, Ollama, and other model catalogs do not expose an equally reliable per-model capability flag through the endpoints Synthline uses, so verify those models against the provider documentation before selecting them:
- OpenRouter structured outputs
- OpenAI structured outputs
- Ollama structured outputs
- Mistral structured outputs
Web UI
A browser-based interface is available on Hugging Face Spaces or self-hosted with Docker.
git clone https://github.com/abdelkarim-elhajjami/Synthline.git && cd Synthline && ./dev.sh
Project Structure
synthline/ SDK package (pip install synthline)
core/ FM parser, resolver, generator, PACE, alignment verifier
utils/ Logger, parsing, progress tracking
client.py Synthline class — build_prompts(), optimize(), generate()
types.py PromptSet, Dataset
cli.py CLI entry point
server/ FastAPI + WebSocket server for the Web UI
tests/ Unit and integration tests
web/ Next.js frontend
Citation
@software{synthline,
author = {El Hajjami, Abdelkarim},
title = {Synthline: Feature Model–Guided Synthetic Data Generator},
url = {https://github.com/abdelkarim-elhajjami/Synthline},
year = {2025},
}
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synthline-0.3.0.tar.gz.
File metadata
- Download URL: synthline-0.3.0.tar.gz
- Upload date:
- Size: 47.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bc0813b99093b34f1904d92558d876299f40b23c6d8e42fb21a7e4a78be891b
|
|
| MD5 |
416e4f6d2145df5c040b869bf5e06e3c
|
|
| BLAKE2b-256 |
23851281a4d884107aa39dc9534f8afbb82abfdeeaf5165136d7cd8d3eb79975
|
Provenance
The following attestation bundles were made for synthline-0.3.0.tar.gz:
Publisher:
publish.yml on abdelkarim-elhajjami/synthline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synthline-0.3.0.tar.gz -
Subject digest:
4bc0813b99093b34f1904d92558d876299f40b23c6d8e42fb21a7e4a78be891b - Sigstore transparency entry: 1824548439
- Sigstore integration time:
-
Permalink:
abdelkarim-elhajjami/synthline@1473a20a71bdaf770ba698be27edbff3f9aaf031 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/abdelkarim-elhajjami
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1473a20a71bdaf770ba698be27edbff3f9aaf031 -
Trigger Event:
push
-
Statement type:
File details
Details for the file synthline-0.3.0-py3-none-any.whl.
File metadata
- Download URL: synthline-0.3.0-py3-none-any.whl
- Upload date:
- Size: 53.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
450e519988dcd0030874313253a453b6d034781bc7067ea17d043d08aec05503
|
|
| MD5 |
386bd208fa4365d69151c06002274af6
|
|
| BLAKE2b-256 |
1536fd4e237e506bd6385d50505908d29152bdde55e792122c3a775f39c17bd4
|
Provenance
The following attestation bundles were made for synthline-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on abdelkarim-elhajjami/synthline
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synthline-0.3.0-py3-none-any.whl -
Subject digest:
450e519988dcd0030874313253a453b6d034781bc7067ea17d043d08aec05503 - Sigstore transparency entry: 1824548548
- Sigstore integration time:
-
Permalink:
abdelkarim-elhajjami/synthline@1473a20a71bdaf770ba698be27edbff3f9aaf031 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/abdelkarim-elhajjami
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1473a20a71bdaf770ba698be27edbff3f9aaf031 -
Trigger Event:
push
-
Statement type: