We're excited to announce an upcoming feature for @nanocollective/get-md: optional AI-powered HTML to Markdown conversion using locally-run language models. This enhancement will give developers the choice between lightning-fast conversion and AI-enhanced quality, all while maintaining complete offline functionality.
The Challenge
While our current Turndown-based conversion is fast and reliable (sub-100ms for most pages), complex HTML structures like nested tables, intricate layouts, and heavily formatted content can sometimes result in less-than-perfect Markdown output. We wanted to offer a solution that could handle these edge cases better without forcing all users to adopt a slower, more resource-intensive approach.
The Solution: Optional Local LLM
We're adding support for ReaderLM-v2, a 1.5 billion parameter language model specifically designed for HTML-to-Markdown conversion. The key aspects of our approach:
- Completely optional: Turndown remains the default. Users opt-in via a simple flag.
- Runs locally: No API keys, no cloud services, no internet required (after model download).
- Full control: Developers using get-md in their applications can let their end-users decide whether to enable AI conversion.
- Smart fallback: If the LLM fails for any reason, the system automatically falls back to Turndown.
How It Works
For CLI Users
# Check if the model is available
getmd --model-info
# Download the AI model (986MB, one-time)
getmd --download-model
# Convert using AI
getmd https://example.com --use-llm
The CLI provides interactive prompts and progress bars to guide users through the model download process.
For SDK/Package Users
import {
convertToMarkdown,
checkLLMModel,
downloadLLMModel
} from '@nanocollective/get-md';
// Check if model is available
const status = await checkLLMModel();
if (!status.available) {
// Download with progress callbacks
await downloadLLMModel({
onProgress: (downloaded, total, percentage) => {
console.log(`Downloading: ${percentage.toFixed(1)}%`);
}
});
}
// Convert with AI
const result = await convertToMarkdown('https://example.com', {
useLLM: true,
onLLMEvent: (event) => {
// React to conversion events
if (event.type === 'conversion-complete') {
console.log(`Done in ${event.duration}ms`);
}
}
});
Perfect for Application Developers
One of the most powerful aspects of this feature is how it works for developers building applications with get-md. Whether you're creating an Obsidian plugin, VS Code extension, Electron app, or web service, you can give your users the choice to enable AI conversion.
Example: Obsidian Plugin
// In your plugin settings
new Setting(containerEl)
.setName('AI-powered conversion')
.setDesc('Better quality, slower (986MB model)')
.addToggle(toggle => toggle
.setValue(this.settings.useAI)
.onChange(async (value) => {
this.settings.useAI = value;
await this.saveSettings();
}));
// Add a download button if model isn't installed
if (!modelAvailable) {
new Setting(containerEl)
.addButton(button => button
.setButtonText('Download AI Model')
.onClick(async () => {
await downloadLLMModel({
onProgress: (_, __, percentage) => {
button.setButtonText(`Downloading... ${percentage}%`);
}
});
}));
}
Your users get a seamless experience with progress feedback, and the model downloads directly to their machine—no server-side infrastructure needed on your end.
Performance Trade-offs
We believe in transparency, so here's what you need to know:
| Metric | Turndown (Default) | LLM (Optional) |
|---|---|---|
| Speed | <100ms | 5-10 seconds |
| RAM | ~100MB | 2-4GB |
| Disk | 0MB | 986MB (model) |
| Quality | Good | Excellent |
| Complex layouts | Good | Excellent |
| Consistency | 100% deterministic | ~95% consistent |
When to Use Each
Use Turndown (default) for:
- Batch processing thousands of pages
- CI/CD pipelines
- Real-time conversion
- Low-resource environments
- Simple blog posts and articles
Use LLM (opt-in) for:
- High-quality single conversions
- Complex documentation sites
- Pages with intricate tables and nested structures
- When visual fidelity matters most
Technical Architecture
The LLM integration is designed to enhance, not replace, the existing pipeline:
- Content extraction (Readability) - removes ads, nav, etc.
- HTML cleaning - removes scripts, normalizes structure
- Structure enhancement - fixes heading hierarchy
- Conversion - Either Turndown OR LLM (user's choice)
- Post-processing - adds frontmatter, calculates stats
By running the LLM on pre-cleaned HTML, we get better results while reducing token usage and processing time.
Callback System for Rich UIs
We've designed a comprehensive callback system so developers can build rich user interfaces around the conversion process:
await convertToMarkdown(url, {
useLLM: true,
onLLMEvent: (event) => {
switch (event.type) {
case 'model-loading':
showSpinner('Loading AI model...');
break;
case 'download-progress':
updateProgressBar(event.percentage);
break;
case 'conversion-complete':
hideSpinner();
showSuccess(`Converted in ${event.duration}ms`);
break;
case 'fallback-start':
showWarning('Using fallback method');
break;
}
}
});
This means whether you're building a CLI tool, desktop app, or web service, you can provide users with real-time feedback on what's happening.
Why ReaderLM-v2?
We chose ReaderLM-v2 for several reasons:
- Purpose-built: Specifically designed for HTML-to-Markdown conversion
- Efficient: 1.5B parameters with GGUF quantization (Q4_K_M) runs on consumer hardware
- Multilingual: Supports 29 languages out of the box
- Proven: Outperforms much larger models on conversion tasks
- Open source: Available on Hugging Face, MIT-compatible licensing
The Q4_K_M quantized version strikes the perfect balance—high quality at 986MB, running comfortably on systems with 8GB+ RAM.
Open Questions & Future Enhancements
We're considering several enhancements for future versions:
- Hybrid mode: Use LLM only for complex sections (tables, nested structures), Turndown for simple content
- GPU acceleration: Faster inference on compatible hardware
- Caching layer: Store conversions to avoid re-processing identical content
- Alternative models: Support for other models based on user preference
- Smart detection: Automatically choose method based on HTML complexity
We'd love to hear your feedback on which features would be most valuable to you.
No Breaking Changes
This is a purely additive feature. All existing code continues to work exactly as before. The default behavior remains unchanged—fast, deterministic Turndown conversion. LLM conversion is opt-in only.
Try It Out
The implementation is currently in planning stages. We're working through the architecture and will be rolling this out in phases:
- Phase 1: Core infrastructure and LLM integration
- Phase 2: CLI and SDK integration with callbacks
- Phase 3: Enhanced features (model management, config files)
- Phase 4: Comprehensive testing and documentation
Follow our GitHub repository for updates, or check out Issue #3 to join the discussion.
We Want Your Feedback
This feature is being designed with the community in mind. We'd love to hear:
- What use cases would benefit most from AI-powered conversion?
- What should the user experience look like in your application?
- Are there specific models or configurations you'd like to see supported?
- What concerns do you have about the implementation?
Join the conversation on GitHub or reach out to us directly. Let's build something amazing together.
get-md is an open-source HTML to Markdown converter optimized for LLM consumption, built by the Nano Collective. Fast, reliable, and now with optional AI enhancement.