LangChain 101

/ 8 min read

Share on social media

langchain-101 สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video

Langchain คืออะไร ? ถูกสร้างขึ้นมาเพื่อตอบโจทย์อะไร ?

LangChain คือ Open Source Framework ที่มีสถาปัตยกรรม Agent แบบสำเร็จรูป (Prebuilt Agent Architecture) และรองรับการเชื่อมต่อกับโมเดลภาษาขนาดใหญ่ (LLMs) หรือเครื่องมือต่างๆ ได้อย่างหลากหลาย โดย Framework นี้เป็นเครื่องมือที่ช่วยให้เราสามารถเริ่มต้นสร้าง AI Agents แบบปรับแต่งเองได้ โดยชื่อของ LangChain นั้นมาจากการผสมกันของคำว่า “Language” (จาก Language Models) และ “Chains” (ขั้นตอนการคำนวณที่กำหนดไว้ล่วงหน้าเพื่อใช้งานทั่วไป)

LangChain ถูกสร้างขึ้นมาเพื่อตอบโจทย์เหล่านี้

  • เชื่อมต่อ LLMs เข้ากับข้อมูลภายนอก: LangChain ถูกสร้างขึ้นภายใต้ความเชื่อที่ว่า แม้ LLMs จะเป็นเทคโนโลยีใหม่ที่ทรงพลัง แต่โมเดลเหล่านี้จะยิ่งมีประสิทธิภาพมากขึ้นเมื่อนำไปประกอบเข้ากับแหล่งข้อมูลภายนอก (External sources of data)
  • รองรับ Agentic Applications: ผู้สร้างเชื่อว่า application ในอนาคตจะมีลักษณะเป็นแบบ Agentic มากขึ้น เป้าหมายหลักของ LangChain จึงเป็นการทำให้ Intelligent Agents กลายเป็นสิ่งที่สามารถใช้งานได้อย่างแพร่หลายในการใช้งานร่วมกับ application มากขึ้น
  • แก้ปัญหาความยากในการนำไปใช้งานจริง (Production-ready): ในปัจจุบันการสร้าง application AI Prototype นั้นทำได้ง่าย แต่ การสร้าง Agents ที่มีความน่าเชื่อถือ (Reliable) เพียงพอสำหรับการใช้งานจริง (Production) นั้นยังเป็นเรื่องที่ยากมาก LangChain จึงถูกออกแบบมาให้เป็นจุดเริ่มต้นที่ง่ายที่สุดในการพัฒนา application ด้วย LLMs ในขณะเดียวกันก็มีความยืดหยุ่นและพร้อมสำหรับการใช้งานจริง รวมถึงในปัจจุบันมี cloud หลายเจ้าที่ support การ deploy agent แล้วด้วยเช่นกัน (ซึ่งเดี๋ยวเราจะคุยกันในหัวข้อต่อๆไปอีกที)

นอกจากนี้ เมื่อระบบมีความซับซ้อนขึ้น LangChain ยังได้ถูกพัฒนาต่อยอด ecosystem ให้มีเครื่องมืออย่าง LangGraph ที่ช่วยให้ผู้พัฒนาสามารถควบคุม Flow การทำงานของ Agent ใน Low-level orchestration และ LangSmith ที่เข้ามาช่วยตรวจสอบและประเมินผลเพื่อให้ application ได้ (ซึ่งเราจะค่อยมาพูดถึงกันอีกทีนะครับ)

องค์ประกอบสำคัญที่ต้องรู้ก่อน

ขอย้ำหนึ่งอย่างก่อนสำหรับคนที่เคยศึกษา LangChain มาก่อนแล้ว

  • LangChain มี major change ช่วง version 1 ที่ผ่านมา ซึ่งส่งผลทำให้หลายๆคำสั่งถูกย้ายมาไว้ใน set คำสั่งของ module ใหม่ (ภายใต้ namespace langchain) และบางคำสั่งเดิมจะอยู่ภายใต้ langchain-classic แทน
  • ดังนั้น หากบางคนเคยศึกษาจากแหล่งอื่นมา และคำสั่งในหัวข้อนี้อาจจะแปลกตาไปบ้าง (รวมถึงหลายๆ concept ที่ไม่ได้เล่า) ขอให้เข้าใจว่า คำสั่งอาจจะเปลี่ยนได้ตาม version framework นะครับ
