สามารถดู 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
pip install -U "langchain[google-genai]"- ใน document ของ langchain ที่ผมแปะไว้ มีเขียนในกรณี setup ของโมเดลแต่ละเจ้าไว้แล้ว
- หากใครใช้เจ้าอื่นสามารถเข้าไปดูที่ document ต้นทางได้เลย
ต่อมาเพิ่ม code สำหรับการคุยกับโมเดลเข้าไป โดย LangChain ได้นำเสนอเอาไว้ทั้งหมด 2 ท่าคือ
- ท่าแรก เป็นการ import ผ่าน model class ที่ langchain ได้ทำไว้ของแต่ละเจ้า
import osfrom 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 osfrom dotenv import load_dotenvfrom 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
- https://docs.langchain.com/oss/python/langchain/messages
- https://reference.langchain.com/python/langchain-core/prompts/chat/ChatPromptTemplate
Message ใน LangChain คือ หน่วยพื้นฐานที่สุดที่ใช้ในการส่งข้อมูลและบริบท (Context) ให้กับ LLM โดยทำหน้าที่เป็นตัวแทนของข้อมูลทั้งฝั่งขาเข้า (Input) และขาออก (Output) เมื่อเราโต้ตอบกับโมเดล
เพื่อให้สามารถใช้งานข้ามระหว่างผู้ให้บริการโมเดลต่างๆ (เช่น Google, OpenAI, Anthropic) ได้อย่างมีมาตรฐานเดียวกัน LangChain จึงได้ออกแบบ Message ให้มีองค์ประกอบหลัก 3 ส่วน ได้แก่:
- Role: ตัวระบุว่าใครเป็นคนส่งข้อความนี้ (เช่น ระบบ, ผู้ใช้, หรือ AI)
- Content: ข้อมูลที่ต้องการส่ง ซึ่งสามารถเป็นได้ทั้งข้อความธรรมดา (Text) หรือข้อมูลแบบหลายสื่อ (Multimodal) เช่น รูปภาพหรือไฟล์เสียง
- 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 osfrom dotenv import load_dotenvfrom langchain.messages import HumanMessage, SystemMessagefrom 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# เราสามารถเข้าถึงเนื้อหาคำตอบได้ผ่านแอตทริบิวต์ .contentprint(response.content)ซึ่งจริงๆนอกจากจะเขียนผ่าน class ของ langchain.messages แล้ว ยัสามารถเขียนในรูปแบบอื่นๆได้เช่นกัน เช่น
- Dictionary format ซึ่งเป็นวิธีที่ตรงไปตรงมา โดยกำหนดผ่าน key
roleและcontent
import osfrom dotenv import load_dotenvfrom 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# เราสามารถเข้าถึงเนื้อหาคำตอบได้ผ่านแอตทริบิวต์ .contentprint(response.content)- ใช้ผ่าน ChatPromptTemplate สำหรับการทำ Message prompts ที่มีความยืดหยุ่น โดย LangChain มี class
ChatPromptTemplateที่ออกแบบมาเพื่อสร้าง template ของบทสนทนา โดยเราสามารถใช้รูปแบบ Tuple(role, template)ในการกำหนดบทบาทและข้อความ ซึ่งรองรับการใส่ตัวแปร (เช่น{topic}) เพื่อแทนที่คำในภายหลังได้
import osfrom dotenv import load_dotenvfrom langchain_google_genai import ChatGoogleGenerativeAIfrom langchain_core.prompts import ChatPromptTemplate
load_dotenv()
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# การสร้าง Message prompts ด้วยการใช้ Tuple ควบคู่กับ ChatPromptTemplateprompt_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 osimport base64from dotenv import load_dotenvfrom langchain_google_genai import ChatGoogleGenerativeAI
load_dotenv()
# 1. เริ่มต้นใช้งานโมเดลmodel = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")
# 2. function สำหรับอ่านไฟล์ภาพและแปลงเป็น Base64def 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 ตามรูปแบบมาตรฐานของ LangChainmessage = { "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
- https://docs.langchain.com/oss/python/langchain/agents
- https://www.geeksforgeeks.org/artificial-intelligence/react-reasoning-acting-prompting/
Agent คือระบบที่นำโมเดล LLM มาผสานการทำงานเข้ากับเครื่องมือ (Tools) ต่างๆ เพื่อสร้างระบบที่สามารถคิดวิเคราะห์เกี่ยวกับงานที่ได้รับมอบหมาย ตัดสินใจเลือกใช้เครื่องมือ และทำงานซ้ำๆ อย่างเป็นขั้นตอนเพื่อนำไปสู่การแก้ปัญหาได้สำเร็จ
หลักการทำงานที่สำคัญของ Agent ประเภทนี้คือการทำงานแบบวน loop ตามรูปแบบที่เรียกว่า ReAct (“Reasoning + Acting”)

- 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 osfrom dotenv import load_dotenvfrom langchain_google_genai import ChatGoogleGenerativeAIfrom langchain.agents import create_agentfrom langchain.tools import tool
load_dotenv()
mock_database = { "นายกรัฐมนตรี": "นายกรัฐมนตรีคนปัจจุบันของประเทศไทยคือ อนุทิน ชาญวีรกูล", "mikelopster": "Mikelopster คือ Content Creator ที่ชอบแบ่งปันความรู้ด้านการเขียนโปรแกรมและ AI",}
@tooldef 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 เพื่อลดความผิดเพี้ยนของการตัดสินใจของ Agentmodel = 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_dotenvfrom langchain_google_genai import ChatGoogleGenerativeAIfrom pydantic import BaseModelimport 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 osfrom dotenv import load_dotenvfrom pydantic import BaseModel, Fieldfrom 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. เริ่มต้นใช้งานโมเดล Geminillm = 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 ของคลาส Recipeprint(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, Fieldfrom 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 เราจะเก็บมาเล่ากันต่อในหัวข้อถัดไปนะครับ
- ลองเล่น Supabase กับ Next.js กันมี Video มี Github
รู้จักกับ Supabase เทคโนโลยีฐานข้อมูลที่เรียกตัวเองว่าเป็น Firebase alternative กันว่าใช้ทำอะไรได้บ้าง
- ลอง Firebase Data Connectมี Github
มารู้จัก นวัตกรรม SQL จากฝั่ง Firebase ผ่าน Service ตัวใหม่ Firebase Data Connect กัน
- รู้จักกับ Design Pattern - Creational (Part 1/3)มี Video
มาเรียนรู้รูปแบบการพัฒนา Software Design Pattern ประเภทแรก Creational กัน
- มารู้จักกับ Elasticseach ที่ใช้ทำ Search engine กันมี Video
มาลองทำ search ผ่าน Elasticsearch กัน มาทำความรู้จักกันว่า Elasticsearch คืออะไร ?