Category: Python

  • เช็กความยาวของ Meta Title ด้วย Pillow ใน Python

    เช็กความยาวของ Meta Title ด้วย Pillow ใน Python

    ใครที่ติดตามงานเขียนของผม จะสังเกตว่าบทความของผมมีชื่อ (meta title) ยาวหลาย 10 บรรทัด จนกระทั่งเมื่อไม่นานมานี้:

    นั่นเป็นเพราะว่า ผมเข้าใจคำว่า long-tail keyword ผิดมาตลอด 😅

    ผมเข้าใจว่า long-tail keyword คือ การเขียนชื่อบทความให้ยาวและมีความแตกต่าง ❌

    แต่จริง ๆ long-tail keyword ไม่ต้องยาว แค่ต้องมีความเจาะจงเพื่อให้เข้าถึงผู้อ่านได้ง่าย ✅

    เช่น:

    ❌ Python (กว้างเกินไป)

    ❌ วิธีเขียนโปรแกรม Python สำหรับวิเคราะห์ข้อมูลและพัฒนาเว็บไซต์แบบมืออาชีพ พร้อมตัวอย่างโค้ดที่ใช้งานได้จริงทุกระดับตั้งแต่เริ่มต้นจนถึงขั้นสูง (ยาวเกินไป)

    ✅ เช็กความยาวของ Meta Title ด้วย Pillow ใน Python (เจาะจง ตรงประเด็น และยาวพอดี)

    ชื่อบทความควรมีความยาว 50–60 ตัวอักษร หรือ 580–600 pixels เพื่อให้แสดงผลบน Google ได้โดยไม่ถูกตัดคำเป็น “…” แบบนี้:

    เราสามารถนับตัวอักษรได้ง่าย ๆ แต่ถ้าจะดี เราควรจะนับความยาว pixel ซึ่งไม่ตรงไปตรงมาเหมือนกับการนับตัวอักษร

    หลังจาก Google ดู ผมก็เจอการคำนวณ pixel ใน Python ด้วย package ชื่อ Pillow ซึ่งใช้ง่ายใน 2 ขั้นตอนดังนี้


    1. 1️⃣ ขั้นที่ 1. สร้าง Font Object
    2. 2️⃣ ขั้นที่ 2. คำนวณความยาว
    3. 🍩 Bonus: เขียน Function เปรียบเทียบความยาว
    4. 🫵 Your Turn
    5. 📄 อ้างอิง

    1️⃣ ขั้นที่ 1. สร้าง Font Object

    ในขั้นแรก เราต้องสร้าง Font object ที่ Pillow ใช้คำนวณความยาว

    ก่อนจะสร้าง font object เราจะต้องโหลด font ที่ต้องการ เช่น Arial Bold ซึ่งเป็น font เดียวกันกับหน้า Google Search:

    Python
    # Import the package
    from pathlib import Path
    # Set the font path
    font_path = Path("/System/Library/Fonts/Supplemental/Arial Bold.ttf

    จากนั้น สร้าง Font object โดยใส่ font และ font size (18) ลงไป:

    Python
    # Import the package
    from PIL import ImageFont
    # Set the default font
    default_font = ImageFont.truetype(
    str(font_path),
    18
    )

    2️⃣ ขั้นที่ 2. คำนวณความยาว

    ในขั้นที่ 2 เราจะคำนวณความยาว ด้วย .getlength() และชื่อบทความที่ต้องการ:

    Python
    # Set the title
    my_title = "เช็กความยาวของ Meta Title ด้วย Pillow ใน Python"
    # Estimate the title length in pixel
    title_length = default_font.getlength(my_title)

    จากนั้น แสดงผลการคำนวณ:

    Python
    # Set the recommended length
    recommended_length = 580
    # Print the title length
    if title_length <= recommended_length:
    print(f"🟢 Title is within the recommended length ({title_length} pixels).")
    else:
    print(f"🔴 Title is too long ({title_length} pixels).")

    ผลลัพธ์:

    🟢 Title is within the recommended length (501.0 pixels).

    🍩 Bonus: เขียน Function เปรียบเทียบความยาว

    ในกรณีที่เรามีหลายชื่อ และไม่รู้จะเลือกชื่อไหน เราสามารถเขียน function ไว้เปรียบเทียบความยาวได้แบบนี้:

    Python
    # Import the package
    import polars as pl
    # Convert to a function
    def estimate_title_length(titles):
    # Instantiate a collector
    results = []
    # Loop through the titles
    for title in titles:
    # Estimate the length
    title_length = default_font.getlength(title)
    # Append to the results
    results.append({
    "Title": title,
    "Length (px)": title_length,
    "Is Within Range": (
    "🟢" if title_length <= recommended_length else "🔴"
    )
    })
    # Return the results as a Polars DataFrame
    return pl.DataFrame(results)

    ทดสอบ function:

    Python
    # Test the function
    titles = [
    "เช็กความยาวของ Meta Title ด้วย Pillow ใน Python",
    "วิธีวิเคราะห์ Meta Title Length ด้วย Pillow ใน Python",
    "คู่มือฉบับสมบูรณ์สำหรับการคำนวณความยาวของ Meta Title ด้วย Pillow ใน Python พร้อมตัวอย่างการวิเคราะห์",
    ]
    # Call the function
    df = estimate_title_length(titles)
    # Display the results
    df

    ผลลัพธ์:

    จะเห็นได้ว่า การเช็กความยาวของ meta title ใน Python ง่ายนิดเดียว


    🫵 Your Turn

    หลังจบบทความนี้แล้ว ลองมาคำนวณความยาวชื่อบทความใน Python กันครับ


    📄 อ้างอิง

  • Altair: สอนวิธีสร้างกราฟ Data Visualisation ใน Python

    Altair: สอนวิธีสร้างกราฟ Data Visualisation ใน Python

    Data visualisation (data viz) เป็นการแสดงข้อมูลผ่านภาพกราฟิก เพื่อช่วยในการนำเสนอและทำความเข้าใจข้อมูล

    Altair เป็น package ใน Python สำหรับสร้างกราฟข้อมูล ซึ่งมีจุดเด่นกว่า packages ยอดนิยมอย่าง Matplotlib และ Seaborn อยู่ 2 ข้อ:

    1. Declarative syntax: ใช้งานง่ายด้วยการเขียนที่เน้นสิ่งที่ต้องแสดงผล (what) แทนการกำหนดว่าจะแสดงอย่างไร (how)
    2. Interactive plotting: สามารถสร้างกราฟแบบ interactive ได้

    ในบทความนี้ ผมจะพาทุกคนไปดูวิธีใช้ Altair เพื่อสร้างกราฟใน Python กัน

    บทความนี้จะแบ่งเป็น 3 ส่วน:

    1. Dataset: แนะนำตัวอย่างข้อมูลที่จะใช้
    2. Basic plotting: การสร้างกราฟพื้นฐานใน Altair
    3. Customisation: การปรับแต่งกราฟใน Altair

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 📦 Dataset ตัวอย่าง
    2. 📊 พื้นฐานการสร้างกราฟใน Altair
    3. 🎨 วิธีปรับแต่งกราฟใน Altair
      1. 🚸 การเพิ่ม Title & Labels
      2. 🔢 การตกแต่ง Data Points
      3. 🥉 การเพิ่ม Third Variable
    4. 💪 บทสรุป
    5. 🫵 Your Turn
    6. 📃 References

    📦 Dataset ตัวอย่าง

    ในบทความนี้ เราจะใช้ cars dataset จาก vega_datasets ซึ่งมีข้อมูลรถ เช่น:

    • ชื่อรุ่น
    • ระดับการกินน้ำมัน
    • แรงม้า
    • จำนวนลูกสูบ

    เราสามารถโหลด dataset ได้แบบนี้:

    Python
    # Import the package
    from vega_datasets import data
    # Load the dataset
    cars = data.cars()
    # Preview the dataset
    cars.head()

    ผลลัพธ์:


    📊 พื้นฐานการสร้างกราฟใน Altair

    การสร้างกราฟใน Altair ประกอบด้วย 3 ส่วน:

    ComponentFor
    .Chart()กำหนด dataset
    .mark_*()กำหนดประเภทกราฟ (เช่น กราฟแท่ง)
    .encode()กำหนดการแสดงข้อมูล (เช่น แกน x-y, สี, รูปทรง)

    ทั้ง 3 ส่วนทำงานรวมกันแบบนี้:

    Python
    # Import the package
    import altair as alt
    # Create a scatter plot
    (
    alt.Chart(cars) # Set dataset
    .mark_point() # Set plot type
    .encode(
    x="Miles_per_Gallon",
    y="Horsepower"
    ) # Map data
    )

    ผลลัพธ์:

    Note: .mark_*() เรากำหนดประเภทกราฟได้ เช่น:

    MarkPlot
    .mark_boxplot()Box plot
    .mark_point()Scatter plot
    .mark_line()Line plot
    .mark_bar()Bar plot

    🎨 วิธีปรับแต่งกราฟใน Altair

    เรามาดูการปรับแต่ง 3 องค์ประกอบในกราฟกัน:

    1. Title and labels: กำหนดชื่อกราฟและแกนข้อมูล
    2. Data points: ปรับแต่งการแสดงข้อมูล (เช่น สี รูปทรง)
    3. Third variable: การเพิ่มตัวแปรที่ 3

    .

    🚸 การเพิ่ม Title & Labels

    เราสามารถเพิ่มชื่อกราฟและชื่อแกนได้ด้วย 3 คำสั่ง:

    SyntaxFor
    .properties(title)ชื่อกราฟ
    alt.X()ชื่อแกน x
    alt.Y()ชื่อแกน y

    ตัวอย่าง:

    Python
    # Customise the title and axis labels
    (
    alt.Chart(cars)
    .mark_point()
    # Add axis labels
    .encode(
    x=alt.X("Miles_per_Gallon", title="MPG"),
    y=alt.Y("Horsepower", title="Horsepower")
    )
    # Add the title
    .properties(
    title="Horsepower vs Fuel Consumption"
    )
    )

    ผลลัพธ์:

    .

    🔢 การตกแต่ง Data Points

    เราสามารถปรับการนำเสนอข้อมูล โดยกำหนด parametre ใน .mark_*() เช่น:

    ParametreProperty
    colorสี
    shapeรูปทรง
    sizeขนาด
    opacityความโปร่งแสง

    ตัวอย่าง:

    Python
    # Customise data points
    (
    alt.Chart(cars)
    # Adjust colour, shape, opacity, size
    .mark_point(
    color="red",
    shape="diamond",
    size=50,
    opacity=0.5
    )
    .encode(
    x=alt.X("Miles_per_Gallon", title="MPG"),
    y=alt.Y("Horsepower", title="Horsepower")
    )
    .properties(
    title="Horsepower vs Fuel Consumption"
    )
    )

    ผลลัพธ์:

    .

    🥉 การเพิ่ม Third Variable

    เราสามารถเพิ่มตัวแปรอื่น ๆ ได้โดยกำหนด parametre ใน .encode() เช่น:

    ParametreProperty
    colorสี
    shapeรูปทรง
    sizeขนาด
    opacityความโปร่งแสง

    ตัวอย่าง:

    Python
    # Add a third variable
    (
    alt.Chart(cars)
    .mark_point(color="red")
    .encode(
    x=alt.X("Miles_per_Gallon", title="MPG"),
    y=alt.Y("Horsepower", title="Horsepower"),
    # Add as colours
    color="Origin"
    )
    .properties(
    title="Horsepower vs Fuel Consumption"
    )
    )

    ผลลัพธ์:


    💪 บทสรุป

    Altair เป็นเครื่องมือสร้างกราฟที่ใช้งานง่ายใน Python โดยมีส่วนประกอบ 3 ส่วนหลัก:

    (
    alt.Chart()
    .mark_*()
    .encode()
    )

    และสามารถปรับแต่งได้โดยการกำหนด parametre ใน:

    1. .mark_*(): ประเภทกราฟ
    2. .encode(): สำหรับการนำเสนอตัวแปร
    3. .properties(): สำหรับชื่อกราฟ

    🫵 Your Turn

    หลังอ่านบทความนี้กันแล้ว ลองมาใช้ Altair กันนะครับ


    📃 References

    Intro to Altair:

    Using Altair:

    Comparing Altair with other packages:

  • วิธีสร้าง RAG Pipeline ด้วย Haystack 2.0 ใน Python

    วิธีสร้าง RAG Pipeline ด้วย Haystack 2.0 ใน Python

    ในบทความก่อน ผมได้แนะนำให้ทุกคนได้รู้จักกับ Haystack 2.0 ซึ่งเป็น package สำหรับสร้าง LLM (large language model) application ใน Python

    ในบทความนี้ ผมจะมาแนะนำการใช้ Haystack 2.0 ในการทำ RAG (Retrieval-Augmented Generation) pipeline ซึ่งเป็นการใช้งานหลักของ Haystack 2.0

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🤨 What Is RAG?
    2. 🗂️ Pipeline 1. Indexing
      1. 1️⃣ Step 1. Create Documents
      2. 2️⃣ Step 2. Create a Splitter
      3. 3️⃣ Step 3. Create Embedder
      4. 4️⃣ Step 4. Create a Vector Store
      5. 5️⃣ Step 5. Create a Document Writer
      6. 6️⃣ Step 6. Create an Indexing Pipeline
      7. 7️⃣ Step 7. Run the Pipeline
    3. 🔍 Pipeline 2. Querying
      1. 1️⃣ Step 1. Create a Query Embedder
      2. 2️⃣ Step 2. Create a Retriever
      3. 3️⃣ Step 3. Create a Prompt Builder
      4. 4️⃣ Step 4. Create a Response Generator
      5. 5️⃣ Step 5. Create a Pipeline
      6. 6️⃣ Step 6. Run the Pipeline
    4. 💪 Summary
    5. ⏭️ Next
    6. 📃 References

    🤨 What Is RAG?

    RAG เป็นเทคนิคที่ช่วยให้ LLM ตอบคำถามได้ดีขึ้น โดยส่งเอกสารที่เกี่ยวข้องไปให้ LLM สร้างคำตอบ

    RAG pipeline ประกอบด้วย 2 ส่วน:

    1. Indexing pipeline: จัดเตรียมเอกสาร
    2. Querying pipeline: ค้นหาเอกสารและเขียนคำตอบ

    Pipeline 1. Indexing pipeline:

    Documents
    ↓
    Split Documents into chunks
    ↓
    Embed chunks into vectors
    ↓
    Write Documents to vector store

    Pipeline 2. Querying pipeline:

    Query
    ↓
    Embed query
    ↓
    Retrieve relevant chunks from vector store
    ↓
    Add retrieved chunks to prompt
    ↓
    Send prompt to LLM
    ↓
    Return answer

    เราไปดูการสร้างแต่ละส่วนด้วย Haystack 2.0 กัน ผ่านตัวอย่างการสร้างบอทตอบคำถามข่าวจาก BBC News Archive dataset กัน


    🗂️ Pipeline 1. Indexing

    Indexing pipeline มี 5 ส่วนประกอบ:

    1. Documents: เอกสารต้นทาง
    2. Splitter: แยกเอกสาร
    3. Embedder: แปลงเอกสารให้เป็น vector
    4. Vector store: ตัวจัดเก็บ vector
    5. Writer: ส่ง vector ไปเก็บที่ vector store

    และเราสามารถสร้าง pipeline ได้ใน 7 ขั้นตอน:

    1. Create Documents
    2. Create a splitter
    3. Create an embedder
    4. Create a vector store
    5. Create a document writer
    6. Create an indexing pipeline
    7. Run the pipeline

    ไปดูการเขียน code ในแต่ละขั้นตอนกัน

    .

    1️⃣ Step 1. Create Documents

    ในขั้นแรก เราจะสร้าง Document object หรือเอกสารที่จะใส่เข้าไปใน RAG pipeline

    ในตัวอย่าง เราจะโหลดเอกสารที่เก็บไว้ในไฟล์ CSV แบบนี้:

    Python
    # Import the package
    import pandas as pd
    # Load the CSV
    df = pd.read_csv("bbc-news-data.csv", sep="\t")
    # Inspect the first 5 rows
    df.head(5)

    ผลลัพธ์:

    และแปลงให้เป็น Document object แบบนี้:

    Python
    # Import the package
    from haystack import Document
    # Instantiate a collector
    docs = []
    # Loop through the records
    for row in df.itertuples():
    doc = Document(
    content=row.content,
    meta={
    "title": row.title,
    "category": row.category,
    "filename": row.filename
    }
    )
    docs.append(doc)
    # Inspect one Document
    docs[0]

    ผลลัพธ์:

    Document(id=7fe87ca8e57420adb9ed47866809d38424003dd43b4eefdf6b1a400eb3709677, content: ' Quarterly profits at US media giant TimeWarner jumped 76% to $1.13bn (£600m) for the three months t...', meta: {'title': 'Ad sales boost Time Warner profit', 'category': 'business', 'filename': '001.txt'})

    .

    2️⃣ Step 2. Create a Splitter

    ในขั้นที่ 2 เราจะสร้าง splitter ที่จะแยกเอกสารออกเป็นก้อน ๆ หรือ chunk ซึ่งจะทำให้ค้นหาเอกสารได้ดีขึ้น

    Splitter มีหลายประเภท:

    SplitterSplit Method
    DocumentSplitter()แบ่งตามคำ บรรทัด ย่อหน้า หรือหน้า
    ChonkieTokenDocumentSplitter()แบ่งตามจำนวน token
    RecursiveDocumentSplitter()แบ่งตาม list ที่เรากำหนด

    ในตัวอย่าง เราจะใช้ RecursiveDocumentSplitter() กัน:

    Python
    # Import the package
    from haystack.components.preprocessors import RecursiveDocumentSplitter
    # Create a splitter
    splitter = RecursiveDocumentSplitter(
    split_length=180,
    split_overlap=30,
    split_unit="word",
    separators=[
    "\n\n",
    "sentence",
    "\n",
    " ",
    ]
    )

    .

    3️⃣ Step 3. Create Embedder

    ในขั้นที่ 3 เราจะสร้าง embedder ที่จะเปลี่ยน chunk ให้เป็น vector หรือตัวเลขที่ใช้ค้นหาเอกสารใน RAG pipeline

    ตัวอย่าง chunk:

    British Airways has blamed high fuel prices ...

    ตัวอย่าง vector:

    [
    -0.0312,
    0.0847,
    -0.0129,
    0.0455,
    0.0068,
    -0.0974,
    0.0381,
    0.0616,
    -0.0442,
    0.0193,
    ...
    ]

    RAG pipeline จะใช้ vector ในการค้นหาเอกสารที่เกี่ยวข้อง โดยเอกสารและคำถามที่มี vector คล้ายกันก็ยิ่งมีเนื้อหาที่เกี่ยวข้องกัน

    เช่น “ข่าวเทคโนโลยี” จะมี vector ที่ใกล้เคียงกับหัวข่าว “Apple เปิดตัว iPhone รุ่นใหม่” มากกว่า “ผลบอลพรีเมียร์ลีกเมื่อคืนนี้”

    ในตัวอย่าง เราจะใช้ embedder ชื่อ Sentence Transformers จาก HuggingFace กัน:

    Python
    # Import the package
    from haystack_integrations.components.embedders.sentence_transformers import (
    SentenceTransformersDocumentEmbedder
    )
    # Create a document embedder
    document_embedder = SentenceTransformersDocumentEmbedder(
    model="sentence-transformers/all-MiniLM-L6-v2",
    meta_fields_to_embed=["title"],
    )

    .

    4️⃣ Step 4. Create a Vector Store

    ในขั้นที่ 4 เราจะสร้าง vector store สำหรับจัดเก็บเอกสารและ vector กัน

    ในตัวอย่าง เราจะสร้าง vector store ชั่วคราวบนเครื่องแบบนี้:

    Python
    # Import the package
    from haystack.document_stores.in_memory import InMemoryDocumentStore
    # Create a vector store
    vector_store = InMemoryDocumentStore(
    embedding_similarity_function="cosine"
    )

    .

    5️⃣ Step 5. Create a Document Writer

    ในขั้นที่ 5 เราจะสร้าง document writer ที่จะส่งเอกสารไปเก็บใน vector store:

    Python
    # Import the package
    from haystack.components.writers import DocumentWriter
    # Create a document writer
    document_writer = DocumentWriter(
    document_store=vector_store
    )

    .

    6️⃣ Step 6. Create an Indexing Pipeline

    ในขั้นที่ 6 เราจะเชื่อมต่อส่วนต่าง ๆ เข้าด้วยกัน

    เริ่มจากสร้าง Pipeline object:

    Python
    # Import the package
    from haystack import Pipeline
    # Instantiate a Pipeline object
    indexing_pipeline = Pipeline()

    เพิ่มส่วนประกอบ โดยกำหนดชื่อและตัวแปร:

    Python
    # Add the components
    indexing_pipeline.add_component("splitter", splitter)
    indexing_pipeline.add_component("embedder", document_embedder)
    indexing_pipeline.add_component("writer", document_writer)

    แล้วเชื่อมส่วนประกอบเข้าด้วยกัน โดยกำหนดว่า แต่ละส่วนประกอบจะส่งและรับอะไรจากกันบ้าง:

    pipeline.connect("sender.output", "receiver.input")

    ตัวอย่าง:

    Python
    # Connect the components
    indexing_pipeline.connect("splitter.documents", "embedder.documents")
    indexing_pipeline.connect("embedder.documents", "writer.documents")

    สุดท้าย เราสามารถดู pipeline ที่สร้างขึ้นได้แบบนี้:

    Python
    # Display the pipeline
    indexing_pipeline.show()

    ผลลัพธ์:

    .

    7️⃣ Step 7. Run the Pipeline

    ในขั้นสุดท้าย เราจะรัน pipeline เพื่อเอาเอกสารเข้าไปเก็บใน vector store:

    Python
    # Run the indexing pipeline
    indexing_result = indexing_pipeline.run(
    {
    "splitter": {
    "documents": docs
    }
    }
    )
    # Display the result
    print(indexing_result)

    ผลลัพธ์:

    {'writer': {'documents_written': 7182}}

    เท่านี้ เราก็มี indexing pipeline ไว้ใช้งานแล้ว


    🔍 Pipeline 2. Querying

    Querying pipeline มี 4 ส่วนประกอบ:

    1. Query embedder: แปลงคำถามเป็น vector
    2. Retriever: ค้นหาเอกสารที่เกี่ยวข้อง
    3. Prompt builder: สร้าง prompt
    4. Response generator: เขียนคำตอบ

    และเราสามารถสร้างและประกอบทั้ง 4 อย่างเข้าด้วยกันได้ใน 6 ขั้นตอน:

    1. Create a query embedder
    2. Create a retriever
    3. Create a prompt builder
    4. Create a response generator
    5. Create a querying pipeline
    6. Run the pipeline

    .

    1️⃣ Step 1. Create a Query Embedder

    ในขั้นแรก เราจะสร้าง embedder ที่จะเปลี่ยนคำถามของผู้ใช้งานให้เป็น vector ที่เราจะใช้ค้นหาเอกสารที่เกี่ยวข้องได้:

    Python
    # Import the package
    from haystack_integrations.components.embedders.sentence_transformers import (
    SentenceTransformersTextEmbedder
    )
    # Create a question embedder
    question_embedder = SentenceTransformersTextEmbedder(
    model="sentence-transformers/all-MiniLM-L6-v2"
    )

    .

    2️⃣ Step 2. Create a Retriever

    ในขั้นที่ 2 เราจะสร้าง retriever หรือตัวค้นหาเอกสารที่เกี่ยวข้องใน vector store:

    Python
    # Import the package
    from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
    # Create a retriever
    retriever = InMemoryEmbeddingRetriever(
    document_store=vector_store,
    top_k=5
    )

    .

    3️⃣ Step 3. Create a Prompt Builder

    ในขั้นที่ 3 เราจะสร้าง prompt builder ที่จะประกอบ prompt ที่จะส่งไปให้ LLM เพื่อตอบคำถาม

    เราจะเริ่มจากกำหนด system prompt ที่จะกำหนดพฤติกรรมการตอบคำถาม:

    Python
    # Set the system prompt
    system_prompt = """
    You are a helpful assistant for a historical BBC News Archive.
    Answer only from the retrieved BBC article passages.
    Rules:
    - Be concise.
    - Do not use outside knowledge.
    - Do not invent facts that are not supported by the passages.
    - The archive is historical, so do not present its content as current news.
    - Cite factual claims using source labels such as [1] or [2].
    - If the retrieved passages do not contain enough evidence, say that clearly.
    - Response in short bullet points.
    - At the end of the answer, include a "Sources:" section listing only the sources that were actually cited in the answer. Format each source as:
    - [n] <Title>
    """

    และ user prompt ที่จะส่งเอกสารที่เกี่ยวข้องกับคำถามของผู้ใช้งานไปให้กับ LLM:

    Python
    # Set the user prompt
    user_prompt = """
    Question:
    {{ question }}
    Retrieved BBC archive passages:
    {% for doc in docs %}
    [{{ loop.index }}]
    Title: {{ doc.meta["title"] }}
    Category: {{ doc.meta["category"] }}
    Filename: {{ doc.meta["filename"] }}
    Passage:
    {{ doc.content }}
    {% endfor %}
    Write a concise answer using only the retrieved passages.
    After the answer, include:
    Sources:
    {% raw %}- [n] <Title>{% endraw %}
    where each title corresponds to the cited passage, and list only the sources that were actually cited in the answer.
    """

    สังเกตว่า เราใช้ Jinja syntax (การเขียน {{}} และ {}) เพื่อทำให้เราแทนที่เอกสารลงไปในตัวแปรใน prompt ได้

    หลังจากกำหนด system และ user prompt แล้ว เราจะสร้าง prompt builder แบบนี้:

    Python
    # Import the packages
    from haystack.components.builders import ChatPromptBuilder
    from haystack.dataclasses import ChatMessage
    # Create a prompt builder
    prompt_builder = ChatPromptBuilder(
    template=[
    ChatMessage.from_system(system_prompt.strip()),
    ChatMessage.from_user(user_prompt.strip())
    ],
    required_variables=["question", "docs"],
    )

    .

    4️⃣ Step 4. Create a Response Generator

    ในขั้นที่ 4 เราจะสร้าง response generator หรือ LLM ที่จะตอบคำถามขึ้นมา

    เริ่มจากกำหนด API key:

    Python
    # Import the packages
    import os
    from dotenv import load_dotenv
    # Load the .env content
    load_dotenv()
    # Get the API key
    GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")

    และสร้าง response generator:

    Python
    # Import the packages
    from haystack.utils import Secret
    from haystack_integrations.components.generators.google_genai import (
    GoogleGenAIChatGenerator
    )
    # Create a generator
    generator = GoogleGenAIChatGenerator(
    model="gemini-2.5-flash",
    api_key=Secret.from_token(GEMINI_API_KEY),
    generation_kwargs={
    "temperature": 0.2
    }
    )

    .

    5️⃣ Step 5. Create a Pipeline

    ในขั้นที่ 5 เราจะเชื่อมต่อทุกส่วนใน querying pipeline เข้าด้วยกัน โดยใช้วิธีเดียวกันกับ indexing pipeline

    สร้าง Pipeline object:

    Python
    # Import the package
    from haystack import Pipeline
    # Instantiate a Pipeline object
    querying_pipeline = Pipeline()

    เพิ่มส่วนประกอบ:

    Python
    # Add the components
    querying_pipeline.add_component("question_embedder", question_embedder)
    querying_pipeline.add_component("retriever", retriever)
    querying_pipeline.add_component("prompt_builder", prompt_builder)
    querying_pipeline.add_component("generator", generator)

    เชื่อมส่วนประกอบเข้าด้วยกัน:

    Python
    # Connect the components
    querying_pipeline.connect("question_embedder.embedding", "retriever.query_embedding")
    querying_pipeline.connect("retriever.documents", "prompt_builder.docs")
    querying_pipeline.connect("prompt_builder.prompt", "generator.messages")

    ดู pipeline ที่สร้างขึ้นมา:

    Python
    # Display the pipeline
    querying_pipeline.show()

    ผลลัพธ์:

    .

    6️⃣ Step 6. Run the Pipeline

    ในขั้นสุดท้าย เราจะเรียกใช้งาน querying pipeline กัน

    เริ่มจากสร้าง function สำหรับเรียกใช้งาน pipeline เพื่อให้ง่ายต่อการเรียกใช้:

    Python
    # Create the function
    def run_query(query: str):
    # Run the pipeline
    result = querying_pipeline.run(
    {
    "question_embedder": {
    "text": query
    },
    "prompt_builder": {
    "question": query
    }
    }
    )
    # Return the result
    return result["generator"]["replies"][0].text

    จากนั้น เรียกใช้งานโดยถามเกี่ยวกับข่าวที่อยู่ใน BBC News Archive เช่น:

    Python
    # Set the question
    my_question = "What concerns did users raise about Google’s AutoLink feature?"
    # Run the query
    query_result = run_query(query=my_question)
    # Display the result
    print(query_result)

    ผลลัพธ์:

    Users raised several concerns about Google’s AutoLink feature:
    * It directs people to pre-selected commercial websites [1].
    * Google's dominant market position could give a competitive edge to firms like Amazon [1].
    * It creates links based on webpage information without the publisher's permission [1].
    * Online libraries and other websites might direct users to commercial sites like Amazon or rival services against their will or in conflict with their own advertising [4].
    * Some users felt it would only be fair if websites had to opt-in or receive revenue for "click throughs" to commercial sites [2].
    * Concerns were raised about user choice, transparency regarding Google's payments, and the ability to substitute preferred companies for those chosen by Google [3].
    * There was an objection to users being forced or tricked into using the service [3].
    * The feature was compared to Microsoft's Smart Tags, which was widely criticised [2].
    Sources:
    - [1] Google's toolbar sparks concern
    - [2] Google's toolbar sparks concern
    - [3] Google's toolbar sparks concern
    - [4] Google's toolbar sparks concern

    💪 Summary

    RAG pipeline ใน Haystack 2.0 ประกอบด้วย 2 ส่วน ซึ่งสร้างได้แบบนี้:

    Pipeline 1. Indexing pipeline:

    1. Create Documents
    2. Create a splitter
    3. Create an embedder
    4. Create a vector store
    5. Create a document writer
    6. Create a pipeline
    7. Run the pipeline

    Pipeline 2. Querying pipeline:

    1. Create a query embedder
    2. Create a retriever
    3. Create a prompt builder
    4. Create a response generator
    5. Create a querying pipeline
    6. Run the pipeline

    ⏭️ Next

    หลังอ่านบทความจบแล้ว ลองมาใช้ Haystack 2.0 กันดูนะครับ:

    1. ดูตัวอย่าง dataset และ code ในบทความนี้
    2. ดูวิธีสร้าง LLM application ด้วย Haystack 2.0
    3. ดูคู่มือการใช้งาน Haystack 2.0

    📃 References

  • วิธีใช้ Haystack 2.0 เชื่อมต่อ LLM ด้วย Python ใน 4 ขั้นตอน

    วิธีใช้ Haystack 2.0 เชื่อมต่อ LLM ด้วย Python ใน 4 ขั้นตอน

    ในบทความก่อน ผมพาทุกคนไปรู้จักกับการใช้ LangChain ซึ่งเป็น package ยอดนิยมสำหรับสร้าง LLM (large language model) application อย่าง chatbot

    ในบทความนี้ ผมจะพาทุกคนไปรู้จักกับ Haystack 2.0 ซึ่งเป็นอีกหนึ่ง package ที่ทำงานได้เหมือนกับ LangChain

    แม้ว่า LangChain เป็นที่นิยมและใช้งานง่าย แต่ก็แลกมาด้วยข้อจำกัดใน “การมองเห็น” เพราะ LangChain ซ่อนการทำงานหลาย ๆ อย่างไว้หลัง code ไม่กี่บรรัดเพื่อให้เราใช้งานง่าย เมื่อเกิด bug ขึ้นมา เราจะไม่รู้เลยว่า error อยู่ที่จุดไหน จนกว่าเราจะแกะการทำงานเบื้องหลัง code ที่เราเขียนออกมา

    Haystack เป็น package ที่มี “การมองเห็น” ที่สูงกว่า เพราะมีการทำงานแบบแยกส่วนประกอบ หรือ component เหมือนกับรถยนต์ที่ประกอบขึ้นมาจากหลายชิ้นส่วน อย่างเครื่องยนต์ ถังน้ำมัน ล้อ และพวงมาลัย เราสามารถกำหนดได้ว่า เราอยากได้ชิ้นส่วนไหนแบบไหน และแต่ละชิ้นส่วนจะประกอบกันยังไง เมื่อเป็นเช่นนี้ เราจะรู้ได้ว่าข้อผิดพลาดอยู่ที่ไหน เพราะเราเป็นคนที่ประกอบทุกอย่างขึ้นมาเอง

    ในบทความนี้ ผมจะพาทุกคนไปดูการใช้ Haystack เพื่อเชื่อมต่อกับ LLM ผ่านตัวอย่างการสร้าง AI ตอบคำถามเกี่ยวกับ mental model กัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. ⭐️ High-Level View
    2. 📜 Step 1. Create a Prompt Builder
    3. 🤖 Step 2. Create an LLM Instance
    4. 🪈 Step 3. Create a Pipeline
    5. 🏃 Step 4. Run
    6. 💪 Summary
    7. 😺 GitHub
    8. 📃 References

    ⭐️ High-Level View

    ในการใช้ Haystack เชื่อมต่อกับ LLM เราจะใช้ component 3 อย่าง:

    1. Prompt builder สำหรับเก็บ prompt
    2. LLM instance สำหรับเรียก LLM
    3. Pipeline สำหรับเชื่อมทุก component เข้าด้วยกัน

    โดยเราจะเรียกใช้งาน 3 components นี้ใน 4 ขั้นตอน:

    1. Create a prompt builder
    2. Create an LLM instance
    3. Create a pipeline
    4. Run

    ไปดูตัวอย่างทั้ง 4 ขั้นตอนกัน


    📜 Step 1. Create a Prompt Builder

    ในขั้นแรก เราจะสร้าง prompt builder สำหรับเก็บ prompt กัน

    เราจะเริ่มจากสร้าง system prompt และ user prompt:

    Python
    # System prompt
    system_prompt = """
    You are an expert curator of mental models across science, philosophy, and applied reasoning.
    Your task is to explain mental models clearly and accurately using a fixed schema.
    If the origin of a model is unclear or debated, state that explicitly.
    Do not invent historical sources. Be concise and concrete.
    """
    # User prompt
    user_prompt = "Explain the following mental model: {{model_query}}"

    Note: เราใช้ {{}} ใน user prompt เพื่อที่เราจะสร้างแทนที่ค่าใน user prompt ได้ในภายหลัง เช่น ถ้าเราต้องการถามเกี่ยวกับ “First-Principles Thinking” user prompt ของเราก็จะกลายเป็น:

    "Explain the following mental model: First-Principles Thinking"

    จากนั้น เราจะใส่ prompts ลงใน ChatPromptBuilder():

    Python
    # Import required packages
    from Haystack.components.builders import ChatPromptBuilder
    from Haystack.dataclasses import ChatMessage
    # Create a prompt builder instance
    prompt_builder = ChatPromptBuilder(
    template=[
    ChatMessage.from_system(system_prompt.strip()),
    ChatMessage.from_user(user_prompt)
    ],
    required_variables=["model_query"]
    )

    Note: เรากำหนด required_variables เพื่อกันไม่ให้ {{model_query}} เป็นค่าว่าง


    🤖 Step 2. Create an LLM Instance

    ในขั้นที่ 2 เราจะสร้าง LLM instance สำหรับเชื่อมต่อกับ LLM โดยในตัวอย่าง เราจะใช้ Gemini

    เราจะเริ่มจากดึง API key ที่เก็บไว้ใน .env:

    Python
    # Import required packages
    import os
    # Retrieve the API key
    GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")

    จากนั้น กำหนด structured output หรือหน้าตา output ที่เราต้องการ ด้วย Pydantic:

    Python
    # Import required packages
    from pydantic import BaseModel, Field
    from typing import List, Literal
    # Define the output schema
    class MentalModel(BaseModel):
    # Mental model name
    model_name: str = Field(
    description="The commonly accepted name of the mental model"
    )
    # Origin or source
    origin: str = Field(
    description="Where the model comes from (a person, book, field, or cultural origin)"
    )
    # Brief description
    description: str = Field(
    description="A brief explanation of what the mental model is and why it matters"
    )
    # Example
    example: str = Field(
    description="A concrete real-world example illustrating the mental model"
    )
    # Tags
    tags: List[str] = Field(
    description="Short tags such as decision-making, systems thinking, learning, and philosophy"
    )

    หน้าตา structured output ที่เราจะได้:

    {
    "model_name": "",
    "origin": "",
    "description": "",
    "example": "",
    "tags": []
    }

    สุดท้าย เราจะใส่ API key และ structured output ลงใน LLM instance:

    Python
    # Import required packages
    from Haystack.utils import Secret
    from Haystack_integrations.components.generators.google_genai import GoogleGenAIChatGenerator
    # Create an LLM instance
    llm_with_structured_output = GoogleGenAIChatGenerator(
    model="gemini-2.5-flash",
    api_key=Secret.from_token(GEMINI_API_KEY),
    generation_kwargs={
    "temperature": 0.5,
    "response_format": MentalModel
    }
    )

    🪈 Step 3. Create a Pipeline

    ในขั้นที่ 3 เราจะเชื่อมต่อ prompt builder และ LLM instance เข้าด้วยกัน

    เริ่มจากสร้าง pipeline:

    Python
    # Import the required package
    from Haystack import Pipeline
    # Create a pipeline instance
    chain = Pipeline()

    เพิ่ม prompt builder และ LLM instance ลงใน pipeline:

    Python
    # Add the prompt builder and LLM instances
    chain.add_component(
    "prompt_builder", # Name
    prompt_builder # Instance
    )
    chain.add_component(
    "llm", # Name
    llm_with_structured_output # Instance
    )

    แล้วเชื่อมต่อ prompt builder และ LLM instance เข้าด้วยกัน:

    Python
    # Connect the components
    chain.connect(
    "prompt_builder.prompt", # Sender: prompt from prompt builder
    "llm.messages" # Receiver: message from LLM instance
    )

    Note: เรากำหนดให้ prompt builder ส่ง system และ user prompts ให้เป็น input สำหรับ LLM instance:

    Prompt FROM prompt builder
    ↓
    Messages TO LLM instance

    🏃 Step 4. Run

    ในขั้นสุดท้าย เราจะรัน pipeline และดึงผลลัพธ์ที่ต้องการออกมา

    ตัวอย่างเช่น ถามเกี่ยวกับ “Compound Interest”:

    Python
    # Run the pipeline with a mental-model query
    raw_result = chain.run(
    data={
    "prompt_builder": {"model_query": "Compound Interest"}
    }
    )

    ดึงผลลัพธ์ที่ต้องการ:

    Python
    # Extract the structured-output text from the raw result
    reply_json = raw_result["llm"]["replies"][0].text
    # Validate the structured output
    result = MentalModel.model_validate_json(reply_json)
    # Print the validated structured output
    print(result.model_dump())

    ผลลัพธ์:

    {
    "model_name": "Compound Interest",
    "origin": (
    "Finance, Mathematics. The concept dates back to ancient Mesopotamia, "
    "with formalization in mathematics and finance over centuries."
    ),
    "description": (
    "Compound interest is the interest on a loan or deposit calculated "
    "based on both the initial principal and the accumulated interest from "
    "previous periods. It matters because it illustrates exponential growth, "
    "where small, consistent gains over time lead to significantly larger "
    "returns, making it a powerful force in finance and many other systems."
    ),
    "example": (
    "If you invest $1,000 at a 5% annual interest rate, after one year "
    "you have $1,050. In the second year, you earn 5% not just on the "
    "initial $1,000, but on the full $1,050, resulting in $1,102.50. "
    "This 'interest on interest' accelerates growth significantly over "
    "decades compared to simple interest."
    ),
    "tags": [
    "Finance",
    "Growth",
    "Long-term thinking",
    "Mathematics",
    "Systems thinking",
    ],
    }

    💪 Summary

    ในบทความนี้ เราได้ทำความรู้จักกับ Haystack ซึ่งเป็น package สำหรับสร้าง LLM application กัน

    เราได้เรียนเกี่ยวกับ 3 components สำหรับเชื่อมต่อกับ LLM:

    1. Prompt builder
    2. LLM instance
    3. Pipeline

    และการเชื่อมต่อกับ LLM ใน 4 ขั้นตอน:

    1. Create a prompt builder
    2. Create an LLM instance
    3. Create a pipeline
    4. Run

    😺 GitHub

    ดูตัวอย่าง code ทั้งหมดได้ที่ GitHub


    📃 References

  • วิธีสร้าง RAG Pipeline ด้วย LangChain ใน Python

    วิธีสร้าง RAG Pipeline ด้วย LangChain ใน Python

    RAG (Retrieval-Augmented Generation) เป็นเทคนิคที่ช่วยให้ LLM (large language model) ตอบคำถามได้แม่นยำขึ้น และไม่ถูกจำกัดด้วย knowledge cutoff หรือความรู้ที่จำกัดจากตอน train model

    RAG ทำงานใน 2 ขั้นตอน:

    1. Retrieve: ดึงเอกสารที่เกี่ยวข้อง
    2. Generate: สร้างคำตอบจากเอกสารที่ได้มา

    RAG มีข้อดี 3 ข้อ:

    1. คำตอบมีความแม่นยำมากขึ้น
    2. คำตอบมีความเกี่ยวข้องกับคำถามมากขึ้น
    3. ช่วยอัปเดตความรู้ให้กับ LLM ได้โดยไม่ต้อง train model ใหม่

    ในบทความนี้ เราจะมาดูวิธีการสร้าง RAG pipeline ด้วย LangChain ซึ่งเป็น framework ในการพัฒนาแอปพลิเคชัน LLM กัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🔆 Overview
    2. 📑 Step 1. Load Documents
    3. 📚 Step 2. Split Text
    4. 💾 Step 3. Embed & Store Chunks
    5. 🔎 Step 4. Create a Retriever
    6. 🤖 Step 5. Generate a Response
    7. 💪 Summary
    8. 😺 GitHub
    9. 📃 References

    🔆 Overview

    เราใช้ LangChain สร้าง RAG pipeline ได้ใน 5 ขั้นตอน

    1. Load documents
    2. Split text
    3. Embed and store chunks
    4. Create a retriever
    5. Generate a response

    เราไปดูการสร้าง RAG pipeline กับตัวอย่างบอทตอบคำถามเกี่ยวกับนโยบาย HR เช่น การลาและสวัสดิ กัน


    📑 Step 1. Load Documents

    ในขั้นแรก เราจะโหลดเอกสารที่เป็นข้อมูลของ RAG pipeline ก่อน

    LangChain มีหลาย functions สำหรับโหลดเอกสาร เช่น:

    FunctionDocument
    TextLoader()Text file
    UnstructuredMarkdownLoader()Markdown file
    CSVLoader()CSV file
    JSONLoader()JSON file
    PyPDFLoader()PDF file
    DirectoryLoader()ไฟล์จากในโฟลเดอร์

    ในตัวอย่าง เราจะใช้ DirectoryLoader() เพราะเราเก็บเอกสารไว้ในโฟลเดอร์ชื่อ documents:

    documents/
    ├── benefits_policy.txt
    ├── compensation_policy.txt
    ├── leave_policy.txt
    └── remote_work_policy.txt

    ตัวอย่างข้อมูลในเอกสาร benefits_policy.txt:

    DataWise Co. Benefits Policy
    Full-time employees receive health insurance after completing probation.
    The company provides annual health checkups once per year.
    Employees can claim up to 2,000 THB per month for wellness activities such as fitness memberships, yoga classes, or mental health support.
    Employees are also eligible for learning support. The company reimburses up to 10,000 THB per year for approved online courses, books, or professional certificates.

    วิธีใช้ DirectoryLoader():

    Python
    # Import packages
    from langchain_community.document_loaders import DirectoryLoader
    from langchain_community.document_loaders import TextLoader
    # Initialise loader
    loader = DirectoryLoader(
    path="documents",
    glob="*.txt",
    loader_cls=TextLoader,
    loader_kwargs={"encoding": "utf-8"}
    )
    # Load documents
    docs = loader.load()

    การใช้งาน DirectoryLoader():

    • path = โฟลเดอร์ที่ต้องการโหลด
    • glob = pattern ชื่อไฟล์ที่ต้องการโหลด (เช่น "*.txt" หมายถึง ไฟล์ที่ลงชื่อด้วย .txt ทั้งหมด)
    • loader_cls = function ที่จะใช้โหลด (เช่น TextLoader())
    • loader_kwargs = argument เพิ่มเติมสำหรับ function ที่จะใช้โหลด

    เราสามารถดูตัวอย่างเอกสารที่โหลดแล้วได้แบบนี้:

    Python
    # View loaded documents
    for doc in docs:
    print("=" * 50)
    print(doc.metadata["source"])
    print("=" * 50)
    print(doc.page_content[:200])

    ผลลัพธ์:

    ==================================================
    documents/remote_work_policy.txt
    ==================================================
    DataWise Co. Remote Work Policy
    Employees may work from home up to 2 days per week.
    Remote work must be approved by the employee's direct manager.
    Employees must be reachable on Slack during core w
    ==================================================
    documents/benefits_policy.txt
    ==================================================
    DataWise Co. Benefits Policy
    Full-time employees receive health insurance after completing probation.
    The company provides annual health checkups once per year.
    Employees can claim up to 2,000 THB
    ==================================================
    documents/compensation_policy.txt
    ==================================================
    DataWise Co. Compensation Policy
    Salary is paid on the last working day of each month.
    Performance bonuses are reviewed once per year in December.
    Employees may receive an annual salary adjustment
    ==================================================
    documents/leave_policy.txt
    ==================================================
    DataWise Co. Leave Policy
    Full-time employees receive 10 days of annual leave per year after completing probation.
    Employees receive 15 days of paid sick leave per year.
    Sick leave of 3 consecutive

    📚 Step 2. Split Text

    ในขั้นที่ 2 เราจะแบ่ง text ในเอกสารออกเป็นก้อน ๆ หรือ chunk เพราะการแบ่ง text จะช่วยให้การค้นหาข้อมูลง่ายขึ้น

    LangChain มี 3 functions หลักในการแบ่ง text:

    FunctionMethod
    CharacterTextSplitter()แบ่งตามจำนวน character ที่กำหนด
    TokenTextSplitter()แบ่งตามจำนวน token ที่กำหนด
    RecursiveCharacterTextSplitter()แบ่งตามย่อหน้า บรรทัด และประโยค

    ในตัวอย่าง เราจะใช้ RecursiveCharacterTextSplitter() เพราะเป็นวิธีที่เก็บรักษาความหมายของ text ได้ดีกว่าวิธีอื่น:

    วิธีใช้ RecursiveCharacterTextSplitter():

    Python
    # Import package
    from langchain_text_splitters import RecursiveCharacterTextSplitter
    # Create splitter
    text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=100
    )
    # Split documents
    chunks = text_splitter.split_documents(docs)

    ดูตัวอย่าง text ที่แบ่งแล้วได้ตามนี้:

    Python
    # View results
    for i, chunk in enumerate(chunks[:5]):
    print(f"Chunk {i+1}")
    print("Source:", chunk.metadata["source"])
    print(chunk.page_content)
    print("-" * 50)

    ผลลัพธ์:

    Chunk 1
    Source: documents/remote_work_policy.txt
    DataWise Co. Remote Work Policy
    Employees may work from home up to 2 days per week.
    Remote work must be approved by the employee's direct manager.
    Employees must be reachable on Slack during core working hours from 10:00 AM to 4:00 PM.
    Employees working remotely are responsible for maintaining a stable internet connection and a quiet work environment.
    New employees may request remote work only after completing their first month.
    --------------------------------------------------
    Chunk 2
    Source: documents/benefits_policy.txt
    DataWise Co. Benefits Policy
    Full-time employees receive health insurance after completing probation.
    The company provides annual health checkups once per year.
    Employees can claim up to 2,000 THB per month for wellness activities such as fitness memberships, yoga classes, or mental health support.
    Employees are also eligible for learning support. The company reimburses up to 10,000 THB per year for approved online courses, books, or professional certificates.
    --------------------------------------------------
    Chunk 3
    Source: documents/compensation_policy.txt
    DataWise Co. Compensation Policy
    Salary is paid on the last working day of each month.
    Performance bonuses are reviewed once per year in December.
    Employees may receive an annual salary adjustment based on company performance, individual performance, and market benchmarks.
    Overtime pay is available only for non-managerial employees and must be approved by a manager before the overtime work begins.
    --------------------------------------------------
    Chunk 4
    Source: documents/leave_policy.txt
    DataWise Co. Leave Policy
    Full-time employees receive 10 days of annual leave per year after completing probation.
    Employees receive 15 days of paid sick leave per year.
    Sick leave of 3 consecutive days or more requires a medical certificate.
    Employees should submit annual leave requests at least 7 days in advance through the HR system.
    Unused annual leave can be carried over for up to 5 days into the next calendar year.
    --------------------------------------------------

    สังเกตว่า text ถูกแบ่งย่อหน้า ทำให้ chunk ที่ได้มีความหมายที่ครบถ้วนในตัวเอง


    💾 Step 3. Embed & Store Chunks

    ในขั้นที่ 3 เราจะ embed และเก็บข้อมูลลงใน vector database

    Embedding คือ การแปลง chunk ให้กลายเป็น vector คือ ชุดตัวเลขที่เป็นตัวแทนของ chunk

    ตัวอย่าง chunk:

    "Employees can work from home up to two days per week."

    ตัวอย่าง vector:

    [
    0.021,
    -0.184,
    0.736,
    0.094,
    -0.511,
    0.302,
    0.087,
    -0.624
    ]

    Vector เป็นสิ่งที่ระบบจะใช้ในการค้นหาเอกสารที่เกี่ยวข้อง โดย vector ที่มีความหมายใกล้เคียงกัน จะมีตัวเลขที่ใกล้เคียงกัน เมื่อเราต้องการหาเอกสาร ระบบจะดึงเอกสารที่มี vector ใกล้เคียงกับคำถามของเราขึ้นมาให้

    ใน LangChain เราสามารถเลือก model ที่จะใช้ embedding ได้ ในตัวอย่าง เราจะใช้ Gemini กัน:

    Python
    # Import packages
    import os
    from langchain_google_genai import GoogleGenerativeAIEmbeddings
    # Get API key
    GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
    # Create embedder
    document_embedder = GoogleGenerativeAIEmbeddings(
    model="gemini-embedding-001",
    task_type="retrieval_document",
    google_api_key=GEMINI_API_KEY
    )

    หลังจากได้ embedding model แล้ว เราจะสร้าง vector database เพื่อเก็บ vector โดยในตัวอย่างเราจะใช้ FAISS database:

    Python
    # Import package
    from langchain_community.vectorstores import FAISS
    # Build vector DB
    vectorstore = FAISS.from_documents(
    documents=chunks,
    embedding=document_embedder
    )

    สังเกตว่า เราใส่ document_embedder ไปใน vector database ด้วย เพื่อแปลง chunk เป็น vector และเก็บลงใน database


    🔎 Step 4. Create a Retriever

    ในขั้นที่ 4 เราจะสร้าง retriever ที่ทำหน้าที่ค้นหา vector โดยใช้ .as_retriever() แบบนี้:

    Python
    # Creater retriever
    retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 2}
    )

    เราสามารถทดสอบ retriever เพื่อดูว่า จะได้เอกสารอะไรกลับมา ได้แบบนี้:

    Python
    # Test retriever
    question = "Do I need a medical certificate for sick leave?"
    relevant_docs = retriever.invoke(question)
    for i, doc in enumerate(relevant_docs, start=1):
    print(f"Retrieved chunk {i}")
    print("Source:", doc.metadata["source"])
    print(doc.page_content)
    print("-" * 60)

    ผลลัพธ์:

    Retrieved chunk 1
    Source: documents/leave_policy.txt
    DataWise Co. Leave Policy
    Full-time employees receive 10 days of annual leave per year after completing probation.
    Employees receive 15 days of paid sick leave per year.
    Sick leave of 3 consecutive days or more requires a medical certificate.
    Employees should submit annual leave requests at least 7 days in advance through the HR system.
    Unused annual leave can be carried over for up to 5 days into the next calendar year.
    ------------------------------------------------------------
    Retrieved chunk 2
    Source: documents/compensation_policy.txt
    DataWise Co. Compensation Policy
    Salary is paid on the last working day of each month.
    Performance bonuses are reviewed once per year in December.
    Employees may receive an annual salary adjustment based on company performance, individual performance, and market benchmarks.
    Overtime pay is available only for non-managerial employees and must be approved by a manager before the overtime work begins.
    ------------------------------------------------------------

    🤖 Step 5. Generate a Response

    ในขั้นสุดท้าย เราจะให้ LLM สร้างคำตอบโดยใช้ข้อมูลใน vector database

    ในตัวอย่างเราจะลองใช้ Gemini ช่วยคิดคำตอบให้กับเรา

    เราจะเริ่มจากเชื่อมต่อกับ Gemini และสร้าง prompt ก่อน:

    Python
    # Import packages
    from langchain_google_genai import ChatGoogleGenerativeAI
    from langchain_core.prompts import ChatPromptTemplate
    # Initialise Gemini
    llm = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    temperature=0,
    google_api_key=GEMINI_API_KEY
    )
    # Create prompt template
    prompt = ChatPromptTemplate.from_template("""
    You are an HR policy assistant.
    Answer the user's question using only the policy context below.
    Rules:
    - Do not use outside knowledge.
    - If the answer is not in the context, say:
    "I could not find this information in the available company policies."
    - Keep the answer concise.
    - Mention the source policy file when possible.
    Policy context:
    {context}
    User question:
    {question}
    """)

    จากนั้น กำหนดคำถามและดึงเอกสารที่เกี่ยวข้องจาก vector database

    Python
    # Ask a question
    question = "Do I need a medical certificate for sick leave?"
    # Retrieve relevant document chunks
    relevant_docs = retriever.invoke(question)
    # Combine retrieved chunks into one context string
    context = "\n\n".join(
    [
    f"Source: {doc.metadata['source']}\n"
    f"{doc.page_content}"
    for doc in relevant_docs
    ]
    )
    # Inspect retrieved context before sending it to Gemini
    print("Retrieved context:")
    print(context)

    ผลลัพธ์:

    Retrieved context:
    Source: documents/leave_policy.txt
    DataWise Co. Leave Policy
    Full-time employees receive 10 days of annual leave per year after completing probation.
    Employees receive 15 days of paid sick leave per year.
    Sick leave of 3 consecutive days or more requires a medical certificate.
    Employees should submit annual leave requests at least 7 days in advance through the HR system.
    Unused annual leave can be carried over for up to 5 days into the next calendar year.
    Source: documents/compensation_policy.txt
    DataWise Co. Compensation Policy
    Salary is paid on the last working day of each month.
    Performance bonuses are reviewed once per year in December.
    Employees may receive an annual salary adjustment based on company performance, individual performance, and market benchmarks.
    Overtime pay is available only for non-managerial employees and must be approved by a manager before the overtime work begins.

    แล้วส่งข้อมูลคำถามและเอกสารให้กับ Gemini:

    Python
    # Add context and question to prompt template
    messages = prompt.invoke(
    {
    "context": context,
    "question": question
    }
    )
    # Send prompt to Gemini
    response = llm.invoke(messages)
    # Print Gemini's answer
    print(response.content)

    ผลลัพธ์:

    Yes, sick leave of 3 consecutive days or more requires a medical certificate. (Source: documents/leave_policy.txt)

    เพื่อให้เราใช้งาน RAG pipeline ได้ง่าย เราสามารถแปลงโค้ดชุดนี้ให้เป็น function ได้:

    Python
    # Convert to function
    def ask_policy_question(question: str) -> str:
    """
    Retrieve relevant policy chunks, send them to Gemini,
    and return Gemini's answer.
    """
    # Retrieve relevant chunks
    relevant_docs = retriever.invoke(question)
    # Combine retrieved chunks into context
    context = "\n\n".join(
    [
    f"Source: {doc.metadata['source']}\n"
    f"{doc.page_content}"
    for doc in relevant_docs
    ]
    )
    # Add context and question to prompt template
    messages = prompt.invoke(
    {
    "context": context,
    "question": question
    }
    )
    # Send completed prompt to Gemini
    response = llm.invoke(messages)
    # Return answer text
    return response.content

    เพื่อที่เราจะเขียนโค้ดสั้นลงในครั้งถัด ๆ ไป:

    Python
    # Test function
    answer = ask_policy_question("Who is eligible for health insurance?")
    print(answer)

    ผลลัพธ์:

    Full-time employees receive health insurance after completing probation. (Source: documents/benefits_policy.txt)

    💪 Summary

    ในบทความนี้ เราได้เรียนรู้การสร้าง RAG pipeline ด้วย LangChain ใน 5 ขั้นตอน:

    1. Load documents: โหลดเอกสารสำหรับ RAG pipeline
    2. Split text: แบ่ง text ในเอกสารเป็น chunk
    3. Embed and store chunks: แปลง chunk เป็น vector และเก็บลงใน database
    4. Create a retriever: สร้างตัวค้นหาเอกสารจาก vector database
    5. Generate a response: สร้างคำตอบจากเอกสาร

    😺 GitHub

    ดูตัวอย่าง code และเอกสารทั้งหมดได้ที่ GitHub


    📃 References

  • วิธีโหลดข้อมูล Google Sheets มาวิเคราะห์ใน Python บน Google Colab ใน 3 ขั้นตอน–ตัวอย่างจาก Harry Potter transaction dataset

    วิธีโหลดข้อมูล Google Sheets มาวิเคราะห์ใน Python บน Google Colab ใน 3 ขั้นตอน–ตัวอย่างจาก Harry Potter transaction dataset

    Google Sheets เป็นเครื่องมือเก็บข้อมูลที่ทุกคนสามารถเข้าถึงได้ฟรี และมักเป็นที่เก็บข้อมูลทั้งส่วนตัว (เช่น รายรับรายจ่าย) และธุรกิจ (เช่น ข้อมูลการขาย ข้อมูลลูกค้า)

    แม้ว่า Google Sheet จะวิเคราะห์ข้อมูลได้ แต่การวิเคราะห์จะมีประสิทธิภาพมากกว่า เมื่อเราใช้ programming language อย่าง Python เข้ามาช่วย

    นอกจากความรวดเร็วในการประมวลผล และรองรับข้อมูลปริมาณมาก Python ยังสามารถวิเคราะห์แบบอัตโนมัติได้ด้วย เพียงแค่เราเขียน code รอเอาไว้

    ในบทความนี้ เราจะมาดูวิธีการโหลดข้อมูลจาก Google Sheet เข้ามาวิเคราะห์ใน Python บน Google Colab กัน

    บทความนี้แบ่งเป็น 3 ส่วน:

    1. Load spreadsheet
    2. Load worksheet
    3. Load data

    สำหรับคนที่ต้องการทำตาม สามารถดูไฟล์ตัวอย่างได้ตาม link:

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 1️⃣ Step 1. Load Spreadsheet
      1. ✅ 1.1 Authorise
      2. 📖 1.2 Open Spreadsheet
    2. 2️⃣ Step 2. Load Worksheet
      1. 📋 2.1 List
      2. 🫳 2.2 Select
    3. 3️⃣ Step 3. Load Data
      1. 👓 3.1 Read Data
      2. 🐼 3.2 Convert to DataFrame
      3. 📈 3.3 Analyse
    4. 💪 Summary
    5. 📃 References

    1️⃣ Step 1. Load Spreadsheet

    เริ่มแรก เราจะโหลด spreadsheet ที่ต้องการ ใน 2 ขั้นตอน:

    1. Authorise: ให้สิทธิ์การเข้าถึง Google Drive กับ Colab
    2. Open spreadsheet: เชื่อมต่อ Google Sheet ที่ต้องการ

    .

    ✅ 1.1 Authorise

    เราเปิดสิทธิ์การเข้าถึง Google Drive ให้กับ Colab ได้แบบนี้:

    # Grant Colab access to Google services
    # Import package
    from google.colab import auth
    # Enable access to Google services
    auth.authenticate_user()

    เมื่อกด “Run”, Google จะพาเราไปที่หน้า Sign In ให้เรากด “Continue”:

    จากนั้น ติ๊ก checkbox เพื่อให้สิทธิ์กับ Colab แล้วกด “Continue”

    หลังเปิดสิทธิ์ ให้เราสร้าง client เพื่อเข้าถึง Google Drive:

    # Connect to Google Drive
    # Import packages
    import gspread
    from google.auth import default
    # Get credentials and Google Cloud project ID
    creds, _ = default()
    # Create Google Sheet client
    gc = gspread.authorize(creds)

    Note:

    • default() จะคืนค่าให้ 2 อย่าง คือ credentials และ Google Cloud project ID
    • เราจะใช้เฉพาะ credentials
    • ส่วน Google Cloud project ID เราจะปล่อยทิ้งไป โดยเก็บไว้ใน _

    .

    📖 1.2 Open Spreadsheet

    หลังจากสร้าง client แล้ว เราจะเชื่อมต่อกับ spreadsheet ซึ่งเราจะต้องเอา ID ของ spreadsheet มาจาก URL ตามตัวอย่างในรูป:

    ให้เรา copy ID มาใช้แบบนี้:

    # Load spreadsheet
    # Define spreadsheet ID
    spreadsheet_id = "12MglU8pFc_7XAylqANyqm8aLQNwvL98fXObjHEjrRvQ"
    # Open spreadsheet
    spreadsheet = gc.open_by_key(spreadsheet_id)
    # Print spreadsheet title
    print(spreadsheet.title)

    ผลลัพธ์:

    Diagon Alley Artefacts

    ตอนนี้ เราก็โหลด spreadsheet สำเร็จแล้ว

    ตัวอย่าง spreadsheet:


    2️⃣ Step 2. Load Worksheet

    หลังจากโหลด Google Sheet แล้ว เราจะเชื่อมต่อกับ worksheet ที่ต้องการ ใน 2 ขั้นตอน:

    1. List: ดูรายชื่อ worksheet ทั้งหมดใน Google Sheet
    2. Select: เลือก worksheet

    .

    📋 2.1 List

    เราดูรายชื่อ worksheet ทั้งหมดได้แบบนี้:

    # List worksheets
    # Get all worksheet names
    worksheets = spreadsheet.worksheets()
    # Print them
    for ws in worksheets:
    print(ws.title)

    ผลลัพธ์:

    transactions
    Sheet2
    Sheet3

    .

    🫳 2.2 Select

    จากนั้น ให้เราโหลด worksheet ที่ต้องการ (เช่น transactions):

    # Select worksheet
    worksheet = spreadsheet.worksheet("transactions")

    ตอนนี้ เราก็เชื่อมต่อกับ worksheet สำเร็จแล้ว


    3️⃣ Step 3. Load Data

    สุดท้าย เราจะโหลดข้อมูลจาก worksheet ใน 3 ขั้นตอน:

    1. Read data: โหลดข้อมูลจาก worksheet
    2. Convert to DataFrame: เปลี่ยนข้อมูลให้เป็น DataFrame
    3. Analyse: วิเคราะห์ข้อมูลตามต้องการ

    .

    👓 3.1 Read Data

    เราจะโหลดข้อมูลจาก worksheet แบบนี้:

    # Get all data from worksheet
    data = worksheet.get_all_values()
    # Print result
    data

    โดยข้อมูลที่ได้จะเป็น list of lists (1 list = 1 row):

    .

    🐼 3.2 Convert to DataFrame

    เพื่อช่วยให้เราวิเคราะห์ข้อมูลได้ง่าย เราจะเปลี่ยนข้อมูลให้เป็น DataFrame ด้วย pandas:

    # Convert data to df
    # Import package
    import pandas as pd
    # Convert
    df = pd.DataFrame(
    data=data[1:],
    columns=data[0]
    )
    # Print result
    df

    ผลลัพธ์:

    .

    📈 3.3 Analyse

    จากนั้น เราสามารถวิเคราะห์ข้อมูลได้ตามต้องการ เช่น คำนวณยอดขายทั้งหมด:

    # Find total sales per category
    # Convert column types to numeric
    df["quantity"] = pd.to_numeric(df["quantity"], errors="coerce")
    df["unit_price"] = pd.to_numeric(df["unit_price"], errors="coerce")
    # Calculate total sales per row
    df["revenue"] = df["quantity"] * df["unit_price"]
    # Calculate sum sales
    total_sales = df["revenue"].sum()
    # Print result
    print(total_sales)

    ผลลัพธ์:

    11600.0

    Note:


    💪 Summary

    ในบทความนี้ เราดูวิธีโหลดข้อมูล Google Sheet เข้ามาใน Python บน Google Colab ใน 3 ขั้นตอน:

    Step 1. Load spreadsheet:

    CodeFor
    auth.authenticate_user()เปิดสิทธิ์เข้าถึง Google Drive
    default()รับ credentials
    gspread.authorize(creds)สร้าง client
    gc.open_by_key(spreadsheet_id)เชื่อมต่อ Google Sheet

    Step 2. Load worksheet:

    CodeFor
    spreadsheet.worksheets()ดูรายชื่อ worksheet ทั้งหมด
    spreadsheet.worksheet("worksheet_name")เลือก worksheet

    Step 3. Load data:

    CodeFor
    worksheet.get_all_values()โหลดข้อมูลใน worksheet
    pd.DataFrame(data=data[1:], columns=data[0])แปลงข้อมูลให้เป็น DataFrame

    📃 References

  • วิธีใช้ LangChain เชื่อมต่อ LLM ด้วย Python ใน 5 ขั้นตอน

    วิธีใช้ LangChain เชื่อมต่อ LLM ด้วย Python ใน 5 ขั้นตอน

    langchain เป็น framework สำหรับสร้างแอปพลิเคชั่นที่ใช้ large language model (LLM) ที่ช่วยลดความยุ่งยากการเรียกใช้งาน API โดยตรง

    langchain มีข้อดี 3 อย่าง:

    1. Modular: ใช้งานง่าย ด้วยการเขียนเป็นส่วน ๆ หรือ module (เหมือนเลโก้)
    2. Use case: รองรับการใช้งานหลายหลาก เพราะสามารถประกอบ module เข้าด้วยกันได้หลายแบบ (ต่อเลโก้ได้หลายแบบ)
    3. Integration: ใช้งานร่วมเครื่องมือได้กับหลากหลาย เช่น OpenAI, Hugging Face, databricks

    ในบทความนี้ เรามาดูวิธีใช้ langchain เพื่อทำงานกับ LLM อย่างง่ายกัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. ☀️ Overview
    2. 🤖 Step 1. Set LLM
    3. 💬 Step 2. Set Prompt
    4. 📦 Step 3. Set Output Structure
    5. ⛓️‍💥 Step 4. Chain
    6. 🏃 Step 5. Run
      1. ☝️ Single Run
      2. 🎳 Batch Run
    7. 💪 Summary
    8. 🫵 Your Turn
    9. 📄 References

    ☀️ Overview

    การใช้งาน langchain มีอยู่ 5 ขั้นตอน ได้แก่:

    1. Set LLM: เลือก LLM ที่ต้องการ
    2. Set prompt: สร้าง prompt สำหรับคุยกับ LLM
    3. Set output structure: กำหนดหน้าตา output ที่ต้องการ
    4. Chain: เชื่อม LLM และ prompt เข้าด้วยกัน เพื่อสร้าง pipeline ในการเรียกใช้ LLM
    5. Run: เรียกใช้งาน LLM

    เราไปดูการใช้งาน ผ่านการสร้าง chatbot ตอบคำถามเกี่ยวกับ mental model กัน


    🤖 Step 1. Set LLM

    langchain รองรับการใช้งาน LLM หลายเจ้า เช่น:

    ในตัวอย่าง เราจะเลือกใช้ Gemini โดยเริ่มจากโหลด module สำหรับเชื่อมกับ Gemini:

    Python
    # Import package
    from langchain_google_genai import ChatGoogleGenerativeAI

    แล้วสร้าง LLM instance ขึ้นมา:

    Python
    # Create model instance
    llm = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    temperature=0.5,
    api_key="YOUR_API_KEY"
    )
    • model: ชื่อ LLM ที่เราต้องการใช้งาน
    • temperature: ระดับความสุ่มของคำตอบจาก LLM (ค่ายิ่งสูง คำตอบยิ่งมีความหลากหลาย ส่วนยิ่งค่าน้อย คำตอบจะยิ่งมีความคล้ายคลึงกัน)
    • api_key: API key สำหรับใช้งาน LLM (ดูวิธีการสร้าง Gemini API key ฟรี)

    💬 Step 2. Set Prompt

    ในขั้นที่ 2 เราจะสร้าง prompt สำหรับคุยกับ LLM กัน:

    1. โหลด module
    2. กำหนด prompt

    ขั้นย่อยที่ 1. โหลด module สำหรับสร้าง prompt:

    Python
    # Import package
    from langchain_core.prompts import ChatPromptTemplate

    ขั้นย่อยที่ 2. กำหนด prompt โดยแยกระหว่าง:

    1. System prompt: บทบาทและสไตล์การตอบคำถามของ LLM (เช่น ผู้เชี่ยวชาญด้าน mental model)
    2. User prompt: คำถามที่จะส่งให้ LLM (เช่น บอกให้อธิบาย mental model ที่ต้องการ)

    ตัวอย่าง system และ user prompts:

    Python
    # Define system prompt
    system_prompt = """
    You are an expert curator of mental models across science, philosophy, and applied reasoning.
    Your task is to explain mental models clearly and accurately using a fixed schema.
    If the origin of a model is unclear or debated, state that explicitly.
    Do not invent historical sources. Be concise and concrete.
    """
    # Define user prompt
    user_prompt = "Explain the following mental model: {model_query}"

    จากนั้น ประกอบ prompts เข้าด้วยกัน:

    Python
    # Create prompt template
    prompts = ChatPromptTemplate.from_messages(
    [
    # System prompt
    ("system", system_prompt.strip()),
    # User prompt
    ("human", user_prompt)
    ]
    )

    เราสามารถดูตัวอย่าง prompt ได้ด้วย .format_messages():

    Python
    # Inspect prompt template
    prompts.format_messages(model_query="Pareto Principle")

    ผลลัพธ์:

    [SystemMessage(content='You are an expert curator of mental models across science, philosophy, and applied reasoning.\\n\\nYour task is to explain mental models clearly and accurately using a fixed schema.\\n\\nIf the origin of a model is unclear or debated, state that explicitly.\\n\\nDo not invent historical sources. Be concise and concrete.', additional_kwargs={}, response_metadata={}),
    HumanMessage(content='Explain the following mental model: Pareto Princinple', additional_kwargs={}, response_metadata={})]

    📦 Step 3. Set Output Structure

    ในขั้นที่ 3 เราจะกำหนดหน้าตา output ที่เราต้องการ

    เช่น ถ้าเราต้องการให้คืนค่า JSON แบบนี้:

    {
    "model_name": "",
    "origin": "",
    "description": "",
    "example": "",
    "tags": []
    }

    เรากำหนดได้โดยใช้ pydantic และ typing packages แบบนี้:

    Python
    # Import packages
    from pydantic import BaseModel, Field
    from typing import List, Literal
    # Define output structure
    class MentalModel(BaseModel):
    # Mental model name
    model_name: str = Field(description="The commonly accepted name of the mental model")
    # Source/origin
    origin: str = Field(
    description="Where the model comes from (person, book, field, or cultural origin)"
    )
    # Brief description
    description: str = Field(
    description="A brief explanation of what the mental model is and why it matters"
    )
    # Example
    example: str = Field(
    description="A concrete real-world example illustrating the mental model"
    )
    # Tags
    tags: List[str] = Field(
    description="Short tags such as decision-making, systems thinking, learning, philosophy"
    )

    Note: ดูวิธีใช้ Pydantic

    หลังกำหนดหน้าตา output แล้ว ให้ใส่เข้าไปใน LLM instance แบบนี้:

    Python
    # Add output structure to LLM
    llm_with_structured_output = llm.with_structured_output(MentalModel)

    ⛓️‍💥 Step 4. Chain

    ในขั้นที่ 4 ให้เราสร้าง chain โดยเชื่อม LLM instance เข้ากับ prompts ด้วย pipe operator (|):

    Python
    # Build chain
    chain = prompts | llm_with_structured_output

    Note: ให้มองว่า | เป็นลูกศรชี้ทางขวา (prompt → llm)


    🏃 Step 5. Run

    ในขั้นสุดท้าย เราจะเรียกใช้งาน chain ซึ่งทำได้ 2 แบบ:

    1. Single run: เรียกใช้ครั้งเดียว
    2. Batch run: เรียกใช้หลายครั้งพร้อมกัน

    .

    ☝️ Single Run

    เราเรียกใช้งานครั้งเดียวด้วย .invoke()

    ในตัวอย่าง เราจะถามเกี่ยวกับ “compound interest” กัน:

    Python
    # Run query
    result = chain.invoke({"model_query": "Compound Interest"})

    แสดงผลลัพธ์ใน console:

    Python
    # Import package
    import json
    # Load result
    result_dict = result.model_dump()
    # Print
    print(json.dumps(result_dict, indent=4))

    ผลลัพธ์:

    {
    "model_name": "Compound Interest",
    "origin": "Finance, Mathematics; concept dates back to ancient times, formalized in the Renaissance.",
    "description": "Compound interest is the interest on a loan or deposit calculated based on both the initial principal and the accumulated interest from previous periods. It is often called 'interest on interest' and leads to exponential growth over time, making it a powerful force in finance for both wealth creation and debt accumulation.",
    "example": "If you invest $1,000 at an annual interest rate of 5% compounded annually, after the first year you'll have $1,050. In the second year, the 5% interest is calculated on $1,050, not just the original $1,000, leading to a balance of $1,102.50. This snowball effect accelerates over decades, significantly increasing the total return compared to simple interest.",
    "tags": [
    "Finance",
    "Economics",
    "Wealth Building",
    "Decision-making",
    "Long-term thinking"
    ]
    }

    .

    🎳 Batch Run

    สำหรับการรันหลายครั้งพร้อมกัน เราจะใช้ .batch() แบบนี้:

    Python
    # Create list of mental models
    mental_model_queries = [
    "First Principles Thinking",
    "Occam's Razor",
    "Confirmation Bias"
    ]
    # Create batch inputs
    batch_inputs = [{"model_query": query} for query in mental_model_queries]
    # Run queries
    results = chain.batch(batch_inputs)
    # Instantiate collector
    query_collector = [result.model_dump() for result in results]

    แสดงผลลัพธ์ใน console:

    Python
    # Instantiate counter
    i = 1
    # Loop through elements in collector
    for result in query_collector:
    # Print result
    print(f"👉 Query {i}:")
    print(json.dumps(result, indent=4))
    print("\\n")
    # Add 1 to counter
    i += 1

    ผลลัพธ์:

    👉 Query 1:
    {
    "model_name": "First Principles Thinking",
    "origin": "Often attributed to Aristotle; popularized in modern business by Elon Musk.",
    "description": "First Principles Thinking involves breaking down complex problems into their most basic, fundamental truths or 'first principles,' rather than reasoning by analogy or conventional wisdom. It matters because it allows for innovative solutions by challenging assumptions and building new knowledge from the ground up.",
    "example": "Instead of accepting the high cost of batteries for electric cars, Elon Musk famously broke down a battery into its constituent raw materials (cobalt, nickel, lithium, etc.) to understand their actual cost, then sought ways to procure and assemble them more efficiently, leading to significant cost reductions and innovation.",
    "tags": [
    "Problem-solving",
    "Innovation",
    "Critical Thinking",
    "Decision-making"
    ]
    }
    👉 Query 2:
    {
    "model_name": "Occam's Razor",
    "origin": "William of Ockham (14th-century philosopher and theologian)",
    "description": "Occam's Razor is a problem-solving principle stating that among competing hypotheses that explain an event or phenomenon equally well, the simplest solution is most likely the correct one. It advocates for parsimony, suggesting that one should not multiply entities beyond necessity, thereby favoring theories with fewer assumptions.",
    "example": "If you hear hoofbeats outside, it is more likely to be horses than zebras, assuming you are in a location where horses are common and zebras are not. The 'horse' explanation is simpler and requires fewer extraordinary assumptions.",
    "tags": [
    "Philosophy",
    "Decision-making",
    "Problem-solving",
    "Critical thinking",
    "Science"
    ]
    }
    👉 Query 3:
    {
    "model_name": "Confirmation Bias",
    "origin": "Psychology; early concepts traced to Francis Bacon's Novum Organum (1620)",
    "description": "Confirmation bias is the tendency to search for, interpret, favor, and recall information in a way that confirms one's pre-existing beliefs or hypotheses. It matters because it can lead to flawed reasoning, poor decision-making, and resistance to new or contradictory evidence, hindering objective analysis.",
    "example": "A person who believes a certain stock will perform well might selectively read news articles and analyst reports that support this positive outlook, while ignoring or downplaying any negative news or warnings about the company.",
    "tags": [
    "cognitive bias",
    "decision-making",
    "psychology",
    "critical thinking"
    ]
    }

    💪 Summary

    เราจะได้เห็นได้ว่า langchain เป็น package ที่ใช้ทำงานกับ LLM ได้อย่างง่าย ๆ ใน 5 ขั้นตอน:

    Set LLM: เลือก model
    ↓
    Set prompt: กำหนด system และ user prompt
    ↓
    Set output: กำหนด output structure
    ↓
    Chain: สร้าง pipeline
    ↓
    Run: เรียกใช้งาน (single & batch)

    🫵 Your Turn

    อ่านบทความจบแล้ว ลองมาใช้ langchain กันนะครับ:


    📄 References

  • สรุป 5 keywords สำหรับ handle exceptions ใน Python: try, except, else, finally, raise — ตัวอย่างโค้ดการจ่ายเงินออนไลน์

    สรุป 5 keywords สำหรับ handle exceptions ใน Python: try, except, else, finally, raise — ตัวอย่างโค้ดการจ่ายเงินออนไลน์

    Exception หมายถึง error ที่เกิดขึ้นกับ code ที่มี syntax ถูกต้อง

    ยกตัวอย่างเช่น การหารเลขด้วย 0:

    print(5 / 0)

    ผลลัพธ์:

    ZeroDivisionError

    Exception สามารถทำให้ code หยุดทำงานหรือทำงานผิดพลาดได้

    ดังนั้น ในการเขียน code เราควรกำหนดวิธีในการจัดการกับ exception เพื่อป้องกันไม่ให้ code ทำงานผิดพลาด

    ใน Python เรามี 5 keywords สำหรับจัดการ exception ได้:

    1. try
    2. except
    3. else
    4. finally
    5. raise

    เราไปดูตัวอย่างการใช้งานทั้ง 5 keywords ผ่านตัวอย่าง code การจ่ายเงินออนไลน์กัน


    1. 🔨 try, except
    2. 🤔 else
    3. ☝️ finally
    4. 👋 raise
    5. 💪 สรุป 5 Keywords
    6. 📚 Further Reading: Python Exceptions
    7. 😺 GitHub
    8. 📃 References

    🔨 try, except

    try และ except เป็น keywords ที่ใช้ร่วมกัน โดยใน try เราจะใส่ code ที่เราคิดว่าอาจจะเกิด exception ขึ้นได้

    ส่วนใน except เราจะใส่สิ่งที่เราต้องการให้เกิดขึ้นเมื่อเกิด exception ขึ้น

    ยกตัวอย่างเช่น เราเขียน code เพื่อเช็กว่า payment มีค่ามากกว่า 0 หรือไม่ แต่ payment ที่ใส่เข้ามาอาจไม่ใช่ตัวเลข ซึ่งจะทำให้ code ของเราหยุดทำงาน:

    # Without try, except
    
    # Set payment
    payment = "one thousand"
    
    # Validate payment
    if float(payment) < 0:
        print("Payment cannot be negative.")

    ผลลัพธ์:

    ValueError

    เราสามารถใช้ try และ except ช่วยให้ code ทำงานต่อได้ พร้อมทำให้บอกเราให้รู้ว่า เกิดข้อผิดพลาดอะไรขึ้น:

    # Set payment
    payment = "one thousand"
    
    # Code that may raise exception
    try:
        if float(payment) < 0:
            print("Payment cannot be negative.")
    
    # Print when exception occurs
    except ValueError:
        print("Payment must be a number.")
    

    ผลลัพธ์:

    Payment must be a number.

    🤔 else

    else ทำงานคล้าย except แต่แทนที่จะส่งค่าบางอย่างกลับมาเมื่อเกิด exception, else จะทำงานเมื่อไม่มี exception เกิดขึ้นใน try

    ยกตัวอย่างเช่น ใช้ else เพื่อแสดงข้อความว่ากำลังประมวลผล เมื่อ payment เป็นตัวเลข:

    # Set payment
    payment = 500
    
    # Code that may raise exception
    try:
        if float(payment) < 0:
            print("Payment cannot be negative.")
    
    # Print when exception occurs
    except ValueError as e:
        print(f"Error: {e}")
    
    # Print when exception does not occur
    else:
        print("Processing payment ...")

    ผลลัพธ์:

    Processing payment ...

    ☝️ finally

    finally จะส่งค่ากลับมาไม่ว่าจะเกิด exception ขึ้นหรือไม่ก็ตาม

    ยกตัวอย่างเช่น ใช้ finally แสดงข้อความขอบคุณลูกค้า ไม่ว่า payment จะผ่านหรือไม่ก็ตาม:

    # Set payment
    payment = 500
    
    # Code that may raise exception
    try:
        if float(payment) < 0:
            print("Payment cannot be negative.")
    
    # Print when exception occurs
    except ValueError as e:
        print(f"Error: {e}")
    
    # Print when exception does not occur
    else:
        print("Processing payment ...")
    
    # Print no matter what
    finally:
        print("Thank you for your payment.")

    ผลลัพธ์:

    Processing payment ...
    Thank you for your payment.

    👋 raise

    สุดท้าย เราจะใช้ raise กำหนด exception ได้เอง

    ยกตัวอย่างเช่น ใช้ raise เพื่อแจ้งเตือนเมื่อ payment ติดลบ:

    # Set payment
    payment = -50
    
    # Code that may raise exception
    try:
        if not isinstance(payment, (int, float)):
            raise TypeError("Payment must be a number.")
        if payment < 0:
            raise ValueError("Payment cannot be negative.")
    
    # Print when exception occurs
    except (TypeError, ValueError) as e:
        print(f"Error: {e}")
    
    # Print when exception does not occur
    else:
        print("Processing payment ...")
    
    # Print no matter what
    finally:
        print("Thank you for your payment.")

    ผลลัพธ์:

    Error: Payment cannot be negative.
    Thank you for your payment.

    💪 สรุป 5 Keywords

    ในบทความนี้ เราได้เรียนรู้วิธีใช้ 5 keywords เพื่อจัดการ exception ใน Python ได้แก่:

    1. try: รัน code ที่เราคิดว่าอาจเกิด exception
    2. except: code ที่จะรันเมื่อเกิด exception จาก try
    3. else: code ที่รันเมื่อไม่เกิด exception จาก try
    4. finally: code ที่จะรันไม่ว่า try จะเกิด exception หรือไม่
    5. raise: code สำหรับแสดง exception ที่กำหนดเอง

    ตัวอย่าง code:

    # Set payments
    payments = {
        "Alex": "one thousand",
        "Barbara": -50,
        "Carter": 500
    }
    
    # Loop through payments
    for name, payment in payments.items():
        
        # Print name and payment
        print(f"{name} paying {payment}.")
        
        # Code that may raise exception
        try:
            if not isinstance(payment, (int, float)):
                raise TypeError("Payment must be a number.")
            if payment < 0:
                raise ValueError("Payment cannot be negative.")
    
        # Print when exception occurs
        except (TypeError, ValueError) as e:
            print(f"Error: {e}")
    
        # Print when exception does not occur
        else:
            print("Processing payment ...")
    
        # Print no matter what
        finally:
            print("Thank you for your payment.")
            
        # Print divider
        print("\\n -------------------------------------------------- \\n")

    ผลลัพธ์:

    Alex paying one thousand.
    Error: Payment must be a number.
    Thank you for your payment.
    
     -------------------------------------------------- 
    
    Barbara paying -50.
    Error: Payment cannot be negative.
    Thank you for your payment.
    
     -------------------------------------------------- 
    
    Carter paying 500.
    Processing payment ...
    Thank you for your payment.
    
     -------------------------------------------------- 
    
    

    📚 Further Reading: Python Exceptions

    ศึกษาประเภทของ exception ใน Python ได้ที่: Python Built-in Exceptions


    😺 GitHub

    ดู code ทั้งหมดในบทความนี้ได้ที่ GitHub


    📃 References

  • วิธีใช้ polars: package ทรงพลังสำหรับทำงานกับ tabular data ใน Python — ตัวอย่างการทำงานกับ IKEA Products dataset

    วิธีใช้ polars: package ทรงพลังสำหรับทำงานกับ tabular data ใน Python — ตัวอย่างการทำงานกับ IKEA Products dataset

    polars เป็น package สำหรับทำงานกับข้อมูลในรูปแบบตาราง (tabular data) ใน Python และถูกพัฒนาด้วย Rust และ Apache Arrow ซึ่งทำให้ polars ประมวลผลได้เร็วและมีประสิทธิภาพสูง

    polars เป็นทางเลือกสำหรับคนที่เบื่อกับข้อจำกัดของ pandas ซึ่งเป็น package ยอดนิยมสำหรับทำงานกับข้อมูลในรูปแบบตาราง โดย polars ได้เปรียบ pandas อยู่ 3 อย่าง:

    1. Fast: ประมวลผลเร็วกว่า
    2. Intuitive: มี syntax ที่ใช้ง่ายกว่า
    3. Lazy: รองรับการเขียนแบบ lazy evaluation (ดูรายละเอียดเพิ่มเติมด้านล่าง) ทำให้ประมวลผลได้มีประสิทธิภาพมากกว่า

    Note: ดูวิธีการใช้ pandas ได้ที่บทความนี้

    Source: https://pola.rs/

    ในบทความนี้ เราจะมาดูวิธีใช้ polars ผ่านตัวอย่างการทำงานกับ IKEA Products dataset ที่มีข้อมูลเฟอร์นิเจอร์จาก IKEA กัน

    โดยบทความแบ่งเป็น 9 ส่วนดังนี้:

    1. Import package and dataset: โหลด package และ dataset
    2. Explore: สำรวจ dataset ก่อนทำงานกับข้อมูล
    3. Select: เลือกข้อมูล
    4. Filter: กรองข้อมูล
    5. Sort: จัดเรียงข้อมูล
    6. Aggregate: หาค่าทางสถิติ
    7. Mutate: เพิ่ม ลบ แก้ไข column
    8. Lazy: การทำงานแบบ lazy
    9. Chaining: การเชื่อมต่อ function

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 📦 Section 1. Import Package & Dataset
    2. 🧭 Section 2. Explore
      1. 🔷 2.1 shape
      2. 🗺️ 2.2 schema
      3. 🐵 2.3 head()
      4. 🔎 2.4 glimpse()
      5. 📝 2.5 describe()
    3. 🫳 Section 3. Select
      1. 🔲 3.1 Using []
      2. 🔪 3.2 Using slice() & select()
    4. 👀 Section 4. Filter
      1. ☝️ 4.1 One Condition
      2. 🖐️ 4.2 Multiple Conditions
    5. ↕️ Section 5. Sort
      1. ⬆️ 5.1 Ascending
      2. ⬇️ 5.2 Descending
      3. 🖐️ 5.3 Multiple Columns
    6. 🧮 Section 6. Aggregate
      1. 🏠 6.1 Basic
      2. 🏘️ 6.2 Group By
    7. 💪 Section 7. Mutate
      1. ➕ 7.1 Add Columns
      2. 🗑️ 7.2 Remove Columns
    8. 🥱 Section 8. Lazy
    9. 🔗 Section 9. Chaining
    10. ⭐️ Summary
    11. ⏭️ Next Step: DIY
    12. 📃 References

    📦 Section 1. Import Package & Dataset

    ในขั้นแรก เราจะโหลด package และ dataset ที่จะใช้งานกันก่อน

    เราจะโหลด package ด้วย import แบบนี้:

    import polars as pl

    Note: ก่อนโหลด เราจะต้องติดตั้ง package ซึ่งเราสามารถทำได้ด้วย pip install

    และโหลด dataset ด้วย read_csv() เพราะข้อมูลเป็นไฟล์ CSV:

    df = pl.read_csv("ikea_products.csv")

    ตอนนี้ เรามีข้อมูลพร้อมจะทำงานต่อแล้ว


    🧭 Section 2. Explore

    ในขั้นที่ 2 เราจะสำรวจข้อมูลที่เพิ่งโหลดเสร็จ ซึ่งเราทำได้ 5 วิธี:

    1. shape
    2. schema
    3. head()
    4. glimpse()
    5. describe()

    .

    🔷 2.1 shape

    shape เป็น attribute สำหรับเช็กจำนวน rows และ columns ใน dataset:

    df.shape

    ผลลัพธ์:

    จากผลลัพธ์ จะเห็นว่า dataset มีข้อมูล 3,694 rows และมี 14 columns

    .

    🗺️ 2.2 schema

    schema เป็น attribute สำหรับแสดงชื่อและประเภทข้อมูลของ columns:

    df.schema

    ผลลัพธ์:

    .

    🐵 2.3 head()

    head() เป็น method สำหรับดู n rows แรกของข้อมูล เช่น ดู 10 แรกของข้อมูล:

    df.head(10)

    ตัวอย่างผลลัพธ์:

    .

    🔎 2.4 glimpse()

    glimpse() เป็น method สำหรับดูโครงสร้างข้อมูล ซึ่งประกอบด้วย:

    1. จำนวน rows และ columns
    2. ชื่อ column
    3. ประเภทข้อมูล
    4. ตัวอย่างข้อมูล
    df.glimpse()

    ตัวอย่างผลลัพธ์:

    .

    .

    📝 2.5 describe()

    describe() เป็น method สำหรับแสดง summary statistics ของ columns:

    1. count: จำนวนข้อมูล
    2. null_count: จำนวนข้อมูลที่เป็นค่าว่าง
    3. mean: ค่าเฉลี่ย
    4. std: ค่าเบี่ยงเบนมาตรฐาน (standard deviation)
    5. min: ค่าต่ำสุด
    6. 25%, 50%, 75%: ข้อมูลที่ quartile ที่ 1, 2, และ 3
    7. max: ค่าสูงสุด
    df.describe()

    ตัวอย่างผลลัพธ์:


    🫳 Section 3. Select

    เรามี 2 วิธีในการเลือก rows และ columns จากข้อมูล:

    1. ใช้ []
    2. ใช้ slice() และ select()

    .

    🔲 3.1 Using []

    เราจะใช้ [] โดยกำหนด rows และ columns ที่ต้องการแบบนี้:

    df[rows, cols]

    ถ้าเราต้องการ rows หรือ columns ทั้งหมด ให้เราเว้นข้อมูลส่วนนั้นไว้ เช่น เลือกข้อมูล 10 rows แรก และ columns ทั้งหมด:

    df[:10]

    ตัวอย่างผลลัพธ์:

    หรือเลือกเฉพาะ columns ชื่อ ประเภท และราคา และ rows ทั้งหมด:

    df[["name", "category", "price"]]

    ผลลัพธ์:

    ถ้าต้องการทั้ง rows และ columns ให้เรากำหนดทั้งสองอย่าง เช่น ข้อมูล 10 rows แรก โดยเลือกเฉพาะ columns ชื่อ ประเภท และราคา:

    df[0:10, ["name", "category", "price"]]

    ผลลัพธ์:

    .

    🔪 3.2 Using slice() & select()

    เราสามารถใช้ slice() และ select() เพื่อเลือกข้อมูลแทนการใช้ [] ได้ โดย:

    1. ใช้ slice() เลือก rows
    2. ใช้ select() เลือก columns

    เช่น เลือกข้อมูล 10 rows แรก:

    df.slice(0, 10)

    ตัวอย่างผลลัพธ์:

    เลือก columns ชื่อ ประเภท และราคา:

    df.select(["name", "category", "price"])

    ผลลัพธ์:

    สุดท้าย เราสามารถใช้ทั้ง slice() และ select() ร่วมกันเพื่อเลือกทั้ง rows และ columns ได้แบบนี้:

    df.slice(0, 10).select(["name", "category", "price"])

    ผลลัพธ์:


    👀 Section 4. Filter

    เรากรองข้อมูลได้ด้วย filter() ซึ่งรับรองการกรองแบบ 1 เงื่อนไข และมากกว่า 1 เงื่อนไข

    .

    ☝️ 4.1 One Condition

    ตัวอย่างการกรองแบบ 1 เงื่อนไข เช่น เลือกเฉพาะข้อมูลของ outdoor furniture:

    df.filter(pl.col("category") == "Outdoor furniture")

    Note: สังเกตว่า เราใช้ col() เพื่อระบุ column ที่ต้องการ

    ตัวอย่างผลลัพธ์:

    .

    🖐️ 4.2 Multiple Conditions

    สำหรับการกรองหลายเงื่อนไข เราจะใช้ logical operator ช่วย:

    OperatorMeaning
    &And
    |Or
    ~Not

    เช่น เลือกข้อมูล outdoor furniture ที่ราคาสูงกว่า 1,000:

    df.filter(
        (pl.col("category") == "Outdoor furniture") &
        (pl.col("price") > 1000)
    )

    ตัวอย่างผลลัพธ์:


    ↕️ Section 5. Sort

    สำหรับจัดลำดับข้อมูล เราจะใช้ sort() ซึ่งรองรับการใช้งาน 3 กรณี:

    1. Ascending: เรียงจากน้อยไปมาก (A–Z)
    2. Descending: เรียงจากมากไปน้อย (Z–A)
    3. Multiple columns: เรียงลำดับหลาย columns พร้อมกัน

    .

    ⬆️ 5.1 Ascending

    Default ในการจัดลำดับของ sort() คือ เรียงจากน้อยไปมาก เช่น จัดเรียงข้อมูลตามราคา:

    df.sort("price")

    ตัวอย่างผลลัพธ์:

    .

    ⬇️ 5.2 Descending

    ถ้าต้องการจัดเรียงแบบมากไปน้อย เราจะต้องกำหนด argument descending=True:

    df.sort("price", descending=True)

    ตัวอย่างผลลัพธ์:

    .

    🖐️ 5.3 Multiple Columns

    ถ้าต้องการจัดลำดับหลาย columns พร้อมกัน เราจะกำหนด columns และวิธีจัดเรียง (ascending vs descending) เช่น จัดเรียงตามประเภทเฟอร์นิเจอร์ (A–Z) และราคา (Z–A):

    df.sort(
        ["category", "price"],
        descending=[False, True]
    )

    ตัวอย่างผลลัพธ์:


    🧮 Section 6. Aggregate

    Aggregate คือ การสรุปข้อมูล เช่น หาค่าเฉลี่ย และทำได้ 2 วิธี:

    1. แบบไม่จัดกลุ่ม ด้วยคำสั่ง select()
    2. แบบจัดกลุ่ม ด้วยคำสั่ง group_by() และ agg()

    .

    🏠 6.1 Basic

    ตัวอย่างสรุปข้อมูลโดยไม่จัดกลุ่ม เช่น หาค่าเฉลี่ย ค่าต่ำสุด และค่าสูงสุดของราคาเฟอร์นิเจอร์:

    df.select(
        pl.col("price").mean().alias("Mean"),
        pl.col("price").min().alias("Min"),
        pl.col("price").max().alias("Max")
    )

    Note: alias() ใช้ตั้งชื่อ column

    ผลลัพธ์:

    .

    🏘️ 6.2 Group By

    ตัวอย่างสรุปข้อมูลแบบจัดกลุ่ม เช่น หาค่าเฉลี่ย ค่าต่ำสุด และค่าสูงสุดของราคาเฟอร์นิเจอร์ ตามประเภทเฟอร์นิเจอร์:

    df.group_by("category").agg(
        pl.col("price").mean().alias("Mean"),
        pl.col("price").min().alias("Min"),
        pl.col("price").max().alias("Max")
    )

    ตัวอย่างผลลัพธ์:


    💪 Section 7. Mutate

    Mutate หมายถึง การปรับเปลี่ยน columns ที่มีอยู่ เช่น เพิ่มหรือลบ columns

    .

    ➕ 7.1 Add Columns

    ตัวอย่างการเพิ่ม columns เช่น:

    1. เพิ่ม column ส่วนลด (discount) โดยราคามากกว่า 1,000 จะลด 15% และราคาน้อยกว่านั้นจะลด 10% และ
    2. เพิ่ม column แสดงราคาหลังใช้ส่วนลดแล้ว (price_discounted)

    เราสามารถเขียน code ได้ดังนี้:

    df.with_columns(
        discount = pl.when(pl.col("price") > 1000)
        .then(0.15)
        .otherwise(0.10),
    ).with_columns(
        price_discounted = pl.col("price") * (1 - pl.col("discount"))
    )

    Note: เราใช้ when(), then(), otherwise() ช่วยกำหนดเงื่อนไขที่ต้องการ

    ตัวอย่างผลลัพธ์:

    สังเกตว่า columns ใหม่จะอยู่ต่อท้ายสุด

    .

    🗑️ 7.2 Remove Columns

    เราลบ column ได้ด้วย drop() เช่น ลบ columns ราคาเก่า (old_price) และการขายออนไลน์ (sellable_online):

    df.drop(["old_price", "sellable_online"])

    ตัวอย่างผลลัพธ์:


    🥱 Section 8. Lazy

    Lazy evaluation เป็นการประมวลผลที่จะรันก็ต่อเมื่อได้รับคำสั่ง ซึ่งช่วยให้การทำงานมีประสิทธิภาพมากขึ้น เพราะการประมวลผลจะไม่เกิดขึ้นจนกว่าจะจำเป็น

    Note: การประมวลผลในทันทีโดยไม่รอคำสั่ง เรียกว่า eager evaluation

    การทำงานแบบ lazy evaluation มีอยู่ 3 ขั้นตอน:

    ขั้นที่ 1. สร้าง LazyFrame ซึ่งเป็นข้อมูลสำหรับ lazy evaluation ด้วย lazy():

    df_lz = df.lazy()

    ขั้นที่ 2. เขียนคำสั่งที่ต้องการ เช่น เลือก columns:

    execution = df_lz.select(["name", "category", "price"])

    ขั้นที่ 3. สั่งให้ประมวลผลด้วยคำสั่ง collect():

    execution.collect()

    ผลลัพธ์:


    🔗 Section 9. Chaining

    Chaining เป็นการเชื่อมต่อ function เพื่อส่งผลลัพธ์จาก function หนึ่งไปยังอีก function หนึ่ง:

    df.function1().function2().function3()...

    Chaining ช่วยให้เราตอบโจทย์ที่ซับซ้อนขึ้นได้ เช่น:

    สำหรับเฟอร์นิเจอร์ที่ Francis Cayouette ออกแบบ ประเภทไหนจัดว่าเป็น “Premium” (ราคาสูงกว่า 1,000) และ “Affordable” (ราคาน้อยกว่า 1,000)

    เราสามารถใช้ polars เพื่อตอบโจทย์ได้แบบนี้:

    df_lz.filter(
        pl.col("designer") == "Francis Cayouette"
    ).group_by(
        "category"
    ).agg(
        pl.col("price").mean().round().alias("avg_price")
    ).with_columns(
        pl.when(pl.col("avg_price") > 1000)
        .then(pl.lit("Premium"))
        .otherwise(pl.lit("Affordable"))
        .alias("price_label")
    ).sort(
        "avg_price",
        descending=True
    ).select(
        [
            "category",
            "price_label",
            "avg_price"
        ]
    ).collect()

    ผลลัพธ์:


    ⭐️ Summary

    ในบทความนี้ เราได้เห็นวิธีการใช้ polars เพื่อทำงานกับข้อมูลในรูปแบบตาราง ซึ่งสามารถสรุปเป็นการเขียน code 9 กลุ่มได้ดังนี้:

    Section 1. Import package & dataset:

    • import polars as pl
    • pl.read_csv()

    Section 2. Explore:

    • df.shape
    • df.schema
    • df.head()
    • df.glimpse()
    • df.describe()

    Section 3. Select:

    • df[rows, cols]
    • pl.slice()
    • pl.select()

    Section 4. Filter:

    • df.filter()
    • pl.col()
    • &, |, ~

    Section 5. Sort:

    • df.sort()

    Section 6. Aggregate:

    • df.select()
    • df.group_by().agg()
    • alias()

    Section 7. Mutate:

    • df.with_columns()
    • pl.when().then().otherwise()
    • df.drop()

    Section 8. Lazy:

    • df.lazy()
    • collect()

    Section 9. Chaining:

    • df.function1().function2().function()...

    ⏭️ Next Step: DIY

    ใครที่อยากฝึกใช้ polars สามารถดูตัวอย่าง code และ dataset ได้ที่ GitHub


    📃 References


    🔔 ใครที่ชอบบทความนี้ ฝากกด subscribe และติดตามกันได้ที่:

  • วิธีใช้ SQLAlchemy วิเคราะห์ข้อมูลจาก Database โดยไม่ต้องออกจาก Python

    วิธีใช้ SQLAlchemy วิเคราะห์ข้อมูลจาก Database โดยไม่ต้องออกจาก Python

    Updated: 31 Jul 2026

    .

    SQLAlchemy เป็น Python package ยอดนิยมสำหรับเชื่อมต่อกับ database ทั้งสำหรับพัฒนาเว็บแอปพลิเคชัน (web application) และการวิเคราะห์ข้อมูล (data analytics)

    นอกจาก SQLAlchemy จะช่วยให้เราเชื่อมต่อกับ database หลากหลายประเภท ไม่ว่าจะเป็น:

    • SQLite
    • PostgreSQL
    • MySQL
    • และอีกมากมาย

    SQLAlchemy ยังช่วยให้เราทำงานกับ database ได้โดยไม่ต้องรู้ SQL (Structured Query Language) ก็ได้ โดยทำหน้าที่เป็น Object-Relational Mapper (ORM) ที่แปลงข้อมูลใน database ให้เป็น Python object ที่เราใช้งานต่อได้

    ในบทความนี้ ผมจะพาทุกคนไปดูวิธีใช้ SQLAlchemy คู่กับ Pandas เพื่อวิเคราะห์ข้อมูลใน database โดยไม่ต้องออกจาก Python กัน

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🚀 Overview
    2. 1️⃣ Step 1. เชื่อมต่อกับ Database
    3. 2️⃣ Step 2. ดูโครงสร้าง Database
    4. 3️⃣ Step 3. เขียน SQL
    5. 4️⃣ Step 4. โหลดข้อมูล
    6. 5️⃣ Step 5. วิเคราะห์ข้อมูล
    7. 💪 Summary
    8. ⏭️ Next
    9. 📃 References

    🚀 Overview

    การทำงานกับ SQLAlchemy มีอยู่ 5 ขั้นตอน:

    1. เชื่อมต่อกับ database
    2. ดูโครงสร้าง database
    3. เขียน SQL
    4. โหลดข้อมูล
    5. วิเคราะห์ข้อมูล

    เราไปดูตัวอย่าง ผ่านการทำงานกับ Chinook SQLite ที่มีข้อมูลของร้านขาย digital media (เช่น ข้อมูลลูกค้า เพลง นักร้อง) กัน


    1️⃣ Step 1. เชื่อมต่อกับ Database

    ในขั้นแรก เราจะเชื่อมกับ database โดยสร้าง Engine object ที่เก็บข้อมูลการเชื่อมต่อ database ไว้ให้:

    Python
    # Import the package
    from sqlalchemy import create_engine
    # Connect to the database
    engine = create_engine("sqlite:///chinook.sqlite")

    2️⃣ Step 2. ดูโครงสร้าง Database

    ในขั้นที่ 2 เราจะสำรวจโครงสร้าง database ว่ามี table อะไรอยู่บ้าง:

    Python
    # Import the package
    from sqlalchemy import inspect
    # Get the inspector
    inspector = inspect(engine)
    # List the table names
    table_names = inspector.get_table_names()
    # Print the table names
    print(table_names)

    ผลลัพธ์:

    [
    "Album",
    "Artist",
    "Customer",
    "Employee",
    "Genre",
    "Invoice",
    "InvoiceLine",
    "MediaType",
    "Playlist",
    "PlaylistTrack",
    "Track",
    ]

    3️⃣ Step 3. เขียน SQL

    ในขั้นที่ 3 เราจะเขียน SQL สำหรับดึงข้อมูลจาก database:

    Python
    # Import the package
    from sqlalchemy import text
    # Set a query
    query = text(
    """
    SELECT
    InvoiceId,
    InvoiceDate,
    BillingCountry,
    Total
    FROM Invoice;
    """
    )

    Note:

    ถ้าใช้ SQL ไม่เป็น เราสามารถใช้ SQLAlchemy เพื่อสร้าง SQL ขึ้นมาให้เราได้ เช่น:

    Python
    # Import the package
    from sqlalchemy import select
    # Create a query
    query = (
    select(
    invoice.c.InvoiceId,
    invoice.c.InvoiceDate,
    invoice.c.BillingCountry,
    invoice.c.Total,
    )
    )

    4️⃣ Step 4. โหลดข้อมูล

    ในขั้นที่ 4 เราจะโหลดข้อมูลเข้ามาใน Python ด้วย Pandas:

    Python
    # Import the package
    import pandas as pd
    # Load the table
    df = pd.read_sql(
    query,
    engine
    )
    # Inspect the df
    df.head()

    ผลลัพธ์:


    5️⃣ Step 5. วิเคราะห์ข้อมูล

    ในขั้นสุดท้าย เราจะวิเคราะห์ข้อมูลด้วย Pandas เช่น หาค่าเฉลี่ยต่อประเทศ:

    # Find mean total by country
    (
    df
    .groupby("BillingCountry", as_index=False)
    .agg(MeanTotal=("Total", "mean"))
    .sort_values("MeanTotal", ascending=False)
    )

    ผลลัพธ์:


    💪 Summary

    SQLAlchemy เป็น package ที่ช่วยให้เราทำงานกับ database ได้โดยไม่ต้องออกจาก Python และใช้งานง่ายใน 5 ขั้นตอน:

    1. เชื่อมต่อกับ database
    2. ดูโครงสร้าง database
    3. เขียน SQL
    4. โหลดข้อมูล
    5. วิเคราะห์ข้อมูล

    ⏭️ Next

    หลังอ่านบทความจบแล้ว ลองใช้ SQLAlchemy เพื่อทำงานกับ database กันดูนะครับ:


    📃 References

  • สร้าง chatbot ส่วนตัว ใน 5 ขั้นตอน ด้วย OpenAI library ใน Python — ตัวอย่างการสร้าง Gemini chatbot

    สร้าง chatbot ส่วนตัว ใน 5 ขั้นตอน ด้วย OpenAI library ใน Python — ตัวอย่างการสร้าง Gemini chatbot

    ในบทความนี้ เราจะมาดูวิธีสร้าง chatbot ส่วนตัว ด้วย openai library ใน Python ใน 5 ขั้นตอนกัน:

    1. Import libraries
    2. Create a client
    3. Create a chat history
    4. Create a chat function
    5. Chat

    Note: เราจะรัน code ตัวอย่างบน Google Colab ซึ่งทุกคนสามารถดูได้ Gemini Chatbot in Google Colab

    ถ้าพร้อมแล้ว ไปเริ่มกันเลย


    1. 🏁 Step 1. Import Libraries
    2. 💁‍♂️ Step 2. Create a Client
    3. 🙊 Step 3. Create a Chat History
    4. 📨 Step 4. Create a Chat Function
    5. 💬 Step 5. Chat
    6. 👍 Google Colab
    7. 📃 References

    🏁 Step 1. Import Libraries

    ในขั้นแรก เราจะโหลด 2 libraries ที่เกี่ยวข้อง ซึ่งได้แก่:

    1. openai: สำหรับเรียกใช้ API ของ AI service *
    2. display และ Markdown: สำหรับแสดง markdown text (อย่างคำตอบที่ส่งมาจาก AI) ให้อ่านง่าย
    # Import libraries
    
    # For Gemini
    from openai import OpenAI
    
    # For text rendering
    from IPython.display import display, Markdown

    Note: * openai library ถูกออกแบบสำหรับ OpenAI API แต่สามารถใช้งานกับ AI อื่น ๆ ได้ เช่น:


    💁‍♂️ Step 2. Create a Client

    ในขั้นที่ 2 เราจะสร้าง client เพื่อเชื่อมต่อกับ AI ที่เป็น “สมอง” ของ chatbot ด้วย OpenAI() ซึ่งต้องการ 2 arguments ได้แก่:

    1. api_key: รหัส API ของเรา
    2. base_url: URL สำหรับเรียกใช้ API

    ในตัวอย่าง เราจะเรียกใช้ Gemini ซึ่งเราสามารถกำหนด arguments ได้ดังนี้:

    # Create client
    client = OpenAI(
        api_key="YOUR_API_KEY_HERE",
        base_url="<https://generativelanguage.googleapis.com/v1beta/openai/>"
    )

    Note:

    • ใส่ API key ใน "YOUR_API_KEY_HERE"
    • ดูวิธีสร้าง API key ฟรีได้ที่ Using Gemini API keys
    • สำหรับคนที่จะเรียกใช้ OpenAI API (ChatGPT) แทน Gemini เราสามารถข้ามการเขียน base_url ไปได้

    🙊 Step 3. Create a Chat History

    ในขั้นที่ 3 เราจะสร้าง chat history เพื่อเก็บ:

    1. System prompt ที่กำหนดพฤติกรรมของ chatbot (ในตัวอย่าง เราจะกำหนดให้เป็นผู้ช่วยที่กระตือรือร้น)
    2. ประวัติการพูดคุยระหว่างเรากับ chatbot ซึ่งจะทำให้ chatbot จำสิ่งที่คุยกันได้
    # Set system prompt
    system_prompt = """
    You are a helpful, cheerful, and optimistic assistant.
    
    Be concise, validate answers, and admit when you don’t know.
    
    Make responses clear, easy to read, and sprinkle in playful emoji.
    """
    
    # Instantiate chat history
    chat_history = [
        {
            "role": "system",
            "content": system_prompt
        }
    ]

    📨 Step 4. Create a Chat Function

    ในขั้นที่ 4 เราจะสร้าง function ที่จะทำให้เราถาม-ตอบกับ chatbot แบบ real-time ได้:

    # Create a function for chatbot
    def chatbot(model="gemini-2.5-flash"):
    
        # Set chat history as global variable
        global chat_history
    
        # Print chat header
        display(Markdown("# 🟢 --- Chat Begins ---"))
    
        # Print chat instruction
        print("ℹ️ Type \\"end chat\\" to exit.")
    
        # Loop through conversation
        while True:
    
            # Render user prompt display
            display(Markdown("## 🧑‍💻 You:"))
    
            # Get user input
            user_prompt = input("")
    
            # Check if user wants to exit chat
            if user_prompt.lower() == "end chat":
    
                # Print goodbye message
                display(Markdown("## ✨ Assistant:\\n" + "👋 See you later!"))
    
                # End chat
                break
    
            # Append user input to chat history
            chat_history.append(
                {
                    "role": "user",
                    "content": user_prompt
                }
            )
    
            # Get response
            response = client.chat.completions.create(
    
                # Set prompt
                messages=chat_history,
    
                # Set model
                model=model
            )
    
            # Append response to history
            chat_history.append(
                {
                    "role": "assistant",
                    "content": response.choices[0].message.content
                }
            )
    
            # Render response
            display(Markdown("## ✨ Assistant:\\n" + response.choices[0].message.content + "\\n"))

    💬 Step 5. Chat

    ในขั้นสุดท้าย เราจะเรียกใช้งาน chatbot() เพื่อเริ่มคุยกับ AI เลย:

    # Start chatting
    chatbot()

    ผลลัพธ์:


    👍 Google Colab

    ดูตัวอย่าง code ทั้งหมดได้ที่ Google Colab


    📃 References

  • Python for AI: รวบรวม 8 บทความการทำงานกับ AI ใน Python

    Python for AI: รวบรวม 8 บทความการทำงานกับ AI ใน Python

    ในช่วงที่ผ่านมา ผมมีโอกาสแชร์การใช้ Python เพื่อทำงานกับ AI จากการที่ผมได้ทำงานเกี่ยวกับ AI มากขึ้น

    เพื่อช่วยในการแชร์ ผมได้สรุปเนื้อหาไว้ใน 8 บทความ (5 กลุ่ม) ซึ่งทุกคนสามารถอ่านตามได้ดังนี้:

    🐍 Session #1. Intro to Python:

    • Intro to Python: แนะนำการใช้งานและประเภทข้อมูลใน Python

    🔁 Session #2. Control flow:

    • Control flow: สอนใช้ statement เช่น if, for, while เพื่อควบคุมการทำงานของ Python

    💻 Session #3. Functions:

    • Functions: สอนการสร้าง function ใน Python

    📦 Session #4. Packages and files:

    • open(): สอนการทำงานกับไฟล์ด้วย base Python
    • json package: สอนการทำงานกับ JSON ด้วย json package
    • pd.read_csv(): สอนการทำงานกับ CSV ด้วย pandas package

    🤖 Session #5. AI packages:

    • openai package: สอนการทำงานกับ AI API ผ่าน openai package
    • google-genai package: สอนการใช้ google-genai เพื่อทำงานกับ Gemini API