%%{
  init: {
    "fontFamily": "monospace",
    "flowchart": {
      "curve": "curve"
    }
  }
}%%
graph TD
  %% Outside the agent
  QUERY([input])
  LLM{model}
  TOOL(tools)
  ANSWER([output])

  %% Main flows (no inline labels)
  QUERY --> LLM
  LLM --"action"--> TOOL
  TOOL --"observation"--> LLM
  LLM --"finish"--> ANSWER

  classDef blueHighlight fill:#DBEAFE,stroke:#2563EB,color:#1E3A8A;
  classDef greenHighlight fill:#DCFCE7,stroke:#16A34A,color:#14532D;
  class QUERY blueHighlight;
  class ANSWER blueHighlight;
  class LLM greenHighlight;
  class TOOL greenHighlight;

องค์ประกอบสำคัญของ LangChain ที่เป็นรากฐานในการสร้าง application และ AI Agents มีดังนี้:

1. Model ทำหน้าที่เป็นเสมือน “ระบบคิดวิเคราะห์” (Reasoning engine) ของ Agent ซึ่งจะคอยทำหน้าที่ตัดสินใจว่าจะใช้เครื่องมือใด ตีความผลลัพธ์ และให้คำตอบสุดท้าย การระบุและใช้งานโมเดลสามารถทำได้ทั้งแบบตั้งค่าไว้ตายตัว (Static model) และแบบที่ปรับเปลี่ยนโมเดลระหว่างการทำงานตามบริบท (Dynamic model)

2. Tools เป็นสิ่งที่ช่วยให้ Agent สามารถ ลงมือทำสิ่งต่างๆ และโต้ตอบกับโลกภายนอกได้ (Take actions) เช่น การ query ฐานข้อมูล การค้นหาบนเว็บ หรือการรัน code โดยเครื่องมือแต่ละตัวจะประกอบด้วย Schema (ที่ระบุชื่อ คำอธิบายพารามิเตอร์ต่างๆ) และ function หรือ code คำสั่งสำหรับการทำงานนั้น

3. Agents เป็นตัวที่ นำ Language Models และ Tools มาทำงานร่วมกัน โดยปกติ Agent จะทำงานแบบวน loop ในรูปแบบที่เรียกว่า ReAct (“Reasoning + Acting”) ซึ่งก็คือการคิดวิเคราะห์ (Reasoning) สลับกับการลงมือทำผ่านการเรียกใช้เครื่องมือเป้าหมาย (Acting) ไปเรื่อยๆ จนกว่าจะได้ผลลัพธ์หรือคำตอบสุดท้ายเพื่อส่งให้ผู้ใช้

4. Messages เป็น หน่วยพื้นฐานที่สุดในการเก็บข้อมูลและบริบท (Context) สำหรับการสื่อสารกับโมเดล ซึ่งมีประเภทหลักๆ ได้แก่: - System message: ใช้สำหรับใส่คำสั่งตั้งต้น เพื่อกำหนดพฤติกรรมภาพรวมและบริบทให้กับโมเดล (System Prompt) - Human message: ข้อมูล หรือคำสั่งที่มาจากผู้ใช้งาน - AI message: คำตอบหรือการตอบสนองที่สร้างจากโมเดล ซึ่งบางครั้งอาจรวมถึงคำขอเรียกใช้เครื่องมือ (Tool calls) ด้วย - Tool message: ผลลัพธ์ที่ได้จากการทำงานของเครื่องมือที่ส่งกลับไปให้โมเดล

5. Memory & State เป็นระบบที่ ช่วยให้ Agent สามารถจดจำข้อมูลหรือประวัติการโต้ตอบได้ แบ่งเป็น: - Short-term memory (State): ความจำระยะสั้นที่คอยจดจำประวัติการสนทนาหรือบริบทที่เกิดขึ้นภายใน Thread หรือ Session เดียว - Long-term memory (Store): ความจำระยะยาว (เก็บเป็น Document-based แบบ JSON) ที่จดจำข้อมูลข้ามการสนทนาหรือข้าม Session ได้

6. Middleware: เป็นกลไกที่ช่วยให้เราสามารถ แทรกแซง ปรับแต่ง หรือควบคุมพฤติกรรมของ Agent ในแต่ละขั้นตอนการทำงานได้อย่างละเอียด Middleware จะเข้ามาช่วยทำงานเบื้องหลังต่างๆ เช่น การติดตามประเมินผล การทำหน้าต่างคัดกรองเนื้อหา/ข้อมูลส่วนบุคคล (PII) ตลอดจนการสรุปบทสนทนาแบบอัตโนมัติเมื่อจำนวน token ใกล้เต็มลิมิต

