·

Ở các bài trước trong module này, chúng ta đã nói về vòng đời của một session đơn lẻ: khi nào nên tiếp tục (continue), khi nào nên reset, khi nào nên fork sang một nhánh mới. Bài này đặt ra một câu hỏi ở tầm cao hơn — tầm "danh mục công việc" (portfolio công việc). Giả sử bạn có một khối lượng công việc gồm nhiều phần: nên gói toàn bộ vào một cuộc hội thoại sâu, nơi mỗi turn (lượt trao đổi) kế thừa toàn bộ context (ngữ cảnh) đã tích lũy từ những turn trước? Hay nên chia nhỏ thành nhiều cuộc hội thoại độc lập, mỗi cuộc có context riêng, nhỏ gọn, chạy song song hoặc tách biệt hoàn toàn?

Đây không phải là câu hỏi "session này nên tiếp tục hay dừng" — đó là quyết định vi mô, xảy ra trong lúc làm. Câu hỏi ở đây là quyết định kiến trúc, phải đưa ra trước khi bắt đầu: tôi sẽ tổ chức toàn bộ công việc theo hình dạng nào? Một sợi chỉ dài xuyên suốt, hay nhiều sợi chỉ ngắn chạy đồng thời rồi bện lại?

Quyết định này ảnh hưởng trực tiếp đến số token (đơn vị tính phí và tính giới hạn của LLM — mô hình ngôn ngữ lớn) bạn tiêu tốn, tốc độ hoàn thành công việc, và chất lượng đầu ra cuối cùng. Chọn sai cấu trúc, bạn có thể trả gấp 3-4 lần token cần thiết, hoặc tệ hơn, nhận về một tập kết quả rời rạc, mâu thuẫn nhau mà không ai đứng ra hợp nhất.

The Core Trade-Off: Đánh đổi giữa Chiều sâu và Chiều rộng

Bản chất của quyết định này là một đánh đổi (trade-off) giữa hai chiến lược:

Chiến lược 1 — Sequential depth (chiều sâu tuần tự): Toàn bộ công việc diễn ra trong một thread (luồng hội thoại) duy nhất. Mỗi turn mới có thể tham chiếu tự do đến mọi thứ đã nói trước đó — không cần giải thích lại bối cảnh, không cần nhắc lại quy ước đặt tên, không cần dán lại đoạn code đã show ở turn 3. Ưu điểm là context được chia sẻ hoàn toàn (fully shared context). Nhược điểm: context window (cửa sổ ngữ cảnh) phình to dần theo từng turn, và vì hầu hết LLM tính phí theo tổng số token input mỗi lần gọi (bao gồm toàn bộ lịch sử hội thoại trước đó), turn thứ 20 sẽ đắt hơn turn thứ 2 rất nhiều — dù nội dung câu hỏi ở hai turn có độ phức tạp tương đương.

Chiến lược 2 — Parallel breadth (chiều rộng song song): Công việc được chia thành các phần độc lập, mỗi phần chạy trong một session riêng với context nhỏ, gọn, chỉ chứa những gì liên quan đến phần việc đó. Ưu điểm: chi phí mỗi session thấp và ổn định (không phình to), có thể chạy đồng thời để tiết kiệm thời gian thực (wall-clock time). Nhược điểm: các session không biết gì về nhau. Session A không biết session B đã quyết định gì. Điều này tạo ra hai vấn đề — (1) cần một bước synthesis (tổng hợp) tốn thêm token để ghép các đầu ra lại, và (2) rủi ro các session đưa ra quyết định không đồng nhất (một session đặt tên biến kiểu camelCase, session khác dùng snake_case; một session chọn kiến trúc REST, session khác ngầm giả định GraphQL).

Bài toán token cụ thể

