মূল কনটেন্টে যান
এআই টিউটোরিয়াল

nesformer দিয়ে কম্পাইল করা Qwen3.5 মডেলের ভেতরে NES গেম চালান

এই টিউটোরিয়ালে দেখানো হয়েছে, কীভাবে nesformer একটি NES 6502 CPU, মেমরি এবং কার্ট্রিজ ROM-কে একটি স্ট্যান্ডার্ড Qwen3.5 চেকপয়েন্টে কম্পাইল করে। আপনি CLI ইনস্টল করবেন, সামঞ্জস্যপূর্ণ গেম চালাবেন, কন্ট্রোলার ইনপুট স্বয়ংক্রিয় করবেন, অ্যানিমেশন এক্সপোর্ট করবেন, একটি রেফারেন্স CPU-এর সঙ্গে এক্সিকিউশন তুলনা করবেন এবং বিকল্প ইঞ্জিনগুলো অন্বেষণ করবেন।

nesformer দিয়ে কম্পাইল করা Qwen3.5 মডেলের ভেতরে NES গেম চালানো

nesformer কী?

nesformer হলো একটি পরীক্ষামূলক NES রানটাইম, যেখানে কনসোলের 6502 CPU, 2 KB ওয়ার্ক RAM এবং কার্ট্রিজ প্রোগ্রাম ROM একটি সাধারণ Qwen3_5ForCausalLM চেকপয়েন্টের weights ও state-এর ভেতরে কাজ করে। weights প্রশিক্ষিত নয়। পরিবর্তে, CPU circuit বাস্তবায়নের জন্য একটি compiler এগুলো গণনা করে তৈরি করেছে।

গেম চলার সময় মডেলটি একবারে একটি token করে CPU execution log পূর্বাভাস দেয়। একটি Python host program কনসোলের বাকি উপাদানগুলো সরবরাহ করে: এটি graphics render করে, controller input পড়ে, timing পরিচালনা করে, I/O read-এর উত্তর দেয় এবং vertical-blanking NMI interrupt inject করে।

প্রকল্পটি Qwenputer-এর ওপর ভিত্তি করে তৈরি এবং এর compiler ও কেন্দ্রীয় memory technique পুনরায় ব্যবহার করে। প্রতিটি Gated DeltaNet head একটি state matrix ধরে রাখে। One-hot key ও query ব্যবহার করে ওই matrix-এর সারিগুলো memory cell হিসেবে কাজ করতে পারে এবং register, RAM ও cartridge data ধারণ করে।

প্রধান বৈশিষ্ট্য

  • প্রশিক্ষণের বদলে compiled: প্রতিটি nonzero weight একটি circuit specification থেকে তৈরি হয়।
  • সাধারণ checkpoint format: checkpoint-টি একটি সাধারণ Hugging Face folder এবং custom model code ছাড়াই Qwen3_5ForCausalLM.from_pretrained দিয়ে load করা যায়।
  • সম্পূর্ণ official 6502 instruction set: circuit-এ সব 151টি official opcode, addressing mode, flag, stack operation, BRK এবং NMI entry বাস্তবায়িত হয়েছে।
  • পুনর্ব্যবহারযোগ্য NROM support: একই weights দিয়ে বিভিন্ন iNES mapper 0 ROM চালানো যায়, কারণ startup-এর সময় নির্বাচিত cartridge model state-এ লেখা হয়।
  • Scripted controls: command line থেকে frame অনুযায়ী button press নির্ধারণ করা যায়।
  • Visual exports: run-গুলো compatible terminal-এ প্রদর্শন করা এবং GIF বা PNG frame হিসেবে সংরক্ষণ করা যায়।
  • Execution verification: check command মডেলের output-কে bundled reference CPU-এর সঙ্গে তুলনা করে এবং প্রথম পার্থক্যেই থেমে যায়।
  • একাধিক execution engine: nesformer একটি দ্রুত numba engine, একটি সাধারণ NumPy engine এবং একটি stock Transformers engine সরবরাহ করে।

মডেলের ভেতরে কী চলে বুঝুন

checkpoint-এ 6502 core, CPU register ও flag, 2 KB work RAM এবং একটি নির্দিষ্ট 32 KB program-ROM table রয়েছে। এটি program fetch, data read, stack operation এবং OAM DMA read-ও পরিচালনা করে।

