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.
- lmcache/__init__.py +84 -0
- lmcache/_version.py +24 -0
- lmcache/cli/__init__.py +1 -0
- lmcache/cli/commands/__init__.py +34 -0
- lmcache/cli/commands/base.py +157 -0
- lmcache/cli/commands/bench/__init__.py +557 -0
- lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
- lmcache/cli/commands/bench/engine_bench/config.py +245 -0
- lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
- lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
- lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
- lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
- lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
- lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
- lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
- lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
- lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
- lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
- lmcache/cli/commands/describe.py +310 -0
- lmcache/cli/commands/kvcache.py +133 -0
- lmcache/cli/commands/mock.py +75 -0
- lmcache/cli/commands/ping.py +113 -0
- lmcache/cli/commands/query/__init__.py +155 -0
- lmcache/cli/commands/query/prompt.py +134 -0
- lmcache/cli/commands/query/request.py +357 -0
- lmcache/cli/commands/server.py +99 -0
- lmcache/cli/commands/tool/__init__.py +63 -0
- lmcache/cli/commands/tool/cache_simulator.py +113 -0
- lmcache/cli/commands/trace/__init__.py +505 -0
- lmcache/cli/commands/trace/dispatch.py +249 -0
- lmcache/cli/commands/trace/driver.py +372 -0
- lmcache/cli/commands/trace/stats.py +289 -0
- lmcache/cli/documents/lmcache.txt +11 -0
- lmcache/cli/main.py +42 -0
- lmcache/cli/metrics/__init__.py +29 -0
- lmcache/cli/metrics/formatter.py +171 -0
- lmcache/cli/metrics/handler.py +94 -0
- lmcache/cli/metrics/metrics.py +161 -0
- lmcache/cli/metrics/section.py +77 -0
- lmcache/connections.py +173 -0
- lmcache/integration/__init__.py +2 -0
- lmcache/integration/base_service_factory.py +165 -0
- lmcache/integration/request_telemetry/__init__.py +1 -0
- lmcache/integration/request_telemetry/base.py +51 -0
- lmcache/integration/request_telemetry/factory.py +113 -0
- lmcache/integration/request_telemetry/fastapi.py +109 -0
- lmcache/integration/request_telemetry/noop.py +35 -0
- lmcache/integration/sglang/__init__.py +2 -0
- lmcache/integration/sglang/sglang_adapter.py +326 -0
- lmcache/integration/sglang/utils.py +39 -0
- lmcache/integration/vllm/__init__.py +1 -0
- lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
- lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
- lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
- lmcache/integration/vllm/utils.py +433 -0
- lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
- lmcache/integration/vllm/vllm_service_factory.py +339 -0
- lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
- lmcache/logging.py +107 -0
- lmcache/native_storage_ops.pyi +230 -0
- lmcache/non_cuda_equivalents.py +1424 -0
- lmcache/observability.py +1958 -0
- lmcache/storage_backend/serde/__init__.py +1 -0
- lmcache/storage_backend/serde/cachegen_basics.py +210 -0
- lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
- lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
- lmcache/storage_backend/serde/serde.py +75 -0
- lmcache/tools/__init__.py +1 -0
- lmcache/tools/cache_simulator/README.md +392 -0
- lmcache/tools/cache_simulator/__init__.py +1 -0
- lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
- lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
- lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
- lmcache/tools/cache_simulator/lru_cache.py +124 -0
- lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
- lmcache/tools/cache_simulator/simulator.py +795 -0
- lmcache/tools/controller_benchmark/README.md +161 -0
- lmcache/tools/controller_benchmark/__init__.py +1 -0
- lmcache/tools/controller_benchmark/__main__.py +331 -0
- lmcache/tools/controller_benchmark/benchmark.py +660 -0
- lmcache/tools/controller_benchmark/config.py +44 -0
- lmcache/tools/controller_benchmark/constants.py +10 -0
- lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
- lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
- lmcache/tools/controller_benchmark/handlers/base.py +47 -0
- lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
- lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
- lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
- lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
- lmcache/tools/controller_benchmark/handlers/register.py +56 -0
- lmcache/tools/mp_status_viewer/__init__.py +1 -0
- lmcache/tools/mp_status_viewer/__main__.py +95 -0
- lmcache/usage_context.py +417 -0
- lmcache/utils.py +665 -0
- lmcache/v1/__init__.py +2 -0
- lmcache/v1/api_server/__init__.py +2 -0
- lmcache/v1/api_server/__main__.py +537 -0
- lmcache/v1/basic_check.py +112 -0
- lmcache/v1/cache_controller/__init__.py +9 -0
- lmcache/v1/cache_controller/commands/__init__.py +15 -0
- lmcache/v1/cache_controller/commands/base.py +35 -0
- lmcache/v1/cache_controller/commands/full_sync.py +49 -0
- lmcache/v1/cache_controller/config.py +176 -0
- lmcache/v1/cache_controller/controller_manager.py +535 -0
- lmcache/v1/cache_controller/controllers/__init__.py +11 -0
- lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
- lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
- lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
- lmcache/v1/cache_controller/executor.py +463 -0
- lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
- lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
- lmcache/v1/cache_controller/frontend/static/index.html +234 -0
- lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
- lmcache/v1/cache_controller/full_sync_sender.py +475 -0
- lmcache/v1/cache_controller/locks.py +149 -0
- lmcache/v1/cache_controller/message.py +828 -0
- lmcache/v1/cache_controller/observability.py +208 -0
- lmcache/v1/cache_controller/utils.py +679 -0
- lmcache/v1/cache_controller/worker.py +665 -0
- lmcache/v1/cache_engine.py +2058 -0
- lmcache/v1/cache_interface.py +19 -0
- lmcache/v1/check/__init__.py +74 -0
- lmcache/v1/check/check_mode_gen.py +86 -0
- lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
- lmcache/v1/check/check_mode_test_remote.py +155 -0
- lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
- lmcache/v1/check/utils.py +571 -0
- lmcache/v1/compute/__init__.py +2 -0
- lmcache/v1/compute/attention/__init__.py +0 -0
- lmcache/v1/compute/attention/abstract.py +39 -0
- lmcache/v1/compute/attention/flash_attn.py +129 -0
- lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
- lmcache/v1/compute/attention/metadata.py +85 -0
- lmcache/v1/compute/attention/utils.py +14 -0
- lmcache/v1/compute/blend/__init__.py +7 -0
- lmcache/v1/compute/blend/blender.py +168 -0
- lmcache/v1/compute/blend/metadata.py +34 -0
- lmcache/v1/compute/blend/utils.py +63 -0
- lmcache/v1/compute/models/__init__.py +0 -0
- lmcache/v1/compute/models/base.py +141 -0
- lmcache/v1/compute/models/llama.py +9 -0
- lmcache/v1/compute/models/qwen3.py +24 -0
- lmcache/v1/compute/models/utils.py +68 -0
- lmcache/v1/compute/positional_encoding.py +199 -0
- lmcache/v1/config.py +848 -0
- lmcache/v1/config_base.py +848 -0
- lmcache/v1/distributed/api.py +248 -0
- lmcache/v1/distributed/config.py +321 -0
- lmcache/v1/distributed/error.py +64 -0
- lmcache/v1/distributed/eviction.py +192 -0
- lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
- lmcache/v1/distributed/eviction_policy/factory.py +27 -0
- lmcache/v1/distributed/eviction_policy/lru.py +244 -0
- lmcache/v1/distributed/eviction_policy/noop.py +50 -0
- lmcache/v1/distributed/internal_api.py +170 -0
- lmcache/v1/distributed/l1_manager.py +835 -0
- lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
- lmcache/v1/distributed/l2_adapters/base.py +360 -0
- lmcache/v1/distributed/l2_adapters/config.py +385 -0
- lmcache/v1/distributed/l2_adapters/factory.py +205 -0
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
- lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
- lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
- lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
- lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
- lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
- lmcache/v1/distributed/memory_manager.py +179 -0
- lmcache/v1/distributed/storage_controller.py +39 -0
- lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
- lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
- lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
- lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
- lmcache/v1/distributed/storage_manager.py +532 -0
- lmcache/v1/event_manager.py +145 -0
- lmcache/v1/exceptions/__init__.py +16 -0
- lmcache/v1/gpu_connector/__init__.py +126 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
- lmcache/v1/gpu_connector/gpu_ops.py +85 -0
- lmcache/v1/gpu_connector/hpu_connector.py +326 -0
- lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
- lmcache/v1/gpu_connector/utils.py +890 -0
- lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
- lmcache/v1/health_monitor/__init__.py +1 -0
- lmcache/v1/health_monitor/base.py +587 -0
- lmcache/v1/health_monitor/checks/__init__.py +1 -0
- lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
- lmcache/v1/health_monitor/constants.py +36 -0
- lmcache/v1/internal_api_server/__init__.py +0 -0
- lmcache/v1/internal_api_server/api_registry.py +59 -0
- lmcache/v1/internal_api_server/api_server.py +120 -0
- lmcache/v1/internal_api_server/common/__init__.py +1 -0
- lmcache/v1/internal_api_server/common/env_api.py +22 -0
- lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
- lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
- lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
- lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
- lmcache/v1/internal_api_server/common/thread_api.py +63 -0
- lmcache/v1/internal_api_server/controller/__init__.py +1 -0
- lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
- lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
- lmcache/v1/internal_api_server/utils.py +43 -0
- lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
- lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
- lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
- lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
- lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
- lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
- lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
- lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
- lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
- lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
- lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
- lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
- lmcache/v1/kv_layer_groups.py +267 -0
- lmcache/v1/lazy_memory_allocator.py +284 -0
- lmcache/v1/lookup_client/__init__.py +25 -0
- lmcache/v1/lookup_client/abstract_client.py +77 -0
- lmcache/v1/lookup_client/async_lookup_message.py +50 -0
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
- lmcache/v1/lookup_client/factory.py +251 -0
- lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
- lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
- lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
- lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
- lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
- lmcache/v1/lookup_client/record_strategies/base.py +327 -0
- lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
- lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
- lmcache/v1/manager.py +539 -0
- lmcache/v1/memory_management.py +2619 -0
- lmcache/v1/metadata.py +114 -0
- lmcache/v1/mp_observability/AGENTS.override.md +21 -0
- lmcache/v1/mp_observability/README.md +204 -0
- lmcache/v1/mp_observability/config.py +340 -0
- lmcache/v1/mp_observability/event.py +100 -0
- lmcache/v1/mp_observability/event_bus.py +313 -0
- lmcache/v1/mp_observability/otel_init.py +145 -0
- lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
- lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
- lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
- lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
- lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
- lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
- lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
- lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
- lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
- lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
- lmcache/v1/mp_observability/trace/__init__.py +50 -0
- lmcache/v1/mp_observability/trace/codecs.py +255 -0
- lmcache/v1/mp_observability/trace/decorator.py +147 -0
- lmcache/v1/mp_observability/trace/format.py +132 -0
- lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
- lmcache/v1/mp_observability/trace/reader.py +167 -0
- lmcache/v1/mp_observability/trace/recorder.py +300 -0
- lmcache/v1/multiprocess/__init__.py +0 -0
- lmcache/v1/multiprocess/affinity_pool.py +102 -0
- lmcache/v1/multiprocess/blend_server_v2.py +891 -0
- lmcache/v1/multiprocess/config.py +253 -0
- lmcache/v1/multiprocess/custom_types.py +281 -0
- lmcache/v1/multiprocess/futures.py +194 -0
- lmcache/v1/multiprocess/gpu_context.py +511 -0
- lmcache/v1/multiprocess/http_server.py +235 -0
- lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
- lmcache/v1/multiprocess/mq.py +732 -0
- lmcache/v1/multiprocess/protocol.py +86 -0
- lmcache/v1/multiprocess/protocols/README.md +213 -0
- lmcache/v1/multiprocess/protocols/__init__.py +127 -0
- lmcache/v1/multiprocess/protocols/base.py +89 -0
- lmcache/v1/multiprocess/protocols/blend.py +109 -0
- lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
- lmcache/v1/multiprocess/protocols/controller.py +53 -0
- lmcache/v1/multiprocess/protocols/debug.py +34 -0
- lmcache/v1/multiprocess/protocols/engine.py +146 -0
- lmcache/v1/multiprocess/protocols/observability.py +39 -0
- lmcache/v1/multiprocess/server.py +1134 -0
- lmcache/v1/multiprocess/session.py +190 -0
- lmcache/v1/multiprocess/token_hasher.py +441 -0
- lmcache/v1/offload_server/__init__.py +17 -0
- lmcache/v1/offload_server/abstract_server.py +37 -0
- lmcache/v1/offload_server/message.py +30 -0
- lmcache/v1/offload_server/zmq_server.py +122 -0
- lmcache/v1/periodic_thread.py +579 -0
- lmcache/v1/pin_monitor.py +246 -0
- lmcache/v1/plugin/__init__.py +0 -0
- lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
- lmcache/v1/protocol.py +317 -0
- lmcache/v1/rpc/__init__.py +17 -0
- lmcache/v1/rpc/transport.py +105 -0
- lmcache/v1/rpc/zmq_transport.py +213 -0
- lmcache/v1/rpc_utils.py +165 -0
- lmcache/v1/server/__init__.py +2 -0
- lmcache/v1/server/__main__.py +170 -0
- lmcache/v1/server/storage_backend/__init__.py +21 -0
- lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
- lmcache/v1/server/storage_backend/local_backend.py +75 -0
- lmcache/v1/server/utils.py +21 -0
- lmcache/v1/standalone/__init__.py +1 -0
- lmcache/v1/standalone/__main__.py +583 -0
- lmcache/v1/standalone/manager.py +80 -0
- lmcache/v1/standalone/standalone_service_factory.py +86 -0
- lmcache/v1/storage_backend/__init__.py +313 -0
- lmcache/v1/storage_backend/abstract_backend.py +445 -0
- lmcache/v1/storage_backend/audit_backend.py +233 -0
- lmcache/v1/storage_backend/batched_message_sender.py +222 -0
- lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
- lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
- lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
- lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
- lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
- lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
- lmcache/v1/storage_backend/connector/__init__.py +443 -0
- lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
- lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
- lmcache/v1/storage_backend/connector/base_connector.py +379 -0
- lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
- lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
- lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
- lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
- lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
- lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
- lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
- lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
- lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
- lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
- lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
- lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
- lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
- lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
- lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
- lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
- lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
- lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
- lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
- lmcache/v1/storage_backend/gds_backend.py +1199 -0
- lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
- lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
- lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
- lmcache/v1/storage_backend/local_disk_backend.py +656 -0
- lmcache/v1/storage_backend/maru_backend.py +734 -0
- lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
- lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
- lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
- lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
- lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
- lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
- lmcache/v1/storage_backend/p2p_backend.py +788 -0
- lmcache/v1/storage_backend/path_sharder.py +117 -0
- lmcache/v1/storage_backend/pd_backend.py +646 -0
- lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
- lmcache/v1/storage_backend/remote_backend.py +624 -0
- lmcache/v1/storage_backend/resp_client.py +227 -0
- lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
- lmcache/v1/storage_backend/storage_manager.py +1352 -0
- lmcache/v1/system_detection.py +110 -0
- lmcache/v1/token_database.py +551 -0
- lmcache/v1/transfer_channel/__init__.py +83 -0
- lmcache/v1/transfer_channel/abstract.py +285 -0
- lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
- lmcache/v1/transfer_channel/nixl_channel.py +639 -0
- lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
- lmcache/v1/transfer_channel/transfer_utils.py +63 -0
- lmcache/v1/utils/__init__.py +1 -0
- lmcache/v1/utils/bloom_filter.py +109 -0
- lmcache/v1/utils/cache_utils.py +125 -0
- lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
- lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
- lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
- lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
- lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
- lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Hierarchical metrics collector with handler-based output.
|
|
3
|
+
|
|
4
|
+
Example usage::
|
|
5
|
+
|
|
6
|
+
from lmcache.cli.metrics import Metrics
|
|
7
|
+
|
|
8
|
+
metrics = Metrics(title="Bench KV Cache Result (30s)")
|
|
9
|
+
|
|
10
|
+
# Sectioned metrics
|
|
11
|
+
metrics.add_section("ops", "Operations (ops/s)")
|
|
12
|
+
metrics["ops"].add("store", "Store", 41.3)
|
|
13
|
+
metrics["ops"].add("retrieve", "Retrieve", 127.3)
|
|
14
|
+
|
|
15
|
+
# Top-level (flat) metrics
|
|
16
|
+
metrics.add("status", "Status", "OK")
|
|
17
|
+
|
|
18
|
+
metrics.emit()
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# Standard
|
|
22
|
+
from typing import Any, Optional
|
|
23
|
+
|
|
24
|
+
# First Party
|
|
25
|
+
from lmcache.cli.metrics.handler import FileHandler, MetricsHandler
|
|
26
|
+
from lmcache.cli.metrics.section import Section, sections_to_dict
|
|
27
|
+
from lmcache.logging import init_logger
|
|
28
|
+
|
|
29
|
+
logger = init_logger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Metrics:
|
|
33
|
+
"""Hierarchical metrics collector with handler-based output.
|
|
34
|
+
|
|
35
|
+
Handlers are registered via :meth:`add_handler` and triggered
|
|
36
|
+
together by :meth:`emit`. ``BaseCommand`` sets up default
|
|
37
|
+
handlers automatically, so command authors typically only need
|
|
38
|
+
to build metrics and call :meth:`emit`.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
title: Report title shown in the header.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, title: str) -> None:
|
|
45
|
+
self._title = title
|
|
46
|
+
self._sections: list[Section] = []
|
|
47
|
+
self._section_map: dict[Optional[str], Section] = {}
|
|
48
|
+
self._handlers: list[MetricsHandler] = []
|
|
49
|
+
|
|
50
|
+
def title(self, title: str) -> None:
|
|
51
|
+
"""Set the report title.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
title: New report title shown in the header.
|
|
55
|
+
"""
|
|
56
|
+
self._title = title
|
|
57
|
+
|
|
58
|
+
# -- Handler management -------------------------------------------------
|
|
59
|
+
|
|
60
|
+
def add_handler(self, handler: MetricsHandler) -> None:
|
|
61
|
+
"""Register a handler.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
handler: The handler to add.
|
|
65
|
+
"""
|
|
66
|
+
self._handlers.append(handler)
|
|
67
|
+
|
|
68
|
+
# -- Section management -------------------------------------------------
|
|
69
|
+
|
|
70
|
+
def add_section(self, key: str, label: str) -> Section:
|
|
71
|
+
"""Add a named section.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
key: Machine-readable section key (used in JSON output and
|
|
75
|
+
for ``metrics["key"]`` access).
|
|
76
|
+
label: Human-readable label (used in terminal output).
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The newly created ``Section``.
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
ValueError: If a section with the same *key* already exists.
|
|
83
|
+
"""
|
|
84
|
+
if key in self._section_map:
|
|
85
|
+
raise ValueError(f"Section {key!r} already exists")
|
|
86
|
+
section = Section(key, label)
|
|
87
|
+
self._sections.append(section)
|
|
88
|
+
self._section_map[key] = section
|
|
89
|
+
return section
|
|
90
|
+
|
|
91
|
+
def add_list_section(self, group: str, key: str, label: str) -> Section:
|
|
92
|
+
"""Add a section that belongs to a list group.
|
|
93
|
+
|
|
94
|
+
In terminal output, renders as a normal section with *label* as
|
|
95
|
+
the header. In JSON output, sections sharing the same *group*
|
|
96
|
+
are collected into a list: ``"group": [{...}, {...}]``.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
group: The JSON key for the list (e.g., ``"models"``).
|
|
100
|
+
key: Unique machine key for this section instance.
|
|
101
|
+
label: Human-readable label (used in terminal output).
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
The newly created ``Section``.
|
|
105
|
+
"""
|
|
106
|
+
if key in self._section_map:
|
|
107
|
+
raise ValueError(f"Section {key!r} already exists")
|
|
108
|
+
section = Section(key, label, list_group=group)
|
|
109
|
+
self._sections.append(section)
|
|
110
|
+
self._section_map[key] = section
|
|
111
|
+
return section
|
|
112
|
+
|
|
113
|
+
def __getitem__(self, key: str) -> Section:
|
|
114
|
+
"""Return the section registered under *key*.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
KeyError: If ``add_section(key, ...)`` was not called first.
|
|
118
|
+
"""
|
|
119
|
+
return self._section_map[key]
|
|
120
|
+
|
|
121
|
+
# -- Flat (top-level) metrics -------------------------------------------
|
|
122
|
+
|
|
123
|
+
def _default_section(self) -> Section:
|
|
124
|
+
"""Return the unnamed default section, creating it on first use."""
|
|
125
|
+
if None not in self._section_map:
|
|
126
|
+
section = Section(None, None)
|
|
127
|
+
# Insert at the beginning so flat metrics appear first
|
|
128
|
+
self._sections.insert(0, section)
|
|
129
|
+
self._section_map[None] = section
|
|
130
|
+
return self._section_map[None]
|
|
131
|
+
|
|
132
|
+
def add(self, key: str, label: str, value: Any) -> None:
|
|
133
|
+
"""Record a top-level metric (not inside any named section).
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
key: Machine-readable key (used in JSON output).
|
|
137
|
+
label: Human-readable label (used in terminal output).
|
|
138
|
+
value: Metric value.
|
|
139
|
+
"""
|
|
140
|
+
self._default_section().add(key, label, value)
|
|
141
|
+
|
|
142
|
+
# -- Output -------------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
def emit(self) -> None:
|
|
145
|
+
"""Trigger all registered handlers."""
|
|
146
|
+
for handler in self._handlers:
|
|
147
|
+
handler.emit(self._title, self._sections)
|
|
148
|
+
for handler in self._handlers:
|
|
149
|
+
if isinstance(handler, FileHandler):
|
|
150
|
+
logger.info("Results saved to %s", handler.path)
|
|
151
|
+
|
|
152
|
+
def to_dict(self) -> dict[str, Any]:
|
|
153
|
+
"""Return metrics as a JSON-serialisable dictionary.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
A dict with ``"title"`` and ``"metrics"`` keys. Named
|
|
157
|
+
sections become nested dicts keyed by machine key. The
|
|
158
|
+
unnamed default section's entries are placed at the top
|
|
159
|
+
level of ``"metrics"``.
|
|
160
|
+
"""
|
|
161
|
+
return sections_to_dict(self._title, self._sections)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Section — a named group of metric entries."""
|
|
3
|
+
|
|
4
|
+
# Standard
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Section:
|
|
9
|
+
"""A named group of metrics.
|
|
10
|
+
|
|
11
|
+
Each entry has a machine ``key`` (used in JSON), a human-readable
|
|
12
|
+
``label`` (used in terminal output), and a ``value``.
|
|
13
|
+
|
|
14
|
+
Sections with the same :attr:`list_group` are collected into a
|
|
15
|
+
JSON list under that key (e.g., ``"models": [{...}, {...}]``).
|
|
16
|
+
In terminal output they render as normal independent sections.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
key: Optional[str],
|
|
22
|
+
label: Optional[str],
|
|
23
|
+
list_group: Optional[str] = None,
|
|
24
|
+
) -> None:
|
|
25
|
+
self.key = key
|
|
26
|
+
self.label = label
|
|
27
|
+
self.list_group = list_group
|
|
28
|
+
self.entries: list[tuple[str, str, Any]] = []
|
|
29
|
+
|
|
30
|
+
def add(self, key: str, label: str, value: Any) -> None:
|
|
31
|
+
"""Record a metric in this section.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
key: Machine-readable key (used in JSON output).
|
|
35
|
+
label: Human-readable label (used in terminal output).
|
|
36
|
+
value: Metric value. Floats are formatted to 2 decimal
|
|
37
|
+
places on terminal output; strings are printed as-is.
|
|
38
|
+
"""
|
|
39
|
+
self.entries.append((key, label, value))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def sections_to_dict(
|
|
43
|
+
title: str,
|
|
44
|
+
sections: list[Section],
|
|
45
|
+
) -> dict[str, Any]:
|
|
46
|
+
"""Convert a title and sections to a JSON-serialisable dictionary.
|
|
47
|
+
|
|
48
|
+
Named sections become nested dicts keyed by machine key. The
|
|
49
|
+
unnamed default section's entries are placed at the top level
|
|
50
|
+
of ``"metrics"``.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
title: The report title.
|
|
54
|
+
sections: Ordered list of ``Section`` objects.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
A dict with ``"title"`` and ``"metrics"`` keys.
|
|
58
|
+
"""
|
|
59
|
+
metrics: dict[str, Any] = {}
|
|
60
|
+
list_groups: dict[str, list[dict[str, Any]]] = {}
|
|
61
|
+
for section in sections:
|
|
62
|
+
if section.key is None:
|
|
63
|
+
for key, _label, value in section.entries:
|
|
64
|
+
metrics[key] = value
|
|
65
|
+
elif section.list_group is not None:
|
|
66
|
+
section_dict: dict[str, Any] = {}
|
|
67
|
+
for key, _label, value in section.entries:
|
|
68
|
+
section_dict[key] = value
|
|
69
|
+
list_groups.setdefault(section.list_group, []).append(section_dict)
|
|
70
|
+
else:
|
|
71
|
+
section_dict = {}
|
|
72
|
+
for key, _label, value in section.entries:
|
|
73
|
+
section_dict[key] = value
|
|
74
|
+
metrics[section.key] = section_dict
|
|
75
|
+
for group_key, items in list_groups.items():
|
|
76
|
+
metrics[group_key] = items
|
|
77
|
+
return {"title": title, "metrics": metrics}
|
lmcache/connections.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# This file is copied from the vLLM project (https://github.com/vllm-project/vllm).
|
|
3
|
+
# Original source file: [vllm/vllm/connections.py]
|
|
4
|
+
# License: [Apache License 2.0]
|
|
5
|
+
# Modifications: header name
|
|
6
|
+
|
|
7
|
+
# Standard
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Mapping, MutableMapping, Optional
|
|
10
|
+
from urllib.parse import urlparse
|
|
11
|
+
|
|
12
|
+
# Third Party
|
|
13
|
+
import aiohttp
|
|
14
|
+
import requests
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class HTTPConnection:
|
|
18
|
+
"""Helper class to send HTTP requests."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, *, reuse_client: bool = True) -> None:
|
|
21
|
+
super().__init__()
|
|
22
|
+
|
|
23
|
+
self.reuse_client = reuse_client
|
|
24
|
+
|
|
25
|
+
self._sync_client: Optional[requests.Session] = None
|
|
26
|
+
self._async_client: Optional[aiohttp.ClientSession] = None
|
|
27
|
+
|
|
28
|
+
def get_sync_client(self) -> requests.Session:
|
|
29
|
+
if self._sync_client is None or not self.reuse_client:
|
|
30
|
+
self._sync_client = requests.Session()
|
|
31
|
+
|
|
32
|
+
return self._sync_client
|
|
33
|
+
|
|
34
|
+
# NOTE: We intentionally use an async function even though it is not
|
|
35
|
+
# required, so that the client is only accessible inside async event loop
|
|
36
|
+
async def get_async_client(self) -> aiohttp.ClientSession:
|
|
37
|
+
if self._async_client is None or not self.reuse_client:
|
|
38
|
+
self._async_client = aiohttp.ClientSession()
|
|
39
|
+
|
|
40
|
+
return self._async_client
|
|
41
|
+
|
|
42
|
+
def _validate_http_url(self, url: str):
|
|
43
|
+
parsed_url = urlparse(url)
|
|
44
|
+
|
|
45
|
+
if parsed_url.scheme not in ("http", "https"):
|
|
46
|
+
raise ValueError(
|
|
47
|
+
"Invalid HTTP URL: A valid HTTP URL must have scheme 'http' or 'https'."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def _headers(self, **extras: str) -> MutableMapping[str, str]:
|
|
51
|
+
return {"User-Agent": "LMCache", **extras}
|
|
52
|
+
|
|
53
|
+
def get_response(
|
|
54
|
+
self,
|
|
55
|
+
url: str,
|
|
56
|
+
*,
|
|
57
|
+
stream: bool = False,
|
|
58
|
+
timeout: Optional[float] = None,
|
|
59
|
+
extra_headers: Optional[Mapping[str, str]] = None,
|
|
60
|
+
):
|
|
61
|
+
self._validate_http_url(url)
|
|
62
|
+
|
|
63
|
+
client = self.get_sync_client()
|
|
64
|
+
extra_headers = extra_headers or {}
|
|
65
|
+
|
|
66
|
+
return client.get(
|
|
67
|
+
url,
|
|
68
|
+
headers=self._headers(**extra_headers),
|
|
69
|
+
stream=stream,
|
|
70
|
+
timeout=timeout,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
async def get_async_response(
|
|
74
|
+
self,
|
|
75
|
+
url: str,
|
|
76
|
+
*,
|
|
77
|
+
timeout: Optional[float] = None,
|
|
78
|
+
extra_headers: Optional[Mapping[str, str]] = None,
|
|
79
|
+
):
|
|
80
|
+
self._validate_http_url(url)
|
|
81
|
+
|
|
82
|
+
client = await self.get_async_client()
|
|
83
|
+
extra_headers = extra_headers or {}
|
|
84
|
+
|
|
85
|
+
return client.get(url, headers=self._headers(**extra_headers), timeout=timeout)
|
|
86
|
+
|
|
87
|
+
def get_bytes(self, url: str, *, timeout: Optional[float] = None) -> bytes:
|
|
88
|
+
with self.get_response(url, timeout=timeout) as r:
|
|
89
|
+
r.raise_for_status()
|
|
90
|
+
|
|
91
|
+
return r.content
|
|
92
|
+
|
|
93
|
+
async def async_get_bytes(
|
|
94
|
+
self,
|
|
95
|
+
url: str,
|
|
96
|
+
*,
|
|
97
|
+
timeout: Optional[float] = None,
|
|
98
|
+
) -> bytes:
|
|
99
|
+
async with await self.get_async_response(url, timeout=timeout) as r:
|
|
100
|
+
r.raise_for_status()
|
|
101
|
+
|
|
102
|
+
return await r.read()
|
|
103
|
+
|
|
104
|
+
def get_text(self, url: str, *, timeout: Optional[float] = None) -> str:
|
|
105
|
+
with self.get_response(url, timeout=timeout) as r:
|
|
106
|
+
r.raise_for_status()
|
|
107
|
+
|
|
108
|
+
return r.text
|
|
109
|
+
|
|
110
|
+
async def async_get_text(
|
|
111
|
+
self,
|
|
112
|
+
url: str,
|
|
113
|
+
*,
|
|
114
|
+
timeout: Optional[float] = None,
|
|
115
|
+
) -> str:
|
|
116
|
+
async with await self.get_async_response(url, timeout=timeout) as r:
|
|
117
|
+
r.raise_for_status()
|
|
118
|
+
|
|
119
|
+
return await r.text()
|
|
120
|
+
|
|
121
|
+
def get_json(self, url: str, *, timeout: Optional[float] = None) -> str:
|
|
122
|
+
with self.get_response(url, timeout=timeout) as r:
|
|
123
|
+
r.raise_for_status()
|
|
124
|
+
|
|
125
|
+
return r.json()
|
|
126
|
+
|
|
127
|
+
async def async_get_json(
|
|
128
|
+
self,
|
|
129
|
+
url: str,
|
|
130
|
+
*,
|
|
131
|
+
timeout: Optional[float] = None,
|
|
132
|
+
) -> str:
|
|
133
|
+
async with await self.get_async_response(url, timeout=timeout) as r:
|
|
134
|
+
r.raise_for_status()
|
|
135
|
+
|
|
136
|
+
return await r.json()
|
|
137
|
+
|
|
138
|
+
def download_file(
|
|
139
|
+
self,
|
|
140
|
+
url: str,
|
|
141
|
+
save_path: Path,
|
|
142
|
+
*,
|
|
143
|
+
timeout: Optional[float] = None,
|
|
144
|
+
chunk_size: int = 128,
|
|
145
|
+
) -> Path:
|
|
146
|
+
with self.get_response(url, timeout=timeout) as r:
|
|
147
|
+
r.raise_for_status()
|
|
148
|
+
|
|
149
|
+
with save_path.open("wb") as f:
|
|
150
|
+
for chunk in r.iter_content(chunk_size):
|
|
151
|
+
f.write(chunk)
|
|
152
|
+
|
|
153
|
+
return save_path
|
|
154
|
+
|
|
155
|
+
async def async_download_file(
|
|
156
|
+
self,
|
|
157
|
+
url: str,
|
|
158
|
+
save_path: Path,
|
|
159
|
+
*,
|
|
160
|
+
timeout: Optional[float] = None,
|
|
161
|
+
chunk_size: int = 128,
|
|
162
|
+
) -> Path:
|
|
163
|
+
async with await self.get_async_response(url, timeout=timeout) as r:
|
|
164
|
+
r.raise_for_status()
|
|
165
|
+
|
|
166
|
+
with save_path.open("wb") as f:
|
|
167
|
+
async for chunk in r.content.iter_chunked(chunk_size):
|
|
168
|
+
f.write(chunk)
|
|
169
|
+
|
|
170
|
+
return save_path
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
global_http_connection = HTTPConnection()
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
BaseServiceFactory: Abstract interface for creating LMCache service components.
|
|
4
|
+
|
|
5
|
+
Each serving engine integration (e.g., vLLM) should implement a concrete
|
|
6
|
+
ServiceFactory that determines which components to create for each role.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Standard
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from typing import TYPE_CHECKING, Optional, Union
|
|
12
|
+
|
|
13
|
+
# First Party
|
|
14
|
+
from lmcache.logging import init_logger
|
|
15
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
16
|
+
from lmcache.v1.health_monitor.base import HealthMonitor
|
|
17
|
+
from lmcache.v1.health_monitor.constants import (
|
|
18
|
+
DEFAULT_PING_INTERVAL,
|
|
19
|
+
PING_INTERVAL_CONFIG_KEY,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
# First Party
|
|
24
|
+
from lmcache.observability import PrometheusLogger
|
|
25
|
+
from lmcache.v1.cache_engine import LMCacheEngine
|
|
26
|
+
from lmcache.v1.internal_api_server.api_server import InternalAPIServer
|
|
27
|
+
from lmcache.v1.lookup_client.abstract_client import LookupClientInterface
|
|
28
|
+
from lmcache.v1.lookup_client.lmcache_async_lookup_client import (
|
|
29
|
+
LMCacheAsyncLookupServer,
|
|
30
|
+
)
|
|
31
|
+
from lmcache.v1.lookup_client.lmcache_lookup_client import LMCacheLookupServer
|
|
32
|
+
from lmcache.v1.manager import LMCacheManager
|
|
33
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
34
|
+
from lmcache.v1.offload_server.zmq_server import ZMQOffloadServer
|
|
35
|
+
from lmcache.v1.plugin.runtime_plugin_launcher import RuntimePluginLauncher
|
|
36
|
+
|
|
37
|
+
logger = init_logger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class BaseServiceFactory(ABC):
|
|
41
|
+
"""Abstract base for creating LMCache service components.
|
|
42
|
+
|
|
43
|
+
Subclasses must implement all methods to provide the appropriate
|
|
44
|
+
components for their serving engine integration.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def get_engine_instance_id(self) -> str:
|
|
49
|
+
"""Return the instance_id used to register the engine with
|
|
50
|
+
LMCacheEngineBuilder. Used by LMCacheManager for engine destruction."""
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def get_or_create_metadata(self) -> Optional["LMCacheMetadata"]:
|
|
55
|
+
raise NotImplementedError
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def get_or_create_lmcache_engine(self) -> Optional["LMCacheEngine"]:
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def maybe_create_lookup_client(self) -> Optional["LookupClientInterface"]:
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def maybe_create_prometheus_logger(self) -> Optional["PrometheusLogger"]:
|
|
67
|
+
raise NotImplementedError
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
def maybe_create_lookup_server(
|
|
71
|
+
self,
|
|
72
|
+
) -> Optional[Union["LMCacheLookupServer", "LMCacheAsyncLookupServer"]]:
|
|
73
|
+
raise NotImplementedError
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def maybe_create_offload_server(self) -> Optional["ZMQOffloadServer"]:
|
|
77
|
+
raise NotImplementedError
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def maybe_create_runtime_plugin_launcher(
|
|
81
|
+
self,
|
|
82
|
+
) -> Optional["RuntimePluginLauncher"]:
|
|
83
|
+
raise NotImplementedError
|
|
84
|
+
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def maybe_create_internal_api_server(
|
|
87
|
+
self, lmcache_manager: "LMCacheManager"
|
|
88
|
+
) -> Optional["InternalAPIServer"]:
|
|
89
|
+
raise NotImplementedError
|
|
90
|
+
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def maybe_create_health_monitor(
|
|
93
|
+
self, lmcache_manager: "LMCacheManager"
|
|
94
|
+
) -> Optional[HealthMonitor]:
|
|
95
|
+
raise NotImplementedError
|
|
96
|
+
|
|
97
|
+
def _create_health_monitor(
|
|
98
|
+
self,
|
|
99
|
+
lmcache_manager: "LMCacheManager",
|
|
100
|
+
config: LMCacheEngineConfig,
|
|
101
|
+
engine: Optional["LMCacheEngine"] = None,
|
|
102
|
+
) -> HealthMonitor:
|
|
103
|
+
"""Create, configure, and start the health monitor.
|
|
104
|
+
|
|
105
|
+
Shared implementation used by subclass maybe_create_health_monitor.
|
|
106
|
+
"""
|
|
107
|
+
# First Party
|
|
108
|
+
from lmcache.observability import PrometheusLogger
|
|
109
|
+
from lmcache.v1.periodic_thread import (
|
|
110
|
+
PeriodicThreadRegistry,
|
|
111
|
+
ThreadLevel,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
ping_interval = config.get_extra_config_value(
|
|
115
|
+
PING_INTERVAL_CONFIG_KEY, DEFAULT_PING_INTERVAL
|
|
116
|
+
)
|
|
117
|
+
health_monitor = HealthMonitor(
|
|
118
|
+
manager=lmcache_manager,
|
|
119
|
+
ping_interval=ping_interval,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if engine is not None:
|
|
123
|
+
engine.set_health_monitor(health_monitor)
|
|
124
|
+
|
|
125
|
+
health_monitor.start()
|
|
126
|
+
logger.info("Health monitor initialized and started")
|
|
127
|
+
|
|
128
|
+
prometheus_logger = PrometheusLogger.GetInstanceOrNone()
|
|
129
|
+
if prometheus_logger is not None:
|
|
130
|
+
prometheus_logger.lmcache_is_healthy.set_function(
|
|
131
|
+
lambda: 1 if lmcache_manager.is_healthy() else 0
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
registry = PeriodicThreadRegistry.get_instance()
|
|
135
|
+
|
|
136
|
+
prometheus_logger.periodic_threads_total_count.set_function(
|
|
137
|
+
lambda: len(registry.get_all())
|
|
138
|
+
)
|
|
139
|
+
prometheus_logger.periodic_threads_running_count.set_function(
|
|
140
|
+
lambda: registry.get_running_count()
|
|
141
|
+
)
|
|
142
|
+
prometheus_logger.periodic_threads_active_count.set_function(
|
|
143
|
+
lambda: registry.get_active_count()
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
for level in ThreadLevel:
|
|
147
|
+
level_name = level.value
|
|
148
|
+
total_attr = f"periodic_threads_{level_name}_total"
|
|
149
|
+
running_attr = f"periodic_threads_{level_name}_running"
|
|
150
|
+
active_attr = f"periodic_threads_{level_name}_active"
|
|
151
|
+
|
|
152
|
+
if hasattr(prometheus_logger, total_attr):
|
|
153
|
+
getattr(prometheus_logger, total_attr).set_function(
|
|
154
|
+
lambda lvl=level: registry.get_count_by_level(lvl)["total"]
|
|
155
|
+
)
|
|
156
|
+
if hasattr(prometheus_logger, running_attr):
|
|
157
|
+
getattr(prometheus_logger, running_attr).set_function(
|
|
158
|
+
lambda lvl=level: registry.get_count_by_level(lvl)["running"]
|
|
159
|
+
)
|
|
160
|
+
if hasattr(prometheus_logger, active_attr):
|
|
161
|
+
getattr(prometheus_logger, active_attr).set_function(
|
|
162
|
+
lambda lvl=level: registry.get_count_by_level(lvl)["active"]
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return health_monitor
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Abstract base class for request telemetry.
|
|
4
|
+
|
|
5
|
+
This module provides the interface for tracking request-level events
|
|
6
|
+
in LMCache, such as when a request finishes and its associated async
|
|
7
|
+
save operations complete.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Standard
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class RequestTelemetry(ABC):
|
|
16
|
+
"""
|
|
17
|
+
Abstract base class for request telemetry.
|
|
18
|
+
|
|
19
|
+
This class defines the interface for capturing request-level telemetry
|
|
20
|
+
events. Implementations can log events, emit metrics, or perform other
|
|
21
|
+
actions when specific request lifecycle events occur.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def __init__(self, config: dict[str, Any]) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def on_request_store_finished(
|
|
30
|
+
self,
|
|
31
|
+
request_ids_set: set[str],
|
|
32
|
+
model_name: str,
|
|
33
|
+
world_size: int,
|
|
34
|
+
kv_rank: int,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Callback when request finishes AND all its KV cache store ops completes.
|
|
38
|
+
|
|
39
|
+
This method ensures that request_ids_set is not empty.
|
|
40
|
+
|
|
41
|
+
Technically this function is implemented by inspecting the return value
|
|
42
|
+
of `get_finished` method.
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def close(self) -> None:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
def __del__(self) -> None:
|
|
51
|
+
self.close()
|