Harness Academy
Tài liệu gốc 29 10 phútTiếng Việt + English
docs/en/s26-evaluation-system.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

s26: Hệ thống đánh giá

s00 > s01 > s02 > s03 > s04 > s05 > s06 > s07 > s08 > s09 > s10 > s11 > s12 > s13 > s14 > s15 > s16 > s17 > s18 > s19 > s20 > s21 > s22 > s23 > s24 > s25 > [ s26 ] > s27

Trước khi cải thiện bất cứ điều gì, hãy học cách đo lường nó. Chương này xây dựng cơ sở hạ tầng đánh giá: cách tạo dữ liệu thử nghiệm, cách chấm điểm đầu ra của agent và cách sử dụng các ràng buộc cứng để chặn các thay đổi xấu.

Thành phần hệ thống đánh giá

Chương này giải quyết vấn đề gì

s25 đã đưa ra bức tranh đầy đủ về quá trình phát triển kỹ năng và lộ trình của nó. Nhưng quy trình này có một điều kiện tiên quyết: bạn cần một cách để định lượng "tốt hay xấu".

Sau khi chỉnh sửa thủ công SKILL.md, làm sao bạn biết nó tốt hơn hay tệ hơn? Bằng trực giác? Bằng cách chạy một hoặc hai ví dụ?

Những gì quá trình phát triển kỹ năng đòi hỏi là đánh giá có thể lặp lại, định lượng, tự động hóa -- chạy cùng một kỹ năng với cùng một bộ trường hợp thử nghiệm và nhận được điểm. Chỉnh sửa nó, chạy lại, so sánh điểm số. Đó là hệ thống đánh giá.

Ba thành phần:

  1. Đánh giá tập dữ liệu -- Cần kiểm tra cái gì? (Tổng hợpDatasetBuilder)
  2. Chức năng thể dục -- Làm thế nào để ghi điểm? (FitnessScore + LLM-với tư cách là giám khảo)
  3. Ràng buộc kiểm soát -- Khi nào nên từ chối hoàn toàn? (ConstraintValidator)

Đề xuất đọc

  • s25-skill-evolution.md -- Tổng quan về tiến hóa kỹ năng; chương này bao gồm các bước 2-4 của quy trình
  • s08-skill-system.md -- Định dạng tệp kỹ năng (đối tượng đang được đánh giá)

Các quyết định thiết kế chính

Tại sao dự kiến_behavior là một phiếu tự đánh giá, không phải văn bản chính xác

# Bad: exact matching
expected_behavior = "pip install -e '.[dev]'"

# Good: rubric description
expected_behavior = "Should use editable install instead of requirements.txt"

Văn bản chính xác quá dễ vỡ -- "hãy sử dụng pip install -e .[dev]" và "chạy cài đặt có thể chỉnh sửa qua pip" có nghĩa giống nhau, nhưng việc khớp chính xác sẽ đánh dấu cài đặt đó là lỗi. Phiếu tự đánh giá cho phép LLM với tư cách là thẩm phán thực hiện việc hiểu ngữ nghĩa, gần giống với đánh giá của con người hơn nhiều.

Tại sao chia thành train/val/holdout

Bộ dữ liệuĐược sử dụng bởiMục đích
tàuTrình tối ưu hóa nhìn thấy nó mọi vòngThu thập ý kiến ​​phản hồi, hướng dẫn đột biến
giáOptimizer chọn phiên bản tốt nhấtNgăn chặn việc trang bị quá mức để tập luyện
chờ giữChỉ được sử dụng trong quá trình đánh giá cuối cùng"Bài kiểm tra" thực sự -- không bao giờ được sử dụng trong quá trình tối ưu hóa

Nếu bạn chỉ sử dụng một tập dữ liệu, trình tối ưu hóa sẽ "ghi nhớ các câu trả lời" -- nó tiếp tục điều chỉnh để vượt qua các trường hợp kiểm thử cụ thể đó nhưng lại không thực hiện được các tác vụ mới. Sự phân chia ba chiều ngăn chặn kiểu trang bị quá mức này.

Tại sao phản hồi lại quan trọng hơn điểm số

@dataclass
class FitnessScore:
    correctness: float = 0.0
    procedure_following: float = 0.0
    conciseness: float = 0.0
    feedback: str = ""          # <- this field drives the entire optimization

Điểm cho bạn biết "tốt hay xấu." Phản hồi cho bạn biết "tại sao nó xấu và cách khắc phục."

