This project uses separate environment files for dev, qa, perf, cte, and prod, each located at the project root as .env.dev, .env.qa, .env.perf, .env.cte, and .env.prod. These files contain environment-specific variables for OIDC, metrics, tracing, and service endpoints. All files use the same variable structure for consistency and ease of deployment. See the examples/stripe_schemas/ directory for environment-specific schema configs.
JsonAI is a comprehensive Python library for generating structured JSON data using Large Language Models (LLMs). It provides enterprise-grade features including robust JSON schema validation, multiple model backends, REST API, React frontend, CLI interface, and production deployment configurations.
Current version: 0.15.2
- Conversational Agents: Natural language interface with multi-agent collaboration
- Real-time Streaming: Live generation updates and agent responses
- Plugin System: Extensible architecture for custom backends, formatters, and tools
- Integration Hub: Connect with GitHub, Slack, VS Code, and webhooks
- One-Click Deployment: Automated deployment to Docker, cloud providers
- Token Limits: Optimized token management for small models (Mistral, etc.)
- Stabilized FastAPI REST API with endpoints for sync/async generation, batch processing, stats, cache management, and schema validation
- Performance suite:
- PerformanceMonitor async timing fixes
- CachedJsonformer with LRU/TTL caching
- BatchProcessor for efficient concurrent execution
- OptimizedJsonformer combines caching + batch processing with warmup
- Async generation improvements:
- FullAsyncJsonformer (aliased as AsyncJsonformer in the API)
- AsyncJsonformer wrapper in main.py for async tool execution
- Logging hygiene: lazy logging interpolation to reduce overhead
- Packaging: PyPI publish flow cleaned; version bumped to 0.15.1
JsonAI's output quality is validated with statistical metrics. The following table summarizes KL divergence (lower is better) and timing (seconds) for core types, measured using uniform schema sampling and the built-in metrics suite:
| Type | KL Divergence | Time (s) |
|---|---|---|
| number | 0.016813 | 4.5798 |
| integer | 0.000864 | 4.5564 |
| boolean | 0.000018 | 4.4584 |
| enum | 0.000108 | 4.4765 |
All values are well below the recommended threshold (KL < 0.5), demonstrating high-fidelity, schema-faithful sampling. See tests/test_metrics_sampling.py for methodology.
- Multiple LLM Backends: Ollama, OpenAI, and HuggingFace Transformers
- Full JSON Schema Coverage: primitives, arrays, objects, enums, nested structures, oneOf
- Performance Optimization: caching (LRU/TTL), batch processing, async operations
- Production Ready: Docker, FastAPI, monitoring, scaling considerations
- REST API: FastAPI-based service with OpenAPI docs
- React Frontend: Modern web interface for JSON generation
- CLI Interface: Command-line tools for automation and batch processing
- Python Library: Programmatic access with sync and async support
- Caching System: Intelligent multi-level caching (LRU/TTL)
- Batch Processing: Concurrent batch execution
- Performance Monitoring: Built-in metrics via PerformanceMonitor
- Schema Validation: Comprehensive validation with jsonschema
- Multiple Output Formats: JSON, YAML, XML, and CSV
JsonAI provides comprehensive integration with Ollama, enabling local LLM-powered structured data generation. The integration includes:
- Enhanced Ollama Backend: Robust error handling, retry mechanisms, and support for all Ollama options
- Model Selection & Tuning: Automatic model selection based on task type and performance tuning
- Agentic Testing Ecosystem: Full support for workflow orchestration, state management, and tracing
- Performance Optimization: Configurable parameters for optimal generation quality and speed
from jsonAI.model_backends import OllamaBackend
from jsonAI.main import Jsonformer
# Create Ollama backend
backend = OllamaBackend(model_name="mistral", max_retries=3)
# Define schema and prompt
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
}
}
prompt = "Generate a person profile"
# Create Jsonformer with Ollama
jsonformer = Jsonformer(
model_backend=backend,
json_schema=schema,
prompt=prompt,
ollama_options={"temperature": 0.7}
)
# Generate data
result = jsonformer.generate_data()
JsonAI supports complex agentic workflows with Ollama:
- Workflow orchestration with conditional execution
- State management with session isolation
- Persistent storage for workflow execution tracking
- Distributed tracing for observability
- MCP protocol support for tool integration
See examples/ollama_integration_example.py for detailed usage examples.
JsonAI now includes advanced agentic capabilities for natural language interaction and extensible workflows:
from jsonAI.conversational_agent import ConversationalAgentInterface
from jsonAI.model_backends import OllamaBackend
# Create agent interface
backend = OllamaBackend(model_name="mistral:latest")
agent_interface = ConversationalAgentInterface(backend)
# Create specialized agents
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"role": {"type": "string"},
"skills": {"type": "array", "items": {"type": "string"}}
}
}
agent = agent_interface.create_agent(
agent_id="developer_agent",
name="DevAgent",
role="Software Developer",
capabilities=["code_generation", "debugging"],
schema=schema,
max_tokens=150 # Optimized for Mistral
)
# Process natural language requests
async for response in agent_interface.process_conversation(
"test_conv", "Generate a Python developer profile"
):
print(response)from jsonAI.streaming_interface import StreamingJsonformer
# Enable streaming for live updates
jsonformer = StreamingJsonformer(
model_backend=backend,
json_schema=schema,
prompt="Generate user data",
enable_streaming=True
)
# Stream generation results
async for chunk in jsonformer.stream_generate():
print(f"Received: {chunk}")from jsonAI.plugin_system import PluginRegistry
# Load custom plugins
registry = PluginRegistry()
registry.setup_default_paths()
registry.auto_discover()
# Use custom backends or tools
custom_backend = registry.get_backend("custom_llm")from jsonAI.integration_hub import IntegrationHub
# Connect to external services
hub = IntegrationHub()
await hub.github_integration(token="your_token")
await hub.slack_integration(webhook_url="your_webhook")from jsonAI.one_click_deploy import OneClickDeployer
# Deploy to multiple platforms
deployer = OneClickDeployer()
await deployer.deploy_docker()
await deployer.deploy_cloud(provider="aws")See examples/next_gen_demo.py and examples/mistral_token_limits_example.py for complete examples.
- Test installation and import in a clean environment (virtualenv, Docker, etc.)
- Run all tests and linting (pytest, flake8, mypy if used)
- Build and verify PyPI package (poetry build or python -m build)
- Finalize and verify documentation (README, API docs, deployment, EGC/validation)
- Expose and document user-facing configuration for EGC/validation
- Ensure all validation rules and entity generation configs are tested and documented
- Verify CI/CD automation for tests, lint, build, and PyPI publish
- Harden secret management for CI/CD and PyPI tokens
- Bump version and publish to PyPI
- Post-release: validate install, run, and schema-faithful output from PyPI
pip install jsonaigit clone https://github.com/yourusername/JsonAI.git
cd JsonAI
poetry install# Quick start with Docker
docker run -p 8000:8000 jsonai:latest
# Full stack with Docker Compose
docker-compose up -dThe jsonAI library is modular and consists of the following components:
- Jsonformer (jsonAI.main): Orchestrates generation, formatting, and validation
- TypeGenerator: Generates values for each JSON Schema type
- OutputFormatter: Converts data into JSON, YAML, XML, CSV
- SchemaValidator: Validates data with jsonschema
- ToolRegistry: Registers and resolves Python/MCP tools
- Async Paths:
- FullAsyncJsonformer (jsonAI.async_jsonformer): asynchronous generator taking model_backend, json_schema, prompt (aliased as AsyncJsonformer in API)
- AsyncJsonformer wrapper (jsonAI.main): wraps a Jsonformer instance for async tool execution
The project includes comprehensive tests for each component and integration:
- Unit Tests: Test individual components.
- Integration Tests: Validate the interaction between components.
To run tests:
pytest tests/Run the API with uvicorn:
uvicorn jsonAI.api:app --host 0.0.0.0 --port 8000Then open http://localhost:8000/docs for interactive Swagger UI.
- POST /generate — synchronous generation
- POST /generate/async — asynchronous generation
- POST /generate/batch — concurrent batch generation
- GET /stats — performance and cache statistics
- DELETE /cache — clear all caches
- POST /validate — validate a JSON schema
Minimal cURL examples:
# Sync generate
curl -X POST http://localhost:8000/generate -H "Content-Type: application/json" -d '{
"prompt": "Generate a simple user object",
"schema": {"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}}},
"model_name": "ollama",
"model_path": "mistral:latest"
}'
# Async generate
curl -X POST http://localhost:8000/generate/async -H "Content-Type: application/json" -d '{
"prompt": "Generate a simple user object",
"schema": {"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}}},
"model_name": "ollama",
"model_path": "mistral:latest"
}'
# Batch generate
curl -X POST http://localhost:8000/generate/batch -H "Content-Type: application/json" -d '{
"requests": [
{"prompt":"User 1","schema":{"type":"object","properties":{"name":{"type":"string"}}},"model_name":"ollama","model_path":"mistral:latest"},
{"prompt":"User 2","schema":{"type":"object","properties":{"name":{"type":"string"}}},"model_name":"ollama","model_path":"mistral:latest"}
],
"max_concurrent": 5
}'A full demonstration of environment-based configuration and schema-driven generation is provided in both:
examples/stripe_schemas/stripe_schema_demo.py(Python script)examples/stripe_schemas/stripe_schema_demo.ipynb(Jupyter notebook)
Features demonstrated:
- Loading Stripe-like schemas and environment-specific config files
- Switching between multiple schemas (
transfer_reversals_metadata,tax_rates_metadata,transfer_reversals) and environments (dev,qa,cte,perf,prod) - Using config file naming conventions:
<schema>.<env>.json(e.g.,transfer_reversals_metadata.dev.json) - Tool chaining and environment-driven config patterns
- Integration with Ollama and JsonAI's tool registry
Usage pattern:
env = "dev" # or "qa", "cte", "perf", "prod"
schema_choice = "transfer_reversals_metadata" # or "tax_rates_metadata", "transfer_reversals"
config_path = base_dir / f"{schema_choice}.{env}.json"All required schema and config files are provided in examples/stripe_schemas/.
You can run the Python script or the notebook to see how to generate and validate data for any supported schema/environment combination.
See the examples/stripe_schemas/ directory for all related files and configuration patterns.
from jsonAI.main import Jsonformer
from jsonAI.model_backends import DummyBackend
backend = DummyBackend() # replace with OllamaBackend/OpenAIBackend/etc.
# Primitive type: string
schema = {"type": "string"}
prompt = "Generate a random color name."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt)
print(jsonformer()) # e.g., "blue"
# Primitive type: number
schema = {"type": "number"}
prompt = "Generate a random floating point number."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt)
print(jsonformer()) # e.g., 3.1415
# Enum type
schema = {"type": "string", "enum": ["A", "B", "C"]}
prompt = "Pick a letter from the set A, B, or C."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt)
print(jsonformer()) # e.g., "B"
# Object type
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"isStudent": {"type": "boolean"}
}
}
prompt = "Generate a person's profile."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt)
output = jsonformer()
print(output)
schema = {
"type": "object",
"properties": {
"city": {"type": "string"},
"population": {"type": "integer"}
}
}
prompt = "Generate a city profile."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt, output_format="yaml")
output = jsonformer()
print(output)
schema = {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"score": {"type": "number"}
}
}
}
prompt = "Generate a list of students and their scores."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt, output_format="csv")
output = jsonformer()
print(output)
python -m jsonAI.cli generate --schema schema.json --prompt "Generate a product" --output-format json
python -m jsonAI.cli generate --schema complex_schema.json \
--prompt "Generate a comprehensive person profile as JSON." \
--use-ollama --ollama-model mistral:latest
- Robustly extracts the first valid JSON object from any LLM output (even if wrapped in tags or surrounded by extra text)
- Supports all JSON schema types: primitives, enums, arrays, objects, null, oneOf, nested/complex
- Validates output against the schema and warns if invalid
- Pretty-prints objects/arrays, prints primitives/null as-is
- Production-ready for any schema and LLM output style
{
"id": "profile with all supported JSON schema types.",
"name": "re",
"age": 30,
"is_active": true,
"email": "[email protected]",
"roles": ["admin", "user"],
"address": {"street": "123 Main St", "city": "Anytown", "zip": "12345", "country": "USA"},
"preferences": {"newsletter": true, "theme": "dark", "language": "en"},
"tags": ["tech", "developer"],
"score": 95,
"metadata": {"key1": "value1", "key2": "value2"},
"status": "active",
"history": [{"date": "2023-01-01", "event": "joined", "details": "Account created"}],
"profile_picture": "https://example.com/avatar.jpg",
"settings": {"notifications": true, "privacy": "private"},
"null_field": null
}
See complex_schema.json for a comprehensive schema example.
def send_email(email):
print(f"Sending email to {email}")
return "Email sent"
tool_registry = ToolRegistry()
tool_registry.register_tool("send_email", send_email)
schema = {
"type": "object",
"properties": {
"email": {"type": "string", "format": "email"}
},
"x-jsonai-tool-call": {
"name": "send_email",
"arguments": {"email": "email"}
}
}
prompt = "Generate a user email."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt, tool_registry=tool_registry)
output = jsonformer()
print(output)
def mcp_callback(tool_name, server_name, kwargs):
# Simulate MCP call
return f"Called {tool_name} on {server_name} with {kwargs}"
schema = {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"x-jsonai-tool-call": {
"name": "search_tool",
"arguments": {"query": "query"}
}
}
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt, mcp_callback=mcp_callback)
output = jsonformer()
print(output)
schema = {
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"id": {"type": "uuid"},
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
}
},
"roles": {
"type": "array",
"items": {"type": "string", "enum": ["admin", "user", "guest"]}
},
"profile": {
"oneOf": [
{"type": "object", "properties": {"age": {"type": "integer"}}},
{"type": "object", "properties": {"birthdate": {"type": "date"}}}
]
}
},
"x-jsonai-tool-call": {
"name": "send_welcome_email",
"arguments": {"email": "user.email"}
}
}
# ...setup model, tokenizer, tool_registry, etc...
jsonformer = Jsonformer(model, tokenizer, schema, prompt, tool_registry=tool_registry)
output = jsonformer()
print(output)
schema = {
"type": "object",
"properties": {
"book": {
"type": "object",
"properties": {
"title": {"type": "string"},
"author": {"type": "string"},
"year": {"type": "integer"}
}
}
}
}
prompt = "Generate details for a book."
jsonformer = Jsonformer(model_backend=backend, json_schema=schema, prompt=prompt, output_format="xml")
output = jsonformer()
print(output)You can chain multiple tools together using the x-jsonai-tool-chain schema key. Each tool in the chain receives arguments from the generated data and/or previous tool outputs.
from jsonAI.main import Jsonformer
from jsonAI.tool_registry import ToolRegistry
def add(x, y):
return {"sum": x + y}
def multiply(sum, factor):
return {"product": sum * factor}
registry = ToolRegistry()
registry.register_tool("add", add)
registry.register_tool("multiply", multiply)
schema = {
"type": "object",
"properties": {
"x": {"type": "integer"},
"y": {"type": "integer"},
"factor": {"type": "integer"}
},
"x-jsonai-tool-chain": [
{
"name": "add",
"arguments": {"x": "x", "y": "y"}
},
{
"name": "multiply",
"arguments": {"sum": "sum", "factor": "factor"}
}
]
}
prompt = "Calculate (x + y) * factor."
jsonformer = Jsonformer(
model_backend=None, # Not used in this example
json_schema=schema,
prompt=prompt,
tool_registry=registry
)
# Provide input data (simulate generated data)
jsonformer.value = {"x": 2, "y": 3, "factor": 4}
generated = jsonformer.generate_data()
result = jsonformer._execute_tool_call(generated)
print(result)
# Output will include all intermediate and final tool results.
JsonAI includes a performance suite to optimize throughput and latency.
JsonAI's output quality is validated with statistical metrics. The following table summarizes KL divergence (lower is better) and timing (seconds) for core types, measured using uniform schema sampling and the built-in metrics suite:
| Type | KL Divergence | Time (s) |
|---|---|---|
| number | 0.016813 | 4.5798 |
| integer | 0.000864 | 4.5564 |
| boolean | 0.000018 | 4.4584 |
| enum | 0.000108 | 4.4765 |
All values are well below the recommended threshold (KL < 0.5), demonstrating high-fidelity, schema-faithful sampling. See tests/test_metrics_sampling.py for methodology.
- PerformanceMonitor: measures durations for operations (async-safe)
- CachedJsonformer: two-level caching
- LRU cache for simple schema-based results
- TTL cache for prompt-based entries for complex schemas
- OptimizedJsonformer: all performance features plus cache warmup and batch helpers
- BatchProcessor: asynchronous concurrent processing (configurable semaphore)
Example:
from jsonAI.performance import OptimizedJsonformer
from jsonAI.model_backends import DummyBackend
backend = DummyBackend()
schema = {"type":"object","properties":{"name":{"type":"string"}}}
jsonformer = OptimizedJsonformer(
model=backend, # accepts a ModelBackend
tokenizer=backend.tokenizer,
schema=schema,
cache_size=1000,
cache_ttl=3600
)
# Single generation (cached)
print(jsonformer.generate("Generate a name"))
# Batch generation
requests = [
{"prompt":"User A","kwargs":{}},
{"prompt":"User B","kwargs":{}}
]
print(jsonformer.generate_batch(requests))
To inspect performance and cache stats at runtime, use the REST API GET /stats or:
jsonformer.get_comprehensive_stats()
| Type | Example | JSON | XML | YAML | CSV* |
|---|---|---|---|---|---|
| number | 3.14 | ✅ | ✅ | ✅ | ✅ |
| integer | 42 | ✅ | ✅ | ✅ | ✅ |
| boolean | true | ✅ | ✅ | ✅ | ✅ |
| string | "hello" | ✅ | ✅ | ✅ | ✅ |
| datetime | "2023-06-29T12:00:00Z" | ✅ | ✅ | ✅ | ✅ |
| date | "2023-06-29" | ✅ | ✅ | ✅ | ✅ |
| time | "12:00:00" | ✅ | ✅ | ✅ | ✅ |
| uuid | "123e4567-e89b-12d3-a456-426614174000" | ✅ | ✅ | ✅ | ✅ |
| binary | "SGVsbG8=" | ✅ | ✅ | ✅ | ✅ |
| null | null | ✅ | ( |
✅ | ( |
| array | [1,2,3] | ✅ | ✅ | ✅ | ( |
| object | {"a":1} | ✅ | ✅ | ✅ | ( |
| enum | "red" | ✅ | ✅ | ✅ | ✅ |
| p_enum | "blue" | ✅ | ✅ | ✅ | ✅ |
| p_integer | 7 | ✅ | ✅ | ✅ | ✅ |
✅ = Supported
- LLMs: HuggingFace Transformers, OpenAI, Ollama (vLLM patterns apply)
- FastAPI: See
jsonAI/api.pyandexamples/fastapi_example.py - Tool Registry: Register and call Python or MCP tools from schemas; supports tool chaining via
x-jsonai-tool-chain - Async Support:
FullAsyncJsonformerfor async generation withmodel_backend/json_schema/promptAsyncJsonformerwrapper (jsonAI.main) for async tool execution
See the examples/ directory for more advanced usage and integration patterns.
This project is licensed under the MIT License.
JsonAI leverages high-performance native libraries for data processing and extensibility:
- PyYAML for YAML serialization
- lxml for XML output
- cachetools for caching
- requests and aiohttp for HTTP
- jsonschema for validation
For any tabular or batch data processing, it is recommended to use pandas for reliability and performance. If you extend JsonAI or build custom output logic, prefer native libraries like pandas, numpy, or others for best results.
JsonAI supports multiple environments: dev, qa, perf, cte, and prod. Each environment has its own .env file at the project root.
-
Local Development:
Copy or rename the desired.env.*file to.envbefore running locally.cp .env.dev .env uvicorn jsonAI.api:app --host 0.0.0.0 --port 8000
-
Docker Compose:
Editdocker-compose.ymlto set theenv_filefor the desired environment (e.g.,.env.prod).
Or override at runtime:docker-compose --env-file .env.qa up -d
-
Docker:
Pass the environment file at runtime:docker run --env-file .env.prod -p 8000:8000 jsonai:latest
-
CI/CD:
The GitHub Actions workflow tests all environments by copying the correct.env.*file to.envfor each matrix job. -
APP_ENV Variable:
The Dockerfile setsAPP_ENV(default: dev) for extensibility. You can override this at runtime.
See docs/deployment.md for more details.
- API:
uvicorn jsonAI.api:app --host 0.0.0.0 --port 8000- CORS is enabled by default for development; harden for production
- Docker:
docker build -t jsonai:latest .docker run -p 8000:8000 jsonai:latest
- Docker Compose:
docker-compose up -d
- See
docs/deployment.mdfor more
PyPI forbids reusing the same filename for the same version. Always bump the version:
poetry version patch # or minor/major
poetry build
poetry publish -u __token__ -p $PYPI_TOKENAutomate in CI by bumping on tags and using repository secrets for tokens.
JsonAI supports streaming data generation (experimental API in examples). Example pattern:
jsonformer = Jsonformer(model_backend, json_schema, prompt)
for data_chunk in jsonformer.stream_generate_data():
print(data_chunk)
For async streaming, adapt the pattern with the async wrapper as needed.
- All native JSON schema types are now fully supported and tested, including primitives (
string,number,integer,boolean,null), enums, arrays, objects, oneOf, and nested/complex schemas. - See examples/test_json_schema_variety.py for comprehensive test coverage and usage patterns.