Chuyển tới nội dung chính

Nén bối cảnh và bộ nhớ đệm

Hermes Agent sử dụng hệ thống nén kép và bộ nhớ đệm nhắc nhở của Anthropic để quản lý việc sử dụng cửa sổ ngữ cảnh một cách hiệu quả trong các cuộc hội thoại dài.

Tệp nguồn: agent/context_engine.py (ABC), agent/context_compressor.py (công cụ mặc định), `agent/prompt_caching.py

, gateway/run.py (vệ sinh phiên), run_agent.py (tìm kiếm `_compress_context

)

Công cụ bối cảnh có thể cắm được

Quản lý bối cảnh được xây dựng trên ContextEngine ABC ( `agent/context_engine.py

). ContextCompressor tích hợp sẵn là cách triển khai mặc định nhưng các plugin có thể thay thế nó bằng các công cụ thay thế (ví dụ: Quản lý bối cảnh không mất dữ liệu).

context:
engine: "compressor" # default — built-in lossy summarization
engine: "lcm" # example — plugin providing loSSLess context

`
``Động cơ có nhiệm vụ:

- Quyết định khi nào nên kích hoạt quá trình nén (
`should_compress()

)
- Thực hiện đầm nén (
`compress()

)
- Tùy chọn hiển thị các công cụ mà tác nhân có thể gọi (ví dụ:
`lcm_grep

)
- Theo dõi việc sử dụng mã thông báo từ phản hồi API

Lựa chọn được định hướng theo cấu hình thông qua
`context.engine
` trong
`config.yaml

. Trình tự giải quyết:
1. Kiểm tra thư mục
`plugins/context_engine/<name/

2. Kiểm tra hệ thống plugin chung (
`register_context_engine()

)
3. Quay trở lại
`ContextCompressor
` tích hợp

Công cụ plugin **không bao giờ được kích hoạt tự động** — người dùng phải đặt rõ ràng
`context.engine
` thành tên của plugin.

"compressor"
` mặc định luôn sử dụng tính năng tích hợp sẵn.

Định cấu hình qua
`Hermes plugins
` → Plugin nhà cung cấp → Công cụ bối cảnh hoặc chỉnh sửa trực tiếp
`config.yaml

.

Để xây dựng plugin công cụ ngữ cảnh, hãy xem [Context Engine Plugins](/docs/developer-guide/context-engine-plugin).

## Hệ thống nén kép

Hermes có hai lớp nén riêng biệt hoạt động độc lập:

`
┌──────────────────────────┐
Incoming message │ Gateway Session Hygiene │ Fires at 85% of context
─────────────────► │ (pre-agent, rough est.) │ Safety net for large sessions
└─────────────┬────────────┘


┌──────────────────────────┐
│ Agent ContextCompressor │ Fires at 50% of context (default)
│ (in-loop, real tokens) │ Normal context management
└──────────────────────────┘

`

### 1. Vệ sinh phiên cổng (ngưỡng 85%)

Nằm trong
`gateway/run.py
` (tìm kiếm
`Session hygiene: auto-compress

). Đây là **mạng lưới an toàn**
chạy trước khi tác nhân xử lý một tin nhắn. Nó ngăn ngừa lỗi API khi phiên
tăng quá lớn giữa các lượt (ví dụ: tích lũy qua đêm trong Telegram/Discord).
- **Ngưỡng**: Đã sửa ở mức 85% độ dài ngữ cảnh của mô hình
- **Nguồn mã thông báo**: Ưu tiên mã thông báo được báo cáo API thực tế từ lượt trước; ngã lại
đến ước tính dựa trên ký tự thô (
`estimate_messages_tokens_rough

)
- **Kích hoạt**: Chỉ khi
`len(history) >= 4
` và tính năng nén được bật
- **Mục đích**: Bắt các phiên thoát khỏi máy nén của chính tác nhân

Ngưỡng vệ sinh cửa ngõ cố tình cao hơn máy nén của đại lý.
Đặt nó ở mức 50% (giống như tác nhân) gây ra tình trạng nén sớm ở mỗi lượt
trong các phiên cổng dài.

### 2. Agent ContextCompressor (ngưỡng 50%, có thể định cấu hình)

Tọa lạc tại
`agent/context_compressor.py

. Đây là ** nén chính
hệ thống** chạy bên trong vòng công cụ của tác nhân với quyền truy cập chính xác,
Số lượng mã thông báo được API báo cáo.

## Cấu hình

Tất cả cài đặt nén được đọc từ
`config.yaml
` dưới khóa
`compression

:

``` yaml
compression:
enabled: true # Enable/disable compression (default: true)
threshold: 0.50 # Fraction of context window (default: 0.50 = 50%)
target_ratio: 0.20 # How much of threshold to keep as tail (default: 0.20)
protect_last_n: 20 # Minimum protected tail messages (default: 20)

# Summarization model/provider configured under auxiliary:
auxiliary:
compression:
model: null # Override model for summaries (default: auto-detect)
provider: auto # Provider: "auto", "OpenRouter", "nous", "main", etc.
base_url: null # Custom OpenAI-compatible endpoint

`

### Chi tiết tham số

| Tham số | Mặc định | Phạm vi | Mô tả |
|----------|----------|-------|-------------|
|
`threshold
` |
`0.50
` | 0,0-1,0 | Quá trình nén được kích hoạt khi mã thông báo nhắc ≥
`threshold × context_length
` |
|
`target_ratio
` |
`0.20
` | 0,10-0,80 | Kiểm soát ngân sách mã thông báo bảo vệ đuôi:
`threshold_tokens × target_ratio
` |
|
`protect_last_n
` |
`20
` | ≥1 | Số lượng tin nhắn gần đây tối thiểu luôn được giữ nguyên |
|
`protect_first_n
` |
`3
` | (mã hóa cứng) | Lời nhắc hệ thống + trao đổi đầu tiên luôn được bảo tồn |

### Giá trị được tính toán (đối với mô hình bối cảnh 200K theo mặc định)

`
context_length = 200,000
threshold_tokens = 200,000 × 0.50 = 100,000
tail_token_budget = 100,000 × 0.20 = 20,000
max_summary_tokens = min(200,000 × 0.05, 12,000) = 10,000

`

`

## Thuật toán nén

Phương pháp
`ContextCompressor.compress()
` tuân theo thuật toán 4 pha:

### Giai đoạn 1: Cắt bỏ kết quả công cụ cũ (giá rẻ, không gọi LLM)

Kết quả công cụ cũ (>200 ký tự) bên ngoài phần đuôi được bảo vệ được thay thế bằng:

`

[Old tool output cleared to save context space]

`
``Đây là một thẻ vượt qua giá rẻ giúp tiết kiệm các mã thông báo đáng kể từ công cụ dài dòng
kết quả đầu ra (nội dung tập tin, đầu ra terminal, kết quả tìm kiếm).

### Giai đoạn 2: Xác định ranh giới

`
┌─────────────────────────────────────────────────────────────┐
│ Message list │
│ │
[0..2] ← protect_first_n (system + first exchange) │
[3..N] ← middle turns → SUMMARIZed │
[N..end] ← tail (by token budget OR protect_last_n) │
│ │
└─────────────────────────────────────────────────────────────┘

`
``Bảo vệ đuôi **dựa trên ngân sách mã thông báo**: đi lùi từ cuối,
tích lũy token cho đến khi cạn kiệt ngân sách. Trở lại trạng thái cố định
`protect_last_n
` được tính nếu ngân sách sẽ bảo vệ ít tin nhắn hơn.

Các ranh giới được căn chỉnh để tránh chia tách các nhóm tool_call/tool_result.
Phương pháp
`_align_boundary_backward()
` đi qua các kết quả dao liên tiếp
để tìm thông báo trợ lý phụ huynh, giữ nguyên các nhóm.

### Giai đoạn 3: Tạo bản tóm tắt có cấu trúc:::warning Summary model context length
Mô hình tóm tắt phải có cửa sổ ngữ cảnh **ít nhất phải lớn** bằng mô hình tác nhân chính. Toàn bộ phần giữa được gửi đến mô hình tóm tắt trong một lệnh gọi
`call_LLM(task="compression")

. Nếu ngữ cảnh của mô hình tóm tắt nhỏ hơn thì API sẽ trả về lỗi độ dài ngữ cảnh —
`_generate_summary()
` sẽ phát hiện lỗi đó, ghi cảnh báo và trả về
`None

. Sau đó, máy nén bỏ đoạn giữa **không có bản tóm tắt**, âm thầm làm mất bối cảnh cuộc trò chuyện. Đây là nguyên nhân phổ biến nhất làm giảm chất lượng đầm nén.
:::

Các lượt giữa được tóm tắt bằng cách sử dụng LLM phụ trợ với cấu trúc
mẫu:

`
## Goal
[What the user is trying to accomplish]

## Constraints & Preferences
[User preferences, coding style, constraints, important decisions]

## Progress
### Done
[Completed work — specific file paths, commands run, results]
### In Progress
[Work currently underway]
### Blocked
[Any blockers or issues encountered]

## Key Decisions
[Important technical decisions and why]

## Relevant Files
[Files read, modified, or created — with brief note on each]

## Next Steps
[What needs to happen next]

## Critical Context
[Specific values, error messages, configuration details]

`
``Tóm tắt quy mô ngân sách theo số lượng nội dung được nén:
- Công thức:
`content_tokens × 0.20
` (hằng số
`_SUMMARY_RATIO

)
- Tối thiểu: 2.000 token
- Tối đa: token
`min(context_length × 0.05, 12,000)

### Giai đoạn 4: Tập hợp tin nhắn nén

Danh sách tin nhắn nén là:
1. Thông báo chính (có ghi chú được thêm vào lời nhắc hệ thống trong lần nén đầu tiên)
2. Thông báo tóm tắt (vai trò được chọn để tránh vi phạm liên tiếp cùng vai trò)
3. Tin nhắn đuôi (chưa sửa đổi)

Các cặp tool_call/tool_result mồ côi được
`_sanitize_tool_pairs()
` dọn sạch:
- Công cụ kết quả tham chiếu cuộc gọi đã xóa → đã xóa
- Cuộc gọi công cụ có kết quả bị xóa → kết quả sơ khai được chèn

### Nén lại lặp đi lặp lại

Trong các lần nén tiếp theo, bản tóm tắt trước đó được chuyển tới LLM với
hướng dẫn **cập nhật** thay vì tóm tắt từ đầu. Điều này bảo tồn
thông tin qua nhiều lần nén — các mục chuyển từ "Đang tiến hành" sang "Xong",
tiến trình mới được thêm vào và thông tin lỗi thời bị xóa.

Trường
`_previous_summary
` trên phiên bản máy nén lưu trữ bản tóm tắt cuối cùng
văn bản cho mục đích này.

## Ví dụ trước/sau

### Trước khi nén (45 tin nhắn, ~95K token)

`
[0] system: "You are a helpful assistant..." (system prompt)
[1] user: "Help me set up a FastAPI project"
[2] assistant: <tool_call terminal: mkdir project </tool_call
[3] tool: "directory created"
[4] assistant: <tool_call write_file: main.py </tool_call
[5] tool: "file written (2.3KB)"
... 30 more turns of file editing, testing, debugging ...
[38] assistant: <tool_call terminal: pytest </tool_call
[39] tool: "8 passed, 2 failed\n..." (5KB output)
[40] user: "Fix the failing tests"
[41] assistant: <tool_call read_file: tests/test_API.py </tool_call
[42] tool: "import pytest\n..." (3KB)
[43] assistant: "I see the issue with the test fixtures..."
[44] user: "Great, also add error handling"