Trong s27, trình tối ưu hóa thu thập phản hồi mỗi vòng và cung cấp phản hồi đó cho LLM để tạo đột biến mục tiêu. Nếu không có phản hồi, đột biến sẽ trở nên mù quáng -- những chỉnh sửa ngẫu nhiên, hy vọng điều tốt nhất. Với phản hồi, đột biến có hướng -- "xử lý lỗi bị thiếu" dẫn đến việc bổ sung xử lý lỗi; "các bước không rõ ràng" dẫn đến việc viết lại cho rõ ràng.

Đây là ý tưởng cốt lõi đằng sau GEPA: đọc dấu vết -> hiểu lý do -> thay đổi có mục đích. Phiên bản giảng dạy mô phỏng ý tưởng tương tự bằng cách sử dụng trường phản hồi.

Thành phần 1: SyntheticDatasetBuilder

Nó làm gì

Đọc văn bản kỹ năng và yêu cầu LLM tạo một tập hợp các trường hợp thử nghiệm. Mỗi trường hợp là một (task_input, expected_behavior) cặp.

Dữ liệu đến từ đâu

Hermes hỗ trợ ba nguồn dữ liệu:

NguồnThực hiệnChất lượngPhiên bản giảng dạy
Tổng hợpKỹ năng đọc LLM -> tạo trường hợpTrung bìnhĐã triển khai
PhiênDBKhai thác từ lịch sử hội thoại thực tế + tính điểm LLMCaoChỉ khái niệm
VàngBộ bài kiểm tra được viết thủ côngCao nhấtChỉ khái niệm

Hermes' external_importers.py (~500 dòng) cũng có thể khai thác dữ liệu từ lịch sử trò chuyện của chính Claude Code, Copilot và Hermes -- giải quyết vấn đề khởi đầu "người dùng mới không có tập dữ liệu vàng". Nó thực hiện phát hiện bí mật (ngăn khóa API rò rỉ vào tập dữ liệu), lọc mức độ liên quan (LLM đánh giá xem cuộc hội thoại có liên quan đến kỹ năng mục tiêu hay không) và tự động chấm điểm.

Phiên bản giảng dạy chỉ thực hiện tạo tổng hợp -- ý tưởng cốt lõi giống nhau và không cần nguồn dữ liệu bên ngoài.

Thực hiện tối thiểu

class SyntheticDatasetBuilder:
    def generate(self, skill_text: str, num_cases: int = 15) -> EvalDataset:
        prompt = f"Read this skill and generate {num_cases} test cases..."
        response = client.chat.completions.create(model=MODEL, messages=[...])
        # Parse JSON -> create EvalExample list
        # Shuffle -> split 60/20/20 into train/val/holdout

Thành phần 2: đánh giá_skill() + FitnessScore

Nó làm gì

Đưa ra một văn bản về kỹ năng và một trường hợp kiểm tra, hãy trả lời "kỹ năng này thực hiện nhiệm vụ này tốt như thế nào?"

Quy trình hai bước

Step 1: Have the agent process the task using the skill
  system prompt = skill text
  user message = task_input
  -> produces agent_output

Step 2: LLM-as-judge scores the output
  input = skill + task + rubric + agent_output
  -> produces correctness / procedure_following / conciseness / feedback

Nội dung này trình bày chi tiết về hệ thống, giới hạn và cách vận hành của agent.

Chế độ Heuristic nhanh

LLM-as-thẩm phán là chính xác nhưng chậm. Trong quá trình tối ưu hóa, mỗi vòng cần chạy N trường hợp kiểm thử x M lần lặp -- sử dụng LLM cho tất cả chúng là quá tốn kém.

Hermes' skill_fitness_metric() sử dụng trùng lặp từ khóa làm điểm proxy nhanh:

expected_words = set(expected_behavior.lower().split())
skill_words = set(skill_text.lower().split())
overlap = len(expected_words & skill_words) / len(expected_words)
score = 0.3 + 0.7 * overlap

Không chính xác nhưng đủ tốt -- hãy sử dụng nó để tăng tốc vòng lặp tối ưu hóa, sau đó chuyển về LLM với tư cách là người đánh giá để đánh giá cuối cùng.

Thành phần 3: ConstraintValidator

Nó làm gì

Văn bản được phát triển phải vượt qua bốn lần kiểm tra cứng. Nếu bất kỳ lần kiểm tra nào không thành công, thay đổi sẽ bị từ chối -- bất kể điểm số cao đến đâu.

Bốn hạn chế

Ràng buộcQuy tắcCơ sở lý luận
size_limit<= 15KBPrevent skill bloat -- LLMs tend to "add more instructions" to boost scores
Hệ thống còn có các ràng buộc bổ sung được trình bày trong phiên bản đầy đủ. growth_limit
non_emptyMust not be emptyMutation can produce empty text
skill_structureMust start with # or ---Ensure valid markdown format

These four constraints map directly to Hermes' evolution/core/constraints.py.

Hệ thống còn có các ràng buộc bổ sung được trình bày trong phiên bản đầy đủ.

  • Full pytest suite must pass (for code evolution)
  • Benchmark regression check (TBLite score must not drop more than 2%)
  • Semantic fidelity (must not drift from the original purpose)
  • Cache compatibility (must not invalidate mid-conversation caches)

Walkthrough: Evaluating a Skill

=== Input ===
skill_text: "# GitHub Actions CI\n1. Create .github/workflows/ci.yml\n2. Use pip install..."
test_case: EvalExample(
    task_input="Help me set up CI for a Python project",
    expected_behavior="Should use pip install -e instead of pip install -r, mention Codecov token"
)

=== Step 1: Agent Execution ===
system: "Follow these instructions:\n# GitHub Actions CI\n1. Create..."
user: "Help me set up CI for a Python project"
-> agent_output: "Sure, I'll help you configure...\n1. Create ci.yml...\nUse pip install -r requirements.txt..."

=== Step 2: LLM-as-judge Scoring ===
input: skill + task + rubric + agent_output
-> {
    "correctness": 0.4,       // used pip install -r, not -e
    "procedure_following": 0.7, // followed most steps
    "conciseness": 0.8,       // response was concise
    "feedback": "Skill does not explicitly say not to use pip install -r; should add a warning at step 2"
  }
-> composite = 0.5*0.4 + 0.3*0.7 + 0.2*0.8 = 0.57

=== Constraint Check ===
size_limit: 800/15000 chars -> OK
non_empty: OK
skill_structure: starts with # -> OK

Hệ thống còn có các ràng buộc bổ sung được trình bày trong phiên bản đầy đủ.

Common Beginner Mistakes

1. Using Exact Matching for Evaluation

Nội dung này mô tả quy tắc đánh giá và cách vận hành trong hệ thống agent. pip install -e

Fix: Use rubric descriptions + LLM-as-judge so that evaluation performs semantic understanding.

2. Running Constraint Gating After Evaluation

Run the full evaluation first (expensive), then discover the evolved skill exceeds 15KB (constraint fails). You just wasted those evaluation API calls.

Fix: Run constraint checks before evaluation. Hermes checks baseline constraints first, then runs optimization, then checks evolved constraints.

3. Eval Dataset Too Small

3 test cases -> the optimizer easily "memorizes the answers" and overfits.

Nội dung này mô tả quy tắc đánh giá và cách vận hành trong hệ thống agent.

Scope of This Chapter

Nội dung này mô tả quy tắc đánh giá và cách vận hành trong hệ thống agent.

Covered:

  • How to generate eval datasets (synthetic)
  • How the fitness function scores (LLM-as-judge + heuristic)
  • How constraint gating rejects bad changes (four hard checks)

Not covered:

  • Full implementation of SessionDB mining and external importers -> concept introduced
  • DSPy Signature's specific API -> phiên bản giảng dạy sử dụng tính năng hoàn thành trò chuyện trực tiếp
  • Benchmark gating (TBLite / YC-Bench) -> yêu cầu môi trường chạy đầy đủ

Chương này liên quan đến chương khác như thế nào

  • s25 là tổng quan -> chương này thực hiện các bước 2-4
  • s27 là bước 5-7 -> nó tiêu thụ FitnessScore và ConstraintResult được tạo ở đây
  • s23 extract_tool_stats() -> có thể đóng vai trò là một nguồn tín hiệu đánh giá (công cụ nào thành công/thất bại)

Sau chương này, bạn sẽ có thể trả lời

  • Tại sao dự kiến_behavior sử dụng phiếu tự đánh giá thay vì văn bản chính xác?
  • Mỗi phần trong số ba phần tách tập dữ liệu (train/val/holdout) được sử dụng để làm gì? Điều gì xảy ra nếu bạn đánh rơi một cái?
  • Ai sử dụng trường phản hồi trong FitnessScore? Tại sao nó quan trọng hơn điểm số?
  • Việc hạn chế gating giải quyết được vấn đề gì? Tại sao size_limit là cổng cứng?
  • Khi nào bạn sử dụng tính năng tính điểm theo kinh nghiệm nhanh so với LLM với tư cách là giám khảo?

Hãy nhớ một câu: bộ ba đánh giá -- tập dữ liệu cho bạn biết cần kiểm tra những gì, hàm thích hợp cho bạn biết nó tốt đến mức nào và cổng ràng buộc cho bạn biết liệu nó có thể được vận chuyển hay không.

Mục lục nguồn