Hãy hình dung con số cụ thể để thấy rõ đánh đổi. Giả sử mỗi turn "thực chất" (câu hỏi + câu trả lời hữu ích) tốn khoảng 500 token nếu đứng độc lập, không có lịch sử kèm theo.

  • Một thread sâu, N = 20 turn: Turn 1 tốn ~500 token. Turn 2 phải gửi lại toàn bộ turn 1 (giả sử input/output turn 1 ~1.000 token) cộng thêm nội dung mới, nên tốn ~1.500 token. Đến turn 20, bạn phải gửi lại gần như toàn bộ 19 turn trước — có thể lên tới 15.000-20.000 token chỉ để "nhắc lại", trong khi nội dung mới thực sự cần thiết chỉ là 500 token. Tổng chi phí cho toàn bộ 20 turn có thể lên đến hàng trăm nghìn token (tăng theo cấp số cộng dồn — cumulative), dù nhờ prompt caching (cơ chế cache lại phần prompt không đổi) chi phí thực tế trả tiền có thể được giảm bớt đáng kể so với tính "thô".
  • Chia thành k = 4 thread song song, mỗi thread 5 turn: Mỗi thread chỉ tích lũy context trong phạm vi 5 turn của riêng nó, nên chi phí tích lũy nhỏ hơn nhiều — ước tính mỗi thread tốn vài nghìn token. Bốn thread cộng lại vẫn thấp hơn một thread 20 turn rất nhiều, vì không thread nào phải "vác" toàn bộ lịch sử của 15 turn khác không liên quan đến nó. Nhưng bạn phải cộng thêm chi phí của 1 session synthesis để ghép 4 đầu ra lại — session này cần đọc tóm tắt của cả 4 nhánh, nên tốn thêm một khoản không nhỏ.

Kết luận rút ra: nếu các phần việc thực sự độc lập (không cần biết chi tiết suy luận của nhau), chia nhỏ luôn rẻ hơn về token và nhanh hơn về thời gian thực. Nhưng nếu các phần việc phụ thuộc chặt vào nhau (turn sau cần hiểu sâu lý do turn trước), chia nhỏ sẽ phá vỡ dòng suy luận, buộc bạn phải tóm tắt lại thủ công — và nếu tóm tắt thiếu sót, chất lượng đầu ra giảm nghiêm trọng, tốn kém hơn nhiều so với số token tiết kiệm được.

Mẹo

  • Trước khi bắt đầu một khối lượng công việc lớn, hãy tự hỏi: "Nếu tôi giao phần B cho một người khác chỉ đọc tóm tắt phần A (không đọc toàn bộ hội thoại), họ có làm đúng phần B không?" Nếu có — chia song song được. Nếu không — cần chiều sâu tuần tự.
  • Đừng chỉ so token của các nhánh song song mà quên cộng chi phí session synthesis — đây là chi phí ẩn dễ bị bỏ sót khi ước lượng tổng ngân sách token.
  • Với các LLM có hỗ trợ prompt caching, chi phí thực tế của một thread dài có thể thấp hơn tính toán "thô" ở trên khá nhiều — nhưng vẫn tăng dần theo độ dài, nên nguyên tắc đánh đổi vẫn đúng về xu hướng.

Khi nào Chiều sâu tuần tự (Sequential Depth) chiến thắng

Các dạng phụ thuộc chặt (Strong interdependency patterns)

Có những loại công việc mà mỗi bước thực sự cần biết kết quả suy luận đầy đủ của bước trước, không chỉ cần kết luận cuối mà cần cả lý do dẫn đến kết luận đó. Đặc điểm nhận diện:

  • Debug lặp theo giả thuyết: Bạn đưa ra giả thuyết A, kiểm tra, loại nó, chuyển sang giả thuyết B — nhưng để loại đúng giả thuyết B, model cần nhớ chính xác tại sao giả thuyết A bị loại (log nào, test nào, kết quả nào). Nếu tách sang session mới, bạn phải chép lại toàn bộ log điều tra — tốn công hơn là giữ nguyên trong một thread.
  • Thảo luận thiết kế tiến hóa qua nhiều vòng: Một bản thiết kế API được góp ý, sửa, góp ý tiếp, sửa tiếp — mỗi vòng chỉnh sửa dựa trên đúng những gì đã thống nhất ở vòng trước, kể cả những phương án đã bị bác bỏ (để tránh đề xuất lại).
  • Refactor có tính lịch sử: Đổi tên một hàm xuyên suốt codebase, xử lý từng file một, nhưng quyết định ở file thứ 10 phải nhất quán với quyết định ở file thứ 2 (ví dụ: cách xử lý một edge case đặc biệt đã được thống nhất từ đầu).

