Học AI Agents

"Học AI Agents" là một hành trình thực tiễn giúp người đọc khám phá và xây dựng các ứng dụng AI Agent thông minh, linh hoạt. Với trọng tâm là các công nghệ hiện đại như LangChain, LangGraph, và các mô hình ngôn ngữ lớn (LLMs), sách hướng dẫn từng bước để phát triển các agent có khả năng tương tác, ra quyết định và sử dụng công cụ hiệu quả. Bên cạnh lý thuyết súc tích, sách đi kèm nhiều ví dụ thực tế như tạo chatbot, trợ lý cá nhân, hệ thống phân tích tự động. Đặc biệt phù hợp cho developer, data engineer và những ai đang muốn ứng dụng AI vào sản phẩm của mình. Đây là cuốn sách cầu nối giữa tư duy kỹ thuật và sức mạnh của AI hiện đại.
Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

AI Agents đang thay đổi cách chúng ta làm việc, học tập và tương tác với công nghệ. Không chỉ đơn thuần là công cụ tự động hóa, chúng còn có khả năng ra quyết định, thích ứng và cộng tác như một “đồng nghiệp số” thực thụ. Để tận dụng hết tiềm năng này, chúng ta cần hiểu rõ cách AI Agents hoạt động, ứng dụng và tạo ra giá trị thực trong doanh nghiệp và cuộc sống.

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Gen AI và AI Agents

Gen AI là gì?

Gen AI (viết tắt của Generative Artificial Intelligence) là một nhánh của trí tuệ nhân tạo tập trung vào việc tạo ra nội dung mới thay vì chỉ phân tích hay nhận diện như AI truyền thống.

Ví dụ về Gen AI:

Công nghệ nền tảng:

AI Agents là gì?

AI Agents (hay còn gọi là Autonomous Agents) là những hệ thống AI có khả năng tự chủ động thực hiện các hành động để đạt được mục tiêu nào đó. Chúng không chỉ phản hồi một câu hỏi đơn giản, mà còn có thể:

Ví dụ dễ hiểu:

Bạn nói với AI Agent:
“Tìm kiếm thông tin về thị trường ô tô Việt Nam, viết báo cáo, tạo biểu đồ và gửi vào email tôi.”

Thì AI Agent có thể:

  1. Dùng công cụ tìm kiếm → tổng hợp thông tin

  2. Phân tích dữ liệu → viết báo cáo

  3. Tạo biểu đồ bằng code (Python, Excel, v.v.)

  4. Kết nối Gmail → gửi mail

Tất cả các bước đều tự động, và có logic suy nghĩ như một con người làm việc.

Một số Framework phổ biến:


So sánh đơn giản:

Đặc điểm Gen AI AI Agent
Mục tiêu chính Tạo nội dung Hoàn thành nhiệm vụ
Tính chủ động Phản hồi theo yêu cầu Tự ra quyết định, tự thực hiện
Ví dụ ChatGPT viết bài, DALL·E vẽ tranh AutoGPT hoàn thành project

Dưới đây là ví dụ cụ thể về Gen AIAI Agents được áp dụng trong lĩnh vực sản xuất (ví dụ: cơ khí, nhà máy, ERP...):

Gen AI trong sản xuất:

Tình huống: Hỗ trợ lập báo cáo sản xuất

Bạn cần viết một báo cáo năng suất xưởng gia công trong tuần để gửi cho giám đốc.

Gen AI làm gì?

Bạn chỉ cần nhập:

“Tạo báo cáo tổng kết năng suất xưởng A từ dữ liệu sau: số lượng sản phẩm, tỷ lệ lỗi, thời gian vận hành máy...”

→ Gen AI (như ChatGPT) sẽ viết một báo cáo hoàn chỉnh với văn phong chuyên nghiệp, có thể thêm biểu đồ hoặc gợi ý cải tiến.

Tình huống: Đào tạo công nhân mới

Bạn có một nhóm công nhân mới chưa quen quy trình.

Gen AI làm gì?

Bạn dùng Gen AI để:

AI Agents trong sản xuất:

Tình huống: Quản lý đơn hàng và tồn kho tự động

Bạn muốn tự động hoá việc:

AI Agent làm gì?

  1. Theo dõi hệ thống tồn kho

  2. Nếu thấy sắp hết → tự động gửi đơn đặt hàng cho nhà cung cấp

  3. Nếu phát hiện đơn hàng giao chậm → gửi cảnh báo cho phòng mua hàng

  4. Nếu vượt mức tiêu hao nguyên vật liệu → gợi ý kiểm tra lỗi quy trình

Bạn chỉ cần thiết lập mục tiêu:

“Đảm bảo tồn kho nguyên vật liệu tối thiểu 500 đơn vị và không để ngưng sản xuất”

→ Agent sẽ tự vận hành như một nhân viên giám sát thông minh.


Tình huống: Kiểm soát chất lượng (QC)

Bạn muốn AI giám sát quy trình QC và đưa ra đánh giá.

AI Agent có thể:


Tóm lại:

Tình huống Gen AI làm gì AI Agent làm gì
Viết báo cáo QC Viết nội dung, định dạng báo cáo Lấy dữ liệu, tổng hợp, gửi báo cáo đúng giờ
Đào tạo nhân viên mới Tạo tài liệu học, video minh hoạ Tùy theo trình độ nhân viên, chọn nội dung học phù hợp
Quản lý đơn hàng Viết email, báo cáo mua hàng Tự đặt hàng, kiểm tra tiến độ, báo lỗi
Giám sát sản xuất Viết cảnh báo nếu có lỗi Tự thu thập dữ liệu, phát hiện lỗi, báo cáo
  1. AI Agent kiểm soát tồn kho tự động

  2. Gen AI tạo báo cáo lỗi sản xuất từ dữ liệu thực tế


1. AI Agent kiểm soát tồn kho (Tự động hóa)

Mục tiêu:

“Đảm bảo nguyên vật liệu Thép tấm A luôn đủ trong kho để sản xuất, không bị gián đoạn.”

Quy trình hoạt động của Agent:

Input:


Agent thực hiện:

  1. Kiểm tra tồn kho hiện tại

    • Ví dụ: còn 120 tấm Thép A

  2. Dự đoán tiêu thụ trong 3 ngày tới

    • Dựa vào dữ liệu lịch sử: 30 tấm/ngày → 3 ngày = 90 tấm

  3. So sánh tồn kho và mức an toàn

    • Nếu 120 - 90 < 50 → cần đặt hàng

  4. Tự động gửi đơn hàng

    • Gửi email/mẫu đơn tới nhà cung cấp

  5. Gửi cảnh báo tới phòng vật tư

    • “Dự kiến tồn kho xuống thấp trong 3 ngày. Đã gửi yêu cầu đặt hàng.”


Agent thực hiện mỗi ngày (cron job hoặc real-time)


Có thể xây bằng gì?


2. Gen AI viết báo cáo lỗi sản xuất

Mục tiêu:

Viết báo cáo lỗi sản xuất trong tuần cho xưởng gia công cơ khí.

image.png

Gen AI tạo báo cáo:

image.png

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

AI Agents và Multi-Agents

AI Agent là gì?

AI Agent là một hệ thống trí tuệ nhân tạo có thể tự hành động để hoàn thành mục tiêu nào đó. Nó có thể suy nghĩ, lên kế hoạch, ra quyết định và hành động mà không cần con người can thiệp liên tục.

Một AI Agent thường gồm 4 thành phần:

Thành phần Vai trò
Perception (Cảm nhận) Nhận dữ liệu từ môi trường hoặc hệ thống
Reasoning (Suy luận) Phân tích dữ liệu và đưa ra lựa chọn
Planning (Lập kế hoạch) Xác định các bước cần làm
Action (Hành động) Thực hiện hành động cụ thể (gửi email, chạy code, gọi API...)

Ví dụ về AI Agent:

"Tạo Agent kiểm soát tồn kho nguyên vật liệu"


Multi-Agent là gì?

Multi-Agent System (Hệ thống đa tác tử) là một hệ thống gồm nhiều AI Agents làm việc cùng nhau, mỗi agent có vai trò riêng, phối hợp để hoàn thành một nhiệm vụ phức tạp hơn.


So sánh:

  AI Agent Multi-Agent System
Số lượng Agent 1 Nhiều
Mức độ phức tạp Thấp đến trung bình Cao
Tự vận hành Có, và có phối hợp với agent khác
Ứng dụng Tác vụ đơn Tác vụ phức tạp cần chia vai trò

Ví dụ thực tế – Hệ thống Multi-Agent trong sản xuất

Mục tiêu: Quản lý toàn bộ quy trình sản xuất từ đơn hàng → sản xuất → QC → giao hàng

Gồm 4 AI Agents:

Agent Nhiệm vụ
Order Agent Nhận đơn hàng, lên lịch sản xuất
Production Agent Giám sát tiến độ sản xuất
QC Agent Theo dõi lỗi, kiểm tra chất lượng
Logistics Agent Điều phối giao hàng, lên lịch xe

→ Các Agent này giao tiếp với nhau: ví dụ khi Production Agent hoàn thành, nó sẽ báo cho QC Agent kiểm tra.


Một số công cụ hỗ trợ Multi-Agent:


Tổng kết:

Khái niệm AI Agent Multi-Agent System
Định nghĩa Hệ thống AI tự động xử lý một nhiệm vụ Nhiều AI agents phối hợp để xử lý tác vụ phức tạp
Phạm vi Tác vụ riêng lẻ Dự án/Quy trình lớn
Giao tiếp Không cần (hoặc ít) Cần giao tiếp giữa các agent
Ứng dụng Trả lời câu hỏi, giám sát thiết bị Quản lý sản xuất, tài chính, lập kế hoạch

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Minh hoạ một hệ thống Multi-Agent trong nhà máy sản xuất cơ khí

Mô hình Multi-Agent cho Nhà máy Cơ khí

Mục tiêu:

Tự động hóa quy trình từ đặt hàng → sản xuất → QC → lưu kho → giao hàng, với các AI Agents phối hợp như một đội nhân sự.


Các AI Agents và nhiệm vụ

Tên Agent Vai trò chính
🧾 Order Agent Tiếp nhận đơn hàng, kiểm tra tồn kho, lên lịch sản xuất
⚙️ Production Agent Theo dõi tiến độ sản xuất, cập nhật trạng thái
🔍 QC Agent Tự động kiểm tra dữ liệu lỗi và đánh giá chất lượng
📦 Inventory Agent Kiểm soát kho, đảm bảo tồn kho nguyên vật liệu và thành phẩm
🚚 Logistics Agent Lên kế hoạch giao hàng và điều phối xe
🤝 Communication Agent (Tùy chọn) Gửi thông báo email, cảnh báo hoặc báo cáo

Mô phỏng quy trình hoạt động

Order Agent


Production Agent


QC Agent


Inventory Agent


Logistics Agent


Communication Agent (tuỳ chọn)

Sơ đồ hệ thống Multi-Agent (giản lược)

image.png

Công nghệ có thể sử dụng để triển khai:

Nhu cầu Gợi ý công nghệ
Xây dựng Agents LangChain, CrewAI, AutoGen
Kết nối dữ liệu, API, ERP Python, FastAPI, REST API
Tích hợp với hệ thống sẵn có VHTerp, Odoo, SAP, SQL Server, Excel
Giao tiếp giữa Agents WebSocket, Message Queue (RabbitMQ, MQTT)
Trực quan hóa trạng thái Streamlit, Dash, React Dashboard

Lợi ích thực tế

Giảm thời gian xử lý thủ công
Tăng độ chính xác trong lập lịch sản xuất
Cảnh báo sớm rủi ro (thiếu nguyên vật liệu, lỗi hàng loạt)
Tự động hoá báo cáo và thông báo
Giao tiếp giữa các bộ phận hiệu quả, không lệ thuộc con người

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Thị Trường AI Agents: Cơ Hội, Chi Phí và Xu Hướng Ứng Dụng Trong Doanh Nghiệp

Cơ hội thị trường (Opportunities)

Thị trường AI Agents đang bùng nổ nhờ:

Theo báo cáo của McKinsey, đến năm 2030, AI Agents có thể giúp tăng thêm 13 nghìn tỷ USD cho nền kinh tế toàn cầu.


Chi phí (Cost)

Chi phí phát triển và triển khai AI Agents phụ thuộc vào nhiều yếu tố:

Hạng mục Chi phí ước tính Ghi chú
Phát triển nội bộ Trung đến cao Tốn thời gian, cần đội ngũ kỹ sư AI
Dùng nền tảng có sẵn Thấp đến trung bình CrewAI, LangChain, AutoGen, AgentOps...
Mô hình AI (LLM) Biến động theo API Dùng OpenAI, Claude, Mistral, LLaMA...
Bảo trì & tích hợp hệ thống Trung bình Cần đảm bảo bảo mật, hiệu suất cao

Tổng quan, chi phí đang giảm nhờ mã nguồn mở, mô hình mã hoá nhẹ, và nền tảng hỗ trợ no-code/low-code.


Mức độ áp dụng trong doanh nghiệp (Enterprise adoption)

Các doanh nghiệp đang tích cực thử nghiệm và triển khai AI Agents, đặc biệt trong các khâu như:

🔹 Công ty đi đầu: Microsoft, Google, Meta, SAP, ServiceNow, Nvidia, OpenAI
🔹 Thị trường SMB (doanh nghiệp vừa và nhỏ) cũng đang thử nghiệm qua các nền tảng như Zapier AI Agents, LangGraph, hay MultiOn.


Ứng dụng theo ngành

1. Nội dung & Marketing (Content)

Công cụ: Jasper, Copy.ai, Writer, AutoGPT


2. Y tế (Healthcare)

Thí dụ: Agent kiểm tra triệu chứng, tổng hợp dữ liệu bệnh nhân để gửi bác sĩ.


3. Công nghệ sinh học (Biotech)

Ví dụ: Agent đề xuất cấu trúc phân tử mới dựa trên dữ liệu protein.


4. Dịch vụ tài chính (Financial Services)

Ví dụ: Agent đọc và tổng hợp báo cáo lợi nhuận để hỗ trợ phòng tài chính ra quyết định.


5. Phát triển phần mềm (Software Development)

Ví dụ: Dự án MetaGPT mô phỏng cả đội làm sản phẩm: PM, Tech Lead, QA, Dev...


Tương lai của AI Agents

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Lợi Ích Chính Của AI Agent Trong Doanh Nghiệp Hiện Đại

Trong kỷ nguyên chuyển đổi số, AI Agent (tác tử AI) đang trở thành một trong những công cụ mạnh mẽ nhất giúp doanh nghiệp nâng cao hiệu suất, giảm chi phí và tăng khả năng cạnh tranh. Với khả năng tự động hoá thông minh, phản ứng linh hoạt và học hỏi liên tục, AI Agent không chỉ là một công cụ – mà là một trợ lý ảo có tư duy.

Dưới đây là những lợi ích chính mà AI Agent mang lại:


Tự động hoá thông minh

AI Agent có thể đảm nhiệm nhiều công việc phức tạp mà trước đây đòi hỏi con người, ví dụ:

⏱️ Kết quả: Tiết kiệm thời gian, tăng hiệu suất và giảm sai sót.


Ra quyết định nhanh và chính xác

AI Agent được hỗ trợ bởi các mô hình học máy (Machine Learning) và AI tổng quát (Generative AI), giúp:

📊 Kết quả: Doanh nghiệp đưa ra quyết định dựa trên dữ liệu thay vì cảm tính.


Làm việc liên tục 24/7

Không như con người, AI Agent không cần nghỉ ngơi và có thể làm việc liên tục mọi thời điểm:

🌙 Kết quả: Đảm bảo quy trình hoạt động liền mạch, không bị gián đoạn.


Cá nhân hoá trải nghiệm người dùng

AI Agent có thể nhớ và học từ hành vi của từng người dùng để:

💬 Kết quả: Tăng sự hài lòng, giữ chân khách hàng và tạo ấn tượng chuyên nghiệp.


Giảm chi phí vận hành

Việc thay thế các thao tác thủ công bằng AI Agent giúp:

💰 Kết quả: Doanh nghiệp có thể mở rộng quy mô mà không cần tăng tương ứng về nhân sự.


Khả năng học hỏi và thích nghi

AI Agents có thể được huấn luyện và cải tiến liên tục để:

🧠 Kết quả: AI Agent ngày càng "thông minh" hơn và phù hợp hơn với môi trường thực tế.


Phối hợp linh hoạt trong môi trường Multi-Agent

Nhiều AI Agent có thể phối hợp như một đội ngũ chuyên trách, ví dụ:

Kết quả: Xây dựng hệ thống làm việc thông minh, phân quyền rõ ràng và hiệu quả cao.


Kết luận

AI Agent đang trở thành “cánh tay phải kỹ thuật số” của mọi tổ chức hiện đại. Dù là trong sản xuất, tài chính, y tế, marketing hay chăm sóc khách hàng, việc áp dụng AI Agent không chỉ giúp doanh nghiệp đi nhanh hơn, mà còn đi đúng hướngbền vững hơn trong tương lai.

Bạn đang cân nhắc đưa AI Agent vào doanh nghiệp mình? Hãy bắt đầu từ những tác vụ lặp đi lặp lại, nhiều dữ liệu – và mở rộng dần theo nhu cầu!
Gọi ngay cho đội ngũ VHTSoft(0969661340), chúng tôi sẽ hỗ trợ lập kế hoạch truyển khai mô hình AI cho doanh nghiệp bạn

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Nguyên tắc triển khai AI agent

1.  Cung cấp quyền truy cập nhật ký hệ thống(Provide Access to Logs)

Giới thiệu:

Ghi lại và truy cập nhật ký hoạt động của AI agent giúp theo dõi, kiểm tra và phân tích hành vi của hệ thống trong suốt vòng đời vận hành.

Key Practices:

Benefits:


2. Khả năng tạm dừng hoặc chấm dứt an toàn(Ability to Pause or Terminate Safely)

Giới thiệu:

Một AI agent nên được thiết kế sao cho có thể được tạm dừng hoặc chấm dứt hoạt động một cách an toàn mà không gây ra hậu quả nghiêm trọng hay mất mát dữ liệu.

Key Practices:

Benefits:


Giám sát bởi con người(Human Supervision)

Giới thiệu:

Sự can thiệp của con người đảm bảo rằng AI hoạt động đúng mục tiêu và đạo đức, đặc biệt khi xử lý các tình huống phức tạp hoặc có tác động lớn.

Key Practices:

Benefits:


4. Kiểm tra có hệ thống các dữ liệu lệch lạc(Systematic Audit for Biases )

Giới thiệu:

AI agent có thể vô tình học và khuếch đại các thiên lệch có trong dữ liệu huấn luyện. Do đó cần có quy trình kiểm tra định kỳ để phát hiện và giảm thiểu dữ liệu lệch lạc.

Key Practices:

Benefits:


5. Bảo vệ khỏi truy cập trái phép(Protect Against Unauthorized Access)

Giới thiệu:

AI agent cần được bảo vệ trước các mối đe dọa về an ninh mạng để tránh việc bị khai thác hoặc bị sử dụng vào mục đích xấu.

Key Practices:

Benefits:

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Các trường hợp ứng dụng của AI Agent trong đời sống

1. Dịch vụ tài chính(Financial Services)

Giới thiệu:
AI agents đang thay đổi cách ngành tài chính hoạt động thông qua việc tự động hóa quy trình, phân tích rủi ro, và cá nhân hóa trải nghiệm khách hàng.

Ứng dụng:


2. Phần mềm(Software )

 Giới thiệu:
AI agents hỗ trợ tăng tốc quá trình phát triển phần mềm và cải thiện hiệu suất bảo trì, kiểm thử và triển khai hệ thống.

Ứng dụng:


3. Marketing

Giới thiệu:
AI agents giúp cá nhân hóa nội dung, dự đoán hành vi khách hàng và tối ưu hóa chiến dịch tiếp thị một cách hiệu quả.

Ứng dụng:


4. Y tế(Healthcare)

 Giới thiệu:
Trong ngành y tế, AI agents hỗ trợ chẩn đoán chính xác, theo dõi bệnh nhân và tối ưu hóa quá trình chăm sóc.

Ứng dụng:


5. Chuỗi cung ứng(Supply Chain)

Giới thiệu:
AI agents cải thiện khả năng dự báo, tối ưu hóa vận hành và quản lý tồn kho hiệu quả trong chuỗi cung ứng.

Ứng dụng:


6. Dịch vụ khách hàng(Customer Services)

Giới thiệu:
AI agents được sử dụng để cung cấp hỗ trợ khách hàng liên tục 24/7 và cá nhân hóa trải nghiệm tương tác.

Ứng dụng:


7. Ứng phó khẩn cấp(Emergency Response)

Giới thiệu:
AI agents giúp cải thiện phản ứng nhanh và hiệu quả trong các tình huống khẩn cấp như thiên tai, tai nạn hoặc y tế.

Ứng dụng:


8. Thương mại điện tử và bán lẻ(E-commerce and Retail)

Giới thiệu:
AI agents tạo ra trải nghiệm mua sắm thông minh hơn, giúp cá nhân hóa và tối ưu hóa chuỗi bán hàng.

Ứng dụng:


9. Giáo dục và đào tạo(Education and Training)

Giới thiệu:
AI agents hỗ trợ người học cá nhân hóa lộ trình học tập, đưa ra phản hồi kịp thời và nâng cao hiệu quả giảng dạy.

Ứng dụng:


10. Trợ lý cá nhân và thiết bị thông minh(Personal Assistants and Smart Devices)

Giới thiệu:
AI agents ngày càng trở thành một phần thiết yếu trong đời sống cá nhân qua trợ lý ảo và các thiết bị IoT thông minh.

Ứng dụng:


11. Robot thông minh(Robotics)

Giới thiệu:
AI agents đóng vai trò "bộ não" cho robot, giúp robot nhận thức môi trường, tương tác và đưa ra quyết định.

Ứng dụng:


12. Tác nhân đa nhiệm / Hệ thống nhiều tác nhân(Multi-Agents)

Giới thiệu:
Hệ thống nhiều AI agents làm việc cùng nhau để giải quyết các vấn đề phức tạp vượt quá khả năng của một tác nhân đơn lẻ.

Ứng dụng:

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Làm Thế Nào Để Xây Dựng Kế Hoạch Giới Thiệu AI Agents Trong Công Ty Của Bạn?

Trong bối cảnh công nghệ ngày càng phát triển, AI Agents (tác nhân trí tuệ nhân tạo) đang trở thành công cụ đột phá giúp các doanh nghiệp nâng cao hiệu suất, tối ưu hóa vận hành và mở rộng khả năng sáng tạo. Nhưng làm sao để bắt đầu? Làm thế nào để hiểu tiềm năng thật sự của AI agents và từng bước xây dựng kế hoạch triển khai chúng trong tổ chức?

Hãy cùng khám phá một cách tiếp cận thực tiễn để giới thiệu AI Agents vào doanh nghiệp của bạn, từ khâu tìm hiểu đến triển khai và mở rộng.


1. Hiểu Rõ AI Agents Là Gì Và Mang Lại Lợi Ích Gì?

AI agents là những hệ thống có khả năng:

Khác với các hệ thống tự động hóa thông thường, AI agents có thể học hỏi, thích nghi và thậm chí phối hợp với các tác nhân khác (multi-agent systems) để giải quyết vấn đề phức tạp.

Lợi ích tiềm năng của AI Agents:


2. Đánh Giá Nhu Cầu Doanh Nghiệp & Các Tình Huống Ứng Dụng (Use Cases)

Trước khi xây dựng, bạn cần xác định các lĩnh vực có thể ứng dụng AI agents trong doanh nghiệp của mình. Một số lĩnh vực tiềm năng:

👉 Hãy bắt đầu từ một hoặc hai tình huống rõ ràng, có thể đo lường hiệu quả, trước khi mở rộng.


3. Thiết Kế Lộ Trình Triển Khai AI Agent

Dưới đây là các bước đề xuất trong kế hoạch triển khai:

Bước 1: Xây dựng đội ngũ và xác định người phụ trách

Bước 2: Chọn công nghệ và công cụ phù hợp

Bước 3: Phát triển phiên bản thử nghiệm (MVP)

Bước 4: Đánh giá và cải tiến


4. Đảm Bảo Các Yếu Tố Bảo Mật, Giám Sát Và Đạo Đức

Khi đưa AI agents vào hệ thống thực tế, bạn cần quan tâm đến:


5. Mở Rộng Và Tích Hợp Sau Khi Thành Công Giai Đoạn Thử Nghiệm

Sau khi đã chứng minh hiệu quả của AI agent, bạn có thể:


Kết Luận

AI agents không phải là công nghệ xa vời — chúng đã và đang hiện diện trong các doanh nghiệp tiên phong. Với một kế hoạch rõ ràng, bạn hoàn toàn có thể:

Bắt đầu hôm nay để đón đầu tương lai!

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Những thách thức triển khai AI Agents

Việc triển khai AI Agents trong doanh nghiệp và các tổ chức mở ra nhiều cơ hội đổi mới, nhưng cũng đi kèm với không ít thách thức phức tạp. Về mặt kỹ thuật, các AI Agents có thể gặp rủi ro như vòng lặp phản hồi vô hạn, thiếu khả năng giải thích quyết định, và đòi hỏi tài nguyên tính toán lớn. Hạ tầng công nghệ như mô hình nền tảng, phần cứng, điện toán đám mây và khả năng tích hợp phần mềm cũng có thể trở thành điểm nghẽn. Trong quá trình triển khai, doanh nghiệp cần đối mặt với các vấn đề như định nghĩa quy trình, bảo mật dữ liệu, giám sát con người và đảm bảo đạo đức AI. Bên cạnh đó, thị trường AI đang bị chi phối bởi các nhà cung cấp lớn, thỏa thuận độc quyền và rào cản từ các nền tảng di động. Cuối cùng, vấn đề quản trị như khung pháp lý, tiêu chuẩn, cơ chế minh bạch và hợp tác liên ngành cũng là yếu tố sống còn để đảm bảo AI phát triển bền vững và có trách nhiệm.

I. Rủi ro và hạn chế kỹ thuật của AI Agents

1. Sự hợp tác có nghĩa là nhiều rủi ro hơn

Mô tả: Khi nhiều AI agents cùng tương tác hoặc cộng tác để hoàn thành một nhiệm vụ, rủi ro hệ thống trở nên phức tạp hơn. Nếu một tác nhân có hành vi sai lệch, nó có thể ảnh hưởng dây chuyền đến các tác nhân khác, gây ra hiệu ứng domino.

Ví dụ: Trong một hệ thống AI hỗ trợ vận hành chuỗi cung ứng, một AI phụ trách dự đoán nhu cầu có thể đưa ra dự báo sai, khiến AI điều phối kho bãi nhập hàng dư thừa, và AI phụ trách vận chuyển phải xử lý khối lượng vượt mức — dẫn đến tắc nghẽn toàn hệ thống.

2. Vòng phản hồi vô hạn

Mô tả: Khi AI agent học từ phản hồi của chính mình hoặc từ tác nhân khác mà không có cơ chế giới hạn, có thể tạo ra vòng lặp phản hồi vô tận. Điều này dẫn đến hành vi lệch lạc, dữ liệu huấn luyện sai lệch hoặc quyết định ngày càng sai.

Ví dụ: Một chatbot AI trả lời khách hàng và đồng thời học từ phản hồi... của chính nó (vì bị nhầm là từ người dùng). Sau một thời gian, nó bắt đầu lặp lại câu trả lời không phù hợp và mất kiểm soát nội dung.

3. Tài nguyên tính toán

Mô tả: Các AI agents, đặc biệt là những agent phức tạp dùng mô hình ngôn ngữ lớn (LLMs), đòi hỏi sức mạnh tính toán rất cao. Điều này có thể làm tăng chi phí hạ tầng, chậm hệ thống hoặc gây quá tải.

Ví dụ: Một công ty triển khai AI trợ lý nội bộ sử dụng GPT để tổng hợp báo cáo. Khi hàng trăm nhân viên truy cập đồng thời, hệ thống trở nên chậm và tiêu tốn quá nhiều GPU trên cloud, gây tốn kém tài chính.

4. Thiếu khả năng giải thích

Mô tả: Nhiều AI agents hoạt động như hộp đen (black box), đưa ra quyết định mà con người khó hiểu được logic phía sau. Điều này gây khó khăn trong việc đánh giá, kiểm tra và tin tưởng AI.

Ví dụ: Một AI agent được giao nhiệm vụ từ chối hoặc duyệt đơn vay vốn, nhưng không thể giải thích lý do cụ thể tại sao đơn A được duyệt còn đơn B thì không, dù hồ sơ tương tự nhau. Điều này dễ dẫn đến nghi ngờ và khiếu nại.


II. Mô hình nền tảng

Mô tả: AI Agents thường dựa trên các mô hình ngôn ngữ lớn hoặc mô hình thị giác sâu đã được huấn luyện trước. Tuy nhiên, việc phụ thuộc vào các mô hình nền này có thể gây ra các vấn đề về chi phí, quyền truy cập, và độ phù hợp với từng trường hợp cụ thể. Ngoài ra, những mô hình này cũng có thể mang theo những thiên kiến và hạn chế từ dữ liệu gốc.

Ví dụ: Một công ty tài chính sử dụng GPT để hỗ trợ phân tích báo cáo tài chính. Tuy nhiên, mô hình nền tảng không hiểu rõ các khái niệm chuyên sâu trong ngành tài chính Việt Nam, dẫn đến phân tích sai hoặc thiếu thông tin quan trọng.

2. Phần cứng

Mô tả: Các tác nhân AI cần phần cứng mạnh mẽ, như GPU, TPU, RAM lớn hoặc thiết bị cảm biến chuyên biệt (trong robotics). Thiếu phần cứng phù hợp có thể làm chậm hệ thống, giảm hiệu suất, hoặc không thể chạy tác vụ thời gian thực.

Ví dụ: Một công ty bán lẻ triển khai robot AI để kiểm kê hàng hóa trong kho, nhưng robot không có đủ cảm biến hoặc camera chất lượng cao để đọc mã vạch trong điều kiện ánh sáng yếu — dẫn đến sai sót và tốn thời gian kiểm tra lại thủ công.

3. Hạ tầng đám mây

Mô tả: Hầu hết AI Agents hiện nay vận hành trên nền tảng điện toán đám mây. Tuy nhiên, hiệu suất của AI phụ thuộc nhiều vào khả năng mở rộng, bảo mật, và độ ổn định của cloud provider. Bất kỳ sự cố nào về mạng, bảo mật, hay tài nguyên hạn chế cũng ảnh hưởng đến toàn hệ thống.

Ví dụ: Một AI chăm sóc khách hàng đang vận hành qua dịch vụ đám mây bị gián đoạn do sự cố từ nhà cung cấp (ví dụ AWS bị downtime). Kết quả là hệ thống phản hồi khách hàng bị tê liệt trong nhiều giờ, ảnh hưởng đến trải nghiệm và uy tín thương hiệu.

4. Tích hợp phần mềm

Mô tả: Để AI agents hoạt động hiệu quả, chúng cần tích hợp liền mạch với các hệ thống hiện tại như CRM, ERP, HRM, v.v. Tuy nhiên, sự khác biệt về kiến trúc hệ thống, giao thức truyền thông hoặc độ tương thích có thể tạo ra rào cản lớn cho việc tích hợp.

Ví dụ: Một công ty muốn tích hợp AI để tự động tạo và gửi hóa đơn thông qua hệ thống kế toán cũ. Tuy nhiên, hệ thống hiện tại không hỗ trợ API hoặc không tương thích với mô hình AI hiện có, buộc phải xây dựng cầu nối trung gian tốn kém và mất thời gian.

III. Các vấn đề thực hiện

Triển khai AI Agents trong môi trường doanh nghiệp không chỉ đơn thuần là việc đưa một công nghệ mới vào hệ thống hiện có — đó là một quá trình phức tạp đòi hỏi sự chuẩn bị kỹ lưỡng về quy trình, hạ tầng và con người. Những thách thức này bắt đầu từ việc xác định rõ quy trình mà AI sẽ tham gia, cho đến việc tích hợp AI với các hệ thống hiện hành. Bảo mật dữ liệu là mối quan tâm hàng đầu, đặc biệt khi AI xử lý thông tin nhạy cảm. Đồng thời, AI cần có sự giám sát của con người để đảm bảo hoạt động đúng định hướng và phù hợp với giá trị đạo đức. Ngoài ra, việc duy trì tính công bằng, không dư thừa dữ liệu và đảm bảo khả năng mở rộng, bảo trì lâu dài cũng là những yếu tố sống còn cho sự thành công của AI trong thực tế.

1. Định nghĩa qui trình

Mô tả: Trước khi triển khai AI agent, doanh nghiệp cần xác định rõ quy trình nào sẽ được tự động hóa hoặc hỗ trợ. Thiếu định nghĩa quy trình rõ ràng sẽ khiến AI hoạt động không hiệu quả, chồng chéo với công việc con người hoặc gây gián đoạn vận hành.

