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,537 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from contextlib import asynccontextmanager
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+ import argparse
6
+ import asyncio
7
+ import json
8
+ import os
9
+ import sys
10
+ import uuid
11
+
12
+ # Add project root to Python path for local development
13
+ sys.path.insert(
14
+ 0,
15
+ os.path.dirname(
16
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
17
+ ),
18
+ )
19
+
20
+ # Third Party
21
+ from fastapi import FastAPI, HTTPException
22
+ from fastapi.responses import HTMLResponse
23
+ from fastapi.staticfiles import StaticFiles
24
+ from pydantic import BaseModel
25
+ import uvicorn
26
+
27
+ # First Party
28
+ from lmcache.logging import init_logger
29
+ from lmcache.v1.cache_controller.config import (
30
+ load_controller_config_with_overrides,
31
+ )
32
+ from lmcache.v1.cache_controller.controller_manager import LMCacheControllerManager
33
+ from lmcache.v1.cache_controller.message import ( # noqa: E501
34
+ CheckFinishMsg,
35
+ CheckFinishRetMsg,
36
+ ClearMsg,
37
+ ClearRetMsg,
38
+ CompressMsg,
39
+ CompressRetMsg,
40
+ DecompressMsg,
41
+ DecompressRetMsg,
42
+ ErrorMsg,
43
+ HealthMsg,
44
+ HealthRetMsg,
45
+ LookupMsg,
46
+ LookupRetMsg,
47
+ MoveMsg,
48
+ MoveRetMsg,
49
+ PinMsg,
50
+ PinRetMsg,
51
+ QueryInstMsg,
52
+ QueryInstRetMsg,
53
+ QueryWorkerInfoMsg,
54
+ QueryWorkerInfoRetMsg,
55
+ WorkerInfo,
56
+ )
57
+ from lmcache.v1.config_base import parse_command_line_extra_params
58
+ from lmcache.v1.internal_api_server.api_registry import APIRegistry
59
+
60
+ logger = init_logger(__name__)
61
+
62
+
63
+ def parse_extra_params(extra_args: list) -> Dict[str, Any]:
64
+ """Parse extra parameters in key=value format"""
65
+ params = {}
66
+ for arg in extra_args:
67
+ if "=" in arg:
68
+ key, value = arg.split("=", 1)
69
+ key = key.lstrip("-")
70
+ try:
71
+ if value.lower() in ("true", "false"):
72
+ params[key] = value.lower() == "true"
73
+ elif value.isdigit():
74
+ params[key] = int(value)
75
+ elif value.replace(".", "", 1).isdigit():
76
+ params[key] = float(value)
77
+ else:
78
+ params[key] = value
79
+ except ValueError:
80
+ params[key] = value
81
+ logger.info(f"Extra parameter: {key} = {params[key]}")
82
+ return params
83
+
84
+
85
+ def create_app(
86
+ controller_urls: dict[str, str],
87
+ health_check_interval: int,
88
+ lmcache_worker_timeout: int,
89
+ ) -> FastAPI:
90
+ """
91
+ Create a FastAPI application with endpoints for LMCache operations.
92
+ """
93
+ lmcache_controller_manager = LMCacheControllerManager(
94
+ controller_urls, health_check_interval, lmcache_worker_timeout
95
+ )
96
+
97
+ @asynccontextmanager
98
+ async def lifespan(app: FastAPI):
99
+ # Start background task here
100
+ lmcache_cluster_monitor_task = asyncio.create_task(
101
+ lmcache_controller_manager.start_all()
102
+ )
103
+ yield
104
+ # Optionally cancel the task on shutdown
105
+ lmcache_cluster_monitor_task.cancel()
106
+ try:
107
+ await lmcache_cluster_monitor_task
108
+ except asyncio.CancelledError:
109
+ pass
110
+
111
+ app = FastAPI(lifespan=lifespan)
112
+ app.state.lmcache_controller_manager = lmcache_controller_manager
113
+
114
+ # Register internal APIs (only common APIs, not vllm-specific ones)
115
+ registry = APIRegistry(app)
116
+ registry.register_all_apis(categories=["common", "controller"])
117
+
118
+ # Add static files for frontend
119
+ project_root = os.path.dirname(
120
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
121
+ )
122
+ static_dir = os.path.join(
123
+ project_root,
124
+ "lmcache",
125
+ "v1",
126
+ "cache_controller",
127
+ "frontend",
128
+ "static",
129
+ )
130
+ if os.path.exists(static_dir):
131
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
132
+ logger.info("Controller frontend static files mounted at /static")
133
+ else:
134
+ logger.warning("Controller frontend static directory not found: %s", static_dir)
135
+
136
+ @app.get("/", response_class=HTMLResponse)
137
+ async def serve_frontend():
138
+ """Serve the Controller frontend HTML page."""
139
+ index_path = os.path.join(static_dir, "index.html")
140
+ if os.path.exists(index_path):
141
+ with open(index_path, "r") as f:
142
+ html_content = f.read()
143
+ return HTMLResponse(content=html_content)
144
+ else:
145
+ return HTMLResponse(
146
+ content="<h1>Controller Frontend not found</h1>"
147
+ "<p>Please build the frontend first.</p>",
148
+ status_code=404,
149
+ )
150
+
151
+ class QueryInstRequest(BaseModel):
152
+ event_id: str
153
+ ip: str
154
+
155
+ class QueryInstResponse(BaseModel):
156
+ event_id: str
157
+ res: str # the instance id
158
+
159
+ @app.post("/query_instance")
160
+ async def query_instance(req: QueryInstRequest):
161
+ try:
162
+ event_id = "QueryInst" + str(uuid.uuid4())
163
+ msg = QueryInstMsg(
164
+ event_id=event_id,
165
+ ip=req.ip,
166
+ )
167
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
168
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
169
+ assert isinstance(ret_msg, QueryInstRetMsg)
170
+ return QueryInstResponse(
171
+ event_id=ret_msg.event_id,
172
+ res=ret_msg.instance_id,
173
+ )
174
+ except Exception as e:
175
+ raise HTTPException(status_code=500, detail=str(e)) from e
176
+
177
+ class LookupRequest(BaseModel):
178
+ tokens: List[int]
179
+
180
+ class LookupResponse(BaseModel):
181
+ event_id: str
182
+ # a list of (instance_id, location, token_count)
183
+ layout_info: Dict[str, Tuple[str, int]]
184
+
185
+ @app.post("/lookup", response_model=LookupResponse)
186
+ async def lookup(req: LookupRequest):
187
+ try:
188
+ event_id = "Lookup" + str(uuid.uuid4())
189
+ msg = LookupMsg(
190
+ event_id=event_id,
191
+ tokens=req.tokens,
192
+ )
193
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
194
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
195
+ assert isinstance(ret_msg, LookupRetMsg)
196
+ return LookupResponse(
197
+ event_id=ret_msg.event_id, layout_info=ret_msg.layout_info
198
+ )
199
+ except Exception as e:
200
+ raise HTTPException(status_code=500, detail=str(e)) from e
201
+
202
+ class ClearRequest(BaseModel):
203
+ instance_id: str
204
+ location: str
205
+
206
+ class ClearResponse(BaseModel):
207
+ event_id: str
208
+ num_tokens: int
209
+
210
+ @app.post("/clear", response_model=ClearResponse)
211
+ async def clear(req: ClearRequest):
212
+ try:
213
+ event_id = "Clear" + str(uuid.uuid4())
214
+ msg = ClearMsg(
215
+ event_id=event_id,
216
+ instance_id=req.instance_id,
217
+ location=req.location,
218
+ )
219
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
220
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
221
+ assert isinstance(ret_msg, ClearRetMsg)
222
+ return ClearResponse(
223
+ event_id=ret_msg.event_id, num_tokens=ret_msg.num_tokens
224
+ )
225
+ except Exception as e:
226
+ raise HTTPException(status_code=500, detail=str(e)) from e
227
+
228
+ class PinRequest(BaseModel):
229
+ instance_id: str
230
+ location: str
231
+ tokens: list[int]
232
+
233
+ class PinResponse(BaseModel):
234
+ event_id: str
235
+ num_tokens: int
236
+
237
+ @app.post("/pin", response_model=PinResponse)
238
+ async def pin(req: PinRequest):
239
+ try:
240
+ event_id = "Pin" + str(uuid.uuid4())
241
+ msg = PinMsg(
242
+ event_id=event_id,
243
+ instance_id=req.instance_id,
244
+ location=req.location,
245
+ tokens=req.tokens,
246
+ )
247
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
248
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
249
+ assert isinstance(ret_msg, PinRetMsg)
250
+ return PinResponse(event_id=ret_msg.event_id, num_tokens=ret_msg.num_tokens)
251
+ except Exception as e:
252
+ raise HTTPException(status_code=500, detail=str(e)) from e
253
+
254
+ class CompressRequest(BaseModel):
255
+ instance_id: str
256
+ method: str
257
+ location: str
258
+ tokens: Optional[List[int]] = []
259
+
260
+ class CompressResponse(BaseModel):
261
+ event_id: str
262
+ num_tokens: int
263
+
264
+ class DecompressRequest(BaseModel):
265
+ instance_id: str
266
+ method: str
267
+ location: str
268
+ tokens: Optional[List[int]] = []
269
+
270
+ class DecompressResponse(BaseModel):
271
+ event_id: str
272
+ num_tokens: int
273
+
274
+ @app.post("/compress", response_model=CompressResponse)
275
+ async def compress(req: CompressRequest):
276
+ try:
277
+ event_id = "Compress" + str(uuid.uuid4())
278
+ msg = CompressMsg(
279
+ event_id=event_id,
280
+ instance_id=req.instance_id,
281
+ method=req.method,
282
+ location=req.location,
283
+ tokens=req.tokens,
284
+ )
285
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
286
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
287
+ assert isinstance(ret_msg, CompressRetMsg)
288
+ return CompressResponse(
289
+ event_id=ret_msg.event_id, num_tokens=ret_msg.num_tokens
290
+ )
291
+ except Exception as e:
292
+ raise HTTPException(status_code=500, detail=str(e)) from e
293
+
294
+ @app.post("/decompress", response_model=DecompressResponse)
295
+ async def decompress(req: DecompressRequest):
296
+ try:
297
+ event_id = "Decompress" + str(uuid.uuid4())
298
+ msg = DecompressMsg(
299
+ event_id=event_id,
300
+ instance_id=req.instance_id,
301
+ method=req.method,
302
+ location=req.location,
303
+ tokens=req.tokens,
304
+ )
305
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
306
+ assert isinstance(ret_msg, DecompressRetMsg)
307
+ return DecompressResponse(
308
+ event_id=ret_msg.event_id, num_tokens=ret_msg.num_tokens
309
+ )
310
+ except Exception as e:
311
+ raise HTTPException(status_code=500, detail=str(e)) from e
312
+
313
+ class MoveRequest(BaseModel):
314
+ # (instance_id, location)
315
+ old_position: Tuple[str, str]
316
+ new_position: Tuple[str, str]
317
+ tokens: Optional[List[int]] = []
318
+ should_copy: Optional[bool] = False
319
+
320
+ class MoveResponse(BaseModel):
321
+ event_id: str
322
+ num_tokens: int
323
+
324
+ @app.post("/move", response_model=MoveResponse)
325
+ async def move(req: MoveRequest):
326
+ try:
327
+ event_id = "Move" + str(uuid.uuid4())
328
+ msg = MoveMsg(
329
+ event_id=event_id,
330
+ old_position=req.old_position,
331
+ new_position=req.new_position,
332
+ tokens=req.tokens,
333
+ copy=req.should_copy,
334
+ )
335
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
336
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
337
+ assert isinstance(ret_msg, MoveRetMsg)
338
+ return MoveResponse(
339
+ event_id=ret_msg.event_id,
340
+ num_tokens=ret_msg.num_tokens,
341
+ )
342
+ except Exception as e:
343
+ raise HTTPException(status_code=500, detail=str(e)) from e
344
+
345
+ class HealthRequest(BaseModel):
346
+ instance_id: str
347
+
348
+ class HealthResponse(BaseModel):
349
+ event_id: str
350
+ # worker_id -> error_code
351
+ error_codes: dict[int, int]
352
+
353
+ @app.post("/health", response_model=HealthResponse)
354
+ async def health(req: HealthRequest):
355
+ try:
356
+ event_id = "health" + str(uuid.uuid4())
357
+ msg = HealthMsg(
358
+ event_id=event_id,
359
+ instance_id=req.instance_id,
360
+ )
361
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
362
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
363
+ assert isinstance(ret_msg, HealthRetMsg)
364
+ return HealthResponse(
365
+ event_id=ret_msg.event_id, error_codes=ret_msg.error_codes
366
+ )
367
+ except Exception as e:
368
+ raise HTTPException(status_code=500, detail=str(e)) from e
369
+
370
+ class CheckFinishRequest(BaseModel):
371
+ event_id: str
372
+
373
+ class CheckFinishResponse(BaseModel):
374
+ status: str
375
+
376
+ @app.post("/check_finish", response_model=CheckFinishResponse)
377
+ async def check_finish(req: CheckFinishRequest):
378
+ try:
379
+ msg = CheckFinishMsg(
380
+ event_id=req.event_id,
381
+ )
382
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
383
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
384
+ assert isinstance(ret_msg, CheckFinishRetMsg)
385
+ return CheckFinishResponse(status=ret_msg.status)
386
+ except Exception as e:
387
+ raise HTTPException(status_code=500, detail=str(e)) from e
388
+
389
+ class QueryWorkerInfoRequest(BaseModel):
390
+ instance_id: str
391
+ worker_ids: Optional[list[int]] = None
392
+
393
+ class QueryWorkerInfoResponse(BaseModel):
394
+ event_id: str
395
+ worker_infos: list[WorkerInfo]
396
+
397
+ @app.post("/query_worker_info", response_model=QueryWorkerInfoResponse)
398
+ async def query_worker_info(req: QueryWorkerInfoRequest):
399
+ try:
400
+ event_id = "QueryWorkerInfo" + str(uuid.uuid4())
401
+ msg = QueryWorkerInfoMsg(
402
+ event_id=event_id,
403
+ instance_id=req.instance_id,
404
+ worker_ids=req.worker_ids,
405
+ )
406
+ ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)
407
+ assert not isinstance(ret_msg, ErrorMsg), ret_msg.error
408
+ assert isinstance(ret_msg, QueryWorkerInfoRetMsg)
409
+ return QueryWorkerInfoResponse(
410
+ event_id=ret_msg.event_id, worker_infos=ret_msg.worker_infos
411
+ )
412
+ except Exception as e:
413
+ raise HTTPException(status_code=500, detail=str(e)) from e
414
+
415
+ return app
416
+
417
+
418
+ def main():
419
+ parser = argparse.ArgumentParser()
420
+ parser.add_argument(
421
+ "--config", type=str, help="Path to controller configuration file"
422
+ )
423
+ parser.add_argument("--host", type=str, default="0.0.0.0")
424
+ parser.add_argument("--port", type=int, default=9000)
425
+ parser.add_argument(
426
+ "--monitor-ports",
427
+ type=json.loads,
428
+ default=None,
429
+ help='JSON string of monitor ports, e.g. \'{"pull": 8300, "reply": 8400}\'',
430
+ )
431
+ parser.add_argument(
432
+ "--monitor-port",
433
+ type=int,
434
+ default=9001,
435
+ help="The controller pull port to maintain backward compatibility.",
436
+ )
437
+ parser.add_argument(
438
+ "--health-check-interval",
439
+ type=int,
440
+ default=-1,
441
+ help="Health check interval in secs, default is -1, which means disabled.",
442
+ )
443
+ parser.add_argument(
444
+ "--lmcache-worker-timeout",
445
+ type=int,
446
+ default=300,
447
+ help="The lmcache worker timeout in seconds.",
448
+ )
449
+
450
+ # Parse known args first, then handle extra parameters
451
+ args, extra = parser.parse_known_args()
452
+ extra_params = parse_command_line_extra_params(extra)
453
+
454
+ try:
455
+ # Build overrides dictionary from command-line arguments
456
+ override_dict = {}
457
+
458
+ # Map command-line arguments to config keys
459
+ arg_mappings = {
460
+ "host": "controller_host",
461
+ "port": "controller_port",
462
+ "monitor_ports": "controller_monitor_ports",
463
+ "health_check_interval": "health_check_interval",
464
+ "lmcache_worker_timeout": "lmcache_worker_timeout",
465
+ }
466
+
467
+ for arg_name, config_key in arg_mappings.items():
468
+ arg_value = getattr(args, arg_name)
469
+ if arg_value is not None:
470
+ override_dict[config_key] = arg_value
471
+
472
+ # Add extra parameters
473
+ if extra_params:
474
+ override_dict.update(extra_params)
475
+
476
+ # Load configuration using the generic utility function
477
+ # This replaces the previous manual config loading code
478
+ config = load_controller_config_with_overrides(
479
+ config_file_path=args.config,
480
+ overrides=override_dict,
481
+ )
482
+
483
+ # Build controller URLs from config or arguments
484
+ if config.controller_monitor_ports is not None:
485
+ controller_urls = {
486
+ "pull": (
487
+ f"{config.controller_host}:"
488
+ f"{config.controller_monitor_ports['pull']}"
489
+ ),
490
+ "reply": (
491
+ f"{config.controller_host}:"
492
+ f"{config.controller_monitor_ports['reply']}"
493
+ ),
494
+ "heartbeat": (
495
+ f"{config.controller_host}:"
496
+ f"{config.controller_monitor_ports['heartbeat']}"
497
+ if config.controller_monitor_ports.get("heartbeat")
498
+ else None
499
+ ),
500
+ }
501
+ else:
502
+ if args.monitor_port != 9001: # Only warn if explicitly set
503
+ logger.warning(
504
+ "Argument --monitor-port will be deprecated soon. "
505
+ "Please use --monitor-ports instead."
506
+ )
507
+ controller_urls = {
508
+ "pull": f"{config.controller_host}:{args.monitor_port}",
509
+ "reply": None,
510
+ "heartbeat": None,
511
+ }
512
+
513
+ # Use config values for health check and timeout
514
+ health_check_interval = config.health_check_interval
515
+ lmcache_worker_timeout = config.lmcache_worker_timeout
516
+
517
+ app = create_app(controller_urls, health_check_interval, lmcache_worker_timeout)
518
+
519
+ logger.info(
520
+ f"Starting LMCache controller at "
521
+ f"{config.controller_host}:{config.controller_port}"
522
+ )
523
+ ports_message = f"Monitoring lmcache workers at ports {controller_urls}"
524
+ logger.info(ports_message)
525
+ logger.info(f"Health check interval: {health_check_interval}s")
526
+ logger.info(f"Worker timeout: {lmcache_worker_timeout}s")
527
+
528
+ uvicorn.run(app, host=config.controller_host, port=config.controller_port)
529
+ except TimeoutError as e:
530
+ logger.error(e)
531
+ except Exception as e:
532
+ logger.error(f"Failed to start controller: {e}", exc_info=True)
533
+ sys.exit(1) # Exit with error code
534
+
535
+
536
+ if __name__ == "__main__":
537
+ main()
@@ -0,0 +1,112 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ import argparse
4
+ import asyncio
5
+
6
+ # First Party
7
+ from lmcache.v1.check import registry
8
+
9
+ model_name = "/lmcache_test_model/"
10
+
11
+
12
+ def parse_args():
13
+ parser = argparse.ArgumentParser(description="LMCache basic check Tool")
14
+ parser.add_argument(
15
+ "--mode",
16
+ required=True,
17
+ help="Operation mode (e.g. test_remote, test_storage_manager). "
18
+ "Use 'list' to show available modes",
19
+ )
20
+ parser.add_argument("--model", default=model_name, help="model name")
21
+ parser.add_argument(
22
+ "--num-keys",
23
+ type=int,
24
+ default=5,
25
+ help="Number of keys for gen mode or test iterations "
26
+ "for test_* modes (default: 5)",
27
+ )
28
+ parser.add_argument(
29
+ "--concurrency",
30
+ type=int,
31
+ default=16,
32
+ help="Concurrency level for generation (gen mode only)",
33
+ )
34
+ parser.add_argument(
35
+ "--offset",
36
+ type=int,
37
+ default=0,
38
+ help="Offset for key generation (gen mode only)",
39
+ )
40
+ parser.add_argument(
41
+ "--l2-adapter",
42
+ dest="l2_adapter",
43
+ action="append",
44
+ default=[],
45
+ type=str,
46
+ metavar="JSON",
47
+ help="L2 adapter spec as JSON (test_l2_adapter mode). "
48
+ 'e.g. \'{"type":"mock","max_size_gb":1}\'.',
49
+ )
50
+ parser.add_argument(
51
+ "--obj-size",
52
+ dest="obj_size",
53
+ type=int,
54
+ default=None,
55
+ help="Object size in number of elements (default: 1024)",
56
+ )
57
+ parser.add_argument(
58
+ "--kv-dtype",
59
+ dest="kv_dtype",
60
+ type=str,
61
+ default=None,
62
+ help="KV dtype, e.g. float32, bfloat16, float16 (default depends on mode)",
63
+ )
64
+ parser.add_argument(
65
+ "--settle-time",
66
+ dest="settle_time",
67
+ type=float,
68
+ default=0.0,
69
+ help="Seconds to wait after store before load "
70
+ "(default: 0, useful for remote backends)",
71
+ )
72
+ return parser.parse_args()
73
+
74
+
75
+ async def main():
76
+ args = parse_args()
77
+
78
+ # List available modes if requested
79
+ if args.mode == "list":
80
+ registry.load_modes()
81
+ print("Available check modes:")
82
+ for mode_name in registry.modes:
83
+ print(f" - {mode_name}")
84
+ return
85
+
86
+ # Get the requested mode function
87
+ mode_func = registry.get_mode(args.mode)
88
+ if not mode_func:
89
+ print(
90
+ f"Error: Unknown mode '{args.mode}'. "
91
+ "Use '--mode list' to see available modes."
92
+ )
93
+ return
94
+
95
+ # Prepare arguments for the mode function
96
+ mode_args = {
97
+ "model": args.model,
98
+ "num_keys": args.num_keys,
99
+ "concurrency": args.concurrency,
100
+ "offset": args.offset,
101
+ "l2_adapter": args.l2_adapter,
102
+ "obj_size": args.obj_size,
103
+ "kv_dtype": args.kv_dtype,
104
+ "settle_time": args.settle_time,
105
+ }
106
+
107
+ # Execute the mode function
108
+ await mode_func(**mode_args)
109
+
110
+
111
+ if __name__ == "__main__":
112
+ asyncio.run(main())
@@ -0,0 +1,9 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # First Party
3
+ from lmcache.v1.cache_controller.executor import LMCacheClusterExecutor # noqa: E501
4
+ from lmcache.v1.cache_controller.worker import LMCacheWorker # noqa: E501
5
+
6
+ __all__ = [
7
+ "LMCacheClusterExecutor",
8
+ "LMCacheWorker",
9
+ ]
@@ -0,0 +1,15 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Heartbeat commands module
3
+
4
+ This module provides the command abstraction for the heartbeat mechanism.
5
+ Commands can be sent from controller to workers through heartbeat responses.
6
+ """
7
+
8
+ # First Party
9
+ from lmcache.v1.cache_controller.commands.base import HeartbeatCommand
10
+ from lmcache.v1.cache_controller.commands.full_sync import FullSyncCommand
11
+
12
+ __all__ = [
13
+ "HeartbeatCommand",
14
+ "FullSyncCommand",
15
+ ]