AI & GenAI

[Tech Blog #23 | AI & GenAI] Giải Mã AI Agents: Xây Dựng Trợ Lý Tự Lập Kế Hoạch Với Mô Hình ReAct Bằng Python

0 views
[Tech Blog #23 | AI & GenAI] Giải Mã AI Agents: Xây Dựng Trợ Lý Tự Lập Kế Hoạch Với Mô Hình ReAct Bằng Python

1. Đặt vấn đề: Bước nhảy vọt từ Chatbot sang AI Agent

Trong năm 2023, thế giới phát sốt vì những con Chatbot trả lời câu hỏi mượt mà. Nhưng sang các năm tiếp theo, kỳ vọng của các doanh nghiệp đã thay đổi hoàn toàn: Họ không cần một cỗ máy chỉ biết "nói chuyện", họ cần một "nhân viên số" biết tự làm việc.

Hãy so sánh hai kịch bản khi nhận lệnh: "Hãy kiểm tra doanh thu tuần này của chi nhánh Đà Nẵng, nếu đạt KPI thì gửi email chúc mừng cho quản lý cửa hàng":

  • Chatbot thông thường: Sẽ viết ra một bức thư chúc mừng mẫu rất hay, nhưng... nó không thể tự kiểm tra doanh thu, và cũng chẳng thể tự bấm gửi email. Bạn vẫn phải làm mọi thao tác thủ công bằng tay.
  • AI Agent (Tác tử tự chủ): Tự phân tích yêu cầu thành các bước nhỏ →\rightarrow Tự gọi API cơ sở dữ liệu để lấy doanh thu →\rightarrow Tự so sánh với KPI →\rightarrow Nếu đạt, tự động soạn email và bấm gửi qua Gmail API →\rightarrow Báo cáo lại cho bạn: "Đã hoàn thành xong xuôi!".

Bí mật đằng sau khả năng tự lập kế hoạch và tự sửa lỗi của AI Agent chính là kiến trúc ReAct (Reasoning + Acting).


2. Kiến trúc ReAct: Vòng lặp "Tư Duy & Hành Động"

Kiến trúc ReAct (được giới thiệu bởi các nhà nghiên cứu từ Đại học Princeton và Google) kết hợp hai năng lực cốt lõi: Lý luận (Reasoning) và Thực thi (Acting) thành một vòng lặp liên tục:

                  [MỤC TIÊU CỦA NGƯỜI DÙNG]
                              │
                              ▼
        ┌───────────────────────────────────────────┐
        │  1. THOUGHT (Suy nghĩ / Lập luận):        │
        │     "Mình đang có gì? Cần làm gì tiếp?"  │
        └─────────────────────┬─────────────────────┘
                              │
                              ▼
        ┌───────────────────────────────────────────┐
        │  2. ACTION (Hành động):                   │
        │     Quyết định gọi Công cụ nào + Tham số? │
        └─────────────────────┬─────────────────────┘
                              │
                              ▼
        ┌───────────────────────────────────────────┐
        │  3. OBSERVATION (Quan sát kết quả thật):   │
        │     Hệ thống/API trả về dữ liệu thực tế   │
        └─────────────────────┬─────────────────────┘
                              │
          (Chưa xong mục tiêu?)│ (Đã đủ thông tin?)
          └───────────────────┴────────► [FINAL ANSWER]
  • Thought (Tư duy): Giúp mô hình tự nói chuyện với chính nó (Internal Monologue), phân tích kết quả vừa nhận được và lên kế hoạch cho bước đi tiếp theo. Bước này triệt tiêu tới 80% nguy cơ ảo giác.
  • Action (Hành động): Lựa chọn công cụ phù hợp từ bộ công cụ được cấp (đã học ở [Tech Blog #15]).
  • Observation (Quan sát): Đọc kết quả trả về từ công cụ thật để nạp vào trí nhớ ngắn hạn.

3. Bảng so sánh các cấp độ trợ lý AI

Tiêu chíCấp 1: Chatbot Truyền ThốngCấp 2: Function Calling Đơn LẻCấp 3: Autonomous AI Agent (ReAct)
Quy trình xử lý1 Lượt hỏi →\rightarrow 1 Lượt đáp tĩnh.1 Lượt hỏi →\rightarrow Gọi đúng 1 hàm duy nhất →\rightarrow Đáp.Vòng lặp đa bước tự chủ cho đến khi giải xong bài toán.
Khả năng tự sửa sai❌ Không có (Nếu sai là sai luôn).❌ Phụ thuộc vào code xử lý cứng phía sau.✅ Tự phục hồi (Self-healing): Nếu gọi hàm lỗi, tự nghĩ cách thử lại bằng tham số khác.
Lập kế hoạch (Planning)❌ Không thể.❌ Do con người chỉ định sẵn.✅ Tự phân rã bài toán lớn thành chuỗi các nhiệm vụ nhỏ.
Mức độ phụ thuộc người dùngRất cao, người dùng phải hướng dẫn từng bước.Trung bình, người dùng hỏi câu hỏi cụ thể.Thấp, chỉ cần giao mục tiêu cuối cùng (Goal-oriented).

4. Thực hành thực chiến: Tự xây dựng ReAct AI Agent bằng Python (No-Framework)

Thay vì dùng các thư viện cồng kềnh như LangChain hay CrewAI, đoạn mã Python dưới đây tự hiện thực hóa vòng lặp ReAct thuần túy từ đầu để bạn nắm trọn bản chất bên trong "cỗ máy":

import os
import json
import re
from openai import OpenAI

client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "your-api-key-here"))

# ==============================================================================
# BƯỚC 1: ĐỊNH NGHĨA CÁC CÔNG CỤ NGOẠI VI (REAL-WORLD TOOLS)
# ==============================================================================
def get_stock_price(ticker: str) -> str:
    """Tra cứu giá cổ phiếu thời gian thực (Giả lập dữ liệu sàn HOSE)."""
    prices = {
        "FPT": "135,000 VND",
        "VNM": "68,000 VND",
        "HPG": "26,500 VND"
    }
    return prices.get(ticker.upper(), "Không tìm thấy mã cổ phiếu này")

def calculate(expression: str) -> str:
    """Máy tính toán học chính xác 100% bằng Python."""
    try:
        # Làm sạch chuỗi biểu thức để an toàn
        clean_expr = re.sub(r"[^0-9+\-*/(). ]", "", expression)
        result = eval(clean_expr)
        return str(result)
    except Exception as e:
        return f"Lỗi tính toán: {e}"

AVAILABLE_TOOLS = {
    "get_stock_price": get_stock_price,
    "calculate": calculate
}

# ==============================================================================
# BƯỚC 2: PROMPT ĐỊNH HÌNH TƯ DUY REACT (REASONING PROMPT)
# ==============================================================================
REACT_SYSTEM_PROMPT = """
Bạn là một AI Agent giải quyết vấn đề theo chu trình ReAct.
Bạn có quyền truy cập vào các công cụ sau:
- get_stock_price(ticker): Tra cứu giá cổ phiếu hiện tại (ví dụ: get_stock_price("FPT"))
- calculate(expression): Thực hiện phép tính số học chính xác (ví dụ: calculate("135000 * 15"))

Để giải quyết nhiệm vụ, bạn BẮT BUỘC phải tuân thủ nghiêm ngặt định dạng sau:

Thought: Bạn tự suy nghĩ xem cần làm gì tiếp theo.
Action: tên_công_cụ("tham_số")
Observation: Chờ kết quả từ hệ thống trả về...
... (Quy trình Thought/Action/Observation này có thể lặp lại nhiều lần)
Thought: Tôi đã có đủ thông tin để đưa ra kết luận cuối cùng.
Final Answer: Câu trả lời hoàn chỉnh, chính xác cho người dùng.

Bắt đầu nhiệm vụ ngay!
"""

# ==============================================================================
# BƯỚC 3: VÒNG LẶP ĐIỀU PHỐI TỰ CHỦ (AGENT EXECUTION LOOP)
# ==============================================================================
def run_react_agent(user_query: str, max_iterations: int = 5):
    print(f"\n🎯 [MỤC TIÊU]: {user_query}")
    prompt_history = f"User Question: {user_query}\n"
    
    for step in range(1, max_iterations + 1):
        print(f"\n--- BƯỚC {step} ---")
        
        # Gọi LLM với toàn bộ lịch sử suy nghĩ và quan sát
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": REACT_SYSTEM_PROMPT},
                {"role": "user", "content": prompt_history}
            ],
            temperature=0.0, # Đặt bằng 0 để tư duy logic nhất quán
            stop=["Observation:"] # Dừng lại ngay khi AI chuẩn bị viết Observation để hệ thống điền vào
        )
        
        agent_output = response.choices[0].message.content.strip()
        print(agent_output)
        prompt_history += agent_output + "\n"
        
        # Kiểm tra xem Agent đã đạt tới Final Answer chưa
        if "Final Answer:" in agent_output:
            final_answer = agent_output.split("Final Answer:")[1].strip()
            print(f"\n🏁 [KẾT QUẢ CUỐI CÙNG]:\n{final_answer}")
            return final_answer
            
        # Bóc tách Action bằng Regular Expression: tên_hàm("tham_số")
        action_match = re.search(r"Action:\s*(\w+)\((.*)\)", agent_output)
        if action_match:
            tool_name = action_match.group(1).strip()
            # Bỏ dấu ngoặc kép hoặc đơn quanh tham số
            tool_arg = action_match.group(2).strip().strip("\"'")
            
            # Thực thi công cụ thực tế
            if tool_name in AVAILABLE_TOOLS:
                tool_func = AVAILABLE_TOOLS[tool_name]
                observation = tool_func(tool_arg)
            else:
                observation = f"Lỗi: Không tồn tại công cụ '{tool_name}'."
                
            print(f"Observation: {observation}")
            prompt_history += f"Observation: {observation}\n"
        else:
            print("Lỗi định dạng hành động, dừng vòng lặp.")
            break
            
    print("Vượt quá số bước cho phép mà chưa xong nhiệm vụ.")

