Skip to main content

AnkiForgeAI

License: MIT Python 3.11+ CI

AI-powered vocabulary flashcard pipeline for any language with automatic delivery to Anki. Language-agnostic via configurable YAML profiles (languages/{code}/language.yaml).

Built-in languages: ๐Ÿ‡ณ๐Ÿ‡ด Norwegian Bokmรฅl (nb), ๐Ÿ‡ฉ๐Ÿ‡ช German (de), ๐Ÿ‡ฌ๐Ÿ‡ง English (en), ๐Ÿ‡ช๐Ÿ‡ธ Spanish (es).

What it does

  1. Ingest โ€” generates word candidates:
    • by topic via LLM ("20 food-related words, A2")
    • from a URL (web page extraction + LLM parsing)
  2. Enrich โ€” adds grammar forms, translation, example sentences.
  3. Dedupe โ€” checks duplicates against existing Anki notes and staging DB.
  4. Media โ€” generates mp3 audio (edge-tts) and downloads images (pick a provider: Unsplash, Pexels, Pixabay, or key-free Openverse).
  5. Review โ€” interactive review of ambiguous candidates (CLI).
  6. Push โ€” sends approved cards to Anki via AnkiConnect.

Architecture

Decision Why
AnkiConnect, not CSV Two-way sync, dedupe against live Anki deck
SQLite as staging + audit + cache Anki = source of truth, SQLite = local index + history
forms as JSON Different schemas for nouns/verbs/adjectives per language
edge-tts over gTTS Microsoft neural voices, free, per-language quality
Pluggable image provider images.provider: Unsplash, Pexels, Pixabay, or key-free Openverse โ€” legal, free tiers
Selectable transcription transcription: practical (Cyrillic respelling) or ipa โ€” pronunciation hints aren't hardcoded to Russian speakers
Prompts in prompts/*.md Improve card quality without touching code
Any LLM provider OpenRouter or Anthropic Claude

Card statuses

pending โ†’ review โ†’ approved โ†’ pushed
              โ†“
           skipped / suspended
  • pending โ€” just created, not yet enriched
  • review โ€” potential duplicates found, needs decision
  • approved โ€” ready for push to Anki
  • pushed โ€” already in Anki (anki_note_id set)
  • skipped โ€” discarded (reason in audit_log)
  • suspended โ€” postponed

Supported Languages

Language profiles live in languages/{code}/. Currently supported:

Language Code Status
๐Ÿ‡ณ๐Ÿ‡ด Norwegian Bokmรฅl nb โœ… Complete
๐Ÿ‡ฉ๐Ÿ‡ช German de โœ… Complete
๐Ÿ‡ฌ๐Ÿ‡ง English en โœ… Complete
๐Ÿ‡ช๐Ÿ‡ธ Spanish es โœ… Complete

Select the active language with language: <code> in config.yaml, or pick it interactively via ankiforgeai setup.

Adding Your Language

  1. Create languages/{code}/language.yaml using nb or de as template:
code: xx              # ISO 639-1
name: Language Name
article: true         # whether nouns have articles
pos_labels:           # POS โ†’ target language name
  noun: ...
  verb: ...
forms:                # grammar field schema per POS
  noun:
    - {key: gender, label: "Gender"}
    - {key: ...}
tts:                  # edge-tts voices
  voice_female: xx-XX-NameNeural
anki:
  deck_name: MyDeck
back_labels:          # labels in your native language
  translation: "Translation"
  1. Copy prompts: cp prompts/*.md languages/{code}/prompts/
  2. Adapt prompts for the target language
  3. Minimal setup for a working language: language.yaml + topic_words.md

Installation

Requires Python 3.11+ and Anki desktop + the AnkiConnect addon.

As a tool (end users)

uv tool install ankiforgeai   # or: pipx install ankiforgeai / pip install ankiforgeai
ankiforgeai setup             # writes config.yaml in the current directory
ankiforgeai init              # creates the local DB and the Anki Note Type

config.yaml, data/, and media/ are created in whatever directory you run ankiforgeai from โ€” cd into a project folder first (e.g. mkdir ~/ankiforgeai && cd ~/ankiforgeai).

init is safe to re-run: if the Note Type already exists in Anki, it pushes the current card templates and CSS to it instead of skipping, so re-run it after pulling an update that changes the card design. This also applies if an update renames the Note Type itself (anki.note_type in languages/{code}/language.yaml) โ€” ankiforgeai push will fail with Note Type '...' ะฝะต ะฝะฐะนะดะตะฝ ะฒ Anki until you re-run init to create it.

From source (contributors)

git clone https://github.com/k0bad/AnkiForgeAi.git
cd AnkiForgeAi
uv venv
source .venv/bin/activate     # Linux/macOS
# .venv\Scripts\activate      # Windows
uv pip install -e ".[dev]"

# Configuration
cp .env.example .env
# edit .env โ€” add your API keys

# Initialize (DB + Anki Note Type)
ankiforgeai init

Usage

# Generate 20 food-related words at A2 level
ankiforgeai ingest topic "mat" --count 20 --level A2

# Extract words from a web page
ankiforgeai ingest url "https://example.com/lesson"

# Run interactive review
ankiforgeai review

# Push approved cards to Anki
ankiforgeai push

# Sync Anki โ†’ local cache (daily)
ankiforgeai sync

# View stats
ankiforgeai stats

# Consistency check: enrich/images config toggles vs actual card data
ankiforgeai doctor

# Delete cards permanently (frees their id for reuse; irreversible if already pushed)
ankiforgeai delete <id> [<id> ...]

Automated Daily Cycle

# Generate โ†’ dedupe (AI-adjudicated)/enrich/media โ†’ push (no Telegram notification)
python scripts/daily_topic.py

# Preview what today's topic would be
python scripts/daily_topic.py --dry-run

# Override topic and count
python scripts/daily_topic.py --topic dyr --count 5 --no-push

# Full cycle incl. notifications (config.yaml -> notifications:) โ€” use this for cron
./scripts/daily_topic.sh

daily_topic.py alone does not send notifications โ€” pass --notify (which is what daily_topic.sh does) to fan the report out to every enabled channel in config.yaml -> notifications:. Today that's a generic webhook backend (POST JSON to any URL โ€” n8n, Zapier, a custom bot gateway); see src/ankicards/notify/. Set up daily_topic.sh as a cron job for hands-free daily vocabulary generation with delivery to your configured channel.

Project Structure

src/ankicards/
โ”œโ”€โ”€ models.py              # Card, POS, Status, Decision (Pydantic)
โ”œโ”€โ”€ config.py              # config.yaml + language profiles
โ”œโ”€โ”€ db.py                  # SQLite layer
โ”œโ”€โ”€ cli.py                 # Typer CLI
โ”œโ”€โ”€ pipeline.py            # Stage orchestration
โ”œโ”€โ”€ llm.py                 # LLM client (OpenRouter/Anthropic)
โ”œโ”€โ”€ dedupe.py              # Exact + fuzzy matching (rapidfuzz)
โ”œโ”€โ”€ doctor.py              # Consistency check: enrich/images config vs card data
โ”œโ”€โ”€ migrate_ids.py         # One-time UUID โ†’ sequential int id migration
โ”œโ”€โ”€ ingest/
โ”‚   โ”œโ”€โ”€ url.py             # trafilatura + LLM
โ”‚   โ””โ”€โ”€ topic.py           # Topic-based generation
โ”œโ”€โ”€ enrich/
โ”‚   โ”œโ”€โ”€ grammar.py         # Grammar forms per POS
โ”‚   โ”œโ”€โ”€ translation.py     # Translations
โ”‚   โ”œโ”€โ”€ examples.py        # Example sentences
โ”‚   โ””โ”€โ”€ pronunciation.py   # Pronunciation hints
โ”œโ”€โ”€ media/
โ”‚   โ”œโ”€โ”€ tts.py             # edge-tts audio
โ”‚   โ””โ”€โ”€ images.py          # Image search: unsplash/pexels/pixabay/openverse
โ”œโ”€โ”€ anki/
โ”‚   โ”œโ”€โ”€ connect.py         # HTTP client for AnkiConnect
โ”‚   โ”œโ”€โ”€ sync.py            # Anki โ†’ cache sync
โ”‚   โ””โ”€โ”€ notetype.py        # Note type definition
โ”œโ”€โ”€ notify/
โ”‚   โ”œโ”€โ”€ base.py            # Notifier protocol
โ”‚   โ””โ”€โ”€ webhook.py         # Generic webhook backend (n8n, Zapier, ...)
โ””โ”€โ”€ review/
    โ”œโ”€โ”€ interactive.py     # Rich + questionary UI
    โ””โ”€โ”€ actions.py         # Non-interactive accept/skip/suspend/resume/edit/delete

languages/                 # Language profiles (YAML + prompts)
prompts/                   # Default prompts
scripts/                   # daily_topic, run_images
tests/
data/                      # DB, logs (gitignored)
media/                     # Audio, images (gitignored)

Roadmap

  • Multi-language architecture
  • Ingest by topic (LLM)
  • Ingest from URL (trafilatura + LLM)
  • Dedupe (rapidfuzz)
  • Grammar enrichment
  • edge-tts audio
  • Pluggable image providers (Unsplash / Pexels / Pixabay / Openverse)
  • Selectable pronunciation transcription (practical Cyrillic / IPA)
  • AnkiConnect push & sync
  • Interactive review CLI
  • Full auto cycle (cron + dedupe + push + notify)
  • Pluggable notification channels (generic webhook: n8n / Zapier / Hermes / any)
  • AI-adjudicated dedupe โ€” ambiguous fuzzy matches are judged by the LLM (same word vs. coincidentally similar), not blindly auto-accepted or left for a human by default
  • PyPI publication โ€” package and release workflow are ready (see DEVELOPER_GUIDE.md ยง12), pending one-time trusted-publisher setup on pypi.org

For Developers

See DEVELOPER_GUIDE.md for the full architecture reference, and CONTRIBUTING.md for contribution guidelines.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ankiforgeai-0.4.0.tar.gz (83.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ankiforgeai-0.4.0-py3-none-any.whl (116.2 kB view details)

Uploaded Python 3

File details

Details for the file ankiforgeai-0.4.0.tar.gz.

File metadata

  • Download URL: ankiforgeai-0.4.0.tar.gz
  • Upload date:
  • Size: 83.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ankiforgeai-0.4.0.tar.gz
Algorithm Hash digest
SHA256 ac44d55de6158823c57c4e0e24d7ecd0f8d226ef59b28d44254cc12c6dae7ecf
MD5 a9b638762d5ff7d00381970cae4bbce6
BLAKE2b-256 40f153d324ba0cf2097b3d6c9f8c4e0736e378b286d07e78daeb01a8310c53df

See more details on using hashes here.

Provenance

The following attestation bundles were made for ankiforgeai-0.4.0.tar.gz:

Publisher: publish.yml on k0bad/AnkiForgeAi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ankiforgeai-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: ankiforgeai-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 116.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ankiforgeai-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f299e36959799586930e13078eb689228227f2bd519ddf938586b9d14ed03ea1
MD5 91bc2f24f1dd4f8c29301cf701ad2f03
BLAKE2b-256 677c0b01fbdd3391379c38b9ef3405e0a05f244f1248204aeee95895b00bd497

See more details on using hashes here.

Provenance

The following attestation bundles were made for ankiforgeai-0.4.0-py3-none-any.whl:

Publisher: publish.yml on k0bad/AnkiForgeAi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page