目录

AgentMem:面向长生命周期智能体推理的分层 KV Cache 服务系统

AgentMem 面向代码智能体、工具调用智能体和多轮检索增强生成等长生命周期负载,围绕 KV Cache 的跨轮复用、分层存储、及时预取与 Prefill 调度构建完整推理服务。系统基于 vLLM 运行时扩展,可在昇腾 NPU 上以 Prefill–Decode 分离拓扑运行,并提供固定执行轨迹的多轮负载客户端与可复现实验工具。

1. 项目简介

长生命周期智能体会在一次任务中反复执行“模型推理—工具调用—环境反馈”。随着轮次推进,上下文持续增长;工具调用又会在相邻模型请求之间形成可利用的窗口期。传统在线推理系统通常把每一轮当作独立请求,已生成的 KV Cache 可能被重复计算、过早释放,或在请求到达后才从低速层恢复,并在高负载下形成持续排队。

AgentMem 将任务生命周期、KV Cache 生命周期和 Serving 调度统一起来:在 NPU/GPU、CPU 与 SSD 之间管理跨轮 KV 状态,以内容身份和引用计数支持单副本共享;由 Sidecar 影子调度器判断请求能否在下一步被准入,并在窗口期内提前完成所需 KV 的恢复;Prefill 侧通过 Future-Feasible Admission、长短请求协同和 Dynamic Chunk 控制排队及干扰。系统同时提供固定执行轨迹的评测入口,使不同模型、方案和运行轮次之间的时延与资源指标具有可比性。

2. 应用场景

  • 代码智能体与软件工程智能体:任务包含代码搜索、文件修改、测试执行等多轮工具调用,上下文长且轮间存在等待窗口。
  • 多轮工具调用与 RAG:同一任务反复携带历史上下文,适合跨轮复用 KV Cache,并利用检索或工具执行时间提前恢复缓存。
  • 长上下文混合服务:长、短请求同时到达时,需要限制大 Prefill 对后续请求的阻塞,并避免局部停顿传播为持续积压。
  • 国产异构加速平台:在昇腾 NPU 上完成分层存储、跨设备 KV 迁移、动态形状 Attention 与 PD 分离适配。

3. 系统架构与主要功能

AgentMem 系统架构

  1. 分层 KV Cache 管理:以 NPU/GPU HBM、CPU 内存和 SSD 组成三级存储,支持冷热识别、下沉分离、按需加载、后台迁移和跨轮持久化。
  2. 高效跨层迁移与及时预取:采用分层流水、融合 Scatter/Gather、固定内存 Arena 等机制降低碎片化拷贝开销;Sidecar 根据下一步准入结果,在工具调用窗口内提前搬运 KV Cache,无需预测工具执行时长。
  3. 跨请求、跨轮次前缀复用:以内容哈希构建隐式状态树,通过 Copy-on-Write、引用计数和任务无关身份实现单副本共享。其管理方式类似操作系统的打开文件表:共享对象只保留一份,由引用计数记录活跃使用者,在引用归零后回收。
  4. 异构 Prefill 请求的动态调度与未来可行准入:通过长短请求协同、Dynamic Chunk 和 Future-Feasible Admission 控制 Prefill 干扰,并在准入时考虑下一步容量,避免先接纳后驱逐。
  5. 固定执行轨迹的智能体推理评测:Trajectory Replay 通过 Teacher-Forcing 固定工具调用与状态演化,客户端按原始轮间时序重放多轮轨迹,用于可重复的系统性能比较。
  6. 昇腾 NPU 系统适配:适配动态长度 Attention、CPU–NPU 分层传输、HCCL PD 分离迁移流水线和 NPU 融合算子。

4. 仓库结构