Ví dụ: Một công ty muốn dùng AI để xử lý yêu cầu hỗ trợ khách hàng, nhưng không xác định rõ khi nào AI nên chuyển tiếp cho nhân viên thật. Hậu quả là AI giữ khách hàng quá lâu hoặc chuyển không đúng lúc, gây bất mãn.

2. Tích hợp

Mô tả: AI agents cần được tích hợp liền mạch vào hệ thống hiện có (CRM, ERP, website, v.v.). Quá trình này thường gặp khó khăn do không tương thích, thiếu API, hoặc kiến trúc phần mềm cũ.

Ví dụ: Một bệnh viện triển khai AI hỗ trợ đọc kết quả chụp X-quang, nhưng hệ thống AI không kết nối được với phần mềm lưu trữ hồ sơ bệnh án (EMR), khiến nhân viên phải nhập tay kết quả → chậm trễ và sai sót.

3. Bảo mật dữ liệu

Mô tả: AI agents cần truy cập và xử lý dữ liệu nhạy cảm như thông tin cá nhân, tài chính, y tế,… Nếu không được bảo vệ tốt, đây sẽ là lỗ hổng nghiêm trọng về bảo mật.

Ví dụ: Một AI hỗ trợ kế toán nội bộ bị khai thác qua API không được bảo mật, khiến dữ liệu lương và hợp đồng nhân sự bị rò rỉ ra bên ngoài.

4. Giám sát của con người

Mô tả: AI cần được giám sát bởi con người để đảm bảo hoạt động đúng, tránh lỗi hệ thống hoặc đưa ra quyết định không phù hợp. Thiếu giám sát có thể gây hậu quả nghiêm trọng, nhất là trong các ngành nhạy cảm.

Ví dụ: Một AI phỏng vấn tuyển dụng tự động loại bỏ nhiều ứng viên chỉ vì giọng nói địa phương, nhưng không có người kiểm tra lại các tiêu chí đánh giá → dẫn đến mất ứng viên chất lượng và phản ứng tiêu cực.

5. Mối quan tâm về đạo đức và thiên vị

Mô tả: AI có thể vô tình tái tạo hoặc khuếch đại các định kiến từ dữ liệu huấn luyện. Nếu không được kiểm soát, AI có thể đưa ra các quyết định phân biệt đối xử hoặc phi đạo đức.

Ví dụ: Một AI phân tích hồ sơ vay vốn học tập lại có xu hướng ưu tiên người từ khu vực đô thị hơn nông thôn, vì mô hình học từ dữ liệu lịch sử thiếu công bằng → gây bất bình đẳng xã hội.

6. Khả năng mở rộng và bảo trì

Mô tả: AI agent ban đầu có thể chạy tốt, nhưng khi số lượng người dùng hoặc dữ liệu tăng lên, hệ thống có thể bị quá tải nếu không được thiết kế để mở rộng. Đồng thời, AI cần được cập nhật và bảo trì định kỳ.

Ví dụ: Một cửa hàng online dùng AI để gợi ý sản phẩm. Trong mùa sale, lượng truy cập tăng gấp 10 lần khiến AI đưa ra đề xuất sai hoặc đứng hệ thống → làm mất doanh thu và trải nghiệm khách hàng.

III. Các nhà cung cấp chi phối thị trường

Thị trường hiện tại lại đang bị chi phối bởi một số rào cản lớn có thể cản trở khả năng phát triển và triển khai của các doanh nghiệp. Những thách thức này bao gồm sự thống trị của các nhà cung cấp lớn (dominant providers), các thỏa thuận độc quyền (exclusivity agreements), và sự kiểm soát chặt chẽ từ các nền tảng di động như hệ điều hành và chợ ứng dụng (mobile OS and app stores). Những yếu tố này không chỉ làm hạn chế sự lựa chọn công nghệ, mà còn ảnh hưởng đến khả năng tiếp cận, phân phối và sáng tạo trong không gian AI. Do đó, các doanh nghiệp muốn ứng dụng AI Agents cần hiểu rõ môi trường thị trường để xây dựng chiến lược thích nghi phù hợp và giảm thiểu rủi ro phụ thuộc.

1. Các nhà cung cấp chi phối thị trường

Mô tả: Thị trường AI hiện đang bị thống trị bởi một số ít công ty lớn như OpenAI, Google, Microsoft, Anthropic... Họ kiểm soát các mô hình AI nền tảng, hạ tầng tính toán và API, khiến doanh nghiệp nhỏ phụ thuộc và thiếu lựa chọn.

Ví dụ: Một công ty khởi nghiệp muốn xây dựng AI agent nội bộ nhưng buộc phải phụ thuộc vào GPT của OpenAI vì không đủ nguồn lực huấn luyện mô hình riêng. Khi OpenAI tăng giá API hoặc thay đổi chính sách, công ty này không có phương án thay thế.


2. Thỏa thuận độc quyền

Mô tả: Một số công ty công nghệ lớn ký thỏa thuận độc quyền với các nhà cung cấp AI, giới hạn quyền truy cập hoặc tích hợp vào nền tảng của đối thủ, khiến thị trường bị khóa và cản trở đổi mới.

Ví dụ: Microsoft ký thỏa thuận độc quyền tích hợp GPT vào các sản phẩm Microsoft 365. Một đối thủ trong lĩnh vực phần mềm văn phòng không thể tích hợp cùng mức độ hoặc chức năng tương đương, dẫn đến mất lợi thế cạnh tranh.


3. Hệ điều hành và cửa hàng ứng dụng di động

Mô tả: Các nền tảng như iOS (Apple) và Android (Google) kiểm soát chặt chẽ hệ sinh thái ứng dụng, bao gồm quyền truy cập vào phần cứng, dữ liệu người dùng, và cả phân phối ứng dụng. Việc đưa AI agent lên điện thoại gặp rào cản chính sách, giới hạn kỹ thuật hoặc chia sẻ doanh thu.

Ví dụ: Một startup phát triển AI agent tương tác bằng giọng nói cho thiết bị di động, nhưng Apple không cho phép quyền truy cập toàn phần vào micro hoặc Siri. Ngoài ra, ứng dụng phải chia 30% doanh thu cho Apple nếu bán qua App Store.

IV. Quản trị AI Agents

Quản trị(Governance) trong lĩnh vực AI đề cập đến việc xây dựng các cơ chế, chính sách, luật pháp và quy trình nhằm đảm bảo rằng các hệ thống AI – bao gồm cả AI Agents – được phát triển, triển khai và vận hành một cách an toàn, minh bạch, có trách nhiệm và tuân thủ đạo đức.

Khi AI Agents ngày càng trở nên tự chủ và mạnh mẽ, việc quản trị chúng không còn là một lựa chọn, mà là điều bắt buộc để ngăn ngừa rủi ro và bảo vệ lợi ích xã hội, doanh nghiệp và cá nhân.

1. Quy định pháp lý

Mô tả: Các luật lệ và quy định từ chính phủ hoặc cơ quan quốc tế nhằm kiểm soát cách AI được thiết kế, triển khai và sử dụng.

Ví dụ:


2. Tiêu chuẩn kỹ thuật

Mô tả: Các hướng dẫn và tiêu chuẩn chung để thiết kế, phát triển và đánh giá AI một cách nhất quán, minh bạch và có thể kiểm chứng.

Ví dụ:


3. Cơ chế trách nhiệm

Mô tả: Xác định rõ ai chịu trách nhiệm khi AI Agent gây ra sự cố hoặc hành vi sai lệch. Điều này giúp doanh nghiệp không "đổ lỗi cho AI" mà phải gắn trách nhiệm với con người hoặc tổ chức cụ thể.

Ví dụ:
Nếu một AI Agent từ chối đơn bảo hiểm sai do lỗi thuật toán, công ty bảo hiểm cần có bộ phận chịu trách nhiệm xử lý khiếu nại, sửa lỗi hệ thống, và bồi thường nếu cần.


4. Yêu cầu minh bạch

Mô tả: Các AI Agent cần minh bạch trong hoạt động của mình: chúng đưa ra quyết định như thế nào, sử dụng dữ liệu gì, và người dùng có thể hiểu (hoặc kiểm tra) quá trình đó.

Ví dụ:
Một AI Agent gợi ý sản phẩm trên sàn thương mại điện tử cần nêu rõ lý do: "Sản phẩm này được đề xuất vì bạn đã mua các sản phẩm tương tự trong 30 ngày qua".


5. Hợp tác liên ngành

Mô tả: Các tổ chức, doanh nghiệp, cơ quan chính phủ và giới học thuật cần phối hợp cùng nhau để đảm bảo AI phát triển một cách cân bằng, bền vững, và toàn diện.

Ví dụ:

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Yêu cầu pháp lý (Regulatory) trong xây dựng AI Agents:

  1. Đảm bảo thị trường cạnh tranh và thúc đẩy đổi mới sáng tạo
    Tránh độc quyền công nghệ, tạo môi trường để các công ty nhỏ và startup cũng có cơ hội tham gia và sáng tạo AI Agents.

  2. Đảm bảo quyền riêng tư và bảo mật dữ liệu
    AI Agents cần tuân thủ nghiêm ngặt các quy định về bảo vệ dữ liệu cá nhân, tránh thu thập hoặc xử lý dữ liệu nhạy cảm một cách trái phép.

  3. Bảo vệ quyền sở hữu trí tuệ
    Các mô hình AI không được sao chép hoặc tái sử dụng nội dung, phần mềm, hoặc dữ liệu của bên thứ ba mà không có sự cho phép hợp pháp.

  4. Ngăn chặn thông tin sai lệch, đe doạ mạng và lạm dụng AI
    AI Agents không được trở thành công cụ phát tán tin giả, tấn công mạng, hoặc bị sử dụng cho các mục đích độc hại như deepfake hoặc lừa đảo.

  5. Giảm thiểu tác động môi trường và đảm bảo phát triển bền vững
    Khuyến khích phát triển các mô hình AI tiết kiệm năng lượng, tối ưu hóa tính toán và giảm phát thải carbon.

  6. Hạn chế sự thiên lệch (bias)
    Đảm bảo AI Agents không tạo ra hoặc tái tạo định kiến giới, chủng tộc, địa lý, hoặc xã hội trong quá trình xử lý dữ liệu hay ra quyết định.

  7. Đảm bảo tính minh bạch và cơ chế giải trình
    Người dùng và tổ chức phải hiểu được cách AI Agents hoạt động, đưa ra quyết định và có thể kiểm tra, truy xuất nguồn gốc kết quả nếu cần.

  8. Bồi thường thiệt hại do mất việc làm và tác động kinh tế tiêu cực
    Khi AI thay thế công việc truyền thống, cần có chính sách hỗ trợ đào tạo lại lao động, phân phối lại lợi ích một cách công bằng.

  9. Cân bằng giữa đổi mới công nghệ và trách nhiệm xã hội
    Khuyến khích phát triển AI nhanh chóng nhưng không đánh đổi các giá trị đạo đức, quyền con người và lợi ích cộng đồng.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tìm Hiểu Tiềm Năng Thực Sự Của AI AGENTS

Sự hiện hữu của AI Agents

1. Từ bản demo đến sản phẩm thực tế (From Demos to Products)


2. Tăng tốc triển khai (Acceleration)


3. Mở rộng các tình huống ứng dụng (Expansion of use cases)


4. Kết hợp với công nghệ mới nổi (With Emerging Tech)


5. Cuộc cách mạng lực lượng lao động (Workforce Revolution)


6. Đối tác cộng tác thông minh (Collaborative Partners)


7. Đội nhóm lai (Hybrid Teams)


8. Thị trường AI Agent (AI Agent Marketplaces)


9. Khuyến nghị (Recommendations)

Để chuẩn bị cho tương lai này, các tổ chức nên:


10. Sự phát triển công nghệ (Tech Evolution)

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Cách Xây Dựng AI AGENTS Chuyên Nghiệp

Hướng dẫn dành cho các tổ chức, doanh nghiệp và nhà phát triển muốn khai thác tối đa tiềm năng của AI Agents. Bài viết sẽ giúp bạn hiểu rõ các yếu tố cốt lõi trong thiết kế, triển khai và quản trị AI Agents một cách bài bản. Từ chiến lược công nghệ đến yếu tố đạo đức và vận hành, đây là nền tảng để xây dựng các tác nhân AI hiệu quả, an toàn và đáng tin cậy.

Cách Xây Dựng AI AGENTS Chuyên Nghiệp

Xây Dựng AI Agents Chuyên Nghiệp với LangGraph

Trong hành trình này, bạn sẽ được học cách xây dựng các AI Agent hiện đại bằng LangGraph – một công cụ mạnh mẽ đang thay đổi cách chúng ta tạo ra các hệ thống AI tương tác. Khóa học được thiết kế từ cơ bản đến nâng cao, từng bước hướng dẫn bạn vượt qua những khó khăn ban đầu, để rồi làm chủ những mô hình phức tạp, thực tế và hiệu quả.

Cách Xây Dựng AI AGENTS Chuyên Nghiệp

Bài học thực chiến với ví dụ chi tiết

Agent, Assistant và Message

Trong LangChain, các loại Message đóng vai trò rất quan trọng khi làm việc với các mô hình như ChatOpenAI, nhất là khi xây dựng các hệ thống hội thoại (conversational agents). Những message này mô phỏng cách người và AI giao tiếp với nhau trong một cuộc trò chuyện.

Agent, Assistant và Message

Giới thiệu

Trong LangChain, Message là thành phần cốt lõi dùng để mô tả các tương tác giữa người dùng, hệ thống và mô hình ngôn ngữ (LLM). Việc hiểu rõ các loại Message giúp bạn xây dựng các tác vụ hội thoại, agent, và ứng dụng AI một cách chính xác, dễ kiểm soát và có thể mở rộng.

LangChain định nghĩa nhiều loại message khác nhau, mỗi loại phản ánh một vai trò cụ thể trong quá trình giao tiếp. Dưới đây là tổng quan các loại message chính:

1. HumanMessage – Tin nhắn từ người dùng

Đây là loại message đại diện cho đầu vào từ người dùng cuối. Khi bạn nhập văn bản để hỏi AI, LangChain sẽ đóng gói nội dung đó thành một HumanMessage.

from langchain.schema import HumanMessage

message = HumanMessage(content="Bạn có thể giúp tôi tính 5 nhân 3 không?")

Dùng khi mô phỏng hoặc truyền input từ con người.

2. AIMessage – Phản hồi từ AI

Đại diện cho phản hồi từ LLM, thường là kết quả sau khi xử lý HumanMessage. Ngoài văn bản, AIMessage còn có thể bao gồm tool calls, nếu AI quyết định gọi một công cụ thay vì trả lời trực tiếp.

from langchain.schema import AIMessage

message = AIMessage(content="Kết quả là 15.")

Dùng để mô tả output từ AI.

3. SystemMessage – Định hướng AI

Được dùng để thiết lập bối cảnh hoặc hướng dẫn hành vi của AI từ đầu. Những chỉ dẫn như “bạn là một trợ lý thân thiện” hay “chỉ trả lời bằng tiếng Việt” thường được đặt trong SystemMessage.

from langchain.schema import SystemMessage

message = SystemMessage(content="Bạn là một trợ lý AI chuyên nghiệp.")

Dùng để hướng dẫn mô hình trước khi bắt đầu cuộc trò chuyện.

4. ToolMessage – Phản hồi từ công cụ (tool)

Khi một AI gọi tool (hàm toán học, API, công cụ bên ngoài…), kết quả trả về sẽ được biểu diễn qua ToolMessage. Nó mô tả output của tool, và giúp AI tiếp tục hội thoại dựa trên dữ liệu đó.

from langchain.schema import ToolMessage

message = ToolMessage(
    tool_call_id="abc123",
    content="Kết quả của phép chia là 2.5"
)

Dùng khi bạn có workflow với tool calling.

5. ToolCall – Yêu cầu từ AI gọi một tool

Không phải là message, nhưng thường được gói trong AIMessage. Khi AI muốn gọi một hàm cụ thể, nó tạo ra một ToolCall để mô tả tên tool và các tham số truyền vào.

from langchain.schema.messages import ToolCall

call = ToolCall(
    name="multiply",
    args={"a": 5, "b": 3},
    id="tool_call_1"
)

Gắn liền với quá trình sử dụng bind_tools() hoặc khi xây dựng các agent có tool.

Tóm lại

Message Type Vai trò chính Dùng khi nào?
HumanMessage Người dùng gửi yêu cầu Mọi input của người dùng
AIMessage AI phản hồi hoặc gọi tool Output từ AI
SystemMessage Thiết lập bối cảnh và hành vi AI Trước khi bắt đầu cuộc trò chuyện
ToolMessage Phản hồi từ công cụ (tool) Khi một tool được AI gọi và trả về kết quả
ToolCall (Không phải message) – Gọi hàm/tool Khi AI quyết định gọi tool thay vì trả lời

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Agent, Assistant và Message

Assistant và Agent

I. Assistant là gi?

Assistant trong  thường là một hệ thống AI đơn lẻ được thiết kế để thực hiện các nhiệm vụ cụ thể, thường làm việc theo prompt cố định: ví dụ nhận input, trả lời output, không linh hoạt nhiều.

Trong nhiều dự án, bạn thấy "Assistant" = "OpenAI Assistant", tức là chỉ một chatbot đơn giản trả lời tin nhắn.

Dùng Assistant khi:

Kiến trúc Assistant:

Assistant có kiến trúc rất đơn giản,
User Input → [Assistant] → Output

VÍ dụ 

II. Agent là gì

Agent là một khái niệm nâng cao hơn với nhiều khả năng phức tạp:

Agent là một thực thể (entity) có thể:

 Agent thường tự động làm việc, có trí thông minh riêng tùy theo mục đích lập trình cho nó thế nào.

Ví dụ Agent:

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Agent, Assistant và Message

HumanMessage – Tin nhắn từ người dùng

Trong LangChain, HumanMessage là một trong những loại message cơ bản nhất, đại diện cho lời nói, câu hỏi hoặc yêu cầu từ người dùng trong cuộc trò chuyện với mô hình ngôn ngữ (LLM).

Khi bạn gọi mô hình bằng ChatModel như ChatOpenAI, bạn có thể truyền vào một danh sách các message. HumanMessage mô phỏng nội dung do con người nhập vào — tương đương với việc bạn gõ câu hỏi vào ChatGPT.

Cú pháp khai báo

from langchain.schema import HumanMessage

message = HumanMessage(content="Hôm nay thời tiết thế nào?")

Ví dụ đơn giản sử dụng với ChatOpenAI

from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage

# Khởi tạo mô hình
llm = ChatOpenAI()

# Tạo HumanMessage
user_message = HumanMessage(content="Hãy tính giúp tôi 7 + 5 là bao nhiêu?")

# Gửi message đến mô hình và in kết quả
response = llm([user_message])
print(response.content)

Kết quả có thể là:
7 + 5 = 12.

Dùng nhiều messages trong cuộc hội thoại

from langchain.schema import HumanMessage, AIMessage, SystemMessage
from langchain.chat_models import ChatOpenAI

chat = ChatOpenAI()

messages = [
    SystemMessage(content="Bạn là một trợ lý AI thông minh và lịch sự."),
    HumanMessage(content="Bạn tên là gì?"),
    AIMessage(content="Tôi là trợ lý AI được thiết kế để hỗ trợ bạn."),
    HumanMessage(content="Bạn có thể dịch câu 'Hello' sang tiếng Việt không?")
]

response = chat(messages)
print(response.content)

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Agent, Assistant và Message

AIMessage – Tin nhắn phản hồi từ AI

Trong LangChain, AIMessage đại diện cho phản hồi từ mô hình ngôn ngữ (LLM) sau khi nhận một hoặc nhiều HumanMessage.

Bạn có thể nghĩ nó giống như câu trả lời mà ChatGPT gửi lại sau khi bạn hỏi.

LangChain cho phép bạn truyền danh sách các message vào mô hình — trong đó AIMessage giúp mô phỏng những phản hồi trước đó từ AI để giữ ngữ cảnh hội thoại.

Cú pháp khai báo

from langchain.schema import AIMessage

message = AIMessage(content="Tôi có thể giúp gì cho bạn hôm nay?")

Ví dụ sử dụng với ChatOpenAI

from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, AIMessage

chat = ChatOpenAI()

messages = [
    HumanMessage(content="Bạn tên là gì?"),
    AIMessage(content="Tôi là trợ lý ảo của bạn."),
    HumanMessage(content="Bạn có thể giúp tôi dịch từ 'apple' sang tiếng Việt không?")
]

response = chat(messages)
print(response.content)

Kết quả có thể là:
"Từ 'apple' trong tiếng Việt là 'quả táo'."

Sử dụng trong hội thoại nhiều lượt (multi-turn conversation)

from langchain.schema import HumanMessage, AIMessage, SystemMessage

messages = [
    SystemMessage(content="Bạn là trợ lý lịch sự, trả lời bằng tiếng Việt."),
    HumanMessage(content="Xin chào!"),
    AIMessage(content="Chào bạn! Tôi có thể giúp gì hôm nay?"),
    HumanMessage(content="Thời tiết hôm nay như thế nào ở Hà Nội?")
]

Bạn có thể gửi messages này vào ChatOpenAI() để giữ toàn bộ ngữ cảnh từ đầu đến cuối.

AIMessage sử dụng trong những trường hợp

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

Agent, Assistant và Message

SystemMessage - Thiết lập ngữ cảnh

Trong LangChain, SystemMessage là một loại message đặc biệt dùng để thiết lập ngữ cảnh hoặc hướng dẫn hành vi cho mô hình ngôn ngữ (LLM).

Nó giống như "lệnh nền" mà người dùng không thấy, nhưng ảnh hưởng đến cách AI trả lời.

Cú pháp

from langchain.schema import SystemMessage

system_msg = SystemMessage(content="Bạn là một trợ lý AI nói tiếng Việt và luôn lịch sự.")

Mục đích sử dụng

Ví dụ đơn giản

from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage

llm = ChatOpenAI()

messages = [
    SystemMessage(content="Bạn là một trợ lý AI lịch sự và vui tính."),
    HumanMessage(content="Hôm nay bạn khỏe không?")
]

response = llm(messages)
print(response.content)

Kết quả  có thể là

Cảm ơn bạn đã hỏi! Tôi là AI nên không có cảm giác, nhưng nếu có thì chắc chắn hôm nay tôi rất tuyệt vời. Còn bạn thì sao?

Thấy không? AI trở nên "vui tính" và "lịch sự" đúng như chỉ dẫn trong SystemMessage.

Ví dụ hội thoại có nhiều loại message

from langchain.schema import HumanMessage, AIMessage, SystemMessage
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI()

messages = [
    SystemMessage(content="Bạn là một chuyên gia lịch sử Việt Nam, nói ngắn gọn."),
    HumanMessage(content="Ai là vua đầu tiên của triều Nguyễn?"),
]

response = llm(messages)
print(response.content)

Kết quả mẫu:

Vua đầu tiên của triều Nguyễn là Gia Long, lên ngôi năm 1802.

Mẹo chuyên sâu

 

 

 

 

 

Agent, Assistant và Message

ToolMessage - Kết quả phản hồi từ một công cụ (tool)

Trong LangChain, ToolMessage đại diện cho kết quả phản hồi từ một công cụ (tool) sau khi mô hình LLM gọi tool đó.

Nó giống như AI bảo: "Tôi cần dùng máy tính để tính 2 + 2", sau đó bạn gửi lại kết quả "4" bằng ToolMessage.

Khi nào dùng ToolMessage?

Khi bạn dùng bind_tools() để cho phép LLM gọi các hàm (tools), LangChain sẽ:

  1. LLM tạo một ToolCall (ví dụ: gọi hàm multiply(a=2, b=3)).

  2. Bạn thực thi hàm Python tương ứng.

  3. Sau đó, bạn dùng ToolMessage để truyền kết quả trả về của tool đó lại cho LLM.

Cú pháp

from langchain_core.messages import ToolMessage

msg = ToolMessage(tool_call_id="abc123", content="Kết quả là 6")

Các tham số:

Tham số Ý nghĩa
tool_call_id ID của lời gọi hàm (do ToolCallMessage sinh ra)
content Nội dung trả lời (kết quả của tool)
Ví dụ đầy đủ: Gọi hàm nhân trong Python

1. Định nghĩa hàm (tool)

def multiply(a: int, b: int) -> int:
    """Nhân hai số."""
    return a * b

2. Dùng LLM + tool

from langchain_core.messages import HumanMessage, ToolMessage
from langchain_openai import ChatOpenAI

chat = ChatOpenAI().bind_tools([multiply], parallel_tool_calls=False)

3. LLM đưa ra ToolCall

messages = [
    HumanMessage(content="Hãy nhân 4 với 5")
]

response = chat.invoke(messages)
tool_call = response.tool_calls[0]
print(tool_call)  # --> thông tin về lời gọi hàm multiply

4. Gửi kết quả về lại cho LLM bằng ToolMessage

# Gọi hàm thủ công
result = multiply(**tool_call.args)

# Gửi kết quả về lại
followup = chat.invoke([
    response,
    ToolMessage(tool_call_id=tool_call.id, content=str(result))
])

print(followup.content)  # => LLM phản hồi dựa trên kết quả tool

Quan trọng

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

 

 

Agent, Assistant và Message

ToolCall - Mô hình ngôn ngữ gọi đến một công cụ

Trong LangChain, ToolCall đại diện cho việc mô hình ngôn ngữ gọi đến một công cụ (function) để thực hiện một hành động cụ thể.

Nói cách khác, khi bạn dạy AI cách gọi các hàm Python, thì ToolCall là cách mô hình nói: “Tôi muốn dùng hàm add(5, 3) nhé.”

Tại sao cần ToolCall?

Mô hình ngôn ngữ rất giỏi hiểu và tạo ra văn bản, nhưng lại không giỏi tính toán, truy vấn API, hoặc thao tác với dữ liệu phức tạp.
Khi cần làm những việc như vậy, mô hình sẽ gọi một “tool” (được định nghĩa trước bằng Python), thông qua một ToolCall.

Cấu trúc cơ bản của ToolCall

from langchain_core.messages import ToolCall

tool_call = ToolCall(
    name="multiply",
    args={"a": 5, "b": 3},
    id="call_123"
)

Các thành phần:

Ví dụ đầy đủ: Sử dụng ToolCall với LLM

Bước 1: Định nghĩa công cụ

def add(a: int, b: int) -> int:
    return a + b

Bước 2: Bind tool vào LLM

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")
llm_with_tools = llm.bind_tools([add])

Bước 3: Gửi tin nhắn có yêu cầu tính toán

from langchain_core.messages import HumanMessage

messages = [HumanMessage(content="Hãy cộng 4 và 7 giúp tôi")]
response = llm_with_tools.invoke(messages)

print(response.tool_calls)  # Đây chính là danh sách ToolCall

 


Output mẫu:


[
    ToolCall(
        name='add',
        args={'a': 4, 'b': 7},
        id='toolu_abc123'
    )
]

Tức là mô hình quyết định gọi hàm add với a=4, b=7 thông qua ToolCall.

Tương tác hoàn chỉnh: Gọi Tool và trả lại kết quả

from langchain_core.messages import AIMessage, ToolMessage

# Gọi hàm add
tool_result = add(4, 7)

# Trả kết quả lại cho AI thông qua ToolMessage
final_response = llm_with_tools.invoke([
    HumanMessage(content="Hãy cộng 4 và 7"),
    AIMessage(tool_calls=[ToolCall(name="add", args={"a": 4, "b": 7}, id="call_1")]),
    ToolMessage(tool_call_id="call_1", content=str(tool_result))
])

print(final_response.content)

Output

Kết quả là 11!

Tóm tắt so sánh

Thành phần Vai trò
ToolCall Yêu cầu gọi hàm từ mô hình LLM
ToolMessage Trả kết quả từ tool về để LLM tiếp tục xử lý
bind_tools Cho LLM biết có thể gọi những hàm nào

Khi nào cần dùng ToolCall?

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

 

 

 

 

Giới thiệu về LangGraph

Dưới đây là một bài viết giới thiệu về LangGraph, được trình bày theo kiểu bài viết chia sẻ kiến thức công nghệ, phù hợp cho  tài liệu kỹ thuật.

Giới thiệu về LangGraph

Giới thiệu về LangGraph

 LangGraph Tạo LLM Workflow dễ dàng như vẽ đồ thị

Trong thời đại của trí tuệ nhân tạo và mô hình ngôn ngữ lớn (LLM), việc xây dựng các workflow phức tạp để xử lý ngôn ngữ tự nhiên đang trở nên ngày càng quan trọng. Tuy nhiên, quản lý các chuỗi tác vụ, rẽ nhánh logic, và vòng lặp trong quá trình tương tác với LLM có thể nhanh chóng trở nên phức tạp. Đây chính là lý do LangGraph ra đời.

 

LangGraph là gì?

LangGraph là một thư viện mã nguồn mở được phát triển dựa trên LangChain, cho phép bạn xây dựng các đồ thị trạng thái (stateful graphs) cho các ứng dụng sử dụng LLM. Thay vì chỉ chạy một chuỗi cố định các bước, LangGraph cho phép bạn xây dựng các quy trình linh hoạt hơn, bao gồm:

LangGraph mang lại cách tiếp cận kết hợp giữa Lập trình khai báo(declarative) và Lập trình mệnh lệnh(imperative), giúp bạn dễ dàng hình dung và kiểm soát luồng dữ liệu và trạng thái trong quá trình xử lý.

Vì sao nên sử dụng LangGraph?

Dễ hiểu, dễ hình dung

Bạn xây dựng workflow như một đồ thị gồm các nút (nodes), mỗi nút thực hiện một tác vụ cụ thể, như gọi API, xử lý dữ liệu, tương tác với LLM, hay rẽ nhánh theo điều kiện.

Tái sử dụng và mở rộng tốt

Mỗi nút trong LangGraph là một function, nên bạn dễ dàng viết lại, mở rộng hoặc chia sẻ logic giữa các ứng dụng khác nhau.

Tích hợp chặt chẽ với LangChain

LangGraph kế thừa sức mạnh từ LangChain nên bạn có thể dễ dàng kết hợp với các PromptTemplate, Agents, Memory, hay Tools trong hệ sinh thái LangChain.


Cách hoạt động của LangGraph

Cấu trúc cơ bản của một LangGraph bao gồm:

Ví dụ đơn giản về đồ thị gồm 3 node:

from langgraph.graph import StateGraph, END

# Định nghĩa trạng thái
class MyState(TypedDict):
    input: str
    output: str

# Định nghĩa node
def process_input(state):
    result = state["input"].upper()
    return {"output": result}

# Tạo đồ thị
builder = StateGraph(MyState)
builder.add_node("process", process_input)
builder.set_entry_point("process")
builder.set_finish_point("process", END)
graph = builder.compile()

# Chạy đồ thị
result = graph.invoke({"input": "hello"})
print(result)

Ứng dụng thực tế

LangGraph rất phù hợp cho các bài toán phức tạp với LLM như:

 

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Giới thiệu về LangGraph

Vì sao LangGraph ra đời và Graph có ý nghĩa gì

Khi các ứng dụng xây dựng trên mô hình ngôn ngữ lớn (LLM) ngày càng trở nên phức tạp – từ chatbot đơn giản đến hệ thống tự động hóa tác vụ – thì nhu cầu về cách điều phối luồng suy nghĩ, trạng thái, và hành động của LLMs cũng tăng theo.

Đó là lý do vì sao LangGraph ra đời.

LangGraph là một framework kết hợp LLMs với cấu trúc đồ thị trạng thái (stateful graphs), giúp tạo ra các ứng dụng có khả năng:

I. Tại sao lại là LangGraph?

1. Giới hạn của mô hình agent truyền thống (LangChain Agents)

Các agents trong LangChain rất linh hoạt, nhưng đôi khi:

Kết quả là khi xây dựng các ứng dụng phức tạp như AutoGPT, trợ lý đa tác vụ, hệ thống hỏi đáp nhiều bước... developer phải viết rất nhiều code xử lý luồng hoặc hack workaround.

2. LangGraph: Giải pháp điều phối LLM theo kiểu đồ thị trạng thái

LangGraph đưa ra một kiến trúc mới, nơi quá trình suy nghĩ và hành động của LLM được mô hình hóa như một đồ thị (graph).

Mỗi node trong đồ thị:

 Lợi ích chính:

Tính năng Ý nghĩa
Có trạng thái Lưu giữ thông tin giữa các bước
Có vòng lặp Hỗ trợ dễ dàng quá trình phản xạ (reflection), retry, sửa lỗi
Modular Mỗi node độc lập, dễ tái sử dụng
Dễ debug Có thể quan sát từng node và hướng đi trong quá trình xử lý
Tùy chọn luồng Có thể dùng LLM để quyết định đi hướng nào trong graph

 

II. Tại sao lại dùng từ “Graph”?

