A production-ready toolkit for building AI-powered document transformation apps.
fire-light provides the building blocks I use to create AI applications — multi-provider LLM integration, resilient API calls, hallucination detection, bulk processing with checkpoint/resume, and three ready-to-use interfaces (Web, CLI, REST API).
| Module | What It Does |
|---|---|
llm.py |
Multi-provider LLM factory — OpenAI, Anthropic, Google Gemini, Ollama (local). One function call, any provider. |
resilience.py |
Retry with exponential backoff, rate-limit handling, bulk checkpoint/resume tracker. |
transform.py |
Full transformation pipeline — prompt loading, LLM call, model escalation on truncation. |
hallucination.py |
Two-stage hallucination detection: fast local text comparison + LLM-powered deep analysis. |
validate.py |
Output validation for XML, JSON, and text — well-formedness, artifact detection, completeness. |
prompts.py |
Markdown-based prompt template system with project/shared override hierarchy. |
| App | Interface | Description |
|---|---|---|
| Doc Transformer | Streamlit, CLI, FastAPI | Transform documents between formats using AI with real-time feedback |
| Content Generator | Streamlit | Generate structured documents from templates + topic descriptions |
git clone https://github.com/amelabrs/fire-light.git
cd fire-light
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txtcp .env.example .env
# Edit .env with your API key(s)Choose your provider:
| Provider | Env Var | Free Tier? |
|---|---|---|
| OpenAI | OPENAI_API_KEY |
No |
| Anthropic | ANTHROPIC_API_KEY |
No |
| Google Gemini | GOOGLE_API_KEY |
Yes |
| Ollama (local) | — (just install Ollama) | Yes |
Web UI (Streamlit):
streamlit run apps/doc_transformer/app_web.pyCLI:
python apps/doc_transformer/app_cli.py input.xml -o output.xml --prompt Transform_DocumentREST API (FastAPI):
uvicorn apps.doc_transformer.app_api:app --reload
# Then: curl -X POST http://localhost:8000/transform -H "Content-Type: application/json" -d '{"source": "...", "prompt_name": "Transform_Document"}'Content Generator:
streamlit run apps/content_generator/app.pyQuickstart example:
python examples/quickstart.pyfire-light/
├── core/ # Reusable engine
│ ├── llm.py # Multi-provider LLM factory
│ ├── resilience.py # Retry, backoff, checkpoint/resume
│ ├── transform.py # Document transformation pipeline
│ ├── hallucination.py # Source-vs-output fidelity audit
│ ├── validate.py # Structural output validation
│ └── prompts.py # Markdown prompt loader
│
├── apps/ # Ready-to-use applications
│ ├── doc_transformer/ # AI document transformation
│ │ ├── app_web.py # Streamlit UI
│ │ ├── app_cli.py # CLI
│ │ ├── app_api.py # FastAPI REST
│ │ └── prompts/ # App-specific prompts
│ │
│ └── content_generator/ # AI document generation
│ ├── app.py # Streamlit UI
│ ├── templates/ # Document skeletons
│ └── prompts/ # Generation prompts
│
├── prompts/ # Shared prompt library
├── examples/ # Quick-start scripts
└── docs/ # Architecture documentation
from core.llm import get_llm
# Swap providers with one argument — no code changes
llm = get_llm(provider="openai", model="gpt-4o")
llm = get_llm(provider="anthropic", model="claude-sonnet-4-20250514")
llm = get_llm(provider="ollama", model="llama3") # Free, local
response = llm.invoke("Hello!")from core.resilience import retry_llm_call, call_with_retry
@retry_llm_call(max_retries=3, base_delay=2.0)
def my_ai_function(text):
llm = get_llm()
return llm.invoke(text)
# Or wrap any function
result = call_with_retry(llm.invoke, "Hello!", max_retries=3)from core.hallucination import quick_fidelity_check, check_hallucination
# Stage 1: Fast local check (no API call)
hints = quick_fidelity_check(source_text, output_text)
# Stage 2: LLM-powered deep analysis
result = check_hallucination(source_text, output_text, fidelity_hints=hints)
print(result["verdict"]) # "clean" or "issues"from core.resilience import BulkProgressTracker
tracker = BulkProgressTracker(run_folder, total=len(files))
for f in files:
if tracker.is_completed(f.name):
continue # Resume from where we left off
result = process(f)
tracker.mark_completed(f.name, {"status": "ok"})
tracker.finalize()from core.transform import transform
# Automatically retries with a larger model if output is truncated
result = transform(
source=long_document,
prompt_text=prompt,
provider="openai",
model="gpt-4o-mini", # Starts here
escalate_on_truncation=True, # Auto-escalates to gpt-4o → gpt-4.1
)
print(result.model_used) # Shows which model actually produced the output- Create a folder under
apps/your_app/ - Add prompts to
apps/your_app/prompts/(or use sharedprompts/) - Import from
core/— that's it
from core.llm import get_llm
from core.prompts import load_prompt
from core.transform import transform
from core.resilience import retry_llm_call
prompt = load_prompt("Your_Prompt", project_prompts_dir=Path("apps/your_app/prompts"))
result = transform(source, prompt, provider="openai")MIT
Built by amelabrs — extracted from production AI systems that transformed thousands of documents.