Từ Cầu Cổng Vàng đến JSON Bị Hỏng- Tại sao SAE Steering của Anthropic Thất bại với Đầu ra Có Cấu trúc

Bài viết phân tích lý do tại sao SAE Steering của Anthropic không hiệu quả với đầu ra có cấu trúc.

  • 39 min read
Từ Cầu Cổng Vàng đến JSON Bị Hỏng- Tại sao SAE Steering của Anthropic Thất bại với Đầu ra Có Cấu trúc
Bài viết phân tích lý do tại sao SAE Steering của Anthropic không hiệu quả với đầu ra có cấu trúc.

Từ Cầu Cổng Vàng đến JSON Lỗi: Tại Sao Phương Pháp Điều Hướng SAE của Anthropic Thất Bại Với Kết Quả Có Cấu Trúc

Một bài đăng trên blog của Maziyar Panahi trên Hugging Face

Hành trình 6 Thử Nghiệm Từ 86.8% Đến 24.4% JSON Hợp Lệ (Và Làm Thế Nào Tôi Đạt Được 100% Cuối Cùng)


Sau sáu thử nghiệm và hàng tá lần thất bại, tôi đã học được một điều bất ngờ: phương pháp điều hướng kích hoạt, kỹ thuật mà Anthropic sử dụng cho an toàn AI, hoàn toàn thất bại đối với một trong những nhiệm vụ phổ biến nhất trong việc triển khai LLM sản xuất: tạo JSON hợp lệ.

Và tôi không có ý nói “thất bại trong việc hữu ích”. Phương pháp chỉ điều hướng của tôi đạt 24.4% JSON hợp lệ, so với 86.8% của mô hình cơ sở hoàn toàn chưa được đào tạo. Điều hướng làm cho mô hình tệ hơn cả việc không làm gì cả.

Đây là những gì tôi đã học, tại sao nó lại quan trọng, và điều gì thực sự hiệu quả khi bạn cần kết quả đầu ra có cấu trúc được đảm bảo từ các mô hình ngôn ngữ chỉ có bộ giải mã.

Lời Hứa (Và Vấn Đề)

Các LLM bộ giải mã hiện đại có thể tạo dữ liệu có cấu trúc (JSON, XML, YAML) với kết quả ấn tượng. Tinh chỉnh một mô hình như Qwen2.5-0.5B của Qwen cho nhiệm vụ của bạn, và bạn có thể thấy tỷ lệ đầu ra JSON hợp lệ là 96-97%. Đối với các bản demo nghiên cứu, điều đó thật tuyệt vời. Đối với các hệ thống sản xuất tự động phân tích các kết quả đầu ra này? Không hẳn vậy.

Tỷ lệ lỗi 3-4% đó có nghĩa là các trình phân tích bị lỗi, các lệnh gọi API thất bại, hư hỏng dữ liệu thầm lặng và các cảnh báo lúc 3 giờ sáng cho kỹ sư ứng trực của bạn.

Hình 1: Vấn đề JSON trong Sản xuất

Đầu vào người dùng → LLM → Trình phân tích JSON → Cơ sở dữ liệu ↓ (Tỷ lệ lỗi 3-4%) 💥 Lỗi 500

Khi tôi bắt đầu nghiên cứu này, phương pháp điều hướng kích hoạt có vẻ là một giải pháp hoàn hảo. Anthropic vừa công bố công trình nghiên cứu của họ về Bộ Tự Mã hóa Thưa thớt (SAE), cho thấy cách điều hướng có thể khiến Claude ám ảnh về Cầu Cổng Vàng, giảm đầu ra có hại và sửa đổi các đặc điểm tính cách, tất cả mà không cần đào tạo lại.

Nếu điều hướng có thể làm cho mô hình an toàn hơn, chắc chắn nó cũng có thể làm cho mô hình tạo JSON hợp lệ chứ?

Nó không thể. Nhưng việc hiểu tại sao lại dạy cho tôi điều quan trọng về cách LLM thực sự hoạt động và cách kiểm soát chúng.

Bối cảnh: Sức Hút của Điều Hướng Kích Hoạt

Một nền tảng nhanh chóng về điều hướng kích hoạt là gì và tại sao nó lại có vẻ đầy hứa hẹn như vậy.

Điều Hướng Kích Hoạt Là Gì?

Điều hướng kích hoạt sửa đổi các kích hoạt bên trong mạng nơ-ron trong quá trình truyền xuôi của mô hình để ảnh hưởng đến hành vi. Thay vì thay đổi trọng số của mô hình (tinh chỉnh) hoặc thao tác văn bản đầu vào (kỹ thuật gợi ý), bạn trực tiếp điều chỉnh các biểu diễn trung gian khi thông tin chảy qua mạng.

Toán học rất đơn giản:

h̃ = h + α · v_steer

Trong đó: h = vector kích hoạt ban đầu ở một lớp nào đó v_steer = hướng điều hướng (được tính từ các ví dụ) α = cường độ điều hướng (hệ số nhân vô hướng)

Câu Chuyện Thành Công của Anthropic

Trong bài báo tháng 3 năm 2024 của họ, “Scaling Monosemanticity”, nhóm nghiên cứu về khả năng diễn giải của Anthropic đã chứng minh kết quả đáng chú ý với điều hướng dựa trên SAE. Họ đã đào tạo các bộ tự mã hóa thưa thớt trên các kích hoạt của Claude 3 Sonnet, trích xuất khoảng 34 triệu đặc trưng có thể diễn giải, mỗi đặc trưng tương ứng với các khái niệm ngữ nghĩa như “Cầu Cổng Vàng”, “chất lượng mã”, “thiên vị giới tính” hoặc “ngôn ngữ lừa đảo”.

Ví dụ nổi tiếng: khi các nhà nghiên cứu cố định đặc trưng “Cầu Cổng Vàng” ở mức kích hoạt tối đa, Claude bắt đầu tuyên bố rằng nó Cầu Cổng Vàng, liên hệ mọi chủ đề trở lại với cây cầu, thể hiện cảm xúc về cầu và San Francisco. Các thành công khác bao gồm giảm việc tạo mã bị lỗi, giảm thiểu thiên vị giới tính và chính trị, và phát hiện đầu ra có hại.

Sức hấp dẫn: thay đổi hành vi của mô hình mà không cần đào tạo lại, kết hợp nhiều vector điều hướng và điều chỉnh cường độ tại thời điểm suy luận. Đối với việc tạo JSON, điều này có vẻ là một sự phù hợp tự nhiên.

Nhiệm Vụ: Trích Xuất PII Với Đầu Ra JSON

Tôi cần trích xuất Thông tin Nhận dạng Cá nhân (PII) từ văn bản và xuất nó theo định dạng JSON nghiêm ngặt. Đây là những gì tôi đang làm việc:

Mô hình: Qwen/Qwen2.5-0.5B (494M tham số, kiến trúc chỉ bộ giải mã)

Tập dữ liệu: Nemotron-PII (30.000 mẫu bao gồm 55 loại thực thể PII bao gồm email, tên, địa chỉ, SSN, hồ sơ y tế, v.v.)

Định dạng Đầu Ra Mục Tiêu:

json [ { “text”: “john@example.com”, “label”: “email” }, { “text”: “John Doe”, “label”: “name” }, { “text”: “555-1234”, “label”: “phone_number” } ]

Hiệu suất Cơ sở (mô hình chưa đào tạo):

  • JSON Hợp lệ: 86.8%
  • Micro F1: 7.7%

Mục tiêu: ≥99.9% JSON hợp lệ trong khi duy trì điểm F1 cao cho việc trích xuất thực thể.


Thử Nghiệm 1: Điều Hướng Thiên Vị Qua Phép Chiếu QKV

Ý tưởng: đóng băng vĩnh viễn hướng “giống JSON” vào các tham số thiên vị của mô hình để mỗi lần truyền xuôi đều ưu tiên cú pháp JSON hợp lệ.

Phương Pháp

Tôi bắt đầu với thứ trực tiếp nhất mà tôi có thể nghĩ ra: sửa đổi các tham số thiên vị trong các lớp chú ý của mô hình. Tôi nhắm mục tiêu các thiên vị chiếu Truy vấn (Query), Khóa (Key) và Giá trị (Value) ở các lớp 12-15 (khoảng giữa các lớp của kiến trúc 24 lớp).

Triển khai:

  1. Trích xuất vector điều hướng từ các cặp ví dụ (JSON tốt so với JSON sai định dạng)
  2. Tính toán sự khác biệt trong các mẫu kích hoạt
  3. Sửa đổi thiên vị: b̃_proj = b_proj + W_proj @ v · α
  4. Kiểm tra với cường độ điều hướng α ∈ {0.1, 0.5, 1.0, 2.0}

Phương pháp này có một lợi thế lớn: không có chi phí suy luận. Việc điều hướng sẽ được “đóng băng” vĩnh viễn.

Hình 2: Sửa đổi Thiên vị Phép Chiếu QKV

Sửa đổi thiên vị ở các lớp 12-15, nhắm mục tiêu vào các phép chiếu Query, Key và Value.

Kết Quả

JSON Hợp lệ: ~70% (ước tính) Micro F1: ~20% (ước tính) Phán quyết: ❌ Hiệu suất suy giảm so với cơ sở

Đầu ra của mô hình tệ hơn cả cơ sở chưa được đào tạo. Các cấu trúc JSON thường bị sai định dạng, với các dấu ngoặc không khớp, vị trí dấu phẩy không chính xác và các ràng buộc kiểu bị vi phạm.

Tại Sao Nó Thất Bại

Ba vấn đề:

  1. Sự Pha loãng Ma trận Phép Chiếu. Vector điều hướng được nhân với ma trận phép chiếu W_proj, lan truyền tín hiệu qua nhiều đầu chú ý. Điều bắt đầu như một hướng “cấu trúc JSON” tập trung đã trở thành nhiễu ngữ nghĩa bị pha loãng trên 32 đầu chú ý.
  2. Nền Tảng Sai. Thiên vị chú ý kiểm soát cái gì mô hình chú ý (những phần nào của đầu vào cần tập trung vào). Chúng không kiểm soát cách mô hình định dạng đầu ra của nó. Tôi đã cố gắng sửa ngữ pháp bằng cách điều chỉnh những gì ai đó chú ý đến.
  3. Sự Gián đoạn Năng lực Cơ sở. Mô hình chưa được đào tạo sử dụng sự hiểu biết ngôn ngữ chung để tạo ra JSON tương đối hợp lệ. Việc thêm điều hướng đã phá vỡ các khả năng cơ sở đó và chủ động làm cho mô hình tệ hơn so với việc không làm gì cả.

Nói tóm lại: sửa đổi thiên vị chú ý ảnh hưởng đến sự tập trung ngữ nghĩa, không phải hiểu biết cú pháp.


Thử Nghiệm 2: Thiết Lập Giới Hạn Trên Với Tinh Chỉnh

Trước khi dành thêm thời gian cho việc điều hướng, tôi cần biết: mô hình này có thể học nhiệm vụ này không?

Phương Pháp

Tinh chỉnh giám sát tiêu chuẩn:

  • 1.000 mẫu đào tạo từ Nemotron-PII
  • Tinh chỉnh toàn bộ tham số (tất cả 494M tham số có thể huấn luyện)
  • 3 epoch, tốc độ học 2e-5
  • Thời gian đào tạo: ~30 phút trên GPU A100 đơn lẻ

Không điều hướng. Không mánh khoé. Chỉ là gradient descent trên hàm mất mát chéo entropy.

Kết Quả

Hình 3: Kết Quả Tinh Chỉnh Trên 500 Mẫu Kiểm Tra

Chỉ số Điểm
Tỷ lệ JSON Hợp lệ 96.6%
Micro Precision 0.944
Micro Recall 0.867
Micro F1 0.912
Macro F1 0.819

Mô hình có đủ năng lực cho nhiệm vụ.

Điều Đó Cho Tôi Biết

Điều này đã chứng minh ba điều: mô hình có thể học định dạng JSON, nó có thể trích xuất các thực thể PII một cách chính xác và 494M tham số là đủ năng lực.

Nhưng nó cũng đặt ra một câu hỏi mà lẽ ra tôi phải xem xét nghiêm túc hơn: nếu tinh chỉnh hoạt động tốt như vậy, tại sao tôi lại cần đến điều hướng?


Thử Nghiệm 3: Chỉ Điều Hướng (Cái Đã Thay Đổi Mọi Thứ)

Đây là thử nghiệm khiến tôi phải suy nghĩ lại toàn bộ phương pháp.

Ý Tưởng

Điều gì sẽ xảy ra nếu tôi bỏ qua hoàn toàn việc đào tạo và chỉ sử dụng điều hướng kích hoạt thuần túy tại thời điểm suy luận? Tính toán vector điều hướng từ 100 cặp ví dụ và thêm nó vào luồng còn sót lại trong quá trình tạo.

Kiểm tra thuần túy nhất về điều hướng: không sửa đổi trọng số, không đào tạo, chỉ thao tác kích hoạt tại thời gian chạy.

Phương Pháp

  1. Thu thập 100 cặp ví dụ:

    • Tích cực: JSON được định dạng tốt với việc trích xuất PII chính xác
    • Tiêu cực: JSON sai định dạng hoặc trích xuất không chính xác
  2. Tính toán vector điều hướng:

    python v_steer = mean(activations_positive) - mean(activations_negative)

  3. Thêm vào luồng còn sót lại ở các lớp 12-15 trong quá trình suy luận:

    python h̃ = h + α · v_steer

  4. Kiểm tra với α ∈ {0.5, 1.0, 2.0, 5.0}

Không đào tạo. Chỉ thao tác kích hoạt trực tiếp.

Kết Quả

Bảng 1: So sánh Trên 500 Mẫu Kiểm Tra

Phương pháp JSON Hợp lệ Micro F1 Macro F1 Phán quyết
Mô hình cơ sở 86.8% 7.7% 0.5% Cơ sở
Điều hướng 24.4% 1.5% 0.2% THẢM KHỐC
Tinh chỉnh 96.6% 91.2% 81.9% Tuyệt vời

Điều hướng đã giảm tỷ lệ JSON hợp lệ xuống 62,4 điểm phần trăm. Nó không phải là không hiệu quả. Nó thực sự có hại.

Phân Tích Chế Độ Lỗi

Nhìn vào các đầu ra thực tế cho bạn biết mọi thứ:

Đầu ra Cơ sở (chưa được đào tạo, 86.8% hợp lệ):