AgentMem/
├── README.md                         # 项目入口与复现说明
├── src/                              # 主运行时、实验工具和第三方插件
│   ├── vllm/                         # AgentMem 主运行时实现
│   ├── third_party/vllm-ascend/      # 配套昇腾设备插件
│   ├── examples/                     # 原始服务端实现与示例
│   ├── agentmem_exp/                 # 多轮客户端、数据处理与分析工具
│   ├── tools/                        # 安装及开发工具
│   ├── trace_data/                   # 实验轨迹与负载文件
│   └── DEPLOYMENT_ASCEND_ZH.md       # 昇腾部署细节
├── demo/
│   ├── start_server.sh               # 稳定服务端入口
│   └── run_client.sh                 # 稳定客户端入口
├── tests/                             # 单元测试与机制测试
├── docs/                              # 决赛文档及 README 图片
├── presentation/                      # 演示材料
└── 作品原创承诺书.pdf

demo/ 下两个脚本是重构后的稳定入口,负责转发全部命令行参数;底层实现仍位于 src/,便于开发、调试和复现实验。

5. 系统环境与依赖要求

5.1 已验证环境

类别 已验证配置
操作系统 openEuler 22.03 LTS-SP4,aarch64
加速设备 4 × Ascend 910B3,单卡 64 GiB HBM
Python 3.10.16
CANN 8.2.RC1
PyTorch 2.7.1
torch-npu 2.7.1.dev20250724
vLLM-Ascend 随仓库提供的修改版 0.10.2rc1
模型精度 BF16

5.2 资源与软件依赖

  • 需要可用的 Ascend Driver、Firmware、CANN Toolkit、PyTorch 与 torch-npu;版本应与上表匹配。
  • 生产默认配置使用 1 个 Prefill Worker 和 3 个 Decode Worker,至少需要 4 张可见 NPU。
  • 分层缓存默认使用 /dev/shm/licht_round_kv 和 /remote-home/licht_ssd。运行前应确保共享内存与 SSD 空间充足,或通过启动参数指定其他路径和容量。
  • Python 依赖见 src/requirements/common.txt 与两个源码包的 pyproject.toml。主运行时和配套 vLLM-Ascend 必须同时从本仓库以 editable 方式安装,避免被同名官方 wheel 覆盖。

6. 构建与安装

6.1 加载 Ascend 环境

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh

不同镜像中的 CANN 路径可能不同,请以实际安装位置为准。

6.2 安装 Python 依赖与本地扩展

cd /root/work/AgentMem/src
python -m pip install -r requirements/common.txt
SOC_VERSION=Ascend910B3 bash tools/install_agentmem_ascend.sh

安装脚本使用 --no-deps 安装主运行时、配套 vLLM-Ascend 和 AgentMem 自定义扩展,避免自动替换已匹配的 torch/torch-npu。若环境尚未准备基础依赖,应先按依赖文件安装;不要使用无约束的 pip install -U 升级 Ascend 软件栈。

6.3 安装后核验

cd /root/work/AgentMem/src
python - <<'PY'
import vllm
import vllm_ascend
import licht_arena_atomic
import licht_fused_scatter_npu
print("vllm:", vllm.__file__)
print("vllm_ascend:", vllm_ascend.__file__)
print("arena:", licht_arena_atomic.__file__)
print("npu scatter:", licht_fused_scatter_npu.__file__)
PY

vllm 应位于 /root/work/AgentMem/src/,vllm_ascend 应位于 /root/work/AgentMem/src/third_party/vllm-ascend/。

7. 运行方法

7.1 启动服务端

cd /root/work/AgentMem
bash demo/start_server.sh --help

默认生产配置使用 NPU 7 作为 Prefill、NPU 4/5/6 作为 Decode,API 端口为 10234,模型路径为底层脚本中的默认 Llama-3.1-8B-Instruct。建议显式传入部署参数:

bash demo/start_server.sh \
  --model-path /path/to/Llama-3.1-8B-Instruct \
  --prefill-gpus 7 \
  --decode-gpus 4,5,6 \
  --licht-v3 \
  --prefill-opt \
  --shadow-tiering-experiment