1. Graph = Đồ thị trạng thái có hướng

LangGraph sử dụng  lý thuyết đồ thị (directed graph) như một cách để mô hình hóa quy trình tư duy của một agent.

 Trong graph:

Graph này giống như flowchart thông minh, nhưng được điều khiển bởi LLM.

2. Graph giúp dễ hình dung quy trình phức tạp

Dưới dạng graph, developer có thể:

Ví dụ:

[User Input]
    ↓
[LLM hiểu yêu cầu]
    ↓
[Chọn hành động] ──→ [Dùng công cụ] ──→ [Tóm tắt kết quả]
    ↑                                  ↓
 [Thiếu dữ liệu?] ←──────[Kiểm tra đủ chưa?]

III. Khi nào nên dùng LangGraph?

LangGraph cực kỳ phù hợp khi bạn xây dựng:

Multi-step reasoning (suy luận nhiều bước)
Agents có khả năng reflection / retry / repair
Workflow có trạng thái (stateful flows)
Hệ thống cần kiểm soát logic chặt chẽ
Quy trình có loop, branching hoặc fallback logic

Ví dụ ứng dụng:

❓ Câu hỏi ✅ Trả lời
Vì sao LangGraph? Vì các ứng dụng LLM ngày càng phức tạp, cần khả năng điều phối, giữ trạng thái, và xử lý logic phức tạp.
Vì sao "Graph"? Vì LangGraph mô hình hóa tư duy của agent dưới dạng đồ thị trạng thái có hướng — giúp kiểm soát, mở rộng, debug dễ dàng hơn.
Giới thiệu về LangGraph

Lập trình khai báo(declarative) và Lập trình mệnh lệnh(imperative)

Lập trình khai báo(declarative) và Lập trình mệnh lệnh(imperative) là hai phong cách lập trình khác nhau — chúng phản ánh cách bạn mô tả công việc mà máy tính cần thực hiện

I. Lập trình khai báo(declarative) 

# Declarative (giống kiểu functional programming)
result = [x * 2 for x in data if x > 10]

Hoặc ví dụ quen thuộc hơn:

SELECT * FROM users WHERE age > 18;

Bạn không nói “lặp qua từng dòng, kiểm tra tuổi”, mà chỉ nói “hãy lấy dữ liệu theo điều kiện”.

II. Lập trình mệnh lệnh(imperative)

III. Trong LangGraph thì sao?

LangGraph kết hợp cả hai phong cách:

 Ví dụ:

builder.add_node("process", process_input)  # declarative
def process_input(state):                   # imperative
    return {"output": state["input"].upper()}

Tóm lại:

LangGraph giúp bạn tận dụng sức mạnh kết hợp: vừa dễ hình dung (declarative), vừa dễ điều khiển (imperative).

Phong cách Bạn mô tả... Ưu điểm Nhược điểm
Imperative CÁCH máy tính phải làm Kiểm soát chi tiết Dễ rối với quy trình phức tạp
Declarative CÁI GÌ bạn muốn đạt được Gọn, dễ hiểu Khó kiểm soát từng bước nhỏ

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Giới thiệu về LangGraph

So sánh LangGraph và LangChain

image.png

Với sự phát triển nhanh chóng của các mô hình ngôn ngữ lớn như GPT, Claude, Mistral..., các thư viện như LangChainLangGraph ra đời để giúp lập trình viên dễ dàng xây dựng ứng dụng sử dụng LLM. Nhưng giữa hai cái tên quen thuộc này, bạn nên chọn cái nào? Hoặc khi nào nên dùng cả hai?

Bài viết này sẽ giúp bạn hiểu rõ sự khác biệt, điểm mạnh, và cách sử dụng của LangChainLangGraph.

I. Tổng quan

Đặc điểm LangChain LangGraph
Mục tiêu Tạo pipeline (chuỗi) LLM logic Tạo workflow (đồ thị trạng thái) phức tạp
Cấu trúc Tuyến tính (linear chain / agent) Đồ thị trạng thái có vòng lặp, rẽ nhánh
Mô hình dữ liệu Stateless (không lưu trạng thái) Stateful (quản lý trạng thái qua nhiều bước)
Tích hợp LLM Rất mạnh, nhiều tools tích hợp Kế thừa từ LangChain
Độ linh hoạt Cao với chuỗi đơn giản hoặc agents Rất cao với workflow phức tạp
Sử dụng chính Chatbot, Q&A, Retrieval, Agents Bot đa bước, phân nhánh logic, memory flows

II. Kiến trúc hoạt động

LangChain

LangChain cung cấp một tập hợp các abstractions như:

Mỗi chain là tuyến tính — dữ liệu đi từ đầu đến cuối qua từng bước.

Ưu điểm: Dễ dùng, dễ hiểu, setup nhanh.
Nhược điểm: Hạn chế khi bạn muốn rẽ nhánh, lặp lại, hoặc xử lý logic phức tạp.

LangGraph

LangGraph đưa kiến trúc lên tầm cao hơn: bạn không chỉ nối các bước, bạn vẽ ra một đồ thị trạng thái. Trong đó:

LangGraph kế thừa toàn bộ các công cụ từ LangChain như LLMChain, PromptTemplate, Tool, Memory, Agent,… nhưng nâng cấp khả năng tổ chức luồng xử lý lên mức workflow engine.

Ưu điểm: Xử lý logic phức tạp, hỗ trợ đa chiều, có vòng lặp.
Nhược điểm: Khó hơn để bắt đầu, yêu cầu hiểu về state và luồng.

III. Khi nào dùng LangChain?

Dùng LangChain khi bạn:

Ví dụ: Lấy nội dung từ một file, tóm tắt nó bằng GPT, rồi gửi email.

IV. Khi nào dùng LangGraph?

Dùng LangGraph khi bạn:

Ví dụ:
Hệ thống kiểm tra đơn hàng:

  1. Người dùng gửi mã đơn →

  2. Hệ thống kiểm tra trạng thái đơn →

  3. Nếu đơn đang giao: gửi thông báo;

  4. Nếu đơn bị huỷ: hỏi lý do → ghi log → gửi xác nhận.

Bạn khó làm điều này gọn gàng với LangChain, nhưng LangGraph làm rất tốt.

V. Có thể dùng kết hợp không?

Hoàn toàn có thể!
LangGraph thực tế được xây dựng trên nền LangChain, nên bạn có thể dùng LLMChain, RetrievalChain, Agents, PromptTemplate bên trong các node của LangGraph.

Ví dụ: Một node trong đồ thị LangGraph có thể gọi một LangChain Agent để xử lý một phần công việc.

VI. So sánh ngắn gọn qua ví dụ

 LangChain (linear):

chain = SimpleSequentialChain(chains=[chain1, chain2])
result = chain.run("Hello world")

LangGraph (graph):

builder = StateGraph()
builder.add_node("step1", step1)
builder.add_node("step2", step2)
builder.add_edge("step1", "step2")
builder.set_entry_point("step1")
graph = builder.compile()
graph.invoke({"input": "Hello world"})

VII. Kết luận

Nếu bạn cần... Hãy chọn...
Xây dựng nhanh một chuỗi xử lý 🟢 LangChain
Quản lý nhiều trạng thái phức tạp 🟢 LangGraph
Làm chatbot đơn giản 🟢 LangChain
Làm agent với hành vi linh hoạt 🟢 LangGraph
Kết hợp các công cụ và logic rẽ nhánh 🟢 LangGraph

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Giới thiệu về LangGraph

Tác nhân điều phối(Agentic) trong ứng dụng mô hình ngôn ngữ lớn (LLMs)

Với sự phát triển mạnh mẽ của các mô hình ngôn ngữ lớn (LLMs), chúng ta có thể xây dựng nhiều loại ứng dụng khác nhau. Trong đó, hai hướng tiếp cận nổi bật là:

Vậy đâu là sự khác biệt, điểm mạnh – điểm yếu, và bạn nên chọn loại nào cho dự án của mình?

I. Định nghĩa

1. Non-Agentic LLM App là gì?

Đây là các ứng dụng chạy theo logic tuyến tính, được xác định rõ ràng. Mỗi bước được lập trình cụ thể, LLM chỉ làm từng nhiệm vụ một cách tường minh.

 Đặc điểm:

Ví dụ:

summary = llm("Tóm tắt đoạn văn sau...")

2. Agentic LLM App là gì?

Là ứng dụng mà trong đó LLM hoạt động như một "agent" (tác nhân) — có khả năng:

Đặc điểm:

Ví dụ:

II. So sánh chi tiết

Đặc điểm Non-Agentic Agentic
Mục tiêu Xử lý 1 nhiệm vụ đơn giản hoặc theo kịch bản Tự động hóa nhiều bước, xử lý tác vụ mở
Luồng xử lý Tuyến tính, xác định trước Rẽ nhánh, điều kiện, có thể điều phối vòng lặp
Khả năng lập kế hoạch ❌ Không Có (có thể lên kế hoạch và thực thi từng bước)
Khả năng chọn công cụ phù hợp ❌ Không Có thể chọn tool/action phù hợp theo ngữ cảnh
Tính linh hoạt Trung bình – cao Rất cao
Dễ debug, kiểm soát  Rất dễ ❌ Phức tạp hơn do có hành vi tự động
Hiệu suất Nhanh hơn, ít token hơn Chậm hơn, tốn token hơn do phải lập kế hoạch
Khả năng sử dụng thực tế Rất tốt với quy trình ổn định Tốt với quy trình phức tạp hoặc cần tự thích nghi

3. Minh họa đơn giản

Tác vụ: “Hãy tìm thông tin về Elon Musk và tóm tắt”

Non-Agentic:

Agentic:

4. Công nghệ hỗ trợ

Tính năng Non-Agentic Agentic
Thư viện phổ biến LangChain, Transformers LangChain Agents, LangGraph, AutoGPT
Công cụ gọi ngoài (Tools) Có, nhưng gọi tường minh LLM tự chọn công cụ thông minh
Bộ nhớ (Memory) Đơn giản hoặc không có Quan trọng để theo dõi trạng thái
Loop / Retry logic Phải lập trình thủ công Agent có thể tự thực hiện

5. Khi nào nên dùng loại nào?

Trường hợp Nên chọn
Xử lý một bước (dịch, tóm tắt, phân loại) ✅ Non-Agentic
Luồng cố định, logic rõ ràng ✅ Non-Agentic
Tác vụ phức tạp, cần suy luận nhiều bước ✅ Agentic
Cần tương tác nhiều hệ thống / API / Tool ✅ Agentic
Trợ lý AI hoặc hệ thống hỗ trợ quyết định ✅ Agentic
Ưu tiên tốc độ, đơn giản, tiết kiệm tài nguyên ✅ Non-Agentic

6. Tổng kết

Tiêu chí Non-Agentic App Agentic App
Đơn giản ❌ (phức tạp hơn)
Linh hoạt
Tự chủ
Dễ kiểm soát
Tác vụ phức tạp
Sử dụng tool ngoài Có nhưng hạn chế Mạnh mẽ, linh hoạt

Không có lựa chọn "tốt hơn tuyệt đối" — bạn cần chọn dựa trên mức độ phức tạp của bài toán, khả năng chấp nhận rủi ro, và yêu cầu logic xử lý.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Giới thiệu về LangGraph

Cấp độ hành vi của tác nhân(Agentic) trong ứng dụng LLM

image.png

LLMs như GPT, Claude, hay Gemini, ngày càng nhiều ứng dụng được xây dựng theo kiến trúc agentic – tức là cho phép mô hình "suy nghĩ", lập kế hoạch, và tự ra quyết định. Nhưng không phải ứng dụng nào cũng cần mức độ agentic giống nhau.

Vì vậy, khái niệm Cấp độ hành vi của tác nhân(Degrees of Agentic Behavior) ra đời – mô tả các cấp độ từ đơn giản đến phức tạp mà một hệ thống có thể thể hiện hành vi như một tác nhân (agent).

Agentic Behavior là gì?

"Agentic behavior" đề cập đến khả năng hành động một cách có mục đích của mô hình – không chỉ trả lời từng lệnh một, mà còn:

Ví dụ, thay vì chỉ trả lời “không biết”, một agentic app có thể:

“Tôi không có thông tin trong cơ sở dữ liệu. Tôi sẽ tìm kiếm trên web, tóm tắt, rồi trình bày kết quả.”

5 Cấp độ Hành vi Agentic (Degrees of Agentic Behavior)

Chúng ta có thể chia hành vi agentic thành năm cấp độ, từ đơn giản (non-agentic) đến phức tạp (autonomous agents):


Level 0 – Không có hành vi tác nhân(Non-Agentic)

🔹 Chỉ thực hiện một hành động theo prompt đã lập trình sẵn.
🔹 Không có logic điều phối, không lập kế hoạch.

Ví dụ:

response = llm("Hãy tóm tắt đoạn văn sau...")

Dùng cho:

Level 1 – Tăng cường bằng công cụ - Sử dụng công cụ một bước(Tool-Enhanced - Single-step Tool Use)

🔹 Ứng dụng có thể sử dụng một công cụ bên ngoài, nhưng người lập trình phải chỉ định rõ khi nào dùng tool nào.

Ví dụ:

if "search" in user_input:
    result = web_search_tool(query)
else:
    result = llm(user_input)

Dùng cho:


Level 2 – Các tác nhân phản ứng - Sử dụng công cụ động(Reactive Agents - Dynamic Tool Use)

🔹 LLM tự quyết định khi nào cần dùng công cụ nào
🔹 Các công cụ (tools) được mô tả bằng prompt hoặc API
🔹 LLM chọn hành động tốt nhất dựa trên ngữ cảnh hiện tại

Ví dụ: LLM tự chọn Calculator để tính toán thay vì chỉ đoán kết quả.

Dùng LangChain Agents, OpenAI Function Calling, hoặc LangGraph Nodes.

Dùng cho:


Level 3 – Các tác nhân tự phản hồi hoặc thực hiện vòng lặp (Reflective / Iterative)

🔹 Agent có khả năng tự phản hồi (self-reflect) và thực hiện vòng lặp xử lý đến khi đạt được mục tiêu
🔹 Có thể lập kế hoạch, thực hiện hành động, kiểm tra lại, và sửa lỗi

Ví dụ:

if "search" in user_input:
    result = web_search_tool(query)
else:
    result = llm(user_input)

Dùng Looping Graphs trong LangGraph hoặc Agent Executors có khả năng hồi quy.

Dùng cho:


Level 4 – Các tác nhân tự chủ đa mục tiêu (Autonomous Multi-goal Agents)

🔹 Agent có khả năng:

Ví dụ: AutoGPT, BabyAGI, OpenDevin

Có thể chạy nhiều vòng lặp, tự lưu trạng thái và chuyển hướng kế hoạch khi có lỗi.

Dùng cho:

So sánh nhanh

Cấp độ Tên gọi Mức độ tự chủ Có lập kế hoạch Có hành vi phản xạ Dùng cho tác vụ phức tạp
0

Không có hành vi tác nhân

(Non-agentic)
1

Tăng cường bằng công cụ

(Tool-enhanced)
2

Các tác nhân phản ứng

(Reactive agents)
✅ (mức vừa)
3

Các tác nhân tự phản hồi hoặc thực hiện vòng lặp

(Reflective/Iterative agents)
✅✅ ✅✅
4

Các tác nhân tự chủ đa mục tiêu

(Autonomous agents)
✅✅✅ ✅✅ ✅✅ ✅✅✅

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Giới thiệu về LangGraph

LangGraph Studio, giới thiệu, cài đặt và cách dùng

Giới thiệu LangGraph Studio – Trình quan sát & phát triển Agentic Graphs

I. LangGraph Studio là gì?

LangGraph Studio là một công cụ giao diện đồ họa (GUI) giúp bạn:

Nó giống như một "developer console" dành riêng cho LangGraph, giúp bạn hiểu và kiểm soát quá trình suy luận và hành động của mô hình AI một cách rõ ràng, trực quan.

II. Tại sao nên dùng LangGraph Studio?

Vấn đề khi không có Studio LangGraph Studio giúp
❌ Debug khó vì agent ẩn trong LLM Hiển thị chi tiết từng bước, trạng thái
❌ Khó hiểu LLM đang đi hướng nào Hiển thị flow trực quan
❌ Phát triển agent lặp đi lặp lại Test từng phần trực tiếp
❌ Không biết LLM nghĩ gì Hiển thị prompt, output, action, tool dùng

III. Cài đặt LangGraph Studio

LangGraph Studio được tích hợp sẵn trong thư viện langgraph. Để cài đặt và sử dụng, bạn chỉ cần:

1. Cài đặt thư viện:

pip install langgraph[dev]

Hoặc nếu bạn đã có langgraph:

pip install -U "langgraph[dev]"

dev extras sẽ cài thêm các gói phục vụ cho Studio như fastapi, uvicorn, jupyter, v.v.

IV. Cách dùng LangGraph Studio

LangGraph Studio hiện hỗ trợ hai cách chính để sử dụng:


1. Chạy dưới dạng local app (FastAPI server)

Bạn có thể thêm dòng sau vào project của bạn để chạy Studio như một app mini:

from langgraph.studio import start_trace_server

start_trace_server()

Mặc định server chạy tại http://localhost:4000

Khi bạn chạy graph của mình, Studio sẽ tự động ghi lại luồng xử lý, trạng thái, inputs/outputs, và hiển thị trên giao diện web.

2 . Tích hợp trong Jupyter Notebook

Nếu bạn đang làm việc trong Jupyter (hoặc Google Colab), bạn có thể dùng:

from langgraph.studio.jupyter import trace_graph

with trace_graph(graph) as session:
    result = session.invoke(input_data)

Tính năng này giúp bạn:

from langgraph.graph import StateGraph
from langgraph.studio import start_trace_server

# Define some simple node functions
def say_hello(state):
    print("Hello!")
    return state

def ask_name(state):
    state["name"] = "Alice"
    return state

# Build graph
builder = StateGraph(dict)
builder.add_node("hello", say_hello)
builder.add_node("ask", ask_name)
builder.set_entry_point("hello")
builder.add_edge("hello", "ask")

graph = builder.compile()

# Start studio server
start_trace_server()

# Run
graph.invoke({})

Khi chạy đoạn code này, bạn có thể truy cập http://localhost:4000 để thấy luồng hello → ask cùng với trạng thái và log chi tiết.

VI. Các tính năng nổi bật

Tính năng Mô tả
Flow Graph View Hiển thị đồ thị agent và luồng thực tế đã đi qua
Prompt Viewer Hiển thị đầy đủ prompt mà LLM nhận được
Input/Output Log Xem tất cả input và output của từng bước
Multi-run Comparison So sánh nhiều phiên bản chạy graph khác nhau
Token usage & Cost (tương lai) Theo dõi chi phí sử dụng OpenAI, Anthropic,...
 Node debug Hiển thị error và traceback nếu có lỗi ở một node

VII. Khi nào nên dùng LangGraph Studio?

VIII. Tổng kết

Câu hỏi Trả lời
LangGraph Studio là gì? Là công cụ GUI để quan sát và phát triển LangGraph Agents một cách trực quan và có thể debug.
Làm gì được với nó? Theo dõi prompt, response, trạng thái, tool call... từng bước trong graph
Cài đặt ra sao? pip install langgraph[dev]
Chạy ở đâu? Trong local (FastAPI) hoặc trong Jupyter Notebook

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Tài liệu này sẽ hướng dẫn bạn cách cài đặt dự án và hiểu rõ các thành phần cốt lõi trong một đồ thị (graph).
Từ đó, bạn có thể dễ dàng tùy chỉnh, mở rộng hoặc tích hợp thêm các công cụ để phù hợp với nhu cầu thực tế.
Biên soạn bởi:
Đỗ Ngọc Tú
CEO VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

LangGraph: Framework Xây Dựng Ứng Dụng LLM Dựa Trên Agent + Graph

LangGraph là một framework mã nguồn mở được xây dựng trên nền tảng của LangChain, cho phép bạn phát triển các ứng dụng sử dụng LLM (Large Language Models) theo mô hình agentic – nơi AI không chỉ trả lời câu hỏi, mà còn suy luận, quyết định, gọi tool, và ghi nhớ trạng thái trong nhiều bước.

Điểm đặc biệt của LangGraph là nó tổ chức toàn bộ logic ứng dụng dưới dạng một đồ thị trạng thái (stateful graph) – mỗi "node" là một hành động, một agent, hoặc một bước xử lý.

Tại sao cần LangGraph?

Các ứng dụng AI ngày nay không chỉ dừng ở hỏi-đáp đơn lẻ. Chúng cần:

LangGraph giúp bạn làm tất cả điều đó một cách có cấu trúc, dễ theo dõi và mở rộng.

LangGraph hoạt động như thế nào?

LangGraph xây dựng ứng dụng theo mô hình Finite-State Machine (FSM):

Bạn có thể tạo các ứng dụng như:

Cú pháp cơ bản

from langgraph.graph import StateGraph

def greet(state): print("Hello!"); return state
def ask_name(state): state["name"] = "Alice"; return state

builder = StateGraph(dict)
builder.add_node("greet", greet)
builder.add_node("ask", ask_name)
builder.set_entry_point("greet")
builder.add_edge("greet", "ask")

graph = builder.compile()
graph.invoke({})

Tạo ứng dụng cơ bản LangGraph AI Agents.

5 Khái Niệm Trụ Cột

LangGraph là một framework mạnh mẽ để xây dựng các ứng dụng LLM có logic phức tạp theo mô hình graph-based agent. Để làm chủ LangGraph, bạn cần hiểu rõ 5 thành phần chính: State, Schema, Node, Edge, và Compile.

1.  State = Memory (Trạng thái là bộ nhớ)

Trong LangGraph, State là nơi lưu trữ toàn bộ thông tin mà ứng dụng của bạn cần ghi nhớ trong suốt quá trình chạy.

Ví dụ:

{"question": "Chủ tịch nước Việt Nam là ai?", "llm_response": "..." }

State giống như RAM của agent – càng tổ chức tốt, agent càng thông minh và hiệu quả.

2. Schema = Data Format (Định dạng dữ liệu)

LangGraph yêu cầu bạn định nghĩa Schema cho State để đảm bảo dữ liệu được quản lý nhất quán, an toàn và rõ ràng.

Ví dụ:

from typing import TypedDict

class MyState(TypedDict):
    question: str
    answer: str

Schema = bản thiết kế dữ liệu, giúp bạn tránh lỗi, dễ debug và mở rộng.

3. Node = Step (Một bước xử lý)

Node là một bước trong đồ thị – nơi một phần công việc được thực hiện.

Ví dụ node đơn giản:

def call_llm(state):
    response = llm.invoke(state["question"])
    state["answer"] = response
    return state

4.  Edge = Kết nối giữa các bước(Operation Between Steps)

Edge là mối liên kết giữa các node – giúp bạn định nghĩa luồng đi của chương trình.

Ví dụ:

graph.add_edge("ask_user", "call_llm")
graph.add_conditional_edges("call_llm", {
    "need_more_info": "search_tool",
    "done": END
})

Edge quyết định luồng suy nghĩlogic quyết định của agent.

5. Compile = Đóng gói đồ thị để sử dụng(Pack)

Sau khi bạn đã định nghĩa đầy đủ các node, edge và schema, bước cuối cùng là compile – để tạo ra một graph sẵn sàng chạy.

Ví dụ:

builder = StateGraph(MyState)
# add node, edge...
graph = builder.compile()
graph.invoke({"question": "..."})

Compile = chuyển bản thiết kế sang sản phẩm hoàn chỉnh có thể vận hành.

Tóm lại

Thành phần Vai trò Ví dụ dễ hiểu
State Bộ nhớ dùng để truyền dữ liệu giữa các bước “Tôi nhớ câu hỏi người dùng”
Schema Định nghĩa cấu trúc và loại dữ liệu trong state “State phải có ‘question’ dạng chuỗi”
Node Một bước xử lý như LLM call, tool call, v.v. “Gọi GPT để trả lời”
Edge Điều khiển luồng di chuyển giữa các node “Nếu xong thì kết thúc, nếu thiếu thì tìm tiếp”
Compile Đóng gói toàn bộ graph để vận hành “Biến các bước rời rạc thành một chương trình”

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Giới thiệu Poetry

Poetry – một công cụ hiện đại để quản lý gói (package) và môi trường (environment) trong Python.

Poetry là gì?

Poetry là một công cụ giúp bạn:

Poetry thay thế việc bạn phải dùng pip, venv, requirements.txt, setup.py, pyproject.toml,... riêng lẻ — tất cả tích hợp trong một công cụ.

Tại sao nên dùng Poetry?

Truyền thống (pip + venv + requirements) Poetry
Quản lý môi trường và dependency riêng Tất cả-in-one
Cần nhiều file config khác nhau Dùng duy nhất pyproject.toml
Khó pin version chính xác Poetry lock chính xác
Không tự động tạo môi trường Poetry tự tạo virtualenv
Không có tính năng publish Poetry có lệnh poetry publish

Khi nào nên dùng Poetry?

Cài đặt Poetry

curl -sSL https://install.python-poetry.org | python3 -
Sau đó thêm vào shell config nếu cần:
export PATH="$HOME/.local/bin:$PATH"

poetry --version

Khởi tạo project với Poetry

poetry new myproject
cd myproject

Cấu trúc thư mục sẽ được tạo sẵn:

myproject/
├── myproject/
│   └── __init__.py
├── tests/
├── pyproject.toml
└── README.rst

Thêm dependency

poetry add requests

Poetry sẽ:

Muốn thêm dev-dependency?

poetry add --dev black

Tạo môi trường và chạy shell

poetry shell

Giống như source venv/bin/activate — bạn sẽ vào môi trường ảo của Poetry.

Hoặc chạy lệnh trong môi trường mà không cần shell:

poetry run python script.py

pyproject.toml là gì?

Đây là file cấu hình trung tâm của project Python hiện đại.
Poetry dùng file này để:

Ví dụ:

[tool.poetry]
name = "VHTSoft"
version = "0.1.0"
description = "Dự án tuyệt vời"
authors = ["Bạn <admin@vhtsoft.com>"]

[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.31.0"

[tool.poetry.dev-dependencies]
black = "^23.0.0"

Build và Publish

poetry build
poetry publish --username __token__ --password pypi-***

Bạn có thể đăng lên PyPI nếu muốn chia sẻ package.

Lệnh phổ biến

Lệnh Chức năng
poetry new myproject Tạo mới một project
poetry init Tạo pyproject.toml trong thư mục hiện tại
poetry add <package> Thêm dependency
poetry install Cài dependencies từ pyproject.toml
poetry update Cập nhật toàn bộ thư viện
poetry lock Tạo/cập nhật poetry.lock
poetry run <cmd> Chạy lệnh trong môi trường ảo
poetry shell Mở môi trường ảo
poetry build Đóng gói project
poetry publish Đăng lên PyPI

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Cơ bản về GraphBuilder

Trong LangGraph, bạn sẽ sử dụng một GraphBuilder để định nghĩa các bước (nodes), luồng xử lý (edges), điều kiện phân nhánh (routers), và điểm bắt đầu/kết thúc của một ứng dụng dựa trên LLM.

from langgraph.graph import StateGraph

builder = StateGraph(StateType)

Ở đây StateType là schema mô tả state (thường là TypedDict hoặc pydantic model).

Ví dụ

from typing import TypedDict, Literal

class DrinkState(TypedDict):
    preference: Literal["coffee", "tea", "unknown"]

1. builder.add_node(name, node_callable)

Thêm một bước xử lý (node) vào graph.

Cú pháp:

builder.add_node("tên_node", hàm_xử_lý)

Ví dụ

def ask_name(state):
    state["name"] = input("Tên bạn là gì? ")
    return state

builder.add_node("ask_name", ask_name)
2. builder.add_edge(from_node, to_node)

Tạo liên kết (đường đi) giữa hai node.

Cú pháp:

builder.add_edge("node_nguồn", "node_đích")

Ví dụ:

builder.add_edge("ask_name", "ask_preference")

3. builder.add_conditional_edges(from_router_node, conditions_dict)

from_router_node: là một hàm xử lý

Tạo đường đi có điều kiện (routing) từ một node tới nhiều node tùy thuộc vào kết quả của node đó.

Cú pháp:

builder.add_conditional_edges("router_node", {
    "kết_quả_1": "node_1",
    "kết_quả_2": "node_2",
    ...
})

Ví dụ:

builder.add_conditional_edges("router", {
    "coffee_node": "coffee_node",
    "tea_node": "tea_node",
    "fallback_node": "fallback_node"
})

=> Node "router" sẽ trả về một chuỗi (ví dụ "coffee_node"), và flow sẽ đi đến node tương ứng.

4. builder.set_entry_point(node_name)

Xác định điểm bắt đầu của graph.

Ví dụ

builder.set_entry_point("start")
5. builder.set_finish_point(node_name)

Đánh dấu node kết thúc, tức là sau node này thì flow dừng lại.

Có thể có nhiều node kết thúc!

Ví dụ

builder.set_finish_point("coffee_node")
builder.set_finish_point("tea_node")
6. builder.compile()

Biên dịch graph của bạn thành một CompiledGraph có thể chạy được.

Ví dụ

app = builder.compile()

Sau đó

app.invoke({"preference": "unknown"}
7. Tổng kết
Hàm Mô tả
add_node(name, node_fn) Thêm một bước xử lý đơn vào graph
add_edge(from_node, to_node) Tạo liên kết tuyến tính giữa 2 node
add_conditional_edges(name, mapping) Tạo node phân nhánh có điều kiện
set_entry_point(name) Xác định điểm bắt đầu của flow
set_finish_point(name) Xác định điểm kết thúc
add_branch(name, sub_graph) Thêm một graph phụ (dạng phân nhánh) vào một node
add_recursion(name, recursive_graph) Cho phép gọi đệ quy một graph con
compile() Biên dịch toàn bộ graph thành một ứng dụng chạy được
add_generator_node(name, generator_node) Thêm một node sử dụng generator (yield từng bước)
add_parallel_nodes(nodes: dict) Chạy nhiều node song song trong một bước
add_conditional_edges_with_default(name, conditions, default) Giống add_conditional_edges nhưng có nhánh mặc định
add_stateful_node(name, node_fn) Dùng khi node cần giữ trạng thái riêng biệt
add_async_node(name, async_node) Thêm node xử lý bất đồng bộ (async def)

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Xây dựng một ứng dụng đơn giản (graph) quyết định xem người dùng nên uống cà phê hay trà

Mục tiêu của bài tập này là làm quen với các thành phần và bước chính của ứng dụng LangGraph cơ bản. StateSchemaNodeEdge, và Compile.

I. Cài đặt

Đây là hình ảnh đồ họa của ứng dụng chúng ta sẽ xây dựng

image.png

2. Xác định lược đồ trạng thái(state schema)

Đối với ví dụ này, lớp State sẽ chỉ có một khóa, graph_state, với định dạng chuỗi

from typing_extensions import TypedDict

class State(TypedDict):
    graph_state: str

TypedDict là gì?
- TypedDict cho phép bạn định nghĩa các từ điển có cấu trúc cụ thể. Nó cho phép bạn chỉ định các khóa chính xác và các loại giá trị liên quan của chúng, giúp mã của bạn rõ ràng hơn và an toàn hơn về mặt kiểu.

Ví dụ, thay vì một từ điển đơn giản như

{"name": "Ngoc Tu", "age": 40}

bạn có thể định nghĩa một TypedDict để thực thi rằng tên phải luôn là một chuỗi và tuổi phải luôn là một số nguyên.

Ở đây, một cấu trúc giống như từ điển mới có tên là State được định nghĩa.
State kế thừa từ TypedDict, nghĩa là nó hoạt động giống như một từ điển, nhưng có các quy tắc cụ thể về các khóa và giá trị mà nó phải có.

state: State = {"graph_state": "active"}  # Đúng
state: State = {"graph_state": 123}  # Sai, Điều này sẽ gây ra lỗi kiểm tra kiểu vì giá trị 123 không phải là chuỗi.

3. Xác định các Nodes của ứng dụng

Các Nodes của ứng dụng này được định nghĩa là các hàm python.
Đối số đầu tiên của hàm Node là state. Mỗi Node có thể truy cập khóa graph_state, với state['graph_state'].
Trong bài tập này, mỗi Node sẽ trả về một giá trị mới của khóa trạng thái graph_state. Giá trị mới do mỗi Node trả về sẽ ghi đè lên giá trị state trước đó.
Nếu luồng đồ thị là Node 1 đến Node 2, trạng thái cuối cùng sẽ là "Chọn Trà".
Nếu luồng đồ thị là nút 1 đến nút 3, trạng thái cuối cùng sẽ là "Chọn Coffee".

def node_1(state):
    print("---Node 1---")
    return {"graph_state": state['graph_state'] +" Tôi sẽ quyết định"}

def node_2(state):
    print("---Node 2---")
    return {"graph_state": state['graph_state'] +" Chọn Trà"}

def node_3(state):
    print("---Node 3---")
    return {"graph_state": state['graph_state'] +" Chọn Coffee"}

4. Xác định các Edges(cạnh) kết nối các Node

Cạnh thông thường đi từ Node này sang Node khác.

4.1 Edge không điều kiện giữa các node
builder = GraphBuilder()

# Thêm các node
builder.add_node("node_1", node_1)
builder.add_node("node_2", node_2)
builder.add_node("node_3", node_3)

# Tạo edge không điều kiện
builder.add_edge("node_1", "node_2")  # Sau node_1 thì luôn đi đến node_2
builder.add_edge("node_2", "node_3")  # Sau node_2 thì luôn đi đến node_3

# Đặt node bắt đầu
builder.set_entry_point("node_1")

# Tạo app và chạy thử
app = builder.compile()

initial_state = {"graph_state": ""}
final_state = app.invoke(initial_state)
print("Kết quả:", final_state["graph_state"])
---Node 1---
---Node 2---
---Node 3---
Kết quả: Tôi sẽ quyết định. Chọn Trà. Chọn Coffee.
4.2 Edge Có điều kiện giữa các node

Cạnh có điều kiện được sử dụng khi bạn muốn tùy chọn định tuyến giữa các Node. Chúng là các hàm chọn nút tiếp theo dựa trên một số logic.
Trong ví dụ trên, để sao chép kết quả quyết định của người dùng, chúng ta sẽ xác định một hàm để mô phỏng xác suất Chọn Trà là 60%.

import random
from typing import Literal

def decide_dring(state) -> Literal["node_2", "node_3"]:
    """
    Quyết định nút tiếp theo dựa trên xác suất chia 60/40.
    """
    # Mô phỏng xác suất 60% cho "node_2"
    if random.random() < 0.6:  # 60% chance
        return "node_2"
    
    # Còn lại 40% cơ hội
    return "node_3"
from IPython.display import Image, display
from langgraph.graph import StateGraph, START, END

# Build graph
builder = StateGraph(State)

builder.add_node("node_1", node_1)
builder.add_node("node_2", node_2)
builder.add_node("node_3", node_3)

# Add the logic of the graph
builder.add_edge(START, "node_1")
builder.add_conditional_edges("node_1", decide_dring) #decide_dring trả về tên `node 2` hoặc `node 3`
builder.add_edge("node_2", END)
builder.add_edge("node_3", END)

# Compile the graph
graph = builder.compile()

# Visualize the graph
display(Image(graph.get_graph().draw_mermaid_png()))

Đầu tiên, chúng ta khởi tạo StateGraph với lớp State mà chúng ta đã định nghĩa ở trên.
Sau đó, chúng ta thêm các nút và cạnh.
START Node là một nút đặc biệt gửi dữ liệu đầu vào của người dùng đến graph, để chỉ ra nơi bắt đầu đồ thị của chúng ta.

builder.add_conditional_edges("node_1", decide_dring)

Mỗi lần hàm được gọi, nó đưa ra quyết định dựa trên cơ hội ngẫu nhiên:
60% cơ hội: Trả về "node_2".
40% cơ hội: Trả về "node_3".
Tại sao sử dụng điều này?
Để ra quyết định: Nó mô phỏng một lựa chọn xác suất, có thể hữu ích trong các ứng dụng như mô phỏng, trò chơi hoặc học máy.
Kiểu trả về theo nghĩa đen đảm bảo rằng hàm sẽ luôn chỉ trả về "node_2" hoặc "node_3", giúp dễ dự đoán và gỡ lỗi hơn.

END Node là một nút đặc biệt biểu thị một nút đầu cuối.
Chúng ta biên dịch graph của mình để thực hiện một vài kiểm tra cơ bản trên cấu trúc graph.

image.png

5. Chạy ứng dụng

Graph đã biên dịch triển khai giao thức runnable, một cách chuẩn để thực thi các thành phần LangChain. Do đó, chúng ta có thể sử dụng invoke làm một trong những phương pháp chuẩn để chạy ứng dụng này.

Đầu vào ban đầu của chúng ta là từ điển {"graph_state": "Xin chào, đây là VHTSoft."}, từ điển này đặt giá trị ban đầu cho từ điển trạng thái.

Khi invoke được gọi:

Biểu đồ bắt đầu thực thi từ nút START.

Nó tiến triển qua các nút đã xác định (node_1, node_2, node_3) theo thứ tự.

Cạnh có điều kiện sẽ đi qua từ nút 1 đến nút 2 hoặc 3 bằng quy tắc quyết định 60/40.

Mỗi hàm nút nhận trạng thái hiện tại và trả về một giá trị mới, giá trị này sẽ ghi đè trạng thái biểu đồ.

Việc thực thi tiếp tục cho đến khi đạt đến nút END.

graph.invoke({"graph_state" : "Hi, Tôi là VHTSoft."})
{'graph_state': 'Hi, Tôi là VHTSoft. Tôi sẽ quyết định Chọn Trà'}

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Ứng dụng LangGraph cơ bản với chatbot và công cụ

Mục tiêu của ứng dụng.

image.png

Sử dụng LangGraph quyết định phản hồi bằng chatbot hoặc sử dụng công cụ

Chúng ta sẽ xây dựng một ứng dụng cơ bản thực hiện 4 thao tác
Sử dụng chat messages làm State

Sử dụng chat model làm Node

Liên kết một công cụ với chat model

Thực hiện lệnh gọi công cụ trong Node

I. Cài đặt

* cd project_name
* pyenv local 3.11.4
* poetry install
* poetry shell
* jupyter lab

tạo file .env

OPENAI_API_KEY=your_openai_api_key
* LANGCHAIN_TRACING_V2=true
* LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
* LANGCHAIN_API_KEY=your_langchain_api_key
* LANGCHAIN_PROJECT=your_project_name

Bạn sẽ cần đăng ký tài khoản tại smith.langchain.com để lấy API key.

Kết nối với file .env nằm trong cùng thư mục của notebook

#pip install python-dotenv
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
openai_api_key = os.environ["OPENAI_API_KEY"]
Cài  LangChain

#!pip install langchain-openai

from langchain_openai import ChatOpenAI

chatModel35 = ChatOpenAI(model="gpt-3.5-turbo-0125")
chatModel4o = ChatOpenAI(model="gpt-4o")

II. Xác định State schema

from typing_extensions import TypedDict
from langchain_core.messages import AnyMessage
from typing import Annotated
from langgraph.graph.message import add_messages

class MessagesState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
from typing_extensions import TypedDict
from langchain_core.messages import AnyMessage
from typing import Annotated

Metadata là gì? Xem tại đây

Annotated là gì? Xem tại đây

from langgraph.graph.message import add_messages
class MessagesState(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
đây là định nghĩa một State schema

III. Xác định Node duy nhất của ứng dụng 

def simple_llm(state: MessagesState):
    return {"messages": [chatModel4o.invoke(state["messages"])]}

Đây là một LangGraph Node Function. Nó:

  1. Nhận vào state (dạng dictionary có cấu trúc MessagesState)

  2. Lấy danh sách tin nhắn từ state["messages"]

  3. Gửi toàn bộ danh sách đó vào mô hình ngôn ngữ chatModel4o

  4. Nhận lại một phản hồi từ LLM

  5. Trả về phản hồi đó trong một dict mới dưới dạng {"messages": [<message>]}

Ví dụ minh họa

Giả sử:

state = {
    "messages": [
        HumanMessage(content="Chào bạn"),
    ]
}

Gọi

simple_llm(state)

Trả về

{
    "messages": [
        AIMessage(content="Chào bạn! Tôi có thể giúp gì?")
    ]
}

Tóm lại

Thành phần Vai trò
state: MessagesState Trạng thái hiện tại (danh sách message)
chatModel4o.invoke(...) Gửi prompt đến LLM
return {"messages": [...]} Trả về message mới để nối thêm vào state

Vì trong ví dụ này chúng ta chỉ có một nút nên chúng ta không cần phải xác định các cạnh.

IV. Biên dịch ứng dụng
from IPython.display import Image, display
from langgraph.graph import StateGraph, START, END
    
# Build graph
builder = StateGraph(MessagesState)

builder.add_node("simple_llm", simple_llm)

# Add the logic of the graph
builder.add_edge(START, "simple_llm")
builder.add_edge("simple_llm", END)

# Compile the graph
graph = builder.compile()

# Visualize the graph
display(Image(graph.get_graph().draw_mermaid_png()))

from IPython.display import Image, display
from langgraph.graph import StateGraph, START, END

Xây dựng Graph:

builder = StateGraph(MessagesState)

Khởi tạo 1 builder để tạo ra graph, với MessagesState là định nghĩa schema cho state.

builder.add_node("simple_llm", simple_llm)

Kết nối các bước xử lý:

builder.add_edge(START, "simple_llm")
builder.add_edge("simple_llm", END)

START → simple_llm → END: bạn đang định nghĩa luồng chạy của graph theo thứ tự:

  1. Bắt đầu

  2. Chạy simple_llm

  3. Kết thúc

Biên dịch Graph:

graph = builder.compile()

Hiển thị sơ đồ:

display(Image(graph.get_graph().draw_mermaid_png()))

image.png

V. Chạy ứng dụng

from pprint import pprint
from langchain_core.messages import AIMessage, HumanMessage

messages = graph.invoke({"messages": HumanMessage(content="Where is the Golden Gate Bridge?")})

for m in messages['messages']:
    m.pretty_print()


- **Gọi Graph để xử lý một prompt** (giống như một chatbot).
- `graph.invoke(...)` là cách chạy luồng xử lý bạn đã định nghĩa bằng `StateGraph`.
- Bạn truyền vào một `dict` có key `"messages"` và giá trị là một **HumanMessage duy nhất**.

Trong thực tế, `"messages"` thường là **list[BaseMessage]**, nhưng LangGraph tự động chuyển đổi nếu bạn truyền một message duy nhất (nó sẽ biến nó thành `[HumanMessage(...)]`)

---### ```python
for m in messages['messages']:
    m.pretty_print()

Kết quả in ra (ví dụ)

Giả sử AI trả lời như sau, bạn sẽ thấy:

Human: Where is the Golden Gate Bridge?
AI: The Golden Gate Bridge is located in San Francisco, California, USA.

Diễn giải toàn bộ quy trình

  1. Bạn tạo một HumanMessage hỏi AI một câu.

  2. Gửi message đó vào graph (đã xây bằng LangGraph).

  3. Graph chạy các node, ví dụ simple_llm, và thêm AIMessage phản hồi vào state.

  4. Trả về danh sách messages mới (có cả user + AI).

  5. In ra từng message bằng .pretty_print().

V. Bây giờ chúng ta hãy thêm một công cụ vào ChatModel4o 
def multiply(a: int, b: int) -> int:
    """Multiply a and b.

    Args:
        a: first int
        b: second int
    """
    return a * b

chatModel4o_with_tools = chatModel4o.bind_tools([multiply])

Định nghĩa một hàm nhân 2 số nguyên ab.

chatModel4o.bind_tools([multiply])

VI. Bây giờ chúng ta hãy tạo một ứng dụng LangGraph thứ hai có thể quyết định xem ứng dụng đó có sử dụng chatbot LLM hay Công cụ Multiply để trả lời câu hỏi của người dùng hay không

# Node
def llm_with_tool(state: MessagesState):
    return {"messages": [chatModel4o_with_tools.invoke(state["messages"])]}
from IPython.display import Image, display
from langgraph.graph import StateGraph, START, END
    
# Build graph
builder = StateGraph(MessagesState)

builder.add_node("llm_with_tool", llm_with_tool)

# Add the logic of the graph
builder.add_edge(START, "llm_with_tool")
builder.add_edge("llm_with_tool", END)

# Compile the graph
graph = builder.compile()

# Visualize the graph
display(Image(graph.get_graph().draw_mermaid_png()))

image.png

from pprint import pprint
from langchain_core.messages import AIMessage, HumanMessage

# The following two lines are the most frequent way to 
# run and print a LangGraph chatbot-like app results.
messages = graph.invoke({"messages": HumanMessage(content="Where is the Eiffel Tower?")})

for m in messages['messages']:
    m.pretty_print()

================================ Human Message ================================= Where is the Eiffel Tower? ================================== Ai Message ================================== The Eiffel Tower is located in Paris, France. It is situated on the Champ de Mars, near the Seine River.

from pprint import pprint
from langchain_core.messages import AIMessage, HumanMessage

# The following two lines are the most frequent way to 
# run and print a LangGraph chatbot-like app results.
messages = graph.invoke({"messages": HumanMessage(content="Multiply 4 and 5")})

for m in messages['messages']:
    m.pretty_print()

================================ Human Message ================================= Multiply 4 and 5 ================================== Ai Message ================================== Tool Calls: multiply (call_QRyPmp5TdcIlfEOyBrJ9E7V5) Call ID: call_QRyPmp5TdcIlfEOyBrJ9E7V5 Args: a: 4 b: 5

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Định tuyến(Router) trong LangGraph

Router trong LangGraph là gì?

Trong LangGraph, Router là một Node đặc biệt (tức một bước – step) cho phép bạn tạo ra các nhánh (branches) dựa trên dữ liệu hoặc trạng thái hiện tại.

Nói đơn giản:

Router giống như ngã ba đường — dựa trên state hiện tại, bạn chọn hướng đi tiếp theo (chuyển tới node A, B hoặc C).

Khi nào bạn cần dùng Router?

Khi bạn có logic như:

Bạn không muốn xử lý tất cả trong một node, mà tách nhánh theo logic, thì Router là giải pháp.

Cách dùng Router trong LangGraph

def my_router(state):
    if state["preference"] == "coffee":
        return "coffee_node"
    elif state["preference"] == "tea":
        return "tea_node"
    else:
        return "unknown_preference"

Đây là một Router node, tức là nó nhận một state (trạng thái hiện tại), và trả về tên node kế tiếp dựa trên logic.

state["preference"] là giá trị đầu vào mà bạn đưa vào để quyết định nhánh.

Đăng ký Router node trong graph

Ví dụ sau, Router không thực thi hành động chính mà chọn node tiếp theo dựa trên logic phân nhánh.

builder = StateGraph(StateSchema)
builder.add_node("start", start_node)
builder.add_node("router", my_router)
builder.add_node("coffee_node", coffee_node)
builder.add_node("tea_node", tea_node)

# Router branching
builder.add_edge("start", "router")
builder.add_conditional_edges(
    "router",
    {
        "coffee_node": "coffee_node",
        "tea_node": "tea_node"
    }
)

Lợi ích của Router

Gợi ý dùng thực tế

Use case Router logic
Trợ lý cá nhân Phân nhánh theo yêu cầu người dùng: tra cứu lịch, gửi mail, hoặc dịch văn bản
Ứng dụng học tập Phân hướng học viên đến bài kiểm tra phù hợp trình độ
Ứng dụng đặt hàng Nếu sản phẩm còn → đặt hàng; nếu không → đề xuất khác

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

So sánh Router và Node trong LangGraph

Dưới đây là bài so sánh chi tiết giữa Router và Node trong LangGraph, giúp bạn dễ phân biệt và áp dụng chính xác trong từng tình huống.

Tiêu chí Node (Nút xử lý) Router (Bộ định tuyến)
Chức năng chính Xử lý logic cụ thể và trả về dữ liệu mới Định tuyến (chọn nhánh tiếp theo dựa trên trạng thái)
Trả về Một dictionary chứa các giá trị mới cho state Một chuỗi (string) tên của node tiếp theo
Điều hướng tiếp theo Sử dụng add_edge() hoặc add_conditional_edges() Sử dụng add_conditional_edges() để ánh xạ chuỗi → node
Tính logic Chứa logic chính như gọi LLM, xử lý dữ liệu... Chứa logic quyết định hướng đi tiếp theo
Dữ liệu trả về Ví dụ: { "graph_state": "Tôi chọn trà" } Ví dụ: "coffee_node" hoặc "tea_node"
Dùng khi nào? Khi cần thực hiện một hành động/ghi nhớ dữ liệu Khi cần rẽ nhánh theo điều kiện hoặc phân luồng logic
Ví dụ minh họa

Node bình thường trả về giá trị mới cho state:

def coffee_node(state):
    print("☕ Tôi chọn coffee")
    return {"result": "Bạn sẽ có một ly coffee"}

Router trả về tên của node tiếp theo:

def my_router(state):
    if state["preference"] == "coffee":
        return "coffee_node"
    elif state["preference"] == "tea":
        return "tea_node"
    else:
        return "unknown_node"

Khi nào dùng Router thay vì Node?

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Hiểu rõ hơn về add_conditional_edges

Chúng ta lấy 2 ví dụ để so sánh

builder.add_conditional_edges("node_1", decide_dring)

và 

builder.add_conditional_edges("router", {
    "coffee_node": "coffee_node",
    "tea_node": "tea_node",
    "fallback_node": "fallback_node"
})

Hai dòng builder.add_conditional_edges(...) trên đều dùng để thêm điều kiện rẽ nhánh, nhưng cách dùng và mục đích của chúng có sự khác biệt rõ ràng.

Tiêu chí builder.add_conditional_edges("node_1", decide_dring) builder.add_conditional_edges("router", { "coffee_node": ..., ... })
Kiểu truyền đối số Truyền một hàm điều kiện (condition function) Truyền một dict ánh xạ giá trị trả về từ router đến các node tương ứng
Ai quyết định rẽ nhánh? Hàm decide_dring(state) sẽ quyết định đi đến node nào Hàm router(state) sẽ trả về một string → dict ánh xạ string đó đến node tương ứng
Giá trị trả về của hàm Trả về tên node dưới dạng string Trả về tên node dưới dạng string, phải trùng với key trong dict
Node được gắn vào Gắn vào một node bình thường (node_1) Gắn vào một router node (router)
Sử dụng khi Khi bạn muốn node đang xử lý tự quyết định rẽ nhánh tiếp theo Khi bạn tách riêng logic định tuyến ra một router riêng biệt
Ví dụ hàm điều kiện def decide_dring(state): return "coffee_node" if ... else "tea_node" def router(state): return "coffee_node" / "tea_node" / "fallback_node"
Thường dùng khi Bạn muốn node_1 vừa xử lý vừa quyết định hướng đi tiếp Bạn muốn tách riêng xử lý (node) và định tuyến (router) một cách rõ ràng
Dạng Ý nghĩa
add_conditional_edges("node_1", decide_dring) Node xử lý xong rồi chọn tiếp theo đi đâu.
add_conditional_edges("router", { ... }) Router chỉ quyết định hướng đi, còn xử lý nằm ở node khác.

Khi nào dùng cái nào?

Nếu bạn muốn... Hãy dùng...
Một node tự quyết định rẽ nhánh tiếp theo add_conditional_edges("node_1", decide_dring)
Một router chuyên dùng để rẽ nhánh add_conditional_edges("router", { ... })

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Bài Thực Hành Router Trong LangGraph

Mục tiêu: Tạo một LangGraph gồm các bước đơn giản, giúp người dùng quyết định sẽ uống Coffee hay Trà.

image.png


I. Cài đặt

* cd project_name
* pyenv local 3.11.4
* poetry install
* poetry shell
* jupyter lab

Tạo .env file

OPENAI_API_KEY=your_openai_api_key
LANGCHAIN_TRACING_V2=true
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_API_KEY=your_langchain_api_key
LANGCHAIN_PROJECT=your_project_name

Kết nối file .env

#pip install python-dotenv
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
openai_api_key = os.environ["OPENAI_API_KEY"]

II. Kết nối LangChain

#!pip install langgraph langchain openai

III.  Định nghĩa State Schema (State = Memory)

from typing import TypedDict, Literal

class DrinkState(TypedDict):
    preference: Literal["coffee", "tea", "unknown"]

TypedDict

DrinkState

preference: Literal["coffee", "tea", "unknown"]

IV. Định nghĩa các Nodes (mỗi Node là một Step)

# Node: Bắt đầu
def start_node(state: DrinkState) -> DrinkState:
    print("👉 Bạn thích uống gì hôm nay?")
    choice = input("Nhập 'coffee' hoặc 'tea': ").strip().lower()
    if choice not in ["coffee", "tea"]:
        choice = "unknown"
    return {"preference": choice}

# Node: Nếu chọn coffee
def coffee_node(state: DrinkState) -> DrinkState:
    print("☕ Bạn đã chọn Coffee! Tuyệt vời!")
    return state

# Node: Nếu chọn tea
def tea_node(state: DrinkState) -> DrinkState:
    print("🍵 Bạn đã chọn Trà! Thanh tao ghê!")
    return state

# Node: Nếu nhập sai
def fallback_node(state: DrinkState) -> DrinkState:
    print("Không rõ bạn chọn gì. Vui lòng thử lại.")
    return state

V. Định nghĩa Router

def drink_router(state: DrinkState) -> str:
    if state["preference"] == "coffee":
        return "coffee_node"
    elif state["preference"] == "tea":
        return "tea_node"
    else:
        return "fallback_node"

VI. Xây dựng Graph

from langgraph.graph import StateGraph

builder = StateGraph(DrinkState)

# Thêm các nodes
builder.add_node("start", start_node)
builder.add_node("coffee_node", coffee_node)
builder.add_node("tea_node", tea_node)
builder.add_node("fallback_node", fallback_node)
builder.add_node("router", drink_router)

# Tạo flow giữa các bước
builder.set_entry_point("start")
builder.add_edge("start", "router")

builder.add_conditional_edges("router", {
    "coffee_node": "coffee_node",
    "tea_node": "tea_node",
    "fallback_node": "fallback_node"
})

# Gắn điểm kết thúc cho mỗi nhánh
builder.set_finish_point("coffee_node")
builder.set_finish_point("tea_node")
builder.set_finish_point("fallback_node")

# Compile graph
app = builder.compile()

 

VII. Chạy thử

# Trạng thái khởi đầu rỗng
initial_state: DrinkState = {"preference": "unknown"}
final_state = app.invoke(initial_state)

Kết quả

Tùy người dùng nhập vào coffee hay tea, graph sẽ tự động điều hướng tới đúng bước xử lý, và in kết quả tương ứng.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Giới thiệu về ReAct Architecture

Kiến trúc ReAct là một mô hình rất quan trọng trong việc xây dựng các Agent dựa trên LLM. Tên “ReAct” là viết tắt của Reasoning and Acting – tức là kết hợp giữa lập luậnhành động. Đây là cách mà một Agent thông minh có thể thực hiện nhiều bước để hoàn thành một nhiệm vụ, thay vì chỉ trả lời một lần rồi kết thúc.

Giới thiệu về ReAct Architecture

ReAct cho phép các LLM (Large Language Models) hoạt động theo chu trình:

  1. act (hành động)
    Mô hình quyết định gọi một công cụ (tool) để thực hiện một hành động cụ thể. Ví dụ: tìm kiếm thông tin, tính toán, tra dữ liệu từ API, v.v.

  2. observe (quan sát)
    Công cụ thực hiện hành động và trả về kết quả. Kết quả này sẽ được đưa trở lại LLM như một phần của cuộc hội thoại (hoặc “context”).

  3. reason (lập luận)
    LLM tiếp nhận kết quả, phân tích và quyết định bước tiếp theo: có thể gọi thêm một công cụ khác, tiếp tục hỏi người dùng, hoặc kết thúc bằng một câu trả lời.

image.png

ReAct là cách mà AI (LLM) suy nghĩ và hành động như một con người:

 “Nghĩ – Làm – Quan sát – Nghĩ tiếp – Làm tiếp…”

Câu chuyện đơn giản

Bạn nói với AI:

"Tính giúp tôi 3 + 5"

AI làm gì?

Bước Hành động Giải thích dễ hiểu
Act "Tôi sẽ gọi công cụ máy tính để tính toán" (Gọi hàm calculator_tool)
Tool Máy tính nhận yêu cầu, tính ra kết quả 8  
Observe AI nhìn vào kết quả: 8 (Cập nhật kết quả vào bộ nhớ)
Reason AI tự hỏi: “Người dùng muốn tính tiếp không?” Nếu có, lặp lại từ đầu

Ví dụ thực tế

Giả sử bạn hỏi:
"Hôm nay thời tiết ở TP Hồ Chí Minh như thế nào và tôi có nên mang ô không?"

Agent thực hiện:

Trả lời cuối cùng:
"Hôm nay TP Hồ Chí Minh có khả năng mưa vào chiều tối, bạn nên mang theo ô."

Ứng dụng của ReAct

Ví dụ cơ bản

Tạo một agent hỏi người dùng một phép tính, gọi một công cụ để tính, rồi tiếp tục hỏi đến khi người dùng muốn dừng.

Kiến trúc Agent như sau

START
  ↓
LLM (hỏi phép tính)
  ↓
TOOL (tính kết quả)
  ↓
LLM (xem kết quả, hỏi tiếp hay kết thúc?)
  → Nếu tiếp → quay lại TOOL
  → Nếu kết thúc → END

1. Định nghĩa State

from typing import TypedDict, List, Optional

class CalcState(TypedDict):
    history: List[str]
    next_action: Optional[str]
    question: Optional[str]
    answer: Optional[str]

2. Tạo Tool Node

def calculator_tool(state: CalcState) -> CalcState:
    question = state["question"]
    try:
        answer = str(eval(question))  # WARNING: chỉ dùng với ví dụ đơn giản!
    except:
        answer = "Không thể tính được."

    state["answer"] = answer
    state["history"].append(f"Q: {question}\nA: {answer}")
    return state

3. Tạo LLM Node

def llm_node(state: CalcState) -> CalcState:
    print("🧠 LLM: Tôi đang nghĩ...")
    print(f"Câu hỏi: {state.get('question')}")
    print(f"Kết quả: {state.get('answer')}")
    
    # Quyết định bước tiếp theo
    choice = input("Bạn muốn tiếp tục (yes/no)? ")
    if choice.lower() == "no":
        state["next_action"] = "end"
    else:
        new_q = input("Nhập phép tính mới: ")
        state["question"] = new_q
        state["next_action"] = "calculate"
    return state

4. Router

def calc_router(state: CalcState) -> str:
    return state["next_action"]

5. Kết nối các bước bằng LangGraph

from langgraph.graph import StateGraph

builder = StateGraph(CalcState)

builder.add_node("llm_node", llm_node)
builder.add_node("tool_node", calculator_tool)
builder.add_node("router", calc_router)

builder.set_entry_point("llm_node")
builder.add_edge("llm_node", "router")

builder.add_conditional_edges("router", {
    "calculate": "tool_node",
    "end": "__end__"
})

builder.add_edge("tool_node", "llm_node")
graph = builder.compile()

6. Chạy thử

state = {
    "history": [],
    "next_action": None,
    "question": "2 + 3",
    "answer": None,
}

graph.invoke(state)

Output mẫu

LLM: Tôi đang nghĩ...
Câu hỏi: 2 + 3
Kết quả: None
Nhập phép tính mới: 2 + 3
Q: 2 + 3
A: 5
Bạn muốn tiếp tục (yes/no)? yes
Nhập phép tính mới: 10 * 2
...
Tóm tắt kiến trúc ReAct
Pha Vai trò Ý nghĩa
Act LLM gọi công cụ LLM yêu cầu tính một biểu thức toán học
Observe Công cụ trả kết quả Công cụ calculator_tool xử lý phép tính và trả về kết quả
Reason LLM quyết định bước tiếp theo Dựa trên kết quả, LLM quyết định tiếp tục hay dừng
Tool Công cụ được LLM gọi Ở đây là hàm calculator_tool dùng eval() để tính toán

Phân tích chi tiết ví dụ trên

1. Act – LLM gọi công cụ

Trong hàm llm_node, nếu người dùng muốn tiếp tục:

state["next_action"] = "calculate"

LLM quyết định hành động tiếp theo là gọi công cụ tính toán.

2. Observe – Công cụ trả kết quả

def calculator_tool(state: CalcState) -> CalcState:
    ...
    state["answer"] = answer

Công cụ thực hiện tính toán và cập nhật lại state (trạng thái) với kết quả.
LLM sẽ quan sát lại kết quả ở bước tiếp theo.

3. Reason – LLM quyết định tiếp theo

Sau khi đã có kết quả trong state["answer"], LLM đánh giá và hỏi:

choice = input("Bạn muốn tiếp tục (yes/no)? ")

Nếu yes thì act lần nữa (gọi lại công cụ).
Nếu no thì kết thúc (gọi "end").

4. Tool – Công cụ độc lập

def calculator_tool(state: CalcState) -> CalcState:
    ...

Đây chính là một công cụ (Tool) – thực hiện công việc cụ thể do LLM yêu cầu.
Nó không thông minh, chỉ đơn thuần xử lý dữ liệu đầu vào.

Tổng kết dễ hiểu

Bước Thành phần Vai trò
1 llm_node Act: Quyết định gọi tool
2 calculator_tool Observe: Trả kết quả về
3 llm_node Reason: Xem kết quả và quyết định hành động tiếp theo

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Thực hành – Node LLM quyết định bước tiếp theo

Chúng ta sẽ xây dựng lại ứng dụng trước đó, nhưng lần này sẽ bổ sung hành vi mang tính "agent" điển hình. Theo cách gọi của nhóm LangGraph, đây sẽ là Agent đầu tiên của chúng ta.

Những điểm chính:

Agent Cơ Bản

Thực hành

Tạo một agent sử dụng kiến trúc ReAct với quy trình:

  1. Người dùng không biết chọn gì → LLM hỏi ý kiến.

  2. LLM gọi một tool để kiểm tra trạng thái năng lượng người dùng.

  3. Tool trả lời về mức năng lượng.

  4. Dựa vào đó, LLM đưa ra lời khuyên nên uống trà hay cà phê.

image.png

1. Cài đặt và chuẩn bị

pip install langgraph openai

2. Định nghĩa State

from typing import TypedDict, Literal, Optional

class DrinkState(TypedDict):
    preference: Literal["coffee", "tea", "unknown"]
    energy_level: Optional[str]
    messages: list[dict]

3. Tạo công cụ kiểm tra năng lượng

def check_energy_level(state: DrinkState) -> DrinkState:
    # Giả sử công cụ xác định người dùng đang "mệt"
    energy = "tired"
    state["energy_level"] = energy
    state["messages"].append({"role": "tool", "content": f"Energy level is {energy}"})
    return state

4. Tạo node LLM để đưa ra quyết định

from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(temperature=0)

def llm_node(state: DrinkState) -> DrinkState:
    messages = state["messages"]
    response = llm.invoke(messages)
    state["messages"].append({"role": "assistant", "content": response.content})
    if "coffee" in response.content.lower():
        state["preference"] = "coffee"
    elif "tea" in response.content.lower():
        state["preference"] = "tea"
    return state

5. Tạo Graph

from langgraph.graph import StateGraph

builder = StateGraph(DrinkState)

builder.add_node("llm", llm_node)
builder.add_node("check_energy", check_energy_level)

builder.set_entry_point("llm")

# LLM gọi tool rồi quay lại chính nó
builder.add_edge("llm", "check_energy")
builder.add_edge("check_energy", "llm")

# Thiết lập điểm kết thúc
builder.set_finish_point("llm")

graph = builder.compile()

6. Chạy thử

initial_state = {
    "preference": "unknown",
    "energy_level": None,
    "messages": [{"role": "user", "content": "Tôi không biết nên uống gì hôm nay"}],
}

final_state = graph.invoke(initial_state)
print("Gợi ý của Agent:", final_state["preference"])

Giải thích luồng hoạt động

  1. Người dùng không đưa ra lựa chọn cụ thể.

  2. LLM phân tích và quyết định cần kiểm tra mức năng lượng.

  3. Tool check_energy trả về trạng thái "mệt".

  4. LLM đưa ra khuyến nghị uống cà phê để tăng tỉnh táo.

  5. Kết thúc.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Kết nối các công cụ (tools) bằng bind_tools

bind_tools là một tính năng trong LangChain (thường dùng với các mô hình như OpenAI’s GPT) để kết nối các công cụ (tools) với LLM. Nó cho phép mô hình gọi những tool đó khi cần, như tính toán, truy xuất thông tin, tra cứu, v.v.

ind_tools giúp bạn nói với LLM rằng:

"Ê, ngoài việc trả lời bằng văn bản, mày có thể gọi mấy tool này nếu thấy cần."

Cú pháp cơ bản

llm_with_tools = chat_model.bind_tools(
    tools=[tool_1, tool_2],
    parallel_tool_calls=False  # hoặc True nếu muốn gọi song song nhiều tool
)

Ví dụ đơn giản

Bước 1: Định nghĩa các tool

from langchain.tools import tool

@tool
def add(a: int, b: int) -> int:
    """Cộng hai số"""
    return a + b

@tool
def multiply(a: int, b: int) -> int:
    """Nhân hai số"""
    return a * b

Bước 2: Bind tools vào mô hình

from langchain.chat_models import ChatOpenAI

chat_model = ChatOpenAI(model="gpt-4")

llm_with_tools = chat_model.bind_tools(
    tools=[add, multiply],
    parallel_tool_calls=False  # toán học thường nên làm tuần tự
)

Bước 3: Gọi mô hình và để nó tự chọn tool

response = llm_with_tools.invoke("Hãy cộng 3 và 5 giúp tôi")
print(response.content)

Nếu LLM hiểu rằng cần thực hiện phép cộng, nó sẽ tự động gọi tool add(3, 5) và trả lại kết quả là 8.

bind_tools hữu ích vì

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Xây dựng một ứng dụng quyết định xem có nên trò chuyện bằng LLM hay sử dụng công cụ

image.png

1. Cài đặt

* cd project_name
* pyenv local 3.11.4
* poetry install
* poetry shell
* jupyter lab

2. Tạo .env file

* OPENAI_API_KEY=your_openai_api_key
* LANGCHAIN_TRACING_V2=true
* LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
* LANGCHAIN_API_KEY=your_langchain_api_key
* LANGCHAIN_PROJECT=your_project_name

3. Kết nối file .env

#pip install python-dotenv
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
openai_api_key = os.environ["OPENAI_API_KEY"]

4. Cài đặt LangChain

#!pip install langchain
#!pip install langchain-openai
from langchain_openai import ChatOpenAI

chatModel35 = ChatOpenAI(model="gpt-3.5-turbo-0125")
chatModel4o = ChatOpenAI(model="gpt-4o")

5. LLM với các công cụ

from langchain.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multiply a and b.

    Args:
        a: first int
        b: second int
    """
    return a * b

@tool
def add(a: int, b: int) -> int:
    """Adds a and b.

    Args:
        a: first int
        b: second int
    """
    return a + b
@tool
def divide(a: int, b: int) -> float:
    """Divide a and b.

    Args:
        a: first int
        b: second int
    """
    return a / b

tools = [add, multiply, divide]

llm_with_tools = chatModel4o.bind_tools(tools, parallel_tool_calls=False)

Define the State schema

from langgraph.graph import MessagesState

class MessagesState(MessagesState):
    # Add any keys needed beyond messages, which is pre-built 
    pass

Define the first Node

from langchain_core.messages import HumanMessage, SystemMessage

# System message, system prompt
sys_msg = SystemMessage(content="You are a helpful assistant tasked with performing arithmetic on a set of inputs.")

# Node
def assistant(state: MessagesState):
   return {"messages": [llm_with_tools.invoke([sys_msg] + state["messages"])]}

* Các nút của đồ thị được định nghĩa là các hàm python.
* Đối số đầu tiên của hàm Node là trạng thái. Do đó, trong bài tập này, mỗi nút có thể truy cập khóa `messages`, với `state['messages']`.
* Trong ví dụ này, chúng ta sẽ bắt đầu bằng một nút tương tự như nút chúng ta đã tạo trong bài tập trước, **nhưng lần này bằng SystemMessage**:

Kết hợp các nút và cạnh để xây dựng đồ thị

from langgraph.graph import START, StateGraph
from langgraph.prebuilt import tools_condition
from langgraph.prebuilt import ToolNode
from IPython.display import Image, display

# Build graph
builder = StateGraph(MessagesState)

builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(tools))

# Add the logic of the graph
builder.add_edge(START, "assistant")

builder.add_conditional_edges(
    "assistant",
    # If the latest message (result) from assistant is a tool call -> tools_condition routes to tools
    # If the latest message (result) from assistant is a not a tool call -> tools_condition routes to END
    tools_condition,
)

# PAY ATTENTION HERE: from the tools node, back to the assistant
builder.add_edge("tools", "assistant")

# PAY ATTENTION: No END edge.

# Compile the graph
react_graph = builder.compile()

# Visualize the graph
display(Image(react_graph.get_graph(xray=True).draw_mermaid_png()))


* act - LLM gọi một công cụ.
* observer - công cụ chuyển đầu ra trở lại LLM.
* reason - LLM quyết định phải làm gì tiếp theo (gọi một công cụ khác hoặc phản hồi trực tiếp).

image.png

Chạy ứng dụng
messages = [HumanMessage(content="What was the relationship between Marilyn and JFK?")]
messages = react_graph.invoke({"messages": messages})

for m in messages['messages']:
    m.pretty_print()
================================ Human Message =================================

What was the relationship between Marilyn and JFK?
================================== Ai Message ==================================

Marilyn Monroe and President John F. Kennedy (JFK) are often rumored to have had a romantic relationship, though concrete details about the nature and extent of their relationship remain speculative and are part of popular lore. The most famous public connection between them was Marilyn Monroe's sultry performance of "Happy Birthday, Mr. President" at a Democratic Party fundraiser and early birthday celebration for Kennedy in May 1962. However, both contemporaneous accounts and historical research have not conclusively proven a long-term affair, and much of the speculation is based on anecdotal evidence and hearsay.
messages = [HumanMessage(content="Add 3 and 4. Multiply the output by 2. Divide the output by 5")]
messages = react_graph.invoke({"messages": messages})

for m in messages['messages']:
    m.pretty_print()
================================ Human Message =================================

Add 3 and 4. Multiply the output by 2. Divide the output by 5
================================== Ai Message ==================================
Tool Calls:
  add (call_UR7Cp0pbVpRyof8Dyq4kZUHm)
 Call ID: call_UR7Cp0pbVpRyof8Dyq4kZUHm
  Args:
    a: 3
    b: 4
================================= Tool Message =================================
Name: add

7
================================== Ai Message ==================================
Tool Calls:
  multiply (call_OiwYtGUW13AY8CB3qY3Y3Vlt)
 Call ID: call_OiwYtGUW13AY8CB3qY3Y3Vlt
  Args:
    a: 7
    b: 2
================================= Tool Message =================================
Name: multiply

14
...
2.8
================================== Ai Message ==================================

The final result after adding 3 and 4, multiplying the result by 2, and then dividing by 5 is 2.8.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Tạo ứng dụng cơ bản LangGraph AI Agents.

Tóm tắt chương

Tạm dừng một chút để cùng nhau ôn lại những gì chúng ta đã học được nhé!

Chúng ta bắt đầu chương này với cảm giác khá lo lắng – có lẽ bạn cũng từng nghĩ: "Cái LangGraph này nghe thật rối rắm và phức tạp", đúng không? Những khái niệm nghe có vẻ như dành riêng cho những người có siêu năng lực, phải có bằng tiến sĩ hay ít nhất là thạc sĩ mới hiểu nổi cách dùng nó!

Nhưng rồi khi đi đến cuối chương, ta nhận ra rằng ai cũng có thể xây dựng ứng dụng với LangGraph. Đằng sau những thuật ngữ nghe phức tạp đó thật ra lại là những khái niệm rất đơn giản. Và chúng ta đã thấy rằng bất kỳ ai cũng có thể tạo ra những agent thông minh, thậm chí là những ứng dụng có thể thay đổi cả thế giới.

Vậy cụ thể, ta đã làm gì?

Đơn giản đúng không nào?

Và cuối cùng, ta đã tạo ra agent đầu tiên của mình bằng cách cho phép tool phản hồi trở lại LLM – chính là mô hình ReAct: act (gọi tool), observe (quan sát kết quả), reason (suy luận xem làm gì tiếp theo).


Sắp tới là gì?

Trong chương tiếp theo, chúng ta sẽ khám phá một chủ đề cực kỳ quan trọng trong thế giới LangGraph: Memory (Bộ nhớ).

Dù trước giờ ta đã nói về state và một chút về memory, nhưng bạn sẽ thấy rằng, trong LangGraph, memory không đơn giản chỉ là lưu trữ thông tin – nó là cốt lõi để tạo ra những agent thông minh và có tính phản hồi cao.

Hãy chuẩn bị tinh thần để bước vào một chương siêu hấp dẫn nhé!

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Một trong những yếu tố quan trọng nhất để tạo nên sự khác biệt giữa một agent “bình thường” và một agent “đỉnh cao” sẵn sàng chạy trên môi trường thực tế (production).
Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Giới Thiệu

Tiếp tục hành trình – Bước vào một chủ đề cực kỳ quan trọng: Memory (Bộ nhớ) trong LangGraph

Trong phần này, chúng ta sẽ đào sâu vào một chủ đề đóng vai trò sống còn khi xây dựng agent bằng LangGraph – đó chính là memory (bộ nhớ). Và không chỉ nói đến trí nhớ ngắn hạn(short term memory), mà cả trí nhớ dài hạn(long term memory) nữa!

Ngay từ đầu, bạn sẽ nhận ra: đây chính là một trong những yếu tố quan trọng nhất để tạo nên sự khác biệt giữa một agent “bình thường” và một agent “đỉnh cao” sẵn sàng chạy trên môi trường thực tế (production).

Nói đơn giản:
Ứng dụng của bạn có thật sự thông minh và đáng nhớ hay chỉ dừng lại ở mức “cho vui” – tất cả nằm ở cách bạn xử lý memory.

Vậy chúng ta sẽ học gì?

Chúng ta sẽ bắt đầu với phần dễ trước – trí nhớ ngắn hạn(short term memory). Đây là loại bộ nhớ gắn liền với cuộc trò chuyện hiện tại giữa người dùng và agent.

Nếu bạn muốn agent của mình hiểu được mạch hội thoại (biết bạn vừa nói gì, nhớ câu hỏi trước, không bị “mất trí nhớ ngắn hạn”), thì bạn cần phải kích hoạt trí nhớ dài hạn(long term memory) cho nó.

Và bạn sẽ thấy: Việc này cực kỳ đơn giản với LangGraph.

Có những thứ bạn cần nắm trước

Trong tài liệu chính thức của LangGraph, khi họ bắt đầu nói về memory, họ thường đưa ra rất nhiều khái niệm như:

Thành thật mà nói, cách LangGraph viết tài liệu không phải lúc nào cũng dễ hiểu, thậm chí có thể gây rối nếu bạn mới bắt đầu.

Vì vậy, chúng ta sẽ làm rõ ba khái niệm đó trước – theo cách đơn giản, trực quan và đúng bản chất, giúp bạn hiểu sâu mà không bị rối bởi quá nhiều dòng code.

Mục tiêu của phần này là gì?

 Hãy sẵn sàng! Trong những bài tiếp theo, chúng ta sẽ cùng nhau khám phá kỹ hơn về 4 khái niệm trên, với những ví dụ thực tế và trực quan nhất.

Bạn chỉ cần nhớ: đừng để tài liệu khó hiểu làm bạn nản lòng – chúng ta sẽ đi từng bước, và bạn chắc chắn sẽ làm được. 

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Thêm Bộ Nhớ Ngắn Hạn vào Agent trong LangGraph

Trong bài học này, chúng ta sẽ tìm hiểu cách thêm bộ nhớ ngắn hạn (short-term memory) vào agent để nó có thể ghi nhớ ngữ cảnh của cuộc trò chuyện. Điều này giúp agent hiểu được các yêu cầu liên tiếp từ người dùng một cách chính xác hơn.

Vấn đề của Agent Không Có Bộ Nhớ

Trong bài tập trước, chúng ta đã xây dựng một agent đơn giản có thể thực hiện các phép tính toán học bằng cách di chuyển qua các node "assistant" và "tools". Tuy nhiên, agent này có một hạn chế lớn: nó không có bộ nhớ.

Ví dụ minh họa:
  1. Người dùng yêu cầu:
    "3 + 5."
    → Agent trả lời: "Tổng của 3 + 5 = 8"

  2. Người dùng tiếp tục:
    "nhân kết quả với 2"

Nếu agent không có bộ nhớ, nó sẽ không hiểu "kết quả" ám chỉ kết quả trước đó và yêu cầu người dùng cung cấp lại số:
"Tôi cần một số cụ thể để nhân với hai. Bạn vui lòng cung cấp số bạn muốn nhân"

Điều này gây bất tiện vì người dùng phải lặp lại thông tin đã cung cấp trước đó.

Cách Thêm Bộ Nhớ Ngắn Hạn vào Agent

Trong LangGraph, việc thêm bộ nhớ ngắn hạn rất đơn giản bằng cách sử dụng module MemorySaver. Module này giúp lưu trữ thông tin tạm thời trong một phiên hội thoại cụ thể.

1. Sử dụng MemorySaver tại bước compile

Khi khởi tạo agent, chúng ta thêm bộ nhớ vào trong quá trình compile:

from langgraph.checkpoint.memory import MemorySaver

memory = MemorySaver()

react_graph_memory = builder.compile(checkpointer=memory)

2. Sử dụng thread_id để phân biệt các cuộc hội thoại

Để đảm bảo bộ nhớ chỉ áp dụng cho một phiên trò chuyện cụ thể, ta sử dụng thread_id khi gọi invoke:

config = {"configurable": {"thread_id": "1"}}

messages = [HumanMessage(content="Add 3 and 4.")]

messages = react_graph_memory.invoke({"messages": messages},config)

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Thực hành bộ nhớ ngắn hạn

Trong bài học này, chúng ta sẽ học cách thêm bộ nhớ ngắn hạn vào agent của mình.

1. Cài đặt

Tại console:

* cd project_name
* pyenv local 3.11.4
* poetry install
* poetry shell
* jupyter lab

2. Tạo file .env

* OPENAI_API_KEY=your_openai_api_key
* LANGCHAIN_TRACING_V2=true
* LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
* LANGCHAIN_API_KEY=your_langchain_api_key
* LANGCHAIN_PROJECT=your_project_name

3. Kết nối với tệp .env nằm trong cùng thư mục của notebook

#pip install python-dotenv
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
openai_api_key = os.environ["OPENAI_API_KEY"]

3. Cài đặt LangChain

#!pip install langchain
#!pip install langchain-openai
from langchain_openai import ChatOpenAI

chatModel35 = ChatOpenAI(model="gpt-3.5-turbo-0125")
chatModel4o = ChatOpenAI(model="gpt-4o")

4. LLM kết hợp với nhiều công cụ hỗ trợ

from langchain_openai import ChatOpenAI
from langchain.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multiply a and b.

    Args:
        a: first int
        b: second int
    """
    return a * b

@tool
def add(a: int, b: int) -> int:
    """Adds a and b.

    Args:
        a: first int
        b: second int
    """
    return a + b
  
@tool
def divide(a: int, b: int) -> float:
    """Divide a and b.

    Args:
        a: first int
        b: second int
    """
    return a / b

tools = [add, multiply, divide]
llm_with_tools = chatModel4o.bind_tools(tools, parallel_tool_calls=False)
parallel_tool_calls=True

Đây là gọi công cụ song song (chạy nhiều công cụ cùng lúc).

parallel_tool_calls=False

Đây là gọi công cụ tuần tự (chạy lần lượt từng cái một).

Chi tiết tại

https://python.langchain.com/docs/how_to/tool_calling_parallel/

5. Xây dựng một ứng dụng (gọi là đồ thị trong langgraph) quyết định xem có nên trò chuyện bằng LLM hay sử dụng công cụ

image.png

5.1 Định nghĩa State schema
from langgraph.graph import MessagesState

class MessagesState(MessagesState):
    # Add any keys needed beyond messages, which is pre-built 
    pass

5.2 Định nghĩa Node đầu tiên

from langgraph.graph import MessagesState
from langchain_core.messages import HumanMessage, SystemMessage

# Khai báo System message
sys_msg = SystemMessage(content="Bạn là trợ lý hữu ích có nhiệm vụ thực hiện phép tính số học trên một tập hợp dữ liệu đầu vào.")

# Định nghĩa Node
def assistant(state: MessagesState):
   return {"messages": [llm_with_tools.invoke([sys_msg] + state["messages"])]}
[sys_msg] + state["messages"]
5.3. Kết hợp các Node và Edge để xây dựng Graph
from langgraph.graph import START, StateGraph
from langgraph.prebuilt import tools_condition
from langgraph.prebuilt import ToolNode
from IPython.display import Image, display

# Build graph
builder = StateGraph(MessagesState)

builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(tools))

# Add the logic of the graph
builder.add_edge(START, "assistant")

builder.add_conditional_edges(
    "assistant",
    # Nếu câu trả lời gần nhất của assistant là một lời gọi tới tool, Thì điều kiện tools_condition sẽ quyết định đi tiếp đến node tools
    # Ngược lại, tools_condition sẽ quyết định chuyển sang node END (kết thúc luồng, trả kết quả ra ngoài).
    tools_condition,
)

# PAY ATTENTION HERE: from the tools node, back to the assistant
builder.add_edge("tools", "assistant")

# PAY ATTENTION: No END edgge.

# Compile the graph
react_graph = builder.compile()

# Visualize the graph
display(Image(react_graph.get_graph(xray=True).draw_mermaid_png()))

image.png

5.4 Chạy ứng dụng
messages = [HumanMessage(content="Add 3 and 4.")]

messages = react_graph.invoke({"messages": messages})

for m in messages['messages']:
    m.pretty_print()

================================ Human Message ================================= Add 3 and 4. ================================== Ai Message ================================== Tool Calls: add (call_AKxpCcslEcimrNFvBEWZ2Ru3) Call ID: call_AKxpCcslEcimrNFvBEWZ2Ru3 Args: a: 3 b: 4 ================================= Tool Message ================================= Name: add 7 ================================== Ai Message ================================== The sum of 3 and 4 is 7.

5.5 Tiếp tục hỏi Agent 

messages = [HumanMessage(content="Multiply that by 2.")]

messages = react_graph.invoke({"messages": messages})

for m in messages['messages']:
    m.pretty_print()

================================ Human Message ================================= Multiply that by 2. ================================== Ai Message ================================== I need a specific number to multiply by 2. Could you please provide the number you want to multiply?

Như bạn thấy, Agent yêu cầu cung cấp một số cụ thể để thực hiện phép tính nhân, nó không nhớ được kết quả của phép tính cộng đã thực hiện ở trên

6. Thêm bộ nhớ
from langgraph.checkpoint.memory import MemorySaver

memory = MemorySaver()

react_graph_memory = builder.compile(checkpointer=memory)
# PAY ATTENTION HERE: see how we specify a thread
config = {"configurable": {"thread_id": "1"}}

# Enter the input
messages = [HumanMessage(content="Add 3 and 4.")]

# PAY ATTENTION HERE: see how we add config to referr to the thread_id
messages = react_graph_memory.invoke({"messages": messages},config)

for m in messages['messages']:
    m.pretty_print()

Kết quả

================================ Human Message ================================= Add 3 and 4. ================================== Ai Message ================================== Tool Calls: add (call_7lH6zvBw4rMeTG3Zu66i53eW) Call ID: call_7lH6zvBw4rMeTG3Zu66i53eW Args: a: 3 b: 4 ================================= Tool Message ================================= Name: add 7 ================================== Ai Message ================================== The sum of 3 and 4 is 7.

Tiếp tục yêu cầu phép tính nhân

# PAY ATTENTION HERE: see how we check if the app has memory
messages = [HumanMessage(content="Multiply that by 2.")]

# Again, see how we use config here to referr to the thread_id
messages = react_graph_memory.invoke({"messages": messages}, config)

for m in messages['messages']:
    m.pretty_print()

================================ Human Message ================================= Multiply that by 2. ================================== Ai Message ================================== Tool Calls: multiply (call_x3tKpGBsTHUCbVwzBr3PiNn1) Call ID: call_x3tKpGBsTHUCbVwzBr3PiNn1 Args:

...

14 ================================== Ai Message ================================== The result of multiplying 7 by 2 is 14.

Agent đã nhớ được kết quả của phép tính cộng và thực hiện phép tính nhân

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Định dạng state schema trong LangGraph từ TypeDict sang Pydantic

Trong ba bài học tiếp theo, chúng tôi sẽ giới thiệu cho bạn về một số khái niệm thú vị mà bạn sẽ gặp trong tài liệu của LangGraph, đặc biệt là trong phần memo.

Tuy nhiên, ở thời điểm này, những khái niệm này có thể gây xao nhãng cho bạn. Vì vậy, chúng tôi không khuyến khích bạn đào sâu vào các chủ đề này ngay lúc này. Mục tiêu là giúp bạn hiểu khái niệmbiết nơi có thể tìm hiểu thêm khi cần thiết.

Chủ đề đầu tiên là các cách định dạng state schema trong LangGraph.

Nếu bạn còn nhớ, khi tạo state schema trong các bài tập trước, chúng ta luôn sử dụng loại TypeDict.

TypeDict là một cách rất đơn giản để xây dựng state schema.
Tuy nhiên, khi bạn làm việc với các ứng dụng ở cấp độ production, cách này có thể quá đơn giảnthiếu tính an toàn, đặc biệt trong việc phát hiện lỗi hoặc cảnh báo khi có điều gì đó sai trong ứng dụng của bạn.

Trong bài học này, chúng tôi sẽ giải thích nội dung mà tài liệu của LangGraph đề cập về các cách định dạng state schema:

Bao gồm:

I. TypeDict trong State Schema

TypeDict là một cách đơn giản và nhanh chóng để định nghĩa state schema – tức là cấu trúc trạng thái (state) mà LangGraph sẽ lưu trữ và truyền giữa các node (hoặc giữa LLM và công cụ).

Nó là một alias của TypedDict trong Python, được dùng để định nghĩa dictionary có kiểu rõ ràng cho từng key.

Khi nào nên dùng TypeDict?

Cách định nghĩa State Schema với TypeDict

from typing import TypedDict

class MyState(TypedDict):
    name: str
    mood: str
    count: int

Trong ví dụ trên, MyState định nghĩa một state có 3 trường:

Ví dụ trong LangGraph
from langgraph.graph import StateGraph

# Định nghĩa schema bằng TypeDict
class State(TypedDict):
    name: str
    mood: str

# Tạo Graph với state schema
builder = StateGraph(State)

# Add nodes, edges... (ví dụ đơn giản)
def greet(state: State) -> State:
    print(f"Hello, {state['name']}! You seem {state['mood']} today.")
    return state

builder.add_node("greet", greet)
builder.set_entry_point("greet")

app = builder.compile()

# Chạy thử
initial_state = {"name": "Alice", "mood": "happy"}
app.invoke(initial_state)

Lưu ý khi dùng TypeDict

Ưu điểm Hạn chế
Dễ viết, nhanh chóng Không xác thực dữ liệu
Phù hợp cho prototyping(giai đoạn thử nghiệm hoặc xây dựng bản mẫu) Dễ gây lỗi trong ứng dụng lớn
Sử dụng chuẩn Python typing Không cảnh báo khi sai dữ liệu
II. Literal

Trong Python, Literal được cung cấp bởi thư viện typing và cho phép bạn ràng buộc giá trị của một biến chỉ được phép nằm trong một tập hợp cụ thể. Đây là một cách tuyệt vời để tăng tính an toàn cho state schema, đảm bảo rằng người dùng hoặc ứng dụng chỉ có thể nhập những giá trị hợp lệ.

Literal trong State Schema

Khi định nghĩa trạng thái (state) trong LangGraph, bạn có thể muốn giới hạn một trường nào đó chỉ nhận một số giá trị nhất định.
Ví dụ: trạng thái "mood" chỉ được là "happy" hoặc "sad" — không được là "angry", "confused", v.v.

Ví dụ 1

from typing import TypedDict, Literal

class MyState(TypedDict):
    mood: Literal["happy", "sad"]

Trong ví dụ trên:

Ví dụ 2

from typing import TypedDict, Literal

class UserState(TypedDict):
    name: str
    mood: Literal["happy", "sad"]

Giá trị hợp lệ:

state: UserState = {
    "name": "Alice",
    "mood": "happy"
}

Giá trị không hợp lệ (trình kiểm tra type sẽ cảnh báo):

state: UserState = {
    "name": "Alice",
    "mood": "angry"  # ❌ Không nằm trong Literal["happy", "sad"]
}

Trong LangGraph, bạn có thể sử dụng Literal để đảm bảo rằng luồng logic của bạn hoạt động đúng như mong đợi.
Ví dụ:

class WorkflowState(TypedDict):
    step: Literal["start", "processing", "done"]

Với định nghĩa này, bạn có thể đảm bảo:

III. dataclass để tạo state schema

Nhắc lại dataclass trong python

dataclasses giúp bạn tự động tạo ra các phương thức như:

Ví dụ

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

Python sẽ tự động sinh ra:

def __init__(self, name: str, age: int):
    self.name = name
    self.age = age

dataclass để tạo state schema(Chi tiết về dataclass tại đây)

from dataclasses import dataclass

@dataclass
class ConversationState:
    name: str
    mood: str
    count: int = 0  # Giá trị mặc định

__post_init__: logic sau khi khởi tạo

@dataclass
class State:
    name: str
    mood: str

    def __post_init__(self):
        if self.mood not in ["happy", "sad"]:
            raise ValueError("Mood must be 'happy' or 'sad'")

Hợp lệ

state = State(name="Lan", mood="happy")
print(state)
# Output: ConversationState(name='Lan', mood='happy')

Không hợp lệ

state = State(name="Lan", mood="angry")
# Output: ValueError: Mood must be 'happy' or 'sad'
IV. Dùng Pydantic làm State Schema trong LangGraph

Chi tiết về Pydantic

Trong LangGraph, State Schema định nghĩa cấu trúc dữ liệu sẽ được truyền và cập nhật giữa các node trong graph.
Pydantic là một thư viện mạnh mẽ giúp xác thực dữ liệu, kiểm tra lỗi đầu vào và định kiểu rõ ràng, rất phù hợp cho các ứng dụng thực tế (production-level).

Ưu điểm khi dùng Pydantic cho State Schema

Cách định nghĩa State Schema bằng Pydantic

Bạn sẽ tạo một lớp kế thừa từ pydantic.BaseModel.
Mỗi thuộc tính của lớp đại diện cho một phần trong trạng thái.

1. Cài đặt pydantic

pip install pydantic

2.  Tạo State

from pydantic import BaseModel
from typing import Literal

class MyState(BaseModel):
    name: str
    age: int
    mood: Literal["happy", "sad"]
Ví dụ sử dụng trong LangGraph:
from langgraph.graph import StateGraph, END
from langgraph.checkpoint import MemorySaver

# Định nghĩa schema với Pydantic
class State(BaseModel):
    name: str
    mood: Literal["happy", "sad"]

# Node đơn giản: in trạng thái hiện tại
def print_state(state: State):
    print(f"👤 {state.name} đang cảm thấy {state.mood}")
    return state

# Tạo graph
builder = StateGraph(State)
builder.add_node("printer", print_state)
builder.set_entry_point("printer")
builder.set_finish_point("printer")

# Chạy
graph = builder.compile()
graph.invoke({"name": "An", "mood": "happy"})  # ✅ OK
graph.invoke({"name": "An", "mood": "angry"})  # ❌ Gây lỗi ValidationError

Khi có lỗi, bạn sẽ thấy:

ValidationError: 1 validation error for State
mood
  unexpected value; permitted: 'happy', 'sad' (type=value_error.const; given=angry; permitted=('happy', 'sad'))

Mở rộng với mặc định và tùy chỉnh:

from pydantic import Field

class State(BaseModel):
    name: str = Field(..., description="Tên người dùng")
    mood: Literal["happy", "sad"] = "happy"  # mặc định là happy

name: str = Field(..., description="Tên người dùng")

Nếu bạn không truyền name, bạn sẽ nhận được lỗi:

ValidationError: 1 validation error for State
name
  field required (type=value_error.missing)

mood: Literal["happy", "sad"] = "happy"

State(name="An")  # OK, mood mặc định là "happy"
State(name="An", mood="sad")  # OK
State(name="An", mood="angry")  # ❌ Lỗi vì "angry" không nằm trong ["happy", "sad"]

Tổng kết:

Thành phần Giải thích
Field(...) Đánh dấu giá trị là bắt buộc
description Ghi chú mô tả, dùng cho docs
Literal[...] Ràng buộc giá trị chỉ được nằm trong một tập hợp cố định
= "giá trị" Thiết lập giá trị mặc định nếu không truyền vào

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Cách Tùy Chỉnh Cập Nhật Trạng Thái bằng Reducers

Trong LangGraph, Reducers là những hàm đặc biệt được sử dụng để tổng hợp dữ liệu hoặc kết hợp trạng thái khi có nhiều luồng song song (parallel branches) trả về kết quả khác nhau.

Nói cách khác:

Khi bạn chạy nhiều node cùng lúc (parallel), và muốn gom kết quả từ chúng lại để đưa vào bước tiếp theo – thì bạn cần một Reducer.

Bạn cần dùng Reducer khi:

Mục đích Chi tiết
Kết hợp dữ liệu Khi có nhiều nhánh chạy song song
Nhận đầu vào Một danh sách các trạng thái (dict)
Trả đầu ra Một trạng thái duy nhất đã được tổng hợp
Ứng dụng Tổng hợp kết quả LLM, kết hợp thông tin từ nhiều nguồn

Giả sử bạn có 3 nhánh song song:

Sau khi 3 node này chạy xong, bạn cần gộp kết quả lại thành:

{
  "name": "VHTSoft",
  "address": "TP. Hồ Chí Minh",
  "phone": "0123456789"
}

Reducer sẽ gom và hợp nhất những giá trị này thành một trạng thái chung.

Định nghĩa Reducer

Reducer là một hàm nhận vào nhiều trạng thái (dưới dạng danh sách) và trả về một trạng thái duy nhất.

def my_reducer(states: list[dict]) -> dict:
    result = {}
    for state in states:
        result.update(state)  # Gộp tất cả dict lại
    return result

Cách sử dụng trong LangGraph

Khi bạn xây dựng graph với StateGraph, bạn có thể chỉ định reducer cho một node nhất định như sau:

from langgraph.graph import StateGraph

builder = StateGraph(dict)
# Các node song song được thêm ở đây...

# Thêm reducer cho node tổng hợp
builder.add_reducer("merge_node", my_reducer)

Ví dụ thực tế

1. Khai báo các node

def node_1(state): return {"name": "VHTSoft"}
def node_2(state): return {"address": "TP.Hồ Chí Minh"}
def node_3(state): return {"phone": "0123456789"}

2. Tạo graph

builder = StateGraph(dict)
builder.add_node("node_1", node_1)
builder.add_node("node_2", node_2)
builder.add_node("node_3", node_3)
builder.add_node("merge_node", lambda x: x)  # Dummy node

# Thêm reducer
def my_reducer(states):  # states là list các dict
    result = {}
    for s in states:
        result.update(s)
    return result

builder.add_reducer("merge_node", my_reducer)

# Chạy 3 node song song → gộp về merge_node
builder.add_edge("node_1", "merge_node")
builder.add_edge("node_2", "merge_node")
builder.add_edge("node_3", "merge_node")

builder.set_entry_point("node_1")  # node_1 là điểm vào chính

graph = builder.compile()

Các hàm hữu ích về Reducers trong LangGraph

1. Custom Logic trong Reducer

Bạn không bị giới hạn bởi việc chỉ dùng dict.update(). Bạn có thể áp dụng bất kỳ logic tùy chỉnh nào để gộp dữ liệu:

Ví dụ: Lọc trạng thái hợp lệ

def filtered_reducer(states: list[dict]) -> dict:
    final_state = {}
    for state in states:
        # Bỏ qua những trạng thái thiếu dữ liệu cần thiết
        if "score" in state and state["score"] >= 0.8:
            final_state.update(state)
    return final_state

Dùng khi:

Trong ví dụ này, ta sẽ có 3 nhánh song song trả về thông tin khác nhau cùng với một chỉ số độ tin cậy (score). Sau đó, ta sẽ dùng một reducer để chỉ giữ lại những kết quả có score >= 0.8.

Giả sử bạn có một graph với 3 agent xử lý một nhiệm vụ phân tích cảm xúc từ một đoạn văn. Mỗi agent trả về:

Bạn chỉ muốn giữ lại kết quả của các agent có độ tin cậy cao (score ≥ 0.8).

Bước 1: Tạo các node trả về kết quả

from langgraph.graph import StateGraph, END
from typing import TypedDict

class State(TypedDict):
    sentiment: str
    score: float

# Mỗi node trả về một kết quả khác nhau
def analyzer_1(state):
    return {"sentiment": "happy", "score": 0.9}

def analyzer_2(state):
    return {"sentiment": "sad", "score": 0.7}  # Không đạt

def analyzer_3(state):
    return {"sentiment": "neutral", "score": 0.85}

Bước 2: Tạo filtered_reducer

def filtered_reducer(states: list[dict]) -> dict:
    for state in states:
        if state.get("score", 0) >= 0.8:
            return state  # Trả về state đầu tiên đạt yêu cầu
    return {"sentiment": "unknown", "score": 0.0}

Bước 3: Dựng graph và chạy thử

graph = StateGraph(State)
graph.add_node("analyzer_1", analyzer_1)
graph.add_node("analyzer_2", analyzer_2)
graph.add_node("analyzer_3", analyzer_3)

graph.add_edge("analyzer_1", END)
graph.add_edge("analyzer_2", END)
graph.add_edge("analyzer_3", END)

graph.set_entry_point(["analyzer_1", "analyzer_2", "analyzer_3"])
graph.set_finish_point(END, filtered_reducer)

app = graph.compile()

result = app.invoke({})
print(result)

Kết quả mong đợi:

{'sentiment': 'happy', 'score': 0.9}

Vì analyzer_1 là node đầu tiên đạt yêu cầu score >= 0.8, nên nó được giữ lại. Các kết quả khác bị bỏ qua.

Biến thể nâng cao: Trả về danh sách tất cả các kết quả tốt
def filtered_reducer(states: list[dict]) -> dict:
    good_results = [s for s in states if s.get("score", 0) >= 0.8]
    return {"results": good_results}

Kết quả:

{
  'results': [
    {'sentiment': 'happy', 'score': 0.9},
    {'sentiment': 'neutral', 'score': 0.85}
  ]
}

2. Merging trạng thái phức tạp (nested)

Giả sử mỗi nhánh trả về trạng thái dạng lồng nhau (nested):

{
  "agent": {
    "name": "Alice",
    "tasks": ["translate"]
  }
}

Bạn có thể merge có điều kiện, thậm chí hợp nhất danh sách:

def deep_merge_reducer(states: list[dict]) -> dict:
    merged = {"agent": {"name": "", "tasks": []}}
    for state in states:
        agent = state.get("agent", {})
        if "name" in agent:
            merged["agent"]["name"] = agent["name"]
        if "tasks" in agent:
            merged["agent"]["tasks"] += agent["tasks"]
    return merged

Giả sử bạn có một hệ thống thu thập thông tin sản phẩm từ nhiều nguồn. Mỗi node (agent) sẽ trả về thông tin chi tiết khác nhau về sản phẩm, như:

Mỗi thông tin nằm trong một cấu trúc nested dictionary:

{
  "product": {
    "name": ...,
    "price": ...,
    "reviews": [...],
  }
}

Chúng ta sẽ merge lại tất cả thành một state hoàn chỉnh.

1. Định nghĩa state phức tạp

from typing import TypedDict, Optional
from langgraph.graph import StateGraph, END

class ProductInfo(TypedDict, total=False):
    name: Optional[str]
    price: Optional[float]
    reviews: list[str]

class State(TypedDict, total=False):
    product: ProductInfo

2. Các node thu thập thông tin khác nhau

def fetch_name(state):
    return {
        "product": {
            "name": "Smartphone X"
        }
    }

def fetch_price(state):
    return {
        "product": {
            "price": 799.99
        }
    }

def fetch_reviews(state):
    return {
        "product": {
            "reviews": ["Good value", "Excellent battery", "Fast delivery"]
        }
    }

3. Merge state phức tạp bằng custom reducer

LangGraph sẽ merge các dicts theo mặc định, nhưng với dict lồng nhau, bạn cần viết custom reducer.

def nested_merge_reducer(states: list[dict]) -> dict:
    merged = {"product": {}}
    for state in states:
        product = state.get("product", {})
        for key, value in product.items():
            if key == "reviews":
                merged["product"].setdefault("reviews", []).extend(value)
            else:
                merged["product"][key] = value
    return merged

4. Tạo Graph

graph = StateGraph(State)

graph.add_node("name", fetch_name)
graph.add_node("price", fetch_price)
graph.add_node("reviews", fetch_reviews)

graph.add_edge("name", END)
graph.add_edge("price", END)
graph.add_edge("reviews", END)

graph.set_entry_point(["name", "price", "reviews"])
graph.set_finish_point(END, nested_merge_reducer)

app = graph.compile()
result = app.invoke({})

print(result)

Kết quả mong đợi:

{
  "product": {
    "name": "Smartphone X",
    "price": 799.99,
    "reviews": [
      "Good value",
      "Excellent battery",
      "Fast delivery"
    ]
  }
}

Ghi chú:

3. Giữ thứ tự hoặc gán vai trò

Trong một số trường hợp, bạn muốn biết được nhánh nào trả về cái gì, thay vì merge chung.

def role_based_reducer(states: list[dict]) -> dict:
    return {
        "summarizer_result": states[0]["output"],
        "validator_result": states[1]["output"],
        "rewriter_result": states[2]["output"],
    }

Ví Dụ

Bạn đang xây dựng một ứng dụng hội thoại với nhiều agent khác nhau tham gia đối thoại. Mỗi agent đóng một vai trò (ví dụ: Customer, Support, Bot), và bạn muốn giữ thứ tự lời thoại cùng với vai trò rõ ràng.

1. Định nghĩa State

from typing import TypedDict
from langgraph.graph import StateGraph, END

class Message(TypedDict):
    role: str
    content: str

class ChatState(TypedDict, total=False):
    messages: list[Message]

2. Các node đóng vai khác nhau

def customer_node(state):
    return {
        "messages": [
            {"role": "customer", "content": "Tôi muốn kiểm tra đơn hàng của mình."}
        ]
    }

def support_node(state):
    return {
        "messages": [
            {"role": "support", "content": "Chào anh/chị, vui lòng cung cấp mã đơn hàng ạ."}
        ]
    }

def bot_node(state):
    return {
        "messages": [
            {"role": "bot", "content": "Tôi có thể hỗ trợ những câu hỏi thường gặp. Bạn muốn hỏi gì?"}
        ]
    }

3. Custom reducer giữ thứ tự lời thoại

def ordered_reducer(states: list[dict]) -> dict:
    all_messages = []
    for state in states:
        msgs = state.get("messages", [])
        all_messages.extend(msgs)
    return {"messages": all_messages}

 Lưu ý: extend giúp nối danh sách lời thoại từ các node theo đúng thứ tự gọi.

4. Xây dựng LangGraph

graph = StateGraph(ChatState)

graph.add_node("customer", customer_node)
graph.add_node("support", support_node)
graph.add_node("bot", bot_node)

graph.add_edge("customer", "support")
graph.add_edge("support", "bot")
graph.add_edge("bot", END)

graph.set_entry_point("customer")
graph.set_finish_point(END, reducer=ordered_reducer)

app = graph.compile()
result = app.invoke({})

from pprint import pprint
pprint(result)

Kết quả mong đợi:

{
  'messages': [
    {'role': 'customer', 'content': 'Tôi muốn kiểm tra đơn hàng của mình.'},
    {'role': 'support', 'content': 'Chào anh/chị, vui lòng cung cấp mã đơn hàng ạ.'},
    {'role': 'bot', 'content': 'Tôi có thể hỗ trợ những câu hỏi thường gặp. Bạn muốn hỏi gì?'}
  ]
}

4. Gộp theo trọng số(Weighted merge )

Khi bạn có nhiều nguồn dữ liệu và muốn ưu tiên nguồn nào đó, bạn có thể merge có trọng số.

def weighted_merge_reducer(states: list[dict]) -> dict:
    scores = [0.5, 0.3, 0.2]  # trọng số cho từng nhánh
    merged_output = ""
    for state, score in zip(states, scores):
        merged_output += f"{score:.1f} * {state['text']}\n"
    return {"combined_output": merged_output}

Ví dụ

Giả sử  có 3 agent khác nhau đề xuất một câu trả lời cho cùng một câu hỏi, nhưng mỗi agent có độ tin cậy khác nhau. Bạn muốn:

1. Khai báo State

from typing import TypedDict

class State(TypedDict, total=False):
    suggestions: list[dict]  # Mỗi đề xuất có 'text' và 'score'

2. Tạo các node với "đề xuất" khác nhau

def agent_1(state):
    return {"suggestions": [{"text": "Trả lời từ agent 1", "score": 0.8}]}

def agent_2(state):
    return {"suggestions": [{"text": "Trả lời từ agent 2", "score": 0.6}]}

def agent_3(state):
    return {"suggestions": [{"text": "Trả lời từ agent 3", "score": 0.9}]}

3. Gộp theo trọng số(Weighted merge )

def weighted_merge(states: list[dict]) -> dict:
    from collections import defaultdict

    scores = defaultdict(float)

    for state in states:
        for suggestion in state.get("suggestions", []):
            text = suggestion["text"]
            score = suggestion.get("score", 1.0)
            scores[text] += score  # Cộng điểm nếu có trùng câu trả lời

    # Chọn text có tổng điểm cao nhất
    best_text = max(scores.items(), key=lambda x: x[1])[0]
    return {"final_answer": best_text}

defaultdict: xem chi tiết tại https://docs.vhterp.com/books/ky-thuat-lap-trinh-python/page/defaultdict

4. Xây dựng đồ thị

from langgraph.graph import StateGraph, END

graph = StateGraph(State)

graph.add_node("agent_1", agent_1)
graph.add_node("agent_2", agent_2)
graph.add_node("agent_3", agent_3)

graph.add_edge("agent_1", END)
graph.add_edge("agent_2", END)
graph.add_edge("agent_3", END)

graph.set_entry_point("agent_1")
graph.set_finish_point(END, reducer=weighted_merge)

app = graph.compile()
result = app.invoke({})

print(result)

Kết quả:

{'final_answer': 'Trả lời từ agent 3'}

5. Reducers + Pydantic = An toàn tuyệt đối

Khi reducer trả về một dict, bạn có thể dùng Pydantic để đảm bảo kết quả hợp lệ và chặt chẽ:

from pydantic import BaseModel

class FinalState(BaseModel):
    name: str
    summary: str
    mood: str

def reducer_with_validation(states):
    merged = {}
    for s in states:
        merged.update(s)
    return FinalState(**merged).dict()

Tình huống thực tế:

Giả sử bạn đang xây dựng một hệ thống trợ lý AI cho chăm sóc khách hàng. Bạn có nhiều "nhánh" (agents) cùng phân tích yêu cầu của người dùng để trích xuất thông tin: name, email, issue.

Mỗi agent có thể phát hiện một phần thông tin. Bạn muốn:

1. Định nghĩa State với Pydantic

from pydantic import BaseModel, EmailStr
from typing import Optional

class UserRequest(BaseModel):
    name: Optional[str]
    email: Optional[EmailStr]
    issue: Optional[str]
2. Tạo các Agent
def extract_name(state):
    return {"name": "Nguyễn Văn A"}

def extract_email(state):
    return {"email": "nguyenvana@example.com"}

def extract_issue(state):
    return {"issue": "Không đăng nhập được vào tài khoản"}

3. Tạo Reducer sử dụng Pydantic để kiểm tra tính hợp lệ

def safe_merge(states: list[dict]) -> dict:
    merged = {}
    for state in states:
        merged.update(state)

    # Kiểm tra hợp lệ bằng Pydantic
    validated = UserRequest(**merged)
    return validated.dict()

4. Xây dựng Graph

from langgraph.graph import StateGraph, END

graph = StateGraph(UserRequest)

graph.add_node("name", extract_name)
graph.add_node("email", extract_email)
graph.add_node("issue", extract_issue)

# Cho các node chạy song song
graph.add_edge("name", END)
graph.add_edge("email", END)
graph.add_edge("issue", END)

graph.set_entry_point("name")
graph.set_finish_point(END, reducer=safe_merge)

app = graph.compile()
result = app.invoke({})

print(result)

Kết quả

{
  'name': 'Nguyễn Văn A',
  'email': 'nguyenvana@example.com',
  'issue': 'Không đăng nhập được vào tài khoản'
}

6. Kết hợp với ToolCall

Nếu các nhánh là các công cụ (tools), bạn có thể dùng reducer để phân tích kết quả từ từng công cụ:

def tool_result_reducer(states):
    results = {}
    for state in states:
        tool_name = state["tool"]
        result = state["result"]
        results[tool_name] = result
    return {"tools_result": results}

Tình huống thực tế:

Bạn có một hệ thống AI assistant, khi người dùng hỏi:

"Tôi tên là Minh, email của tôi là minh@example.com, tôi cần hỗ trợ về hóa đơn."

Bạn dùng LLM để tách thông tin đó, nhưng thay vì chỉ tách thủ công, bạn dùng ToolCall để giao cho từng tool xử lý riêng một phần.

1. Định nghĩa ToolState với Pydantic
from pydantic import BaseModel, EmailStr
from typing import Optional
from langchain_core.tools import tool

class UserInfo(BaseModel):
    name: Optional[str]
    email: Optional[EmailStr]
    issue: Optional[str]
2. Định nghĩa các Tool dùng ToolCall
@tool
def extract_name_tool(text: str) -> dict:
    if "tên là" in text:
        return {"name": "Minh"}
    return {}

@tool
def extract_email_tool(text: str) -> dict:
    if "email" in text:
        return {"email": "minh@example.com"}
    return {}

@tool
def extract_issue_tool(text: str) -> dict:
    return {"issue": "hỗ trợ về hóa đơn"}
3. Dùng LangGraph gọi các Tool + Gộp lại bằng Reducer
from langgraph.graph import StateGraph, END
from langgraph.graph.message import ToolMessage
from langgraph.prebuilt.tool_node import ToolNode

# Khởi tạo ToolNode
tool_node = ToolNode(tools=[extract_name_tool, extract_email_tool, extract_issue_tool])

# Reducer sử dụng Pydantic để validate kết quả
def merge_tool_results(states: list[dict]) -> dict:
    merged = {}
    for state in states:
        merged.update(state)
    return UserInfo(**merged).dict()
4. Tạo Graph
graph = StateGraph(UserInfo)

# Tạo một node để gọi tool dựa vào user input
def prepare_tool_call(state):
    return ToolMessage(
        tool_name="extract_name_tool",  # Không cần quá cụ thể vì ToolNode sẽ tự chọn tool phù hợp
        tool_input={"text": "Tôi tên là Minh, email của tôi là minh@example.com, tôi cần hỗ trợ về hóa đơn."}
    )

graph.add_node("call_tool", prepare_tool_call)
graph.add_node("tool_node", tool_node)

graph.add_edge("call_tool", "tool_node")
graph.add_edge("tool_node", END)

graph.set_entry_point("call_tool")
graph.set_finish_point(END, reducer=merge_tool_results)

app = graph.compile()
result = app.invoke({})

print(result)

Kết quả

{
  "name": "Minh",
  "email": "minh@example.com",
  "issue": "hỗ trợ về hóa đơn"
}

Lợi ích của việc dùng ToolCall:

Tính năng Lợi ích
Tách vai trò Mỗi Tool xử lý một phần dữ liệu
Kết hợp logic Dễ dàng mở rộng thêm Tool mà không phải viết lại toàn bộ
An toàn dữ liệu Pydantic đảm bảo kết quả hợp lệ, đúng định dạng
Tự động ToolNode sẽ chọn tool phù hợp dựa vào tên tool và input

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 





Memory (Bộ nhớ)

Public State, Private State và Multiple State Schemas trong LangGraph

Ví Dụ Minh Họa: Cửa Hàng Sửa Máy Tính

1. Public State - Giao Tiếp Đơn Giản Với Khách Hàng

→ Đây chính là public state trong Landgraaf: trạng thái mà người dùng cuối (khách hàng) tương tác trực tiếp.

2. Private State - Giao Tiếp Nội Bộ Kỹ Thuật

→ Đây là private state: trạng thái nội bộ để xử lý logic phức tạp.

3. Kết Quả Cuối Cùng - Quay Lại Public State

→ Thông tin được đơn giản hóa từ private state trở lại public state.

Áp Dụng Vào LangGraph

1. Public State Schema
2. Private State Schema
3. Chuyển Đổi Giữa Các Trạng Thái

Tại Sao Điều Này Quan Trọng?

  1. Bảo Mật: Private state giúp che giấu logic nhạy cảm khỏi người dùng.

  2. Hiệu Suất: Tách biệt xử lý phức tạp khỏi giao diện người dùng.

  3. Dễ Bảo Trì: Thay đổi logic kỹ thuật mà không ảnh hưởng đến trải nghiệm người dùng.

Lời Khuyên Khi Áp Dụng

"LandGraph không chỉ dành cho siêu anh hùng - nó đơn giản nếu bạn hiểu cách tổ chức trạng thái!"

Kết Luận

Việc phân chia public/private state giống như cách một cửa hàng sửa chữa hoạt động:

Multiple State Schemas Qua Ví Dụ Cửa Hàng Sửa Máy Tính

1. Multiple State Schemas Là Gì?

Trong LangGraph, Multiple State Schemas (Đa lược đồ trạng thái) là cách phân chia trạng thái ứng dụng thành nhiều "lớp" khác nhau, mỗi lớp có:

Giống như một cửa hàng có khu vực bán hàng (public) và xưởng sửa chữa (private).

2. Áp Dụng Vào Ví Dụ Cửa Hàng Sửa Máy Tính

Schema 1: Public State Schema

(Khu vực tiếp tân)

Schema 2: Private State Schema

(Xưởng kỹ thuật)

3. Cách Chuyển Đổi Giữa Các State Schema

Quy Trình Xử Lý

  1. Public → Private (Node 1)

    • Nhận yêu cầu đơn giản từ khách

    • "Mở rộng" thành thông số kỹ thuật

    • def public_to_private(public_state):
          private_state = {
              'deviceId': lookup_device_id(public_state['device']),
              'diagnosticLogs': run_hardware_tests(),
              'repairPlan': generate_repair_options()
          }
          return private_state
  2. Private → Public (Node 2)

    • Tổng hợp kết quả kỹ thuật

    • "Rút gọn" thành thông báo dễ hiểu

    • def private_to_public(private_state):
          public_state_update = {
              'status': "Đã xác định lỗi",
              'solution': f"Thay {private_state['repairPlan'][0]['part']}",
              'cost': calculate_cost(private_state)
          }
          return public_state_update

4. Lợi Ích Của Multiple State Schemas

Tiêu Chí Public State Private State
Đối tượng Khách hàng Kỹ thuật viên
Độ phức tạp 1x (dễ hiểu) 1000x (chi tiết)
Bảo mật Ai cũng thấy Nội bộ
Ví dụ thực tế App Mobile Database + Microservices

Ưu điểm:

5. Sai Lầm Cần Tránh

  1. Nhồi nhét private state vào public
    → Làm người dùng bối rối với thông báo kiểu:
    "Lỗi 0x7F do sector 512 bị bad, cần remap cluster"

  2. Thiếu chuyển đổi giữa các schema
    → Dẫn đến mất mát thông tin khi giao tiếp giữa các thành phần

  3. Dùng chung schema cho mục đích khác nhau
    → Như bắt kỹ thuật viên dùng form đơn giản của khách để ghi chép

Câu Hỏi Thực Hành

Hãy thử thiết kế Multiple State Schemas cho các tình huống sau:

  1. Ứng dụng ngân hàng

    • Public: Số dư tài khoản

    • Private: Lịch sử giao dịch chi tiết + thuật toán chống gian lận

  2. Trợ lý ảo y tế

    • Public: Triệu chứng đơn giản ("Đau đầu 3 ngày")

    • Private: Dữ liệu EHR + mô hình chẩn đoán AI

💡 Mẹo: Luôn tự hỏi "Thông tin này có CẦN THIẾT cho người dùng cuối không?" khi thiết kế schema.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Memory (Bộ nhớ)

Thực hành Public State and Private State

1. Cài Đặt LangGraph

pip install langgraph

2. Triển Khai Code

from langgraph.graph import Graph
from typing import Dict, Any

# ======================================
# ĐỊNH NGHĨA SCHEMAS
# ======================================

# Public State Schema (Dành cho khách hàng)
PublicState = Dict[str, Any]  # Ví dụ: {'customer_name': 'John', 'problem': 'Không khởi động'}

# Private State Schema (Dành cho kỹ thuật viên)
PrivateState = Dict[str, Any]  # Ví dụ: {'diagnostics': ['lỗi ổ cứng', 'pin hỏng'], 'repair_cost': 200}

# ======================================
# ĐỊNH NGHĨA CÁC NODE
# ======================================

def receive_complaint(state: PublicState) -> Dict[str, Any]:
    """Node 1: Tiếp nhận yêu cầu từ khách hàng (Public State)"""
    print(f"🎤 Nhân viên nhận máy từ khách hàng: {state['customer_name']}")
    print(f"🔧 Vấn đề mô tả: {state['problem']}")
    return {"internal_note": f"Khách hàng {state['customer_name']} báo: {state['problem']}"}

def diagnose_problem(state: Dict[str, Any]) -> PrivateState:
    """Node 2: Chuyển sang Private State để chẩn đoán"""
    print("\n🔎 Kỹ thuật viên đang kiểm tra...")
    diagnostics = [
        "Test nguồn: OK",
        "Ổ cứng bị bad sector (LBA 1024-2048)",
        "Mainboard lỗi khe RAM"
    ]
    return {
        'diagnostics': diagnostics,
        'repair_cost': 350,
        'technician_notes': "Cần thay ổ cứng SSD 256GB + vệ sinh khe RAM"
    }

def summarize_report(state: PrivateState) -> PublicState:
    """Node 3: Chuyển kết quả về Public State cho khách hàng"""
    print("\n📝 Tổng hợp báo cáo đơn giản...")
    return {
        'customer_name': state['internal_note'].split()[2],  # Lấy tên từ internal_note
        'solution': "Thay ổ cứng SSD + bảo dưỡng",
        'cost': f"${state['repair_cost']}",
        'time_estimate': "2 ngày"
    }

# ======================================
# XÂY DỰNG GRAPH
# ======================================

workflow = Graph()

# Thêm các node vào graph
workflow.add_node("receive_complaint", receive_complaint)
workflow.add_node("diagnose_problem", diagnose_problem)
workflow.add_node("summarize_report", summarize_report)

# Kết nối các node
workflow.add_edge("receive_complaint", "diagnose_problem")
workflow.add_edge("diagnose_problem", "summarize_report")

# Biên dịch graph
chain = workflow.compile()

# ======================================
# CHẠY VÍ DỤ
# ======================================

# Khởi tạo Public State ban đầu
initial_state = {
    'customer_name': 'Nguyễn Văn A',
    'problem': 'Máy tính không lên nguồn',
    'status': 'received'
}

# Thực thi workflow
final_state = chain.invoke(initial_state)

# ======================================
# KẾT QUẢ
# ======================================
print("\n📢 Kết quả cuối cùng (Public State):")
print(final_state)

3. Giải Thích Hoạt Động

Luồng Dữ Liệu

20250423_5ef500.png

Kết Quả Khi Chạy
🎤 Nhân viên nhận máy từ khách hàng: Nguyễn Văn A
🔧 Vấn đề mô tả: Máy tính không lên nguồn

🔎 Kỹ thuật viên đang kiểm tra...

📝 Tổng hợp báo cáo đơn giản...

📢 Kết quả cuối cùng (Public State):
{
    'customer_name': 'Nguyễn',
    'solution': 'Thay ổ cứng SSD + bảo dưỡng',
    'cost': '$350',
    'time_estimate': '2 ngày'
}

4. Ghi nhớ

  1. Public State → Private State

    • Node 1 nhận thông tin đơn giản, Node 2 mở rộng thành dữ liệu kỹ thuật.

  2. Private State → Public State

    • Node 3 lọc bỏ chi tiết không cần thiết, chỉ giữ lại thông tin khách hàng cần biết.

  3. Ưu Điểm LangGraph

    • Dễ dàng mở rộng thêm node (vd: thêm node "Xác nhận thanh toán")

    • Tách biệt rõ ràng giữa các tầng logic.

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

 

 

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Trong quá trình xây dựng tác nhân AI với LangGraph, việc quản lý bộ nhớ hiệu quả và duy trì bộ nhớ lâu dài là hai yếu tố then chốt để đảm bảo ứng dụng vừa tiết kiệm chi phí vừa vận hành ổn định. Hiệu quả bộ nhớ giúp giảm lượng token tiêu thụ, tối ưu tốc độ phản hồi và chi phí sử dụng mô hình AI. Trong khi đó, khả năng lưu trữ bộ nhớ lâu dài (memory persistence) cho phép tác nhân ghi nhớ thông tin quan trọng giữa các phiên làm việc, tạo ra trải nghiệm thông minh và cá nhân hóa hơn cho người dùng. Bài viết này sẽ giới thiệu những kỹ thuật cơ bản và những lưu ý cần thiết khi triển khai hai yếu tố quan trọng này trong LangGraph.

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Giới thiệu

Trong phần này, chúng ta sẽ khám phá ba kỹ thuật rất thú vị.
Tuy nhiên, điều quan trọng nhất tôi muốn bạn ghi nhớ: Đừng để mình bị phân tâm.

Mục tiêu của tôi là bạn nắm chắc ý tưởngkhái niệm cốt lõi đằng sau mỗi kỹ thuật hoặc bài học này. Bạn không cần dành quá nhiều thời gian thực hành hoặc áp dụng ngay lập tức, bởi vì:

Đây cũng là một lời khuyên quan trọng mà bạn có thể áp dụng nhiều lần khi học hoặc nghiên cứu tài liệu kỹ thuật — ví dụ như tài liệu của LangGraph.

Cẩn Thận Với Những "Sự Phân Tâm" Khi Học Tài Liệu LangGraph

Khi bạn đọc tài liệu của LangGraph, sẽ có rất nhiều kỹ thuật nhỏ, thủ thuật đặc biệt hiện ra và thu hút sự chú ý.
Nếu không cẩn thận, bạn có thể dễ dàng:

Điều quan trọng là:
 - Hãy ghi nhận sự tồn tại của các kỹ thuật đó, hiểu sơ qua, nhưng đừng để chúng làm bạn chệch hướng.
 - Tiếp tục tập trung vào mục tiêu lớn: học cách xây dựng ứng dụng mạnh mẽ, thú vị và ấn tượng với LangGraph.

Nội dung bạn sẽ học ở phần này

Chúng ta sẽ tìm hiểu những kỹ thuật liên quan đến quản lý bộ nhớ trong ứng dụng LangGraph, cụ thể:

1. Tối ưu hóa chi phí sử dụng LLM

Bạn sẽ học một vài phương pháp để:

2. Giới thiệu về bộ nhớ dài hạn (Long-term Memory)

Chúng ta sẽ bắt đầu thảo luận về cách:

Một lời nhắc quan trọng

Như tôi đã nhấn mạnh:

Hãy nhớ rằng: việc xây dựng một ứng dụng mạnh mẽ, thú vị và chuyên nghiệp đòi hỏi bạn phải biết chọn lọc thông tin để tập trung.
Đừng để những chi tiết phụ đánh lạc hướng bạn khỏi mục tiêu lớn hơn!

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Tối Ưu Chi Phí và Quản Lý Bộ Nhớ Khi Xây Dựng Ứng Dụng AI Với OpenAI

Nếu bạn từng đọc các chương trước của chúng tôi, bạn sẽ biết rằng việc thực hành các bài tập sử dụng OpenAI API không hề tốn kém.
Thông thường, bạn chỉ tốn khoảng 5 đô la cho toàn bộ bootcamp trước, và con số này sẽ tương tự trong bootcamp này.

Tại sao chi phí lại thấp?
Vì chúng ta đang xây dựng các ứng dụng nhỏ gọn, số lượng người dùng hạn chế, tiêu thụ tài nguyên và token ở mức tối thiểu.
Tuy nhiên, khi bạn chuyển sang giai đoạn sản xuất thực tế với nhiều người dùng và ứng dụng lớn, chi phí có thể tăng đáng kể.

Bài học hôm nay sẽ giúp bạn:

Chi Phí Và Bộ Nhớ Trong Ứng Dụng AI

Khi vận hành AI agent:

Ví dụ:

OpenAI hay Open-Source?

Bạn có thể tự hỏi:

Bạn có thể làm vậy, đặc biệt ở giai đoạn thử nghiệm (beta, demo).
❌ Nhưng khi làm việc ở cấp độ chuyên nghiệp, OpenAI vẫn đang là tiêu chuẩn hiện tại (~99% doanh nghiệp dùng OpenAI).
Vì vậy, chúng tôi khuyên bạn nên thành thạo với OpenAI models.

Làm Thế Nào Để Giảm Chi Phí Bộ Nhớ?

Chúng ta sẽ học 2 kỹ thuật chính để giảm dung lượng "ba lô" của chatbot:

Kỹ thuật 1: Giới hạn số lượng tin nhắn lưu trong bộ nhớ

Ưu điểm: Giảm mạnh chi phí token.
Nhược điểm: Độ chính xác của chatbot có thể giảm nhẹ.

Kỹ thuật 2: Sử dụng bản tóm tắt thay cho toàn bộ tin nhắn

(Sẽ được học ở bài tiếp theo)

Ưu điểm: Bộ nhớ cực nhẹ, tiết kiệm chi phí.
Nhược điểm: Chatbot có thể không nhớ chi tiết đầy đủ.

Cách Thực Hiện Kỹ Thuật 1 Trong Thực Tế

Trong bài tập hôm nay, bạn sẽ thực hành:

Kết quả:
Bộ nhớ (backpack) nhẹ hơn → Chi phí token thấp hơn.

Lưu Ý Khi Áp Dụng

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Tối ưu hóa bộ nhớ ngắn hạn bằng cách tóm tắt hội thoại

Trong bài học trước, bạn đã học cách giảm số lượng tin nhắn trong bộ nhớ ngắn hạn để tiết kiệm token khi làm việc với mô hình ngôn ngữ.
Trong bài học này, chúng ta sẽ tìm hiểu một phương pháp thay thế: Tạo bản tóm tắt hội thoại thay vì lưu toàn bộ danh sách tin nhắn.

Tóm tắt hội thoại: Ý tưởng chính

Ưu điểm:

Nhược điểm:

Khi nào nên dùng tóm tắt hội thoại?

Ghi nhớ:
Hiệu suất và chi phí luôn cần cân bằng tùy vào mục tiêu dự án của bạn.

Cách triển khai

a. Cấu trúc State mới

Trong state của ứng dụng, ngoài khóa mặc định messages, bạn sẽ thêm một khóa mới:

state = {
    "messages": [...],
    "summary": "..."
}
b. Logic hoạt động
  1. Bắt đầu cuộc trò chuyện như bình thường.

  2. Khi số lượng tin nhắn trong bộ nhớ vượt quá ngưỡng (ví dụ: 6 tin nhắn), tạo hoặc cập nhật bản tóm tắt.

  3. Nếu chưa vượt ngưỡng, tiếp tục hội thoại bình thường.

Điều kiện:
Nếu len(messages) > 6 → tạo / cập nhật bản tóm tắt.

c. Các thành phần cần lập trình

Lưu ý khi thực thi

Tổng kết

Ghi nhớ

"Hiệu suất vs Chi phí luôn cần cân bằng. Hiểu kỹ các kỹ thuật ngay từ giai đoạn phát triển sẽ giúp bạn xây dựng các ứng dụng AI tối ưu và chuyên nghiệp hơn."

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Giới thiệu về Bộ nhớ Ngoài (Persistent Memory) với LangGraph

Tầm quan trọng của Bộ nhớ Ngoài

⚡️ Ghi nhớ: Hôm nay chỉ là giới thiệu ban đầu, chi tiết sâu hơn sẽ học trong các bài học tới.

Mục tiêu bài học

Bạn sẽ học cách:

Các bước thực hiện

1. Cài đặt SQLite
2. Tạo cơ sở dữ liệu bên ngoài

Lưu ý: Dấu ! trong notebook có nghĩa là chạy lệnh Terminal ngay trong notebook.

3. Kết nối với cơ sở dữ liệu
4. Thiết lập LangGraph với SQLite

Ứng dụng thực tế

Ghi chú quan trọng

Tổng kết nhanh

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

Hiệu quả bộ nhớ và khả năng lưu trữ bộ nhớ trong Agent LangGraph

Tóm tắt chương

Hãy nhớ những gì tôi đã nói trong tài liệu về LangGraph, bạn sẽ gặp rất nhiều thứ mà chúng ta có thể gọi là "cạm bẫy".

Những cạm bẫy cần tránh khi học LangGraph

Chúng tôi gọi chúng là cạm bẫy vì chúng thực sự là những yếu tố gây xao nhãng lớn. Mục tiêu của bạn khi học LangGraph là để tạo ra những agent AI ấn tượng, mạnh mẽ và thú vị. Tuy nhiên, khi đọc tài liệu LangGraph, bạn sẽ gặp rất nhiều yếu tố gây xao nhãng trước khi đạt được mục tiêu đó.

Theo chúng tôi, điều này có thể gây bất lợi vì:

Lời khuyên học tập hiệu quả

Khi tiếp cận tài liệu LangGraph, bạn sẽ gặp rất nhiều cạm bẫy như vậy. Do đó, lời khuyên của chúng tôi là:

  1. Đừng để bị xao nhãng

  2. Nắm vững các khái niệm chính trước

  3. Có thể quay lại nghiên cứu sâu các kỹ thuật sau khi đã xây dựng ứng dụng cơ bản

Ví dụ: Khi làm ứng dụng nâng cao, bạn có thể:

Các kỹ thuật đã học

  1. 3 kỹ thuật đơn giản giảm token usage:

    • Giảm số message lưu trong bộ nhớ ngắn hạn

    • Giảm số token sử dụng

    • Sử dụng các hàm reducer trong Python

  2. Phương pháp thay thế:

    • Lưu bản tóm tắt conversation thay vì toàn bộ message

    • Có thể đặt điều kiện (vd: tạo summary khi có >6 messages)

  3. Bộ nhớ ngoài/lâu dài:

    • Ví dụ đơn giản với SQLite database

    • Các kỹ thuật persistent memory

Lưu ý quan trọng: Đừng dừng lại quá lâu ở các kỹ thuật này! Hãy tiếp tục tiến lên và chỉ quay lại khi bạn thực sự cần áp dụng chúng để cải thiện ứng dụng cụ thể.

Chủ đề quan trọng sắp tới: Human-in-the-loop

Trong phần tiếp theo, chúng ta sẽ học về khái niệm cực kỳ quan trọng trong LangGraph: Human-in-the-loop. Bạn sẽ thấy:

Lời nhắc: Hãy tập trung cao độ cho phần tiếp theo này vì nó sẽ thực sự nâng tầm khả năng phát triển agent AI của bạn!LangGraph thực sự là framework mạnh mẽ nhưng để học hiệu quả, bạn cần:

  1. Xác định rõ mục tiêu (build agent cụ thể nào)

  2. Học theo cách "top-down": dùng trước, tối ưu sau

  3. Đừng sa đà vào micro-optimization quá sớm

  4. Tập trung vào các pattern quan trọng: agent collaboration, human feedback, memory management

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Phản hồi từ người dùng(Human Feedback)

Human Feedback, giúp bạn cải thiện agent theo thời gian, học từ hành vi và đánh giá của con người.

Phản hồi từ người dùng(Human Feedback)

Giới thiệu

Phần này chúng ta sẽ học những khái niệm cực kỳ quan trọng, nhưng xin lưu ý ngay từ đầu:

Lời khuyên học tập quan trọng

⚠️ Đây vẫn là phần kiến thức nền tảng trước khi xây dựng ứng dụng hoàn chỉnh. Tôi khuyên bạn không nên dành quá nhiều thời gian thực hành các bài tập trong phần này ngay lúc này, vì:

Khi đó bạn sẽ tự nhiên cảm thấy:

Vấn đề phổ biến khi học framework mới

Hầu hết tài liệu kỹ thuật (bao gồm cả LangGraph) đều chứa đầy "cạm bẫy" khiến bạn:

Khác biệt của cách tiếp cận này:

  1. Đơn giản hóa tài liệu gốc

  2. Định hướng lộ trình học đúng đắn

  3. Tập trung vào ứng dụng thực tế thay vì lý thuyết suông

2 điểm trọng tâm của phần này

1. Chuyển từ .invoke() sang .stream()

Ví dụ so sánh:

# Cách cũ
result = agent.invoke({"input": "Hello"})

# Cách mới
for chunk in agent.stream({"input": "Hello"}):
    # Xử lý từng phần
    print(chunk)
2. Xử lý stream data cho Human-in-the-loop

Bí mật lớn: Ứng dụng AI hiện nay vẫn chưa thực sự "thông minh" hoàn toàn. Chúng cần con người để đạt hiệu suất tối đa (thường tăng thêm 5-20% chất lượng).

3 hướng tác động chính của Human-in-the-loop:

  1. Phê duyệt/ từ chối các bước tiếp theo của ứng dụng

  2. Điều chỉnh trạng thái hệ thống

  3. Gỡ lỗi ứng dụng trong thời gian thực

Ví dụ thực tế:

for chunk in agent.stream(conversation):
    if needs_human_review(chunk):
        human_feedback = get_human_input()
        agent.adjust_based_on_feedback(human_feedback)

Bổ sung quan trọng từ tôi

LangGraph thực sự tỏa sáng khi kết hợp:

Lời khuyên:

  1. Tập trung hiểu cơ chế stream

  2. Ghi chú các trường hợp cần human feedback

  3. Đừng sa đà vào tối ưu hóa chi tiết

  4. Chuẩn bị tinh thần cho phần human-in-the-loop sắp tới

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Phản hồi từ người dùng(Human Feedback)

Streaming và Human-in-the-loop trong LangGraph

Streaming = "Truyền liên tục", nghĩa là agent hoặc LLM sẽ trả về kết quả dần dần, theo dòng, chứ không phải chờ tính toán xong mới gửi hết.

Thuật ngữ Ý nghĩa Ví dụ thực tế
Streaming Values Nhận các giá trị từng phần Từng đoạn text của câu trả lời
Streaming Updates Các bản cập nhật của 1 giá trị ban đầu Đang xử lý... Đã hoàn thành
Ví dụ đơn giản:

Giả sử bạn có một AI Agent thực hiện tóm tắt 1 tài liệu lớn.

Bạn nhận được dòng text đầu tiên nhanh chóng, sau đó nhiều bản cập nhật liên tiếp.

Ví dụ cụ thể bằng Python (giả lập):

import time

# Streaming giá trị ban đầu
def stream_value():
    print("📥 Loading document...")
    time.sleep(1)
    yield "✅ Step 1: Read Chapter 1"

    time.sleep(2)
    yield "✅ Step 2: Read Chapter 2"

    time.sleep(1)
    yield "✅ Step 3: Summarizing Chapters"

# Xử lý streaming
for value in stream_value():
    print(f"📡 Received update: {value}")

Kết quả

Loading document...
Received update: ✅ Step 1: Read Chapter 1
Received update: ✅ Step 2: Read Chapter 2
Received update: ✅ Step 3: Summarizing Chapters
Ví dụ đơn giản về cách streaming câu trả lời trong chatbot
Tình huống:

Người dùng hỏi: "Tóm tắt tác phẩm Dế Mèn Phiêu Lưu Ký"

Ta sẽ cho chatbot trả lời dần dần (streaming) theo từng câu hoặc từng đoạn văn bản.

Ví dụ Python (giả lập):

import time

def chatbot_streaming_response():
    yield "Dế Mèn Phiêu Lưu Ký là tác phẩm nổi tiếng của nhà văn Tô Hoài."
    time.sleep(1)

    yield "Tác phẩm kể về hành trình phiêu lưu của chú dế Mèn thông minh, gan dạ và thích khám phá."
    time.sleep(1)

    yield "Trong hành trình đó, dế Mèn đã học được nhiều bài học quý giá về tình bạn, lòng dũng cảm và sự trưởng thành."
    time.sleep(1)

    yield "Tác phẩm không chỉ hấp dẫn thiếu nhi mà còn chứa đựng nhiều triết lý sống sâu sắc."
    time.sleep(1)

# Giả lập chatbot gửi từng đoạn
for chunk in chatbot_streaming_response():
    print(f"💬 {chunk}")

Kết quả mô phỏng trên terminal:

💬 Dế Mèn Phiêu Lưu Ký là tác phẩm nổi tiếng của nhà văn Tô Hoài.
💬 Tác phẩm kể về hành trình phiêu lưu của chú dế Mèn thông minh, gan dạ và thích khám phá.
💬 Trong hành trình đó, dế Mèn đã học được nhiều bài học quý giá về tình bạn, lòng dũng cảm và sự trưởng thành.
💬 Tác phẩm không chỉ hấp dẫn thiếu nhi mà còn chứa đựng nhiều triết lý sống sâu sắc.

Sự khác biệt chính giữa .invoke().stream()

Đặc điểm .invoke() .stream()
Cách hoạt động Gọi toàn bộ chain hoặc agent và chờ kết quả Trả về kết quả từng phần một (token, chunk, etc.)
Tốc độ phản hồi Trả lời sau khi xử lý xong toàn bộ Trả lời gần như ngay lập tức, theo thời gian thực
Trường hợp sử dụng Tốt cho các xử lý ngắn hoặc không cần realtime Lý tưởng cho chatbot, UI realtime, hoặc truyền dữ liệu
Trả về Toàn bộ output cùng lúc (ví dụ một string) Một generator (yield từng phần kết quả)
Tích hợp UI Không thể hiện đang gõ Có thể hiện đang gõ như ChatGPT

Lời khuyên thực tế khi triển khai

  1. Ưu tiên dùng stream_mode="values" khi phát triển để dễ debug

  2. Chỉ chuyển sang "updates" khi ứng dụng đã ổn định và cần tối ưu hiệu suất

  3. Luôn thiết kế các "điểm kiểm soát" (checkpoints) cho human-in-the-loop tại:

    • Bước ra quyết định quan trọng

    • Khi cần xác nhận tính chính xác

    • Khi agent không chắc chắn

  4. Xử lý lỗi thông minh:

try:
    for chunk in agent.stream(...):
        process(chunk)
except HumanInterventionRequired as e:
    handle_exception(e)
    wait_for_human_decision()

Bổ sung kiến thức quan trọng

Tại sao .stream() mạnh mẽ hơn?

Pattern hay gặp:

# Hybrid approach - Kết hợp cả invoke và stream khi cần
if is_simple_task(task):
    return agent.invoke(task)
else:
    return process_stream(agent.stream(task))

Hãy coi .stream() như "cửa sổ vào bộ não" của agent - bạn có thể quan sát và can thiệp vào quá trình xử lý theo cách chưa từng có với .invoke() thông thường!

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

Phản hồi từ người dùng(Human Feedback)

Breakpoints và Human-in-the-loop trong LangGraph

Breakpoint là gì?

Một breakpoint trong LangGraph cho phép bạn tạm dừng workflow tại một node (bước), từ đó bạn có thể:

Cách hoạt động

Khi một node có breakpoint, LangGraph sẽ trả về trạng thái tạm thời (trạng thái dừng), và bạn có thể tiếp tục thực thi bằng cách gọi .invoke() hoặc .stream() lại với trạng thái đã cập nhật.

Ví dụ đơn giản: Breakpoint ở một bước LLM

1. Khởi tạo LangGraph
from langgraph.graph import StateGraph, END
from langchain_core.runnables import RunnableLambda

# Bước 1: Xử lý văn bản
def process_text(state):
    text = state["input"]
    return {"processed": text.upper()}

# Bước 2: Tổng kết
def summarize(state):
    return {"summary": f"Summary: {state['processed']}"}

graph = StateGraph()

# Thêm node và breakpoints
graph.add_node("process", RunnableLambda(process_text))
graph.add_node("summarize", RunnableLambda(summarize))

graph.set_entry_point("process")
graph.add_edge("process", "summarize")
graph.add_edge("summarize", END)

# Gắn breakpoint vào bước "summarize"
graph.add_conditional_edges("summarize", lambda x: "__break__")

app = graph.compile()
2. Gọi invoke() và dừng tại breakpoint
state = app.invoke({"input": "Hello LangGraph!"})
print(state)

Output sẽ không kết thúc workflow, mà dừng tại node "summarize" vì có breakpoint.

3. Kiểm tra hoặc chỉnh sửa rồi tiếp tục
# Bạn có thể chỉnh sửa state nếu muốn
state["processed"] = "HELLO LANGGRAPH! (edited)"

# Tiếp tục từ breakpoint
final = app.invoke(state)
print(final)

Khi nào nên dùng breakpoints?

Tình huống Có nên dùng không?
Debug từng bước của graph
Thêm bước xác nhận từ người dùng
Gửi yêu cầu API cần kiểm tra trước
Tự động hóa hoàn toàn không kiểm tra ❌ Không cần

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

OpenAI Agent SDK

OpenAI Agent SDK

Giới thiệu

OpenAI Agent SDK là một bộ công cụ được OpenAI cung cấp (dự kiến chính thức vào năm 2024–2025), cho phép các nhà phát triển xây dựng, triển khai và điều phối “AI agents” — tức là các tác nhân trí tuệ nhân tạo có khả năng thực hiện các hành động phức tạp dựa trên lời nhắc của người dùng hoặc mục tiêu cụ thể.

1. OpenAI Agent là gì?

Một agent là một mô hình AI có khả năng:

2. Agent SDK hỗ trợ gì?

OpenAI Agent SDK giúp bạn:

Tính năng chính Mô tả
Định nghĩa tác vụ (task) Cho phép bạn mô tả hành vi của agent bằng ngôn ngữ tự nhiên + mã Python
Tích hợp công cụ (tools) Agent có thể gọi các tool như API, function, file, browser...
Quản lý vòng phản hồi Agent tự động học từ kết quả sai và điều chỉnh lời nhắc hoặc hành động
Triển khai dễ dàng Có thể chạy trên local hoặc tích hợp vào app web, CLI, backend

3. Cách hoạt động (tóm tắt luồng)

  1. Bạn định nghĩa nhiệm vụ → bằng một đoạn mô tả (natural language).

  2. Gán các công cụ (tools) mà agent có thể dùng.

  3. Agent suy nghĩ và ra quyết định từng bước (plan → act → observe).

  4. Kết quả cuối cùng được tổng hợp và trả về.

OpenAI Agent SDK

3 Bước với OpenAI Agents SKD

  1. Create an instance of Agent
  2. Use with trace() to track the agent
  3. Call runner.run() to run the agent

Bước 1: Tạo một instance của Agent

Đây là bước bạn định nghĩa “nhân vật AI” của mình: mục tiêu, hướng dẫn, và các công cụ mà agent có thể sử dụng.

from openai import Agent

agent = Agent(
    instructions="Bạn là một trợ lý giúp người dùng tóm tắt các tệp văn bản.",
    tools=[file_reader_tool, summarizer_tool],  # các công cụ được phép gọi
)

Bước 2: Dùng with trace() để theo dõi quá trình

Sử dụng trace() sẽ giúp bạn ghi lại và quan sát mọi hành động mà agent thực hiện, rất hữu ích cho việc debug hoặc đánh giá hiệu suất.

from openai import trace

with trace():
    ...

Bước 3: Gọi runner.run() để chạy agent

Tạo một runner từ agent, sau đó gọi .run(input) để gửi tác vụ cho agent thực hiện.

runner = agent.runner()
output = runner.run("Tóm tắt nội dung của tệp report.txt giúp tôi.")
print(output)

Tóm tắt quy trình

from openai import Agent, trace

# B1: Tạo Agent
agent = Agent(
    instructions="Bạn là trợ lý giúp phân tích dữ liệu CSV.",
    tools=[csv_loader, data_analyzer],
)

# B2: Theo dõi agent
with trace():
    # B3: Chạy agent
    runner = agent.runner()
    result = runner.run("Hãy tính trung bình doanh thu theo quý từ file doanhthu.csv.")
    print(result)

 

OpenAI Agent SDK

OpenAI Agent SDK vs. LangGraph

Tiêu chí OpenAI Agent SDK LangGraph
Mục đích chính Xây dựng AI agent hoạt động theo mục tiêu, có hành vi linh hoạt Xây dựng biểu đồ luồng logic (graph) để điều phối các bước xử lý AI
Cơ chế hoạt động Agent tự động lập kế hoạch, ra quyết định, gọi tools Bạn phải định nghĩa rõ ràng các nút (nodes) và đường đi (edges)
Kiểm soát logic Tốt ở cấp nhiệm vụ tổng quát (goal-based) Tốt ở cấp workflow chi tiết, rẽ nhánh, vòng lặp, tái thử...
Định nghĩa tool Dễ, chỉ cần khai báo Python function là xong Cần cấu hình trong node và wiring logic phức tạp hơn
Hỗ trợ vòng lặp / retry Có nhưng hạn chế trong logic sâu phức tạp Cực mạnh: hỗ trợ vòng lặp, điều kiện rẽ nhánh, memory graph rõ ràng
Tính modular / tái sử dụng Ở mức hàm hoặc agent instance Có thể thiết kế thành sub-graph, dùng lại nhiều nơi
Quan sát & debug trace() đơn giản, tập trung vào hành vi agent Rõ ràng từng bước qua graph — dễ kiểm soát từng node
Thư viện sử dụng openai SDK (chính thức từ OpenAI) langgraph (xây dựng trên LangChain)
Trường hợp dùng tốt nhất Xây AI assistant tự chủ động hành động như ChatGPT plugins Xây workflow phức tạp và logic xác định như quá trình xử lý yêu cầu nhiều bước

Nói ngắn gọn:

Nhiệm vụ Nên dùng gì?
“Giúp tôi phân tích file Excel, vẽ biểu đồ và gửi qua email” → Agent tự xử lý ✅ OpenAI Agent SDK
“Lập quy trình xử lý yêu cầu bảo hành qua 4 bước: xác minh → báo giá → gửi email → cập nhật CRM” ✅ LangGraph
OpenAI Agent SDK

Agent, Runner, and Trace Classes

1. Agent – Bộ não của hệ thống

Vai trò:

Đây là nơi bạn định nghĩa hành vi của agent:

Cách dùng:
from openai import Agent

agent = Agent(
    instructions="Bạn là trợ lý chuyên đọc hóa đơn và trả lời câu hỏi về chúng.",
    tools=[invoice_parser, pdf_reader],
)

2. Runner – Bộ máy thực thi nhiệm vụ

Vai trò:

Là một instance hoạt động của Agent, cho phép bạn gọi .run() để xử lý một tác vụ cụ thể.

Mỗi khi bạn muốn agent xử lý một yêu cầu đầu vào, bạn tạo một runner từ agent, rồi gọi runner.run(input).

Cách dùng:
runner = agent.runner()
output = runner.run("Đọc hóa đơn.pdf và cho biết tổng số tiền.")

3. trace() – Công cụ giám sát

Vai trò:

Dùng để theo dõi toàn bộ quá trình suy luận và hành động của agent:

Cách dùng:
from openai import trace

with trace():
    runner = agent.runner()
    result = runner.run("Phân tích file dữ liệu tài chính.xlsx")

Có thể tích hợp với giao diện trực quan của OpenAI để xem toàn bộ flow tác vụ.

Tóm tắt mối quan hệ:

graph TD;
    Agent[Agent: Định nghĩa hành vi và tools]
    Runner[Runner: Gọi tác vụ cụ thể qua .run()]
    Trace[trace(): Ghi log toàn bộ quá trình]

    Agent --> Runner
    Runner -->|run(input)| Task[Thực hiện tác vụ]
    Trace --> Runner

 

OpenAI Agent SDK

Vibe Coding - Lập Trình Theo Cảm Hứng với AI

Vibe Coding là gì?

Tuy nhiên, nếu không cẩn thận, bạn dễ bị AI "dẫn lối sai" → code rối, khó debug.

5 Bí Kíp "Vibe Coding" Hiệu Quả

1. "Good Vibes" - Prompt Chất Lượng
2. "Vibe but Verify" - Kiểm Tra Chéo
3. "Step Up the Vibe" - Chia Nhỏ Vấn Đề
4. "Vibe and Validate" - Kiểm Tra Logic
5. "Vibe with Variety" - Đa Dạng Giải Pháp

Lời Khuyên

OpenAI Agent SDK

Core Concepts for AI Development

Dưới đây là phần giới thiệu tổng quan về Core Concepts for AI Development – những khái niệm nền tảng bạn cần hiểu để phát triển hệ thống AI hiện đại, đặc biệt là các ứng dụng sử dụng LLM (Large Language Models):

1. Foundation Models (FM)

mô hình học sâu được huấn luyện trên lượng dữ liệu cực lớn, dùng được cho nhiều tác vụ khác nhau:

2. Prompt Engineering

Là nghệ thuật thiết kế câu lệnh đầu vào (prompt) để dẫn dắt LLM trả lời theo ý bạn.

🔹 Ví dụ:

Bạn là chuyên gia tài chính. Hãy phân tích bảng sau và tóm tắt kết quả.

3. Tool Use / Function Calling

LLM có thể được kết nối với các công cụ bên ngoài như:

📦 Trong OpenAI, ta dùng functions= hoặc tools= để định nghĩa các công cụ cho agent.

4. Memory / Context Management

LLM không có "trí nhớ dài hạn" tự nhiên. Để xây dựng hội thoại dài, ta cần:

🔸 Framework hỗ trợ: LangChain, Semantic Kernel...

5. Agentic Reasoning

Là khả năng để LLM tự đưa ra kế hoạch, chọn công cụ, thực thi nhiều bước – như một "agent thông minh".

Ví dụ:

📦 Hỗ trợ bởi:

6. Retrieval-Augmented Generation (RAG)

Kết hợp kiến thức bên ngoài (từ database, PDF, Notion...) vào LLM để trả lời chính xác hơn.

▶️ Quy trình:

  1. Index tài liệu thành vector

  2. Nhận truy vấn → tìm đoạn liên quan

  3. Ghép vào prompt → trả về kết quả

7. Evaluation & Tracing

Cần kiểm tra chất lượng kết quả AI:

8. Workflow Design Patterns

Kết hợp các pattern như:

Tùy bài toán mà chọn pattern phù hợp (đọc tài liệu, hỏi-đáp, xử lý file...)

 

 

OpenAI Agent SDK

Tạo 3 agent bán hàng với phong cách giao tiếp khác nhau

1. Cài đặt (nếu chưa có):

pip install openai

2. Code: Tạo 3 Agents bán hàng

from openai import AssistantEventHandler, Agent, trace

# Agent 1: Chuyên nghiệp, nghiêm túc
agent_professional = Agent(
    name="Professional Sales Agent",
    instructions="""
    Bạn là một chuyên viên bán hàng chuyên nghiệp, nói chuyện lịch sự, nghiêm túc và rõ ràng. 
    Luôn cung cấp thông tin đầy đủ, chính xác, và giữ thái độ tôn trọng tuyệt đối với khách hàng.
    """,
    model="gpt-4o-mini"
)

# Agent 2: Hài hước, thu hút
agent_funny = Agent(
    name="Professional Sales Agent",
    instructions="""
    Bạn là một chuyên viên bán hàng với phong cách hài hước, vui tính. 
    Luôn pha trò nhẹ nhàng để khiến khách hàng cảm thấy thoải mái, nhưng vẫn truyền đạt được thông tin bán hàng rõ ràng.""",
    model="gpt-4o-mini"
)

# Agent 3: Ngắn gọn, đi thẳng vào vấn đề
agent_direct = Agent(
    name="Professional Sales Agent",
    instructions="""
    Bạn là một chuyên viên bán hàng nói chuyện nhanh, ngắn gọn, đi thẳng vào trọng tâm. 
    Tránh nói vòng vo và luôn cung cấp câu trả lời súc tích.
    """,
    model="gpt-4o-mini"
)

3. Cách chạy các agent

# Một ví dụ input từ khách hàng
input_text = "Sản phẩm của bạn có bảo hành không?"

# Dùng trace để theo dõi quá trình
with trace():
    runner1 = agent_professional.runner()
    runner2 = agent_funny.runner()
    runner3 = agent_direct.runner()

    result1 = runner1.run(input_text)
    result2 = runner2.run(input_text)
    result3 = runner3.run(input_text)

    print("Agent Chuyên Nghiệp:", result1)
    print("Agent Hài Hước:", result2)
    print("Agent Ngắn Gọn:", result3)

Kết quả (ví dụ mong đợi)

Agent Phong cách phản hồi
Chuyên nghiệp "Dạ vâng, sản phẩm của chúng tôi được bảo hành chính hãng 12 tháng..."
 Hài hước "Có chứ! Chúng tôi bảo hành 12 tháng – đủ lâu để bạn... quên luôn ngày mua 😄"
Ngắn gọn "Có. Bảo hành 12 tháng."

OpenAI Agent SDK

Tạo 3 Agents bán hàng theo kiểu luồng (streaming)

Rất hữu ích khi bạn muốn xử lý kết quả theo thời gian thực, ví dụ: hiển thị từng dòng chat ngay khi mô hình sinh ra.

import asyncio
from openai import Agent, trace

# 1. Khởi tạo các agent với phong cách khác nhau
agent_professional = Agent(
    instructions="""
    Bạn là một chuyên viên bán hàng chuyên nghiệp, lịch sự và nghiêm túc.
    Trả lời chi tiết, rõ ràng, có cấu trúc.
    """
)

agent_funny = Agent(
    instructions="""
    Bạn là một nhân viên bán hàng hài hước, vui vẻ. Hãy làm khách hàng bật cười nhưng vẫn hiểu vấn đề.
    """
)

agent_direct = Agent(
    instructions="""
    Bạn là một chuyên viên bán hàng ngắn gọn, súc tích. Trả lời đúng trọng tâm, không vòng vo.
    """
)

# 2. Hàm chạy một agent và in kết quả theo từng đoạn (stream)
async def stream_agent(agent, input_text, label):
    print(f"\n============================")
    print(f"💬 {label} ĐANG TRẢ LỜI:\n")
    
    runner = agent.runner()
    async for chunk in runner.run_stream(input_text):
        print(chunk.delta, end="", flush=True)
    
    print("\n============================")

# 3. Hàm chính: chạy từng agent lần lượt
async def main():
    input_text = "Tôi đang tìm mua một chiếc laptop để thiết kế đồ họa chuyên nghiệp. Bạn có thể tư vấn không?"

    with trace():
        await stream_agent(agent_professional, input_text, "🎩 Agent CHUYÊN NGHIỆP")
        await stream_agent(agent_funny, input_text, "😄 Agent HÀI HƯỚC")
        await stream_agent(agent_direct, input_text, "⚡ Agent NGẮN GỌN")

# 4. Thực thi
asyncio.run(main())

Kết quả mong đợi (mô phỏng):

💬 🎩 Agent CHUYÊN NGHIỆP ĐANG TRẢ LỜI:

Chào anh/chị, cảm ơn anh/chị đã quan tâm đến sản phẩm của chúng tôi. 
Đối với nhu cầu thiết kế đồ họa chuyên nghiệp, tôi xin đề xuất các mẫu laptop có GPU rời, RAM từ 16GB trở lên...

💬 😄 Agent HÀI HƯỚC ĐANG TRẢ LỜI:

Whoa, bạn là designer à? Chắc chắn rồi! Bạn sẽ cần một con laptop mạnh mẽ – kiểu như “siêu nhân có card đồ họa” ấy 😆. 

💬 ⚡ Agent NGẮN GỌN ĐANG TRẢ LỜI:

Có. Dùng MacBook Pro M3 hoặc Dell XPS 15. RAM 16GB, GPU rời. Đủ mạnh.

 

 

OpenAI Agent SDK

Agent trong OpenAI Agent SDK để gọi dữ liệu sản phẩm từ một API thật(Tool)

Dưới đây là hướng dẫn và ví dụ thêm một "Tool" vào mỗi Agent trong OpenAI Agent SDK để gọi dữ liệu sản phẩm từ một API thật (hoặc mô phỏng).

Mục tiêu

Thêm một tool có thể gọi API để lấy danh sách laptop phù hợp, và cho phép các agent dùng tool này trong quá trình phản hồi người dùng.

1. Giả lập Tool gọi API

Đầu tiên, bạn cần định nghĩa một tool dưới dạng Python function – nó nên có docstring đầy đủ để agent hiểu cách dùng.

from openai import tool

@tool
def get_laptop_suggestions(purpose: str) -> list:
    """
    Trả về danh sách gợi ý laptop phù hợp với mục đích sử dụng.

    Args:
        purpose (str): Mục đích sử dụng, ví dụ: "thiết kế đồ họa", "lập trình", "văn phòng".

    Returns:
        list: Danh sách các laptop phù hợp, mỗi cái là một chuỗi mô tả.
    """
    # Đây là dữ liệu mô phỏng. Bạn có thể thay bằng gọi tới API thật.
    database = {
        "thiết kế đồ họa": [
            "MacBook Pro 16 M3 Max - 64GB RAM, GPU mạnh",
            "Dell XPS 17 - Intel i9, RTX 4070, màn 4K",
            "Asus ROG Studio - Ryzen 9, RAM 32GB, GPU RTX"
        ],
        "lập trình": [
            "MacBook Air M2 - nhẹ, pin lâu",
            "Lenovo ThinkPad X1 Carbon",
            "Dell XPS 13 - nhỏ gọn, hiệu năng tốt"
        ]
    }
    return database.get(purpose.lower(), ["Không tìm thấy laptop phù hợp"])

2. Gắn Tool này vào Agent

from openai import Agent

agent_professional = Agent(
    instructions="Bạn là nhân viên bán hàng chuyên nghiệp, lịch sự. Hãy tư vấn đúng mục tiêu khách hàng.",
    tools=[get_laptop_suggestions],
)

agent_funny = Agent(
    instructions="Bạn tư vấn với phong cách hài hước. Hãy làm khách hàng vui vẻ nhưng vẫn đúng mục tiêu.",
    tools=[get_laptop_suggestions],
)

agent_direct = Agent(
    instructions="Bạn tư vấn ngắn gọn, đúng trọng tâm. Không vòng vo.",
    tools=[get_laptop_suggestions],
)

3. Chạy Agent với run_stream()

async def stream_agent(agent, input_text, label):
    print(f"\n💬 {label} đang trả lời:\n")
    runner = agent.runner()
    async for chunk in runner.run_stream(input_text):
        print(chunk.delta, end="", flush=True)
    print("\n---------------------------")

Ví dụ gọi Agent

async def main():
    input_text = "Tôi cần mua laptop để thiết kế đồ họa. Tư vấn giúp tôi."

    with trace():
        await stream_agent(agent_professional, input_text, "🎩 CHUYÊN NGHIỆP")
        await stream_agent(agent_funny, input_text, "😄 HÀI HƯỚC")
        await stream_agent(agent_direct, input_text, "⚡ NGẮN GỌN")

asyncio.run(main())

Agent có thể tự động gọi get_laptop_suggestions(), ví dụ:

🎩 CHUYÊN NGHIỆP đang trả lời:

Dựa trên nhu cầu "thiết kế đồ họa", tôi gợi ý bạn những mẫu laptop sau:
- MacBook Pro 16 M3 Max - 64GB RAM, GPU mạnh
- Dell XPS 17 - Intel i9, RTX 4070, màn 4K
- Asus ROG Studio - Ryzen 9, RAM 32GB, GPU RTX

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

OpenAI Agent SDK

AI Sales Agents sử dụng OpenAI Agent SDK, SendGrid để gửi email chào hàng

Dưới đây là một hướng dẫn chi tiết để bạn có thể xây dựng hệ thống AI Sales Agents sử dụng OpenAI Agent SDK, SendGrid để gửi email chào hàng, và cộng tác nhiều agent với vai trò khác nhau trong một phiên làm việc.

Mục tiêu:

Xây dựng 3 AI Sales Agents có thể:

  1. Trò chuyện với khách hàng.

  2. Gọi tool lấy sản phẩm phù hợp.

  3. Gửi email giới thiệu sản phẩm (qua SendGrid).

  4. Hợp tác với nhau để tối ưu trải nghiệm khách hàng.

Yêu cầu:

Cấu trúc tổng thể:

.
├── main.py
├── tools.py         # chứa các tool: lấy sản phẩm, gửi email
├── agents.py        # định nghĩa các agent
├── .env             # lưu API key
  1. Cài đặt thư viện
    pip install openai sendgrid python-dotenv

  2. tools.py: Định nghĩa tool gọi sản phẩm + gửi email
    from openai import tool
    from sendgrid import SendGridAPIClient
    from sendgrid.helpers.mail import Mail
    import os
    
    @tool
    def get_sales_products(category: str) -> list:
        """
        Gợi ý danh sách sản phẩm phù hợp với danh mục được yêu cầu.
        """
        db = {
            "laptop": ["MacBook Pro M3", "Dell XPS 15", "Asus ZenBook"],
            "smartphone": ["iPhone 15", "Samsung S24", "Google Pixel 8"]
        }
        return db.get(category.lower(), ["Không tìm thấy sản phẩm phù hợp"])
    
    @tool
    def send_sales_email(to_email: str, subject: str, content: str) -> str:
        """
        Gửi email giới thiệu sản phẩm cho khách hàng.
        """
        sg = SendGridAPIClient(os.getenv("SENDGRID_API_KEY"))
        message = Mail(
            from_email="your-email@example.com",
            to_emails=to_email,
            subject=subject,
            html_content=content,
        )
        response = sg.send(message)
        return f"Đã gửi email đến {to_email} (status {response.status_code})"

  3. .env: Lưu API Key
    SENDGRID_API_KEY=SG.xxxxxxxx

  4. agents.py: Khai báo các Agent
    from openai import Agent
    from tools import get_sales_products, send_sales_email
    
    agent_professional = Agent(
        instructions="Bạn là nhân viên bán hàng chuyên nghiệp. Hãy giúp khách hàng chọn sản phẩm và gửi email.",
        tools=[get_sales_products, send_sales_email],
    )
    
    agent_funny = Agent(
        instructions="Bạn tư vấn sản phẩm với phong cách hài hước và sáng tạo. Có thể gửi email cho khách.",
        tools=[get_sales_products, send_sales_email],
    )
    
    agent_direct = Agent(
        instructions="Bạn trả lời ngắn gọn và đi thẳng vào vấn đề. Tư vấn đúng trọng tâm và gửi email nhanh chóng.",
        tools=[get_sales_products, send_sales_email],
    )

  5. main.py: Thực thi và tương tác agent
    import asyncio
    from dotenv import load_dotenv
    from openai import trace
    from agents import agent_professional, agent_funny, agent_direct
    
    load_dotenv()
    
    async def run_agent(agent, input_text):
        runner = agent.runner()
        async for chunk in runner.run_stream(input_text):
            print(chunk.delta, end="", flush=True)
        print("\n------------------")
    
    async def main():
        input_text = "Khách hàng muốn mua laptop và nhận email tại khachhang@example.com"
    
        with trace():
            print("🎩 CHUYÊN NGHIỆP:")
            await run_agent(agent_professional, input_text)
    
            print("😄 HÀI HƯỚC:")
            await run_agent(agent_funny, input_text)
    
            print("⚡ NGẮN GỌN:")
            await run_agent(agent_direct, input_text)
    
    asyncio.run(main())

  6. Ví dụ kết quả Agent có thể tạo ra:
    Xin chào! Tôi gợi ý các laptop sau:
    - MacBook Pro M3
    - Dell XPS 15
    - Asus ZenBook
    
    Tôi sẽ gửi danh sách này qua email cho bạn tại khachhang@example.com nhé.
    → Đã gửi email đến khachhang@example.com (status 202)
    • Agents tự gọi tool để lấy danh sách sản phẩm.

    • Tự động gửi email bán hàng thông qua SendGrid.

    • Phân vai linh hoạt: chuyên nghiệp – hài hước – ngắn gọn.


Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

OpenAI Agent SDK

Xây Dựng Hệ Thống Sales Agent Thông Minh với OpenAI SDK

Trong OpenAI Agent SDK, bạn có thể biến một Agent thành một Tool, nghĩa là Agent này có thể được gọi bởi Agent khác như một công cụ chuyên trách — mở ra khả năng phối hợp nhiều Agent để tự động hóa quy trình bán hàng thông minh.

Ý tưởng:

image.png

Cập nhật code: Biến Agent thành Tool

Bước 1: Cập nhật agents.py
from openai import Agent
from tools import get_sales_products, send_sales_email

# 3 agents như trước
agent_professional = Agent(
    instructions="Bạn là nhân viên bán hàng chuyên nghiệp. Hãy viết email chào hàng chuyên nghiệp và gửi đi.",
    tools=[get_sales_products, send_sales_email],
)

agent_funny = Agent(
    instructions="Bạn là nhân viên bán hàng hài hước. Hãy viết email sáng tạo và vui nhộn để thu hút khách hàng.",
    tools=[get_sales_products, send_sales_email],
)

agent_direct = Agent(
    instructions="Bạn là nhân viên bán hàng ngắn gọn. Hãy viết email ngắn, đúng trọng tâm và gửi đi.",
    tools=[get_sales_products, send_sales_email],
)

# Biến các Agent thành công cụ
tool_professional = agent_professional.as_tool(
    name="SalesAgentProfessional",
    description="Viết email chào hàng chuyên nghiệp và gửi đi"
)

tool_funny = agent_funny.as_tool(
    name="SalesAgentFunny",
    description="Viết email chào hàng hài hước và gửi đi"
)

tool_direct = agent_direct.as_tool(
    name="SalesAgentDirect",
    description="Viết email chào hàng ngắn gọn, đi thẳng vào vấn đề và gửi đi"
)
Bước 2: Tạo Agent Điều Phối (Orchestrator)
orchestrator = Agent(
    instructions="""
    Bạn là điều phối viên bán hàng. Tùy theo phong cách khách hàng yêu cầu, hãy gọi đúng agent tương ứng
    để viết email chào hàng và gửi đi.
    """,
    tools=[tool_professional, tool_funny, tool_direct]
)
Bước 3: Tự động chạy Agent Điều Phối trong main.py
import asyncio
from dotenv import load_dotenv
from openai import trace
from agents import orchestrator

load_dotenv()

async def run_orchestration():
    customer_input = """
    Khách hàng muốn mua smartphone. Gửi email tới hoang@example.com.
    Phong cách: hài hước.
    """
    runner = orchestrator.runner()
    async for chunk in runner.run_stream(customer_input):
        print(chunk.delta, end="", flush=True)

asyncio.run(run_orchestration())

Kết quả kỳ vọng:

Orchestrator phân tích đầu vào:

"Phong cách: hài hước"
→ Gọi tool_funny
→ Gọi get_sales_products("smartphone")
→ Soạn email hài hước
→ Gọi send_sales_email()
→ Trả kết quả

Lợi ích:

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

OpenAI Agent SDK

Agent as Tool và Handoff

Trong OpenAI Agents SDK, "Agent as Tool""Handoff" là hai khái niệm quan trọng giúp xây dựng quy trình cộng tác linh hoạt giữa các agent. Dưới đây là giải thích chi tiết:

1. "Agent as Tool" – Biến Agent thành một công cụ

Mục tiêu:

Biến một agent thành một tool có thể được gọi bởi agent khác, giống như cách ta gọi một hàm hay API.

Cách hoạt động:

2. Handoff – Chuyển nhiệm vụ giữa các agent

Mục tiêu:

Cho phép agent này chuyển giao nhiệm vụ (task) cho agent khác khi cần sự hỗ trợ chuyên sâu.

Cách hoạt động:

So sánh nhanh:

Khía cạnh Agent as Tool Handoff
Cách gọi Gọi như một API Chuyển luôn vai trò trả lời
Tái sử dụng Cao Thấp hơn
Kiểm soát luồng logic Do agent chủ động điều phối Tự động tùy theo nội dung hội thoại
Duy trì hội thoại Không giữ hội thoại Giữ ngữ cảnh và phiên
Dùng khi nào? Khi cần gọi tác vụ cụ thể Khi cần chuyển giao vai trò chuyên gia

Ví dụ đầy đủ về cách thiết lập handoff giữa nhiều agent bằng OpenAI Agent SDK, mô phỏng một quy trình bán hàng nơi agent có thể chuyển tiếp (handoff) nhiệm vụ nếu không thuộc chuyên môn của mình.

Tình huống

Chúng ta có:

Chúng ta sẽ chạy một hội thoại qua autogen.runner và để các agent tự động "handoff" khi nội dung vượt khỏi chuyên môn của họ.

Cài đặt các Agent

from autogen import AssistantAgent, UserProxyAgent, run

# User agent
user_proxy = UserProxyAgent(name="user", human_input_mode="NEVER")

# Sales Agent
agent_sales = AssistantAgent(
    name="sales_agent",
    llm_config={"config_list": config_list},
    system_message="Bạn là nhân viên bán hàng. Hãy tư vấn sản phẩm và viết email chào hàng."
)

# Legal Agent
agent_legal = AssistantAgent(
    name="legal_agent",
    llm_config={"config_list": config_list},
    system_message="Bạn là cố vấn pháp lý. Hãy trả lời các câu hỏi pháp lý hoặc điều khoản hợp đồng."
)

# Support Agent
agent_support = AssistantAgent(
    name="support_agent",
    llm_config={"config_list": config_list},
    system_message="Bạn là nhân viên hỗ trợ kỹ thuật. Hãy giải quyết các thắc mắc về sản phẩm sau bán hàng."
)
Chạy Handoff Tự Động với run()
run(
    [user_proxy, agent_sales, agent_legal, agent_support],
    # user gửi 1 câu hỏi tổng hợp
    messages=[
        {"role": "user", "content": """
        Tôi cần mua phần mềm quản lý doanh nghiệp. Hãy gửi tôi email báo giá.
        Ngoài ra, chính sách bảo hành của công ty là gì? Và hợp đồng có điều khoản hoàn tiền không?
        """}
    ]
)

 

Ghi chú

OpenAI Agent SDK

Bài tập thực hành: Tự động hóa bán hàng với OpenAI Agent SDK

Bài 1: Tạo Agent với Tool

Mục tiêu: Hiểu cách biến agent thành công cụ (as_tool) để tạo các mô-đun xử lý riêng biệt.

Yêu cầu:

  1. Tạo 3 agents: email_writer_1, email_writer_2, email_writer_3 với 3 phong cách viết cold email khác nhau (ngắn gọn, thuyết phục, thân thiện).

  2. Biến 3 agents này thành tool:

    tool_1 = email_writer_1.as_tool(name="email_writer_1", description="Viết email ngắn gọn")
    tool_2 = email_writer_2.as_tool(name="email_writer_2", description="Viết email thuyết phục")
    tool_3 = email_writer_3.as_tool(name="email_writer_3", description="Viết email thân thiện")

Bài 2: Tạo Agent Quản Lý (Sales Manager Agent)

Mục tiêu: Dùng các tools để chọn ra email tốt nhất, không trực tiếp sinh email.

Yêu cầu:

  1. Tạo sales_manager_agent với system message như sau:

    Bạn là sales manager. Bạn chỉ sử dụng các công cụ để viết email bán hàng, không tự viết.
    Hãy thử cả 3 công cụ ít nhất 1 lần trước khi chọn email tốt nhất.
    Sau đó, giao tiếp với email_manager để gửi đi.
  2. Dùng .run() với input:

Bài 3: Handoff – Giao nhiệm vụ cho Agent khác

Mục tiêu: Sử dụng handoff để trao quyền cho email_manager.

Yêu cầu:

  1. Tạo agent email_manager, có nhiệm vụ:

    • Nhận email từ sales_manager

    • Format lại

    • Dùng 2 công cụ:

      • subject_writer: viết tiêu đề hấp dẫn

      • send_email: gửi email

  2. Tạo quy trình handoff:

    • Từ sales_manageremail_manager

    • Sau khi sales_manager chọn được email tốt nhất

Bài 4: Mở rộng – Giao tiếp nhiều lượt (Optional nâng cao)

Mục tiêu: Thiết kế agent có thể tiếp tục xử lý phản hồi từ người nhận email.

Gợi ý:

OpenAI Agent SDK

“Hàng Rào An Toàn” Cho AI - Guardrails

Guardrails là gì?

Guardrails (tạm dịch: hàng rào an toàn) là các cơ chế, quy tắc, hoặc giới hạn được thiết kế để kiểm soát hành vi của AI, đảm bảo AI hoạt động đúng mục đích, an toàn, và đáng tin cậy.

Chúng giống như "lan can" trên đường cao tốc, ngăn AI vượt khỏi phạm vi mong muốn – dù AI có khả năng suy diễn linh hoạt hoặc tự động xử lý nhiều bước.

Tại sao cần Guardrails?

Khi sử dụng AI agent hoặc LLM (mô hình ngôn ngữ lớn) trong các hệ thống tự động như:

Thì việc thiếu kiểm soát có thể gây ra:

Tình huống Rủi ro
Agent tự tạo nội dung độc hại Vi phạm đạo đức/hành vi
Agent gửi email không phù hợp Ảnh hưởng danh tiếng doanh nghiệp
Agent gọi API sai Gây lỗi hệ thống hoặc tốn chi phí
Agent trả lời sai lệch Gây hiểu nhầm hoặc sai thông tin

Vì vậy, Guardrails giúp định hướng và giới hạn hành vi AI một cách có kiểm soát.

Guardrails hoạt động như thế nào?

Một số kỹ thuật hoặc chiến lược để thiết lập Guardrails gồm:

1. Instructions rõ ràng (hướng dẫn vai trò cụ thể)

Ví dụ:

"Bạn là Giám đốc bán hàng. Không bao giờ tự tạo email. Luôn sử dụng các công cụ được cung cấp."

→ Hạn chế AI không tự viết email, buộc phải sử dụng tool hợp lệ.

2. Tách biệt giữa "Tool" và "Handoff"
Loại Vai trò
Tool (công cụ) Gọi API, thực hiện hành động cụ thể
Handoff (bàn giao) Chuyển quyền điều khiển sang agent khác

Giúp đảm bảo rõ ràng từng phần trong quy trình được kiểm soát và có thể audit.

Trace & quan sát (theo dõi agent)

Sử dụng tính năng trace để theo dõi:

Điều này giúp kiểm tra và khôi phục lại hành vi nếu có sai sót.

Các kiểu Guardrails phổ biến

Loại Guardrails Mô tả
Ràng buộc logic Nếu không hài lòng với kết quả, thử lại bằng công cụ khác
Luật đạo đức / an toàn Không thảo luận về chủ đề nhạy cảm hoặc cá nhân hóa quá mức
Giới hạn hành động Chỉ được phép gửi email sau khi kiểm tra toàn bộ tools
Theo dõi chi tiết (trace) Kiểm tra lại toàn bộ hành trình trước khi gửi

Bài học thực tế từ Sales Automation

Trong ví dụ "From Function Calls to Agent Autonomy":

→ Đây là mô hình agent có Guardrails rõ ràng.

Thực hành đề xuất

Bài tập 1: Xác định Guardrails trong đoạn sau

“"Bạn là Giám đốc bán hàng. Không bao giờ tự tạo email. Luôn sử dụng các công cụ được cung cấp."”

Câu hỏi:

Bài tập 2: Viết Guardrails cho Agent Tuyển dụng

Hãy viết các hướng dẫn guardrails cho một AI agent tuyển dụng, với các quy tắc như:

Bài tập 3: Quan sát hành vi agent qua Trace

Dựa trên dữ liệu trace của ví dụ trên:

Guardrails là linh hồn của hệ thống AI có trách nhiệm. Chúng:

Giữ AI hoạt động đúng vai trò
Tránh sai lệch, vi phạm đạo đức hoặc kỹ thuật
Tạo cơ sở để mở rộng agent một cách an toàn

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

OpenAI Agent SDK

Thực hành Xây dựng AI Agent “Sales Manager” với Guardrails

Mục tiêu:

I. Cài đặt Môi trường

pip install langchain langchain-core openai guardrails-ai

II. Cấu hình Guardrails

a. Input Guardrail – Kiểm tra Tên Riêng

Tạo file input_guardrail.xml:

<guardrail>
  <input>
    <validation name="no_personal_name" on_fail="exception">
      <regex pattern="\b(Alice|Bob|Charlie|David)\b" match="false"/>
    </validation>
  </input>
</guardrail>

Regex ở đây sẽ từ chối đầu vào có chứa các tên người thường gặp.

b. Output Guardrail – Chặn Từ Lỗi Thời

Tạo file output_guardrail.xml:

<guardrail>
  <output>
    <validation name="no_copyright" on_fail="exception">
      <regex pattern="copyright 2023" match="false"/>
    </validation>
  </output>
</guardrail>

III. Code Agent “Sales Manager”

Tạo file sales_manager.py:

from guardrails import Guard
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage

# Load Guardrails
input_guard = Guard.from_rail("input_guardrail.xml")
output_guard = Guard.from_rail("output_guardrail.xml")

# Model
llm = ChatOpenAI(model="gpt-3.5-turbo")

def run_sales_email(prompt):
    # Kiểm tra input
    input_guard.validate(prompt)

    # Sinh email
    messages = [HumanMessage(content=prompt)]
    response = llm(messages).content

    # Kiểm tra output
    output_guard.validate(response)

    return response

# TEST 1 – Gây lỗi (Tên người thật)
try:
    print("▶ Test 1 – Có tên thật")
    prompt = "Viết email chào hàng gửi CEO từ Alice"
    print(run_sales_email(prompt))
except Exception as e:
    print("⛔ Guardrail kích hoạt:", e)

# TEST 2 – Thành công
try:
    print("\n▶ Test 2 – Không có PII")
    prompt = "Viết email chào hàng gửi CEO từ Trưởng phòng Kinh doanh"
    print(run_sales_email(prompt))
except Exception as e:
    print("⛔ Guardrail kích hoạt:", e)

IV. Kết quả mong đợi

V. Mở rộng

Mục tiêu

Tạo một AI Agent dạng Sales Manager, khi được yêu cầu viết email chào hàng, sẽ trả về dữ liệu JSON có cấu trúc như sau:

{
  "subject": "Let's Talk About Increasing Your ROI",
  "body": "Dear CEO, I hope this message finds you well...",
  "signature": "Head of Business Development"
}

Cách làm: Dùng Pydantic + Output Parser

Langchain hỗ trợ xuất ra JSON theo schema định nghĩa bởi Pydantic.

 Bước 1: Cài thư viện cần thiết

pip install langchain openai pydantic

Bước 2: Tạo Schema bằng Pydantic

from pydantic import BaseModel

class SalesEmail(BaseModel):
    subject: str
    body: str
    signature: str

Bước 3: Dùng OutputFixingParser để ép LLM xuất JSON

from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate

llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# Khai báo parser
parser = PydanticOutputParser(pydantic_object=SalesEmail)

# Tạo prompt
prompt = PromptTemplate(
    template="""Bạn là một chuyên gia viết email chào hàng. Viết một email theo định dạng JSON sau:

{format_instructions}

Thông tin:
- Gửi cho: CEO
- Người gửi: Trưởng phòng Kinh doanh
- Sản phẩm: Giải pháp tăng hiệu quả bán hàng

Bắt đầu viết email.
""",
    input_variables=[],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

# Gọi LLM
formatted_prompt = prompt.format()
output = llm.predict(formatted_prompt)

# Parse kết quả
email = parser.parse(output)

# In ra
print(email.json(indent=2))

Kết quả mong đợi

{
  "subject": "Giải pháp giúp CEO tăng hiệu quả bán hàng",
  "body": "Kính gửi CEO, Chúng tôi xin giới thiệu...",
  "signature": "Trưởng phòng Kinh doanh"
}

 

 

OpenAI Agent SDK

Giới Thiệu Dịch vụ web-search

web-searchmột công cụ được OpenAI host sẵn (hosted tool), cho phép các AI Agent (assistant) tra cứu thông tin mới nhất từ internet trong thời gian thực. Nó giống như việc bạn tìm kiếm Google, nhưng do AI thực hiện thay bạn — và nó chỉ trả về phần thông tin cần thiết, được trích lọc và tóm tắt gọn gàng.

Cách hoạt động

  1. Bạn (người dùng) nhập câu hỏi như:
    → "Tình hình kinh tế Việt Nam đầu năm 2025 như thế nào?"

  2. AI dùng công cụ web-search để tìm kiếm thông tin mới nhất trên các trang báo, website uy tín.

  3. AI đọc, tóm tắt, tổng hợp và trả lời bạn như một chuyên gia.

Lợi ích của web-search

Lợi ích Mô tả
Cập nhật thời gian thực Truy cập được thông tin mới nhất trên web (không bị giới hạn bởi kiến thức trước tháng 4/2023 như GPT-4 thường)
Tìm đúng nội dung cần thiết Không phải đọc cả chục bài, AI sẽ trích phần liên quan và tóm tắt cho bạn
Tiết kiệm thời gian Dùng AI thay thế việc bạn phải tìm đọc từng trang
Kết hợp tư duy AI Không chỉ tìm, AI còn phân tích, so sánh, đánh giá nội dung giúp bạn hiểu sâu hơn
Tích hợp dễ dàng với Agent Bạn không cần lập trình crawling, không cần API Google Search – chỉ cần khai báo "type": "web-search" là xong

Ai nên dùng?

Chi phí sử dụng

Công cụ Chức năng chính  Lợi ích khi sử dụng
web-search Tìm kiếm thông tin từ Internet Cập nhật thông tin mới nhất, thay thế Google Search
code interpreter (tên mới: python) Chạy Python trực tiếp trong môi trường an toàn Phân tích dữ liệu, xử lý file CSV, vẽ biểu đồ, giải toán, v.v.
image generation (image_gen) Tạo hình ảnh từ mô tả văn bản (text-to-image) hoặc chỉnh sửa ảnh Dùng cho thiết kế, ý tưởng sáng tạo, bản vẽ kỹ thuật, hình minh họa
file upload (trực tiếp với GPT) Tải lên file (PDF, CSV, DOCX...) để AI đọc và phân tích Trích xuất nội dung, so sánh tài liệu, tóm tắt nội dung file
code editor (Canmore canvas) Chỉnh sửa mã nguồn hoặc văn bản dài với giao diện song song Lập trình, sửa lỗi, viết tài liệu hoặc văn bản dài dễ dàng hơn
browser (trước đây) Phiên bản cũ của web-search, nay đã thay thế bằng web-search ❌ Không còn được dùng trực tiếp
DALL·E Editor Vẽ hoặc sửa ảnh trực tiếp bằng AI với giao diện vùng chọn Tạo ảnh nghệ thuật, mockup, biểu tượng, avatar
OpenAI Agent SDK

Tạo Ứng Dụng Agent Tự Nghiên Cứu

Hôm nay, chúng ta sẽ xây dựng dự án lớn đầu tiên – một Deep Research Agent.

Đây là một trong những ứng dụng kinh điển của Agentic AI – nơi agent sẽ:

Mục tiêu của dự án

Tạo một AI Agent có khả năng:

Công cụ cần chuẩn bị

Cấu trúc dự án gợi ý

deep_research_agent/
├── .env
├── deep_research.ipynb
└── requirements.txt

1. Cài đặt môi trường

Tạo thư mục và cài thư viện

mkdir deep_research_agent
cd deep_research_agent
python -m venv venv
source venv/bin/activate  # hoặc .\venv\Scripts\activate trên Windows

pip install openai python-dotenv jupyter

Tạo file requirements.txt

openai
python-dotenv
jupyter

2. Tạo file .env

Tạo file .env chứa API key của bạn:

OPENAI_API_KEY=sk-...

3. Tạo Notebook deep_research.ipynb

Bạn có thể tạo một file notebook mới trong VSCode hoặc Jupyter. Dưới đây là nội dung gợi ý từng bước bạn cần triển khai:

4. Nội dung notebook (deep_research.ipynb)

🔹 Bước 1: Khởi tạo môi trường
import os
from dotenv import load_dotenv
import openai

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

🔹 Bước 2: Định nghĩa công cụ hosted (web search)

from openai import OpenAI
from openai.types.beta.threads import ToolAssistant
from openai.types.beta.tools import ToolChoice

client = OpenAI()

# Mô tả Search Agent
instructions = """
You are a research assistant.
Given a search term, you search the web for that term.
You produce a concise summary in 2–3 paragraphs, capturing the main points.
Write succinctly. No need for good grammar.
"""

tools = [{"type": "web-search"}]  # Tool được OpenAI host

🔹 Bước 3: Tạo Assistant (Agent)

assistant = client.beta.assistants.create(
    name="Search Agent",
    instructions=instructions,
    tools=tools,
    model="gpt-4-turbo"
)

Bước 4: Tạo Thread, gửi yêu cầu tìm kiếm

thread = client.beta.threads.create()

user_input = "Latest AI agent frameworks in 2025"

# Thêm message
client.beta.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content=user_input
)

# Run với yêu cầu bắt buộc dùng web-search
run = client.beta.threads.runs.create(
    thread_id=thread.id,
    assistant_id=assistant.id,
    tool_choice={"type": "required"},
    model="gpt-4-turbo"
)

# Chờ chạy xong
import time
while True:
    run_status = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
    if run_status.status in ["completed", "failed"]:
        break
    time.sleep(1)

# Lấy kết quả
messages = client.beta.threads.messages.list(thread_id=thread.id)
for msg in messages:
    print(f"{msg.role}: {msg.content[0].text.value}")

Lưu ý về chi phí

 

OpenAI Agent SDK

Xây dựng "Planner Agent" – Trợ lý lập kế hoạch tìm kiếm thông minh

Mục tiêu

Tạo một agent có khả năng phân tích câu hỏi đầu vào và đề xuất 3 truy vấn tìm kiếm web hợp lý để nghiên cứu sâu về chủ đề đó. Agent này sẽ không tìm kiếm mà chỉ đưa ra kế hoạch tìm kiếm.

 Bước 1: Cài đặt thư viện cần thiết

pip install openai pydantic

Bước 2: Định nghĩa cấu trúc đầu ra

Sử dụng Pydantic để định nghĩa schema cho dữ liệu mà mô hình sẽ trả về.

from pydantic import BaseModel, Field
from typing import List

class WebSearchItem(BaseModel):
    reason: str = Field(..., description="Lý do tại sao nên thực hiện truy vấn này.")
    query: str = Field(..., description="Cụm từ khóa cần tìm kiếm trên internet.")

class WebSearchPlan(BaseModel):
    searches: List[WebSearchItem] = Field(..., description="Danh sách các tìm kiếm để trả lời câu hỏi.")

Bước 3: Tạo prompt hướng dẫn hệ thống

SYSTEM_PROMPT = """
Bạn là một trợ lý nghiên cứu hữu ích.
Dựa trên một câu hỏi đầu vào, hãy đề xuất 3 truy vấn tìm kiếm trên web tốt nhất để trả lời câu hỏi đó.
Mỗi truy vấn cần bao gồm:
1. Lý do thực hiện truy vấn đó.
2. Cụm từ khóa cụ thể cần tìm kiếm.

Trả lời dưới dạng một đối tượng JSON có dạng:
{
  "searches": [
    {"reason": "...", "query": "..."},
    {"reason": "...", "query": "..."},
    {"reason": "...", "query": "..."}
  ]
}
"""

Bước 4: Gọi mô hình GPT để lập kế hoạch tìm kiếm

import openai
import json

openai.api_key = "YOUR_OPENAI_API_KEY"  # Thay bằng API key của bạn

def generate_search_plan(question: str):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": f"Câu hỏi: {question}"}
        ],
        temperature=0.7
    )
    
    content = response["choices"][0]["message"]["content"]
    
    try:
        # Chuyển JSON thành đối tượng WebSearchPlan
        data = json.loads(content)
        return WebSearchPlan(**data)
    except Exception as e:
        print("Lỗi khi phân tích phản hồi:", e)
        print("Phản hồi thô:", content)

# Thử nghiệm
plan = generate_search_plan("Các framework AI phổ biến trong năm 2025 là gì?")
if plan:
    for idx, item in enumerate(plan.searches, start=1):
        print(f"\n🔍 Tìm kiếm #{idx}")
        print(f"Lý do : {item.reason}")
        print(f"Truy vấn: {item.query}")

Kết quả mong đợi

{
  "searches": [
    {
      "reason": "Tìm hiểu các framework AI mới được giới thiệu năm 2025",
      "query": "framework AI mới năm 2025"
    },
    {
      "reason": "Phân tích các xu hướng ứng dụng AI trong ngành công nghiệp",
      "query": "ứng dụng AI trong công nghiệp 2025"
    },
    {
      "reason": "Tìm các công bố tại hội nghị AI hàng đầu năm 2025",
      "query": "hội nghị AI công bố framework 2025"
    }
  ]
}

Ghi nhớ

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

OpenAI Agent SDK

Bài Thực Hành: "Trợ Lý Lập Kế Hoạch Marketing"

Mục tiêu

Xây dựng một agent AI có khả năng hiểu mục tiêu Marketing (ví dụ: ra mắt sản phẩm mới, tăng lượt đăng ký, nâng cao nhận diện thương hiệu, v.v...) và tự động đề xuất 3 hành động cụ thể mà team nên thực hiện, kèm lý do chiến lược cho từng hành động.

Tình huống

Team Marketing đưa vào một mục tiêu chiến dịch. AI agent sẽ trả về:

Bước 1: Định nghĩa cấu trúc dữ liệu

from pydantic import BaseModel, Field
from typing import List

class MarketingAction(BaseModel):
    action: str = Field(..., description="Hành động cụ thể cần làm trong chiến dịch.")
    reason: str = Field(..., description="Lý do chiến lược để thực hiện hành động này.")
    channel: str = Field(..., description="Kênh thực hiện phù hợp (Facebook, TikTok, Blog, Email, v.v.)")

class MarketingPlan(BaseModel):
    objective: str = Field(..., description="Mục tiêu chiến dịch marketing.")
    actions: List[MarketingAction]

Bước 2: Prompt hệ thống

SYSTEM_PROMPT = """
Bạn là một chuyên gia Marketing.
Dựa trên một mục tiêu chiến dịch cụ thể, hãy gợi ý 3 hành động nên thực hiện trong chiến dịch marketing đó.
Với mỗi hành động, hãy chỉ rõ:
1. Hành động gì?
2. Lý do chiến lược.
3. Kênh thực hiện phù hợp.

Trả về dưới dạng JSON có cấu trúc như sau:
{
  "objective": "...",
  "actions": [
    {"action": "...", "reason": "...", "channel": "..."},
    {"action": "...", "reason": "...", "channel": "..."},
    {"action": "...", "reason": "...", "channel": "..."}
  ]
}
"""

Bước 3: Hàm gọi GPT

import openai
import json

openai.api_key = "YOUR_OPENAI_API_KEY"

def generate_marketing_plan(objective: str):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": f"Mục tiêu: {objective}"}
        ],
        temperature=0.7
    )
    content = response["choices"][0]["message"]["content"]
    
    try:
        data = json.loads(content)
        return MarketingPlan(**data)
    except Exception as e:
        print("Lỗi khi phân tích phản hồi:", e)
        print("Phản hồi thô:", content)

Bước 4: Thử nghiệm

objective = "Tăng nhận diện thương hiệu cho sản phẩm chăm sóc da mới dành cho Gen Z"
plan = generate_marketing_plan(objective)

if plan:
    print(f"\n🎯 Mục tiêu chiến dịch: {plan.objective}")
    for idx, action in enumerate(plan.actions, start=1):
        print(f"\n👉 Hành động #{idx}")
        print(f"- Hành động : {action.action}")
        print(f"- Lý do     : {action.reason}")
        print(f"- Kênh      : {action.channel}")

Kết quả mong đợi (ví dụ)

{
  "objective": "Tăng nhận diện thương hiệu cho sản phẩm chăm sóc da mới dành cho Gen Z",
  "actions": [
    {
      "action": "Hợp tác với các beauty TikTokers nổi tiếng",
      "reason": "Gen Z dành nhiều thời gian trên TikTok và bị ảnh hưởng bởi review chân thực từ KOL",
      "channel": "TikTok"
    },
    {
      "action": "Tổ chức mini game giveaway trên Instagram",
      "reason": "Tạo hiệu ứng lan truyền và thu hút người dùng theo dõi fanpage",
      "channel": "Instagram"
    },
    {
      "action": "Viết bài blog chia sẻ bí quyết chăm sóc da tuổi teen",
      "reason": "Nâng cao niềm tin và cung cấp giá trị hữu ích để thu hút khách hàng tiềm năng qua Google Search",
      "channel": "Blog/SEO"
    }
  ]
}

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft

 

OpenAI Agent SDK

BÀI THỰC HÀNH: Xây dựng Deep Research Agent và gửi kết quả qua Email

Mục tiêu

Xây dựng một hệ thống gồm nhiều agents có thể thực hiện song song các tìm kiếm sâu (deep research), tổng hợp kết quả, và gửi email HTML chứa bản báo cáo chuyên sâu.

Công nghệ sử dụng

Các thành phần

Thành phần Mô tả
Planner Agent Nhận đầu vào là chủ đề nghiên cứu và chia thành nhiều truy vấn nhỏ
Search Agents (n) Thực hiện các tìm kiếm song song theo truy vấn được giao
Writer Agent Tổng hợp kết quả từ các search agents và viết báo cáo HTML
Email Agent Gửi báo cáo qua email HTML đến người nhận

Bước 1: Cài đặt cấu trúc project

deep_research_agent/
├── agents/
│   ├── planner.py
│   ├── search_agent.py
│   ├── writer.py
│   └── email_agent.py
├── main.py
├── utils.py
├── .env
└── requirements.txt

Bước 2: Cấu hình file .env

OPENAI_API_KEY=sk-...
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_HOST_USER=your_email@gmail.com
EMAIL_HOST_PASSWORD=your_app_password
RECEIVER_EMAIL=receiver@example.com

Bước 3: Viết từng agent

planner.py

async def planner(topic: str, num_tasks: int = 5) -> list[str]:
    return [f"{topic} - góc nhìn {i+1}" for i in range(num_tasks)]

search_agent.py

import asyncio

async def search(query: str) -> str:
    await asyncio.sleep(1)  # giả lập thời gian tìm kiếm
    return f"Kết quả cho: {query}"

writer.py

def write_report(results: list[str], topic: str) -> str:
    html = f"<h1>Báo cáo về: {topic}</h1><ul>"
    for r in results:
        html += f"<li>{r}</li>"
    html += "</ul><p><strong>Kết luận:</strong> Báo cáo này dựa trên {len(results)} truy vấn.</p>"
    return html

email_agent.py

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os

def send_email(subject: str, html: str):
    msg = MIMEMultipart()
    msg['From'] = os.getenv("EMAIL_HOST_USER")
    msg['To'] = os.getenv("RECEIVER_EMAIL")
    msg['Subject'] = subject

    msg.attach(MIMEText(html, 'html'))

    server = smtplib.SMTP(os.getenv("EMAIL_HOST"), int(os.getenv("EMAIL_PORT")))
    server.starttls()
    server.login(os.getenv("EMAIL_HOST_USER"), os.getenv("EMAIL_HOST_PASSWORD"))
    server.send_message(msg)
    server.quit()

Bước 4: main.py

import asyncio
from agents.planner import planner
from agents.search_agent import search
from agents.writer import write_report
from agents.email_agent import send_email

async def main():
    topic = "Ứng dụng AI trong marketing"
    queries = await planner(topic, num_tasks=10)

    tasks = [search(q) for q in queries]
    results = await asyncio.gather(*tasks)

    report_html = write_report(results, topic)
    send_email(subject=f"[Báo cáo] {topic}", html=report_html)
    print("✅ Email đã được gửi!")

if __name__ == "__main__":
    asyncio.run(main())

Mục tiêu học viên đạt được

Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft