CodeGym /Các khóa học /ChatGPT Apps /Workflow nhiều bước như một cách để giảm gánh nặng nhận t...

Workflow nhiều bước như một cách để giảm gánh nặng nhận thức

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Workflow là gì trong bối cảnh ChatGPT App

Nếu bạn đã vượt qua phần đăng nhập, bạn xứng đáng được thưởng. Hãy chuyển sang một chủ đề rất thú vịworkflow trong ChatGPT App. Nói thật, từ “workflow” hay gợi flashback về các sơ đồ BPMN và phần mềm doanh nghiệp buồn tẻ. Yên tâm: trong bối cảnh ChatGPT App, ta quan tâm đến một phiên bản nhẹ nhàng hơn nhiều.

Trong khóa học này, workflow được hiểu là kịch bản nhiều bước, trong đó:

  • có một mục tiêu rõ ràng (ví dụ, chọn quà và đi đến mua hàng),
  • có các bước tuần tự (khảo sát → tạo phương án → làm rõ → kết thúc),
  • mỗi bước có vai trò riêng cho GPT, widget và công cụ.

Điểm quan trọng: workflow không phải là “một method trong MCP‑server”. Nó là sự kết hợp:

  • lập luận của mô hình (hỏi gì, gọi công cụ nào),
  • gọi tools (MCP/Agents),
  • các bước UI trong widget,
  • trạng thái ở backend.

Tức là bạn không có một “siêu công cụ” solve_everything, mà có nhiều công cụ đơn giản, kích hoạt ở các giai đoạn khác nhau. Và không phải một “mega widget”, mà là một tập nhỏ các màn hình/trạng thái, mỗi cái cho một tiểu nhiệm vụ.

“Tam giác trách nhiệm” trong workflow

Nghĩ về workflow như một điệu nhảy của ba bên là rất tiện:

Vai trò Nhiệm vụ trong workflow Ví dụ trong GiftGenius
GPT Bộ não. Hiểu ý định người dùng, quyết định khi nào bước hoàn tất, bước tiếp theo là gì. Có thể gọi tools. Hiểu “mình muốn thứ gì đó cho geek” và quyết định gọi search_items(category="geek").
Widget Gương mặt. Render bước hiện tại, chỉ hiển thị phần liên quan, thu thập click và nhập liệu. Lưu trạng thái UI. Hiển thị form “Tặng quà cho ai?”, rồi thẻ các món quà, sau đó là nút “Mua”.
MCP/Agent Đôi tay. Làm việc nặng và có cấu trúc, kiểm định dữ liệu, lưu trạng thái nghiệp vụ. Lưu hồ sơ người nhận, truy vấn danh mục quà, lọc theo ngân sách.

Ba vai trò này cùng thực hiện một kịch bản, nhưng ở các tầng khác nhau: GPT quyết định “tiếp theo là gì”, widget hiển thị “bây giờ là gì”, MCP đảm nhiệm những gì thực sự xảy ra với dữ liệu.

2. Ví dụ workflow dựa trên GiftGenius

Lấy kịch bản GiftGenius đã quen — trợ lý chọn quà. Có thể mô tả nó như một wizard tuyến tính đơn giản.

Trình tự bước có thể là:

  1. Thu thập thông tin cơ bản về người nhận.
  2. Xác định ngân sách và ràng buộc.
  3. Tạo và lọc ý tưởng quà.
  4. Hiển thị ứng viên, cho phép like/ẩn.
  5. Chuyển sang Checkout hoặc lưu bộ sưu tập.

Cùng kịch bản đó có thể được biểu diễn như một “máy trạng thái” nhỏ:

stateDiagram-v2
    [*] --> Profiling
    Profiling --> ProfilingDone: hồ sơ đã hoàn tất
    ProfilingDone --> Browsing: đã tạo ý tưởng
    Browsing --> Refining: người dùng đã chỉnh bộ lọc
    Refining --> Browsing: danh sách đã cập nhật
    Browsing --> Checkout: đã chọn quà
    Checkout --> Success: đơn hàng đã tạo
    Success --> [*]

Ở đây:

  • Profiling — bước thu thập câu trả lời về người nhận,
  • Browsing/Refining — làm việc với danh sách ứng viên,
  • Checkout — đặt hàng,
  • Success — xác nhận cuối cùng.

