Tôi cứ ngỡ mình thật thông minh. Tôi đã viết một hàm bổ trợ để dành chính xác 30% cửa sổ ngữ cảnh làm ngân sách suy nghĩ (thinking budget) cho pipeline AI của chúng tôi. Nó rất gọn gàng, dễ dự đoán và hoạt động cực kỳ mượt mà trên Opus 4.5. Thế rồi tôi chuyển sang Opus 4.8 và mọi yêu cầu đều chết đứng với lỗi 400. Những phép tính token được tôi tính toán kỹ lưỡng đã trở thành rác rưởi chỉ sau một đêm.

Mô hình cũ rất đơn giản. Bạn thiết lập một giá trị budget_tokens và mô hình sẽ phân bổ việc suy nghĩ của nó để nằm trong giới hạn đó. Nếu tôi đưa vào một ngữ cảnh 128K, mã của tôi sẽ trích ra khoảng 38.000 token cho việc suy luận và để lại phần còn lại cho câu trả lời. Cảm giác rất có trách nhiệm, giống như việc giữ tốc độ xe dưới giới hạn cho phép vậy.

Mô hình đó đã không còn nữa. Các bản phát hành mới hơn như Opus 4.7 và 4.8 sử dụng tư duy thích ứng (adaptive thinking). Bạn không còn chọn một con số nữa. Thay vào đó, bạn truyền vào một nút điều chỉnh nỗ lực (effort knob). Nghe có vẻ như chỉ là đổi tên, nhưng hai cơ chế điều khiển này không thể khác biệt hơn. budget_tokens thiết lập một trần cứng về lượng suy nghĩ mà mô hình được phép thực hiện. Còn Effort (nỗ lực) kiểm soát cách mô hình suy nghĩ và hành động ngay từ đầu. Một cái là đồng hồ đo tại trạm xăng, cái còn lại là bản đồ điều khiển động cơ (engine map).

Ánh xạ Nỗ lực vào Công việc Thực tế

Khi cơ chế điều khiển thay đổi, trực giác cũ của tôi không còn tác dụng. Tôi phải học lại xem mỗi thiết lập thực sự mang lại điều gì. Tôi đã chạy thử nghiệm trên lưu lượng truy cập nội bộ để tìm xem mỗi mức nỗ lực sẽ nằm ở đâu trong thực tế.

Phân loại và định tuyến (Classification and routing) hầu như luôn nên sử dụng mức nỗ lực low. Những tác vụ này là những quyết định nhanh. Đây là yêu cầu hoàn tiền hay là một câu hỏi bán hàng? Mục nhật ký này có cần leo thang không? Bạn không cần một bài độc thoại. Mức nỗ lực thấp giúp giảm độ trễ và giữ chi phí ở mức cực thấp.

Hầu hết lưu lượng ứng dụng, các công việc hàng ngày như tóm tắt, viết lại, trả lời hỗ trợ và trích xuất nội dung, phù hợp với mức nỗ lực từ medium đến high. Đây là điểm cân bằng. Mô hình có đủ không gian để giải quyết các sự mơ hồ thực sự mà không lãng phí token vào một tác vụ không cần chuỗi suy nghĩ kéo dài.

Lập trình và các vòng lặp tác nhân (agentic loops) cần mức nỗ lực xhigh. Đây là nơi các sai lầm sẽ bị cộng dồn. Nếu mô hình viết một kế hoạch tồi ngay trong lượt đầu tiên của một vòng lặp gọi công cụ (tool-calling loop), nó sẽ mất ba bước tiếp theo để sửa chữa thiệt hại. Hoặc tệ hơn, nó sẽ gọi sai công cụ, ảo tưởng tham số (hallucinate parameters) và khiến người dùng phải nhìn chằm chằm vào một quy trình làm việc bị hỏng. Khả năng suy luận tốt ngay từ đầu sẽ ngăn chặn vòng xoáy đó.

Các tác vụ quan trọng nên được cấp mức nỗ lực max. Đừng dùng mức này cho mọi thứ. Hãy dành nó cho những khoảnh khắc mà một câu trả lời sai sẽ gây tốn kém hơn bất kỳ hóa đơn token nào. Đối soát tài chính, kiểm tra an toàn, quyết định kiến trúc và phân loại y tế (medical triage) là những trường hợp phù hợp. Nếu một lỗi xảy ra đồng nghĩa với việc con người phải mất hàng giờ để gỡ rối, hãy trả thêm tiền cho việc suy nghĩ kỹ hơn.

Sự bất ngờ về chi phí

Đây là phần đã phá vỡ mô hình tư duy của tôi. Tôi đã giả định rằng mức nỗ lực tối đa (max effort) sẽ luôn làm chi phí tăng vọt. Trong một lượt đơn lẻ, đúng là như vậy. Vết suy luận (reasoning trace) sẽ dài hơn. Nhưng đối với các tác vụ tác nhân đa bước, tổng hóa đơn thường lại giảm xuống.

Mô hình lập kế hoạch tốt hơn ngay từ lần thử đầu tiên. Nó thực hiện ít lần gọi công cụ hơn. Nó tự ngăn mình không đi vào những ngõ cụt. Tôi đã quan sát một tác nhân trích xuất dữ liệu mà bình thường cần năm lượt trao đổi qua lại, nay đã hoàn thành chỉ trong hai lượt vì mô hình có đủ không gian suy luận để phân tích đúng schema ngay từ đầu. Khi đo lường chi phí, hãy nhìn vào việc hoàn thành công việc, chứ đừng nhìn vào từng yêu cầu. Một ngân sách suy nghĩ lớn hơn cho mỗi bước có thể đồng nghĩa với việc tổng số bước sẽ ít đi.

Cách di chuyển mà không làm hỏng mọi thứ khác

Nếu bạn vẫn còn budget_tokens nằm rải rác trong mã nguồn của mình, đây là lộ trình chính xác để thoát ra. Đừng bỏ qua bước ba và bước năm. Tôi đã từng bỏ qua, và nó đã khiến tôi mất cả một buổi chiều để gỡ lỗi.

Tìm kiếm budget_tokens trong mã nguồn của bạn. Mọi thực thể cần phải được loại bỏ. Tham số này đã lỗi thời trên các mô hình mới và sẽ gây ra lỗi 400.

Thay thế đối tượng budget bằng một khối tư duy thích ứng (adaptive thinking block). Sử dụng thinking: { type: "adaptive" }.

Thêm output_config với mức nỗ lực rõ ràng cho mỗi lần gọi. Đừng để nó theo mặc định toàn cục nếu lưu lượng truy cập của bạn là hỗn hợp. Endpoint phân loại nhẹ nhàng của bạn không nên vô tình thừa hưởng cùng một thiết lập nỗ lực như tác nhân lập trình của bạn. Hãy chỉ định rõ ràng tại nơi gọi (call site).

Xóa hàm bổ trợ tính toán ngân sách của bạn. Tôi biết. Có thể nó có cả các bài kiểm tra đơn vị (unit tests). Của tôi cũng vậy. Nhưng giờ nó chỉ là gánh nặng thừa thãi. Nền tảng không muốn các phép tính token của bạn. Mô hình sẽ tự điều tiết tốc độ của chính nó.

Loại bỏ temperature, top_p, và top_k. Trên Opus 4.7 và 4.8, các tham số lấy mẫu này sẽ gây ra lỗi 400. Nền tảng đã loại bỏ chúng khỏi thế hệ này. Các mẹo tinh chỉnh temperature cũ của bạn sẽ không còn áp dụng được ở đây, và nếu để chúng lại, quá trình chuyển đổi của bạn sẽ bị lỗi một cách âm thầm.

Kiểm tra từng mô hình một cách riêng biệt. Opus 4.5 và 4.8 là hai thực thể hoàn toàn khác nhau. Một cấu hình hoạt động trên mô hình này chưa chắc đã hoạt động trên mô hình kia. Nếu bạn hỗ trợ nhiều phiên bản, hãy phân nhánh logic hoặc xử lý chúng như các backend riêng biệt.

Khắc phục tình trạng UI bị treo

Có một hành vi streaming sẽ khiến người dùng bối rối nếu bạn không xử lý nó. Trên các mô hình mới, các khối suy nghĩ (thinking blocks) được truyền ra nhưng văn bản mặc định lại trống rỗng. Trong giao diện của bạn, điều này trông giống như một khoảng dừng dài, khó chịu mà không có tiến trình hiển thị nào. Người dùng sẽ cho rằng ứng dụng đã bị treo.

Để khắc phục, hãy truyền thinking: { type: "adaptive", display: "summarized" }. Điều này sẽ giúp bạn có một chỉ báo tiến trình hiển thị được mà không cần đổ toàn bộ luồng suy nghĩ thô vào cửa sổ chat. Frontend của bạn vẫn duy trì được sự phản hồi và người dùng sẽ biết rằng có điều gì đó đang diễn ra ở phía sau.

Bài học thực sự

Tôi đã xây dựng cả một lớp trừu tượng (abstraction layer) dựa trên một tham số mà nhà cung cấp chưa bao giờ có ý định duy trì lâu dài. Tôi đã bao bọc các cài đặt của họ trong logic riêng của mình vì tôi nghĩ rằng mình hiểu rõ sự đánh đổi tốt hơn nền tảng. Nhưng tôi đã lầm. Adaptive thinking là một lựa chọn tốt hơn vì mô hình thực sự tự quyết định khi nào cần suy luận sâu và khi nào có thể vận hành bình thường. Mã nguồn của tôi giờ đây gọn nhẹ hơn. Kết quả thì sắc bén hơn. Đôi khi, bước đi kỹ thuật đúng đắn nhất là xóa bỏ những đoạn code "thông minh" và để nền tảng thực hiện công việc của nó.

Nếu bạn muốn đọc các ghi chú chuyển đổi gốc, bạn có thể tìm thấy chúng tại đây. Để tham gia thêm các cuộc thảo luận thực tế như thế này, hãy tham gia cộng đồng GyaanSetu AI trên Telegram.