PackageNew ConceptDraft

Introducing AI-Powered HTML to Markdown Conversion in get-md

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:

  1. Content extraction (Readability) - removes ads, nav, etc.
  2. HTML cleaning - removes scripts, normalizes structure
  3. Structure enhancement - fixes heading hierarchy
  4. Conversion - Either Turndown OR LLM (user's choice)
  5. 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.

Want to join the discussion? Head over to GitHub to share your thoughts!

View Discussion on GitHub