host-এর দায়িত্বে থাকে PPU renderer, palette, controller, vblank NMI timing, cycle counting এবং APU register handling। Sound বাস্তবায়িত হয়নি। host I/O read ও NMI event-এর জন্য token stream-এ value inject করে, কিন্তু emitted trace-এর বাইরে মডেলের register বা RAM সরাসরি inspect করে না।

nesformer model inference-এর মাধ্যমে CPU emulate করে, কিন্তু এটি weights-এর ভেতরে সম্পূর্ণ NES বাস্তবায়ন নয়।

Requirements এবং folder setup

আপনার Python 3.11 বা তার পরের সংস্করণ, nesformer source archive এবং আলাদা weights archive প্রয়োজন। দুটি archive একই top-level folder-এ extract করুন। weights directory-টি Python package-এর ভেতরে নয়, তার পাশে থাকতে হবে।

nesformer/
├── nesformer/
├── chipformer/
├── roms/
├── examples/
├── tests/
├── pyproject.toml
└── weights/
    ├── config.json
    ├── generation_config.json
    ├── model.safetensors
    ├── nesformer.json
    └── SHA256SUMS

উপরের top-level directory থেকেই সব command চালান। ডিফল্টভাবে CLI, nesformer/ package-এর পাশে থাকা weights/ খোঁজে।

ডাউনলোড করা weights যাচাই করুন

weights সঠিকভাবে extract হয়েছে কি না নিশ্চিত করতে অন্তর্ভুক্ত checksum file ব্যবহার করুন:

shasum -a 256 -c weights/SHA256SUMS

checkpoint অন্য কোথাও রাখলে run, check বা trace ব্যবহারের সময় --weights /path/to/weights দিয়ে তার অবস্থান দিন। info command সরাসরি checkpoint path গ্রহণ করে।

nesformer ইনস্টল করুন

একটি virtual environment তৈরি ও activate করুন, তারপর প্রয়োজনীয় numerical এবং image-processing package ইনস্টল করুন:

python3 -m venv .venv
source .venv/bin/activate
pip install numpy scipy numba pillow

Windows-এ environment activate করুন:

.venv\Scripts\activate

ডিফল্ট fast engine numba ব্যবহার করে। প্রথমবার চালানোর সময় engine compile করতে প্রায় 20 সেকেন্ড লাগে। পরবর্তী run-গুলোতে এই compilation কাজ পুনরায় ব্যবহার করা হয়।

আপনার প্রথম game চালান

repository-তে freely licensed test ROM অন্তর্ভুক্ত রয়েছে। নিচের command-টি Thwaite-কে 600 frame চালায়, terminal-এ frame প্রদর্শন করে এবং Start ও A button press-এর একটি scripted sequence সরবরাহ করে:

python -m nesformer run roms/thwaite.nes --frames 600 --show \
  --buttons "start@90-95+200-205,a@230-233+250-253+270-273+290-293+310-313+330-333+350-353+370-373+390-393+410-413+430-433+450-453+470-473+490-493+510-513+530-533+550-553+570-573+590-593"

--show option-টি iTerm2 বা Windows Terminal-এর মতো 24-bit color support থাকা terminal-এ প্রতিটি generated frame আঁকে। execution শেষ হলে CLI ROM-এর নামে একটি animated GIF সংরক্ষণ করে, যেমন thwaite.gif।

একটি physical NES-এর তুলনায় performance অনেক ধীর। initial compilation-এর পর সাধারণত একটি frame নিতে প্রায় এক থেকে ছয় সেকেন্ড লাগে। 600-frame run NES time-এর 10 সেকেন্ডের সমান এবং প্রায় 25 মিনিট সময় নিতে পারে।

নিজের compatible ROM চালান

আপনার আইনসম্মতভাবে সংগ্রহ করা ROM roms/ directory-তে রাখুন অথবা অন্য কোনো path দিন। ROM-টিকে NROM board ব্যবহার করতে হবে, যা iNES mapper 0 হিসেবে চিহ্নিত। Compatible উদাহরণের মধ্যে রয়েছে Super Mario Bros., Donkey Kong এবং Excitebike, যদিও এই commercial ROM-গুলো অন্তর্ভুক্ত নয়।

এই উদাহরণটি Super Mario Bros. চালু করে, Right ধরে রাখে এবং কয়েকটি লাফের সময় নির্ধারণ করে:

python -m nesformer run roms/smb.nes --frames 600 --show \
  --buttons "start@60-65,right@200-600,a@250-265+300-315+360-375+420-435+480-495+540-555"

শুরুতেই ROM-টি মডেলের DeltaNet স্টেটে লোড হয়। প্রতিটি সামঞ্জস্যপূর্ণ গেমের জন্য চেকপয়েন্ট পুনর্নির্মাণের প্রয়োজন নেই।

স্ক্রিপ্ট দিয়ে কন্ট্রোল ইনপুট

--buttons অপশনটি কমা দিয়ে বিভক্ত এন্ট্রি গ্রহণ করে। প্রতিটি এন্ট্রিতে এক বা একাধিক বোতামের নাম, একটি @ চিহ্ন এবং এক বা একাধিক ফ্রেম রেঞ্জ থাকে।

start@60-65
right@200-600
a@250-265+300-315
right+b@200-600
  • start@60-65 ফ্রেম ৬০ থেকে ৬৫ পর্যন্ত Start চাপা রাখে।
  • right@200-600 নির্দিষ্ট সময়সীমা ধরে Right চাপা রাখে।
  • a@250-265+300-315 দুটি A-বোতাম চাপার সময় নির্ধারণ করে।
  • right+b@200-600 একই সঙ্গে Right এবং B চাপা রাখে।

উপলভ্য নামগুলো হলো a, b, select, start, up, down, left এবং right। ফ্রেম পাওয়ার-অন থেকে গণনা শুরু হয় এবং প্রতি সেকেন্ডে ৬০ ফ্রেম এগোয়। তাই ফ্রেম ৬০০ NES সময়ের ১০ সেকেন্ডের সমান।

সাধারণত কোনো বোতাম একটু আগে চাপা শুরু করা নিরাপদ, কারণ যেসব স্ক্রিনে চলাচল সম্ভব নয় সেখানে গেমগুলো কন্ট্রোল উপেক্ষা করে। বোতাম চাপার স্থায়িত্ব গুরুত্বপূর্ণ হতে পারে; যেমন, Super Mario Bros.-এ বেশি সময় A চাপলে লাফ আরও উঁচু হয়।

ফ্রেম আউটপুট নিয়ন্ত্রণ

ডিফল্টভাবে, run ১২০টি ফ্রেম চালায় এবং ROM-এর নাম অনুসারে একটি GIF লিখে। ফলাফল কাস্টমাইজ করতে আউটপুট অপশন ব্যবহার করুন:

python -m nesformer run roms/thwaite.nes \
  --frames 300 \
  --every 2 \
  --scale 3 \
  --gif output/thwaite.gif
  • --frames N Nটি ফ্রেমের পর থামে।
  • --gif PATH অ্যানিমেটেড GIF-এর গন্তব্য নির্ধারণ করে।
  • --png DIR সংরক্ষিত ফ্রেমগুলো আলাদা PNG ফাইল হিসেবে সংরক্ষণ করে।
  • --every N প্রতি Nতম ফ্রেম সংরক্ষণ করে।
  • --scale N সংরক্ষিত ফ্রেমগুলোকে পূর্ণসংখ্যা গুণক অনুযায়ী বড় করে।
  • --show তৈরি হওয়া ফ্রেমগুলো টার্মিনালে দেখায়।

শুধু --png ব্যবহার করলে GIF আউটপুট বন্ধ থাকে। PNG ফ্রেম এবং অ্যানিমেশন দুটিই চাইলে একটি স্পষ্ট --gif অপশন যোগ করুন।

python -m nesformer run roms/thwaite.nes \
  --frames 120 \
  --png frames \
  --gif thwaite.gif

এক্সিকিউশন পরিদর্শন ও যাচাই

রেফারেন্স CPU-এর সঙ্গে তুলনা

check কমান্ডটি চেকপয়েন্ট এবং প্রকল্পের প্রচলিত রেফারেন্স 6502-কে পাশাপাশি চালায়। প্রথম টোকেন পার্থক্য পেলেই এটি থেমে যায়:

python -m nesformer check roms/thwaite.nes --tokens 50000

ডিফল্ট তুলনার দৈর্ঘ্য ৫০,০০০ টোকেন। অন্যান্য এক্সিকিউশন কমান্ডে গ্রহণযোগ্য একই --buttons, --weights, --engine এবং --no-skip অপশন এখানে দিতে পারেন।