# ==============================================================================
# CHẠY THỬ NGHIỆM TÁC VỤ PHỨC TẠP ĐA BƯỚC
# ==============================================================================
if __name__ == "__main__":
    complex_task = "Tôi muốn mua 15 cổ phiếu FPT với giá hiện tại thì cần chuẩn bị bao nhiêu tiền VNĐ?"
    run_react_agent(complex_task)

5. Câu hỏi phỏng vấn thực tế (Interview Q&A)

Câu 1 (Mức độ: Entry / Junior)

Câu hỏi: "Kiến trúc ReAct (Reasoning + Acting) giải quyết điểm yếu gì lớn nhất của các mô hình LLM khi tự động hóa công việc?"

Gợi ý trả lời:
*"Kiến trúc ReAct giải quyết điểm yếu thiếu khả năng lập kế hoạch và không tự nhận thức được sai sót của LLM:

  1. Nếu chỉ dùng 'Reasoning' thuần túy (như Chain-of-Thought), LLM vẫn bị giới hạn trong trí nhớ tĩnh và rất dễ bịa ra số liệu sai (Hallucination).
  2. Nếu chỉ dùng 'Acting' thuần túy (như Function Calling đơn lẻ), LLM chỉ biết gọi hàm một cách máy móc mà không biết cách xâu chuỗi nhiều công cụ hoặc không biết làm gì tiếp theo khi hàm trả về kết quả lạ.
    ReAct kết hợp cả hai: Cho phép LLM vừa suy ngẫm kế hoạch vừa hành động thực tế, đọc kết quả thực tế để điều chỉnh suy nghĩ cho bước tiếp theo, giúp giảm thiểu sai sót và hoàn thành được các bài toán phức tạp nhiều giai đoạn."*