Dấu hiệu nhận biết chung: nếu bạn thử tóm tắt trạng thái hiện tại cho một người mới tham gia giữa chừng, bản tóm tắt đó sẽ dài gần bằng toàn bộ lịch sử gốc — nghĩa là không có gì để "cắt gọn", công việc này vốn dĩ tuần tự và tích lũy.

Ví dụ chiều sâu tuần tự theo từng vai trò

Software Engineer — Debug flaky test: Một test tự động thất bại ngẫu nhiên (flaky test) trong CI. Turn 1: engineer mô tả hiện tượng, model đề xuất giả thuyết "có thể do race condition khi hai async task chạy song song". Turn 2: engineer chạy lại 20 lần, thấy tỷ lệ fail 15%, gửi log — model loại giả thuyết race condition (log không cho thấy dấu hiệu đó), chuyển sang giả thuyết "test phụ thuộc vào thứ tự chạy của các test khác (test order dependency)". Turn 3: engineer chạy riêng lẻ test đó 50 lần, không fail lần nào — xác nhận giả thuyết đúng, model đề xuất kiểm tra shared state (biến static, singleton, database chưa được reset giữa các test). Turn 4: engineer tìm thấy một biến cache tĩnh không được clear. Mỗi turn phụ thuộc chặt vào turn trước — nếu tách turn 3 ra một session mới, engineer phải chép lại toàn bộ diễn biến giả thuyết 1 và 2 đã bị loại như thế nào, nếu không model có thể đề xuất lại chính giả thuyết đã bị bác bỏ.

QA Engineer — Tinh chỉnh test plan qua nhiều vòng review: QA lead soạn bản test plan đầu tiên cho một tính năng thanh toán mới. Turn 1: model giúp soạn khung test plan với các nhóm test case (happy path, edge case, security). Turn 2: sau khi trình bày cho team, QA lead nhận góp ý "thiếu test case cho trường hợp thanh toán trùng lặp (duplicate payment) khi mạng chập chờn" — model bổ sung, đồng thời điều chỉnh lại các mục liên quan (ví dụ mục rollback transaction) để nhất quán với bổ sung mới. Turn 3: một góp ý khác về việc cần test với nhiều loại thẻ khác nhau — model bổ sung tiếp, đồng thời tự kiểm tra chéo xem có trùng lặp với các test case đã có ở turn 1 không. Việc "tự kiểm tra chéo" này chỉ làm được chính xác nếu model còn nhớ toàn bộ các test case trước đó trong cùng context.

Product Manager — Tinh chỉnh phạm vi PRD qua nhiều vòng phản hồi: PM soạn PRD (Product Requirements Document) cho một tính năng mới. Turn 1: model giúp phác thảo phạm vi ban đầu (scope) dựa trên brief từ PM. Turn 2: sau khi gửi cho engineering lead, nhận phản hồi "phần X quá phức tạp để làm trong sprint này, nên tách ra phase 2" — model điều chỉnh lại toàn bộ document, đồng thời phải nhớ những phần khác đã phụ thuộc vào phần X (ví dụ một success metric đo lường tính năng X) để cập nhật đồng bộ. Turn 3: nhận phản hồi từ sales rằng phase 2 cần đẩy sớm hơn — model cần nhớ lý do ban đầu tách phase 2 ở turn 2 để đánh giá đúng mức độ ảnh hưởng khi đẩy sớm.

