源文件:chapter2/kv-cache/README.md 基于 ReAct Agent 的 KV Cache 演示 一个综合演示,借助一个带本地文件系统工具的 ReAct 模式 Agent,展示 KV(Key-Value)缓存在 LLM 中的重要性。本项目通过六种不同的实现模式——一种正确、五种错误——说明看似微小的改动如何让 KV Cache 失效,从而严重影响性能。 🎯 概览 本项目实现了一个 ReAct(Reasoning and Acting)Agent,使用当前的 Moonshot Kimi 模型(默认 )分析代码项目。
源文件:chapter2/kv-cache/README.md
一个综合演示,借助一个带本地文件系统工具的 ReAct 模式 Agent,展示 KV(Key-Value)缓存在 LLM 中的重要性。本项目通过六种不同的实现模式——一种正确、五种错误——说明看似微小的改动如何让 KV Cache 失效,从而严重影响性能。
本项目实现了一个 ReAct(Reasoning and Acting)Agent,使用当前的 Moonshot Kimi 模型(默认 kimi-k2.6)分析代码项目。Agent 采用标准的 OpenAI 工具调用格式,并演示了六种不同的实现模式——一种正确、五种错误——展示看似微小的改动如何让 KV Cache 失效并大幅拖累性能。
关于模型。 在 Moonshot 线上端点上,当前整个 Kimi 家族(
kimi-k2.5/kimi-k2.6/kimi-k2.7*/kimi-k3)都是推理模型:它们会输出reasoning_content,且只接受temperature=1(代码会自动处理这一点)。它们会上报cached_tokens,这正是本实验要测量的对象。与之相对,旧的非推理moonshot-v1-*chat 模型不上报cached_tokens,因此无法演示缓存效果。我们默认使用kimi-k2.6,因为它与同族其他模型一样会上报缓存命中,但推理开销最轻,能让 TTFT 的噪声最小。由于任何推理模型都会带来可变的思考延迟,缓存命中率 / 缓存比 这两列(具有确定性)才是这里最稳健的信号;请把 TTFT 视作次要指标。
KV Cache 存储的是 Transformer 模型注意力机制产生的键值对。当对话上下文保持稳定时,这些缓存值可以被复用,从而大幅减少计算量、改善响应延迟(尤其是首 token 延迟,即 Time to First Token,TTFT)。
read_file、find、grep 命令--report):无需 API Key,从已保存的结果文件渲染跨策略对比表--cache-price-ratio 配置)correct)在整个对话过程中保持上下文稳定:
dynamic_system)每次请求都在系统提示中加入时间戳:
shuffled_tools)每次请求都随机重排工具列表:
dynamic_profile)在上下文中加入不断变化的用户积分:
sliding_window)只保留最近 5 条消息:
text_format)把对话历史格式化成纯文本而非结构化消息:
要让错误模式下的 KV Cache 真正失效,必须在每次迭代的开始就把整个消息上下文从零重建。
实现上通过以下方式保证这一点:
CORRECT 模式:
错误模式:
重要:两种模式在单次迭代内部都会追加工具结果,以保证 API 看到完整的对话流。关键区别在于错误模式会在每次新迭代开始时丢弃消息列表并重建,从而强制让缓存失效。
# Navigate to the project directory cd chapter2/kv-cache # Install dependencies pip install -r requirements.txt # Set your Kimi API key export MOONSHOT_API_KEY="your-api-key-here"
通用回退(OpenRouter):未设置
MOONSHOT_API_KEY/KIMI_API_KEY时,只要
配置了OPENROUTER_API_KEY,实验会自动改走 OpenRouter(kimi-*会映射为moonshotai/kimi-k2)。设置了 Moonshot key 时行为完全不变。
# Run interactive mode selection menu python main.py # You'll see a menu like: # ============================================================ # KV CACHE DEMONSTRATION - MODE SELECTION # ============================================================ # # Select a mode to run: # # 1. ✅ Correct Implementation - Optimal KV cache usage # 2. ❌ Dynamic System Prompt - Adds timestamps # 3. ❌ Shuffled Tools - Randomizes tool order # 4. ❌ Dynamic Profile - Updates user credits # 5. ❌ Sliding Window - Keeps only recent messages # 6. ❌ Text Format - Plain text instead of structured # 7. 📊 Compare All - Run all modes and compare # # 0. Exit
CLI 自带中文 --help;运行 python main.py --help 查看完整列表。关键参数:
| Flag | 说明 |
|---|---|
--mode MODE |
运行单个策略(correct / dynamic_system / shuffled_tools / dynamic_profile / sliding_window / text_format) |
--compare |
依次运行全部策略并打印横向对比表(需要 API Key) |
--report |
离线:从已保存的 result_*.json / comparison_*.json 生成对比表,无需 API Key |
--input ... |
配合 --report 指定结果文件 / 通配符 / 目录(默认扫描当前目录) |
--model MODEL |
选择模型(默认 kimi-k2.6;同族 kimi-k2.5 / kimi-k3 亦可,均会上报 cached_tokens) |
--output PATH |
指定结果 JSON 的输出路径(默认按模式 + 时间戳自动命名) |
--cache-price-ratio R |
成本估算中缓存 token 相对正常 token 的计费比例(默认 0.1,即一折),仅作示意 |
--task, --root-dir |
自定义任务 / 文件工具根目录 |
# Run specific mode directly (bypasses menu) python main.py --mode correct # Pick a model and write to a named file python main.py --mode sliding_window --model kimi-k2.6 --output run.json # Run comparison across all modes (needs API key) python main.py --compare # Disable interactive mode python main.py --no-interactive --mode correct
实时运行需要 Moonshot/Kimi API Key。要读取已保存的结果文件并用一条命令打印跨策略对比表:
# Uses the result_*.json files already in this directory python main.py --report # Or point at specific files / a directory, and change the assumed cache discount python main.py --report --input result_correct_*.json result_text_format_*.json python main.py --report --cache-price-ratio 0.5
该表格跨策略对比缓存命中率、缓存比、TTFT 延迟、总时长,以及示意性的计费 token / 节省比例估算。报告既能解析旧的单模式文件(指标以 AgentMetrics(...) 字符串形式存储),也能解析较新的 dict 格式文件,因此既有的结果依然可用。
Bill.Tok/Save%两列是实测 token 数与你提供的--cache-price-ratio的透明函数——
它们是对成本影响的示意,并非某个具体服务商的报价。
# Provide custom task via command line python main.py --mode correct --task "Read all README files and summarize their contents" # Use different root directory python main.py --mode correct --root-dir ../.. --task "Analyze the project structure"
对比各实现时,你应观察到:
正确实现:
错误实现:
text_format 高达正确运行的约 2.4 倍)在推理模型上(当前整个 Kimi 家族都会推理)TTFT 还带有隐藏思考 token 带来的额外
方差,因此缓存比一列是该效应最干净的证据。另请注意,在原本稳定的前缀末尾追加
动态数据(如dynamic_system/dynamic_profile所做的那样)只会让缓存从该点起失效
——它之前的基础前缀仍然能缓存——因此它们的总览缓存比可能看起来接近correct,而
总时长仍然退化。教训是:让动态数据完全离开前缀。
📊 Performance Metrics: • Time to First Token (TTFT): 0.823 seconds • TTFT per iteration: Iteration 1: 0.823s Iteration 2: 0.234s (with cache) Iteration 3: 0.198s (with cache) Iteration 4: 0.187s (with cache) Iteration 5: 0.192s (with cache) • TTFT Analysis: First iteration: 0.823s Last iteration: 0.192s Average (after first): 0.203s Improvement: 76.7%
--report 读取本目录下已保存的结果文件)以下是单次 --compare 运行的真实实测数字——六种策略在同一个任务下(kimi-k2.6,根目录 = 当前文件夹,任务 = "找出所有 Python 文件、读 main.py + agent.py、用 3 句话总结"),随后用 python main.py --report 读回:
Mode Iters 1st TTFT Avg TTFT Total(s) Prompt Cached Hit% Cache% Bill.Tok Save% ---------------------------------------------------------------------------------------------------------------- correct 3 2.328 6.054 18.163 7,567 768 100.0 10.1 6,876 9.1 dynamic_profile 3 2.206 5.986 17.962 7,652 768 100.0 10.0 6,961 9.0 dynamic_system 3 2.497 8.085 24.260 7,639 768 100.0 10.1 6,948 9.0 shuffled_tools 3 7.818 11.122 33.369 7,568 256 100.0 3.4 7,338 3.0 sliding_window 5 2.234 3.649 14.704 2,224 1,510 100.0 67.9 865 61.1 text_format 3 6.189 14.432 43.297 7,430 674 100.0 9.1 6,823 8.2
读表:shuffled_tools 重排的是位于前缀前部的工具定义,因此它的缓存比从 10.1% 崩溃到 3.4%,首 token 延迟也从约 2.3s 飙升到约 7.8s。text_format 每轮都把历史重建成一大块纯文本,总时长约为正确运行的 2.4 倍。sliding_window 之所以缓存比高,只是因为截断让 prompt 本身变小了(token 更少且大多是已缓存的)——这提醒我们:在小 prompt 上拿到的高比例并不等于一次高效的运行。
Cache% 是 prompt token 中由缓存提供的比例;Hit% 是看到任意缓存的迭代比例。Bill.Tok/Save% 假设缓存 token 按正常 token 的 --cache-price-ratio(默认 0.1)计费——属示意,非服务商报价。六行全部来自一次 --compare 运行,因此可直接横向对比;用 python main.py --compare 可重新生成以复现。
kv-cache/ ├── agent.py # ReAct agent implementation with different modes ├── main.py # Main script for running experiments ├── demo_quick.py # Quick demonstration script ├── test_tools.py # Test local file system tools ├── test_error_handling.py # Test error recovery capabilities ├── test_completion.py # Test final answer detection ├── requirements.txt # Project dependencies ├── README.md # This file └── *.log # Generated log files
Agent 实现了稳健的错误处理:
# API Configuration export MOONSHOT_API_KEY="your-key" # Logging Level export LOG_LEVEL="DEBUG" # INFO, WARNING, ERROR
你可以扩展 agent.py 中的 KVCacheMode 枚举来新增模式:
class KVCacheMode(Enum): CUSTOM = "custom" # Your new mode
然后在对应方法中实现其行为:
_get_system_prompt()_get_tools()_format_messages()基于本演示,请遵循以下实践:
kimi-k2.5 / kimi-k2.6 / kimi-k3)——它们会上报 cached_tokens。非推理的 moonshot-v1-* 模型不上报缓存 token,因此即便服务端实际命中,这一指标也会读到 0。本项目是 AI Agent Book 教学材料的一部分。