Lưu ý: trên sơ đồ không có nút nào, cũng không có fetch. Đây là các bước logic, còn UI cụ thể, tools và gọi API được gắn lên trên chúng.

3. Vì sao phải chia nhỏ nhiệm vụ thành các bước

Nếu bạn từng làm “bảng hỏi 25 câu trên một màn hình”, bạn đã biết lý do. Nhưng hãy phân tích kỹ hơn.

Gánh nặng nhận thức của người dùng

Con người có nguồn lực chú ý hạn chế. Các nhà tâm lý thường nhắc đến luật Miller về 7±2 đối tượng trong trí nhớ ngắn hạn. Trong UX, điều này chuyển hóa thành quy tắc thực dụng: càng nhiều trường và lựa chọn bạn hiển thị cùng lúc, khả năng người dùng đơ, mệt hoặc đóng tab càng cao.

Một form 12 trường trên một màn hình trong widget inline nhỏ của ChatGPT gần như đảm bảo “rage‑quit”: người dùng bỏ hết và đóng tab. Họ đến để “trò chuyện”, không phải làm bài thi.

Nếu bạn chia nhiệm vụ thành các bước:

  • “Bước 1/4: hãy kể về người đó”,
  • “Bước 2/4: chọn ngân sách”,
  • “Bước 3/4: xem các phương án”,
  • “Bước 4/4: xác nhận lựa chọn”.

thì tại mỗi thời điểm, khối lượng trông có thể xử lý. Thanh tiến độ hoặc nhãn bước cho cảm giác kiểm soát: hiểu chuyện gì đang diễn ra và còn bao lâu.

Gánh nặng nhận thức của mô hình

Bất ngờ: mô hình cũng gặp vấn đề tương tự. LLM tất nhiên không phải con người, nhưng nó cũng có “sự chú ý” và cửa sổ ngữ cảnh giới hạn. Nếu bạn yêu cầu GPT trong một lượt:

  • tìm hiểu tất cả về người nhận,
  • xử lý ngân sách,
  • xem xét chi tiết giao hàng,
  • chọn 10 phương án,
  • giải thích vì sao là các phương án đó,

thì ở mỗi mục con, mô hình tiêu tốn một phần chú ý và token. Càng nhiều tác vụ rời rạc trong một yêu cầu, rủi ro một phần bị làm hời hợt hoặc sai càng cao.

Nếu bạn xây một chuỗi bước — thực chất là chain-of-thought nhưng được bày rõ trong giao diện — thì trước hết mô hình giải quyết nhiệm vụ hẹp “trích xuất hồ sơ”, sau đó “điều chỉnh ngân sách”, rồi “chọn ứng viên”. Chất lượng lập luận (reasoning) ở mỗi giai đoạn sẽ cao hơn đáng kể.

Khả năng bảo trì và debug

Khi mọi thứ nhồi vào một công cụ và một màn hình, việc debug thành truy tìm kho báu: “Nó tệ đi chính xác ở đâu?”

Trong workflow nhiều bước, bạn gần như tự động có:

  • các điểm log: step_started, step_completed, step_failed,
  • điểm đo chuyển đổi rõ ràng (bao nhiêu người đến bước 3),
  • vấn đề khu trú: “chỉ rơi ở bước tạo ý tưởng”.

Tất cả sẽ hữu ích trong mô-đun về analytics cho workflow, nhưng ngay bây giờ cũng nên quen tư duy theo bước.

4. Các loại bước trong workflow và chúng trông như thế nào trong UI

Chúng ta đã bàn vì sao nên chia nhỏ nhiệm vụ. Giờ hãy hệ thống hóa các bước và xem những “khối” điển hình thường gặp trong ChatGPT App. Để không trượt vào mớ màn hình hỗn loạn, tốt nhất có một “thư viện” loại bước. Trong App của bạn gần như luôn lặp lại vài pattern.

Đây là bảng cơ bản:

