- Python 71.9%
- Just 28.1%
Previous commit accidentally placed `dependencies` inside [project.urls], breaking the build (hatchling rejected non-string URL value). Co-Authored-By: OpenCode + GLM-5.2 |
||
|---|---|---|
| tests | ||
| .gitignore | ||
| ankanigen.py | ||
| Justfile | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
AnkiGenerator
Build Anki vocabulary decks from the most-used words in a Japanese text file.
Give it any Japanese text — a chat log, a novel, an article, song lyrics — and it counts how often each word appears, then turns the top N most frequent words into Anki cards ordered by usage frequency. The words you encounter most in the source end up first in the deck.
100% vibe-coded by OpenCode + GLM-5.2. 0% human code. No human wrote or edited a line of the implementation — every instruction was given in natural language and the code was generated end-to-end by an AI agent.
Pairs tokenization (MeCab/UniDic via fugashi) with the JMdict dictionary (via jamdict) and emits an importable .apkg using genanki.
Each card looks like:
| Side | Content |
|---|---|
| Front | the word (kanji or kana, as actually written in the source) |
| Back | furigana (hiragana) + brief English senses |
Card order = usage frequency in the source text (most-used word first).
Setup
Requires uv (the fast Python package manager).
uv sync # create .venv and install deps
uv run python -m unidic download # one-off: extract UniDic (~526 MB)
jamdict-data bundles a prebuilt JMdict SQLite DB and is installed automatically by uv sync. On first lookup jamdict copies/uses it from ~/.jamdict/data/jamdict.db.
Usage
uv run ankanigen somefileinjp.txt -o output.apkg \
--limit 500 --deck-name "Top Vocab"
You can also invoke the module directly without installing the entry point:
uv run python ankanigen.py somefileinjp.txt -o output.apkg
Then File → Import the .apkg in Anki Desktop.
Tests
An end-to-end test lives in tests/sample_jp.txt + the test-e2e recipe in the Justfile:
just test-e2e
It builds a small deck from the sample, checks the .apkg is a valid non-empty zip, asserts kana-only words (ありがとう, おはよう) stay kana (no ateji substitution), and asserts verbs are normalised to dictionary form (no bare stems like し / い on the front).
Input format
Any plain-text file containing Japanese. As a convenience, chat-export style
lines prefixed by HH:MM<Tab>Name<Tab> are stripped down to the message body,
and [Sticker] placeholders / http(s)://… URLs are removed before tokenization:
13:54 Alice 今夜は何を食べますか?
14:51 Bob [Sticker]
14:52 Bob お寿司が食べたい!
Plain prose, articles, lyrics, etc. work just as well — every line that contains kana or kanji is tokenized.
How it works
- Filter the file down to Japanese-bearing lines.
- Tokenize each line with MeCab/UniDic, keeping tokens whose coarse POS is in
名詞 / 動詞 / 形容詞 / 副詞 / 連体詞 / 感動詞. - Count dictionary lemmas (falling back to surface form when no lemma is available), and remember which surface forms the writer actually used for each lemma.
- Look up each top lemma in JMdict, preferring the entry whose kanji/kana form matches the surface form or the lemma.
- Build cards:
- Verbs & adjectives → normalised to their dictionary form (食べた → 食べる, すごく → すごい), honouring the writer's kanji/kana choice. Wrote 食べた → card shows 食べる; wrote すごい → card shows すごい (not 凄い).
- Other parts of speech (名詞, 副詞, 感動詞, 連体詞) → the card front honours how the writer actually wrote the word:
- wrote it in kanji → show kanji (the dictionary kanji form);
- wrote it in kana → keep kana. Rare ateji kanji listings in JMdict (有り難う for ありがとうござる, 御早う for おはよう, …) are not substituted.
- Reading → furigana (hiragana-converted kana); meanings → first four English sense glosses.
- Package with
genankiusing stable model/deck IDs so re-imports update cards in place.
Notes / limitations
- Verbs and adjectives are stored in dictionary form (辞書形), e.g. 食べる, すごい. The script (kanji vs kana) follows how the writer most often wrote the word, so すごい stays すごい even though JMdict lists 凄い.
- Particles (助詞), auxiliaries (助動詞), symbols and pure-Latin tokens are excluded.
- Kana-written words like ありがとう, おはよう, うん are kept in kana — JMdict's rare ateji kanji forms are not forced onto the card front.
- Proper nouns (place names, people) show up as 名詞, so anything that recurs often in the source text will rank high.
- Default limit is 500 cards; bump with
--limit.
License
Public Domain (Creative Commons Zero v1.0 Universal / CC0). See LICENSE.
This project is 100% vibe-coded — every line was generated by an AI agent (OpenCode + GLM-5.2) from natural-language prompts, with no human-authored code. See the header note above.