lmcache-cli 0.4.6.dev0__py3-none-any.whl → 0.4.8.dev21__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 +32 -21
- lmcache/_version.py +3 -3
- lmcache/banner.py +119 -0
- lmcache/cli/commands/__init__.py +31 -25
- lmcache/cli/commands/bench/__init__.py +16 -605
- lmcache/cli/commands/bench/engine_bench/command.py +599 -0
- lmcache/cli/commands/bench/engine_bench/config.py +3 -3
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +2 -2
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +13 -3
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +0 -20
- lmcache/cli/commands/bench/l2_adapter_bench/__init__.py +2 -0
- lmcache/cli/commands/bench/l2_adapter_bench/command.py +630 -0
- lmcache/cli/commands/bench/l2_adapter_bench/data.py +195 -0
- lmcache/cli/commands/bench/l2_adapter_bench/result.py +174 -0
- lmcache/cli/commands/bench/l2_adapter_bench/runner.py +319 -0
- lmcache/cli/commands/bench/server_bench/__init__.py +2 -0
- lmcache/cli/commands/bench/server_bench/command.py +719 -0
- lmcache/cli/commands/bench/server_bench/helpers.py +1125 -0
- lmcache/cli/commands/coordinator.py +155 -0
- lmcache/cli/commands/describe.py +47 -24
- lmcache/cli/commands/query/__init__.py +35 -114
- lmcache/cli/commands/query/engine_command.py +130 -0
- lmcache/cli/commands/query/kvcache_command.py +46 -0
- lmcache/cli/commands/quota/__init__.py +91 -0
- lmcache/cli/commands/quota/delete_command.py +77 -0
- lmcache/cli/commands/quota/get_command.py +80 -0
- lmcache/cli/commands/quota/helpers.py +78 -0
- lmcache/cli/commands/quota/list_command.py +76 -0
- lmcache/cli/commands/quota/set_command.py +90 -0
- lmcache/cli/commands/server.py +11 -3
- lmcache/cli/commands/trace/__init__.py +35 -404
- lmcache/cli/commands/trace/info_command.py +77 -0
- lmcache/cli/commands/trace/replay_command.py +340 -0
- lmcache/cli/main.py +2 -0
- lmcache/integration/base_service_factory.py +6 -2
- lmcache/integration/sglang/multi_process_adapter.py +544 -0
- lmcache/integration/sglang/sglang_adapter.py +64 -26
- lmcache/integration/sglang/utils.py +12 -22
- lmcache/integration/tensorrt_llm/tensorrt_mp_adapter.py +8 -7
- lmcache/integration/vllm/kv_cache_group_edits.py +402 -0
- lmcache/integration/vllm/kv_cache_groups.py +190 -0
- lmcache/integration/vllm/lmcache_mp_connector.py +332 -250
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +8 -1
- lmcache/integration/vllm/lmcache_mp_connector_0201.py +7 -1
- lmcache/integration/vllm/vllm_multi_process_adapter.py +511 -138
- lmcache/integration/vllm/vllm_v1_adapter.py +76 -6
- lmcache/lmcache_frontend/__init__.py +2 -0
- lmcache/lmcache_frontend/app.py +1036 -0
- lmcache/lmcache_frontend/config.json +1 -0
- lmcache/lmcache_frontend/heartbeat.py +233 -0
- lmcache/lmcache_frontend/lmcache_mp_plugin/__init__.py +1 -0
- lmcache/lmcache_frontend/lmcache_mp_plugin/lmcache_mp_frontend_plugin.py +176 -0
- lmcache/lmcache_frontend/run_mp_server_with_frontend.sh +21 -0
- lmcache/lmcache_frontend/static/css/style.css +190 -0
- lmcache/lmcache_frontend/static/img/logo.png +0 -0
- lmcache/lmcache_frontend/static/index.html +239 -0
- lmcache/lmcache_frontend/static/js/app.js +1189 -0
- lmcache/native_storage_ops.pyi +61 -2
- lmcache/observability.py +160 -98
- lmcache/{non_cuda_equivalents.py → python_ops_fallback.py} +1224 -68
- lmcache/tools/controller_benchmark/handlers/__init__.py +11 -26
- lmcache/tools/simple_discover_service.py +118 -0
- lmcache/utils.py +66 -1
- lmcache/v1/cache_controller/controllers/kv_controller.py +1 -1
- lmcache/v1/cache_controller/executor.py +2 -2
- lmcache/v1/cache_engine.py +94 -12
- lmcache/v1/check/check_mode_test_l2_adapter.py +2 -2
- lmcache/v1/compute/attention/flash_attn.py +13 -4
- lmcache/v1/compute/attention/utils.py +20 -0
- lmcache/v1/config.py +82 -1
- lmcache/v1/distributed/api.py +71 -42
- lmcache/v1/distributed/config.py +88 -0
- lmcache/v1/distributed/eviction.py +1 -1
- lmcache/v1/distributed/internal_api.py +32 -1
- lmcache/v1/distributed/l1_manager.py +14 -2
- lmcache/v1/distributed/l2_adapters/aerospike_l2_adapter.py +239 -0
- lmcache/v1/distributed/l2_adapters/base.py +9 -30
- lmcache/v1/distributed/l2_adapters/dax_l2_adapter.py +1073 -77
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +25 -28
- lmcache/v1/distributed/l2_adapters/hfbucket_l2_adapter.py +902 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +7 -16
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +10 -10
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +11 -5
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +12 -25
- lmcache/v1/distributed/l2_adapters/raw_block_l2_adapter.py +37 -6
- lmcache/v1/distributed/l2_adapters/reconfiguration.py +64 -0
- lmcache/v1/distributed/l2_adapters/s3_l2_adapter.py +16 -12
- lmcache/v1/distributed/l2_adapters/serde_wrapper.py +16 -25
- lmcache/v1/distributed/memory_manager/__init__.py +25 -0
- lmcache/v1/distributed/memory_manager/gds_l1_memory_manager.py +158 -0
- lmcache/v1/distributed/memory_manager/l1_manager_protocol.py +50 -0
- lmcache/v1/distributed/{memory_manager.py → memory_manager/l1_memory_manager.py} +37 -0
- lmcache/v1/distributed/serde/__init__.py +16 -0
- lmcache/v1/distributed/serde/asym_k16_v8.py +537 -0
- lmcache/v1/distributed/serde/async_processor.py +16 -1
- lmcache/v1/distributed/serde/multi.py +293 -0
- lmcache/v1/distributed/serde/utils.py +2 -1
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +14 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +128 -118
- lmcache/v1/distributed/storage_controllers/store_controller.py +11 -20
- lmcache/v1/distributed/storage_manager.py +267 -34
- lmcache/v1/gpu_connector/__init__.py +152 -39
- lmcache/v1/gpu_connector/_cufile_async.py +384 -0
- lmcache/v1/gpu_connector/gds_context.py +408 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +49 -41
- lmcache/v1/gpu_connector/gpu_ops.py +8 -1
- lmcache/v1/gpu_connector/hpu_connector.py +22 -13
- lmcache/v1/gpu_connector/musa_connectors.py +825 -0
- lmcache/v1/gpu_connector/musa_native.py +218 -0
- lmcache/v1/gpu_connector/utils.py +518 -284
- lmcache/v1/gpu_connector/xpu_connectors.py +1525 -647
- lmcache/v1/health_monitor/base.py +21 -40
- lmcache/v1/internal_api_server/api_server.py +11 -8
- lmcache/v1/internal_api_server/common/loglevel_api.py +5 -5
- lmcache/v1/internal_api_server/common/run_script_api.py +16 -6
- lmcache/v1/internal_api_server/vllm/cache_api.py +5 -3
- lmcache/v1/kv_codec/__init__.py +63 -0
- lmcache/v1/kv_codec/asym_k16_v8.py +473 -0
- lmcache/v1/kv_codec/encoded_kv.py +403 -0
- lmcache/v1/kv_codec/errors.py +39 -0
- lmcache/v1/kv_layer_groups.py +447 -207
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +20 -11
- lmcache/v1/lookup_client/factory.py +1 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +10 -18
- lmcache/v1/memory_management.py +358 -126
- lmcache/v1/metadata.py +3 -3
- lmcache/v1/mp_coordinator/__init__.py +17 -0
- lmcache/v1/mp_coordinator/__main__.py +28 -0
- lmcache/v1/mp_coordinator/app.py +134 -0
- lmcache/v1/mp_coordinator/blend_client.py +266 -0
- lmcache/v1/mp_coordinator/blend_directory.py +236 -0
- lmcache/v1/mp_coordinator/config.py +120 -0
- lmcache/v1/mp_coordinator/http_apis/__init__.py +6 -0
- lmcache/v1/mp_coordinator/http_apis/blend_directory_api.py +103 -0
- lmcache/v1/mp_coordinator/http_apis/health_api.py +20 -0
- lmcache/v1/mp_coordinator/http_apis/instances_api.py +136 -0
- lmcache/v1/mp_coordinator/http_apis/l2_api.py +255 -0
- lmcache/v1/mp_coordinator/l2/__init__.py +1 -0
- lmcache/v1/mp_coordinator/l2/event_listener.py +150 -0
- lmcache/v1/mp_coordinator/l2/eviction_manager.py +161 -0
- lmcache/v1/mp_coordinator/l2/usage_manager.py +121 -0
- lmcache/v1/mp_coordinator/registrar.py +130 -0
- lmcache/v1/mp_coordinator/registry.py +161 -0
- lmcache/v1/mp_coordinator/schemas.py +286 -0
- lmcache/v1/mp_observability/README.md +2 -3
- lmcache/v1/mp_observability/config.py +9 -22
- lmcache/v1/mp_observability/event.py +19 -0
- lmcache/v1/mp_observability/event_bus.py +22 -0
- lmcache/v1/mp_observability/otel_init.py +1 -1
- lmcache/v1/mp_observability/subscribers/__init__.py +0 -2
- lmcache/v1/mp_observability/subscribers/logging/l2.py +7 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +0 -2
- lmcache/v1/mp_observability/subscribers/metrics/cb_server.py +14 -0
- lmcache/v1/mp_observability/subscribers/metrics/event_bus.py +1 -19
- lmcache/v1/mp_observability/subscribers/metrics/l0_l1_throughput.py +4 -4
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +6 -6
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +19 -12
- lmcache/v1/mp_observability/subscribers/metrics/l1_failures.py +2 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +8 -8
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +94 -63
- lmcache/v1/mp_observability/subscribers/metrics/l2_failures.py +1 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2_throughput.py +23 -25
- lmcache/v1/mp_observability/subscribers/metrics/lookup.py +4 -4
- lmcache/v1/mp_observability/subscribers/metrics/sm_lifecycle.py +2 -2
- lmcache/v1/mp_observability/subscribers/metrics/utils.py +28 -0
- lmcache/v1/mp_observability/subscribers/tracing/cb_server.py +44 -5
- lmcache/v1/mp_observability/trace/codecs.py +38 -3
- lmcache/v1/multiprocess/config.py +241 -5
- lmcache/v1/multiprocess/custom_types.py +81 -34
- lmcache/v1/multiprocess/engine_context.py +247 -0
- lmcache/v1/multiprocess/engine_module.py +65 -0
- lmcache/v1/multiprocess/group_view.py +239 -0
- lmcache/v1/multiprocess/http_apis/cache_api.py +14 -14
- lmcache/v1/multiprocess/http_apis/common_api.py +1 -1
- lmcache/v1/multiprocess/http_apis/reconfigure_api.py +374 -0
- lmcache/v1/multiprocess/http_server.py +85 -6
- lmcache/v1/multiprocess/modules/__init__.py +1 -0
- lmcache/v1/multiprocess/{blend_server_v2.py → modules/blend.py} +283 -445
- lmcache/v1/multiprocess/modules/blend_v3.py +1522 -0
- lmcache/v1/multiprocess/modules/engine_driven_transfer.py +444 -0
- lmcache/v1/multiprocess/modules/lmcache_driven_transfer.py +968 -0
- lmcache/v1/multiprocess/modules/lookup.py +467 -0
- lmcache/v1/multiprocess/modules/management.py +129 -0
- lmcache/v1/multiprocess/modules/server_transfer.py +440 -0
- lmcache/v1/multiprocess/mq.py +212 -76
- lmcache/v1/multiprocess/native_completion.py +150 -0
- lmcache/v1/multiprocess/posix_shm.py +273 -0
- lmcache/v1/multiprocess/protocol.py +2 -2
- lmcache/v1/multiprocess/protocols/__init__.py +2 -0
- lmcache/v1/multiprocess/protocols/base.py +12 -0
- lmcache/v1/multiprocess/protocols/blend.py +9 -9
- lmcache/v1/multiprocess/protocols/blend_v2.py +5 -5
- lmcache/v1/multiprocess/protocols/blend_v3.py +69 -0
- lmcache/v1/multiprocess/protocols/engine.py +99 -8
- lmcache/v1/multiprocess/server.py +230 -1106
- lmcache/v1/multiprocess/session.py +3 -2
- lmcache/v1/multiprocess/token_hasher.py +21 -12
- lmcache/v1/multiprocess/transfer_context/__init__.py +43 -0
- lmcache/v1/multiprocess/transfer_context/base.py +714 -0
- lmcache/v1/multiprocess/transfer_context/pickle.py +110 -0
- lmcache/v1/multiprocess/transfer_context/shm.py +218 -0
- lmcache/v1/multiprocess/transfer_context/worker_transfer.py +550 -0
- lmcache/v1/periodic_thread.py +5 -0
- lmcache/v1/pin_monitor.py +24 -10
- lmcache/v1/platform/__init__.py +50 -0
- lmcache/v1/platform/_registry.py +130 -0
- lmcache/v1/platform/base_cache_context.py +339 -0
- lmcache/v1/platform/cache_context.py +205 -0
- lmcache/v1/platform/cpu/__init__.py +35 -0
- lmcache/v1/platform/cpu/cache_context.py +443 -0
- lmcache/v1/platform/cpu/shm.py +292 -0
- lmcache/v1/platform/cpu/stub_cpu_device.py +338 -0
- lmcache/v1/platform/cuda/__init__.py +44 -0
- lmcache/v1/platform/cuda/cache_context.py +631 -0
- lmcache/v1/platform/event_notifier.py +17 -0
- lmcache/v1/storage_backend/__init__.py +24 -4
- lmcache/v1/storage_backend/abstract_backend.py +2 -2
- lmcache/v1/storage_backend/batched_message_sender.py +11 -7
- lmcache/v1/storage_backend/cache_policy/fifo.py +1 -1
- lmcache/v1/storage_backend/cache_policy/lfu.py +1 -1
- lmcache/v1/storage_backend/cache_policy/lru.py +1 -1
- lmcache/v1/storage_backend/cache_policy/mru.py +1 -1
- lmcache/v1/storage_backend/connector/__init__.py +13 -33
- lmcache/v1/storage_backend/connector/bigtable_adapter.py +30 -0
- lmcache/v1/storage_backend/connector/bigtable_config.py +136 -0
- lmcache/v1/storage_backend/connector/bigtable_connector.py +929 -0
- lmcache/v1/storage_backend/connector/bigtable_schema.py +57 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +20 -4
- lmcache/v1/storage_backend/dax/core.py +229 -0
- lmcache/v1/storage_backend/gds_backend.py +10 -5
- lmcache/v1/storage_backend/hipfile_shim.py +167 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +75 -16
- lmcache/v1/storage_backend/local_disk_backend.py +2 -0
- lmcache/v1/storage_backend/native_clients/aerospike_client.py +74 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +671 -181
- lmcache/v1/storage_backend/pd_backend.py +1 -1
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +107 -8
- lmcache/v1/storage_backend/raw_block/core.py +505 -35
- lmcache/v1/storage_backend/raw_block/key_codec.py +11 -7
- lmcache/v1/storage_backend/remote_backend.py +12 -14
- lmcache/v1/storage_backend/storage_manager.py +65 -15
- lmcache/v1/token_database.py +30 -2
- lmcache/v1/utils/subclass_discovery.py +219 -0
- lmcache_cli-0.4.8.dev21.dist-info/METADATA +179 -0
- {lmcache_cli-0.4.6.dev0.dist-info → lmcache_cli-0.4.8.dev21.dist-info}/RECORD +249 -146
- lmcache/cli/commands/test_cache.py +0 -997
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +0 -69
- lmcache/v1/multiprocess/gpu_context.py +0 -540
- lmcache_cli-0.4.6.dev0.dist-info/METADATA +0 -186
- {lmcache_cli-0.4.6.dev0.dist-info → lmcache_cli-0.4.8.dev21.dist-info}/WHEEL +0 -0
- {lmcache_cli-0.4.6.dev0.dist-info → lmcache_cli-0.4.8.dev21.dist-info}/entry_points.txt +0 -0
- {lmcache_cli-0.4.6.dev0.dist-info → lmcache_cli-0.4.8.dev21.dist-info}/licenses/LICENSE +0 -0
- {lmcache_cli-0.4.6.dev0.dist-info → lmcache_cli-0.4.8.dev21.dist-info}/top_level.txt +0 -0
lmcache/__init__.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
import importlib
|
|
6
6
|
import sys
|
|
7
|
+
import types
|
|
7
8
|
|
|
8
9
|
# First Party
|
|
9
10
|
from lmcache.logging import init_logger
|
|
@@ -30,10 +31,8 @@ def _detect_device() -> tuple[Any, str]:
|
|
|
30
31
|
|
|
31
32
|
Returns:
|
|
32
33
|
tuple[Any, str]: A tuple of (torch_device_module, device_type_string),
|
|
33
|
-
e.g. ``(torch.cuda, "cuda")
|
|
34
|
-
|
|
35
|
-
Raises:
|
|
36
|
-
RuntimeError: If no supported accelerator is found (checked CUDA, XPU, HPU).
|
|
34
|
+
e.g. ``(torch.cuda, "cuda")``, ``(torch.musa, "musa")``, or
|
|
35
|
+
``(torch.xpu, "xpu")``.
|
|
37
36
|
"""
|
|
38
37
|
try:
|
|
39
38
|
# Third Party
|
|
@@ -41,18 +40,27 @@ def _detect_device() -> tuple[Any, str]:
|
|
|
41
40
|
except ImportError:
|
|
42
41
|
return None, "cpu" # fallback,CLI-only
|
|
43
42
|
|
|
44
|
-
if hasattr(torch, "
|
|
43
|
+
if hasattr(torch, "musa") and torch.musa.is_available(): # type: ignore[attr-defined]
|
|
44
|
+
logger.info("MUSA device is available. Using MUSA for LMCache engine.")
|
|
45
|
+
return torch.musa, "musa" # type: ignore[attr-defined]
|
|
46
|
+
elif hasattr(torch, "xpu") and torch.xpu.is_available():
|
|
45
47
|
return torch.xpu, "xpu"
|
|
46
48
|
elif hasattr(torch, "hpu") and torch.hpu.is_available():
|
|
47
49
|
return torch.hpu, "hpu"
|
|
48
|
-
|
|
49
|
-
# Fallback: always return torch.cuda for backward compatibility
|
|
50
|
-
# with existing tests and code paths that assume CUDA is the default.
|
|
50
|
+
elif torch.cuda.is_available():
|
|
51
51
|
return torch.cuda, "cuda"
|
|
52
|
+
else:
|
|
53
|
+
# First Party
|
|
54
|
+
from lmcache.v1.platform.cpu.stub_cpu_device import StubCPUDevice
|
|
55
|
+
|
|
56
|
+
# Fallback: always return torch, cpu as stub
|
|
57
|
+
return StubCPUDevice("cpu"), "cpu"
|
|
52
58
|
|
|
53
59
|
|
|
54
60
|
torch_dev, torch_device_type = _detect_device()
|
|
55
61
|
|
|
62
|
+
logger.info(" torch_dev=%s, torch_device_type=%s", torch_dev, torch_device_type)
|
|
63
|
+
|
|
56
64
|
|
|
57
65
|
# --------------------------
|
|
58
66
|
# Dynamic backend selection
|
|
@@ -61,10 +69,16 @@ def _get_backend() -> Any:
|
|
|
61
69
|
"""
|
|
62
70
|
Try backends in order, first successful import wins.
|
|
63
71
|
"""
|
|
72
|
+
default_module = importlib.import_module("lmcache.python_ops_fallback")
|
|
64
73
|
# Third Party
|
|
65
74
|
import torch
|
|
66
75
|
|
|
67
76
|
backend_candidates = [
|
|
77
|
+
(
|
|
78
|
+
"lmcache.xpu_ops",
|
|
79
|
+
"xpu_ops",
|
|
80
|
+
lambda: torch.xpu.is_available(),
|
|
81
|
+
),
|
|
68
82
|
(
|
|
69
83
|
"lmcache.c_ops",
|
|
70
84
|
"cuda_ops",
|
|
@@ -73,8 +87,6 @@ def _get_backend() -> Any:
|
|
|
73
87
|
# should extend to more HWs..
|
|
74
88
|
]
|
|
75
89
|
|
|
76
|
-
imported = False
|
|
77
|
-
module = None
|
|
78
90
|
for module_name, backend_name, predicate in backend_candidates:
|
|
79
91
|
# 1 Check whether the backend is available before importing
|
|
80
92
|
try:
|
|
@@ -93,21 +105,16 @@ def _get_backend() -> Any:
|
|
|
93
105
|
continue
|
|
94
106
|
# 2 Run availability check for the backend
|
|
95
107
|
try:
|
|
96
|
-
|
|
108
|
+
backend_module = importlib.import_module(module_name)
|
|
109
|
+
merged_module = types.ModuleType("lmcache.c_ops")
|
|
110
|
+
merged_module.__dict__.update(default_module.__dict__)
|
|
111
|
+
merged_module.__dict__.update(backend_module.__dict__)
|
|
97
112
|
logger.info("Using backend: %s", module_name)
|
|
98
|
-
|
|
99
|
-
break
|
|
113
|
+
return merged_module
|
|
100
114
|
except Exception as e:
|
|
101
115
|
logger.warning("Failed to import backend %s: %s", module_name, e)
|
|
102
116
|
|
|
103
|
-
|
|
104
|
-
try:
|
|
105
|
-
logger.warning("Fallback to python backend lmcache.non_cuda_equivalents")
|
|
106
|
-
module = importlib.import_module("lmcache.non_cuda_equivalents")
|
|
107
|
-
logger.info("Using backend: lmcache.non_cuda_equivalents")
|
|
108
|
-
except ImportError as e:
|
|
109
|
-
raise ImportError("No backend could be imported for lmcache.") from e
|
|
110
|
-
return module
|
|
117
|
+
return default_module
|
|
111
118
|
|
|
112
119
|
|
|
113
120
|
# --------------------------
|
|
@@ -115,6 +122,10 @@ def _get_backend() -> Any:
|
|
|
115
122
|
# --------------------------
|
|
116
123
|
try:
|
|
117
124
|
_ops = _get_backend()
|
|
125
|
+
# override lmcache.c_ops with merged module,
|
|
126
|
+
# in which:
|
|
127
|
+
# python_ops_fallback as base,
|
|
128
|
+
# use backend implementation if exists
|
|
118
129
|
sys.modules["lmcache.c_ops"] = _ops
|
|
119
130
|
except (ImportError, ModuleNotFoundError):
|
|
120
131
|
logger.debug("No compute backend loaded; CLI-only mode (torch/numba not installed)")
|
lmcache/_version.py
CHANGED
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.4.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 4,
|
|
21
|
+
__version__ = version = '0.4.8.dev21'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 4, 8, 'dev21')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g5d621e1e5'
|
lmcache/banner.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Startup banner shown when LMCache starts serving.
|
|
3
|
+
|
|
4
|
+
The banner is printed at most once per process, to ``stderr``, by the
|
|
5
|
+
``lmcache`` CLI and by the vLLM connector integrations (scheduler role
|
|
6
|
+
only, so tensor-parallel deployments print a single banner). Setting the
|
|
7
|
+
``LMCACHE_DISABLE_BANNER=1`` environment variable suppresses it.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Standard
|
|
11
|
+
from typing import TextIO
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
# First Party
|
|
16
|
+
from lmcache import _version
|
|
17
|
+
|
|
18
|
+
_LMCACHE_VERSION = getattr(_version, "__version__", "unknown")
|
|
19
|
+
_LMCACHE_COMMIT = getattr(_version, "__commit_id__", "")
|
|
20
|
+
except ImportError: # pragma: no cover - version file is generated at build time
|
|
21
|
+
_LMCACHE_VERSION = "unknown"
|
|
22
|
+
_LMCACHE_COMMIT = ""
|
|
23
|
+
|
|
24
|
+
DISABLE_BANNER_ENV = "LMCACHE_DISABLE_BANNER"
|
|
25
|
+
|
|
26
|
+
LMCACHE_WEBSITE = "https://lmcache.ai/"
|
|
27
|
+
LMCACHE_RECIPES = "https://docs.lmcache.ai/recipes"
|
|
28
|
+
LMCACHE_LINKEDIN = "https://www.linkedin.com/company/lmcache-lab"
|
|
29
|
+
|
|
30
|
+
# Solarized palette, 24-bit ANSI escapes (TTY only): "LM" in bold italic
|
|
31
|
+
# orange (#cb4b16), "Cache" in cyan (#2aa198).
|
|
32
|
+
_LM_STYLE = "\x1b[1;3;38;2;203;75;22m"
|
|
33
|
+
_CACHE_STYLE = "\x1b[38;2;42;161;152m"
|
|
34
|
+
_DIM_STYLE = "\x1b[2m"
|
|
35
|
+
_RESET = "\x1b[0m"
|
|
36
|
+
|
|
37
|
+
# Figlet "standard" font, split into the two color groups.
|
|
38
|
+
_LM_ART = (
|
|
39
|
+
" _ __ __ ",
|
|
40
|
+
"| | | \\/ |",
|
|
41
|
+
"| | | |\\/| |",
|
|
42
|
+
"| |___| | | |",
|
|
43
|
+
"|_____|_| |_|",
|
|
44
|
+
)
|
|
45
|
+
_CACHE_ART = (
|
|
46
|
+
" ____ _ ",
|
|
47
|
+
" / ___|__ _ ___| |__ ___ ",
|
|
48
|
+
"| | / _` |/ __| '_ \\ / _ \\",
|
|
49
|
+
"| |__| (_| | (__| | | | __/",
|
|
50
|
+
" \\____\\__,_|\\___|_| |_|\\___|",
|
|
51
|
+
)
|
|
52
|
+
_RIGHT_TEXT_GAP = " "
|
|
53
|
+
|
|
54
|
+
_banner_printed = False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _banner_disabled() -> bool:
|
|
58
|
+
"""Return whether ``LMCACHE_DISABLE_BANNER`` is set to a truthy value."""
|
|
59
|
+
return os.getenv(DISABLE_BANNER_ENV, "").strip().lower() in ("1", "true", "yes")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _render_banner(colored: bool) -> str:
|
|
63
|
+
"""Render the banner text.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
colored: Whether to wrap the logo in ANSI color escapes.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The multi-line banner: the LMCache logo with the version (and
|
|
70
|
+
commit id when available), website, recipes, and LinkedIn links
|
|
71
|
+
on its right, and a final line describing the
|
|
72
|
+
``LMCACHE_DISABLE_BANNER`` opt-out. A blank line surrounds the
|
|
73
|
+
banner on each side to set it apart from adjacent log output.
|
|
74
|
+
"""
|
|
75
|
+
lm_style = _LM_STYLE if colored else ""
|
|
76
|
+
cache_style = _CACHE_STYLE if colored else ""
|
|
77
|
+
dim_style = _DIM_STYLE if colored else ""
|
|
78
|
+
reset = _RESET if colored else ""
|
|
79
|
+
|
|
80
|
+
version = f"LMCache v{_LMCACHE_VERSION}"
|
|
81
|
+
if _LMCACHE_COMMIT:
|
|
82
|
+
version += f" ({_LMCACHE_COMMIT[:9]})"
|
|
83
|
+
right_text = {
|
|
84
|
+
1: version,
|
|
85
|
+
2: f"Website: {LMCACHE_WEBSITE}",
|
|
86
|
+
3: f"Recipes: {LMCACHE_RECIPES}",
|
|
87
|
+
4: f"LinkedIn: {LMCACHE_LINKEDIN}",
|
|
88
|
+
}
|
|
89
|
+
lines = [""]
|
|
90
|
+
for row, (lm_part, cache_part) in enumerate(zip(_LM_ART, _CACHE_ART, strict=True)):
|
|
91
|
+
line = f"{lm_style}{lm_part}{reset} {cache_style}{cache_part}{reset}"
|
|
92
|
+
if row in right_text:
|
|
93
|
+
line += _RIGHT_TEXT_GAP + right_text[row]
|
|
94
|
+
lines.append(line)
|
|
95
|
+
lines.append(f"{dim_style}Set {DISABLE_BANNER_ENV}=1 to hide this banner.{reset}")
|
|
96
|
+
lines.append("")
|
|
97
|
+
return "\n".join(lines)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def print_banner_once(stream: TextIO) -> None:
|
|
101
|
+
"""Print the LMCache startup banner to ``stream`` at most once.
|
|
102
|
+
|
|
103
|
+
The banner shows the LMCache logo, version, and website, followed by
|
|
104
|
+
a hint describing the ``LMCACHE_DISABLE_BANNER`` opt-out. ANSI colors
|
|
105
|
+
are used only when ``stream`` is a TTY. Subsequent calls in the same
|
|
106
|
+
process are no-ops, as are all calls when ``LMCACHE_DISABLE_BANNER``
|
|
107
|
+
is set to ``1``/``true``/``yes``.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
stream: Destination text stream. Callers should pass
|
|
111
|
+
``sys.stderr`` so the banner never interferes with
|
|
112
|
+
machine-readable stdout output.
|
|
113
|
+
"""
|
|
114
|
+
global _banner_printed
|
|
115
|
+
if _banner_printed or _banner_disabled():
|
|
116
|
+
return
|
|
117
|
+
_banner_printed = True
|
|
118
|
+
stream.write(_render_banner(stream.isatty()) + "\n")
|
|
119
|
+
stream.flush()
|
lmcache/cli/commands/__init__.py
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
"""CLI subcommand package.
|
|
3
3
|
|
|
4
|
-
To add a new command
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
To add a new top-level command, simply create a new module (or sub-package
|
|
5
|
+
with an ``__init__.py``) under this package that defines a concrete
|
|
6
|
+
:class:`BaseCommand` subclass. It will be discovered and registered
|
|
7
|
+
automatically — no edits to this file are required.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# First Party
|
|
11
11
|
from lmcache.cli.commands.base import BaseCommand
|
|
12
|
-
from lmcache.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
12
|
+
from lmcache.v1.utils.subclass_discovery import discover_subclasses
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _discover_commands() -> list[BaseCommand]:
|
|
16
|
+
"""Scan direct submodules of this package and collect all concrete
|
|
17
|
+
:class:`BaseCommand` subclasses, returning one instance per class.
|
|
18
|
+
|
|
19
|
+
Import errors are intentionally re-raised: a broken CLI command
|
|
20
|
+
module should fail loudly rather than silently disappear from the
|
|
21
|
+
CLI.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def _raise(module_name: str, exc: Exception) -> None:
|
|
25
|
+
raise exc
|
|
26
|
+
|
|
27
|
+
return [
|
|
28
|
+
cls()
|
|
29
|
+
for cls in discover_subclasses(
|
|
30
|
+
__name__,
|
|
31
|
+
BaseCommand, # type: ignore[type-abstract]
|
|
32
|
+
module_filter=lambda name: name != "base",
|
|
33
|
+
on_import_error=_raise,
|
|
34
|
+
)
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
ALL_COMMANDS: list[BaseCommand] = _discover_commands()
|
|
33
39
|
|
|
34
40
|
__all__ = ["ALL_COMMANDS", "BaseCommand"]
|