Loại bước Mục tiêu Thường trông thế nào trong ChatGPT App Ví dụ trong GiftGenius
Thu thập dữ liệu (Wizard) Điền một đối tượng phức tạp theo từng phần Form nhỏ, chips, chọn tùy chọn, chỉ báo tiến độ “Tặng cho ai?”, “Tuổi?”, “Sở thích?”
Rẽ nhánh Quyết định đi theo nhánh nào tiếp theo Câu hỏi trong chat + lựa chọn đơn giản trong UI “Quà cho trẻ em → danh mục dành cho trẻ em”
Xem/xác nhận Cho người dùng đối chiếu kết quả Thẻ tóm tắt + nút “Quay lại” / “Xác nhận” “Đây là những gì tôi hiểu về cô ấy, đã đúng chưa?”
Bước cuối cùng Kết thúc kịch bản và gợi ý hành động tiếp theo Màn hình cuối với kết quả + các follow‑up trong chat “Đây là các món quà của bạn, muốn tiến hành đặt hàng không?”

Quan trọng: cùng một bước logic có thể xuất hiện cả trong UI lẫn thuần văn bản. Ví dụ, bước “thu thập sở thích” có thể là:

  • hoặc một form với tag “thể thao”, “board game”, “nấu ăn”,
  • hoặc là cuộc hội thoại, nơi GPT khéo léo hỏi: “Anh ấy/cô ấy thích gì?”.

Thường phương án tối ưu là lai: GPT đặt câu hỏi, người dùng trả lời bằng văn bản, đồng thời có thể click vào chips trong widget.

5. Ai “dẫn dắt” workflow: GPT, widget hay server?

Theo trực giác, ta muốn nói: “Dĩ nhiên là widget, chúng ta là frontend, kiểm soát mọi thứ qua state”. Nhưng trong thế giới ChatGPT App thì không vậy. Workflow là công việc chung của cả ba bên.

GPT như nhạc trưởng

GPT:

  • dẫn dắt hội thoại, đặt câu hỏi,
  • quyết định khi nào có thể xem bước là hoàn tất,
  • chọn khi nào gọi tool (ví dụ “đến lúc tạo danh sách quà”).

Với GPT, workflow của bạn trông như tập hợp các tiểu nhiệm vụ. Trong system‑prompt bạn có thể mô tả các tiểu nhiệm vụ và thứ tự thường làm, nhưng vẫn để mô hình có chút tự do điều chỉnh.

Ví dụ mini‑instruction trong system‑prompt cho GiftGenius (pseudo, không theo cú pháp cụ thể):

1. Trước tiên làm rõ hồ sơ người nhận (tuổi, mối quan hệ, sở thích).
2. Sau đó làm rõ ngân sách.
3. Khi đã đủ dữ liệu — gọi công cụ suggest_gifts.
4. Sau khi nhận ứng viên — giúp người dùng chọn.

Điểm chính: GPT không biết (và không cần biết) chi tiết component React của bạn. Nó vận hành theo các bước ở mức mục tiêu: “thu thập hồ sơ”, “chọn ý tưởng”.

Widget như “gương mặt” của bước

Widget:

  • hiển thị đúng bước đang liên quan,
  • lưu trạng thái UI (thẻ được chọn, tab đang mở, trường form cục bộ),
  • có thể hiển thị chỉ báo tiến độ theo bước.

Biểu diễn đơn giản của UI‑workflow trong code:

type GiftWorkflowStep =
  | "profiling"
  | "budget"
  | "candidates"
  | "checkout";

type GiftWidgetState = {
  step: GiftWorkflowStep;
  selectedGiftId?: string;
};

Bên trong React widget, bạn có thể lưu trạng thái này bằng useState thông thường, hoặc nếu muốn gắn với vòng đời widget trong ChatGPT, dùng useWidgetState từ Apps SDK.

const [widgetState, setWidgetState] = useState<GiftWidgetState>({
  step: "profiling",
});

Các handler trong widget sẽ không trực tiếp “mua quà”, mà thay đổi bước và chuyển dữ liệu cần thiết về cho mô hình/backend.

MCP‑tools như “đôi tay” của workflow

MCP‑server:

  • lưu trạng thái nghiệp vụ (hồ sơ, lịch sử lựa chọn),
  • kiểm định bước (“không thể sang Checkout nếu chưa chọn quà”),
  • thực hiện việc nặng: tìm trong catalog, tính giá, tích hợp với ACP.

Ví dụ, hợp lý hơn khi quyết định “hiển thị quà nào” được đưa ra không ở widget mà ở MCP‑tool suggest_gifts, để mô hình có thể gọi nhiều lần khi cần làm rõ.

