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,50 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Optional, Tuple
|
|
4
|
+
|
|
5
|
+
# First Party
|
|
6
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
7
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
8
|
+
from lmcache.v1.storage_backend.naive_serde.cachegen_decoder import CacheGenDeserializer
|
|
9
|
+
from lmcache.v1.storage_backend.naive_serde.cachegen_encoder import CacheGenSerializer
|
|
10
|
+
from lmcache.v1.storage_backend.naive_serde.kivi_serde import (
|
|
11
|
+
KIVIDeserializer,
|
|
12
|
+
KIVISerializer,
|
|
13
|
+
)
|
|
14
|
+
from lmcache.v1.storage_backend.naive_serde.naive_serde import (
|
|
15
|
+
NaiveDeserializer,
|
|
16
|
+
NaiveSerializer,
|
|
17
|
+
)
|
|
18
|
+
from lmcache.v1.storage_backend.naive_serde.serde import Deserializer, Serializer
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def CreateSerde(
|
|
22
|
+
serde_type: str,
|
|
23
|
+
metadata: LMCacheMetadata,
|
|
24
|
+
config: LMCacheEngineConfig,
|
|
25
|
+
) -> Tuple[Serializer, Deserializer]:
|
|
26
|
+
s: Optional[Serializer] = None
|
|
27
|
+
d: Optional[Deserializer] = None
|
|
28
|
+
|
|
29
|
+
if serde_type == "naive":
|
|
30
|
+
s, d = NaiveSerializer(), NaiveDeserializer()
|
|
31
|
+
elif serde_type == "kivi":
|
|
32
|
+
s, d = KIVISerializer(), KIVIDeserializer()
|
|
33
|
+
elif serde_type == "cachegen":
|
|
34
|
+
s, d = (
|
|
35
|
+
CacheGenSerializer(config, metadata),
|
|
36
|
+
CacheGenDeserializer(config, metadata),
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
raise ValueError(f"Invalid type: {serde_type}")
|
|
40
|
+
|
|
41
|
+
return s, d
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
"Serializer",
|
|
46
|
+
"Deserializer",
|
|
47
|
+
"KIVISerializer",
|
|
48
|
+
"KIVIDeserializer",
|
|
49
|
+
"CreateSerde",
|
|
50
|
+
]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
# Third Party
|
|
7
|
+
from transformers import AutoConfig
|
|
8
|
+
|
|
9
|
+
# First Party
|
|
10
|
+
from lmcache.logging import init_logger
|
|
11
|
+
from lmcache.storage_backend.serde.cachegen_basics import QuantizationSpec
|
|
12
|
+
|
|
13
|
+
logger = init_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class CacheGenConfig:
|
|
18
|
+
# TODO: move this class to another file like "cachegen_basics.py"
|
|
19
|
+
nlayers: int
|
|
20
|
+
kspecs: List[QuantizationSpec]
|
|
21
|
+
vspecs: List[QuantizationSpec]
|
|
22
|
+
|
|
23
|
+
def __getitem__(self, key: str) -> int:
|
|
24
|
+
return getattr(self, key)
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def from_model_name(model_name: str) -> "CacheGenConfig":
|
|
28
|
+
family_7b = [
|
|
29
|
+
"mistralai/Mistral-7B-Instruct-v0.2",
|
|
30
|
+
"lmsys/longchat-7b-16k",
|
|
31
|
+
"Qwen/Qwen-7B",
|
|
32
|
+
]
|
|
33
|
+
family_8b = ["meta-llama/Llama-3.1-8B-Instruct"]
|
|
34
|
+
family_9b = ["THUDM/glm-4-9b-chat"]
|
|
35
|
+
if model_name in family_7b:
|
|
36
|
+
return CacheGenConfig(
|
|
37
|
+
nlayers=32,
|
|
38
|
+
kspecs=[
|
|
39
|
+
QuantizationSpec(start_layer=0, end_layer=10, bins=32),
|
|
40
|
+
QuantizationSpec(start_layer=10, end_layer=32, bins=16),
|
|
41
|
+
],
|
|
42
|
+
vspecs=[
|
|
43
|
+
QuantizationSpec(start_layer=0, end_layer=2, bins=32),
|
|
44
|
+
QuantizationSpec(start_layer=2, end_layer=32, bins=16),
|
|
45
|
+
],
|
|
46
|
+
)
|
|
47
|
+
elif model_name in family_8b:
|
|
48
|
+
return CacheGenConfig(
|
|
49
|
+
nlayers=32,
|
|
50
|
+
kspecs=[
|
|
51
|
+
QuantizationSpec(start_layer=0, end_layer=10, bins=32),
|
|
52
|
+
QuantizationSpec(start_layer=10, end_layer=32, bins=16),
|
|
53
|
+
],
|
|
54
|
+
vspecs=[
|
|
55
|
+
QuantizationSpec(start_layer=0, end_layer=2, bins=32),
|
|
56
|
+
QuantizationSpec(start_layer=2, end_layer=32, bins=16),
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
# TODO(Jiayi): needs tuning for better quality
|
|
60
|
+
elif model_name in family_9b:
|
|
61
|
+
return CacheGenConfig(
|
|
62
|
+
nlayers=40,
|
|
63
|
+
kspecs=[
|
|
64
|
+
QuantizationSpec(start_layer=0, end_layer=10, bins=32),
|
|
65
|
+
QuantizationSpec(start_layer=10, end_layer=40, bins=16),
|
|
66
|
+
],
|
|
67
|
+
vspecs=[
|
|
68
|
+
QuantizationSpec(start_layer=0, end_layer=2, bins=32),
|
|
69
|
+
QuantizationSpec(start_layer=2, end_layer=40, bins=16),
|
|
70
|
+
],
|
|
71
|
+
)
|
|
72
|
+
elif model_name == "test_model":
|
|
73
|
+
return CacheGenConfig(
|
|
74
|
+
nlayers=32,
|
|
75
|
+
kspecs=[
|
|
76
|
+
QuantizationSpec(start_layer=0, end_layer=10, bins=32),
|
|
77
|
+
QuantizationSpec(start_layer=10, end_layer=32, bins=16),
|
|
78
|
+
],
|
|
79
|
+
vspecs=[
|
|
80
|
+
QuantizationSpec(start_layer=0, end_layer=2, bins=32),
|
|
81
|
+
QuantizationSpec(start_layer=2, end_layer=32, bins=16),
|
|
82
|
+
],
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
try:
|
|
86
|
+
config = AutoConfig.from_pretrained(model_name)
|
|
87
|
+
# Default name caught by num_hidden_layers
|
|
88
|
+
if config.num_hidden_layers is None:
|
|
89
|
+
raise ValueError(
|
|
90
|
+
f"num_hidden_layers is None for model {model_name}"
|
|
91
|
+
)
|
|
92
|
+
if config.num_hidden_layers < 10:
|
|
93
|
+
return CacheGenConfig(
|
|
94
|
+
nlayers=config.num_hidden_layers,
|
|
95
|
+
kspecs=[
|
|
96
|
+
QuantizationSpec(
|
|
97
|
+
start_layer=0,
|
|
98
|
+
end_layer=config.num_hidden_layers,
|
|
99
|
+
bins=32,
|
|
100
|
+
),
|
|
101
|
+
],
|
|
102
|
+
vspecs=[
|
|
103
|
+
QuantizationSpec(
|
|
104
|
+
start_layer=0,
|
|
105
|
+
end_layer=config.num_hidden_layers,
|
|
106
|
+
bins=32,
|
|
107
|
+
),
|
|
108
|
+
],
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
return CacheGenConfig(
|
|
112
|
+
nlayers=config.num_hidden_layers,
|
|
113
|
+
kspecs=[
|
|
114
|
+
QuantizationSpec(start_layer=0, end_layer=10, bins=32),
|
|
115
|
+
QuantizationSpec(
|
|
116
|
+
start_layer=10,
|
|
117
|
+
end_layer=config.num_hidden_layers,
|
|
118
|
+
bins=16,
|
|
119
|
+
),
|
|
120
|
+
],
|
|
121
|
+
vspecs=[
|
|
122
|
+
QuantizationSpec(start_layer=0, end_layer=2, bins=32),
|
|
123
|
+
QuantizationSpec(
|
|
124
|
+
start_layer=2,
|
|
125
|
+
end_layer=config.num_hidden_layers,
|
|
126
|
+
bins=16,
|
|
127
|
+
),
|
|
128
|
+
],
|
|
129
|
+
)
|
|
130
|
+
except Exception as e:
|
|
131
|
+
raise ValueError(
|
|
132
|
+
f"Model {model_name} not supported by CacheGenConfig"
|
|
133
|
+
) from e
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
# Third Party
|
|
6
|
+
import torch
|
|
7
|
+
|
|
8
|
+
# First Party
|
|
9
|
+
from lmcache.logging import init_logger
|
|
10
|
+
from lmcache.storage_backend.serde.cachegen_basics import (
|
|
11
|
+
CacheGenGPUEncoderOutput,
|
|
12
|
+
)
|
|
13
|
+
from lmcache.storage_backend.serde.cachegen_decoder import (
|
|
14
|
+
decode_function_gpu,
|
|
15
|
+
do_dequantize,
|
|
16
|
+
)
|
|
17
|
+
from lmcache.utils import _lmcache_nvtx_annotate
|
|
18
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
19
|
+
from lmcache.v1.memory_management import (
|
|
20
|
+
BytesBufferMemoryObj,
|
|
21
|
+
MemoryFormat,
|
|
22
|
+
MemoryObj,
|
|
23
|
+
MemoryObjMetadata,
|
|
24
|
+
TensorMemoryObj,
|
|
25
|
+
)
|
|
26
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
27
|
+
from lmcache.v1.storage_backend.naive_serde.cachegen_basics import CacheGenConfig
|
|
28
|
+
from lmcache.v1.storage_backend.naive_serde.serde import Deserializer
|
|
29
|
+
|
|
30
|
+
logger = init_logger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CacheGenDeserializer(Deserializer):
|
|
34
|
+
def __init__(self, config: LMCacheEngineConfig, metadata: LMCacheMetadata):
|
|
35
|
+
self.dtype = metadata.kv_dtype
|
|
36
|
+
self.cachegen_config = CacheGenConfig.from_model_name(metadata.model_name)
|
|
37
|
+
self.chunk_size = config.chunk_size
|
|
38
|
+
self.output_buffer: Optional[torch.Tensor] = None
|
|
39
|
+
self.key_bins = self.make_key_bins(self.cachegen_config)
|
|
40
|
+
self.value_bins = self.make_value_bins(self.cachegen_config)
|
|
41
|
+
|
|
42
|
+
def make_key_bins(self, config: CacheGenConfig) -> torch.Tensor:
|
|
43
|
+
ret = torch.zeros(config.nlayers)
|
|
44
|
+
for spec in config.kspecs:
|
|
45
|
+
ret[spec.start_layer : spec.end_layer] = spec.bins
|
|
46
|
+
return ret.cuda()
|
|
47
|
+
|
|
48
|
+
def make_value_bins(self, config: CacheGenConfig) -> torch.Tensor:
|
|
49
|
+
ret = torch.zeros(config.nlayers)
|
|
50
|
+
for spec in config.vspecs:
|
|
51
|
+
ret[spec.start_layer : spec.end_layer] = spec.bins
|
|
52
|
+
return ret.cuda()
|
|
53
|
+
|
|
54
|
+
def get_output_buffer(self, nlayers: int, nchannels: int, ntokens: int):
|
|
55
|
+
if (
|
|
56
|
+
self.output_buffer is None
|
|
57
|
+
or self.output_buffer.shape[1] != 2 * nlayers * nchannels
|
|
58
|
+
):
|
|
59
|
+
self.output_buffer = torch.zeros(
|
|
60
|
+
(self.chunk_size, 2 * nlayers * nchannels), dtype=torch.uint8
|
|
61
|
+
).cuda()
|
|
62
|
+
return self.output_buffer[:ntokens, :]
|
|
63
|
+
|
|
64
|
+
# TODO(Jiayi): A lot of memory copies can be avoided in this function.
|
|
65
|
+
@_lmcache_nvtx_annotate
|
|
66
|
+
def deserialize(self, buffer_memory_obj: BytesBufferMemoryObj) -> MemoryObj:
|
|
67
|
+
encoder_output = CacheGenGPUEncoderOutput.from_bytes(
|
|
68
|
+
buffer_memory_obj.byte_array
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
encoder_output.max_tensors_key = encoder_output.max_tensors_key.cuda()
|
|
72
|
+
encoder_output.max_tensors_value = encoder_output.max_tensors_value.cuda()
|
|
73
|
+
|
|
74
|
+
ntokens = encoder_output.max_tensors_key.shape[1]
|
|
75
|
+
layers_in_key = encoder_output.max_tensors_key.shape[0]
|
|
76
|
+
key, value = decode_function_gpu(
|
|
77
|
+
encoder_output.cdf,
|
|
78
|
+
encoder_output.data_chunks,
|
|
79
|
+
layers_in_key,
|
|
80
|
+
ntokens,
|
|
81
|
+
self.get_output_buffer(
|
|
82
|
+
encoder_output.cdf.shape[0] // 2,
|
|
83
|
+
encoder_output.cdf.shape[1],
|
|
84
|
+
ntokens,
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Temporary fix for #83: change the device of key_bins and value_bins
|
|
89
|
+
# to the device of key and value
|
|
90
|
+
# This requires a long-term fix in the future. Currently,
|
|
91
|
+
# CacheGenGPUEncoderOutput has implicit device in itself.
|
|
92
|
+
# More specifically, if the encoder encodes the tensor on GPU0, the
|
|
93
|
+
# from_bytes will also return a tensor on GPU0
|
|
94
|
+
# We may want to dynamically configure the device based on config and
|
|
95
|
+
# metadata in the future
|
|
96
|
+
if self.key_bins.device != key.device:
|
|
97
|
+
self.key_bins = self.key_bins.to(key.device)
|
|
98
|
+
|
|
99
|
+
if self.value_bins.device != value.device:
|
|
100
|
+
self.value_bins = self.value_bins.cuda()
|
|
101
|
+
|
|
102
|
+
key = do_dequantize(key, self.key_bins, encoder_output.max_tensors_key)
|
|
103
|
+
value = do_dequantize(value, self.value_bins, encoder_output.max_tensors_value)
|
|
104
|
+
""" merge key and value back and reshape """
|
|
105
|
+
nlayers, ntokens, nchannels = key.shape
|
|
106
|
+
blob = torch.stack([key, value]) # [2, nlayers, ntokens, nchannels]
|
|
107
|
+
blob = blob.reshape(
|
|
108
|
+
(
|
|
109
|
+
2,
|
|
110
|
+
nlayers,
|
|
111
|
+
ntokens,
|
|
112
|
+
encoder_output.num_heads,
|
|
113
|
+
encoder_output.head_size,
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
hidden_dim = blob.shape[-1] * blob.shape[-2]
|
|
118
|
+
kv_chunk = blob.reshape(*blob.shape[:-2], hidden_dim).to(
|
|
119
|
+
self.dtype
|
|
120
|
+
) # [nlayers, 2, ntokens, num_heads, head_size]
|
|
121
|
+
|
|
122
|
+
memory_obj = TensorMemoryObj(
|
|
123
|
+
raw_data=kv_chunk,
|
|
124
|
+
metadata=MemoryObjMetadata(
|
|
125
|
+
shape=kv_chunk.shape,
|
|
126
|
+
dtype=kv_chunk.dtype,
|
|
127
|
+
address=-1,
|
|
128
|
+
phy_size=kv_chunk.numel() * kv_chunk.element_size(),
|
|
129
|
+
ref_count=-1, # HACK: avoid mis-free
|
|
130
|
+
fmt=MemoryFormat.KV_2LTD,
|
|
131
|
+
),
|
|
132
|
+
parent_allocator=None,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return memory_obj
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Third Party
|
|
3
|
+
import torch
|
|
4
|
+
|
|
5
|
+
# First Party
|
|
6
|
+
from lmcache.logging import init_logger
|
|
7
|
+
from lmcache.storage_backend.serde.cachegen_encoder import encode_function
|
|
8
|
+
from lmcache.utils import _lmcache_nvtx_annotate
|
|
9
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
10
|
+
from lmcache.v1.memory_management import BytesBufferMemoryObj, MemoryObj
|
|
11
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
12
|
+
from lmcache.v1.storage_backend.naive_serde.cachegen_basics import CacheGenConfig
|
|
13
|
+
from lmcache.v1.storage_backend.naive_serde.serde import Serializer
|
|
14
|
+
|
|
15
|
+
logger = init_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CacheGenSerializer(Serializer):
|
|
19
|
+
def __init__(self, config: LMCacheEngineConfig, metadata: LMCacheMetadata):
|
|
20
|
+
self.cachegen_config = CacheGenConfig.from_model_name(metadata.model_name)
|
|
21
|
+
self.chunk_size = config.chunk_size
|
|
22
|
+
self.key_bins = self.make_key_bins(self.cachegen_config)
|
|
23
|
+
self.value_bins = self.make_value_bins(self.cachegen_config)
|
|
24
|
+
|
|
25
|
+
self.kv_shape = metadata.kv_shape
|
|
26
|
+
|
|
27
|
+
def make_key_bins(self, config: CacheGenConfig) -> torch.Tensor:
|
|
28
|
+
ret = torch.zeros(config.nlayers)
|
|
29
|
+
for spec in config.kspecs:
|
|
30
|
+
ret[spec.start_layer : spec.end_layer] = spec.bins
|
|
31
|
+
return ret.cuda()
|
|
32
|
+
|
|
33
|
+
def make_value_bins(self, config: CacheGenConfig) -> torch.Tensor:
|
|
34
|
+
ret = torch.zeros(config.nlayers)
|
|
35
|
+
for spec in config.vspecs:
|
|
36
|
+
ret[spec.start_layer : spec.end_layer] = spec.bins
|
|
37
|
+
return ret.cuda()
|
|
38
|
+
|
|
39
|
+
# TODO(Jiayi): A lot of memory copies can be avoided in this function.
|
|
40
|
+
@_lmcache_nvtx_annotate
|
|
41
|
+
def serialize(self, memory_obj: MemoryObj) -> BytesBufferMemoryObj:
|
|
42
|
+
"""
|
|
43
|
+
Serialize a KV_2LTD MemoryObj to CACHEGEN_BINARY MemoryObj.
|
|
44
|
+
|
|
45
|
+
Input:
|
|
46
|
+
memory_obj: the memory object to be serialized.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
MemoryObj: the serialized binary memory object.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# TODO(Jiayi): please avoid this copy by directly performing
|
|
53
|
+
# serialization inside gpu connector.
|
|
54
|
+
assert memory_obj.tensor is not None
|
|
55
|
+
tensor = memory_obj.tensor.cuda()
|
|
56
|
+
|
|
57
|
+
# Temporary fix for issue #83: encoder will have the default device 0
|
|
58
|
+
# on all the ray workers. Need to set it to the correct device.
|
|
59
|
+
# Also need to figure out why this happens.
|
|
60
|
+
if torch.cuda.current_device != tensor.device:
|
|
61
|
+
torch.cuda.set_device(tensor.device)
|
|
62
|
+
if tensor.device != self.key_bins.device:
|
|
63
|
+
self.key_bins = self.key_bins.to(tensor.device)
|
|
64
|
+
if tensor.device != self.value_bins.device:
|
|
65
|
+
self.value_bins = self.value_bins.to(tensor.device)
|
|
66
|
+
|
|
67
|
+
# tensor is [2, num_layers, num_tokens, hidden_size]
|
|
68
|
+
tensor = tensor.view(*tensor.shape[:-1], self.kv_shape[-2], self.kv_shape[-1])
|
|
69
|
+
tensor = tensor.permute([1, 0, 2, 3, 4])
|
|
70
|
+
|
|
71
|
+
# TODO(Jiayi): remove hardcoded "2"
|
|
72
|
+
""" expecting a tensor of shape
|
|
73
|
+
[num_layers, 2, num_tokens, num_heads, head_size] """
|
|
74
|
+
ntokens = tensor.shape[2]
|
|
75
|
+
output_dict = encode_function(
|
|
76
|
+
tensor,
|
|
77
|
+
self.cachegen_config,
|
|
78
|
+
self.key_bins,
|
|
79
|
+
self.value_bins,
|
|
80
|
+
ntokens,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return BytesBufferMemoryObj(output_dict.to_bytes())
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# First Party
|
|
3
|
+
from lmcache.v1.memory_management import MemoryObj
|
|
4
|
+
from lmcache.v1.storage_backend.naive_serde.serde import Deserializer, Serializer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class KIVISerializer(Serializer):
|
|
8
|
+
def __init__(self):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
def serialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
12
|
+
# TODO(Yuhan)
|
|
13
|
+
return memory_obj
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class KIVIDeserializer(Deserializer):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def deserialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
21
|
+
# TODO(Yuhan)
|
|
22
|
+
return memory_obj
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# First Party
|
|
3
|
+
from lmcache.v1.memory_management import MemoryObj
|
|
4
|
+
from lmcache.v1.storage_backend.naive_serde.serde import Deserializer, Serializer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class NaiveSerializer(Serializer):
|
|
8
|
+
def __init__(self):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
def serialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
12
|
+
memory_obj.ref_count_up()
|
|
13
|
+
return memory_obj
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class NaiveDeserializer(Deserializer):
|
|
17
|
+
def deserialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
18
|
+
return memory_obj
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
import abc
|
|
4
|
+
|
|
5
|
+
# First Party
|
|
6
|
+
from lmcache.v1.memory_management import MemoryObj
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Serializer(metaclass=abc.ABCMeta):
|
|
10
|
+
@abc.abstractmethod
|
|
11
|
+
def serialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
12
|
+
"""
|
|
13
|
+
Serialize/compress the memory object.
|
|
14
|
+
|
|
15
|
+
Input:
|
|
16
|
+
memory_obj: the memory object to be serialized/compressed.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
MemoryObj: the serialized/compressed memory object.
|
|
20
|
+
"""
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Deserializer(metaclass=abc.ABCMeta):
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def deserialize(self, memory_obj: MemoryObj) -> MemoryObj:
|
|
27
|
+
"""
|
|
28
|
+
Deserialize/decompress the memory object.
|
|
29
|
+
|
|
30
|
+
Input:
|
|
31
|
+
memory_obj: the memory object to be deserialized/decompressed.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
MemoryObj: the deserialized/decompressed memory object.
|
|
35
|
+
None: if the memory allocation fails.
|
|
36
|
+
"""
|
|
37
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Any, Dict, Generic, Optional, Tuple, TypeVar, Union
|
|
4
|
+
import asyncio
|
|
5
|
+
import concurrent.futures
|
|
6
|
+
|
|
7
|
+
NativeClientT = TypeVar("NativeClientT")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConnectorClientBase(Generic[NativeClientT]):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
native_client: NativeClientT,
|
|
14
|
+
loop: Optional[asyncio.AbstractEventLoop] = None,
|
|
15
|
+
):
|
|
16
|
+
self.loop = loop or asyncio.get_running_loop()
|
|
17
|
+
self._client: NativeClientT = native_client
|
|
18
|
+
self._fd = int(self._client.event_fd()) # type: ignore[attr-defined]
|
|
19
|
+
self._closed = False
|
|
20
|
+
# Keepalive refs prevent buffers passed to native code from being
|
|
21
|
+
# garbage-collected while C++ worker threads still hold raw pointers.
|
|
22
|
+
self._pending: Dict[
|
|
23
|
+
int,
|
|
24
|
+
Tuple[
|
|
25
|
+
Union[asyncio.Future, concurrent.futures.Future], str, Tuple[Any, ...]
|
|
26
|
+
],
|
|
27
|
+
] = {}
|
|
28
|
+
self.loop.add_reader(self._fd, self._on_ready)
|
|
29
|
+
|
|
30
|
+
def _on_ready(self) -> None:
|
|
31
|
+
if self._closed:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
while True:
|
|
36
|
+
items = self._client.drain_completions() # type: ignore[attr-defined]
|
|
37
|
+
if not items:
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
for future_id, ok, error, result_bools in items:
|
|
41
|
+
fid = int(future_id)
|
|
42
|
+
entry = self._pending.pop(fid, None)
|
|
43
|
+
if entry is None:
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
fut, op, _keepalive = entry
|
|
47
|
+
if fut.done():
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
if ok:
|
|
51
|
+
if op == "exists":
|
|
52
|
+
if result_bools is not None and len(result_bools) > 0:
|
|
53
|
+
fut.set_result(bool(result_bools[0]))
|
|
54
|
+
else:
|
|
55
|
+
fut.set_result(False)
|
|
56
|
+
elif op == "batch_exists":
|
|
57
|
+
if result_bools is not None:
|
|
58
|
+
fut.set_result(list(result_bools))
|
|
59
|
+
else:
|
|
60
|
+
fut.set_result([])
|
|
61
|
+
else:
|
|
62
|
+
fut.set_result(None)
|
|
63
|
+
else:
|
|
64
|
+
fut.set_exception(RuntimeError(str(error)))
|
|
65
|
+
except Exception as e:
|
|
66
|
+
self._fail_all(RuntimeError(f"native drain_completions failed: {e}"))
|
|
67
|
+
self._shutdown_native(best_effort=True)
|
|
68
|
+
|
|
69
|
+
def _fail_all(self, exc: Exception) -> None:
|
|
70
|
+
for fid, (fut, _, _keepalive) in list(self._pending.items()):
|
|
71
|
+
if not fut.done():
|
|
72
|
+
fut.set_exception(exc)
|
|
73
|
+
self._pending.clear()
|
|
74
|
+
|
|
75
|
+
def _shutdown_native(self, best_effort: bool = False) -> None:
|
|
76
|
+
try:
|
|
77
|
+
self._closed = True
|
|
78
|
+
self.loop.remove_reader(self._fd)
|
|
79
|
+
except Exception:
|
|
80
|
+
if not best_effort:
|
|
81
|
+
raise
|
|
82
|
+
|
|
83
|
+
def _register_future_async(
|
|
84
|
+
self, op: str, future_id: int, keepalive: Tuple[Any, ...] = ()
|
|
85
|
+
) -> asyncio.Future:
|
|
86
|
+
fut = self.loop.create_future()
|
|
87
|
+
self._pending[int(future_id)] = (fut, op, keepalive)
|
|
88
|
+
return fut
|
|
89
|
+
|
|
90
|
+
def _register_future_sync(
|
|
91
|
+
self, op: str, future_id: int, keepalive: Tuple[Any, ...] = ()
|
|
92
|
+
) -> concurrent.futures.Future:
|
|
93
|
+
fut: concurrent.futures.Future = concurrent.futures.Future()
|
|
94
|
+
self._pending[int(future_id)] = (fut, op, keepalive)
|
|
95
|
+
return fut
|
|
96
|
+
|
|
97
|
+
async def get(self, key: str, buf: memoryview) -> None:
|
|
98
|
+
return await self.batch_get([key], [buf])
|
|
99
|
+
|
|
100
|
+
async def set(self, key: str, buf: memoryview) -> None:
|
|
101
|
+
return await self.batch_set([key], [buf])
|
|
102
|
+
|
|
103
|
+
async def exists(self, key: str) -> bool:
|
|
104
|
+
results = await self.batch_exists([key])
|
|
105
|
+
return results[0]
|
|
106
|
+
|
|
107
|
+
async def batch_get(self, keys: list[str], bufs: list[memoryview]) -> None:
|
|
108
|
+
if len(keys) != len(bufs):
|
|
109
|
+
raise ValueError("keys and bufs length mismatch")
|
|
110
|
+
future_id = int(self._client.submit_batch_get(keys, bufs)) # type: ignore[attr-defined]
|
|
111
|
+
fut = self._register_future_async("batch_get", future_id, (keys, tuple(bufs)))
|
|
112
|
+
return await fut
|
|
113
|
+
|
|
114
|
+
async def batch_set(self, keys: list[str], bufs: list[memoryview]) -> None:
|
|
115
|
+
if len(keys) != len(bufs):
|
|
116
|
+
raise ValueError("keys and bufs length mismatch")
|
|
117
|
+
future_id = int(self._client.submit_batch_set(keys, bufs)) # type: ignore[attr-defined]
|
|
118
|
+
fut = self._register_future_async("batch_set", future_id, (keys, tuple(bufs)))
|
|
119
|
+
return await fut
|
|
120
|
+
|
|
121
|
+
async def batch_exists(self, keys: list[str]) -> list[bool]:
|
|
122
|
+
future_id = int(self._client.submit_batch_exists(keys)) # type: ignore[attr-defined]
|
|
123
|
+
fut = self._register_future_async("batch_exists", future_id)
|
|
124
|
+
return await fut
|
|
125
|
+
|
|
126
|
+
async def batched_exists(self, keys: list[str]) -> list[bool]:
|
|
127
|
+
return await self.batch_exists(keys)
|
|
128
|
+
|
|
129
|
+
def get_sync(self, key: str, buf: memoryview) -> None:
|
|
130
|
+
return self.batch_get_sync([key], [buf])
|
|
131
|
+
|
|
132
|
+
def set_sync(self, key: str, buf: memoryview) -> None:
|
|
133
|
+
return self.batch_set_sync([key], [buf])
|
|
134
|
+
|
|
135
|
+
def exists_sync(self, key: str) -> bool:
|
|
136
|
+
results = self.batch_exists_sync([key])
|
|
137
|
+
return results[0]
|
|
138
|
+
|
|
139
|
+
def batch_get_sync(self, keys: list[str], bufs: list[memoryview]) -> None:
|
|
140
|
+
if len(keys) != len(bufs):
|
|
141
|
+
raise ValueError("keys and bufs length mismatch")
|
|
142
|
+
future_id = int(self._client.submit_batch_get(keys, bufs)) # type: ignore[attr-defined]
|
|
143
|
+
fut = self._register_future_sync("batch_get", future_id, (keys, tuple(bufs)))
|
|
144
|
+
return fut.result()
|
|
145
|
+
|
|
146
|
+
def batch_set_sync(self, keys: list[str], bufs: list[memoryview]) -> None:
|
|
147
|
+
if len(keys) != len(bufs):
|
|
148
|
+
raise ValueError("keys and bufs length mismatch")
|
|
149
|
+
future_id = int(self._client.submit_batch_set(keys, bufs)) # type: ignore[attr-defined]
|
|
150
|
+
fut = self._register_future_sync("batch_set", future_id, (keys, tuple(bufs)))
|
|
151
|
+
return fut.result()
|
|
152
|
+
|
|
153
|
+
def batch_exists_sync(self, keys: list[str]) -> list[bool]:
|
|
154
|
+
future_id = int(self._client.submit_batch_exists(keys)) # type: ignore[attr-defined]
|
|
155
|
+
fut = self._register_future_sync("batch_exists", future_id)
|
|
156
|
+
return fut.result()
|
|
157
|
+
|
|
158
|
+
def batched_exists_sync(self, keys: list[str]) -> list[bool]:
|
|
159
|
+
return self.batch_exists_sync(keys)
|
|
160
|
+
|
|
161
|
+
def close(self) -> None:
|
|
162
|
+
if not self._closed:
|
|
163
|
+
self._shutdown_native(best_effort=True)
|
|
164
|
+
self._fail_all(RuntimeError("Client closed"))
|
|
165
|
+
self._client.close() # type: ignore[attr-defined]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Optional
|
|
4
|
+
import asyncio
|
|
5
|
+
|
|
6
|
+
# Local
|
|
7
|
+
from .connector_client_base import ConnectorClientBase
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
# First Party
|
|
11
|
+
from lmcache.lmcache_redis import LMCacheRedisClient
|
|
12
|
+
|
|
13
|
+
REDIS_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
REDIS_AVAILABLE = False
|
|
16
|
+
LMCacheRedisClient = None # type: ignore
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RESPClient(ConnectorClientBase[LMCacheRedisClient]):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
host: str,
|
|
23
|
+
port: int,
|
|
24
|
+
num_workers: int,
|
|
25
|
+
loop: Optional[asyncio.AbstractEventLoop] = None,
|
|
26
|
+
username: str = "",
|
|
27
|
+
password: str = "",
|
|
28
|
+
):
|
|
29
|
+
if not REDIS_AVAILABLE:
|
|
30
|
+
raise RuntimeError(
|
|
31
|
+
"RESPClient requires the C++ Redis extension. "
|
|
32
|
+
"Build with: pip install -e ."
|
|
33
|
+
)
|
|
34
|
+
native_client = LMCacheRedisClient(host, port, num_workers, username, password)
|
|
35
|
+
super().__init__(native_client, loop)
|