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,113 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Factory for creating request telemetry reporters based on configuration.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from collections.abc import Callable
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
9
|
+
import importlib
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
# First Party
|
|
13
|
+
from lmcache.integration.request_telemetry.base import RequestTelemetry
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RequestTelemetryFactory:
|
|
17
|
+
"""Factory for creating request telemetry reporters."""
|
|
18
|
+
|
|
19
|
+
_registry: dict[str, Callable[[], type["RequestTelemetry"]]] = {}
|
|
20
|
+
_instances: dict[str, "RequestTelemetry"] = {}
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def register(cls, name: str, module_path: str, class_name: str) -> None:
|
|
24
|
+
"""Register a telemetry reporter with lazy-loading module and class name.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
name: The name to register the telemetry reporter under.
|
|
28
|
+
module_path: The module path to import the class from.
|
|
29
|
+
class_name: The class name to import from the module.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
ValueError: If a reporter with the same name is already registered.
|
|
33
|
+
"""
|
|
34
|
+
if name in cls._registry:
|
|
35
|
+
raise ValueError(f"Telemetry reporter '{name}' is already registered.")
|
|
36
|
+
|
|
37
|
+
def loader() -> type["RequestTelemetry"]:
|
|
38
|
+
module = importlib.import_module(module_path)
|
|
39
|
+
return getattr(module, class_name)
|
|
40
|
+
|
|
41
|
+
cls._registry[name] = loader
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def create(
|
|
45
|
+
cls,
|
|
46
|
+
telemetry_type: Optional[str] = None,
|
|
47
|
+
config: Optional[dict[str, Any]] = None,
|
|
48
|
+
use_singleton: bool = True,
|
|
49
|
+
) -> "RequestTelemetry":
|
|
50
|
+
"""Create a request telemetry reporter based on the specified type.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
telemetry_type: The type of telemetry reporter to create.
|
|
54
|
+
If None, defaults to "noop".
|
|
55
|
+
Supported values: "noop", "fastapi".
|
|
56
|
+
config: Optional dict of configuration options passed to the reporter.
|
|
57
|
+
Each reporter defines its own expected keys.
|
|
58
|
+
use_singleton: If True, returns a cached singleton instance.
|
|
59
|
+
If False, creates a new instance each time.
|
|
60
|
+
Note: Singleton is keyed by telemetry_type only.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
A RequestTelemetry instance.
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
ValueError: If an unsupported telemetry type is specified.
|
|
67
|
+
"""
|
|
68
|
+
if telemetry_type is None:
|
|
69
|
+
telemetry_type = "noop"
|
|
70
|
+
|
|
71
|
+
telemetry_type = telemetry_type.lower()
|
|
72
|
+
|
|
73
|
+
if telemetry_type not in cls._registry:
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"Unsupported request telemetry type: {telemetry_type}. "
|
|
76
|
+
f"Supported types: {list(cls._registry.keys())}"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if use_singleton and telemetry_type in cls._instances:
|
|
80
|
+
return cls._instances[telemetry_type]
|
|
81
|
+
|
|
82
|
+
if config is None:
|
|
83
|
+
config = {}
|
|
84
|
+
|
|
85
|
+
telemetry_cls = cls._registry[telemetry_type]()
|
|
86
|
+
instance = telemetry_cls(config)
|
|
87
|
+
|
|
88
|
+
if use_singleton:
|
|
89
|
+
cls._instances[telemetry_type] = instance
|
|
90
|
+
|
|
91
|
+
return instance
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def get_registered_types(cls) -> list[str]:
|
|
95
|
+
"""Get a list of all registered telemetry types."""
|
|
96
|
+
return list(cls._registry.keys())
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Register telemetry types here.
|
|
100
|
+
# The registration should not be done in each individual file, as we want to
|
|
101
|
+
# only load the files corresponding to the current telemetry type.
|
|
102
|
+
|
|
103
|
+
RequestTelemetryFactory.register(
|
|
104
|
+
"noop",
|
|
105
|
+
"lmcache.integration.request_telemetry.noop",
|
|
106
|
+
"NoOpRequestTelemetry",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
RequestTelemetryFactory.register(
|
|
110
|
+
"fastapi",
|
|
111
|
+
"lmcache.integration.request_telemetry.fastapi",
|
|
112
|
+
"FastAPIRequestTelemetry",
|
|
113
|
+
)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
FastAPI-based request telemetry reporter.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
+
from typing import Any
|
|
9
|
+
from urllib.error import URLError
|
|
10
|
+
from urllib.request import Request, urlopen
|
|
11
|
+
import json
|
|
12
|
+
import threading
|
|
13
|
+
|
|
14
|
+
# First Party
|
|
15
|
+
from lmcache.integration.request_telemetry.base import RequestTelemetry
|
|
16
|
+
from lmcache.logging import init_logger
|
|
17
|
+
|
|
18
|
+
logger = init_logger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class FastAPIRequestTelemetry(RequestTelemetry):
|
|
22
|
+
"""
|
|
23
|
+
FastAPI-based request telemetry reporter.
|
|
24
|
+
|
|
25
|
+
Sends telemetry events to a FastAPI server endpoint asynchronously
|
|
26
|
+
using a thread pool to avoid blocking the main execution path.
|
|
27
|
+
|
|
28
|
+
Config dict keys:
|
|
29
|
+
endpoint: The FastAPI endpoint URL to send telemetry events to. (required)
|
|
30
|
+
timeout: Timeout in seconds for HTTP requests. Defaults to 5.0.
|
|
31
|
+
max_workers: Maximum number of threads for async HTTP requests.
|
|
32
|
+
Defaults to 2.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, config: dict[str, Any]) -> None:
|
|
36
|
+
endpoint = config.get("endpoint", None)
|
|
37
|
+
if endpoint is None:
|
|
38
|
+
raise ValueError(
|
|
39
|
+
"FastAPIRequestTelemetry requires setting endpoint. "
|
|
40
|
+
"Please set LMCACHE_REQUEST_TELEMETRY_ENDPOINT envvar."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
self._endpoint = endpoint
|
|
44
|
+
self._timeout = config.get("timeout", 5.0)
|
|
45
|
+
self._executor = ThreadPoolExecutor(
|
|
46
|
+
max_workers=config.get("max_workers", 2),
|
|
47
|
+
thread_name_prefix="fastapi-telemetry",
|
|
48
|
+
)
|
|
49
|
+
self._lock = threading.Lock()
|
|
50
|
+
self._closed = False
|
|
51
|
+
|
|
52
|
+
logger.info(
|
|
53
|
+
"LMCache FastAPIRequestTelemetry initialized with endpoint: %s",
|
|
54
|
+
self._endpoint,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def on_request_store_finished(
|
|
58
|
+
self,
|
|
59
|
+
request_ids_set: set[str],
|
|
60
|
+
model_name: str,
|
|
61
|
+
world_size: int,
|
|
62
|
+
kv_rank: int,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Send request store finished event to the FastAPI endpoint."""
|
|
65
|
+
if self._closed:
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
payload = {
|
|
69
|
+
"event": "request_store_finished",
|
|
70
|
+
"request_ids_set": list(request_ids_set),
|
|
71
|
+
"model_name": model_name,
|
|
72
|
+
"world_size": world_size,
|
|
73
|
+
"kv_rank": kv_rank,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Submit async HTTP request
|
|
77
|
+
self._executor.submit(self._send_event, payload)
|
|
78
|
+
|
|
79
|
+
def _send_event(self, payload: dict[str, Any]) -> None:
|
|
80
|
+
"""Send an event to the FastAPI endpoint (runs in thread pool)."""
|
|
81
|
+
try:
|
|
82
|
+
data = json.dumps(payload).encode("utf-8")
|
|
83
|
+
request = Request(
|
|
84
|
+
self._endpoint,
|
|
85
|
+
data=data,
|
|
86
|
+
headers={"Content-Type": "application/json"},
|
|
87
|
+
method="POST",
|
|
88
|
+
)
|
|
89
|
+
# TODO: this introduces blocking IO, should use asyncio.
|
|
90
|
+
with urlopen(request, timeout=self._timeout) as response:
|
|
91
|
+
if response.status >= 400:
|
|
92
|
+
logger.warning(
|
|
93
|
+
f"FastAPI telemetry request failed with"
|
|
94
|
+
f" status {response.status}"
|
|
95
|
+
)
|
|
96
|
+
except URLError as e:
|
|
97
|
+
logger.warning(f"FastAPI telemetry request failed: {e}")
|
|
98
|
+
except Exception as e:
|
|
99
|
+
logger.warning(f"FastAPI telemetry request failed unexpectedly: {e}")
|
|
100
|
+
|
|
101
|
+
def close(self) -> None:
|
|
102
|
+
"""Shutdown the thread pool executor."""
|
|
103
|
+
with self._lock:
|
|
104
|
+
if self._closed:
|
|
105
|
+
return
|
|
106
|
+
self._closed = True
|
|
107
|
+
|
|
108
|
+
self._executor.shutdown(wait=True)
|
|
109
|
+
logger.info("FastAPIRequestTelemetry closed")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
No-op implementation of request telemetry.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
# First Party
|
|
10
|
+
from lmcache.integration.request_telemetry.base import RequestTelemetry
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NoOpRequestTelemetry(RequestTelemetry):
|
|
14
|
+
"""
|
|
15
|
+
A no-op implementation of RequestTelemetry.
|
|
16
|
+
|
|
17
|
+
This implementation does nothing when events are reported.
|
|
18
|
+
Use this when telemetry is disabled or not needed.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, config: dict[str, Any]) -> None:
|
|
22
|
+
# NoOp doesn't need any config, but accepts it for interface consistency
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def on_request_store_finished(
|
|
26
|
+
self,
|
|
27
|
+
request_ids_set: set[str],
|
|
28
|
+
model_name: str,
|
|
29
|
+
world_size: int,
|
|
30
|
+
kv_rank: int,
|
|
31
|
+
) -> None:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def close(self) -> None:
|
|
35
|
+
pass
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Iterable, List, Optional
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
7
|
+
# Third Party
|
|
8
|
+
from sglang.srt.configs.model_config import ModelConfig
|
|
9
|
+
import torch
|
|
10
|
+
import torch.distributed as dist
|
|
11
|
+
|
|
12
|
+
# First Party
|
|
13
|
+
from lmcache.integration.sglang.utils import ENGINE_NAME, lmcache_get_config
|
|
14
|
+
from lmcache.logging import init_logger
|
|
15
|
+
from lmcache.utils import (
|
|
16
|
+
CacheStoreEvent,
|
|
17
|
+
EngineType,
|
|
18
|
+
mock_up_broadcast_fn,
|
|
19
|
+
mock_up_broadcast_object_fn,
|
|
20
|
+
)
|
|
21
|
+
from lmcache.v1.cache_engine import LMCacheEngine, LMCacheEngineBuilder
|
|
22
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
23
|
+
from lmcache.v1.gpu_connector import CreateGPUConnector
|
|
24
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
25
|
+
|
|
26
|
+
logger = init_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class StoreMetadata:
|
|
31
|
+
last_node: Any
|
|
32
|
+
token_ids: List[int]
|
|
33
|
+
kv_indices: torch.Tensor
|
|
34
|
+
offset: int
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class LoadMetadata:
|
|
39
|
+
token_ids: List[int]
|
|
40
|
+
slot_mapping: torch.Tensor
|
|
41
|
+
offset: int
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def init_lmcache_engine(
|
|
45
|
+
model_config: ModelConfig,
|
|
46
|
+
tp_size: int,
|
|
47
|
+
local_rank: int,
|
|
48
|
+
global_rank: int,
|
|
49
|
+
kv_dtype: torch.dtype,
|
|
50
|
+
) -> LMCacheEngine:
|
|
51
|
+
"""
|
|
52
|
+
Initialize LMCache engine for SGLang integration.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
model_config: SGLang model configuration
|
|
56
|
+
tp_size: Tensor parallel size
|
|
57
|
+
local_rank: Local GPU device index (for device selection)
|
|
58
|
+
global_rank: Global tensor parallel rank (for metadata)
|
|
59
|
+
kv_dtype: Data type for KV cache tensors
|
|
60
|
+
"""
|
|
61
|
+
if curr_engine := LMCacheEngineBuilder.get(ENGINE_NAME):
|
|
62
|
+
return curr_engine
|
|
63
|
+
|
|
64
|
+
config = lmcache_get_config()
|
|
65
|
+
assert isinstance(config, LMCacheEngineConfig), (
|
|
66
|
+
"LMCache v1 configuration is should be passed."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# construct kv shape (for mem pool)
|
|
70
|
+
num_layer = model_config.num_hidden_layers
|
|
71
|
+
chunk_size = config.chunk_size
|
|
72
|
+
num_kv_head = model_config.get_num_kv_heads(tp_size)
|
|
73
|
+
head_dim = model_config.head_dim
|
|
74
|
+
|
|
75
|
+
kv_shape = (num_layer, 2, chunk_size, num_kv_head, head_dim)
|
|
76
|
+
|
|
77
|
+
# Change current device using local GPU index
|
|
78
|
+
# Use global rank for metadata (tensor parallel rank)
|
|
79
|
+
metadata = LMCacheMetadata(
|
|
80
|
+
model_name=model_config.model_path,
|
|
81
|
+
world_size=tp_size,
|
|
82
|
+
local_world_size=tp_size,
|
|
83
|
+
worker_id=global_rank,
|
|
84
|
+
local_worker_id=local_rank,
|
|
85
|
+
kv_dtype=kv_dtype,
|
|
86
|
+
kv_shape=kv_shape,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
gpu_connector = CreateGPUConnector(config, metadata, EngineType.SGLANG)
|
|
90
|
+
engine = LMCacheEngineBuilder.get_or_create(
|
|
91
|
+
ENGINE_NAME,
|
|
92
|
+
config,
|
|
93
|
+
metadata,
|
|
94
|
+
gpu_connector,
|
|
95
|
+
mock_up_broadcast_fn,
|
|
96
|
+
mock_up_broadcast_object_fn,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return engine
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class LMCacheConnector:
|
|
103
|
+
def __init__(
|
|
104
|
+
self,
|
|
105
|
+
sgl_config: ModelConfig,
|
|
106
|
+
tp_size: int,
|
|
107
|
+
rank: int,
|
|
108
|
+
k_pool: List[torch.Tensor],
|
|
109
|
+
v_pool: List[torch.Tensor],
|
|
110
|
+
):
|
|
111
|
+
if not k_pool:
|
|
112
|
+
raise ValueError("k_pool cannot be empty during initialization.")
|
|
113
|
+
kv_dtype = k_pool[0].dtype
|
|
114
|
+
if k_pool[0].is_cuda and k_pool[0].device.index is not None:
|
|
115
|
+
local_rank = k_pool[0].device.index
|
|
116
|
+
else:
|
|
117
|
+
# Fallback for CPU / odd cases
|
|
118
|
+
local_rank = rank
|
|
119
|
+
|
|
120
|
+
# rank is the global tensor parallel rank (tp_rank) from SGLang
|
|
121
|
+
# local_rank is the local GPU device index
|
|
122
|
+
self.lmcache_engine = init_lmcache_engine(
|
|
123
|
+
sgl_config,
|
|
124
|
+
tp_size,
|
|
125
|
+
local_rank,
|
|
126
|
+
rank, # global_rank (tp_rank) for metadata
|
|
127
|
+
kv_dtype,
|
|
128
|
+
)
|
|
129
|
+
self.sgl_config = sgl_config
|
|
130
|
+
self.tp_size = tp_size
|
|
131
|
+
self.rank = local_rank # Use local_rank for torch.device() calls
|
|
132
|
+
self.kvcaches = k_pool + v_pool
|
|
133
|
+
self.num_layer = sgl_config.num_hidden_layers
|
|
134
|
+
|
|
135
|
+
self.lmcache_engine.post_init(kvcaches=self.kvcaches)
|
|
136
|
+
|
|
137
|
+
####################
|
|
138
|
+
# Worker side APIs
|
|
139
|
+
####################
|
|
140
|
+
|
|
141
|
+
def load_kv(self, load_metadata: LoadMetadata) -> int:
|
|
142
|
+
token_ids = torch.tensor(load_metadata.token_ids, dtype=torch.int64).cuda()
|
|
143
|
+
slot_mapping = load_metadata.slot_mapping.cuda()
|
|
144
|
+
offset = load_metadata.offset
|
|
145
|
+
|
|
146
|
+
assert isinstance(token_ids, torch.Tensor)
|
|
147
|
+
assert isinstance(slot_mapping, torch.Tensor)
|
|
148
|
+
assert (len(token_ids) - offset) == len(slot_mapping)
|
|
149
|
+
|
|
150
|
+
slot_mapping = slot_mapping.cuda()
|
|
151
|
+
load_mask = torch.ones_like(token_ids, dtype=torch.bool)
|
|
152
|
+
load_mask[:offset] = False
|
|
153
|
+
|
|
154
|
+
ret_token_mask = self.lmcache_engine.retrieve(
|
|
155
|
+
token_ids,
|
|
156
|
+
mask=load_mask,
|
|
157
|
+
kvcaches=self.kvcaches,
|
|
158
|
+
slot_mapping=slot_mapping,
|
|
159
|
+
offset=offset,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
num_retrieved_tokens = ret_token_mask.sum().item()
|
|
163
|
+
|
|
164
|
+
return num_retrieved_tokens
|
|
165
|
+
|
|
166
|
+
def store_kv(self, store_metadata: StoreMetadata) -> None:
|
|
167
|
+
token_ids = torch.tensor(store_metadata.token_ids, dtype=torch.int64).cuda()
|
|
168
|
+
slot_mapping = store_metadata.kv_indices.to(torch.int64).cuda()
|
|
169
|
+
offset = store_metadata.offset
|
|
170
|
+
|
|
171
|
+
assert isinstance(token_ids, torch.Tensor)
|
|
172
|
+
assert isinstance(slot_mapping, torch.Tensor)
|
|
173
|
+
assert len(token_ids) == len(slot_mapping)
|
|
174
|
+
|
|
175
|
+
slot_mapping = slot_mapping.cuda()
|
|
176
|
+
store_mask = torch.ones_like(token_ids, dtype=torch.bool)
|
|
177
|
+
|
|
178
|
+
self.lmcache_engine.store(
|
|
179
|
+
token_ids,
|
|
180
|
+
mask=store_mask,
|
|
181
|
+
kvcaches=self.kvcaches,
|
|
182
|
+
slot_mapping=slot_mapping,
|
|
183
|
+
offset=offset,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
def get_kv_events(self) -> Iterable[CacheStoreEvent]:
|
|
187
|
+
if self.lmcache_engine is not None:
|
|
188
|
+
return self.lmcache_engine.get_kv_events()
|
|
189
|
+
return []
|
|
190
|
+
|
|
191
|
+
def chunk_size(self):
|
|
192
|
+
return self.lmcache_engine.config.chunk_size
|
|
193
|
+
|
|
194
|
+
def reset(self):
|
|
195
|
+
self.lmcache_engine.clear()
|
|
196
|
+
|
|
197
|
+
def close(self):
|
|
198
|
+
self.lmcache_engine.close()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class LMCacheLayerwiseConnector(LMCacheConnector):
|
|
202
|
+
def __init__(
|
|
203
|
+
self,
|
|
204
|
+
sgl_config: ModelConfig,
|
|
205
|
+
tp_size: int,
|
|
206
|
+
rank: int,
|
|
207
|
+
k_pool: List[torch.Tensor],
|
|
208
|
+
v_pool: List[torch.Tensor],
|
|
209
|
+
tp_group: Optional[torch.distributed.ProcessGroup] = None,
|
|
210
|
+
):
|
|
211
|
+
super().__init__(sgl_config, tp_size, rank, k_pool, v_pool)
|
|
212
|
+
self._lmcache_chunk_size = self.lmcache_engine.config.chunk_size
|
|
213
|
+
self.layerwise_retrievers: List[Any] = []
|
|
214
|
+
self.layer_load_layer: List[int] = []
|
|
215
|
+
self.kvcaches = [k_pool, v_pool]
|
|
216
|
+
self.tp_group = tp_group
|
|
217
|
+
self.lookup_id_list: List[str] = []
|
|
218
|
+
|
|
219
|
+
@torch.no_grad()
|
|
220
|
+
def global_min_tokens(
|
|
221
|
+
self, local_tokens: int, tp_group: dist.ProcessGroup, device: torch.device
|
|
222
|
+
):
|
|
223
|
+
# If tensor parallel size is 1, no need for all_reduce
|
|
224
|
+
if self.tp_size == 1:
|
|
225
|
+
return local_tokens
|
|
226
|
+
|
|
227
|
+
t = torch.tensor([local_tokens], dtype=torch.int32, device=device)
|
|
228
|
+
dist.all_reduce(t, op=dist.ReduceOp.MIN, group=tp_group)
|
|
229
|
+
return int(t.item())
|
|
230
|
+
|
|
231
|
+
def load_kv_layerwise(self, layer_id: int) -> None:
|
|
232
|
+
if len(self.layerwise_retrievers) == 0:
|
|
233
|
+
return
|
|
234
|
+
|
|
235
|
+
indices_to_remove = []
|
|
236
|
+
for i in range(len(self.layerwise_retrievers)):
|
|
237
|
+
if self.layer_load_layer[i] == layer_id + 1:
|
|
238
|
+
next(self.layerwise_retrievers[i])
|
|
239
|
+
self.layer_load_layer[i] += 1
|
|
240
|
+
if self.layer_load_layer[i] == self.sgl_config.num_hidden_layers:
|
|
241
|
+
indices_to_remove.append(i)
|
|
242
|
+
|
|
243
|
+
for i in sorted(indices_to_remove, reverse=True):
|
|
244
|
+
del self.layerwise_retrievers[i]
|
|
245
|
+
del self.layer_load_layer[i]
|
|
246
|
+
self.lmcache_engine.lookup_unpin(self.lookup_id_list[i])
|
|
247
|
+
del self.lookup_id_list[i]
|
|
248
|
+
|
|
249
|
+
return
|
|
250
|
+
|
|
251
|
+
def start_load_kv(self, load_metadata: LoadMetadata) -> int:
|
|
252
|
+
token_ids = torch.tensor(load_metadata.token_ids, dtype=torch.int64).cuda()
|
|
253
|
+
slot_mapping = load_metadata.slot_mapping.cuda()
|
|
254
|
+
offset = load_metadata.offset
|
|
255
|
+
|
|
256
|
+
assert self.lmcache_engine is not None
|
|
257
|
+
|
|
258
|
+
load_mask = torch.ones_like(token_ids, dtype=torch.bool)
|
|
259
|
+
load_mask[:offset] = False
|
|
260
|
+
|
|
261
|
+
lookup_id = str(uuid.uuid4())
|
|
262
|
+
retrieve_token_num = self.lmcache_engine.lookup(
|
|
263
|
+
token_ids,
|
|
264
|
+
lookup_id=lookup_id,
|
|
265
|
+
pin=True,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
retrieve_token_num = self.global_min_tokens(
|
|
269
|
+
retrieve_token_num, self.tp_group, torch.device(f"cuda:{self.rank}")
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# No new tokens to retrieve from LMCache
|
|
273
|
+
if retrieve_token_num <= offset:
|
|
274
|
+
self.lmcache_engine.lookup_unpin(lookup_id)
|
|
275
|
+
logger.info(
|
|
276
|
+
f"LMCache retrieve skipped: lookup={retrieve_token_num}, "
|
|
277
|
+
f"offset={offset}, no new tokens to retrieve"
|
|
278
|
+
)
|
|
279
|
+
return 0
|
|
280
|
+
|
|
281
|
+
layerwise_retriever = self.lmcache_engine.retrieve_layer(
|
|
282
|
+
token_ids[:retrieve_token_num],
|
|
283
|
+
mask=load_mask[:retrieve_token_num],
|
|
284
|
+
kvcaches=self.kvcaches,
|
|
285
|
+
slot_mapping=slot_mapping[:retrieve_token_num],
|
|
286
|
+
sync=False,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
next(layerwise_retriever)
|
|
290
|
+
# Load First Layer
|
|
291
|
+
next(layerwise_retriever)
|
|
292
|
+
|
|
293
|
+
self.layerwise_retrievers.append(layerwise_retriever)
|
|
294
|
+
self.layer_load_layer.append(1)
|
|
295
|
+
|
|
296
|
+
self.lookup_id_list.append(lookup_id)
|
|
297
|
+
|
|
298
|
+
num_new_tokens = retrieve_token_num - offset
|
|
299
|
+
logger.info(
|
|
300
|
+
f"LMCache retrieve started: lookup={retrieve_token_num}, "
|
|
301
|
+
f"offset={offset}, retrieve {num_new_tokens} new tokens"
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
return num_new_tokens
|
|
305
|
+
|
|
306
|
+
def store_kv(self, store_metadata: StoreMetadata) -> None:
|
|
307
|
+
slot_mapping = store_metadata.kv_indices.to(torch.int64).cuda()
|
|
308
|
+
token_ids = torch.tensor(store_metadata.token_ids, dtype=torch.int64).cuda()
|
|
309
|
+
store_mask = torch.ones_like(token_ids, dtype=torch.bool)
|
|
310
|
+
|
|
311
|
+
lookup_id = str(uuid.uuid4())
|
|
312
|
+
self.lmcache_engine.lookup(token_ids, lookup_id=lookup_id, pin=True)
|
|
313
|
+
|
|
314
|
+
layerwise_storer = self.lmcache_engine.store_layer(
|
|
315
|
+
token_ids,
|
|
316
|
+
mask=store_mask,
|
|
317
|
+
kvcaches=self.kvcaches,
|
|
318
|
+
slot_mapping=slot_mapping,
|
|
319
|
+
offset=store_metadata.offset,
|
|
320
|
+
sync=False,
|
|
321
|
+
)
|
|
322
|
+
next(layerwise_storer)
|
|
323
|
+
for _ in range(self.sgl_config.num_hidden_layers):
|
|
324
|
+
next(layerwise_storer)
|
|
325
|
+
|
|
326
|
+
self.lmcache_engine.lookup_unpin(lookup_id)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
# First Party
|
|
6
|
+
from lmcache.logging import init_logger
|
|
7
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
8
|
+
|
|
9
|
+
logger = init_logger(__name__)
|
|
10
|
+
ENGINE_NAME = "sglang-instance"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_false(value: str) -> bool:
|
|
14
|
+
"""Check if the given string value is equivalent to 'false'."""
|
|
15
|
+
return value.lower() in ("false", "0", "no", "n", "off")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def lmcache_get_config() -> LMCacheEngineConfig:
|
|
19
|
+
"""Get the LMCache configuration from the environment variable
|
|
20
|
+
`LMCACHE_CONFIG_FILE`. If the environment variable is not set, this
|
|
21
|
+
function will return the default configuration.
|
|
22
|
+
"""
|
|
23
|
+
logger.info(f"LMCACHE_CONFIG_FILE: {os.getenv('LMCACHE_CONFIG_FILE')}")
|
|
24
|
+
if "LMCACHE_CONFIG_FILE" not in os.environ:
|
|
25
|
+
logger.warn(
|
|
26
|
+
"No LMCache configuration file is set. Trying to read"
|
|
27
|
+
" configurations from the environment variables."
|
|
28
|
+
)
|
|
29
|
+
logger.warn(
|
|
30
|
+
"You can set the configuration file through "
|
|
31
|
+
"the environment variable: LMCACHE_CONFIG_FILE"
|
|
32
|
+
)
|
|
33
|
+
config = LMCacheEngineConfig.from_env()
|
|
34
|
+
else:
|
|
35
|
+
config_file = os.environ["LMCACHE_CONFIG_FILE"]
|
|
36
|
+
logger.info(f"Loading LMCache config file {config_file}")
|
|
37
|
+
config = LMCacheEngineConfig.from_file(config_file)
|
|
38
|
+
|
|
39
|
+
return config
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|