মডেলের টোকেন স্ট্রিম প্রিন্ট করা

মডেল থেকে নির্গত CPU রেকর্ড পরিদর্শন করতে trace ব্যবহার করুন:

python -m nesformer trace roms/thwaite.nes --tokens 100

ডিফল্ট ট্রেসের দৈর্ঘ্য ৪০টি টোকেন। বেশিরভাগ CPU নির্দেশনায় একটি টোকেন লাগে, তবে I/O, পয়েন্টার রিড, স্ট্যাক অপারেশন বা DMA-সম্পর্কিত নির্দেশনায় একাধিক টোকেনের রেকর্ড তৈরি হতে পারে।

রানের সময় টোকেন ID সংরক্ষণ

run কমান্ড পরবর্তী বিশ্লেষণের জন্য তৈরি টোকেন ID একটি ফাইলে লিখতে পারে:

python -m nesformer run roms/thwaite.nes \
  --frames 60 \
  --trace trace.txt

শুধু ফ্রেম সীমার ওপর নির্ভর না করে নির্দিষ্ট সংখ্যক তৈরি টোকেনের পর এক্সিকিউশন থামাতে --max-tokens N ব্যবহার করতে পারেন।

এক্সিকিউশন ইঞ্জিন বেছে নেওয়া

nesformer পারফরম্যান্স এবং নির্ভরতার দিক থেকে ভিন্ন তিনটি ইঞ্জিন সরবরাহ করে:

  • fast: ডিফল্ট numba ইমপ্লিমেন্টেশন। README অনুযায়ী, ডেভেলপমেন্ট মেশিনের একটি CPU কোরে এটি প্রতি সেকেন্ডে প্রায় ১,৬৫০টি টোকেন তৈরি করে।
  • numpy: তুলনামূলক সরল NumPy ইমপ্লিমেন্টেশন, যার গতি প্রতি সেকেন্ডে প্রায় ২১০টি টোকেন বলে উল্লেখ করা হয়েছে।
  • hf: স্টক Hugging Face Transformers, যার গতি প্রতি সেকেন্ডে প্রায় ১০টি টোকেন বলে উল্লেখ করা হয়েছে।

--engine দিয়ে একটি ইঞ্জিন নির্বাচন করুন:

python -m nesformer run roms/thwaite.nes --frames 3 --engine numpy

স্টক Transformers ব্যবহার

Hugging Face ইঞ্জিন নির্বাচন করার আগে অতিরিক্ত নির্ভরতা ইনস্টল করুন:

pip install "torch>=2.6" "transformers>=5.22"
python -m nesformer run roms/thwaite.nes --frames 3 --engine hf

চেকপয়েন্টের জন্য কোনো কাস্টম মডেল ইমপ্লিমেন্টেশন প্রয়োজন নেই। অভ্যন্তরীণভাবে, nesformer এটি লোড করে, একটি padding token ডিকোড করে, ক্যাশের DeltaNet স্টেটগুলোতে প্রাথমিক মেশিন স্টেট লিখে এবং এরপর তৈরি হওয়া টোকেনগুলো একবারে একটি করে আবার ইনপুট হিসেবে পাঠায়।

উন্নত টিপস

রিপোজিটরির বাইরে ওজন রাখুন

চেকপয়েন্ট অন্য কোনো স্থানে সংরক্ষিত থাকলে --weights ব্যবহার করুন:

python -m nesformer run roms/thwaite.nes \
  --weights /path/to/weights \
  --frames 120

চেকপয়েন্টের মেটাডেটা পরিদর্শন

চেকপয়েন্টের বিবরণ দেখতে information কমান্ড ব্যবহার করুন:

python -m nesformer info

ওজনগুলো ডিফল্ট ডিরেক্টরিতে না থাকলে info-তে তাদের পথ দিন।

চেকপয়েন্ট পুনর্নির্মাণ

রিপোজিটরিতে সার্কিট চেকপয়েন্ট পুনরায় তৈরি করার জন্য প্রয়োজনীয় কম্পাইলার রয়েছে। সাধারণ বিল্ড weights/-এ লিখে এবং README অনুযায়ী প্রায় ১০ সেকেন্ড সময় নেয়:

python -m nesformer build

অন্য একটি আউটপুট ডিরেক্টরি বেছে নিন:

python -m nesformer build --out compiled-weights

আইডল-লুপ স্কিপিং বোঝা

NES গেমগুলো প্রায়ই সংক্ষিপ্ত লুপে vblank-এর জন্য অপেক্ষা করে। হোস্ট যখন RAM বা I/O-তে কোনো লেখা ছাড়াই ঠিক পুনরাবৃত্তি হওয়া লুপ শনাক্ত করে, তখন এটি ঘড়িকে পরবর্তী PPU ইভেন্টের কাছাকাছি এগিয়ে নিয়ে যায় এবং অবশিষ্ট ইটারেশনগুলো চালায়। এই অপ্টিমাইজেশন দৃশ্যমান ফ্রেম ও I/O টাইমিং অক্ষুণ্ণ রেখে টোকেন জেনারেশন উল্লেখযোগ্যভাবে কমিয়ে দেয়।

প্রতিটি idle-loop ইটারেশন চালাতে --no-skip পাস করুন। এটি ধীর, তবে সম্পূর্ণ টোকেন সিকোয়েন্স অধ্যয়নের সময় উপযোগী হতে পারে:

python -m nesformer trace roms/thwaite.nes --tokens 100 --no-skip

টেস্ট স্যুট চালান

টেস্টিং নির্ভরতা ইনস্টল করে pytest চালান:

pip install pytest py65
python -m pytest -q tests

টেস্টগুলো সম্পন্ন হতে কয়েক মিনিট লাগে। এগুলো রেফারেন্স CPU-কে nestest লগের সঙ্গে তুলনা করে, কম্পাইল করা সার্কিটকে রেফারেন্সের সঙ্গে যাচাই করে, free-running weight পরীক্ষা করে এবং idle-loop অপ্টিমাইজেশন পরীক্ষা করে।

গুরুত্বপূর্ণ সীমাবদ্ধতা

  • শুধু NROM: গেমগুলোকে iNES mapper 0 ব্যবহার করতে হবে। MMC1 ও MMC3-এর মতো bank-switching mapper সমর্থিত নয়।
  • শুধু অফিসিয়াল opcode: কোনো অনানুষ্ঠানিক 6502 opcode পাওয়া গেলে HALT নির্গত হয়।
  • ROM থেকে এক্সিকিউশন: কোডকে cartridge ROM থেকে এক্সিকিউট করতে হবে; RAM-এ jump করলে HALT নির্গত হয়।
  • IRQ সমর্থন নেই: BRK ও NMI কাজ করে, কিন্তু APU frame এবং DMC IRQ কাজ করে না।
  • সীমিত I/O আচরণ: I/O register-এ read-modify-write নির্দেশনা কোনো I/O write তৈরি করে না, এবং $4020 থেকে $7FFF পর্যন্ত ঠিকানাগুলো শূন্য হিসেবে পড়া হয়।
  • আনুমানিক গ্রাফিক্স বিবরণ: রেন্ডারিং একবারে একটি scanline ধরে সম্পন্ন হয়, mid-scanline প্রভাব পুনরুৎপাদন করা হয় না, এবং sprite-0 hit ও sprite overflow আনুমানিক।
  • অডিও নেই: APU register write গ্রহণ করা হয়, কিন্তু শব্দ তৈরি হয় না।
  • ধীর এক্সিকিউশন: idle-loop skipping চালু থাকলেও প্রকল্পটি বাস্তব কনসোলের তুলনায় প্রায় 150 থেকে 290 গুণ ধীরে চলে।

উপসংহার

nesformer দেখায় যে একটি transformer checkpoint প্রশিক্ষিত language model-এর পরিবর্তে একটি নির্ভুল compiled computer হিসেবে কাজ করতে পারে। source ও weight সঠিকভাবে সাজানো হলে আপনি সামঞ্জস্যপূর্ণ NROM গেম চালাতে, controller input স্বয়ংক্রিয় করতে, frame export করতে, CPU token পরীক্ষা করতে এবং reference 6502-এর সঙ্গে execution তুলনা করতে পারেন। এর mapper, graphics, audio ও speed-সংক্রান্ত সীমাবদ্ধতাগুলো এটিকে একটি পরীক্ষামূলক সিস্টেমে পরিণত করেছে, তবে এর standard Qwen3.5 checkpoint ও verification tool সরাসরি model weight এবং DeltaNet state-এ সংরক্ষিত computation অধ্যয়নের একটি ব্যবহারিক উপায় প্রদান করে।