แผนการเรียนรู้
/

การบ้านสัปดาห์ที่ 13

Text Generator Dashboard

สร้าง Django dashboard สำหรับสร้างข้อความด้วย Language Model

1. ข้อกำหนดโครงงาน

2. โครงสร้าง Django project

3. สิ่งที่ต้องทำใน ml/train.py

4. หน้า landing page

5. วิธีรันและตรวจสอบ

6. การส่งงาน

ข้อกำหนดโครงงาน

- โมเดล: Character-level หรือ Word-level language model ด้วย PyTorch

- ข้อมูล: ใช้ข้อความภาษาไทยหรืออังกฤษ (เช่น นิยาย, บทความ, บทเพลง)

- Architecture: RNN, LSTM, หรือ GRU (เลือกได้)

- Dashboard: SSE streaming แสดง training loss + generated text แบบ real-time

- หน้า landing: แสดง รหัสนักศึกษา และ ชื่อ-นามสกุล (hardcoded)

[สำคัญ] ใช้ Django + PyTorch เท่านั้น ห้ามใช้ Hugging Face transformers

# ผลลัพธ์ที่คาดหวัง:

1. เริ่ม server แล้วเห็นหน้า landing page
   ที่มีรหัสนักศึกษาและชื่อ-นามสกุล

2. กดปุ่ม "เริ่มฝึกสอน" แล้วเห็น
   - ค่า loss ลดลงแบบ real-time
   - ข้อความที่สร้างขึ้นอัปเดตทุก epoch

3. หลังฝึกสอนเสร็จ แสดงผลลัพธ์
   - ตัวอย่างข้อความที่สร้าง (samples.txt)
   - Training loss curve

4. หน้า landing page แสดงรหัสและชื่อ
   ของนักศึกษาที่ทำโครงงาน

โครงสร้าง Django Project

DL69/wk13/
├── pyproject.toml           # uv project, Python 3.13
├── manage.py
├── mysite/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── dashboard/
│   ├── __init__.py
│   ├── apps.py
│   ├── views.py             # SSE streaming endpoint
│   ├── urls.py              # / → index, /train/ → SSE
│   ├── ml/
│   │   ├── __init__.py
│   │   └── train.py         # ★ นักศึกษาเขียนโค้ดตรงนี้
│   ├── templates/
│   │   └── dashboard/
│   │       └── index.html    # ★ ใส่รหัสและชื่อตรงนี้
│   └── static/
│       └── dashboard/
│           └── (ผลลัพธ์จาก train.py)
└── data/
    └── corpus.txt            # ข้อความสำหรับฝึกสอน

- pyproject.toml: กำหนด dependencies สำหรับ uv sync

- dashboard/ml/train.py: ไฟล์หลักที่นักศึกษาต้องเขียน

- dashboard/templates/dashboard/index.html: หน้า landing page

- data/corpus.txt: ไฟล์ข้อความสำหรับฝึกสอน

[สำคัญ] ห้ามลบหรือแก้ไขไฟล์ที่ไม่ได้ระบุว่าต้องแก้ — ใช้ไฟล์เดิมที่ให้มา

สิ่งที่ต้องทำใน ml/train.py

def train(on_progress=None):
    """
    on_progress(epoch, loss, sample_text) → เรียกทุก epoch
    """
    import torch
    import torch.nn as nn

    # 1. โหลดข้อความ
    #    text = open('data/corpus.txt').read()

    # 2. สร้าง vocabulary
    #    chars = sorted(set(text))
    #    char_to_idx = {c: i for i, c in enumerate(chars)}

    # 3. สร้าง training sequences
    #    seq_length = 100
    #    X[i] = text[i:i+seq_length]
    #    y[i] = text[i+1:i+seq_length+1]

    # 4. สร้างโมเดล LSTM
    class TextGenerator(nn.Module):
        def __init__(self, vocab_size, embed_dim=64, hidden=128):
            super().__init__()
            self.embed = nn.Embedding(vocab_size, embed_dim)
            self.lstm = nn.LSTM(embed_dim, hidden, batch_first=True)
            self.fc = nn.Linear(hidden, vocab_size)

        def forward(self, x):
            out = self.embed(x)
            out, _ = self.lstm(out)
            return self.fc(out[:, -1, :])

    # 5. Training loop
    for epoch in range(num_epochs):
        # forward, loss, backward, step
        # ทุก 10 epoch: generate sample text
        # เรียก on_progress(epoch, loss, sample)
        pass

    # 6. บันทึกผลลัพธ์
    #    - samples.txt (ตัวอย่างข้อความ)
    #    - loss_curve.png

- ข้อ 1: โหลดข้อความแล้วสร้าง vocabulary

- ข้อ 2: สร้าง training sequences ด้วย sliding window

- ข้อ 3: สร้าง LSTM model พร้อม embedding layer

- ข้อ 4: Training loop + generate sample text ทุก 10 epoch

- ข้อ 5: บันทึก samples.txt และ loss_curve.png

[เคล็ดลับ] ดู code ตัวอย่างจาก wk13.html slides เป็นแนวทาง

หน้า Landing Page