Mẹo

  • Khi nhận ra một công việc thuộc dạng phụ thuộc chặt, đừng ngắt session giữa đường chỉ vì context window đang phình to — hãy dùng các kỹ thuật tóm tắt/nén context (đã học ở các bài trước của module) để giữ thread sống lâu hơn mà không tốn quá nhiều token.
  • Nếu buộc phải chia nhỏ một công việc phụ thuộc chặt (ví dụ vì giới hạn context cứng), hãy viết một bản "biên bản quyết định" (decision log) tường minh ở cuối mỗi session, liệt kê rõ giả thuyết nào đã bị loại và vì sao — đây là cách rẻ nhất để mang theo "chiều sâu" sang session mới.
  • Trước khi bắt đầu, tự hỏi "việc này có tính lặp/tích lũy hay không" — nếu có, ưu tiên chiều sâu tuần tự ngay từ đầu, đừng để giữa đường mới nhận ra và phải quay lại chép sử.

Khi nào Chiều rộng song song (Parallel Breadth) chiến thắng

Các dạng công việc độc lập (Independent task patterns)

Ngược lại với phần trên, có nhiều loại công việc mà các phần con không cần biết suy luận chi tiết của nhau, chỉ cần được ghép lại ở bước cuối. Dấu hiệu nhận diện:

  • Các phần việc thao tác trên đối tượng khác nhau, không chia sẻ trạng thái (ví dụ: viết unit test cho module A và module B, khi A và B không gọi lẫn nhau).
  • Việc chỉ cần kết quả cuối, không cần biết đường đi (ví dụ: nghiên cứu 3 thư viện logging khác nhau để so sánh — không cần biết model "nghĩ" thế nào trong lúc đọc docs của từng thư viện, chỉ cần bản tóm tắt ưu/nhược điểm).
  • Các phần việc có thể hoán đổi thứ tự mà không ảnh hưởng đến kết quả (nếu làm phần B trước phần A cũng ra kết quả tương đương) — đây là dấu hiệu mạnh cho thấy không có phụ thuộc thực sự.

Ví dụ chiều rộng song song theo từng vai trò

Software Engineer — Triển khai nhiều tính năng/bugfix nhỏ độc lập: Sprint có 4 task nhỏ: sửa lỗi hiển thị sai định dạng ngày ở trang profile, thêm validation cho form đăng ký, tối ưu query chậm ở trang báo cáo, và viết lại một hàm util bị deprecate. Bốn task này chạm vào bốn phần khác nhau của codebase, không phụ thuộc lẫn nhau. Engineer mở 4 session riêng (có thể chạy song song nếu công cụ hỗ trợ, hoặc xử lý nối tiếp nhưng tách biệt về context), mỗi session chỉ cần context của file/module liên quan đến task đó — không cần mang theo chi tiết về 3 task còn lại, giúp mỗi session nhẹ và rẻ.

QA Engineer — Test độc lập nhiều module/API: Cần kiểm thử 5 API endpoint độc lập của một hệ thống microservices (mỗi endpoint thuộc một service khác nhau, không gọi chéo nhau trong luồng test). QA mở 5 session, mỗi session tập trung viết test case và test script cho một endpoint, chỉ cần spec của endpoint đó. Việc này tránh được tình trạng một session khổng lồ chứa spec của cả 5 endpoint (rất tốn token cho mỗi turn khi chỉ đang làm việc với 1 trong số đó).

Product Manager — Nghiên cứu cạnh tranh độc lập nhiều đối thủ: PM cần đánh giá 4 đối thủ cạnh tranh trên thị trường để chuẩn bị cho một buổi họp chiến lược. Mỗi đối thủ có mô hình kinh doanh, tính năng, định giá khác nhau, không liên quan trực tiếp đến nhau. PM mở 4 session, mỗi session nghiên cứu sâu 1 đối thủ (đọc trang giá, đọc review, đọc changelog sản phẩm), sau đó tổng hợp 4 bản báo cáo riêng thành một bản so sánh tổng thể ở bước sau.