如需调整分层存储,可使用 --round-kv-reuse-path、--round-kv-arena-gb、--ssd-path、--ssd-gb 和 --ssd-stage-mb 等参数。所有参数由 demo/start_server.sh 原样转发给底层生产脚本。

服务就绪后可检查:

curl -s http://127.0.0.1:10234/v1/models

7.2 启动多轮客户端

另开终端执行:

cd /root/work/AgentMem
bash demo/run_client.sh --help

# 最小冒烟测试
bash demo/run_client.sh \
  --base-url http://127.0.0.1:10234/v1 \
  --max-trajectories 2

完整实验可通过 --trace-path 指定轨迹文件,通过 --dispatch-mode 和 --jps 设置发送方式及每轮请求到达速率,通过 --output-dir 指定结果目录。客户端默认开启固定轨迹回放;可用 --no-trace-replay 关闭。

8. 测试方法

项目测试与验证材料的统一索引位于 tests/README.md。其中 tests/agentmem/ 提供面向评审的检查和实验入口;这些入口直接调用 src/agentmem_exp/ 与 src/dynamic_chunk/ 中的正式实现,避免维护重复副本。以下各节同时给出对应的底层命令,便于检查具体参数和输出位置。

8.1 无硬件检查

cd /root/work/AgentMem
bash tests/agentmem/check_repository.sh

# 等价的分项检查
bash -n demo/start_server.sh demo/run_client.sh
python3 -m py_compile src/agentmem_exp/multiturn_trace_client.py

python3 - <<'PY'
from pathlib import Path
required = [
    Path("src/pyproject.toml"),
    Path("src/third_party/vllm-ascend/pyproject.toml"),
    Path("src/examples/online_serving/disaggregated_serving_p2p_nccl_xpyd/run_disagg_p2p_nccl_xpyd_prod.sh"),
    Path("src/agentmem_exp/multiturn_trace_client.py"),
]
assert all(path.is_file() for path in required), required
print("repository layout: OK")
PY

8.2 核心机制单元测试

cd /root/work/AgentMem
bash tests/agentmem/run_core_tests.sh

# 等价的底层命令
pytest -q \
  tests/v1/core/test_licht_v3_shadow.py \
  tests/v1/core/test_licht_v3_promote_control.py \
  tests/v1/core/test_long_reservation.py

当前仓库在已验证环境中上述测试共 51 项通过。硬件相关的编译、HCCL 迁移和端到端服务测试必须在匹配的昇腾环境执行。

8.3 端到端冒烟测试

  1. 启动服务端并等待所有 Prefill/Decode Worker 注册完成。
  2. 使用 curl /v1/models 验证代理端口可访问。
  3. 运行两条轨迹的客户端命令。
  4. 检查客户端结果、代理日志和各 Worker 日志中是否存在请求失败、OOM、HCCL 超时或 KV 恢复错误。

8.4 时间戳落盘、结果归档与绘图

服务运行期间,每个实例分别把 scheduler_timestamps 和 monitoring_timestamps 写入:

src/examples/online_serving/disaggregated_serving_p2p_nccl_xpyd/agentmem_exp/
├── prefill_20003/
│   ├── scheduler_timestamps
│   └── monitoring_timestamps
├── decode_20005/
├── decode_20007/
└── decode_20009/

客户端完成后,在服务端终端按一次 Ctrl+C。启动脚本会依次停止 Proxy、Sidecar 和 Worker,并等待各实例将临时文件原子重命名为最终的 monitoring_timestamps;终端出现时间戳完成信息并退出后,才可开始分析。下次启动服务会清空上述实时目录,因此每组实验结束后必须先归档。

下面以唯一的 RUN_TAG 保存一组服务实验。整系统实验和统一 1P3D 实验都使用同一流程:

cd /root/work/AgentMem

RUN_TAG=example_run
RUNTIME_DIR=/root/work/AgentMem/src/examples/online_serving/disaggregated_serving_p2p_nccl_xpyd
RESULT_DIR=/root/work/AgentMem/src/output/${RUN_TAG}