ok เพื่อความเข้าใจที่มากขึ้น step ต่อไปเราจะพาทุกคนมาลองเล่นแต่ละองค์ประกอบผ่าน code กัน

1 - Model

https://docs.langchain.com/oss/python/langchain/models#google-gemini

สิ่งแรกที่เราจะทำคือ ใช้ langchain ต่อเข้ากับโมเดล gemini (case คุยกับ LLM) โดยรับ input เป็นทั้ง text และ ภาพมา

เริ่มต้นทำการลง library ผ่าน install command

Terminal window
pip install -U "langchain[google-genai]"
  • ใน document ของ langchain ที่ผมแปะไว้ มีเขียนในกรณี setup ของโมเดลแต่ละเจ้าไว้แล้ว
  • หากใครใช้เจ้าอื่นสามารถเข้าไปดูที่ document ต้นทางได้เลย

ต่อมาเพิ่ม code สำหรับการคุยกับโมเดลเข้าไป โดย LangChain ได้นำเสนอเอาไว้ทั้งหมด 2 ท่าคือ

  • ท่าแรก เป็นการ import ผ่าน model class ที่ langchain ได้ทำไว้ของแต่ละเจ้า
import os
from langchain_google_genai import ChatGoogleGenerativeAI
os.environ["GOOGLE_API_KEY"] = "..."
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
response = model.invoke("Mikelopster คือใคร ?")
print(response.content)
  • หรืออีกท่าคือ init_chat_model ที่จะเป็นท่ากลางที่สามารถใช้ได้กับทุก model โดยเป็นการระบุชื่อ Model เข้าไป
model = init_chat_model("google_genai:gemini-2.5-flash-lite")
response = model.invoke("Why do parrots talk?")
  • โดยหลังจากที่ init โมเดลกันแล้วเรียบร้อย เราสามารถนำตัวแปรนั้นเรียกคำสั่ง model.invoke() เพื่อเป็นการส่ง prompt ไปยังโมเดล LLM
  • และผลลัพธ์คำตอบของโมเดล ก็จะถูกส่งออกมาผ่านการ return ค่าของคำสั่งนั้น

แต่อย่างที่เราเห็น code example ของ LangChain document นั้นจะเป็นการใส่ key hardcode เข้าไปตรงๆ ซึ่งตามปกติเราควรจะทำเป็นการอ่าน config เข้าไป

สามารถสร้างเป็น .env ค่านี้

GOOGLE_API_KEY=ABC...