Như vậy bạn có phân tách rõ:

  • GPT — văn bản và trình tự,
  • widget — biểu diễn trực quan của bước hiện tại,
  • MCP — dữ liệu và bất biến nghiệp vụ.

6. Mô tả workflow trong code: mini state‑machine

Nhớ sơ đồ trạng thái cho GiftGenius ở đầu bài chứ? Giờ ta ghi lại logic đó bằng các kiểu và hàm đơn giản — một mini state‑machine trong code. Ta sẽ không biến App thành khóa học lý thuyết về automata, nhưng vài kiểu và hàm đơn giản sẽ giúp cuộc sống dễ hơn nhiều.

Các kiểu bước và cấu hình

Bắt đầu với mô tả khai báo các bước. Lấy lại kiểu GiftWorkflowStep (nhắc lại ở đây cho trực quan) và mô tả cấu hình cho nó:

type GiftWorkflowStep =
  | "profiling"
  | "budget"
  | "candidates"
  | "checkout";

type StepConfig = {
  label: string;
  isFinal?: boolean;
};

export const GIFT_WORKFLOW_STEPS: Record<GiftWorkflowStep, StepConfig> = {
  profiling: { label: "Người nhận" },
  budget: { label: "Ngân sách" },
  candidates: { label: "Phương án" },
  checkout: { label: "Thanh toán", isFinal: true },
};

Giờ có thể thêm một hàm chuyển bước đơn giản:

export function getNextStep(
  current: GiftWorkflowStep
): GiftWorkflowStep | null {
  switch (current) {
    case "profiling":
      return "budget";
    case "budget":
      return "candidates";
    case "candidates":
      return "checkout";
    default:
      return null; // kết thúc
  }
}

Điều này mang lại cho bạn:

  • danh sách bước tập trung,
  • quy tắc chuyển bước rõ ràng,
  • khả năng nhanh chóng thay đổi thứ tự và logic.

Sử dụng trong widget

Phiên bản “wizard” tối giản trong widget của bạn có thể như sau:

function GiftWizard() {
  const [step, setStep] = useState<GiftWorkflowStep>("profiling");

  const handleStepComplete = () => {
    const next = getNextStep(step);
    if (next) setStep(next);
  };

  return (
    <div>
      <ProgressBar step={step} />
      <StepContent step={step} onComplete={handleStepComplete} />
    </div>
  );
}

Component StepContent có thể render các form con khác nhau tùy theo bước:

function StepContent(props: {
  step: GiftWorkflowStep;
  onComplete: () => void;
}) {
  const { step, onComplete } = props;

  if (step === "profiling") {
    return <ProfilingStep onNext={onComplete} />;
  }
  if (step === "budget") {
    return <BudgetStep onNext={onComplete} />;
  }
  if (step === "candidates") {
    return <CandidatesStep onNext={onComplete} />;
  }
  return <CheckoutStep />;
}

Lưu ý: ở đây ta chưa đụng đến cách GPT chọn bước — đây là logic UI cục bộ. Sau này bạn có thể đồng bộ step này với trạng thái server hoặc thông điệp từ tools, nhưng để hiểu về tính nhiều bước thì vậy là đủ.

7. Nâng cấp ứng dụng học: từ “mega form” đến wizard

Giả sử trước bài này, widget GiftGenius của bạn trông như một “form lớn”:

  • tên người nhận,
  • tuổi,
  • sở thích,
  • ngân sách,
  • loại sự kiện,
  • checkbox “cần giao hàng” và thêm năm trường nữa,
  • và bên dưới là một nút to “Chọn quà tặng”.

Với prototype thì thường ổn, nhưng khi bạn muốn kịch bản sản phẩm — đã đến lúc chia thành bước.

Trước đây trông như thế nào

Ví dụ mang tính biếm họa:

// Anti‑pattern: một form khổng lồ
function GiftFormAllInOne() {
  return (
    <form>
      {/* 10+ trường trộn lẫn */}
      {/* ... */}
      <button type="submit">Chọn quà tặng</button>
    </
form>
  );
}