mkdir -p "${RESULT_DIR}/raw/logs"
cp -a "${RUNTIME_DIR}/agentmem_exp" "${RESULT_DIR}/raw/"
cp "${RUNTIME_DIR}"/proxy_prod.log \
   "${RUNTIME_DIR}"/prefill_prod_*.log \
   "${RUNTIME_DIR}"/decode_prod_*.log \
   "${RUNTIME_DIR}"/shadow_sidecar_*.log \
   "${RESULT_DIR}/raw/logs/" 2>/dev/null || true

python3 src/agentmem_exp/analyze.py \
  --input-dir "${RESULT_DIR}/raw/agentmem_exp" \
  --all-instances \
  --client-output "${RESULT_DIR}/multiturn_trace_client.json" \
  --service-log-dir "${RESULT_DIR}/raw/logs" \
  --output-dir "${RESULT_DIR}/analysis"

python3 src/agentmem_exp/visualize_results.py \
  --input-dir "${RESULT_DIR}/analysis" \
  --all-instances \
  --output-dir "${RESULT_DIR}/figures"

归档后主要结果为:

  • ${RESULT_DIR}/multiturn_trace_client.json:客户端轨迹、完成情况和逐轮时延;
  • ${RESULT_DIR}/raw/agentmem_exp/:各 Prefill/Decode 实例的原始时间戳及 Sidecar 记录;
  • ${RESULT_DIR}/analysis/*/results.json:按实例整理后的统计结果;
  • ${RESULT_DIR}/figures/*/index.html:图表汇总页面及对应 PNG。

9. 实验结果

以下三组实验的目的不同:整系统实验比较可部署方案的综合表现;Prefill-only 实验隔离调度机制;统一 1P3D 实验在相同拓扑下逐项消融调度与预取机制。完整配置、统计口径和结果见 docs/项目说明书.pdf。

9.1 整系统部署实验

在 4 张 Ascend 910B3、2000 条轨迹、每轮 5 RPS 的负载下,比较原生 vLLM-Ascend 四 NPU PD 不分离部署与 AgentMem 1P3D 部署:

先分别启动两个待测系统。每次只运行一个配置,并为其设置独立的 RUN_TAG。原生 vLLM-Ascend 四 NPU PD 不分离配置:

cd /root/work/AgentMem
MODEL=/root/work/huggingface/models--meta-llama--Llama-3.1-8B-Instruct
RUN_TAG=whole_llama_vllm_ascend

bash demo/start_server.sh \
  --model-path "${MODEL}" \
  --prefill-gpus 7 \
  --decode-gpus 4,5,6 \
  --ascend-baseline \
  --client-pid-file "/root/work/AgentMem/src/output/${RUN_TAG}/client.pid"

AgentMem 1P3D 配置:

cd /root/work/AgentMem
MODEL=/root/work/huggingface/models--meta-llama--Llama-3.1-8B-Instruct
RUN_TAG=whole_llama_agentmem

bash demo/start_server.sh \
  --model-path "${MODEL}" \
  --prefill-gpus 7 \
  --decode-gpus 4,5,6 \
  --licht-v3 \
  --prefill-opt \
  --shadow-tiering-experiment \
  --client-pid-file "/root/work/AgentMem/src/output/${RUN_TAG}/client.pid"

服务就绪后,在另一终端使用与服务端一致的 MODEL 和 RUN_TAG 发送 2000 条轨迹:

cd /root/work/AgentMem
MODEL=/root/work/huggingface/models--meta-llama--Llama-3.1-8B-Instruct
RUN_TAG=whole_llama_agentmem   # 基线运行时改为 whole_llama_vllm_ascend

bash demo/run_client.sh \
  --model-name "${MODEL}" \
  --max-trajectories 2000 \
  --dispatch-mode poisson \
  --jps 5 \
  --dataset-jps longbench=1,lmsys=1,wildchat=1,mtrag=1,swe=1 \
  --shuffle-seed 1234 \
  --output-dir "output/${RUN_TAG}" \
  --pid-file "output/${RUN_TAG}/client.pid"

Qwen3-4B 使用相同命令,仅替换服务端和客户端的 MODEL,并使用新的 RUN_TAG。客户端结束后按 8.4 节归档时间戳、汇总数据并绘图。

模型 指标 vLLM-Ascend AgentMem
Qwen3-4B 任务完成率 97.70% 100%
Qwen3-4B 请求吞吐率 1.213 req/s 2.075 req/s
Llama-3.1-8B 任务完成率 98.15% 100%
Llama-3.1-8B 请求吞吐率 1.073 req/s 2.208 req/s
Llama-3.1-8B E2E P99 492.56 s 138.29 s
Llama-3.1-8B ITL P99 1.356 s 0.103 s

拓扑差异会使 Llama 的 TTFT P50 从 11.03 s 上升到 24.84 s,但 TTFT P95/P99 分别从 184.85/371.79 s 降至 71.84/110.16 s;E2E 与 ITL 各分位数也明显下降。

任务完成情况

吞吐率对比

9.2 Prefill-only 调度消融

在单 Prefill Worker 上构造 5120 个请求,其中短请求 4501 个、长请求 619 个,并在 2.5、5 和 10 RPS 下比较 FCFS-NoChunk、AgentMem-NoChunk 与 AgentMem-DynChunk。5 RPS 时,平均 TTFT 由 82.18 s 降至 9.37 s;10 RPS 时由 341.26 s 降至 54.43 s。Future-Feasible Admission 在三个负载下均保持零驱逐,而仅检查当前容量的策略在 5/10 RPS 下分别发生 16/207 次驱逐。

该实验不启动多进程在线服务,而是由 dynamic_chunk/vllm_bench.py 在单张 NPU 上直接构造 C/L 请求并运行 Prefill-only 推理。dynamic_chunk/workloads.json 的 5120 组即包含上述 4501 个短请求和 619 个长请求。三组配置可顺序运行:

cd /root/work/AgentMem
bash tests/agentmem/run_prefill_only.sh all

对应的底层命令如下:

cd /root/work/AgentMem/src
RESULT_ROOT=/root/work/AgentMem/src/output/prefill_only
mkdir -p "${RESULT_ROOT}"

# FCFS-NoChunk
LICHT_OUT_TAG=fcfs_nochunk \
LICHT_BENCH_RESULT_DIR="${RESULT_ROOT}/fcfs_nochunk" \
python3 dynamic_chunk/vllm_bench.py \
  nochunk 5120 fcfs 7 2.5,5,10

# AgentMem-NoChunk:保留长短请求调度和未来可行准入,关闭 Dynamic Chunk
LICHT_OUT_TAG=agentmem_nochunk \
LICHT_BENCH_RESULT_DIR="${RESULT_ROOT}/agentmem_nochunk" \
python3 dynamic_chunk/vllm_bench.py \
  longcap_nochunk 5120 longcap_fcfs 7 2.5,5,10

# AgentMem-DynChunk:完整 Prefill 调度
LICHT_OUT_TAG=agentmem_dynchunk \
LICHT_BENCH_RESULT_DIR="${RESULT_ROOT}/agentmem_dynchunk" \
python3 dynamic_chunk/vllm_bench.py \
  dynamic_chunk 5120 longcap_fcfs 7 2.5,5,10

脚本会在每个 RPS 完成后增量写入 RESULT_ROOT 下对应配置的 JSON,即使后续负载被中断,已经完成的结果也不会丢失;调度器原始时间戳保存在 src/dynamic_chunk/runs/<LICHT_OUT_TAG>_gpu7/。

Prefill-only 调度消融

9.3 统一 1P3D 端到端消融

该实验使用 Llama-3.1-8B 和 10000 条多轮轨迹,五类数据源的轮次数尽量对齐,并分别以 1 RPS 到达。在相同 1P3D 拓扑下,完整 AgentMem 将 Mean TTFT 从 FCFS-NoChunk 的 186.88 s 降至 12.21 s,将 P99 TTFT 从 444.88 s 降至 130.71 s;Queue AUC 从 4.000M request·s 降至 0.171M request·s。

四个配置使用相同模型、NPU 拓扑和客户端参数,仅替换服务端机制开关:

配置 服务端附加参数
FCFS-NoChunk --licht-v3 --prefill-fcfs --no-chunk
AgentMem-NoChunk --licht-v3 --prefill-opt --no-chunk
AgentMem-DynChunk --licht-v3 --prefill-opt
AgentMem-Prefetch --licht-v3 --prefill-opt --shadow-tiering-experiment

以下以完整配置为例;运行其他配置时替换 RUN_TAG 和表中的服务端附加参数:

cd /root/work/AgentMem
MODEL=/root/work/huggingface/models--meta-llama--Llama-3.1-8B-Instruct
RUN_TAG=e2e_agentmem_prefetch

bash demo/start_server.sh \
  --model-path "${MODEL}" \
  --prefill-gpus 7 \
  --decode-gpus 4,5,6 \
  --licht-v3 \
  --prefill-opt \
  --shadow-tiering-experiment \
  --client-pid-file "/root/work/AgentMem/src/output/${RUN_TAG}/client.pid"

客户端为五类数据集分别建立 1 RPS 的泊松时钟,并优先选择轮次数较多的初始轨迹,使各数据源实际发送的轮次数尽量接近:

cd /root/work/AgentMem
MODEL=/root/work/huggingface/models--meta-llama--Llama-3.1-8B-Instruct
RUN_TAG=e2e_agentmem_prefetch

bash demo/run_client.sh \
  --model-name "${MODEL}" \
  --max-trajectories 10000 \
  --dispatch-mode poisson \
  --jps 5 \
  --dataset-jps longbench=1,lmsys=1,wildchat=1,mtrag=1,swe=1 \
  --weighted-initial \
  --shuffle-seed 1234 \
  --output-dir "output/${RUN_TAG}" \
  --pid-file "output/${RUN_TAG}/client.pid"

每个配置运行结束后先按 8.4 节归档和分析,再启动下一个配置。Eager 与 Lookup 预取对比可在相同的 --licht-v3 --prefill-opt 配置上分别增加 --prefetch-timing eager 或 --prefetch-timing lookup。

统一 1P3D 端到端消融

准入引导预取的覆盖率为 82.90%、存活率为 100%,明显高于 Eager 的 1.04%/93.56% 和 Lookup 的 1.49%/98.90%。完整方案将前台 SSD 恢复比例从 44.43% 降至 8.41%,KV 准备平均时延从 127.05 ms 降至 23.82 ms。

预取机制消融

10. 已知限制

  • 当前发布版本主要在上述 openEuler、CANN、torch-npu 和 Ascend 910B3 组合上验证;更换驱动、CANN、PyTorch、设备型号或 vLLM-Ascend 版本后,需要重新编译自定义扩展并执行回归测试。
  • 默认生产拓扑是单机 1P3D;跨主机部署、弹性扩缩容和故障自动恢复尚未形成统一入口。
  • 分层缓存依赖较大的共享内存与 SSD 空间,首次启动还需完成 Arena 初始化、固定内存注册和部分算子编译,启动时间较长。容量不足时应先缩小 --round-kv-arena-gb、--ssd-gb 或 --ssd-stage-mb。
  • 模型权重未随仓库分发,使用者需自行准备与许可证相符的模型目录。
  • 整系统实验用于比较两种可部署方案,拓扑并不相同;具体调度和预取机制的增量贡献应以 Prefill-only 与统一 1P3D 消融为准。
  • 固定轨迹回放用于保证系统性能测量的可重复性,不替代智能体任务正确率或模型能力评测。

11. 文档与许可证

本仓库中的主运行时扩展与第三方组件分别遵循对应目录中的许可证和第三方声明。

关于
293.6 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号