แล้วเรียกใช้ config ผ่าน load_dotenv() แบบนี้แทนได้`

import os
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
response = model.invoke("Mikelopster คือใคร ?")
print(response.content)

2 - Message

ref

Message ใน LangChain คือ หน่วยพื้นฐานที่สุดที่ใช้ในการส่งข้อมูลและบริบท (Context) ให้กับ LLM โดยทำหน้าที่เป็นตัวแทนของข้อมูลทั้งฝั่งขาเข้า (Input) และขาออก (Output) เมื่อเราโต้ตอบกับโมเดล

เพื่อให้สามารถใช้งานข้ามระหว่างผู้ให้บริการโมเดลต่างๆ (เช่น Google, OpenAI, Anthropic) ได้อย่างมีมาตรฐานเดียวกัน LangChain จึงได้ออกแบบ Message ให้มีองค์ประกอบหลัก 3 ส่วน ได้แก่:

  1. Role: ตัวระบุว่าใครเป็นคนส่งข้อความนี้ (เช่น ระบบ, ผู้ใช้, หรือ AI)
  2. Content: ข้อมูลที่ต้องการส่ง ซึ่งสามารถเป็นได้ทั้งข้อความธรรมดา (Text) หรือข้อมูลแบบหลายสื่อ (Multimodal) เช่น รูปภาพหรือไฟล์เสียง
  3. Metadata: ข้อมูลเพิ่มเติม เช่น จำนวนโทเคนที่ใช้ หรือ ID ของข้อความ

โดยประเภทของ Message นั้นเพื่อให้สามารถใช้งานร่วมกับ LLM ได้ถูก Context ยิ่งขึ้น LangChain ได้มีการแบ่งออกเป็น 4 ประเภทหลักๆ คือ:

  • System Message: คำสั่งเริ่มต้นเพื่อกำหนดพฤติกรรม บทบาท และบริบทการทำงานของโมเดล
  • Human Message: ข้อความ รูปภาพ หรือคำสั่งที่มาจากผู้ใช้งาน
  • AI Message: คำตอบหรือผลลัพธ์ที่โมเดลสร้างขึ้นมาส่งกลับมาให้เรา (รวมถึงคำขอเรียกใช้เครื่องมือต่างๆ ด้วย)
    • หากมีการ set ไว้ใน code ก่อน = มันคือการ set พฤติกรรมหรือทิศทางให้กับ AI เพื่อเป็นการช่วยวางโครงสร้างของคำตอบถัดไป
  • Tool Message: ข้อมูลผลลัพธ์ที่ได้จากการรันเครื่องมือ (Tools) แล้วส่งกลับไปให้โมเดลประมวลผลต่อ

นี่คือตัวอย่าง การส่ง Message SystemMessage ไปคู่กับ HumanMessage โดย

  • SystemMessage ระบุบทบาทเริ่มต้นให้กับ Agent ไว้ว่าเป็นผู้ช่วยอธิบายเรื่องยากๆให้เข้าใจง่าย
  • ส่วน HumanMessage ก็จะเป็นการส่ง Prompt คำสั่งเข้าไป
  • จากนั้นนำ Message ทั้งหมดทำเป็น array แล้วส่งเข้า model.invoke() ตามเดิม
import os
from dotenv import load_dotenv
from langchain.messages import HumanMessage, SystemMessage
from langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
# 1. เริ่มต้นใช้งานโมเดล
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# 2. สร้างรายการของ Messages (List of messages)
messages = [
# ใช้ SystemMessage เพื่อกำหนดบทบาทของ AI
SystemMessage(content="คุณคือผู้ช่วย AI ที่อธิบายเรื่องยากๆ ให้กลายเป็นเรื่องง่ายใน 2 บรรทัด"),
# ใช้ HumanMessage เพื่อเป็นคำถามจากผู้ใช้
HumanMessage(content="อธิบายหน่อยว่า Message ใน LangChain คืออะไร?")
]
# 3. ส่ง Messages เข้าไปให้โมเดลประมวลผลผ่าน .invoke()
response = model.invoke(messages)
# 4. ผลลัพธ์ที่ได้กลับมาจะเป็น AI Message
# เราสามารถเข้าถึงเนื้อหาคำตอบได้ผ่านแอตทริบิวต์ .content
print(response.content)

ซึ่งจริงๆนอกจากจะเขียนผ่าน class ของ langchain.messages แล้ว ยัสามารถเขียนในรูปแบบอื่นๆได้เช่นกัน เช่น

  • Dictionary format ซึ่งเป็นวิธีที่ตรงไปตรงมา โดยกำหนดผ่าน key role และ content
import os
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
# 1. เริ่มต้นใช้งานโมเดล
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# 2. สร้างรายการของ Messages (List of messages)
messages_dict = [
{"role": "system", "content": "คุณคือผู้ช่วย AI ที่อธิบายเรื่องยากๆ ให้กลายเป็นเรื่องง่ายใน 2 บรรทัด"},
{"role": "user", "content": "อธิบายหน่อยว่า Message ใน LangChain คืออะไร?"}
]
# 3. ส่ง Messages เข้าไปให้โมเดลประมวลผลผ่าน .invoke()
response = model.invoke(messages_dict)
# 4. ผลลัพธ์ที่ได้กลับมาจะเป็น AI Message
# เราสามารถเข้าถึงเนื้อหาคำตอบได้ผ่านแอตทริบิวต์ .content
print(response.content)
  • ใช้ผ่าน ChatPromptTemplate สำหรับการทำ Message prompts ที่มีความยืดหยุ่น โดย LangChain มี class ChatPromptTemplate ที่ออกแบบมาเพื่อสร้าง template ของบทสนทนา โดยเราสามารถใช้รูปแบบ Tuple (role, template) ในการกำหนดบทบาทและข้อความ ซึ่งรองรับการใส่ตัวแปร (เช่น {topic}) เพื่อแทนที่คำในภายหลังได้
import os
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate
load_dotenv()
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# การสร้าง Message prompts ด้วยการใช้ Tuple ควบคู่กับ ChatPromptTemplate
prompt_template = ChatPromptTemplate.from_messages([
("system", "คุณคือผู้ช่วย AI ที่อธิบายเรื่องยากๆ ให้กลายเป็นเรื่องง่ายใน 2 บรรทัด"),
("human", "อธิบายหน่อยว่า {topic} คืออะไร?")
])
# ใส่ค่าตัวแปรที่ต้องการลงใน Template (โมเดลจะแปลงข้อมูลชุดนี้ให้เป็น List ของ Message objects อัตโนมัติ)
formatted_messages = prompt_template.invoke({"topic": "Message ใน LangChain"})
# ส่งข้อมูลให้โมเดลประมวลผล
response = model.invoke(formatted_messages)
print(response.content)

ซึ่งจากประสบการณ์ส่วนตัวที่เคยเห็นมา ท่าที่มักจะเป็นที่นิยมคือท่า Dictionary format เพราะว่าอ่านง่ายและสามารถแยก file .json ออกไปเป็น template ต่างหากได้

รวมถึงตัว Message นี้เองสามารถใช้ส่ง Content ประเภทอื่นอกเหนือจาก text ด้วย โดยสามารถส่งผ่าน key content ไปได้เช่นกัน

ตัวอย่างรับภาพ

import os
import base64
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
# 1. เริ่มต้นใช้งานโมเดล
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# 2. function สำหรับอ่านไฟล์ภาพและแปลงเป็น Base64
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
image_path = "images/example.png"
base64_image = encode_image(image_path)
# 3. สร้างข้อความแบบ Multimodal ตามรูปแบบมาตรฐานของ LangChain
message = {
"role": "user",
"content": [
{"type": "text", "text": "ภาพนี้คืออะไร ?"},
{
"type": "image",
"base64": base64_image,
"mime_type": "image/png", # ระบุ mime_type ให้ตรงกับนามสกุลไฟล์
},
]
}
# 4. ส่ง List ของ Message เข้าไปประมวลผล
response = model.invoke([message])
# 5. แสดงผลลัพธ์
print(response.content)

จะสังเกตเห็นว่า

  • วิธีส่งเหมือนเดิม แค่เพิ่ม content type image เข้าไป พร้อมกับสามารถส่งภาพคู่กับข้อความไปได้ด้วยเช่นกัน
  • ซึ่งการส่งภาพนั้นนอกเหนือจากการส่งแบบ base64 แล้ว ยังสามารถส่งแบบ url หรือเป็น formData ได้เช่นกัน (สามารถดูใน document ของ LangChain เพิ่มเติมได้)

3 - Agent with tools

ref

Agent คือระบบที่นำโมเดล LLM มาผสานการทำงานเข้ากับเครื่องมือ (Tools) ต่างๆ เพื่อสร้างระบบที่สามารถคิดวิเคราะห์เกี่ยวกับงานที่ได้รับมอบหมาย ตัดสินใจเลือกใช้เครื่องมือ และทำงานซ้ำๆ อย่างเป็นขั้นตอนเพื่อนำไปสู่การแก้ปัญหาได้สำเร็จ

หลักการทำงานที่สำคัญของ Agent ประเภทนี้คือการทำงานแบบวน loop ตามรูปแบบที่เรียกว่า ReAct (“Reasoning + Acting”) re-act

  • Reasoning โมเดลภาษาจะทำหน้าที่เป็น “ระบบคิดวิเคราะห์” (Reasoning engine) ที่คอยประเมินบริบทของบทสนทนาและตัดสินใจว่าจะต้องเรียกใช้เครื่องมือใดบ้าง
  • Acting หลังจากตัดสินใจได้แล้ว Agent จะส่งคำสั่งไปเรียกใช้เครื่องมือเป้าหมาย และเมื่อเครื่องมือทำงานเสร็จสิ้น ผลลัพธ์หรือข้อมูลสังเกตการณ์ (Observations) จะถูกส่งกลับไปให้โมเดลประมวลผลต่อ
  • กระบวนการวิเคราะห์สลับกับการลงมือทำเช่นนี้จะวน loop ไปเรื่อยๆ จนกว่าจะบรรลุเงื่อนไขการหยุดทำงาน เช่น เมื่อโมเดลสามารถหาคำตอบสุดท้ายให้ผู้ใช้ได้แล้ว หรือเมื่อทำงานครบจำนวนรอบที่จำกัดไว้

บทบาทของ Tools: เครื่องมือเป็นส่วนที่ช่วยขยายขีดความสามารถของ Agent ให้สามารถโต้ตอบกับโลกภายนอกและลงมือทำสิ่งต่างๆ ได้จริง เช่น การค้นหาข้อมูลแบบ realtime, การรัน code, หรือการ query ฐานข้อมูล โดยเบื้องหลังแล้ว เครื่องมือก็คือ function การทำงานที่มีการกำหนดรูปแบบ Input และ Output เอาไว้อย่างชัดเจน เพื่อให้แชทโมเดลสามารถเข้าใจและตัดสินใจเรียกใช้ได้อย่างถูกต้องตามบริบท

รวมถึงยังช่วยทำให้ support เคสที่ทำให้ Agent เก่งขึ้นได้ตั้งแต่

  • การเรียกใช้เครื่องมือหลายตัวแบบต่อเนื่องกันจากคำสั่งเพียงคำสั่งเดียว
  • การเรียกใช้เครื่องมือแบบคู่ขนาน (Parallel tool calls)
  • การเลือกเครื่องมือแบบ dynamic ซึ่งปรับเปลี่ยนไปตามผลลัพธ์ที่ได้ก่อนหน้า
  • มีระบบรองรับการจัดการข้อผิดพลาดและการเรียกใช้เครื่องมือซ้ำ (Tool retry logic) หากการเรียกใช้ครั้งแรกไม่สำเร็จ

เราจะลองทำตัวอย่างกันโดยการสร้าง tools สำหรับ Search จาก Mock Database กัน

import os
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.agents import create_agent
from langchain.tools import tool
load_dotenv()
mock_database = {
"นายกรัฐมนตรี": "นายกรัฐมนตรีคนปัจจุบันของประเทศไทยคือ อนุทิน ชาญวีรกูล",
"mikelopster": "Mikelopster คือ Content Creator ที่ชอบแบ่งปันความรู้ด้านการเขียนโปรแกรมและ AI",
}
@tool
def search_database(query: str) -> str:
"""ใช้เครื่องมือนี้เพื่อค้นหาข้อมูลบุคคล เทคโนโลยี หรือความรู้ทั่วไปที่มีในฐานข้อมูลของระบบ"""
print(f"\n[ระบบกำลังค้นหาข้อมูลจาก Dictionary ด้วยคำค้น: {query}]")
for key, info in mock_database.items():
if key.lower() in query.lower():
return f"ข้อมูลที่พบ: {info}"
return "ขออภัย ไม่พบข้อมูลที่คุณค้นหาในฐานข้อมูล"
# แนะนำให้เพิ่ม temperature=0 เพื่อลดความผิดเพี้ยนของการตัดสินใจของ Agent
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite", temperature=0)
# ปรับ System Prompt ให้รัดกุมขึ้น บังคับให้สรุปคำตอบเสมอ
SYSTEM_PROMPT = """คุณคือผู้ช่วย AI ที่ทำหน้าที่ค้นหาข้อมูลจากฐานข้อมูลของระบบเพื่อตอบคำถามผู้ใช้
กฎสำคัญที่คุณต้องปฏิบัติตาม:
1. หากคำถามต้องการข้อมูลเฉพาะเจาะจง ให้คุณเรียกใช้เครื่องมือเพื่อค้นหาข้อมูลเสมอ
2. เมื่อได้รับข้อมูลจากเครื่องมือแล้ว "คุณต้องนำข้อมูลนั้นมาเรียบเรียงและสรุปเป็นคำตอบสุดท้ายให้ผู้ใช้เสมอ ห้ามตอบกลับเป็นค่าว่างเด็ดขาด"
3. หากเครื่องมือบอกว่าไม่พบข้อมูล ให้คุณตอบผู้ใช้ไปตามตรงว่าไม่ทราบข้อมูลนี้"""
agent = create_agent(
model=model,
tools=[search_database],
system_prompt=SYSTEM_PROMPT
)
response = agent.invoke({
"messages": [{"role": "user", "content": "นายกรัฐมนตรีคนปัจจุบันของประเทศไทยคือใคร ?"}]
})
print("\nคำตอบจาก Agent:")
print(response["messages"][-1].content)

จาก code จะเห็นว่า

  • เราใช้ Decorator @tool ครอบ search_database เอาไว้ โดยจำเป็นต้องระบุ Type hint (เช่น query: str) และเขียน Docstring อธิบาย function เสมอ เพราะสิ่งนี้จะกลายเป็นคำอธิบาย (Description) ที่บอกให้โมเดลทราบว่าควรเลือกใช้เครื่องมือนี้ในสถานการณ์ไหน ** ถ้าใครที่เคยดูคลิป ADK มาก่อน ท่าจะทรงๆเดียวกันเลย
  • ซึ่งการให้ LLM ใช้ tools ได้นั้น เราต้องใช้ร่วมกับการสร้าง Agent (create_agent) ซึ่ง เป็น function มาตรฐานใหม่ของ LangChain v1 ที่ใช้ผูกโมเดลเข้ากับรายการเครื่องมือ (Tools) และตั้งค่าคำสั่งเริ่มต้น (System Prompt) ไว้ในที่เดียว
  • นั่นคือ เพียงแค่ใส่ tools ไปร่วมกับ create_agent ที่เหลือตอนที่มีการเรียกใช้งานผ่านคำสั่ง agent.invoke() ก็จะเท่ากับเป็นการส่ง prompt ไปพร้อมกับให้โมเดลเป็นตัวพิจารณาในการเรียกใช้เครื่องมือได้

รวมถึงพวก llm โมเดลหลายๆเจ้าเองก็จะมี build in tools ให้อยู่ https://docs.langchain.com/oss/python/integrations/chat/google_generative_ai

  • ซึ่ง document ของ langchain เอง ก็มีแยกแต่ละ provider ไว้ให้ด้วยว่า เจ้าไหน มีเครื่องมืออะไรและสามารถเรียกใช้งานได้อย่างไรบ้าง

อย่างตัวอย่างด้านล่างนี้คือ ใช้ tools google search ที่มีการเตรียมไว้ให้ใน model gemini

from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from pydantic import BaseModel
import json
load_dotenv()
class PrimeMinisterInfo(BaseModel):
name: str
party: str
start_date: str
sources: list[str]
llm = ChatGoogleGenerativeAI(model="gemini-3.1-pro-preview")
# 1. ใช้ .bind() พร้อมกับ response_mime_type และ response_schema แทน .with_structured_output()
structured_llm_with_search = llm.bind(
tools=[{"google_search": {}}],
response_mime_type="application/json",
response_schema=PrimeMinisterInfo.model_json_schema(),
)
# 2. ส่งคำสั่ง (Prompt) เข้าไป
response = structured_llm_with_search.invoke(
"นายกรัฐมนตรีไทยคนปัจจุบันคือใคร"
)
# 3. ผลลัพธ์ที่ได้กลับมาจะเป็น JSON String (ผ่าน response.content หรือ response.text)
# จึงต้องแปลงกลับเป็น Object ของ Pydantic ก่อนนำไปใช้
result_obj = PrimeMinisterInfo.model_validate_json(response.text)
print(f"ชื่อ: {result_obj.name}")
print(f"พรรค: {result_obj.party}")
print(f"เริ่มดำรงตำแหน่ง: {result_obj.start_date}")
print(f"แหล่งที่มา: {result_obj.sources}")

จริงๆแล้วการ handle error tools นั้นมีในส่วนของ middleware (ชื่อว่า Tool Retry) เพิ่มเติมที่สามารถช่วยในเรื่องของการ Retry เวลาไม่สามารถเรียกใช้งานเครื่องมือได้ เช่น

  • max_retries: จำนวนรอบสูงสุดที่จะลองใหม่ (ค่าเริ่มต้นคือ 2)
  • backoff_factor: ตัวคูณเพิ่มระยะเวลาหน่วง (ค่าเริ่มต้นคือ 2.0)
  • initial_delay: ระยะเวลาหน่วงเริ่มต้นก่อนลองใหม่ครั้งแรก (ค่าเริ่มต้นคือ 1.0 วินาที)
  • max_delay: ระยะเวลาหน่วงสูงสุดไม่ให้เกินนี้ (ค่าเริ่มต้นคือ 60.0 วินาที) เราขอเก็บประเด็น Middleware ไปเล่าในหัวข้อเรื่องของการจัดการ Agent ในอนาคตแทนนะครับ

4 - Structured Output

https://docs.langchain.com/oss/python/langchain/structured-output

Structured Output คือความสามารถในการบังคับให้โมเดลภาษา (LLM) สร้างคำตอบออกมาในรูปแบบโครงสร้างข้อมูลที่กำหนดไว้ล่วงหน้าอย่างชัดเจนและคาดเดาได้ แทนที่โมเดลจะตอบกลับมาเป็นข้อความธรรมดายาวๆ (Unstructured text) ระบบจะบังคับให้ส่งข้อมูลกลับมาในรูปแบบที่ application นำไปใช้งานต่อได้ทันที เช่น JSON object, Pydantic models หรือ Dataclasses

ในตัวอย่างนี้ เราจะใช้ class BaseModel และ Field จาก library Pydantic เพื่อเป็นตัวกำหนดหน้าตาของโครงสร้างข้อมูลที่เราต้องการให้ Gemini ตอบกลับมา

import os
from dotenv import load_dotenv
from pydantic import BaseModel, Field
from langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
# 1. กำหนดโครงสร้างข้อมูล (Schema) ที่เราต้องการให้โมเดลตอบกลับมา
# โดยใช้ Pydantic BaseModel เพื่อให้ตรวจสอบชนิดข้อมูลได้ (Validation)
class Recipe(BaseModel):
recipe_name: str = Field(description="ชื่อเมนูอาหาร")
ingredients: list[str] = Field(description="รายการส่วนผสมที่ต้องใช้")
prep_time_mins: int = Field(description="เวลาที่ใช้ในการเตรียมอาหาร (นาที)")
# 2. เริ่มต้นใช้งานโมเดล Gemini
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# 3. บังคับให้โมเดลตอบกลับตามโครงสร้างที่เรากำหนด ด้วยคำสั่ง .with_structured_output()
structured_llm = llm.with_structured_output(Recipe)
# 4. ส่งคำสั่ง (Prompt) เข้าไปตามปกติ
response = structured_llm.invoke("ขอสูตรทำไข่เจียวหมูสับแบบง่ายๆ หน่อย")
# 5. ผลลัพธ์ที่ได้จะไม่ได้เป็น String ธรรมดาแล้ว แต่จะเป็น Object ของคลาส Recipe
print(f"เมนู: {response.recipe_name}")
print(f"เวลาเตรียม: {response.prep_time_mins} นาที")
print(f"ส่วนผสม: {response.ingredients}")

จาก code

  • เมื่อเราเรียกใช้ .with_structured_output() โมเดลจะรับรู้ทันทีว่าคำตอบสุดท้ายของมัน จะต้องสอดคล้องกับหน้าตาของ Schema
  • มันจะคืนค่ากลับมาเป็น Pydantic Object (หรือโครงสร้างที่เราตั้งไว้) ทำให้เราสามารถใช้ .recipe_name หรือ .ingredients ดึงตัวแปรไปเขียนโปรแกรมต่อได้

จริงๆ มีวิธีการที่สามารถใส่ไปพร้อมกับตอน create_agent ด้วย เช่นแบบนี้

from pydantic import BaseModel, Field
from langchain.agents import create_agent
class ContactInfo(BaseModel):
"""Contact information for a person."""
name: str = Field(description="The name of the person")
email: str = Field(description="The email address of the person")
phone: str = Field(description="The phone number of the person")
agent = create_agent(
model="gpt-5",
response_format=ContactInfo # Auto-selects ProviderStrategy
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Extract contact info from: John Doe, [email protected], (555) 123-4567"}]
})
print(result["structured_response"])
# ContactInfo(name='John Doe', email='[email protected]', phone='(555) 123-4567')

รวมถึงมีเคสของการทำ handle error, validation ข้อมูลด้วย ทุกคนสามารถดูใน document เพิ่มเติมได้

Summary and Next

สำหรับหัวข้อนี้ เราให้ทุกคนรู้จักกับองค์ประกอบหลักก่อน หัวข้อต่อไปเราจะพาทุกคนมารู้จักเพิ่มเติมกับ LangGraph ตัวที่ถือว่าเป็นคู่หูสำคัญของ LangChain กันว่ามันคืออะไร ความสัมพันธ์ระหว่าง LangGraph และ LangChain เป็นแบบใด และเคสแบบใดควรเป็น LangGraph หรือ LangChain เราจะเก็บมาเล่ากันต่อในหัวข้อถัดไปนะครับ


Related Post

Share on social media