lmcache-cli 0.4.5.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) hide show
  1. lmcache/__init__.py +84 -0
  2. lmcache/_version.py +24 -0
  3. lmcache/cli/__init__.py +1 -0
  4. lmcache/cli/commands/__init__.py +34 -0
  5. lmcache/cli/commands/base.py +157 -0
  6. lmcache/cli/commands/bench/__init__.py +557 -0
  7. lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
  8. lmcache/cli/commands/bench/engine_bench/config.py +245 -0
  9. lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
  10. lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
  11. lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
  12. lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
  13. lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
  14. lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
  15. lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
  16. lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
  17. lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
  18. lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
  19. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
  20. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
  21. lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
  22. lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
  23. lmcache/cli/commands/describe.py +310 -0
  24. lmcache/cli/commands/kvcache.py +133 -0
  25. lmcache/cli/commands/mock.py +75 -0
  26. lmcache/cli/commands/ping.py +113 -0
  27. lmcache/cli/commands/query/__init__.py +155 -0
  28. lmcache/cli/commands/query/prompt.py +134 -0
  29. lmcache/cli/commands/query/request.py +357 -0
  30. lmcache/cli/commands/server.py +99 -0
  31. lmcache/cli/commands/tool/__init__.py +63 -0
  32. lmcache/cli/commands/tool/cache_simulator.py +113 -0
  33. lmcache/cli/commands/trace/__init__.py +505 -0
  34. lmcache/cli/commands/trace/dispatch.py +249 -0
  35. lmcache/cli/commands/trace/driver.py +372 -0
  36. lmcache/cli/commands/trace/stats.py +289 -0
  37. lmcache/cli/documents/lmcache.txt +11 -0
  38. lmcache/cli/main.py +42 -0
  39. lmcache/cli/metrics/__init__.py +29 -0
  40. lmcache/cli/metrics/formatter.py +171 -0
  41. lmcache/cli/metrics/handler.py +94 -0
  42. lmcache/cli/metrics/metrics.py +161 -0
  43. lmcache/cli/metrics/section.py +77 -0
  44. lmcache/connections.py +173 -0
  45. lmcache/integration/__init__.py +2 -0
  46. lmcache/integration/base_service_factory.py +165 -0
  47. lmcache/integration/request_telemetry/__init__.py +1 -0
  48. lmcache/integration/request_telemetry/base.py +51 -0
  49. lmcache/integration/request_telemetry/factory.py +113 -0
  50. lmcache/integration/request_telemetry/fastapi.py +109 -0
  51. lmcache/integration/request_telemetry/noop.py +35 -0
  52. lmcache/integration/sglang/__init__.py +2 -0
  53. lmcache/integration/sglang/sglang_adapter.py +326 -0
  54. lmcache/integration/sglang/utils.py +39 -0
  55. lmcache/integration/vllm/__init__.py +1 -0
  56. lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
  57. lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
  58. lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
  59. lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
  60. lmcache/integration/vllm/utils.py +433 -0
  61. lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
  62. lmcache/integration/vllm/vllm_service_factory.py +339 -0
  63. lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
  64. lmcache/logging.py +107 -0
  65. lmcache/native_storage_ops.pyi +230 -0
  66. lmcache/non_cuda_equivalents.py +1424 -0
  67. lmcache/observability.py +1958 -0
  68. lmcache/storage_backend/serde/__init__.py +1 -0
  69. lmcache/storage_backend/serde/cachegen_basics.py +210 -0
  70. lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
  71. lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
  72. lmcache/storage_backend/serde/serde.py +75 -0
  73. lmcache/tools/__init__.py +1 -0
  74. lmcache/tools/cache_simulator/README.md +392 -0
  75. lmcache/tools/cache_simulator/__init__.py +1 -0
  76. lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
  77. lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
  78. lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
  79. lmcache/tools/cache_simulator/lru_cache.py +124 -0
  80. lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
  81. lmcache/tools/cache_simulator/simulator.py +795 -0
  82. lmcache/tools/controller_benchmark/README.md +161 -0
  83. lmcache/tools/controller_benchmark/__init__.py +1 -0
  84. lmcache/tools/controller_benchmark/__main__.py +331 -0
  85. lmcache/tools/controller_benchmark/benchmark.py +660 -0
  86. lmcache/tools/controller_benchmark/config.py +44 -0
  87. lmcache/tools/controller_benchmark/constants.py +10 -0
  88. lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
  89. lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
  90. lmcache/tools/controller_benchmark/handlers/base.py +47 -0
  91. lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
  92. lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
  93. lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
  94. lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
  95. lmcache/tools/controller_benchmark/handlers/register.py +56 -0
  96. lmcache/tools/mp_status_viewer/__init__.py +1 -0
  97. lmcache/tools/mp_status_viewer/__main__.py +95 -0
  98. lmcache/usage_context.py +417 -0
  99. lmcache/utils.py +665 -0
  100. lmcache/v1/__init__.py +2 -0
  101. lmcache/v1/api_server/__init__.py +2 -0
  102. lmcache/v1/api_server/__main__.py +537 -0
  103. lmcache/v1/basic_check.py +112 -0
  104. lmcache/v1/cache_controller/__init__.py +9 -0
  105. lmcache/v1/cache_controller/commands/__init__.py +15 -0
  106. lmcache/v1/cache_controller/commands/base.py +35 -0
  107. lmcache/v1/cache_controller/commands/full_sync.py +49 -0
  108. lmcache/v1/cache_controller/config.py +176 -0
  109. lmcache/v1/cache_controller/controller_manager.py +535 -0
  110. lmcache/v1/cache_controller/controllers/__init__.py +11 -0
  111. lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
  112. lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
  113. lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
  114. lmcache/v1/cache_controller/executor.py +463 -0
  115. lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
  116. lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
  117. lmcache/v1/cache_controller/frontend/static/index.html +234 -0
  118. lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
  119. lmcache/v1/cache_controller/full_sync_sender.py +475 -0
  120. lmcache/v1/cache_controller/locks.py +149 -0
  121. lmcache/v1/cache_controller/message.py +828 -0
  122. lmcache/v1/cache_controller/observability.py +208 -0
  123. lmcache/v1/cache_controller/utils.py +679 -0
  124. lmcache/v1/cache_controller/worker.py +665 -0
  125. lmcache/v1/cache_engine.py +2058 -0
  126. lmcache/v1/cache_interface.py +19 -0
  127. lmcache/v1/check/__init__.py +74 -0
  128. lmcache/v1/check/check_mode_gen.py +86 -0
  129. lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
  130. lmcache/v1/check/check_mode_test_remote.py +155 -0
  131. lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
  132. lmcache/v1/check/utils.py +571 -0
  133. lmcache/v1/compute/__init__.py +2 -0
  134. lmcache/v1/compute/attention/__init__.py +0 -0
  135. lmcache/v1/compute/attention/abstract.py +39 -0
  136. lmcache/v1/compute/attention/flash_attn.py +129 -0
  137. lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
  138. lmcache/v1/compute/attention/metadata.py +85 -0
  139. lmcache/v1/compute/attention/utils.py +14 -0
  140. lmcache/v1/compute/blend/__init__.py +7 -0
  141. lmcache/v1/compute/blend/blender.py +168 -0
  142. lmcache/v1/compute/blend/metadata.py +34 -0
  143. lmcache/v1/compute/blend/utils.py +63 -0
  144. lmcache/v1/compute/models/__init__.py +0 -0
  145. lmcache/v1/compute/models/base.py +141 -0
  146. lmcache/v1/compute/models/llama.py +9 -0
  147. lmcache/v1/compute/models/qwen3.py +24 -0
  148. lmcache/v1/compute/models/utils.py +68 -0
  149. lmcache/v1/compute/positional_encoding.py +199 -0
  150. lmcache/v1/config.py +848 -0
  151. lmcache/v1/config_base.py +848 -0
  152. lmcache/v1/distributed/api.py +248 -0
  153. lmcache/v1/distributed/config.py +321 -0
  154. lmcache/v1/distributed/error.py +64 -0
  155. lmcache/v1/distributed/eviction.py +192 -0
  156. lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
  157. lmcache/v1/distributed/eviction_policy/factory.py +27 -0
  158. lmcache/v1/distributed/eviction_policy/lru.py +244 -0
  159. lmcache/v1/distributed/eviction_policy/noop.py +50 -0
  160. lmcache/v1/distributed/internal_api.py +170 -0
  161. lmcache/v1/distributed/l1_manager.py +835 -0
  162. lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
  163. lmcache/v1/distributed/l2_adapters/base.py +360 -0
  164. lmcache/v1/distributed/l2_adapters/config.py +385 -0
  165. lmcache/v1/distributed/l2_adapters/factory.py +205 -0
  166. lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
  167. lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
  168. lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
  169. lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
  170. lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
  171. lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
  172. lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
  173. lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
  174. lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
  175. lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
  176. lmcache/v1/distributed/memory_manager.py +179 -0
  177. lmcache/v1/distributed/storage_controller.py +39 -0
  178. lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
  179. lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
  180. lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
  181. lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
  182. lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
  183. lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
  184. lmcache/v1/distributed/storage_manager.py +532 -0
  185. lmcache/v1/event_manager.py +145 -0
  186. lmcache/v1/exceptions/__init__.py +16 -0
  187. lmcache/v1/gpu_connector/__init__.py +126 -0
  188. lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
  189. lmcache/v1/gpu_connector/gpu_ops.py +85 -0
  190. lmcache/v1/gpu_connector/hpu_connector.py +326 -0
  191. lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
  192. lmcache/v1/gpu_connector/utils.py +890 -0
  193. lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
  194. lmcache/v1/health_monitor/__init__.py +1 -0
  195. lmcache/v1/health_monitor/base.py +587 -0
  196. lmcache/v1/health_monitor/checks/__init__.py +1 -0
  197. lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
  198. lmcache/v1/health_monitor/constants.py +36 -0
  199. lmcache/v1/internal_api_server/__init__.py +0 -0
  200. lmcache/v1/internal_api_server/api_registry.py +59 -0
  201. lmcache/v1/internal_api_server/api_server.py +120 -0
  202. lmcache/v1/internal_api_server/common/__init__.py +1 -0
  203. lmcache/v1/internal_api_server/common/env_api.py +22 -0
  204. lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
  205. lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
  206. lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
  207. lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
  208. lmcache/v1/internal_api_server/common/thread_api.py +63 -0
  209. lmcache/v1/internal_api_server/controller/__init__.py +1 -0
  210. lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
  211. lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
  212. lmcache/v1/internal_api_server/utils.py +43 -0
  213. lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
  214. lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
  215. lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
  216. lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
  217. lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
  218. lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
  219. lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
  220. lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
  221. lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
  222. lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
  223. lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
  224. lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
  225. lmcache/v1/kv_layer_groups.py +267 -0
  226. lmcache/v1/lazy_memory_allocator.py +284 -0
  227. lmcache/v1/lookup_client/__init__.py +25 -0
  228. lmcache/v1/lookup_client/abstract_client.py +77 -0
  229. lmcache/v1/lookup_client/async_lookup_message.py +50 -0
  230. lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
  231. lmcache/v1/lookup_client/factory.py +251 -0
  232. lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
  233. lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
  234. lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
  235. lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
  236. lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
  237. lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
  238. lmcache/v1/lookup_client/record_strategies/base.py +327 -0
  239. lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
  240. lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
  241. lmcache/v1/manager.py +539 -0
  242. lmcache/v1/memory_management.py +2619 -0
  243. lmcache/v1/metadata.py +114 -0
  244. lmcache/v1/mp_observability/AGENTS.override.md +21 -0
  245. lmcache/v1/mp_observability/README.md +204 -0
  246. lmcache/v1/mp_observability/config.py +340 -0
  247. lmcache/v1/mp_observability/event.py +100 -0
  248. lmcache/v1/mp_observability/event_bus.py +313 -0
  249. lmcache/v1/mp_observability/otel_init.py +145 -0
  250. lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
  251. lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
  252. lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
  253. lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
  254. lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
  255. lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
  256. lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
  257. lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
  258. lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
  259. lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
  260. lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
  261. lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
  262. lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
  263. lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
  264. lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
  265. lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
  266. lmcache/v1/mp_observability/trace/__init__.py +50 -0
  267. lmcache/v1/mp_observability/trace/codecs.py +255 -0
  268. lmcache/v1/mp_observability/trace/decorator.py +147 -0
  269. lmcache/v1/mp_observability/trace/format.py +132 -0
  270. lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
  271. lmcache/v1/mp_observability/trace/reader.py +167 -0
  272. lmcache/v1/mp_observability/trace/recorder.py +300 -0
  273. lmcache/v1/multiprocess/__init__.py +0 -0
  274. lmcache/v1/multiprocess/affinity_pool.py +102 -0
  275. lmcache/v1/multiprocess/blend_server_v2.py +891 -0
  276. lmcache/v1/multiprocess/config.py +253 -0
  277. lmcache/v1/multiprocess/custom_types.py +281 -0
  278. lmcache/v1/multiprocess/futures.py +194 -0
  279. lmcache/v1/multiprocess/gpu_context.py +511 -0
  280. lmcache/v1/multiprocess/http_server.py +235 -0
  281. lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
  282. lmcache/v1/multiprocess/mq.py +732 -0
  283. lmcache/v1/multiprocess/protocol.py +86 -0
  284. lmcache/v1/multiprocess/protocols/README.md +213 -0
  285. lmcache/v1/multiprocess/protocols/__init__.py +127 -0
  286. lmcache/v1/multiprocess/protocols/base.py +89 -0
  287. lmcache/v1/multiprocess/protocols/blend.py +109 -0
  288. lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
  289. lmcache/v1/multiprocess/protocols/controller.py +53 -0
  290. lmcache/v1/multiprocess/protocols/debug.py +34 -0
  291. lmcache/v1/multiprocess/protocols/engine.py +146 -0
  292. lmcache/v1/multiprocess/protocols/observability.py +39 -0
  293. lmcache/v1/multiprocess/server.py +1134 -0
  294. lmcache/v1/multiprocess/session.py +190 -0
  295. lmcache/v1/multiprocess/token_hasher.py +441 -0
  296. lmcache/v1/offload_server/__init__.py +17 -0
  297. lmcache/v1/offload_server/abstract_server.py +37 -0
  298. lmcache/v1/offload_server/message.py +30 -0
  299. lmcache/v1/offload_server/zmq_server.py +122 -0
  300. lmcache/v1/periodic_thread.py +579 -0
  301. lmcache/v1/pin_monitor.py +246 -0
  302. lmcache/v1/plugin/__init__.py +0 -0
  303. lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
  304. lmcache/v1/protocol.py +317 -0
  305. lmcache/v1/rpc/__init__.py +17 -0
  306. lmcache/v1/rpc/transport.py +105 -0
  307. lmcache/v1/rpc/zmq_transport.py +213 -0
  308. lmcache/v1/rpc_utils.py +165 -0
  309. lmcache/v1/server/__init__.py +2 -0
  310. lmcache/v1/server/__main__.py +170 -0
  311. lmcache/v1/server/storage_backend/__init__.py +21 -0
  312. lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
  313. lmcache/v1/server/storage_backend/local_backend.py +75 -0
  314. lmcache/v1/server/utils.py +21 -0
  315. lmcache/v1/standalone/__init__.py +1 -0
  316. lmcache/v1/standalone/__main__.py +583 -0
  317. lmcache/v1/standalone/manager.py +80 -0
  318. lmcache/v1/standalone/standalone_service_factory.py +86 -0
  319. lmcache/v1/storage_backend/__init__.py +313 -0
  320. lmcache/v1/storage_backend/abstract_backend.py +445 -0
  321. lmcache/v1/storage_backend/audit_backend.py +233 -0
  322. lmcache/v1/storage_backend/batched_message_sender.py +222 -0
  323. lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
  324. lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
  325. lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
  326. lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
  327. lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
  328. lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
  329. lmcache/v1/storage_backend/connector/__init__.py +443 -0
  330. lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
  331. lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
  332. lmcache/v1/storage_backend/connector/base_connector.py +379 -0
  333. lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
  334. lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
  335. lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
  336. lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
  337. lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
  338. lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
  339. lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
  340. lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
  341. lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
  342. lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
  343. lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
  344. lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
  345. lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
  346. lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
  347. lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
  348. lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
  349. lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
  350. lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
  351. lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
  352. lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
  353. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
  354. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
  355. lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
  356. lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
  357. lmcache/v1/storage_backend/gds_backend.py +1199 -0
  358. lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
  359. lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
  360. lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
  361. lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
  362. lmcache/v1/storage_backend/local_disk_backend.py +656 -0
  363. lmcache/v1/storage_backend/maru_backend.py +734 -0
  364. lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
  365. lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
  366. lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
  367. lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
  368. lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
  369. lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
  370. lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
  371. lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
  372. lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
  373. lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
  374. lmcache/v1/storage_backend/p2p_backend.py +788 -0
  375. lmcache/v1/storage_backend/path_sharder.py +117 -0
  376. lmcache/v1/storage_backend/pd_backend.py +646 -0
  377. lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
  378. lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
  379. lmcache/v1/storage_backend/remote_backend.py +624 -0
  380. lmcache/v1/storage_backend/resp_client.py +227 -0
  381. lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
  382. lmcache/v1/storage_backend/storage_manager.py +1352 -0
  383. lmcache/v1/system_detection.py +110 -0
  384. lmcache/v1/token_database.py +551 -0
  385. lmcache/v1/transfer_channel/__init__.py +83 -0
  386. lmcache/v1/transfer_channel/abstract.py +285 -0
  387. lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
  388. lmcache/v1/transfer_channel/nixl_channel.py +639 -0
  389. lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
  390. lmcache/v1/transfer_channel/transfer_utils.py +63 -0
  391. lmcache/v1/utils/__init__.py +1 -0
  392. lmcache/v1/utils/bloom_filter.py +109 -0
  393. lmcache/v1/utils/cache_utils.py +125 -0
  394. lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
  395. lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
  396. lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
  397. lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
  398. lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
  399. lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,435 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Long-document permutator workload for ``lmcache bench engine``.