Các vấn đề điển hình:

  • người dùng không hiểu trường nào bắt buộc,
  • không rõ mất bao lâu,
  • khó để GPT giải thích cho người dùng điều gì đã xảy ra và làm follow‑up.

Làm “sau”: wizard với ba màn hình

Bước 1 — tách hồ sơ khỏi ngân sách:

function ProfilingStep(props: { onNext: () => void }) {
  const [recipientType, setRecipientType] = useState("");
  const [interests, setInterests] = useState<string[]>([]);

  const handleSubmit = () => {
    // có thể gọi tool lưu hồ sơ tại đây
    props.onNext();
  };

  return (
    <div>
      <h3>Chúng ta đang tìm quà cho ai?</h3>
      {/* cặp radio/chips cho loại và sở thích */}
      <button onClick={handleSubmit}>Tiếp theo</button>
    </div>
  );
}

Bước 2 — ngân sách:

function BudgetStep(props: { onNext: () => void }) {
  const [budget, setBudget] = useState<number | null>(null);

  const handleSubmit = () => {
    // có thể gọi tool kiểm định ngân sách
    props.onNext();
  };

  return (
    <div>
      <h3>Ngân sách của bạn là bao nhiêu?</h3>
      {/* slider hoặc input */}
      <button onClick={handleSubmit} disabled={!budget}>
        Gợi ý lựa chọn
      </button>
    </div>
  );
}

Bước 3 — danh sách ứng viên:

function CandidatesStep(props: { onNext: () => void }) {
  const [selectedId, setSelectedId] = useState<string | null>(null);

  // tại đây bạn hiển thị thẻ các món quà
  // và cho phép chọn một món

  return (
    <div>
      <h3>Chọn phương án phù hợp</h3>
      {/* thẻ có onClick = setSelectedId */}
      <button onClick={props.onNext} disabled={!selectedId}>
        Đi tới thanh toán
      </button>
    </div>
  );
}

Đúng là code nhiều hơn chút, nhưng logic đơn giản hơn:

  • mỗi bước giải quyết một nhiệm vụ nhỏ,
  • mô hình có thể bình luận riêng về chuyển tiếp giữa các bước,
  • bạn có thể log/đo lường từng bước riêng rẽ.

8. Anti‑pattern: đừng biến workflow thành quái vật

Thực tế và quan sát từ các app tương tự cho thấy vài lỗi điển hình mà chúng ta nên tránh.

Thứ nhất, đừng cố “vẽ hết” bằng một sơ đồ BPMN phức tạp với 30 trạng thái, 40 mũi tên và tờ A0. Trong bối cảnh ChatGPT App, điều quan trọng là bậc thang bước trực quan, không phải ký pháp hình thức. Chỉ cần các sơ đồ kiểu như ta vẽ cho GiftGenius là đủ.

Thứ hai, đừng biến App thành một form khổng lồ, đặc biệt trong widget inline. Người dùng đã ở trong chat; thêm một khối UI dày đặc phải làm giảm, chứ không tăng gánh nặng. Nếu bạn nghĩ “ở đây 12 trường nhưng đều quan trọng” — đó gần như luôn là dấu hiệu cần chia nhỏ nhiệm vụ.

Thứ ba, đừng tạo bước “cho đẹp”. Mỗi bước phải có mục tiêu rõ: hoặc thu thập dữ liệu, hoặc thu hẹp lựa chọn, hoặc để người dùng xác nhận. Màn hình rỗng kiểu “còn một chút nữa là xong” với một nút “tiếp” hiếm khi giúp ích.

Cuối cùng, đừng cố phô bày mọi khả năng của App ở những bước đầu. Những thứ chi tiết như “bộ lọc nâng cao”, “điều kiện giao hàng đặc biệt” có thể thêm như các bước bổ sung chỉ cho người thực sự cần.

9. Bài tập đơn giản về thiết kế workflow

Để khắc sâu hơn, hãy thử trên giấy (hoặc trong IDE, nhưng không cần code) làm như sau.

Chọn một nhiệm vụ. Có thể là:

  • chọn quà (GiftGenius),
  • đặt chuyến đi,
  • xây dựng kế hoạch học một kỹ năng.

Chia nó thành 3–5 bước. Với mỗi bước, mô tả:

  • mục tiêu: sau bước này cần biết/làm xong điều gì,
  • định dạng: phù hợp nhất là văn bản từ GPT, widget, hay kết hợp.

