FDE PulseViệc làm FDE đang mở 314Mới đăng 7 ngày qua 10Chủ đề nổi bật: Đào tạo kỹ năng FDE tại Đông Nam Á

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Bốn cách bắt model tự phản biện trước quyết định lớn của khách

Lấy nhiều mẫu, dùng nhiều prompt, lùi lại tìm nguyên tắc rồi tìm kiếm theo cây: bốn lớp này giúp bạn biết lúc nào nên tin model và lúc nào cần chuyển cho người duyệt.

Đồ hoạLuồng bỏ phiếu và hai nhánh tùy chọn
  1. 11. Self-consistencyMột prompt chạy nhiều lần với temperature lớn hơn 0, đếm phiếu
  2. 22. Prompt ensemblingBa prompt khác góc nhìn, mỗi prompt ba mẫu: tổng 9 lần gọi
  3. 33. Định tuyến theo ngưỡngĐồng thuận cao đi thẳng; dưới ngưỡng thì chuyển cho người duyệt
  4. 4Tùy chọn: step-backModel nêu nguyên tắc chung trước khi lập luận; chuyên gia của khách đọc lại được
  5. 5Tùy chọn: tree of thoughtsCho bài toán nhiều bước phụ thuộc: sinh, chấm, tìm kiếm BFS, khoảng 30 lần gọi

Bỏ phiếu cho ra tỷ lệ đồng thuận để định tuyến; step-back và ToT chỉ thêm vào khi bài toán cần.

Đồ hoạ: FDE Times

Tóm tắt nhanh

  • Self-consistency hỏi cùng một prompt nhiều lần rồi lấy đáp án đa số; bài báo gốc ghi nhận GSM8K tăng 17,9%.
  • Step-back bắt model nêu nguyên tắc chung trước rồi mới lập luận; tree of thoughts kết hợp sinh và chấm ý tưởng với BFS/DFS.
  • Mỗi lớp nhân thêm số lần gọi model, nên chỉ dùng cho quyết định đắt giá và đừng ép reasoning model suy luận từng bước.
Chia sẻLinkedInFacebookX

Trên bộ đề toán GSM8K, chỉ cần hỏi model nhiều lần rồi lấy đáp án được chọn nhiều nhất, độ chính xác đã tăng 17,9% so với chain-of-thought chạy greedy decoding. Trên trò Game of 24, GPT-4 dùng chain-of-thought chỉ giải được 4% số bài, trong khi tree of thoughts đạt 74%.

Hai con số đó đến từ benchmark chứ không đến từ hệ thống của khách hàng. Dù vậy, chúng cho thấy một điều mà FDE nào cũng sẽ gặp: với cùng một model, cách bạn tổ chức các lần gọi có thể quan trọng ngang với bản thân prompt.

Ở site khách, nhiều quyết định không được phép sai: duyệt hay từ chối một hồ sơ, chọn nhà cung cấp nào, có cần escalate một sự cố hay không. Bài này hướng dẫn bạn dựng một bộ khung nhỏ gồm bốn lớp, đồng thời chỉ ra lớp nào đáng tiền và lớp nào chỉ làm tăng hóa đơn API.

Bạn sẽ dựng gì, và cần chuẩn bị gì?

Thử hình dung một tình huống giả định: khách hàng là công ty bảo hiểm, cần model đọc hồ sơ bồi thường và điều khoản hợp đồng rồi kết luận CHI_TRẢ hoặc TỪ_CHỐI. Một lần gọi model cho bạn một câu trả lời nhưng không cho biết model chắc chắn đến đâu. Mục tiêu là đổi một lần đoán thành một cuộc bỏ phiếu có số liệu đi kèm.

Bạn cần Python 3 và SDK của nhà cung cấp model mà khách đang dùng. Code bên dưới đã được đơn giản hóa: hàm call_llm chỉ là chỗ để bạn cắm SDK thật vào, còn tên tham số và cách xử lý lỗi sẽ khác tùy nhà cung cấp.

from collections import Counter

def call_llm(prompt: str, temperature: float = 0.7) -> str:
    # Giả định: thay bằng lời gọi SDK thật của bạn
    raise NotImplementedError

def extract_answer(text: str) -> str:
    # Quy ước: model kết thúc bằng dòng "KẾT LUẬN: <nhãn>"
    for line in reversed(text.splitlines()):
        if line.startswith("KẾT LUẬN:"):
            return line.split(":", 1)[1].strip().upper()
    return "KHÔNG_RÕ"

Đừng xem nhẹ dòng KẾT LUẬN. Nếu không ép được định dạng đầu ra, bạn không thể đếm phiếu, và mọi bước phía sau đều sụp theo.

Bước 1: hỏi một câu năm lần, đếm phiếu

Thay vì để chain-of-thought chạy với greedy decoding, self-consistency lấy mẫu nhiều đường lập luận khác nhau, rồi chọn đáp án nhất quán nhất giữa các đường đó. Khi làm thực tế, bạn chỉ cần gửi cùng một prompt nhiều lần với temperature lớn hơn 0 và lấy đáp án chiếm đa số.

def self_consistency(prompt: str, n: int = 5):
    answers = [extract_answer(call_llm(prompt, temperature=0.7))
               for _ in range(n)]
    votes = Counter(answers)
    label, count = votes.most_common(1)[0]
    return label, count / n, votes

Kiểm tra: chạy thử một hồ sơ. Nếu kết quả là 3 phiếu TỪ_CHỐI và 2 phiếu CHI_TRẢ, nhãn cuối cùng là TỪ_CHỐI với tỷ lệ đồng thuận 0,6.

Một hồ sơ đạt 5/5 phiếu hoàn toàn có thể là câu trả lời chắc chắn thật, nhất là với những ca dễ. Chỉ khi mọi hồ sơ trong tập thử đều 5/5 thì mới nên xem lại temperature, vì có thể bạn chưa thật sự lấy mẫu.

Ở site khách, hãy trả về cả tỷ lệ đồng thuận chứ đừng chỉ trả về nhãn. Một hồ sơ được 5/5 phiếu và một hồ sơ chỉ được 3/5 phiếu không nên đi chung một luồng xử lý.

Bước 2: đổi góc nhìn bằng prompt ensembling

Self-consistency lấy mẫu từ một prompt duy nhất, nên nếu prompt đó lệch thì cả năm phiếu có thể lệch theo cùng một hướng. Prompt ensembling khắc phục điểm này: dùng nhiều prompt cho cùng một bài toán rồi gộp các câu trả lời thành kết quả cuối.

PROMPTS = [
    "Bạn là chuyên viên bồi thường. Hồ sơ: {case}\n"
    "Kết thúc bằng 'KẾT LUẬN: CHI_TRẢ' hoặc 'KẾT LUẬN: TỪ_CHỐI'.",
    "Liệt kê mọi điều khoản loại trừ liên quan tới hồ sơ: {case}\n"
    "Sau đó kết thúc bằng dòng KẾT LUẬN như trên.",
    "Đóng vai người phản biện, tìm lý do hồ sơ này bị xử lý sai: {case}\n"
    "Sau đó kết thúc bằng dòng KẾT LUẬN như trên.",
]

def ensemble(case: str, n_each: int = 3):
    all_votes = Counter()
    for tpl in PROMPTS:
        _, _, votes = self_consistency(tpl.format(case=case), n=n_each)
        all_votes.update(votes)
    label, count = all_votes.most_common(1)[0]
    return label, count / sum(all_votes.values()), all_votes

Ba prompt nhân ba mẫu cho 9 lần gọi. Giả sử kết quả là 6 phiếu TỪ_CHỐI và 3 phiếu CHI_TRẢ, tỷ lệ đồng thuận là khoảng 0,67. Nên đặt một ngưỡng, chẳng hạn 0,7, và chuyển mọi hồ sơ dưới ngưỡng cho người duyệt. Ngưỡng cụ thể phải hiệu chỉnh trên dữ liệu của khách chứ không nên chọn theo cảm tính.

Lỗi hay gặp: viết ba prompt chỉ khác nhau vài chữ. Lúc đó bạn chỉ có self-consistency tốn gấp ba. Các prompt cần khác nhau về góc nhìn, ví dụ góc người xử lý, góc điều khoản và góc phản biện.

Bước 3: lùi một bước trước khi phán

Step-back prompting gồm hai bước. Đầu tiên model được yêu cầu tập trung vào một khái niệm hoặc nguyên tắc tổng quát hơn liên quan đến câu hỏi, sau đó mới dùng nguyên tắc ấy để lập luận.

Bài báo gốc ghi nhận kỹ thuật này giúp PaLM-2L tăng 7% ở phần Vật lý và 11% ở phần Hóa học của MMLU. Learn Prompting tổng hợp rằng mức vượt chain-of-thought dao động từ 7% đến 27% tùy tác vụ.

def step_back(question: str, case: str) -> str:
    principle = call_llm(
        "Chưa trả lời vội. Nguyên tắc chung nào quyết định "
        f"loại câu hỏi này?\nCâu hỏi: {question}", temperature=0)
    return call_llm(
        f"Nguyên tắc: {principle}\nHồ sơ: {case}\n"
        "Áp dụng nguyên tắc vào hồ sơ. Kết thúc bằng dòng KẾT LUẬN.",
        temperature=0)

Kiểm tra: in biến principle ra và đưa cho chuyên gia nghiệp vụ của khách đọc. Đây là lợi ích phụ nhưng rất đáng giá ở site khách, vì nguyên tắc sai bị phát hiện ngay từ bước một, trước khi nó kéo theo cả kết luận.

Bước 4: tree of thoughts khi bài toán có nhiều nhánh

Có những quyết định không chỉ có hai nhãn, chẳng hạn lập phương án điều phối gồm nhiều bước phụ thuộc nhau. Tree of thoughts xử lý loại này bằng cách cho model sinh các ý tưởng, tự chấm chúng, rồi kết hợp với thuật toán tìm kiếm như BFS hoặc DFS. Phiên bản dưới đây là BFS rút gọn, đã đơn giản hóa nhiều so với bài báo gốc.

def score(path: str) -> float:
    s = call_llm("Chấm 1-10 mức khả thi của hướng lập luận sau. "
                 f"Chỉ trả về một số.\n{path}", temperature=0)
    try:
        return float(s.strip())
    except ValueError:
        return 0.0

def tot_bfs(problem: str, depth=3, breadth=3, keep=2) -> str:
    frontier = [""]
    for _ in range(depth):
        candidates = [
            path + "\n" + call_llm(
                f"Vấn đề: {problem}\nCác bước đã có:{path}\n"
                "Đề xuất MỘT bước tiếp theo.")
            for path in frontier for _ in range(breadth)]
        ranked = sorted(candidates, key=score, reverse=True)
        frontier = ranked[:keep]
    return frontier[0]

Hãy tính số lần gọi trước khi chạy. Ở tầng một có 1 nhánh nhân 3, tức 3 lần sinh và 3 lần chấm. Tầng hai và tầng ba mỗi tầng có 2 nhánh nhân 3, tức 6 lần sinh và 6 lần chấm. Tổng cộng là 30 lần gọi cho một câu hỏi, gấp 30 lần một prompt đơn.

Khi nào không nên dùng bộ khung này?

Prompt Engineering Guide nhắc rằng reasoning model đắt hơn đáng kể so với chat LLM thông thường và chậm hơn, nên chỉ nên dùng cho những thành phần thật sự cần suy luận.

Chạy ensembling 9 lần trên một reasoning model là lấy 9 nhân với một đơn giá mỗi lần gọi vốn đã cao hơn hẳn. Hãy thử trước trên model rẻ, đo xem cải thiện có thật hay không, rồi mới nâng cấp.

Cũng theo hướng dẫn đó, với reasoning model bạn nên tránh ghi chỉ dẫn chain-of-thought kiểu “suy nghĩ từng bước” vào prompt. Lỗi hay gặp là bê nguyên các prompt ở bước 2 sang reasoning model. Hãy giữ phần ngữ cảnh và định dạng KẾT LUẬN, bỏ phần chỉ dẫn từng bước, rồi đo lại.

Kỹ năng này xuất hiện ở site khách như thế nào?

Khách hàng hiếm khi hỏi bạn về self-consistency. Họ sẽ hỏi: “Model sai thì sao?” Câu trả lời tốt nhất là một luồng xử lý cụ thể: hồ sơ có đồng thuận cao đi thẳng, hồ sơ đồng thuận thấp chuyển cho người duyệt, và bạn có bảng số liệu cho thấy tỷ lệ mỗi nhóm.

Trong CV, đừng viết “thành thạo prompt engineering”. Hãy mô tả việc bạn đã làm: dùng ensembling ba prompt kèm ngưỡng đồng thuận để chuyển một phần hồ sơ khó cho người duyệt, đo trên một tập dữ liệu đã gán nhãn, và ghi số liệu thật của bạn chứ không mượn số của benchmark.

Bốn kỹ thuật này không làm model thông minh hơn. Chúng cho model nhiều cơ hội để không đồng ý với chính nó, và chính những lần bất đồng đó cho bạn biết chỗ nào cần một người kiểm tra lại.

9 nguồn
Đọc tiếp trên lộ trình · Chặng 3: AI ứng dụngThực hành: chỉnh top-p, top-k, penalty, max tokens và stop sequence theo từng tác vụ của kháchỞ site khách, dùng chung một bộ tham số cho cả bot hỗ trợ lẫn pipeline trích xuất dữ liệu là cách nhanh nhất để nhận về output lặp từ, JSON bị cắt dở và hóa đơn token vượt dự tính.