3
+
4
+ Stress-tests blended KV cache reuse by sending permutations of a set of
5
+ context documents. Each request is:
6
+
7
+ [System Prompt] + [Doc_i1] + [Doc_i2] + ... + [Doc_iN]
8
+
9
+ where (i1, ..., iN) is one permutation of the N contexts.
10
+
11
+ Stress axes (controlled by config):
12
+ 1. Blended Context Boundaries -> num_contexts
13
+ 2. Eviction -> num_permutations
14
+ 3. Chunk Homogeneity -> vocab_size
15
+ 4. Prefix Domination -> system_prompt_length
16
+ 5. Concurrency -> num_inflight_requests
17
+ """
18
+
19
+ # Standard
20
+ from dataclasses import dataclass
21
+ import asyncio
22
+ import itertools
23
+ import math
24
+ import random
25
+
26
+ # First Party
27
+ from lmcache.cli.commands.bench.engine_bench.progress import ProgressMonitor
28
+ from lmcache.cli.commands.bench.engine_bench.request_sender import RequestSender
29
+ from lmcache.cli.commands.bench.engine_bench.stats import StatsCollector
30
+ from lmcache.cli.commands.bench.engine_bench.workloads.base import BaseWorkload
31
+ from lmcache.logging import init_logger
32
+
33
+ logger = init_logger(__name__)
34
+
35
+
36
+ @dataclass
37
+ class LongDocPermutatorConfig:
38
+ """Workload-specific config for the long-doc-permutator workload."""
39
+
40
+ num_contexts: int = 5
41
+ context_length: int = 5000
42
+ system_prompt_length: int = 1000
43
+ num_permutations: int = 10
44
+ vocab_size: int = 8000
45
+ num_inflight_requests: int = 1
46
+
47
+ def __post_init__(self) -> None:
48
+ if self.num_contexts < 1:
49
+ raise ValueError(f"num_contexts must be >= 1, got {self.num_contexts}")
50
+ if self.context_length <= 0:
51
+ raise ValueError(
52
+ f"context_length must be positive, got {self.context_length}"
53
+ )
54
+ if self.num_permutations < 1:
55
+ raise ValueError(
56
+ f"num_permutations must be >= 1, got {self.num_permutations}"
57
+ )
58
+ if self.vocab_size < 1:
59
+ raise ValueError(f"vocab_size must be >= 1, got {self.vocab_size}")
60
+ if self.num_inflight_requests < 1:
61
+ raise ValueError(
62
+ f"num_inflight_requests must be >= 1, got {self.num_inflight_requests}"
63
+ )
64
+
65
+ @classmethod
66
+ def resolve(
67
+ cls,
68
+ num_contexts: int = 5,
69
+ context_length: int = 5000,
70
+ system_prompt_length: int = 1000,
71
+ num_permutations: int = 10,
72
+ vocab_size: int = 8000,
73
+ num_inflight_requests: int = 1,
74
+ ) -> "LongDocPermutatorConfig":
75
+ """Create a config directly from the provided parameters.
76
+
77
+ Args:
78
+ num_contexts: Number of unique context documents.
79
+ context_length: Token length of each context.
80
+ system_prompt_length: Token length of the shared system prompt.
81
+ Use 0 for no system prompt.
82
+ num_permutations: Number of distinct permutations to send.
83
+ Capped at N! where N = num_contexts.
84
+ vocab_size: Vocabulary pool size for context generation.
85
+ Smaller values increase chunk hash collision risk.
86
+ num_inflight_requests: Max concurrent in-flight requests.
87
+
88
+ Returns:
89
+ A fully-resolved LongDocPermutatorConfig.
90
+ """
91
+ return cls(
92
+ num_contexts=num_contexts,
93
+ context_length=context_length,
94
+ system_prompt_length=system_prompt_length,
95
+ num_permutations=num_permutations,
96
+ vocab_size=vocab_size,
97
+ num_inflight_requests=num_inflight_requests,
98
+ )
99
+
100
+
101
+ # ---------------------------------------------------------------------------
102
+ # Prompt generation helpers (module-level, before classes)
103
+ # ---------------------------------------------------------------------------
104
+
105
+
106
+ def _generate_vocab_pool(size: int, seed: int = 42) -> list[str]:
107
+ """Generate a vocabulary pool of ``size`` unique pseudo-words.
108
+
109
+ Deterministically generates synthetic words so every token is unique.
110
+
111
+ Args:
112
+ size: Number of unique words to generate.
113
+ seed: Random seed for reproducibility.
114
+
115
+ Returns:
116
+ Sorted list of unique pseudo-words.
117
+ """
118
+ rng = random.Random(seed)
119
+ vowels = "aeiou"
120
+ consonants = "bcdfghjklmnpqrstvwxyz"
121
+ pool: set[str] = set()
122
+ while len(pool) < size:
123
+ length = rng.randint(3, 7)
124
+ word = ""
125
+ for j in range(length):
126
+ if j % 2 == 0:
127
+ word += rng.choice(consonants)
128
+ else:
129
+ word += rng.choice(vowels)
130
+ word = f"{word}{len(pool)}"
131
+ pool.add(word)
132
+ return sorted(pool)
133
+
134
+
135
+ def _generate_system_prompt(length: int, seed: int = 42) -> str:
136
+ """Generate a deterministic shared system prompt of ~``length`` tokens.
137
+
138
+ Args:
139
+ length: Approximate token length of the system prompt.
140
+ seed: Random seed for reproducibility.
141
+
142
+ Returns:
143
+ A string of ``length`` space-separated words.
144
+ """
145
+ if length == 0:
146
+ return ""
147
+ rng = random.Random(seed)
148
+ words = [
149
+ "the",
150
+ "system",
151
+ "will",
152
+ "process",
153
+ "your",
154
+ "request",
155
+ "and",
156
+ "provide",
157
+ "an",
158
+ "answer",
159
+ "based",
160
+ "on",
161
+ "context",
162
+ ]
163
+ return " ".join(rng.choices(words, k=length))
164
+
165
+
166
+ def _generate_contexts(
167
+ num_contexts: int,
168
+ length: int,
169
+ vocab_pool: list[str],
170
+ seed: int = 123,
171
+ ) -> list[str]:
172
+ """Generate ``num_contexts`` unique context blocks of ~``length`` tokens.
173
+
174
+ Each context draws from ``vocab_pool`` with a per-context seed so the
175
+ token sequences genuinely diverge.
176
+
177
+ Args:
178
+ num_contexts: Number of context documents to generate.
179
+ length: Approximate token length of each context.
180
+ vocab_pool: Pool of words to sample from.
181
+ seed: Base random seed; each context uses seed + i.
182
+
183
+ Returns:
184
+ List of context strings.
185
+ """
186
+ contexts = []
187
+ for i in range(num_contexts):
188
+ rng = random.Random(seed + i)
189
+ body = " ".join(rng.choices(vocab_pool, k=length))
190
+ contexts.append(body)
191
+ return contexts
192
+
193
+
194
+ def _enumerate_permutations(
195
+ num_contexts: int,
196
+ num_permutations: int,
197
+ seed: int = 0,
198
+ ) -> list[tuple[int, ...]]:
199
+ """Enumerate up to ``num_permutations`` distinct permutations.
200
+
201
+ Returns all N! permutations when num_permutations >= N!. For large N
202
+ uses random sampling to avoid iterating an enormous search space.
203
+
204
+ Args:
205
+ num_contexts: Number of contexts (N).
206
+ num_permutations: Maximum number of permutations to return.
207
+ seed: Random seed used when sampling is needed.
208
+
209
+ Returns:
210
+ List of permutation tuples.
211
+ """
212
+ total_possible = math.factorial(num_contexts)
213
+ if num_permutations >= total_possible:
214
+ return list(itertools.permutations(range(num_contexts)))
215
+
216
+ if total_possible > num_permutations * 10:
217
+ rng = random.Random(seed)
218
+ seen: set[tuple[int, ...]] = set()
219
+ indices = list(range(num_contexts))
220
+ while len(seen) < num_permutations:
221
+ perm = tuple(rng.sample(indices, len(indices)))
222
+ seen.add(perm)
223
+ return sorted(seen)
224
+
225
+ result = []
226
+ for perm in itertools.permutations(range(num_contexts)):
227
+ result.append(perm)
228
+ if len(result) >= num_permutations:
229
+ break
230
+ return result
231
+
232
+
233
+ # ---------------------------------------------------------------------------
234
+ # Workload class
235
+ # ---------------------------------------------------------------------------
236
+
237
+
238
+ class LongDocPermutatorWorkload(BaseWorkload):
239
+ """Workload that sends permutations of context documents.
240
+
241
+ Generates synthetic contexts from a vocab pool, enumerates permutations,
242
+ and dispatches requests with semaphore-controlled concurrency. Includes
243
+ a single dummy warmup request to prime the engine.
244
+ """
245
+
246
+ def __init__(
247
+ self,
248
+ config: LongDocPermutatorConfig,
249
+ request_sender: RequestSender,
250
+ stats_collector: StatsCollector,
251
+ progress_monitor: ProgressMonitor,
252
+ seed: int = 42,
253
+ ) -> None:
254
+ super().__init__(request_sender, stats_collector, progress_monitor)
255
+ self._config = config
256
+ self._seed = seed
257
+
258
+ vocab_pool = _generate_vocab_pool(config.vocab_size, seed=seed)
259
+ self._system_prompt = _generate_system_prompt(
260
+ config.system_prompt_length, seed=seed
261
+ )
262
+ self._contexts = _generate_contexts(
263
+ config.num_contexts, config.context_length, vocab_pool, seed=seed + 1
264
+ )
265
+ self._permutations = _enumerate_permutations(
266
+ config.num_contexts, config.num_permutations, seed=seed
267
+ )
268
+ self._request_list = self._build_request_list()
269
+ self._request_index = 0
270
+
271
+ self._semaphore = asyncio.Semaphore(config.num_inflight_requests)
272
+ self._pending_tasks: set[asyncio.Task] = set()
273
+
274
+ logger.debug(
275
+ "LongDocPermutator: %d contexts x %d permutations = %d requests",
276
+ config.num_contexts,
277
+ len(self._permutations),
278
+ len(self._request_list),
279
+ )
280
+
281
+ def run(self) -> None:
282
+ """Run warmup + benchmark, closing the HTTP client in the same loop.
283
+
284
+ Overrides ``BaseWorkload.run()`` to ensure the ``RequestSender``'s
285
+ async HTTP client is closed before the event loop shuts down.
286
+ ``asyncio.run()`` closes the loop on exit, which orphans any open
287
+ httpx connections; closing the client here — inside the same
288
+ ``asyncio.run()`` — tears them down cleanly so the caller's
289
+ subsequent ``asyncio.run(request_sender.close())`` finds nothing
290
+ to close and completes without error.
291
+ """
292
+
293
+ async def _run_and_close() -> None:
294
+ try:
295
+ await self._run_async()
296
+ finally:
297
+ await self._request_sender.close()
298
+
299
+ asyncio.run(_run_and_close())
300
+
301
+ def log_config(self) -> None:
302
+ """Log key workload config before the benchmark starts."""
303
+ c = self._config
304
+ B = "\033[1m"
305
+ C = "\033[96m"
306
+ Y = "\033[93m"
307
+ R = "\033[0m"
308
+ total = len(self._request_list)
309
+ actual_perms = len(self._permutations)
310
+ print(
311
+ f"{B}{'═' * 50}{R}\n"
312
+ f"{B} Workload: {C}long-doc-permutator{R}\n"
313
+ f"{B}{'─' * 50}{R}\n"
314
+ f" Contexts: {Y}{c.num_contexts}{R}\n"
315
+ f" Context length: {Y}{c.context_length}{R} tokens\n"
316
+ f" System prompt: {Y}{c.system_prompt_length}{R} tokens\n"
317
+ f" Permutations: {Y}{actual_perms}{R} "
318
+ f"(of {math.factorial(c.num_contexts)} possible)\n"
319
+ f" Total requests: {Y}{total}{R}\n"
320
+ f" Vocab size: {Y}{c.vocab_size}{R}\n"
321
+ f" Max inflight: {Y}{c.num_inflight_requests}{R}\n"
322
+ f"{B}{'═' * 50}{R}"
323
+ )
324
+
325
+ # ------------------------------------------------------------------
326
+ # Data generation
327
+ # ------------------------------------------------------------------
328
+
329
+ def _build_request_list(self) -> list[tuple[list[dict[str, str]], int]]:
330
+ """Build the full request list from the enumerated permutations.
331
+
332
+ Each entry is ``(messages, permutation_index)`` where messages
333
+ concatenates all contexts in permutation order into a single user
334
+ message, preceded by the system prompt.
335
+
336
+ Returns:
337
+ List of (messages, permutation_index) tuples.
338
+ """
339
+ requests: list[tuple[list[dict[str, str]], int]] = []
340
+ for perm_idx, perm in enumerate(self._permutations):
341
+ concatenated = "\n\n".join(self._contexts[i] for i in perm)
342
+ messages: list[dict[str, str]] = []
343
+ if self._system_prompt:
344
+ messages.append({"role": "system", "content": self._system_prompt})
345
+ messages.append({"role": "user", "content": concatenated})
346
+ requests.append((messages, perm_idx))
347
+ return requests
348
+
349
+ # ------------------------------------------------------------------
350
+ # Warmup
351
+ # ------------------------------------------------------------------
352
+
353
+ async def warmup(self) -> None:
354
+ """Send a single dummy warmup request to prime the engine."""
355
+ request_id = "warmup_0"
356
+ dummy_content = " ".join(["warmup"] * 500)
357
+ messages: list[dict[str, str]] = [
358
+ {"role": "system", "content": "You are a helpful assistant."},
359
+ {"role": "user", "content": dummy_content},
360
+ ]
361
+ self._progress_monitor.log_message("Warmup (1 dummy request)")
362
+ self._progress_monitor.on_request_sent(request_id)
363
+ result = await self._request_sender.send_warmup_request(request_id, messages)
364
+ if not result.successful:
365
+ self._progress_monitor.log_message(f"Warmup request failed: {result.error}")
366
+ self._progress_monitor.log_message("Warmup complete")
367
+
368
+ # ------------------------------------------------------------------
369
+ # Benchmark dispatch
370
+ # ------------------------------------------------------------------
371
+
372
+ async def step(self, time_offset: float) -> float:
373
+ """Dispatch the next permutation request if semaphore allows.
374
+
375
+ Args:
376
+ time_offset: Seconds since benchmark start (unused).
377
+
378
+ Returns:
379
+ 0.0 to request an immediate re-call, or -1.0 when all done.
380
+ """
381
+ if self._request_index < len(self._request_list):
382
+ await self._semaphore.acquire()
383
+ req_idx = self._request_index
384
+ messages, perm_idx = self._request_list[req_idx]
385
+ self._request_index += 1
386
+
387
+ task = asyncio.create_task(self._dispatch(messages, perm_idx, req_idx))
388
+ self._pending_tasks.add(task)
389
+ task.add_done_callback(self._on_task_done)
390
+ return 0.0
391
+
392
+ if self._pending_tasks:
393
+ await asyncio.wait(
394
+ self._pending_tasks,
395
+ return_when=asyncio.FIRST_COMPLETED,
396
+ )
397
+ return 0.0
398
+
399
+ return -1.0
400
+
401
+ async def _dispatch(
402
+ self,
403
+ messages: list[dict[str, str]],
404
+ perm_idx: int,
405
+ req_idx: int,
406
+ ) -> None:
407
+ """Send a single benchmark request, then release the semaphore.
408
+
409
+ Args:
410
+ messages: Chat messages for the request.
411
+ perm_idx: Index of the permutation (used for request ID).
412
+ req_idx: The request index captured before incrementing the counter.
413
+ """
414
+ request_id = f"perm{perm_idx}_req{req_idx}"
415
+ self._progress_monitor.on_request_sent(request_id)
416
+ self._progress_monitor.log_message(f"Dispatched permutation {perm_idx}")
417
+ try:
418
+ await self._request_sender.send_request(request_id, messages)
419
+ finally:
420
+ self._semaphore.release()
421
+
422
+ def _on_task_done(self, task: asyncio.Task) -> None:
423
+ """Clean up completed tasks and log unexpected errors.
424
+
425
+ Args:
426
+ task: The completed asyncio Task.
427
+ """
428
+ self._pending_tasks.discard(task)
429
+ if not task.cancelled():
430
+ exc = task.exception()
431
+ if exc is not None:
432
+ self._progress_monitor.log_message(f"Dispatch task failed: {exc}")
433
+
434
+ def on_request_finished(self, request_id: str, output: str) -> None:
435
+ """No-op — this workload is stateless."""