7. Workflow Patterns I - Chaining & Parallelization

Nam

Nam Hoang / Sep 07, 2025

8 min read

Chào mừng bạn đến với Phần 2: Các khả năng nâng cao. Ở phần này, chúng ta sẽ không chỉ học cách "vẽ" graph, mà còn học cách "kiến trúc" chúng để giải quyết các vấn đề thực tế trong môi trường sản xuất.

Mở đầu là hai mẫu thiết kế (Workflow Patterns) kinh điển: Prompt Chaining (Chuỗi bước) và Parallelization (Xử lý song song).

I. Prompt Chaining: Chia nhỏ để chiến thắng

Thay vì yêu cầu LLM thực hiện một nhiệm vụ khổng lồ trong một lần gọi (dễ gây "ảo giác" - hallucination), chúng ta chia nhiệm vụ đó thành một chuỗi các Node chuyên biệt.

  • Độ chính xác: Mỗi bước chỉ tập trung vào một việc duy nhất.
  • Khả năng kiểm soát: Bạn có thể kiểm tra đầu ra của bước 1 trước khi cho phép bước 2 bắt đầu.
  • Tiết kiệm: Nếu bước 1 thất bại, bạn có thể dừng ngay lập tức, tiết kiệm token cho các bước sau.

II. Parallelization: Cuộc chiến với độ trễ

Trong môi trường thực tế, Latency (độ trễ) là kẻ thù lớn nhất. Nếu bạn có các nhiệm vụ độc lập, đừng chạy chúng tuần tự. Hãy chạy chúng cùng lúc bằng mô hình Fan-out/Fan-in.

  1. Fan-out: Một Node kích hoạt nhiều Node con chạy song song.
  2. Fan-in (Aggregator): Một Node hội tụ chờ tất cả các nhánh song song hoàn thành để tổng hợp kết quả.

III. Mã nguồn: 07-patterns-chaining-parallel.ts

Ví dụ dưới đây kết hợp cả Chaining và Parallelization để xây dựng một hệ thống phân tích nội dung đa chiều.

// path: 07-patterns-chaining-parallel.ts
import { END, START, StateGraph } from '@langchain/langgraph';
import { registry } from '@langchain/langgraph/zod';
import { generateImage } from '@workspace/util-langchain';
import z from 'zod';

// 1. Define State with Reducer to collect results from parallel branches
const StateDefinition = z.object({
  content: z.string(),
  topic: z.string().optional(),
  // Reducer ensures data from parallel nodes does not overwrite each other
  insights: z.array(z.string()).register(registry, {
    reducer: { fn: (left: string[], right: string[]) => left.concat(right) },
    default: () => [],
  }),
  finalReport: z.string().optional(),
});

type State = z.infer<typeof StateDefinition>;

// 2. Processing nodes
async function analyzeTopic(state: State) {
  console.log('--- NODE: Analyze topic (Step 1) ---');
  return { topic: 'AI Technology' }; // Simulate LLM analysis
}

async function writeSummary(state: State) {
  console.log('--- NODE: Write summary (Parallel A) ---');
  return { insights: ['Summary: AI is changing the world.'] };
}

async function extractKeywords(state: State) {
  console.log('--- NODE: Extract keywords (Parallel B) ---');
  return { insights: ['Keywords: LLM, LangGraph, Python'] };
}

async function reportGenerator(state: State) {
  console.log('--- NODE: Generate report (Fan-in) ---');
  const report = `Topic: ${state.topic}\nDetails:\n${state.insights.join('\n')}`;
  return { finalReport: report };
}

// 3. Build the combined Graph
export const workflow = new StateGraph(StateDefinition)
  .addNode('analyze', analyzeTopic)
  .addNode('summary', writeSummary)
  .addNode('keywords', extractKeywords)
  .addNode('aggregator', reportGenerator)

  .addEdge(START, 'analyze')

  // CHAINING: analyze must finish before moving to parallel branches
  // PARALLEL: Branch from 'analyze' to both 'summary' and 'keywords'
  .addEdge('analyze', 'summary')
  .addEdge('analyze', 'keywords')

  // FAN-IN: Wait for both branches to finish before converging to aggregator
  .addEdge('summary', 'aggregator')
  .addEdge('keywords', 'aggregator')

  .addEdge('aggregator', END)
  .compile();

// 4. Execution
async function run() {
  await generateImage(
    workflow,
    'graph-ignore/scripts-07-patterns-chaining-parallel.jpg',
  );

  const result = await workflow.invoke({
    content: 'Article content about AI...',
  });

  console.log('\n=== FINAL REPORT ===\n', result.finalReport);
}

run();

IV. Khi nào nên dùng mẫu nào?

Mẫu thiết kếTrường hợp sử dụngƯu điểm
ChainingKhi bước sau bắt buộc cần dữ liệu từ bước trước.Độ chính xác cao, dễ gỡ lỗi (debug).
ParallelKhi các tác vụ độc lập với nhau.Giảm độ trễ tối đa, tăng hiệu năng.

Sơ đồ hoạt động:

Sơ đồ Chaining và Parallel

V. Tổng kết

  • Prompt Chaining giúp LLM "suy nghĩ" thấu đáo hơn qua từng bước nhỏ.
  • Parallelization biến Agent của bạn từ một "nhân viên chậm chạp" thành một "đội ngũ làm việc nhóm" hiệu quả.
  • Reducer là "chìa khóa" kỹ thuật để gộp dữ liệu từ các nhánh song song mà không làm mất thông tin.

Trong bài học tiếp theo, chúng ta sẽ tiến tới các mẫu thiết kế phức tạp và linh hoạt hơn, nơi Agent có khả năng tự lập kế hoạch và tự sửa lỗi!

👉 Bài tiếp theo: 8. Workflow Patterns II - Orchestrator & Optimizer