json [ { “text”: “john@example.com”, “label”: “email” }, { “text”: “John Doe”, “label”: “name” }

Chủ yếu là chính xác. Thỉnh thoảng thiếu dấu ngoặc ở cuối, nhưng cấu trúc vẫn nguyên vẹn.

Đầu ra Điều hướng (24.4% hợp lệ):

json [ { “text: john@example.com, label”: email }, {text": John Doe, “label”: name}

Sự sụp đổ cấu trúc hoàn toàn. Thiếu dấu ngoặc kép mở, vị trí dấu ngoặc không nhất quán, dấu phẩy sai vị trí, vi phạm ràng buộc kiểu. Các đầu ra trông giống như đến từ một thứ gì đó đã nghe nói về JSON nhưng chưa bao giờ thực sự nhìn thấy nó.

Tại Sao Lại Như Vậy

  1. Không Học Nhiệm Vụ. Điều hướng không thể dạy các nhiệm vụ mới. Nó chỉ có thể điều chỉnh các hành vi hiện có. Mô hình chưa được đào tạo có các tiền đề JSON yếu từ quá trình đào tạo trước, và điều hướng đã không củng cố chúng, nó đã làm sai lệch chúng.
  2. Thiên Vị Ngữ Nghĩa Mà Không Hiểu Cấu Trúc. Vector điều hướng đã đẩy các kích hoạt về phía “giống JSON” như một khái niệm ngữ nghĩa, điều này không giống với “tính hợp lệ của JSON” như một ràng buộc cú pháp. Hãy nghĩ: dạy ai đó “nói chuyện thông minh” thay vì dạy họ logic.
  3. Làm Gián Đoạn Năng Lực Cơ Sở. Mô hình chưa được đào tạo sử dụng sự hiểu biết ngôn ngữ chung để tạo ra JSON tương đối hợp lệ. Việc thêm điều hướng đã phá vỡ các khả năng cơ sở đó và chủ động làm cho mô hình tệ hơn so với việc không làm gì cả.

Nói tóm lại: sửa đổi thiên vị chú ý ảnh hưởng đến sự tập trung ngữ nghĩa, không phải hiểu biết cú pháp.

Tại thời điểm này tôi nên dừng lại. Nhưng tôi vẫn chưa sẵn sàng từ bỏ việc điều hướng.


Thử Nghiệm 4: Điều Hướng có Giúp Mô Hình Tinh Chỉnh Không?

Sau bốn lần thất bại, tôi nghĩ: có lẽ điều hướng thất bại một mình vì mô hình cần kiến thức nhiệm vụ trước. Nếu tôi kết hợp tinh chỉnh và điều hướng thì sao? Tinh chỉnh dạy nhiệm vụ, điều hướng tinh chỉnh định dạng đầu ra.

Bốn Biến Thể Đã Kiểm Tra

  1. FT Lớp Chọn Lọc (không điều hướng): Đóng băng tất cả trừ các lớp 12-15, tinh chỉnh cho định dạng JSON
  2. FT Chọn Lọc + Điều hướng Suy luận: Thêm vector điều hướng tại thời điểm suy luận sau khi đào tạo
  3. FT Đầy Đủ + Điều hướng Suy luận: Tinh chỉnh tất cả các tham số, sau đó thêm điều hướng
  4. FT Đầy Đủ với Điều hướng Trong Quá Trình Đào tạo: Tích hợp điều hướng trực tiếp vào vòng lặp đào tạo

Biến thể thứ tư này xứng đáng được chú ý. Không giống như điều hướng tại thời điểm suy luận (thêm vector sau khi đào tạo hoàn tất), điều hướng trong quá trình đào tạo sửa đổi các kích hoạt trong quá trình truyền xuôi trong khi gradient đang được tính toán. Ý tưởng: nếu mô hình học cách tạo ra các đầu ra chính xác trong khi đang được điều hướng, có lẽ nó sẽ nội hóa cả kiến thức nhiệm vụ và hướng điều hướng cùng một lúc.

Tại sao điều này lại thú vị:

  • Phối hợp thích ứng: Các trọng số có thể thích ứng với sự hiện diện của các vector điều hướng, học cách làm việc với chúng thay vì chống lại chúng.
  • Tiêm khả năng được nhắm mục tiêu: Điều hướng trong quá trình đào tạo có thể tiêm các khả năng cụ thể mà không cần giám sát rõ ràng.
  • Bảo toàn các khả năng khác: Vì bạn chỉ sửa đổi các kích hoạt theo hướng được nhắm mục tiêu, các khả năng khác của mô hình sẽ được giữ nguyên.

Tôi nên lưu ý rằng mặc dù điều hướng trong quá trình đào tạo đã thất bại trong việc tạo JSON, nhưng nó cho thấy tiềm năng thực sự cho các loại nhiệm vụ khác. Trong các thử nghiệm riêng biệt về suy luận toán học và các nhiệm vụ dịch thuật, tôi đã thấy điều hướng trong quá trình đào tạo thành công trong việc tăng cường các khả năng cụ thể mà không làm giảm hiệu suất trên các điểm chuẩn không liên quan. Sự khác biệt nằm ở bản chất của nhiệm vụ: các khả năng ngữ nghĩa (sự hiểu biết toán học, sự trôi chảy của ngôn ngữ) phản ứng tốt với cách tiếp cận này, trong khi các ràng buộc cú pháp thì không. Đây là một lĩnh vực nghiên cứu đang hoạt động mà tôi dự định xuất bản riêng.

Kết Quả

Bảng 2: Kết Quả Tinh Chỉnh + Điều Hướng (500 mẫu)

Phương pháp JSON Hợp lệ Thay đổi so với Cơ sở
FT Lớp Chọn Lọc (không điều hướng) 67.4% Cơ sở
FT Chọn Lọc + Điều hướng Suy luận 42.2% -25.2pp
FT Đầy Đủ + Điều hướng Suy luận 36.8% -30.6pp
FT Đầy Đủ + Điều hướng Trong Đào tạo 31.6% -35.8pp

Mọi biến thể điều hướng duy nhất đều làm giảm hiệu suất. Điều hướng càng mạnh mẽ, kết quả càng tệ.

Mẫu Hình

  1. Suy giảm Liên tục. Thêm điều hướng tại thời điểm suy luận đã làm giảm JSON hợp lệ xuống 25-31 điểm phần trăm mỗi lần, bất kể cách tiếp cận tinh chỉnh.
  2. Điều hướng trong Quá trình Đào tạo Tệ hơn. Việc tích hợp điều hướng trong quá trình đào tạo (biến thể 4) cho kết quả tệ nhất (-35.8pp). Điều hướng không chỉ không hiệu quả, nó còn can thiệp vào việc học dựa trên gradient.

Điều này hợp lý khi bạn nghĩ về nó. Tinh chỉnh học cấu hình trọng số chính xác thông qua gradient descent. Mỗi lớp đảm nhận một vai trò cụ thể:

  • Lớp 12 học cách nhận dạng ranh giới thực thể
  • Lớp 13 học cách xây dựng cấu trúc mảng JSON
  • Lớp 14 học cách định dạng các cặp khóa-giá trị
  • Lớp 15 học cách đặt dấu ngoặc đóng

Các trọng số này tạo thành một sự cân bằng tinh tế. Việc thêm một vector điều hướng đẩy các kích hoạt vào các vùng mà trọng số đã tinh chỉnh không hoạt động đúng. Giống như huấn luyện một nghệ sĩ piano chơi Chopin, sau đó điều chỉnh ngẫu nhiên vị trí tay của họ giữa buổi biểu diễn. Việc đào tạo đã không tính đến điều đó.

Điều Hướng Can Thiệp Như Thế Nào

Sự không phù hợp giữa tối ưu hóa. Tinh chỉnh học L = -log P(correct_JSON | input). Điều hướng đẩy các kích hoạt về phía một hướng ngữ nghĩa “giống JSON”. Đây là các mục tiêu khác nhau. Một là cụ thể cho nhiệm vụ và rời rạc (JSON hợp lệ hoặc không). Một là ngữ nghĩa và liên tục (giống JSON hơn hoặc kém).

Tại thời điểm này, rõ ràng là: điều hướng không hoạt động cho việc tạo đầu ra có cấu trúc.


Gián Đoạn: Anthropic Làm Khác Biệt Như Thế Nào

Đây là điều tôi không thể hiểu ra. Việc điều hướng SAE của Anthropic hoạt động rất tốt cho an toàn AI. Tại sao nó lại không hoạt động cho JSON?

Xem Xét Lại Các Trường Hợp Thành Công của Anthropic

Nhìn vào những gì điều hướng của Anthropic thực sự đạt được:

  1. Ám ảnh Cầu Cổng Vàng

    • Đặc trưng: 34M_20646 (phát hiện từ hàng triệu đặc trưng SAE)
    • Ảnh hưởng: Mô hình tuyên bố là Cầu, liên hệ mọi thứ với cầu
    • Bản chất: Khái niệm ngữ nghĩa, liên tục (có thể hơn/kém ám ảnh)
  2. Chất Lượng Mã và Bảo Mật

    • Đặc trưng: “mã lỗi”, “cửa hậu”, “lỗ hổng bảo mật”
    • Ảnh hưởng: Giảm việc tạo mã độc
    • Bản chất: Mẫu hành vi, liên tục (nguy hiểm hơn/kém hơn)
  3. Giảm Thiên Vị

    • Đặc trưng: Thiên vị giới tính, quan điểm chính trị, ngôn ngữ khuôn mẫu
    • Ảnh hưởng: Giảm đầu ra thiên vị
    • Bản chất: Đặc điểm hành vi, liên tục (nhiều/ít thiên vị)

Mẫu hình: tất cả những điều này là các khái niệm ngữ nghĩa (ý nghĩa cấp cao), các thang đo liên tục (nhiều hơn/ít hơn X) và các mẫu hành vi (xu hướng, không phải quy tắc).

Nhiệm Vụ Của Tôi: Khác Biệt Cơ Bản

So sánh với việc tạo JSON:

Yêu Cầu Tính Hợp Lệ JSON:

  • Dấu ngoặc nhọn mở { phải khớp với dấu ngoặc nhọn đóng }
  • Các giá trị chuỗi phải được đặt trong dấu ngoặc kép "
  • Các phần tử mảng phải được phân tách bằng dấu phẩy (nhưng không có dấu phẩy cuối)
  • Các khóa phải là chuỗi được đặt trong dấu ngoặc kép
  • Không có ký tự điều khiển nào bị thoát trong chuỗi

Đây là:

  • ❌ Ràng buộc cấu trúc (quy tắc cú pháp cấp thấp)
  • ❌ Trạng thái nhị phân (hợp lệ/không hợp lệ, không có khoảng giữa)
  • ❌ Quy tắc trạng thái (yêu cầu theo dõi độ sâu lồng nhau, trạng thái dấu ngoặc kép)

Bảng 3: Nhiệm vụ Ngữ nghĩa so với Cấu trúc

Chiều Nhiệm vụ của Anthropic (Ngữ nghĩa) Nhiệm vụ của Tôi (Tạo JSON)
Bản chất Khái niệm cấp cao, hành vi Quy tắc cú pháp cấp thấp
Ràng buộc Mềm, liên tục (nhiều/ít X) Cứng, nhị phân (hợp lệ/không hợp lệ)
Thành công Chủ quan, dần dần Khách quan, rời rạc
Ví dụ “Hãy hữu ích hơn” “Đảm bảo dấu ngoặc đóng } khớp với dấu ngoặc mở {
Cơ chế Thao tác biểu diễn ngữ nghĩa Thực thi máy trạng thái

Vấn Đề Không Gian Kích Hoạt

Đây là một cách để hình dung những gì điều hướng có thể và không thể kiểm soát:

Điều Hướng Có Thể Kiểm Soát (Không gian Ngữ nghĩa):

hữu ích ←——————————→ không hữu ích (trục liên tục) trang trọng ←——————————→ thông thường (trục liên tục) dài dòng ←——————————→ súc tích (trục liên tục) giống JSON ←————————→ giống văn xuôi (trục liên tục) ✅

Bạn có thể điều hướng dọc theo các trục này vì chúng đại diện cho các hướng ngữ nghĩa trong không gian biểu diễn đã học của mô hình. Các đặc trưng được phân phối trên các chiều liên tục này.

Điều Hướng Không Thể Kiểm Soát (Trạng thái Cú pháp):

hợp lệ_json = {true, false} (trạng thái nhị phân rời rạc) ❌ số_ngoặc = {…, -2, -1, 0, +1, +2, …} (bộ đếm trạng thái) ❌ trạng thái_dấu_ngoặc kép = {MỞ, ĐÓNG} (trạng thái FSM) ❌ trong_chuỗi = {true, false} (cờ ngữ cảnh) ❌

Đây không phải là hướng ngữ nghĩa. Chúng là các trạng thái rời rạc phải được theo dõi trong quá trình tạo token. Bộ đếm, cờ và máy trạng thái.

Điều hướng hoạt động trên các biểu diễn ngữ nghĩa. Tính hợp lệ của JSON không phải là một khái niệm ngữ nghĩa. Đó là một máy trạng thái.

Bạn có thể làm cho mô hình “nói nhiều hơn về JSON” hoặc “ưu tiên kết quả đầu ra có cấu trúc”, nhưng bạn không thể làm cho nó “theo dõi độ sâu dấu ngoặc” hoặc “ghi nhớ liệu một chuỗi có được mở hay không” thông qua thao tác kích hoạt đơn thuần.

Điều này giải thích tại sao Anthropic thành công với điều hướng an toàn (khái niệm ngữ nghĩa), tại sao tôi thất bại với điều hướng JSON (trạng thái cú pháp), và tại sao điều hướng làm suy giảm các mô hình đã tinh chỉnh (nó đã làm gián đoạn các mẫu cú pháp đã học).

Điều hướng là một núm âm lượng cho các khái niệm ngữ nghĩa, không phải là một bộ phân tích cú pháp cho các quy tắc cú pháp.


Thử Nghiệm 5: Điều Gì Thực Sự Hiệu Quả (Giải Mã Bị Ràng Buộc)

Sau bốn lần thất bại, tôi đã từ bỏ hoàn toàn việc thao tác kích hoạt và thử một cách khác: thực thi cú pháp ở cấp độ token trong quá trình tạo.

Giải mã bị ràng buộc biến việc tạo từ “dự đoán bất kỳ token nào” thành “chỉ dự đoán các token hợp lệ theo một ngữ pháp chính thức.” Tôi đã triển khai một LogitsProcessor tùy chỉnh dựa trên FSM để thực thi cấu trúc JSON ở cấp độ token.

Triển Khai: Custom FSM LogitsProcessor

Ý tưởng cốt lõi rất đơn giản: ở mỗi bước tạo, theo dõi trạng thái phân tích cú pháp JSON hiện tại và loại bỏ bất kỳ token nào sẽ dẫn đến JSON không hợp lệ.

python from transformers import LogitsProcessor import torch from collections import defaultdict

class JSONArrayLogitsProcessor(LogitsProcessor): “““FSM-based logits processor for JSON array generation.”””

STATES = [
    "START",           # Mong đợi '['
    "ARRAY_OPEN",      # Bên trong mảng, mong đợi '{' hoặc ']'
    "OBJECT_START",    # Bên trong đối tượng, mong đợi '"' cho khóa
    "IN_KEY",          # Bên trong chuỗi khóa
    "AFTER_KEY",       # Sau khóa, mong đợi ':'
    "AFTER_COLON",     # Sau ':', mong đợi '"' cho giá trị
    "IN_VALUE",        # Bên trong chuỗi giá trị
    "AFTER_VALUE",     # Sau giá trị, mong đợi ',' hoặc '}'
    "AFTER_OBJECT",    # Sau '}', mong đợi ',' hoặc ']'
    "DONE"             # Sau ']', chỉ cho phép EOS
]

def __init__(self, tokenizer):
    self.tokenizer = tokenizer
    self.state = "START"
    self._build_token_maps()

def _build_token_maps(self):
    """Tiền tính toán các token bắt đầu bằng ký tự nào."""
    self.tokens_starting_with = defaultdict(set)
    for token_id in range(self.tokenizer.vocab_size):
        decoded = self.tokenizer.decode([token_id])
        if decoded:
            self.tokens_starting_with[decoded[0]].add(token_id)

def __call__(self, input_ids, scores):
    # Lấy các token hợp lệ cho trạng thái FSM hiện tại
    valid_tokens = self._get_valid_tokens()

    # Tạo mặt nạ: -inf cho các token không hợp lệ
    mask = torch.full_like(scores, float('-inf'))
    for token_id in valid_tokens:
        if token_id < scores.shape[-1]:
            mask[:, token_id] = 0
    return scores + mask

def _get_valid_tokens(self):
    # Trả về ID token hợp lệ dựa trên trạng thái FSM hiện tại
    state_chars = {
        "START": ["["], "ARRAY_OPEN": ["{", "]"],
        "OBJECT_START": ['"'], "AFTER_KEY": [":"],
        "AFTER_COLON": ['"'], "AFTER_VALUE": [",", "}"],
        "AFTER_OBJECT": [",", "]"]
    }
    if self.state in ["IN_KEY", "IN_VALUE"]:
        return set(range(self.tokenizer.vocab_size))  # Bất kỳ token nào trong chuỗi
    valid = set()
    for char in state_chars.get(self.state, []):
        valid.update(self.tokens_starting_with[char])
    return valid

Tạo một phiên bản bộ xử lý

processor = JSONArrayLogitsProcessor(tokenizer)

Tạo với việc thực thi FSM

output = model.generate( input_ids, max_new_tokens=512, do_sample=False, # Cần greedy cho FSM logits_processor=[processor] )

FSM theo dõi các chuyển đổi trạng thái khi token được tạo ra:

python

Chuyển đổi trạng thái dựa trên ký tự được tạo ra

TRANSITIONS = { “START”: {"[": “ARRAY_OPEN”}, “ARRAY_OPEN”: {"{": “OBJECT_START”, “]”: “DONE”}, “OBJECT_START”: {’"’: “IN_KEY”}, “IN_KEY”: {’"’: “AFTER_KEY”}, # Đơn giản hóa “AFTER_KEY”: {":": “AFTER_COLON”}, “AFTER_COLON”: {’"’: “IN_VALUE”}, “IN_VALUE”: {’"’: “AFTER_VALUE”}, “AFTER_VALUE”: {",": “OBJECT_START”, “}”: “AFTER_OBJECT”}, “AFTER_OBJECT”: {",": “ARRAY_OPEN”, “]”: “DONE”}, }

Điều này được tích hợp với model.generate() của HuggingFace:

python

Tạo bộ xử lý

processor = JSONArrayLogitsProcessor(tokenizer)

Tạo với việc thực thi FSM

output = model.generate( input_ids, max_new_tokens=512, do_sample=False, # Cần greedy cho FSM logits_processor=[processor] )

Chiến Lược Phòng Thủ Hai Pha

Tôi đã triển khai một cơ chế dự phòng cho các trường hợp biên:

Giai đoạn 1 (Chính): Tạo dựa trên FSM tùy chỉnh

  • 86%+ mẫu được phân tích cú pháp trực tiếp
  • Thực thi token theo token

Giai đoạn 2 (Dự phòng): Thư viện json-repair

  • Xử lý các đầu ra bị cắt cụt (đạt giới hạn max_new_tokens)
  • Sửa các sai lệch có thể phục hồi

python def parse_with_repair(text: str) -> tuple: “““Phân tích cú pháp JSON với dự phòng sửa chữa.””” try: # Phân tích cú pháp trực tiếp (Giai đoạn 1) parsed = json.loads(text) return parsed, “direct” except json.JSONDecodeError: # Thử sửa chữa (Giai đoạn 2) try: from json_repair import repair_json repaired = repair_json(text) parsed = json.loads(repaired) return parsed, “repaired” except: # Dự phòng cuối cùng: mảng trống return [], “failed”

Lỗi Đã Khiến Tôi Mất Hàng Giờ: Ô Nhiễm Trạng Thái FSM

Trong quá trình kiểm tra ban đầu, tôi đã gặp một mẫu lỗi kỳ lạ:

Mẫu 1 (văn bản tự nhiên): ✅ THÀNH CÔNG (540 ký tự JSON hợp lệ) Mẫu 2 (bảng markdown): ❌ CHUỖI TRỐNG Mẫu 3 (YAML): ❌ CHUỖI TRỐNG Mẫu 4 (văn bản tự nhiên): ❌ CHUỖI TRỐNG

Văn bản tự nhiên hoạt động, nhưng đầu vào được định dạng (bảng, YAML, mã) liên tục thất bại.

Vấn đề: bộ xử lý LogitsProcessor duy trì trạng thái FSM nội bộ giữa các lần tạo. Khi được sử dụng lại giữa các mẫu, trạng thái cũ từ các lần tạo trước đó đã gây ra lỗi.

Triển khai Sai ❌:

python

Tạo bộ xử lý một lần - SAI!

processor = JSONArrayLogitsProcessor(tokenizer)

for sample in dataset: # Tái sử dụng bộ xử lý với trạng thái bị ô nhiễm output = model.generate( input_ids, logits_processor=[processor] # ← Trạng thái tích lũy! ) # Các mẫu sau này thất bại do trạng thái cũ

Triển khai Đúng ✅:

python for sample in dataset: # Khởi tạo lại cho mỗi mẫu - TỐT! processor = JSONArrayLogitsProcessor(tokenizer)

output = model.generate(
    input_ids,
    logits_processor=[processor]  # ← Trạng thái sạch!
)

Sau khi sửa lỗi: tỷ lệ thành công 100% trên tất cả các loại đầu vào.

Kết Quả: Tỷ lệ Hợp Lệ JSON Hoàn Hảo

Bảng 4: Cơ sở so với Giải mã Bị Ràng buộc (500 mẫu)

Chỉ số Cơ sở (FT) Bị Ràng buộc Thay đổi
Tỷ lệ JSON Hợp lệ 98.0% 100.0% +2.0pp
Đầu ra Không hợp lệ 10 0 -10
Micro F1 0.8995 0.8581 -0.0414 ⚠️
Micro Precision 0.9239 0.9181 -0.0058
Micro Recall 0.8763 0.8055 -0.0708
Macro F1 0.8312 0.6618 -0.1694 ⚠️
Độ trễ (ms) 2,518 4,585 +82.1% ⚠️
Tỷ lệ Sửa chữa - 13.8% Có thể chấp nhận ⚠️

Phân Tích

Những điểm được: 100% JSON hợp lệ (không có đầu ra không hợp lệ), hoạt động trên tất cả các loại đầu vào (văn bản tự nhiên, bảng, YAML, mã), và không có phụ thuộc bên ngoài vì đây là một triển khai FSM tùy chỉnh.

Sự đánh đổi: F1 giảm 4.6% (ngoài mục tiêu ±2% của tôi), có thể vì các ràng buộc FSM nghiêm ngặt giới hạn khả năng diễn đạt của mô hình trong các trường hợp biên. Độ trễ tăng 82.1% do xác thực FSM ở mỗi token. Và 13.8% mẫu cần dự phòng json-repair do bị cắt cụt từ việc đạt max_new_tokens=512.

Tại Sao Phương Pháp Này Hoạt Động

Giải mã bị ràng buộc hoạt động vì nó hoạt động ở cấp độ trừu tượng phù hợp.

Mọi token được tạo ra đều được xác thực so với FSM. Các token không hợp lệ có xác suất là 0. Bạn thực sự không thể tạo ra JSON không hợp lệ. FSM theo dõi độ sâu lồng nhau, liệu bạn có đang ở trong một chuỗi/mảng/đối tượng hay không, token nào là hợp lệ tiếp theo. Đây chính xác là những gì điều hướng không thể làm: theo dõi trạng thái trong quá trình tạo.

Và đó không phải là một phương pháp heuristic. Theo cách xây dựng, đầu ra phải khớp với ngữ pháp. Nó cũng hoạt động với bất kỳ mô hình nào (cơ sở, đã tinh chỉnh, gợi ý) vì nó không yêu cầu mô hình phải “học” định dạng JSON. Nó chỉ thực thi nó.

Điều hướng không ảnh hưởng đến nội dung ngữ nghĩa, cải thiện tính đúng đắn, hoặc kiểm soát phong cách. Nó thực thi tính hợp lệ về mặt cấu trúc bằng cách xây dựng. Nó hoạt động với JSON vì cú pháp là một máy trạng thái hữu hạn, và FSM có thể thực thi hoàn hảo các máy trạng thái hữu hạn.


Thử Nghiệm 6: Xác Minh Giả Thuyết Ngữ Nghĩa/Cú Pháp

Sau thành công của giải mã bị ràng buộc, tôi vẫn muốn biết: điều hướng thất bại vì chính kỹ thuật đó, hay vì tôi đã áp dụng nó cho sai loại nhiệm vụ?

Giả thuyết của tôi từ Thử nghiệm 1-5 là điều hướng thất bại đối với các ràng buộc cú pháp nhưng có thể hoạt động đối với các chiều ngữ nghĩa. Một thử nghiệm nữa để kiểm tra điều này.

Thiết Lập

Tôi đã tạo ba nhiệm vụ điều hướng ngữ nghĩa:

  1. Tính Trang Trọng: Điều hướng có thể làm cho mô hình tạo ra ngôn ngữ trang trọng hơn không?

    • Các cặp đối lập: văn bản học thuật trang trọng so với tiếng lóng thông thường
    • Đo lường: Mức độ theo Flesch-Kincaid
  2. Tập Trung Chủ Đề: Điều hướng có thể thúc đẩy thuật ngữ chuyên ngành không?

    • Các cặp đối lập: nội dung ML kỹ thuật so với văn xuôi thông thường
    • Đo lường: Mật độ từ vựng kỹ thuật
  3. Tính Hữu Ích: Điều hướng có thể tạo ra các câu trả lời hữu ích, chi tiết hơn không?

    • Các cặp đối lập: câu trả lời hữu ích, toàn diện so với những câu trả lời ngắn gọn, bác bỏ
    • Đo lường: Điểm đánh giá của con người (thang điểm 1-5)

Đối với mỗi nhiệm vụ, tôi đã:

  1. Tính toán vector điều hướng từ 100 cặp đối lập
  2. Áp dụng điều hướng ở các lớp 12-15 (giống như các thử nghiệm trước)
  3. Kiểm tra với α ∈ {0.0, 0.5, 1.0, 2.0, 5.0}
  4. Sử dụng kiểm định t cặp với Cohen’s d để có tính chặt chẽ thống kê.

Kết Quả: Xác Minh Một Phần

Bảng: Kết Quả Điều Hướng Ngữ Nghĩa (50 gợi ý mỗi loại)

Nhiệm vụ Chỉ số Cơ sở (α=0) Điều hướng Tốt nhất p-value Cohen’s d Phán quyết
Tính Trang Trọng Mức độ Flesch-Kincaid 11.78 ± 1.34 11.82 ± 1.17 0.870 0.033 ❌ NS
Tập trung Chủ đề Mật độ Kỹ thuật 0.016 ± 0.026 0.016 ± 0.024 0.846 0.040 ❌ NS
Tính Hữu ích Điểm Con người (1-5) 1.84 ± 0.76 2.18 ± 0.87 0.042 0.416 ✅ SIG

Chỉ có tính hữu ích cho thấy ảnh hưởng có ý nghĩa thống kê (p < 0.05) với kích thước ảnh hưởng trung bình (Cohen’s d = 0.42). Đó là mức cải thiện 18% về điểm số hữu ích.

Mẫu Hình Không Đơn Điệu

Phát hiện thú vị: cường độ điều hướng không tuân theo quy tắc “càng nhiều càng tốt”.

Ở α = 5.0, điều hướng thực sự làm cho kết quả đầu ra ít hữu ích hơn so với cơ sở không được điều hướng. Cường độ vừa phải giúp ích, nhưng điều hướng quá mức làm gián đoạn việc tạo ra các câu mạch lạc.

Tại Sao Chỉ Tính Hữu Ích Hoạt Động

Tính hữu ích thành công vì nó rất nổi bật trong dữ liệu đào tạo trước (các mô hình được hướng dẫn theo chỉ thị mã hóa “tính hữu ích” mạnh mẽ), có tín hiệu tương phản rõ ràng và mang tính hành vi thay vì phong cách.

Tính trang trọng và tập trung chủ đề thất bại ngay cả khi chúng là ngữ nghĩa. “Hướng” của chúng có thể được phân phối trên nhiều đặc trưng (không có vector điều hướng duy nhất), phép đo ở cấp độ bề mặt hơn và chúng ít được mã hóa mạnh mẽ hơn trong các biểu diễn của mô hình cơ sở.

Điều Này Có Nghĩa Là Gì

Điều này xác nhận một phần giả thuyết. Điều hướng có thể hoạt động cho các chiều ngữ nghĩa khi được thực hiện đúng cách, và các lỗi JSON không phải do lỗi triển khai. Nhưng không phải tất cả các nhiệm vụ ngữ nghĩa đều giống nhau. Điều hướng yêu cầu các hướng đặc trưng mạnh mẽ, mạch lạc.

Cách Suy Nghĩ về Chúng

Tinh chỉnh giống như viết lại trình biên dịch. Nó thay đổi cách mã được tạo từ đầu và có thể ảnh hưởng đến cả ngữ nghĩa và cú pháp.

Điều hướng giống như chạy trình kiểm tra trên các kích hoạt. Nó phát hiện và điều chỉnh các mẫu cấp cao, tốt cho các vấn đề ngữ nghĩa, nhưng nó không thể sửa lỗi cú pháp.

Giải mã bị ràng buộc giống như một bộ phân tích hướng dẫn ngữ pháp. Nó thực thi ngữ pháp chính thức trong quá trình tạo và đảm bảo tính hợp lệ về mặt cú pháp, nhưng không quan tâm đến chất lượng ngữ nghĩa.


Khuyến Nghị Thực Tế

Nếu bạn cần kiểm soát nội dung/hành vi (súc tích hơn, ít thiên vị hơn, đúng chủ đề): hãy thử kỹ thuật gợi ý trước, sau đó là điều hướng kích hoạt, sau đó là tinh chỉnh với LoRA.

Nếu bạn cần đảm bảo tính hợp lệ về cấu trúc (JSON hợp lệ, SQL chính xác, XML được định dạng tốt): hãy sử dụng giải mã bị ràng buộc với ngữ pháp/lược đồ chính xác và dự phòng sửa chữa cho các trường hợp cắt cụt.

Nếu bạn cần cả nội dung chất lượng và định dạng được đảm bảo (trích xuất thực thể y tế dưới dạng JSON hợp lệ, tạo Python có thể chạy, báo cáo có cấu trúc): tinh chỉnh cho chất lượng nội dung, sau đó thêm giải mã bị ràng buộc cho cấu trúc. Kết quả tốt nhất của tôi là F1 91.2% với JSON hợp lệ 100%.

Mã Triển Khai Sản Xuất

Nếu bạn cần đảm bảo JSON hợp lệ, đây là những gì bạn nên làm:

python from transformers import AutoModelForCausalLM, AutoTokenizer, LogitsProcessor from collections import defaultdict import torch import json

class JSONArrayLogitsProcessor(LogitsProcessor): “““FSM-based logits processor for JSON array generation.”””

STATES = ["START", "ARRAY_OPEN", "OBJECT_START", "IN_KEY",
          "AFTER_KEY", "AFTER_COLON", "IN_VALUE", "AFTER_VALUE",
          "AFTER_OBJECT", "DONE"]

def __init__(self, tokenizer):
    self.tokenizer = tokenizer
    self.state = "START"
    self._build_token_maps()

def _build_token_maps(self):
    self.tokens_starting_with = defaultdict(set)
    for token_id in range(self.tokenizer.vocab_size):
        decoded = self.tokenizer.decode([token_id])
        if decoded:
            self.tokens_starting_with[decoded[0]].add(token_id)

def __call__(self, input_ids, scores):
    valid_tokens = self._get_valid_tokens()
    mask = torch.full_like(scores, float('-inf'))
    for token_id in valid_tokens:
        if token_id < scores.shape[-1]:
            mask[:, token_id] = 0
    return scores + mask

def _get_valid_tokens(self):
    state_chars = {
        "START": ["["], "ARRAY_OPEN": ["{", "]"],
        "OBJECT_START": ['"'], "AFTER_KEY": [":"],
        "AFTER_COLON": ['"'], "AFTER_VALUE": [",", "}"],
        "AFTER_OBJECT": [",", "]"]
    }
    if self.state in ["IN_KEY", "IN_VALUE"]:
        return set(range(self.tokenizer.vocab_size))  # Any token in strings
    valid = set()
    for char in state_chars.get(self.state, []):
        valid.update(self.tokens_starting_with[char])
    return valid

Tải mô hình của bạn

model = AutoModelForCausalLM.from_pretrained(“your-model-name”) tokenizer = AutoTokenizer.from_pretrained(“your-model-name”)

def generate_with_fallback(prompt, max_tokens=512): “““Tạo với xử lý lỗi phòng thủ theo lớp.””” # Tạo bộ xử lý mới cho mỗi lần tạo processor = JSONArrayLogitsProcessor(tokenizer)

try:
    # Giai đoạn 1: Tạo bị ràng buộc
    inputs = tokenizer(prompt, return_tensors="pt")
    output = model.generate(
        inputs.input_ids,
        max_new_tokens=max_tokens,
        do_sample=False,  # Cần greedy cho FSM
        logits_processor=[processor]
    )
    text = tokenizer.decode(output[0], skip_special_tokens=True)
    return json.loads(text), "direct"

except json.JSONDecodeError:
    # Giai đoạn 2: Dự phòng sửa chữa (nếu bị cắt cụt)
    try:
        from json_repair import repair_json
        repaired = repair_json(text)
        return json.loads(repaired), "repaired"
    except:
        # Giai đoạn 3: Mặc định an toàn
        return [], "failed"

Sử dụng trong sản xuất

result, method = generate_with_fallback(your_prompt) print(f"Đã tạo {len(result)} thực thể thông qua {method}")

Chi phí độ trễ tăng thêm khoảng +80-100% (có thể được tối ưu hóa bằng bộ nhớ đệm), tỷ lệ JSON hợp lệ: 100%, tỷ lệ sửa chữa: ~10-15% (do cắt cụt).

Những Gì Cần Giám Sát Trong Sản Xuất

Theo dõi tỷ lệ hợp lệ về mặt cấu trúc (phải là 100%), tỷ lệ sửa chữa (<5%, nếu không thì tăng max_new_tokens), tỷ lệ dự phòng (điều tra bất kỳ thứ gì chạm đến dự phòng cuối cùng), p95/p99 độ trễ và các chỉ số chất lượng nội dung của bạn (F1, độ chính xác, độ phủ).


Kết Luận

Tôi đã bắt đầu với mục tiêu đạt 100% JSON hợp lệ bằng cách sử dụng điều hướng kích hoạt. Nó đã không hoạt động.

Chỉ điều hướng: 24.4% JSON hợp lệ (tệ hơn cơ sở 62pp). Tinh chỉnh + điều hướng: tệ hơn 25-36pp so với chỉ tinh chỉnh. Mọi biến thể tôi đã thử đều làm mọi thứ tệ hơn.

Điều gì thực sự hiệu quả: tinh chỉnh (96.6% JSON hợp lệ, 91.2% F1) và giải mã bị ràng buộc (100% JSON hợp lệ). Và trong Thử nghiệm 6, điều hướng tính hữu ích đã cho thấy sự cải thiện đáng kể +18% (p=0.042), xác nhận rằng điều hướng hoạt động khi bạn áp dụng nó cho đúng loại vấn đề.

Phương pháp điều hướng SAE của Anthropic không phải là một kỹ thuật phổ quát. Đó là một công cụ chuyên biệt để kiểm soát ngữ nghĩa.

Nó hoạt động cho các đặc điểm tính cách, an toàn, giảm thiên vị, tập trung chủ đề. Đây là các khái niệm ngữ nghĩa, liên tục. Nó thất bại với cú pháp JSON, khớp dấu ngoặc, đặt dấu ngoặc kép. Đây là các cấu trúc, nhị phân, trạng thái. Các vấn đề khác nhau, cơ chế khác nhau.

Tôi đã dành nhiều tuần để cố gắng ép buộc điều hướng hoạt động cho JSON. Các cường độ khác nhau, các lớp khác nhau, sửa đổi thiên vị vĩnh viễn, thêm kích hoạt tại thời điểm suy luận, điều hướng trong quá trình đào tạo, kết hợp với tinh chỉnh. Mọi phương pháp đều thất bại. Không phải do lỗi trong triển khai của tôi, mà vì đó là công cụ sai.

Khoảnh khắc tôi chuyển sang giải mã bị ràng buộc, tôi đã đạt được 100% JSON hợp lệ ngay trong thử nghiệm đầu tiên.

Nếu bạn đang làm việc với LLM và cần kiểm soát hành vi của chúng, hãy hỏi: tôi đang cố gắng ảnh hưởng đến cái gì mô hình nói, hay cách nó định dạng những gì nó nói? Nếu là cái gì: điều hướng. Nếu là cách: ràng buộc. Nếu cả hai: làm cả hai.

Điều hướng là một con dao mổ cho phẫu thuật ngữ nghĩa, không phải là một cái búa để xây dựng cú pháp. Biết sự khác biệt là điều phân biệt hệ thống sản xuất với các bản demo nghiên cứu.


Lời Cảm Ơn

Công việc này được thực hiện bằng:

  • Các mô hình đã kiểm tra:
    • Qwen/Qwen2.5-0.5B (494M tham số) - mô hình chính cho các thử nghiệm blog
    • LiquidAI/LFM2-350M (350M tham số) - xác minh bổ sung
    • Google/Gemma-2B với các đặc trưng Gemma Scope SAE - cho các thử nghiệm trích xuất vector điều hướng
  • Tập dữ liệu: Nemotron-PII (30K mẫu, 55 loại thực thể PII)
  • Thư viện: Transformers (HuggingFace), json-repair (dự phòng), LogitsProcessor tùy chỉnh dựa trên FSM
  • Tính toán: GPU NVIDIA A100

Cảm ơn nhóm nghiên cứu về khả năng diễn giải của Anthropic vì công việc của họ về điều hướng SAE, điều này đã truyền cảm hứng cho nghiên cứu này.

Tài Liệu Tham Khảo

  1. Anthropic. (2024). “Scaling Monosemanticity: Extracting Interpretable Features from Claude 3 Sonnet.” Anthropic Interpretability Team. https://www.anthropic.com/news/mapping-mind-language-model
  2. Templeton et al. (2024). “Scaling Monosemanticity: Extracting Interpretable Features from Claude 3 Sonnet.” Anthropic Research.
  3. Tài liệu HuggingFace Transformers. “LogitsProcessor for Constrained Generation.” https://huggingface.co/docs/transformers/main_classes/text_generation
  4. Willard, B. & Louf, R. (2023). “Efficient Guided Generation for Large Language Models.” arXiv preprint.
  5. Turner, A. et al. (2024). “Activation Addition: Steering Language Models without Optimization.” arXiv preprint.
  6. Zou, A. et al. (2023). “Representation Engineering: A Top-Down Approach to AI Transparency.” arXiv preprint.
    <div id="69892479573fbffd10a8fbc2" class="scroll-mt-4 ">
      <div class="flex h-10 items-center justify-between gap-1 px-3 ">
        <div class="flex max-w-full items-center overflow-hidden">
          <span class="inline-block "><span class="contents"><div class="mr-2 flex shrink-0 items-center"><div class="flex-none mr-2"><img alt="" class="size-3.5 rounded-full flex-none select-none" src="https://cdn-avatars.huggingface.co/v1/production/uploads/63e95f58ca4fc7d30dee4b98/CVoT8VqQLQFNNoW192H_z.jpeg" crossorigin="anonymous"></div><a class="whitespace-nowrap font-semibold hover:underline" href="/TylerHilbert">TylerHilbert</a></div></span></span>
          <a href="#69892479573fbffd10a8fbc2" class="truncate text-xs text-gray-400 hover:underline sm:text-sm"><time datetime="2026-02-09T00:04:09.000Z" title="Mon, 09 Feb 2026 00:04:09 GMT">9 days ago</time></a>
        </div>
        <div class="flex items-center space-x-2">
          <div class="relative flex items-center"><button class="text-gray-500 focus:text-gray-900 dark:focus:text-gray-400 " type="button">
              <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><circle cx="16" cy="7" r="3" fill="currentColor"></circle><circle cx="16" cy="16" r="3" fill="currentColor"></circle><circle cx="16" cy="25" r="3" fill="currentColor"></circle></svg>
            </button></div>
        </div>
      </div>
      <div class="break-words rounded-b-lg bg-white px-3.5 pb-2.5 pt-1">
        <div class="prose text-smd/6 sm:text-base/[1.6rem] prose-card hf-sanitized copiable-code-container">
          <p>Thanks for sharing.<br>It makes sense the constrained decoding would create the best results for generating valid json.<br>I was wondering if you have any thoughts on using constrained decoding for generating code for compiled languages, such as C++. Could you utilize a compiler as feedback for the constrained decoder, and if so, would the generated code likely be correct?</p>
        </div>
        <div class="mt-1 leading-tight"><button class="cursor-pointer text-sm text-blue-500 hover:text-blue-700 dark:hover:text-blue-400">See translation</button></div>
        <div class="mt-3 flex items-center gap-2">
          <ul class="flex items-center text-gray-600 flex-row text-xs mr-1.5">
            <li class="-mr-1.5 h-3 w-3 md:h-4 md:w-4 bg-linear-to-br block flex-none rounded-full border-2 border-white from-gray-300 to-gray-100 dark:border-gray-900 dark:from-gray-600 dark:to-gray-800 " title="MaziyarPanahi" style="content-visibility:auto;"><a href="/MaziyarPanahi" title="MaziyarPanahi"><img class="overflow-hidden" alt="" src="https://cdn-avatars.huggingface.co/v1/production/uploads/5fd5e18a90b6dc4633f6d292/gZXHW5dd9R86AV9LMZ--y.png" loading="lazy"></a></li>
            <li class="text-xs hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 order-last ml-2"><button class="ml-1 whitespace-nowrap text-sm text-gray-500 underline decoration-gray-200 underline-offset-2 hover:decoration-gray-400 dark:decoration-gray-600 dark:hover:decoration-gray-400">1 reply</button></li>
          </ul>
          <span class="mr-2 text-gray-300">·</span>
          <div class="peer-first:mt-2! -ml-1 flex gap-y-1.5 space-x-1 overflow-hidden text-sm">
            <div class="scrollbar-hidden mr-1 flex select-none gap-x-1 overflow-x-auto overflow-y-hidden text-sm"></div>
            <div>
              <div class="flex" slot="anchor"><button class="group z-10 select-none"><span class="group relative flex aspect-1 size-7 flex-none select-none items-center justify-center rounded-full border-none text-lg leading-none text-gray-500/80 ring-1 ring-inset ring-gray-100 hover:bg-gray-100 hover:text-gray-700 active:ring-gray-300 dark:ring-gray-800 dark:hover:bg-gray-900 dark:hover:text-yellow-500 dark:active:ring-orange-500/30">1</span></button></div>
            </div>
          </div>
        </div>
      </div>
      <div class="mt-4 flex flex-col ml-2"><div class="border-l pl-1 xl:pl-2">
          <dialog class="shadow-alternate z-40 mx-4 my-auto h-fit select-text overflow-hidden rounded-xl bg-white max-sm:max-w-[calc(100dvw-2rem)] sm:mx-auto lg:mt-26 md:portrait:mt-30 xl:mt-30 2xl:mt-32 w-full lg:w-10/12 xl:w-8/12 2xl:w-7/12 max-w-[calc(100%-4rem)] lg:max-w-4xl ">
            <div tabindex="-1" class="outline-none focus:ring-0 focus-visible:ring-0"></div>
          </dialog>
          <div id="698afedeb0ace27e7704a87c" class="scroll-mt-4 ">
            <div class="flex h-10 items-center justify-between gap-1 px-3 ">
              <div class="flex max-w-full items-center overflow-hidden">
                <span class="inline-block "><span class="contents"><div class="mr-2 flex shrink-0 items-center"><div class="flex-none bg-linear-to-br relative rounded-full from-pink-500 via-green-500 to-yellow-500 p-px mr-2"><img alt="" class="size-3.5 rounded-full flex-none select-none bg-white p-px" src="https://cdn-avatars.huggingface.co/v1/production/uploads/5fd5e18a90b6dc4633f6d292/gZXHW5dd9R86AV9LMZ--y.png" crossorigin="anonymous"><svg class="absolute -bottom-1 -right-1 text-sm text-white dark:text-gray-950" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 12 12"><path d="M10.5 6.36328C10.4998 6.61534 10.3117 6.82821 10.0615 6.85938C9.32558 6.95111 8.62935 7.2287 8.0459 7.66406C7.67946 7.9406 7.38831 8.2959 7.19336 8.69824C6.99846 9.10055 6.90558 9.54059 6.9209 9.98242C6.92561 10.118 6.87449 10.2501 6.78027 10.3477C6.68608 10.445 6.55635 10.5 6.4209 10.5H5.5791C5.30296 10.5 5.0791 10.2761 5.0791 10C5.0791 8.87021 4.58249 8.14202 3.96387 7.66699L3.73926 7.50977C3.20273 7.16204 2.5865 6.93857 1.93945 6.85938C1.6888 6.82871 1.5002 6.61576 1.5 6.36328V5.63672C1.5002 5.38466 1.68831 5.17179 1.93848 5.14062C2.67435 5.0489 3.36971 4.77026 3.95312 4.33496C4.31963 4.05841 4.61166 3.70415 4.80664 3.30176C5.00154 2.89945 5.09442 2.45941 5.0791 2.01758C5.07439 1.88204 5.12551 1.74989 5.21973 1.65234C5.31392 1.55502 5.44365 1.5 5.5791 1.5H6.4209C6.69704 1.5 6.9209 1.72386 6.9209 2C6.9209 3.13215 7.41961 3.86098 8.04004 4.33594L8.29688 4.51465C8.90961 4.90301 9.59451 5.09458 10.0488 5.13965C10.3045 5.16497 10.4998 5.37984 10.5 5.63672V6.36328Z" fill="url(#paint0_linear_345_4)" stroke="currentColor" stroke-linejoin="round"></path><defs><linearGradient id="paint0_linear_345_4" x1="3.69298" y1="3.83122" x2="7.69421" y2="8.60076" gradientUnits="userSpaceOnUse"><stop stop-color="#FF0789"></stop><stop offset="0.63" stop-color="#21DE75"></stop><stop offset="1" stop-color="#FF8D00"></stop></linearGradient></defs></svg></div><a class="whitespace-nowrap font-semibold hover:underline" href="/MaziyarPanahi">MaziyarPanahi</a></div></span></span>
                <span class="max-w-[175px] truncate border font-semibold leading-snug sm:max-w-xs rounded-md px-1.5 border-blue-200 bg-blue-600/10 text-blue-500 dark:border-blue-800/60 dark:bg-blue-800/20 text-sm mr-2">Article author</span>
                <a href="#698afedeb0ace27e7704a87c" class="truncate text-xs text-gray-400 hover:underline sm:text-sm"><time datetime="2026-02-10T09:48:14.000Z" title="Tue, 10 Feb 2026 09:48:14 GMT">7 days ago</time></a>
              </div>
              <div class="flex items-center space-x-2">
                <div class="relative flex items-center"><button class="text-gray-500 focus:text-gray-900 dark:focus:text-gray-400 " type="button">
                    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><circle cx="16" cy="7" r="3" fill="currentColor"></circle><circle cx="16" cy="16" r="3" fill="currentColor"></circle><circle cx="16" cy="25" r="3" fill="currentColor"></circle></svg>
                  </button></div>
              </div>
            </div>
            <div class="break-words rounded-b-lg bg-white px-3.5 pb-2.5 pt-1">
              <div class="prose text-smd/6 sm:text-base/[1.6rem] prose-card hf-sanitized copiable-code-container">
                <p>thank you! glad you enjoyed it!</p>
              </div>
              <div class="mt-1 leading-tight"><button class="cursor-pointer text-sm text-blue-500 hover:text-blue-700 dark:hover:text-blue-400">See translation</button></div>
              <div class="mt-3 flex items-center gap-2">
                <ul class="flex items-center text-gray-600 flex-row text-xs mr-1.5">
                  <li class="-mr-1.5 h-3 w-3 md:h-4 md:w-4 bg-linear-to-br block flex-none rounded-full border-2 border-white from-gray-300 to-gray-100 dark:border-gray-900 dark:from-gray-600 dark:to-gray-800 " title="MaziyarPanahi" style="content-visibility:auto;"><a href="/MaziyarPanahi" title="MaziyarPanahi"><img class="overflow-hidden" alt="" src="https://cdn-avatars.huggingface.co/v1/production/uploads/5fd5e18a90b6dc4633f6d292/gZXHW5dd9R86AV9LMZ--y.png" loading="lazy"></a></li>
                  <li class="text-xs hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 order-last ml-2"><button class="ml-1 whitespace-nowrap text-sm text-gray-500 underline decoration-gray-200 underline-offset-2 hover:decoration-gray-400 dark:decoration-gray-600 dark:hover:decoration-gray-400">1 reply</button></li>
                </ul>
                <span class="mr-2 text-gray-300">·</span>
                <div class="peer-first:mt-2! -ml-1 flex gap-y-1.5 space-x-1 overflow-hidden text-sm">
                  <div class="scrollbar-hidden mr-1 flex select-none gap-x-1 overflow-x-auto overflow-y-hidden text-sm"></div>
                  <div>
                    <div class="flex" slot="anchor"><button class="group z-10 select-none"><span class="group relative flex aspect-1 size-7 flex-none select-none items-center justify-center rounded-full border-none text-lg leading-none text-gray-500/80 ring-1 ring-inset ring-gray-100 hover:bg-gray-100 hover:text-gray-700 active:ring-gray-300 dark:ring-gray-800 dark:hover:bg-gray-900 dark:hover:text-yellow-500 dark:active:ring-orange-500/30"><svg class="size-5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M12.33 2.74c1.49.07 2.88.5 4.1 1.19h-.14c-.65 0-1.24.23-1.7.61A7.93 7.93 0 0 0 3.91 12a7.94 7.94 0 0 0 15.89.07c.5-.13.96-.4 1.3-.77.02.23.03.46.03.7l-.01.48a9.28 9.28 0 0 1-9.26 8.8l-.48-.02a9.28 9.28 0 0 1-8.79-8.78V12a9.28 9.28 0 0 1 9.27-9.27h.47Zm-.52 10.24c2.3 0 4.17-2.17 4.17.13a4.17 4.17 0 0 1-8.34 0c0-2.3 1.87-.13 4.17-.13ZM9.53 8.24a1.09 1.09 0 1 1 0 2.17 1.09 1.09 0 0 1 0-2.17Zm4.66 0a1.09 1.09 0 1 1 0 2.18 1.09 1.09 0 0 1 0-2.18Zm4.95-5.38c.48 0 .87.4.87.87v2.02h2a.87.87 0 0 1 0 1.74h-2V9.5a.87.87 0 0 1-1.73 0V7.49h-2a.87.87 0 0 1 0-1.74h2V3.73c0-.48.39-.86.86-.87Z" fill="currentColor"></path></svg></span></button></div>
                  </div>
                </div>
              </div>
            </div>
            <dialog class="shadow-alternate z-40 mx-4 my-auto h-fit select-text overflow-hidden rounded-xl bg-white max-sm:max-w-[calc(100dvw-2rem)] sm:mx-auto lg:mt-26 md:portrait:mt-30 xl:mt-30 2xl:mt-32 w-full lg:w-7/12 max-w-[calc(100%-4rem)] md:max-w-2xl ">
              <div tabindex="-1" class="outline-none focus:ring-0 focus-visible:ring-0"></div>
            </dialog>
          </div>
        </div>
      </div>
    </div>
    <div class="mx-2 mt-1"><input type="text" class="form-input w-full cursor-pointer py-1.5" placeholder="Reply in thread" /></div>
  </div>
</div>

Recommended for You

Cách Sử dụng Nhiều GPU trong Hugging Face Transformers- Device Map so với Tensor Parallelism

Cách Sử dụng Nhiều GPU trong Hugging Face Transformers- Device Map so với Tensor Parallelism

Hướng dẫn cách sử dụng nhiều GPU với Hugging Face Transformers, so sánh Device Map và Tensor Parallelism.

Forge- Khung và Thuật toán Agent RL có thể mở rộng

Forge- Khung và Thuật toán Agent RL có thể mở rộng

Một bài viết về Forge, một khung và thuật toán Agent RL có thể mở rộng.