Mẹo

  • Trước khi chia song song, hãy phác nhanh danh sách "các phần việc" và tự kiểm tra xem có phần nào ngầm giả định thông tin từ phần khác không (ví dụ: cả 4 bugfix có cùng dùng một hằng số cấu hình mà bạn định đổi ở một trong số đó không) — nếu có, phải xử lý phần đó trước hoặc gộp lại.
  • Đặt tên session/thread rõ ràng theo phần việc (ví dụ "session-fix-date-format", "session-api-validation") để dễ quản lý khi bạn có nhiều session mở song song.
  • Chuẩn bị sẵn một "khung chia sẻ tối thiểu" (ví dụ: coding convention, format tài liệu chung) và dán vào đầu mỗi session song song — điều này giúp giảm rủi ro mâu thuẫn ở bước synthesis mà không cần biến các session thành phụ thuộc chặt.

Bước Synthesis: Hợp nhất các Đầu ra Song song

Chiều rộng song song luôn cần một bước synthesis (tổng hợp) — bước lấy các đầu ra rời rạc từ nhiều session độc lập và ghép chúng thành một thể thống nhất. Đây là bước dễ bị bỏ quên khi lập ngân sách token: người ta thường chỉ tính tổng token của các session song song mà quên rằng còn cần một session (hoặc nhiều bước) riêng để đọc lại, so sánh, và hợp nhất tất cả — và session này, dù ngắn, vẫn phải "nạp" đủ thông tin từ mọi nhánh để làm việc hiệu quả.

Session synthesis trực tiếp

Cách làm gọn nhất: mở một session sạch, nhiệm vụ duy nhất là nhận đầu ra tóm tắt của từng session song song và ghép/thống nhất chúng — không tải toàn bộ log chi tiết của từng session (điều đó sẽ làm session synthesis phình to không cần thiết), chỉ cần bản tóm tắt kết quả cuối của mỗi nhánh.

Ví dụ cấu trúc prompt cho session synthesis, sau khi đã hoàn thành 4 session song song viết bugfix ở ví dụ trên:

You are synthesizing outputs from 4 independent parallel sessions that
each fixed a separate small bug/feature in the same codebase this sprint.

Session 1 summary (date format fix):
- Changed formatDate() in utils/date.ts to use ISO 8601 consistently
- Added a unit test covering timezone edge cases

Session 2 summary (registration form validation):
- Added client-side validation for email and phone fields in
  RegistrationForm.tsx using the existing `validators` module
- No shared files touched outside RegistrationForm.tsx

Session 3 summary (slow report query optimization):
- Added an index on `reports.created_at` and rewrote the query to
  avoid an N+1 pattern in ReportService.ts

Session 4 summary (deprecated util rewrite):
- Replaced `legacyFormatCurrency()` calls across 6 files with the new
  `formatCurrency()` util; removed the deprecated function

Task:
1. Check whether any of these 4 changes touch overlapping files or
   could conflict with each other (e.g., does Session 4's removal of
   legacyFormatCurrency() affect any file touched by Sessions 1-3?).
2. If everything is independent, produce a single consolidated PR
   description covering all 4 changes, grouped clearly by concern.
3. Flag anything that needs a follow-up check before merging.

Cấu trúc này giữ session synthesis nhẹ: nó không cần biết quá trình mỗi session đi đến kết quả, chỉ cần kết quả và đủ chi tiết để phát hiện xung đột.

Xử lý xung đột trong Synthesis

Vấn đề khó hơn là khi các session song song đưa ra kết quả mâu thuẫn nhau — ví dụ hai session dùng hai quy ước đặt tên khác nhau (một dùng camelCase, một dùng snake_case cho tên field API), hoặc hai session đề xuất hai kiến trúc khác nhau cho một vấn đề tương tự (một chọn xử lý bất đồng bộ bằng queue, một chọn xử lý đồng bộ trực tiếp).

Cách làm thực tế: đừng để model tự âm thầm chọn một bên — hãy đưa xung đột ra rõ ràng, cho cả model (và người quyết định cuối, thường là bạn) thấy cả hai phương án cạnh nhau, sau đó đưa ra quyết định tường minh, rồi áp dụng nhất quán ngược lại vào cả hai nhánh.

Ví dụ prompt xử lý xung đột, khi hai session nghiên cứu độc lập đề xuất hai cách đặt tên field khác nhau cho cùng một API mới:

Two parallel research sessions each proposed a naming convention for
the new `/api/orders` response fields:

Session A proposed: order_id, created_at, total_amount (snake_case)
Session B proposed: orderId, createdAt, totalAmount (camelCase)

This is a direct conflict — the API cannot use both. Before I decide,
tell me:
1. What convention does the rest of our existing API surface use
   (check the OpenAPI spec I'm attaching)?
2. Is there a strong technical reason to deviate from that existing
   convention here?

Once I confirm the convention, rewrite BOTH session outputs to use
the chosen one consistently, and list every field name that needs
to change in each.

Điểm mấu chốt: quyết định xung đột không nên "chìm" trong bước synthesis mà không ai để ý — nó cần được nêu tên cụ thể, có căn cứ để quyết (ví dụ tham chiếu convention đã có sẵn trong hệ thống), và áp dụng lại đồng bộ, tránh tình trạng nửa hệ thống theo chuẩn này, nửa theo chuẩn khác.

Mẹo

  • Luôn yêu cầu mỗi session song song kết thúc bằng một bản tóm tắt ngắn, có cấu trúc cố định (ví dụ: "Files changed", "Key decisions", "Assumptions made") — điều này giúp session synthesis không cần đọc lại toàn bộ log dài dòng.
  • Khi phát hiện xung đột, đừng chỉ chọn một bên vì "trông hợp lý hơn" — hãy tìm căn cứ khách quan (convention hiện có, tài liệu chuẩn, ý kiến người có thẩm quyền) trước khi quyết.
  • Tính trước một khoản token dự phòng (buffer) cho bước synthesis khi lập kế hoạch — kinh nghiệm thực tế cho thấy bước này thường bị đánh giá thấp hơn thực tế 30-50%, đặc biệt khi số nhánh song song lớn hơn 3-4.

Cấu trúc lai: Kết hợp Tuần tự và Song song

Trong thực tế, rất ít công việc thuần túy 100% chiều sâu hoặc 100% chiều rộng. Hầu hết công việc lớn có cấu trúc lai (hybrid): một phần cần sự thống nhất chung, một phần có thể tách rời để làm nhanh.

Mô hình lai theo giai đoạn (The phased hybrid model)

Mô hình phổ biến và hiệu quả nhất là chia công việc thành 3 giai đoạn:

  1. Giai đoạn "định hình" (framing) — tuần tự: Một session (hoặc một chuỗi session ngắn) để thống nhất các ràng buộc chung: schema dữ liệu, quy ước đặt tên, kiến trúc tổng thể, phạm vi của từng phần con. Đây là giai đoạn tuần tự vì các quyết định ở đây ảnh hưởng đến tất cả các nhánh sau.
  2. Giai đoạn "thực thi" (execution) — song song: Dựa trên khung đã thống nhất ở giai đoạn 1, mở nhiều session độc lập, mỗi session làm một phần con, không cần biết chi tiết các phần khác — chỉ cần tuân theo khung chung đã có.
  3. Giai đoạn "hợp nhất" (integration) — tuần tự: Một (hoặc vài) session synthesis, ghép các đầu ra của giai đoạn 2 lại, xử lý xung đột (nếu có), và đánh bóng (polish) lần cuối để đảm bảo tính nhất quán toàn thể.

Ví dụ cụ thể cho một tính năng phần mềm nhiều phần — xây dựng tính năng "thông báo trong ứng dụng" (in-app notifications) gồm: backend API lưu và trả thông báo, frontend hiển thị danh sách thông báo, hệ thống gửi email khi có thông báo quan trọng, và cập nhật tài liệu API cho team khác dùng.

  • Giai đoạn định hình (1 session tuần tự, ~5-8 turn): Thống nhất schema của một Notification object (các field: id, type, message, read_at, created_at), thống nhất API contract (GET /notifications, POST /notifications/:id/read), thống nhất quy ước khi nào một thông báo được coi là "quan trọng" (trigger gửi email). Kết quả giai đoạn này là một bản "spec khung" ngắn gọn, đủ để bất kỳ ai đọc cũng hiểu công việc của phần mình.
  • Giai đoạn thực thi (4 session song song): Session A viết backend API dựa trên schema đã thống nhất. Session B viết frontend component hiển thị danh sách, chỉ cần biết API contract từ spec khung, không cần biết backend triển khai nội bộ ra sao. Session C viết logic gửi email, chỉ cần biết field nào đánh dấu "quan trọng". Session D viết tài liệu API, chỉ cần bản spec khung để mô tả đúng.
  • Giai đoạn hợp nhất (1 session tuần tự): Đọc tóm tắt từ 4 session, kiểm tra xem backend (session A) có thực sự trả đúng field mà frontend (session B) mong đợi không, kiểm tra logic "quan trọng" ở session C có khớp với field đã định nghĩa ở spec khung không, chỉnh sửa các điểm lệch, và hoàn thiện PR mô tả tổng thể.

Với PM soạn PRD nhiều phần (ví dụ PRD cho một tính năng lớn gồm phần "trải nghiệm người dùng", "yêu cầu kỹ thuật", "chỉ số thành công", "kế hoạch ra mắt"), mô hình tương tự: giai đoạn định hình thống nhất mục tiêu chung và phạm vi tổng thể của tính năng (1 session), giai đoạn thực thi mở các session riêng để viết chi tiết từng phần (mỗi phần cần chuyên môn/nguồn dữ liệu khác nhau — UX research, engineering estimate, data/analytics, go-to-market), giai đoạn hợp nhất ghép 4 phần vào một PRD hoàn chỉnh, rà soát để các phần không mâu thuẫn (ví dụ: kế hoạch ra mắt không được giả định một tính năng mà phần yêu cầu kỹ thuật đã đánh dấu là "phase 2, chưa làm").

Mẹo

  • Đầu tư kỹ vào giai đoạn định hình — đây là giai đoạn rẻ nhất về token (thường chỉ vài turn) nhưng có ảnh hưởng lớn nhất đến việc giảm xung đột ở giai đoạn hợp nhất. Một khung tốt giúp giai đoạn thực thi song song trơn tru hơn rất nhiều.
  • Xuất bản khung (spec khung) đã thống nhất ra một đoạn văn bản độc lập (không phải chỉ nằm rải rác trong hội thoại) để dán vào đầu mỗi session thực thi — đừng bắt mỗi session tự suy luận lại khung từ đầu.
  • Nếu trong lúc thực thi song song phát hiện khung ban đầu có lỗ hổng (ví dụ thiếu một field quan trọng), đừng để mỗi session tự vá theo cách riêng — quay lại một session ngắn để sửa khung chung, rồi truyền lại cho các session còn lại.

Bảng So sánh Chi phí Token: Hướng dẫn Ra quyết định

Để có cảm nhận cụ thể hơn, hãy so sánh 3 chiến lược cho một công việc gồm 5 phần (ví dụ 5 module cần viết test, hoặc 5 phần của một tài liệu), ước lượng mỗi phần cần khoảng 8 turn thực chất để hoàn thành nếu làm riêng.

Chiến lược A — Một thread tuần tự 40 turn (5 phần × 8 turn, gộp lại làm nối tiếp trong cùng 1 session): Chi phí input token tăng dần theo cấp số cộng dồn vì mỗi turn phải mang theo toàn bộ 39 turn trước. Ước lượng thô (chưa tính cache): nếu turn "độc lập" tốn ~500 token, tổng input tích lũy cho 40 turn có thể lên đến hàng trăm nghìn token — con số cụ thể phụ thuộc nhiều vào việc có prompt caching hay không, nhưng xu hướng là chi phí per-turn cuối cùng đắt hơn per-turn ban đầu 10-20 lần.

Chiến lược B — 5 thread song song, mỗi thread 8 turn + 1 session synthesis: Mỗi thread chỉ tích lũy context trong phạm vi 8 turn của chính nó, nên chi phí mỗi thread thấp hơn nhiều — ước lượng vài nghìn token mỗi thread, tổng 5 thread thấp hơn đáng kể so với chiến lược A. Cộng thêm 1 session synthesis (đọc 5 bản tóm tắt, ghép lại, xử lý xung đột nếu có) — chi phí session này phụ thuộc vào độ dài tóm tắt nhưng thường nhỏ hơn nhiều so với việc đọc lại toàn bộ 40 turn gốc. Tổng chi phí chiến lược B thường thấp hơn đáng kể so với A khi 5 phần thực sự độc lập, và nhanh hơn về thời gian thực nếu chạy đồng thời.

Chiến lược C — Lai theo giai đoạn: 1 session định hình (~6 turn) + 5 thread song song (~7 turn/thread, ngắn hơn B một chút vì không cần tự suy luận khung) + 1 session hợp nhất: Chi phí giai đoạn định hình nhỏ, giúp giảm turn cần thiết ở mỗi thread song song (vì không phải tự đoán các ràng buộc chung), và giảm xung đột ở giai đoạn hợp nhất (ít việc phải sửa lại). Trong hầu hết trường hợp thực tế có tính phụ thuộc một phần (partial interdependency), chiến lược C cho tỷ lệ chi phí/chất lượng tốt nhất.

Checklist quyết định

Dùng danh sách sau để chọn chiến lược phù hợp cho một khối công việc mới:

  1. Các phần việc có chia sẻ trạng thái/quyết định quan trọng không? Có → cần ít nhất một giai đoạn tuần tự (định hình). Không → có thể bỏ qua giai đoạn định hình, chia song song ngay.
  2. Mỗi phần việc có thể được một người khác hoàn thành chỉ với một bản tóm tắt ngắn (không cần đọc toàn bộ lịch sử) không? Có → song song khả thi. Không → cần chiều sâu tuần tự cho phần đó.
  3. Số phần việc độc lập là bao nhiêu? Từ 3 phần trở lên, chi phí synthesis thường vẫn nhỏ hơn chi phí "vác" toàn bộ lịch sử trong một thread dài — nghiêng về song song hoặc lai.
  4. Công việc có cần kết quả nhất quán cao (ví dụ: một API contract, một bộ quy ước code) không? Có → bắt buộc có giai đoạn định hình trước khi tách song song, dù chỉ 1 session ngắn.
  5. Bạn có công cụ/khả năng chạy nhiều session thực sự đồng thời không? Nếu không (chỉ có thể làm nối tiếp), lợi ích về thời gian thực của chiến lược song song giảm đi, nhưng lợi ích về token vẫn giữ nguyên — vẫn nên tách nếu các phần độc lập.

Mẹo

  • Khi không chắc, hãy nghiêng về mô hình lai theo giai đoạn — chi phí giai đoạn định hình thường rất nhỏ so với rủi ro phải sửa lại toàn bộ vì thiếu sự nhất quán ban đầu.
  • Ghi lại (dù chỉ trong đầu, hoặc tốt hơn là bằng văn bản) ước lượng số turn dự kiến cho mỗi chiến lược trước khi bắt đầu — điều này giúp bạn phát hiện sớm khi một thread "sâu" đang phình to vượt dự kiến, để kịp chuyển hướng sang tách nhỏ.
  • Theo dõi thực tế sau vài lần áp dụng: nếu bạn liên tục thấy bước synthesis tốn nhiều token/thời gian hơn dự kiến, đó là dấu hiệu công việc của bạn có tính phụ thuộc chặt hơn bạn nghĩ ban đầu — lần sau nên nghiêng về chiều sâu tuần tự hoặc đầu tư mạnh hơn vào giai đoạn định hình.