`

### Sau khi nén (25 tin nhắn, ~45K token)

`
[0] system: "You are a helpful assistant...
[Note: Some earlier conversation turns have been compacted...]"
[1] user: "Help me set up a FastAPI project"
[2] assistant: "[CONTEXT COMPACTION] Earlier turns were compacted...

## Goal
Set up a FastAPI project with tests and error handling

## Progress
### Done
- Created project structure: main.py, tests/, requirements.txt
- Implemented 5 API endpoints in main.py
- Wrote 10 test cases in tests/test_API.py
- 8/10 tests passing

### In Progress
- Fixing 2 failing tests (test_create_user, test_delete_user)

## Relevant Files
- main.py — FastAPI app with 5 endpoints
- tests/test_API.py — 10 test cases
- requirements.txt — fastAPI, pytest, httpx

## Next Steps
- Fix failing test fixtures
- Add error handling"
[3] user: "Fix the failing tests"
[4] assistant: <tool_call read_file: tests/test_API.py </tool_call
[5] tool: "import pytest\n..."
[6] assistant: "I see the issue with the test fixtures..."
[7] user: "Great, also add error handling"

`

`
## Bộ nhớ đệm nhanh chóng (Anthropic)

Nguồn:
`agent/prompt_caching.py
``Giảm chi phí mã thông báo đầu vào khoảng ~75% cho các cuộc hội thoại nhiều lượt bằng cách lưu vào bộ nhớ đệm
tiền tố hội thoại. Sử dụng các điểm dừng
`cache_control
` của Anthropic.

### Chiến lược: system_and_3

Anthropic cho phép tối đa 4 điểm dừng
`cache_control
` cho mỗi yêu cầu. Hermes
sử dụng chiến lược "system_and_3":

`
Breakpoint 1: System prompt (stable across all turns)
Breakpoint 2: 3rd-to-last non-system message ─┐
Breakpoint 3: 2nd-to-last non-system message ├─ Rolling window
Breakpoint 4: Last non-system message ─┘

`

### Cách thức hoạt động``apply_Anthropic_cache_control()
` sao chép sâu các tin nhắn và đưa vào
Điểm đánh dấu
`cache_control

:

``` python

# Cache marker format
marker = \{"type": "ephemeral"}
# Or for 1-hour TTL:
marker = \{"type": "ephemeral", "ttl": "1h"}

`
``Điểm đánh dấu được áp dụng khác nhau dựa trên loại nội dung:

| Loại nội dung | Điểm đánh dấu đi đâu |
|-------------|-------------------|
| Nội dung chuỗi | Đã chuyển đổi sang

[\{"type": "text", "text": ..., "cache_control": ...}]
` |
| Liệt kê nội dung | Đã thêm vào lệnh của phần tử cuối cùng |
| Không có/trống | Đã thêm dưới dạng
`msg["cache_control"]
` |
| Thông báo công cụ | Đã thêm dưới dạng
`msg["cache_control"]
` (chỉ dành cho Anthropic bản địa) |

### Mẫu thiết kế nhận biết bộ đệm
1. **Lời nhắc hệ thống ổn định**: Lời nhắc hệ thống là điểm dừng 1 và được lưu trong bộ nhớ đệm
tất cả các lượt. Tránh thay đổi nó giữa cuộc trò chuyện (nén sẽ thêm ghi chú
chỉ trong lần đầm đầu tiên).
2. **Vấn đề về thứ tự tin nhắn**: Lượt truy cập bộ nhớ đệm yêu cầu phải khớp tiền tố. Thêm hoặc
xóa tin nhắn ở giữa sẽ làm mất hiệu lực bộ đệm cho mọi thứ sau đó.
3. **Tương tác bộ nhớ đệm nén**: Sau khi nén, bộ đệm không còn hiệu lực
cho vùng nén nhưng bộ đệm nhắc hệ thống vẫn tồn tại. Sự lăn
Cửa sổ 3 thông báo thiết lập lại bộ nhớ đệm trong vòng 1-2 lượt.
4. **Lựa chọn TTL**: Mặc định là
`5m
` (5 phút). Sử dụng
`1h
` để hoạt động lâu dài
các phiên mà người dùng nghỉ giải lao giữa các lượt.

### Kích hoạt bộ đệm nhanh

Bộ nhớ đệm nhắc nhở được kích hoạt tự động khi:
- Model là model Anthropic Claude (được phát hiện theo tên model)
- Nhà cung cấp hỗ trợ
`cache_control
` (API gốc Anthropic hoặc OpenRouter)

``` yaml

# config.yaml — TTL is configurable (must be "5m" or "1h")
prompt_caching:
cache_ttl: "5m"

`
``CLI hiển thị trạng thái bộ đệm khi khởi động:

`

💾 Prompt caching: ENABLED (Claude via OpenRouter, 5m TTL)

`

`
## Cảnh báo áp lực bối cảnh

Cảnh báo áp lực bối cảnh trung gian đã bị xóa (xem khối ngân sách lặp lại trong
`run_agent.py

, trong đó lưu ý: "Không có cảnh báo áp lực trung gian - chúng khiến các mô hình 'từ bỏ' sớm các nhiệm vụ phức tạp"). Tính năng nén sẽ kích hoạt khi mã thông báo nhắc nhở đạt đến
`compression.threshold
` đã định cấu hình (50% mặc định) mà không có bước cảnh báo trước; Vệ sinh phiên cổng hoạt động như mạng lưới an toàn thứ cấp ở 85% cửa sổ ngữ cảnh của mô hình.