Câu 2 (Mức độ: Junior / Mid-level)

Câu hỏi: "Khi xây dựng một AI Agent trong môi trường sản xuất (Production), bạn làm thế nào để ngăn chặn rủi ro Agent bị rơi vào vòng lặp vô tận (Infinite Loop) hoặc tiêu tốn quá nhiều chi phí token?"

Gợi ý trả lời:
*"Để bảo vệ hệ thống trước rủi ro vòng lặp vô tận, em luôn thiết lập 3 lớp phòng vệ (Guardrails):

  1. Giới hạn số bước tối đa (max_iterations): Thiết lập trần cứng (ví dụ tối đa 5 hoặc 8 vòng lặp). Nếu vượt quá số bước này mà chưa ra kết quả, Agent buộc phải dừng lại và kích hoạt cơ chế Fallback (báo lỗi hoặc chuyển giao cho con người xử lý).
  2. Cơ chế phát hiện lặp lại (Loop Detection): Lưu lại lịch sử các lệnh gọi Action; nếu phát hiện Agent gọi cùng một công cụ với cùng một tham số y hệt nhau quá 2 lần liên tiếp mà kết quả không đổi, hệ thống sẽ chèn cảnh báo can thiệp vào prompt: 'Hành động này không hiệu quả, hãy thử chiến lược khác'.
  3. Ràng buộc thời gian (Timeout) và Ngân sách Token (Token Budget): Đặt giới hạn timeout cho mỗi phiên làm việc và ngắt kết nối nếu tổng số token vượt quá hạn mức tài chính cho phép."*

6. Key Takeaways (Ghi nhớ nhanh)

  1. AI Agent = LLM (Bộ não) + Tools (Đôi tay) + Planning (Kế hoạch): Khác với chatbot thụ động, Agent chủ động lập kế hoạch đa bước để hoàn thành mục tiêu.
  2. Chu trình ReAct 3 bước: Thought (Tự lập luận) →\rightarrow Action (Gọi công cụ) →\rightarrow Observation (Đọc dữ liệu thực).
  3. Triệt tiêu ảo giác bằng tính toán thực tế: Hãy để hàm Python làm các phép toán chính xác và gọi Database thật, LLM chỉ đóng vai trò phân tích và điều phối.
  4. Luôn có chốt an toàn (max_iterations): Tuyệt đối không thả cho Agent chạy tự do mà không có giới hạn số bước và cơ chế ngắt vòng lặp an toàn.
0Claps