synthetictext
LLM-powered synthetic text data generation for text classification, style transfer, and RAG evaluation tasks.
synthetictext generates high-quality synthetic training data for any text classification task across multiple languages. It provides five generation strategies, a multi-stage quality filtering pipeline, and a simple Python API.
Features
- Task-agnostic: Define any binary or multi-class text classification task via a
TaskSpec - 5 generation strategies: Direct generation, paraphrasing, contrastive pairs, backtranslation, and pivot translation
- Multi-stage quality filtering: Deduplication, label leakage detection, embedding-based dedup, LLM-as-judge, and keyword marker checks
- Multilingual: Generate data in any language supported by your LLM provider, with optional cross-lingual transfer for low-resource languages
- Provider-agnostic: Built-in support for OpenAI; extensible via
BaseLLMProviderandBaseTranslationProviderinterfaces - RAG Q&A generation: Create grounded question-answer pairs from a source chunk for RAG evaluation
- Templated generation: Transfer a source text's style to a caller-provided target topic, especially useful for pretraining data and style transfer tasks.
- CLI and Python API: Use from scripts or the command line
Installation
# Core (no LLM provider included)
pip install synthetictext
# With OpenAI support (most common)
pip install synthetictext[openai]
# With embedding-based deduplication
pip install synthetictext[embeddings]
# With Google Cloud Translation (for backtranslation/pivot strategies)
pip install synthetictext[google-translate]
# With YAML config file support for the CLI
pip install synthetictext[yaml]
# Everything
pip install synthetictext[all]
Authentication
The library needs an API key for the LLM provider. There are three ways to provide it:
Option 1: Environment variable (recommended)
export OPENAI_API_KEY="sk-..."
Then just use the shorthand -- the OpenAI SDK picks up the env var automatically:
generator = SyntheticDataGenerator(task=task, llm_provider="openai")
Option 2: Explicit API key
generator = SyntheticDataGenerator(
task=task,
llm_provider="openai",
llm_model="gpt-4o-mini",
api_key="sk-...",
)
Option 3: Direct provider construction (full control)
from synthetictext.providers.openai_provider import OpenAIProvider
provider = OpenAIProvider(api_key="sk-...", default_model="gpt-4o")
generator = SyntheticDataGenerator(task=task, llm_provider=provider)
The model defaults to gpt-4o-mini but can be overridden via llm_model or --model on the CLI.
Quick Start
from synthetictext import TaskSpec, SyntheticDataGenerator
# 1. Define your classification task
task = TaskSpec(
name="Sentiment Analysis",
labels={0: "negative", 1: "positive"},
description="Classify product reviews as positive or negative sentiment.",
label_descriptions={
0: "A review expressing dissatisfaction, criticism, or negative experience.",
1: "A review expressing satisfaction, praise, or positive experience.",
},
topics={
"electronics": ["smartphones", "laptops", "headphones"],
"food": ["restaurants", "delivery", "recipes"],
},
)
# 2. Create a generator
generator = SyntheticDataGenerator(
task=task,
llm_provider="openai", # uses OPENAI_API_KEY env var
llm_model="gpt-4o-mini",
)
# 3. Generate data
df = generator.generate(
language="English",
num_samples=1000,
strategies=["direct", "paraphrase", "contrastive"],
strategy_weights=[0.5, 0.3, 0.2],
)
print(df.head())
# Columns: id, text, label, source, generated_at, language
RAG Q&A Generation
Generate grounded question-answer pairs from a source text chunk for future RAG evaluation datasets:
from synthetictext import RAGQAGenerator
chunk = """
Synthetictext can generate classification data and RAG Q&A examples.
The RAG Q&A feature creates questions answerable only from the source chunk.
"""
qa_generator = RAGQAGenerator(llm_provider="openai", llm_model="gpt-4o-mini")
qa_df = qa_generator.generate(chunk=chunk, num_samples=3, language="English")
print(qa_df.head())
# Columns: id, question, answer, source, metadata
From the CLI:
synthetictext rag-qa --input chunk.txt --num-samples 5 --language English --output qa.csv
Templated Generation
Generate new text on a different topic while preserving the source text's style, tone, structure, and approximate length:
from synthetictext import TemplatedGenerator
source_text = "EV adoption is accelerating as battery costs fall and charging networks expand."
templated = TemplatedGenerator(llm_provider="openai", llm_model="gpt-4o-mini")
text = templated.generate_one(
text=source_text,
source_topic="electric vehicles",
target_topic="urban gardening",
style="brief analytical market update",
language="English",
)
df = templated.generate(
text=source_text,
source_topic="electric vehicles",
target_topic="urban gardening",
style="brief analytical market update",
num_samples=5,
language="English",
)
print(text)
print(df.head())
# Columns: id, text, source, metadata
From the CLI:
synthetictext templated \
--input source.txt \
--source-topic "electric vehicles" \
--target-topic "urban gardening" \
--style "brief analytical market update" \
--num-samples 5 \
--output templated.csv
Generation Strategies
| Strategy | Description | Requires |
|---|---|---|
| direct | Generate new samples in the target language | LLM |
| paraphrase | Rewrite existing samples preserving labels | LLM + training data |
| contrastive | Generate minimal pairs (one per class, same topic) | LLM |
| backtranslation | Round-trip translate through a pivot language | Translation API + training data |
| pivot | Generate in English, translate to target language | LLM + Translation API |
Quality Filtering
The default filtering pipeline runs these steps in order:
- BasicFilter -- remove empty, null, or out-of-range-length samples
- LeakageFilter -- remove samples containing label leakage patterns (e.g., "this is a positive example")
- EmbeddingDeduplicator -- remove near-duplicates using multilingual sentence embeddings (cosine similarity > 0.90)
- MarkerFilter -- (optional) ensure samples for specific labels contain expected keywords
Additional optional filters:
- LLMJudgeFilter -- use an LLM to validate realism, label correctness, clarity, and grammar
- TranslationQualityFilter -- check round-trip translation consistency for pivot/backtranslation samples
Multilingual Generation
from synthetictext import LanguageConfig
lang_config = LanguageConfig(
languages={"en": "English", "de": "German", "es": "Spanish"},
related_languages={"es": "en"}, # cross-lingual transfer
)
generator = SyntheticDataGenerator(
task=task,
llm_provider="openai",
lang_config=lang_config,
)
# Generate for all configured languages
results = generator.generate_all(num_samples=500)
CLI Usage
# Generate from a JSON task config
synthetictext generate --config task.json --language en --num-samples 1000
# Generate for all languages
synthetictext generate --config task.json --all --num-samples 500 --output-dir ./output
# Multiple strategies with weights
synthetictext generate --config task.json -l en -n 1000 \
--strategies direct paraphrase contrastive \
--weights 0.5 0.3 0.2
# Filter existing synthetic data
synthetictext filter --config task.json --input synthetic.csv --output filtered.csv
# Generate templated style-transfer text
synthetictext templated --input source.txt \
--source-topic "electric vehicles" \
--target-topic "urban gardening" \
--style "brief analytical market update" \
--num-samples 5 --output templated.csv
Task Config File (JSON)
{
"name": "Toxicity Detection",
"labels": {"0": "non-toxic", "1": "toxic"},
"description": "Classify social media posts as toxic or non-toxic.",
"label_descriptions": {
"0": "A post that discusses topics respectfully.",
"1": "A post containing insults, threats, or dehumanizing language."
},
"text_domain": "social media post",
"word_count_range": [20, 80],
"topics": {
"political": ["elections", "government policy"],
"social": ["gender issues", "immigration"]
}
}
Custom Providers
Extend BaseLLMProvider to use any LLM backend:
from synthetictext.providers.base import BaseLLMProvider
class AnthropicProvider(BaseLLMProvider):
def generate(self, prompt, *, model=None, temperature=0.9,
max_tokens=250, system_prompt=None):
# Your Anthropic API call here
...
Tutorials
Step-by-step Jupyter notebooks in tutorials/:
- Quick Start -- defining tasks, generating data, combining strategies
- Quality Filtering -- using built-in filters, building custom filter pipelines
- Multilingual Generation --
LanguageConfig, backtranslation, pivot translation, tier-based strategies - RAG Q&A Generation -- generating grounded question-answer pairs from source chunks
- Templated Generation -- transferring a source text's style to a new topic
Examples
examples/polarization_detection.py-- Full recreation of the SemEval-2026 Task 9 pipeline (22 languages)examples/toxicity_detection.py-- Simple binary toxicity classifier data generation
Development
git clone https://github.com/srikarkashyap/synthetictext.git
cd synthetictext
pip install -e ".[dev]"
pytest
Origin
This library was developed from the synthetic data pipeline used in the PSK system for SemEval-2026 Task 9: Multilingual Polarization Detection, where it generated training data across 22 languages and contributed to a 2nd-place finish.
License
MIT
Metadata
Release files for synthetictext 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| synthetictext-0.2.0.tar.gz | 58.1 kB | Without provenance | Details for synthetictext-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| synthetictext-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for synthetictext-0.2.0-py3-none-any.whl |
Total release size: 104.5 kB
Release files / synthetictext-0.2.0.tar.gz
| Download URL | synthetictext-0.2.0.tar.gz |
|---|---|
| Size | 58.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fe0a1a05a4d78a1e3aa5aeeb8ada9f0f6e96ed3f37581cc515b2e58174e0572a
|
|
BLAKE2b-256 checksum How to use checksums |
b99ded4528549200b1938b32fd83e51c199ef5777074e17e991f6c945e06f3c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.13
|
Release files / synthetictext-0.2.0-py3-none-any.whl
| Download URL | synthetictext-0.2.0-py3-none-any.whl |
|---|---|
| Size | 46.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
042ce8f08ce228800e3201f92b08ab39d761be4daa40f1796f45091d5f0f36f2
|
|
BLAKE2b-256 checksum How to use checksums |
ffb554d8c47d20430debb7c843253b3550b2c0ac1f53227b4b5dab5ad3842d4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.13
|
Security for synthetictext 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.