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,385 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Configuration for L2 adapters.
|
|
5
|
+
|
|
6
|
+
Supports multiple adapter instances (including multiple instances of the same
|
|
7
|
+
adapter type with different configs) via repeatable --l2-adapter <JSON>.
|
|
8
|
+
Each JSON object must include "type" (adapter type name) and type-specific keys.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Future
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
# Standard
|
|
15
|
+
from abc import ABC, abstractmethod
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
18
|
+
import argparse
|
|
19
|
+
import json
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
# First Party
|
|
23
|
+
from lmcache.v1.distributed.config import EvictionConfig
|
|
24
|
+
|
|
25
|
+
# First Party
|
|
26
|
+
from lmcache.logging import init_logger
|
|
27
|
+
|
|
28
|
+
logger = init_logger(__name__)
|
|
29
|
+
|
|
30
|
+
T = TypeVar("T", bound="L2AdapterConfigBase")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class PersistConfig:
|
|
35
|
+
"""
|
|
36
|
+
Configuration for persist on an L2 adapter.
|
|
37
|
+
|
|
38
|
+
When enabled, data files are kept on disk at shutdown instead of
|
|
39
|
+
deleted. Lookup always checks secondary storage (disk) on miss
|
|
40
|
+
regardless of this setting.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
persist_enabled: bool = True
|
|
44
|
+
""" If True, data files are kept on disk at shutdown instead of deleted. """
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# -----------------------------------------------------------------------------
|
|
48
|
+
# Registry: adapter type name -> config class
|
|
49
|
+
# -----------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
_L2_ADAPTER_CONFIG_REGISTRY: dict[str, type[L2AdapterConfigBase]] = {}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def register_l2_adapter_type(
|
|
55
|
+
name: str,
|
|
56
|
+
config_cls: type[L2AdapterConfigBase],
|
|
57
|
+
) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Register an L2 adapter config class under a type name.
|
|
60
|
+
|
|
61
|
+
The type name is used in JSON specs as the "type" field.
|
|
62
|
+
Each adapter config module should call this at import time.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
name: Adapter type name (e.g. "fs", "mock").
|
|
66
|
+
config_cls: Config class that can parse from dict
|
|
67
|
+
via ``from_dict()``.
|
|
68
|
+
"""
|
|
69
|
+
if name in _L2_ADAPTER_CONFIG_REGISTRY:
|
|
70
|
+
raise ValueError("L2 adapter type already registered: %s" % repr(name))
|
|
71
|
+
_L2_ADAPTER_CONFIG_REGISTRY[name] = config_cls
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _ensure_config_loaded(name: str) -> None:
|
|
75
|
+
"""Trigger lazy import for *name* if it is not
|
|
76
|
+
yet in the config registry.
|
|
77
|
+
|
|
78
|
+
Raises:
|
|
79
|
+
ImportError: If the adapter module cannot be
|
|
80
|
+
imported (missing dependency).
|
|
81
|
+
"""
|
|
82
|
+
if name in _L2_ADAPTER_CONFIG_REGISTRY:
|
|
83
|
+
return
|
|
84
|
+
# Lazy import lives in factory to avoid circular deps
|
|
85
|
+
# First Party
|
|
86
|
+
from lmcache.v1.distributed.l2_adapters.factory import ( # noqa: PLC0415
|
|
87
|
+
ensure_adapter_loaded,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
ensure_adapter_loaded(name)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_registered_l2_adapter_types() -> list[str]:
|
|
94
|
+
"""Return all known adapter type names (eager
|
|
95
|
+
and lazy)."""
|
|
96
|
+
# First Party
|
|
97
|
+
from lmcache.v1.distributed.l2_adapters.factory import ( # noqa: PLC0415
|
|
98
|
+
get_all_registered_names,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return get_all_registered_names()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def get_type_name_for_config(
|
|
105
|
+
config: L2AdapterConfigBase,
|
|
106
|
+
) -> str:
|
|
107
|
+
"""
|
|
108
|
+
Reverse-lookup the registered type name for a config
|
|
109
|
+
instance.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
config: An L2 adapter config instance.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
The registered type name (e.g., "mock", "fs").
|
|
116
|
+
|
|
117
|
+
Raises:
|
|
118
|
+
ValueError: If the config's class is not registered.
|
|
119
|
+
"""
|
|
120
|
+
for name, cls in _L2_ADAPTER_CONFIG_REGISTRY.items():
|
|
121
|
+
if type(config) is cls:
|
|
122
|
+
return name
|
|
123
|
+
raise ValueError("Unregistered L2 adapter config type: %s" % type(config).__name__)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# -----------------------------------------------------------------------------
|
|
127
|
+
# Base config class for a single L2 adapter
|
|
128
|
+
# -----------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class L2AdapterConfigBase(ABC):
|
|
132
|
+
"""
|
|
133
|
+
Base class for per-adapter configs.
|
|
134
|
+
|
|
135
|
+
Each adapter type (e.g. disk, redis) defines a config class that:
|
|
136
|
+
- Subclasses this base.
|
|
137
|
+
- Implements from_dict() to parse a dict (from JSON) into an instance.
|
|
138
|
+
- Is registered via register_l2_adapter_type("type_name", ConfigClass).
|
|
139
|
+
|
|
140
|
+
An optional ``"eviction"`` key in the JSON dict enables per-adapter L2
|
|
141
|
+
eviction. When present it is parsed by ``_parse_eviction_config()`` and
|
|
142
|
+
stored on ``eviction_config``; the L2EvictionController is then created
|
|
143
|
+
for this adapter in the StorageManager.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
#: Populated by ``_parse_eviction_config`` after ``from_dict``; ``None``
|
|
147
|
+
#: means L2 eviction is disabled for this adapter.
|
|
148
|
+
eviction_config: EvictionConfig | None = None
|
|
149
|
+
|
|
150
|
+
#: Populated by ``_parse_persist_config`` after ``from_dict``.
|
|
151
|
+
#: Defaults to ``PersistConfig()`` (persist enabled).
|
|
152
|
+
persist_config: PersistConfig = PersistConfig()
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def _parse_eviction_config(d: dict) -> EvictionConfig | None:
|
|
156
|
+
"""
|
|
157
|
+
Parse an optional ``"eviction"`` sub-dict from an adapter JSON spec.
|
|
158
|
+
|
|
159
|
+
Expected format::
|
|
160
|
+
|
|
161
|
+
{
|
|
162
|
+
"type": "mock",
|
|
163
|
+
...
|
|
164
|
+
"eviction": {
|
|
165
|
+
"eviction_policy": "LRU",
|
|
166
|
+
"trigger_watermark": 0.8,
|
|
167
|
+
"eviction_ratio": 0.2
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
Returns ``None`` when the key is absent (eviction disabled).
|
|
172
|
+
"""
|
|
173
|
+
eviction_dict = d.get("eviction")
|
|
174
|
+
if eviction_dict is None:
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
# Lazy import to avoid circular dependency:
|
|
178
|
+
# l2_adapters/config.py <- config.py <- l2_adapters/config.py
|
|
179
|
+
# First Party
|
|
180
|
+
from lmcache.v1.distributed.config import EvictionConfig # noqa: PLC0415
|
|
181
|
+
|
|
182
|
+
policy = eviction_dict.get("eviction_policy")
|
|
183
|
+
if policy not in ("LRU", "noop"):
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"eviction.eviction_policy must be 'LRU' or 'noop', got {policy!r}"
|
|
186
|
+
)
|
|
187
|
+
return EvictionConfig(
|
|
188
|
+
eviction_policy=policy,
|
|
189
|
+
trigger_watermark=float(eviction_dict.get("trigger_watermark", 0.8)),
|
|
190
|
+
eviction_ratio=float(eviction_dict.get("eviction_ratio", 0.2)),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
@staticmethod
|
|
194
|
+
def _parse_persist_config(d: dict) -> PersistConfig:
|
|
195
|
+
"""
|
|
196
|
+
Parse optional ``"persist_enabled"`` key from an adapter JSON spec.
|
|
197
|
+
|
|
198
|
+
Defaults to ``True``.
|
|
199
|
+
|
|
200
|
+
Expected format::
|
|
201
|
+
|
|
202
|
+
{
|
|
203
|
+
"type": "nixl_store_dynamic",
|
|
204
|
+
...
|
|
205
|
+
"persist_enabled": true
|
|
206
|
+
}
|
|
207
|
+
"""
|
|
208
|
+
persist_enabled = bool(d.get("persist_enabled", True))
|
|
209
|
+
return PersistConfig(persist_enabled=persist_enabled)
|
|
210
|
+
|
|
211
|
+
@classmethod
|
|
212
|
+
@abstractmethod
|
|
213
|
+
def from_dict(cls: type[T], d: dict) -> T:
|
|
214
|
+
"""
|
|
215
|
+
Build a config instance from a dict (e.g. from parsed JSON).
|
|
216
|
+
|
|
217
|
+
The dict will contain the "type" key used for dispatch; the concrete
|
|
218
|
+
class may ignore it. All other keys are type-specific.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
d: Adapter spec dict (must include type-specific keys).
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
An instance of the config class.
|
|
225
|
+
|
|
226
|
+
Raises:
|
|
227
|
+
ValueError: If required keys are missing or values are invalid.
|
|
228
|
+
"""
|
|
229
|
+
...
|
|
230
|
+
|
|
231
|
+
@classmethod
|
|
232
|
+
@abstractmethod
|
|
233
|
+
def help(cls) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Return a help string describing the config fields for this adapter type.
|
|
236
|
+
|
|
237
|
+
This is used in command-line help to explain the expected JSON format for
|
|
238
|
+
each adapter type.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
A help string describing the config fields for this adapter type.
|
|
242
|
+
"""
|
|
243
|
+
...
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# -----------------------------------------------------------------------------
|
|
247
|
+
# Main config: list of adapter configs (order = adapter order)
|
|
248
|
+
# -----------------------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@dataclass
|
|
252
|
+
class L2AdaptersConfig:
|
|
253
|
+
"""
|
|
254
|
+
Main config for L2 adapters.
|
|
255
|
+
|
|
256
|
+
Holds an ordered list of adapter configs. Each element corresponds to one
|
|
257
|
+
L2 adapter instance (e.g. two disk adapters with different paths appear
|
|
258
|
+
as two entries).
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
adapters: list[L2AdapterConfigBase]
|
|
262
|
+
""" Ordered list of adapter configs; one per L2 adapter instance. """
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
# -----------------------------------------------------------------------------
|
|
266
|
+
# Command-line: add args and parse to config
|
|
267
|
+
# -----------------------------------------------------------------------------
|
|
268
|
+
|
|
269
|
+
_L2_ADAPTER_ARG_DEST = "l2_adapter"
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def add_l2_adapters_args(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
|
|
273
|
+
"""
|
|
274
|
+
Add L2 adapter configuration arguments to an existing parser.
|
|
275
|
+
|
|
276
|
+
Adds a repeatable --l2-adapter <JSON> argument. Each JSON object specifies
|
|
277
|
+
one adapter: it must include "type" (registered adapter type name) and
|
|
278
|
+
type-specific keys. Order of arguments is the order of adapters.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
parser: The argument parser to add arguments to.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
The same parser with L2 adapter arguments added.
|
|
285
|
+
|
|
286
|
+
Example:
|
|
287
|
+
>>> parser = argparse.ArgumentParser()
|
|
288
|
+
>>> add_l2_adapters_args(parser)
|
|
289
|
+
>>> args = parser.parse_args(["--l2-adapter", '{"type":"disk","path":"/data"}'])
|
|
290
|
+
>>> config = parse_args_to_l2_adapters_config(args)
|
|
291
|
+
"""
|
|
292
|
+
group = parser.add_argument_group(
|
|
293
|
+
"L2 Adapters",
|
|
294
|
+
"L2 adapter instances. Each --l2-adapter is a JSON object with 'type' and "
|
|
295
|
+
"type-specific keys. Repeat for multiple adapters.",
|
|
296
|
+
)
|
|
297
|
+
group.add_argument(
|
|
298
|
+
"--l2-adapter",
|
|
299
|
+
dest=_L2_ADAPTER_ARG_DEST,
|
|
300
|
+
action="append",
|
|
301
|
+
default=[],
|
|
302
|
+
type=str,
|
|
303
|
+
metavar="JSON",
|
|
304
|
+
help='Adapter spec as JSON with a "type" field and adapter-specific configs'
|
|
305
|
+
', e.g. \'{"type":"disk","path":"/data"}\'.'
|
|
306
|
+
"Repeat for multiple adapters."
|
|
307
|
+
"Supported adapters are: ["
|
|
308
|
+
+ ", ".join(sorted(get_registered_l2_adapter_types()))
|
|
309
|
+
+ "].",
|
|
310
|
+
)
|
|
311
|
+
return parser
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def parse_args_to_l2_adapters_config(args: argparse.Namespace) -> L2AdaptersConfig:
|
|
315
|
+
"""
|
|
316
|
+
Build L2AdaptersConfig from parsed command-line arguments.
|
|
317
|
+
|
|
318
|
+
Expects args to have the attribute added by add_l2_adapters_args (a list
|
|
319
|
+
of JSON strings). Each string is parsed; the "type" field selects the
|
|
320
|
+
config class from the registry, and from_dict() builds the config instance.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
args: Parsed arguments (e.g. from parser.parse_args()).
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
L2AdaptersConfig with one entry per --l2-adapter argument.
|
|
327
|
+
|
|
328
|
+
Raises:
|
|
329
|
+
KeyError: If an adapter "type" is not registered.
|
|
330
|
+
ValueError: If JSON is invalid or a config class raises from_dict().
|
|
331
|
+
"""
|
|
332
|
+
raw_list = getattr(args, _L2_ADAPTER_ARG_DEST, None)
|
|
333
|
+
if raw_list is None:
|
|
334
|
+
raw_list = []
|
|
335
|
+
|
|
336
|
+
adapter_configs: list[L2AdapterConfigBase] = []
|
|
337
|
+
for i, raw in enumerate(raw_list):
|
|
338
|
+
try:
|
|
339
|
+
d = json.loads(raw)
|
|
340
|
+
except json.JSONDecodeError as e:
|
|
341
|
+
raise ValueError(f"Invalid JSON for --l2-adapter #{i + 1}: {e}") from e
|
|
342
|
+
|
|
343
|
+
if not isinstance(d, dict):
|
|
344
|
+
raise ValueError(
|
|
345
|
+
f"--l2-adapter #{i + 1}: expected a JSON object, got {type(d).__name__}"
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
type_name = d.get("type")
|
|
349
|
+
if type_name is None:
|
|
350
|
+
raise ValueError("--l2-adapter #%d: missing 'type' field" % (i + 1))
|
|
351
|
+
|
|
352
|
+
# Trigger lazy import for this adapter type
|
|
353
|
+
_ensure_config_loaded(type_name)
|
|
354
|
+
|
|
355
|
+
if type_name not in _L2_ADAPTER_CONFIG_REGISTRY:
|
|
356
|
+
known = ", ".join(sorted(_L2_ADAPTER_CONFIG_REGISTRY)) or "(none)"
|
|
357
|
+
raise ValueError(
|
|
358
|
+
f"--l2-adapter #{i + 1}: unknown adapter type "
|
|
359
|
+
f"{type_name!r}. Known: {known}"
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
config_cls = _L2_ADAPTER_CONFIG_REGISTRY[type_name]
|
|
363
|
+
try:
|
|
364
|
+
adapter_cfg = config_cls.from_dict(d)
|
|
365
|
+
adapter_cfg.eviction_config = L2AdapterConfigBase._parse_eviction_config(d)
|
|
366
|
+
adapter_cfg.persist_config = L2AdapterConfigBase._parse_persist_config(d)
|
|
367
|
+
adapter_configs.append(adapter_cfg)
|
|
368
|
+
except (TypeError, ValueError) as e:
|
|
369
|
+
logger.error(
|
|
370
|
+
"Error parsing --l2-adapter #%d (type %r): %s",
|
|
371
|
+
i + 1,
|
|
372
|
+
type_name,
|
|
373
|
+
e,
|
|
374
|
+
)
|
|
375
|
+
logger.error(
|
|
376
|
+
"Adapter config help for %s adapter:\n"
|
|
377
|
+
"---------------------\n"
|
|
378
|
+
"%s\n"
|
|
379
|
+
"---------------------\n\n",
|
|
380
|
+
type_name,
|
|
381
|
+
config_cls.help(),
|
|
382
|
+
)
|
|
383
|
+
raise ValueError(f"--l2-adapter #{i + 1} ({type_name!r}): {e}") from e
|
|
384
|
+
|
|
385
|
+
return L2AdaptersConfig(adapters=adapter_configs)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Factory registry for L2 adapters.
|
|
4
|
+
|
|
5
|
+
Each adapter module self-registers a factory callable via
|
|
6
|
+
``register_l2_adapter_factory`` at import time. The factory
|
|
7
|
+
signature is
|
|
8
|
+
``(L2AdapterConfigBase, Optional[L1MemoryDesc]) -> L2AdapterInterface``.
|
|
9
|
+
|
|
10
|
+
Built-in adapters are discovered via ``pkgutil`` but only
|
|
11
|
+
imported on demand -- their modules (and third-party
|
|
12
|
+
dependencies) are loaded only when the adapter type is
|
|
13
|
+
actually requested.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# Future
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
# Standard
|
|
20
|
+
from typing import TYPE_CHECKING, Callable, Optional
|
|
21
|
+
import importlib
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from lmcache.v1.distributed.internal_api import (
|
|
25
|
+
L1MemoryDesc,
|
|
26
|
+
)
|
|
27
|
+
from lmcache.v1.distributed.l2_adapters.base import (
|
|
28
|
+
L2AdapterInterface,
|
|
29
|
+
)
|
|
30
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
31
|
+
L2AdapterConfigBase,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# First Party
|
|
35
|
+
from lmcache.logging import init_logger
|
|
36
|
+
|
|
37
|
+
logger = init_logger(__name__)
|
|
38
|
+
|
|
39
|
+
# Type alias for factory callables:
|
|
40
|
+
# (config, l1_memory_desc) -> L2AdapterInterface
|
|
41
|
+
L2AdapterFactory = Callable[
|
|
42
|
+
["L2AdapterConfigBase", "Optional[L1MemoryDesc]"],
|
|
43
|
+
"L2AdapterInterface",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
# -----------------------------------------------------------------
|
|
47
|
+
# Registry: adapter type name -> factory callable
|
|
48
|
+
# -----------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
_L2_ADAPTER_FACTORY_REGISTRY: dict[str, L2AdapterFactory] = {}
|
|
51
|
+
|
|
52
|
+
# -----------------------------------------------------------------
|
|
53
|
+
# Pending modules: fully-qualified module paths that have
|
|
54
|
+
# been discovered (e.g. via pkgutil) but not yet imported.
|
|
55
|
+
# When a type name is not found in the eager registry we
|
|
56
|
+
# import these one-by-one until the name appears.
|
|
57
|
+
# -----------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
_PENDING_MODULES: list[str] = []
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def register_l2_adapter_factory(
|
|
63
|
+
name: str,
|
|
64
|
+
factory: L2AdapterFactory,
|
|
65
|
+
) -> None:
|
|
66
|
+
"""Register an adapter factory for the given type
|
|
67
|
+
name.
|
|
68
|
+
|
|
69
|
+
Each adapter module should call this at import time
|
|
70
|
+
**after** its config class has been registered via
|
|
71
|
+
``register_l2_adapter_type``.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
name: Adapter type name (must match the name used
|
|
75
|
+
in ``register_l2_adapter_type``).
|
|
76
|
+
factory: ``(config, l1_memory_desc)``
|
|
77
|
+
-> ``L2AdapterInterface``.
|
|
78
|
+
"""
|
|
79
|
+
if name in _L2_ADAPTER_FACTORY_REGISTRY:
|
|
80
|
+
raise ValueError("L2 adapter factory already registered: %s" % name)
|
|
81
|
+
_L2_ADAPTER_FACTORY_REGISTRY[name] = factory
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def add_pending_module(module_path: str) -> None:
|
|
85
|
+
"""Register a module path for deferred import.
|
|
86
|
+
|
|
87
|
+
The module will only be imported when a type name
|
|
88
|
+
lookup misses the eager registry. Importing the
|
|
89
|
+
module triggers its ``register_l2_adapter_type``
|
|
90
|
+
and ``register_l2_adapter_factory`` calls.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
module_path: Fully-qualified module path
|
|
94
|
+
(e.g. ``"lmcache.v1.distributed.
|
|
95
|
+
l2_adapters.fs_l2_adapter"``).
|
|
96
|
+
"""
|
|
97
|
+
if module_path not in _PENDING_MODULES:
|
|
98
|
+
_PENDING_MODULES.append(module_path)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def ensure_adapter_loaded(name: str) -> None:
|
|
102
|
+
"""Import pending modules until *name* appears in
|
|
103
|
+
the factory registry (or all pending modules have
|
|
104
|
+
been tried).
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
ImportError: If a module fails to import due to
|
|
108
|
+
a missing third-party dependency **and** it
|
|
109
|
+
was the last candidate.
|
|
110
|
+
"""
|
|
111
|
+
if name in _L2_ADAPTER_FACTORY_REGISTRY:
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
last_err: ImportError | None = None
|
|
115
|
+
while _PENDING_MODULES:
|
|
116
|
+
mod_path = _PENDING_MODULES.pop(0)
|
|
117
|
+
try:
|
|
118
|
+
importlib.import_module(mod_path)
|
|
119
|
+
except ImportError as exc:
|
|
120
|
+
logger.debug(
|
|
121
|
+
"Skipping module %s (import failed: %s)",
|
|
122
|
+
mod_path,
|
|
123
|
+
exc,
|
|
124
|
+
)
|
|
125
|
+
last_err = exc
|
|
126
|
+
continue
|
|
127
|
+
# Check if the name is now registered
|
|
128
|
+
if name in _L2_ADAPTER_FACTORY_REGISTRY:
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
# If we exhausted all pending modules and still
|
|
132
|
+
# didn't find the name, the last ImportError (if
|
|
133
|
+
# any) might be the root cause.
|
|
134
|
+
if last_err is not None and name not in _L2_ADAPTER_FACTORY_REGISTRY:
|
|
135
|
+
raise last_err
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def load_all_adapters() -> None:
|
|
139
|
+
"""Force-import all pending adapter modules.
|
|
140
|
+
|
|
141
|
+
Useful for CLI help that needs to list every
|
|
142
|
+
registered type name.
|
|
143
|
+
"""
|
|
144
|
+
while _PENDING_MODULES:
|
|
145
|
+
mod_path = _PENDING_MODULES.pop(0)
|
|
146
|
+
try:
|
|
147
|
+
importlib.import_module(mod_path)
|
|
148
|
+
except ImportError:
|
|
149
|
+
logger.debug(
|
|
150
|
+
"Skipping module %s during bulk load",
|
|
151
|
+
mod_path,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def get_all_registered_names() -> list[str]:
|
|
156
|
+
"""Return all known adapter type names.
|
|
157
|
+
|
|
158
|
+
Forces import of all pending modules so that the
|
|
159
|
+
returned list is complete.
|
|
160
|
+
"""
|
|
161
|
+
load_all_adapters()
|
|
162
|
+
return sorted(_L2_ADAPTER_FACTORY_REGISTRY)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def create_l2_adapter_from_registry(
|
|
166
|
+
config: "L2AdapterConfigBase",
|
|
167
|
+
l1_memory_desc: "Optional[L1MemoryDesc]" = None,
|
|
168
|
+
) -> "L2AdapterInterface":
|
|
169
|
+
"""Create an L2 adapter using the factory registry.
|
|
170
|
+
|
|
171
|
+
Looks up the type name for *config* via the config
|
|
172
|
+
registry, then calls the matching factory.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
config: An adapter config instance.
|
|
176
|
+
l1_memory_desc: Optional L1 memory descriptor,
|
|
177
|
+
required by adapters that register L1 memory
|
|
178
|
+
with an external backend (e.g. Nixl).
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
A new ``L2AdapterInterface`` instance.
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
ValueError: If no factory is registered for this
|
|
185
|
+
config type.
|
|
186
|
+
"""
|
|
187
|
+
# Import here to avoid circular dependency
|
|
188
|
+
# First Party
|
|
189
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
190
|
+
get_type_name_for_config,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
name = get_type_name_for_config(config)
|
|
194
|
+
|
|
195
|
+
# Trigger lazy import if needed
|
|
196
|
+
ensure_adapter_loaded(name)
|
|
197
|
+
|
|
198
|
+
factory = _L2_ADAPTER_FACTORY_REGISTRY.get(name)
|
|
199
|
+
if factory is None:
|
|
200
|
+
raise ValueError(
|
|
201
|
+
"No adapter factory registered for type "
|
|
202
|
+
"%s. Make sure the adapter module is "
|
|
203
|
+
"imported." % name
|
|
204
|
+
)
|
|
205
|
+
return factory(config, l1_memory_desc)
|