<!-- dashboard/templates/dashboard/index.html -->
<!DOCTYPE html>
<html lang="th">
<head>
  <title>Text Generator Dashboard</title>
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body x-data="{ training: false, epoch: 0, loss: 0, sample: '' }">

  <!-- ★ ใส่รหัสนักศึกษาและชื่อ-นามสกุลตรงนี้ -->
  <h1>รหัสนักศึกษา: 69000000</h1>
  <h2>ชื่อ-นามสกุล: ชื่อ นามสกุล</h2>

  <button @click="startTraining()">
    เริ่มฝึกสอน
  </button>

  <p>Epoch: <span x-text="epoch"></span></p>
  <p>Loss: <span x-text="loss"></span></p>

  <h3>ตัวอย่างข้อความที่สร้าง:</h3>
  <pre x-text="sample"></pre>

  <canvas id="chart"></canvas>

  <script>
  function startTraining() {
    training = true;
    const es = new EventSource('/train/');
    es.onmessage = function(e) {
      const m = JSON.parse(e.data);
      epoch = m.epoch;
      loss = m.loss.toFixed(4);
      if (m.sample) sample = m.sample;
      drawChart(m.epoch, m.loss);
    };
  }
  </script>
</body>
</html>

- รหัสนักศึกษา: เปลี่ยน 69000000 เป็นรหัสจริง

- ชื่อ-นามสกุล: เปลี่ยน ชื่อ นามสกุล เป็นชื่อจริง

- ปุ่ม "เริ่มฝึกสอน" เชื่อมกับ SSE endpoint

- แสดง ตัวอย่างข้อความ ที่ model สร้างขึ้นแบบ real-time

- ใช้ Canvas หรือ Chart.js สำหรับกราฟ loss

[สำคัญ] ห้ามลบ student ID และชื่อออกจากหน้า — ต้องเห็นชัดเจนเมื่อเปิดหน้า

วิธีรันและตรวจสอบ

# 1. Clone repo และ checkout branch
git clone <DL69-repo>
cd DL69
git checkout wk13

# 2. ติดตั้ง dependencies
uv sync

# 3. รัน server
uv run manage.py runserver

# 4. เปิดเบราว์เซอร์
#    http://127.0.0.1:8000/
#    → เห็นรหัสนักศึกษาและชื่อ
#    → กด "เริ่มฝึกสอน"
#    → เห็น loss ลดลง + ข้อความสร้างขึ้น real-time
#    → หลังฝึกเสร็จ เห็น samples.txt

# 5. ตรวจสอบไฟล์ผลลัพธ์
ls dashboard/static/dashboard/
#    → loss_curve.png
#    → samples.txt

- ขั้นตอนที่ 1: Clone repo แล้ว checkout branch wk13

- ขั้นตอนที่ 2: รัน uv sync เพื่อติดตั้ง dependencies

- ขั้นตอนที่ 3: รัน uv run manage.py runserver

- ขั้นตอนที่ 4: เปิด http://127.0.0.1:8000/

- ขั้นตอนที่ 5: ตรวจสอบว่าหน้า landing แสดงรหัสและชื่อ

[สำคัญ] ต้องรันได้ด้วย uv sync + uv run manage.py runserver เท่านั้น

การส่งงาน

- Branch name: wk13

- Repo: DL69 (GitHub repository ของนักศึกษา)

- สร้าง branch ใหม่จาก main

- Commit โค้ดทั้งหมดลง branch wk13

- Push ขึ้น GitHub

- แจ้ง URL ของ repo ให้อาจารย์

[สำคัญ] ห้าม commit ไฟล์ data ขนาดใหญ่ (>10MB) — ใช้ .gitignore

# สร้างและ push branch
git checkout -b wk13
git add .
git commit -m "wk13: Text Generator Dashboard"
git push origin wk13

# โครงสร้างไฟล์ที่ต้องมี
DL69/wk13/
├── pyproject.toml
├── manage.py
├── mysite/
├── dashboard/
│   ├── views.py
│   ├── ml/train.py       ← โค้ดที่เขียน
│   └── templates/
│       └── dashboard/
│           └── index.html ← ใส่รหัส+ชื่อ
└── data/
    └── corpus.txt        ← ข้อความ

# ตรวจสอบก่อนส่ง
uv sync
uv run manage.py runserver
# → หน้า landing แสดงรหัสและชื่อ
# → กดเริ่มฝึกสอน → SSE ทำงาน
# → ได้ samples.txt + loss_curve.png

เกณฑ์การให้คะแนน

- โมเดลถูกต้อง (30%): LSTM language model ทำงานได้

- SSE Streaming (20%): ฝึกสอน + สร้างข้อความแบบ real-time ได้

- หน้า landing (15%): แสดงรหัสและชื่อชัดเจน

- ผลลัพธ์ (15%): samples.txt มีข้อความที่มีความหมาย, loss curve

- โค้ดสะอาด (10%): โครงสร้างดี, มี docstring

- รันได้จริง (10%): uv sync + runserver ไม่ error

[คะแนนรวม] 100% = คะแนนการบ้านสัปดาห์ที่ 13

# ตรวจสอบก่อนส่ง:

# 1. uv sync สำเร็จ?
uv sync

# 2. server รันได้?
uv run manage.py runserver

# 3. หน้า landing แสดงรหัส+ชื่อ?
#    เปิด http://127.0.0.1:8000/

# 4. SSE ทำงาน?
#    กด "เริ่มฝึกสอน" แล้วเห็น
#    epoch, loss อัปเดต + sample text

# 5. ผลลัพธ์ครบถ้วน?
#    - loss_curve.png มีอยู่
#    - samples.txt มีข้อความ

# 6. Branch ชื่อ wk13?
git branch
#    → * wk13