Ví dụ cho “kế hoạch học TypeScript” đơn giản:

  1. Bước “Đánh giá mức độ” — hội thoại (GPT hỏi vài câu) + form ngắn tự đánh giá.
  2. Bước “Mục tiêu” — thảo luận văn bản + checkbox mục tiêu trong widget.
  3. Bước “Kế hoạch” — tạo kế hoạch (danh sách) + nút “tăng/giảm độ khó”.
  4. Bước “Xác nhận” — tóm tắt ngắn và nút “lưu kế hoạch”.

Sau đó thử ước lượng những tools có thể tham gia ở mỗi bước, nhưng đừng sa đà chi tiết: công cụ, thời điểm bật/tắt và lưu trạng thái — là chủ đề của các bài tiếp theo trong mô-đun này.

10. Lỗi điển hình khi làm việc với workflow nhiều bước

Lỗi số 1: cố giải quyết tất cả bằng một bước và một tool.
Rất hấp dẫn khi làm “một công cụ thông minh lớn” vừa hỏi, vừa phân tích, vừa tự chọn, lại vừa tự đặt hàng. Trên thực tế, điều đó làm xấu cả UX (một màn hình nặng) lẫn chất lượng lập luận của mô hình — quá nhiều trách nhiệm trong một lần gọi. Dễ hơn, đáng tin hơn và rẻ hơn về bảo trì là chia nhiệm vụ thành chuỗi 3–5 bước đơn giản.

Lỗi số 2: các bước ngầm, chỉ nằm trong đầu lập trình viên.
Đôi khi trong code có vẻ có một trình tự hành động, nhưng không được mô tả rõ ở đâu: không có kiểu bước, không có cấu hình, không có sơ đồ. Kết quả là không ai trong đội có thể trả lời rành mạch “điều gì xảy ra trong App này từ đầu đến cuối”. Mô tả khai báo tối thiểu về bước và chuyển bước tiết kiệm hàng giờ debug.

Lỗi số 3: trộn bước UI với logic nghiệp vụ.
Nếu logic chuyển bước bị nhúng sâu vào component React (kiểu if (isValid && hasBudget && !needsShipping) trong onClick của nút), nó sẽ khó tái sử dụng và kiểm thử. Tốt hơn khi có một “máy trạng thái” tương đối rõ ràng hoặc ít nhất là hàm getNextStep, và UI chỉ gọi nó và hiển thị kết quả.

Lỗi số 4: bỏ qua vai trò của GPT như nhạc trưởng.
Đôi khi lập trình viên cố kiểm soát hoàn toàn kịch bản từ widget: “tôi sẽ tự hỏi mọi thứ cần, mô hình chỉ việc chọn”. Kết quả ChatGPT không còn là trợ lý sống động mà thành động cơ tính toán dưới form. Dễ chịu hơn nhiều khi GPT chủ động giao tiếp, thúc đẩy sang bước tiếp theo và tự khởi xướng gọi tools — còn bạn hỗ trợ bằng thiết kế bước và hướng dẫn.

Lỗi số 5: bước không có mục tiêu rõ ràng.
Đôi khi wizard có những bước “thừa” — thật ra chỉ vì trông đẹp hơn. Người dùng thấy “Bước 2/5”, nhưng ở bước đó họ chẳng phải làm gì và cũng chẳng có gì xảy ra. Những màn hình rỗng như vậy chỉ làm tăng cảm giác phức tạp. Nếu không thể phát biểu bước đó như “sau bước này ta chắc chắn biết X” hoặc “sau bước này người dùng đã làm Y” — rất có thể nó không cần thiết.

Lỗi số 6: quên hiển thị tiến độ và thiếu cảm giác về hành trình.
Nhiều bước mà không có hỗ trợ trực quan sẽ thành hộp đen: người dùng không hiểu mình đang ở đâu và còn bao lâu. Ngay cả chỉ báo văn bản “Bước 2/4” hoặc liệt kê ngang các bước ở phần đầu widget cũng giảm lo lắng đáng kể. Bỏ qua hiệu ứng này là một trong các lý do khiến người dùng rời bỏ giữa chừng, dù thực ra đoạn đó có thể không hề khó.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION