isagellm-core 0.3.0.5__tar.gz → 0.3.0.6__tar.gz

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.
Files changed (77) hide show
  1. {isagellm_core-0.3.0.5/src/isagellm_core.egg-info → isagellm_core-0.3.0.6}/PKG-INFO +9 -1
  2. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/README.md +6 -0
  3. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/pyproject.toml +6 -1
  4. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6/src/isagellm_core.egg-info}/PKG-INFO +9 -1
  5. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/isagellm_core.egg-info/SOURCES.txt +9 -0
  6. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/isagellm_core.egg-info/entry_points.txt +3 -0
  7. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/isagellm_core.egg-info/requires.txt +2 -0
  8. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__init__.py +9 -2
  9. isagellm_core-0.3.0.6/src/sagellm_core/__init__.pyc +0 -0
  10. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__main__.pyc +0 -0
  11. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/__init__.cpython-311.pyc +0 -0
  12. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/base_engine.cpython-311.pyc +0 -0
  13. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/config.cpython-311.pyc +0 -0
  14. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/demo.cpython-311.pyc +0 -0
  15. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/engine.cpython-311.pyc +0 -0
  16. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/engine_factory.cpython-311.pyc +0 -0
  17. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/engine_server.cpython-311.pyc +0 -0
  18. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/factory.cpython-311.pyc +0 -0
  19. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/health.cpython-311.pyc +0 -0
  20. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/mock_engine.cpython-311.pyc +0 -0
  21. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/pd_executor.cpython-311.pyc +0 -0
  22. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/plugins.cpython-311.pyc +0 -0
  23. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/runner.cpython-311.pyc +0 -0
  24. isagellm_core-0.3.0.6/src/sagellm_core/__pycache__/runtime.cpython-311.pyc +0 -0
  25. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/__pycache__/workload.cpython-311.pyc +0 -0
  26. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/config.pyc +0 -0
  27. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/demo.pyc +0 -0
  28. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engine.pyc +0 -0
  29. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engine_factory.pyc +0 -0
  30. isagellm_core-0.3.0.6/src/sagellm_core/engine_server.pyc +0 -0
  31. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__init__.pyc +0 -0
  32. isagellm_core-0.3.0.6/src/sagellm_core/engines/__pycache__/__init__.cpython-311.pyc +0 -0
  33. isagellm_core-0.3.0.6/src/sagellm_core/engines/__pycache__/ascend.cpython-311.pyc +0 -0
  34. isagellm_core-0.3.0.6/src/sagellm_core/engines/__pycache__/cpu.cpython-311.pyc +0 -0
  35. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__pycache__/embedding.cpython-311.pyc +0 -0
  36. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__pycache__/hf_cuda.cpython-311.pyc +0 -0
  37. isagellm_core-0.3.0.6/src/sagellm_core/engines/__pycache__/mock.cpython-311.pyc +0 -0
  38. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__pycache__/pytorch.cpython-311.pyc +0 -0
  39. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__pycache__/pytorch_engine.cpython-311.pyc +0 -0
  40. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/ascend.pyc +0 -0
  41. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/cpu.pyc +0 -0
  42. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/embedding.pyc +0 -0
  43. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/hf_cuda.pyc +0 -0
  44. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/pytorch.pyc +0 -0
  45. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/pytorch_engine.pyc +0 -0
  46. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/factory.pyc +0 -0
  47. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/health.pyc +0 -0
  48. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/pd_executor.pyc +0 -0
  49. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/plugins.pyc +0 -0
  50. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/runner.pyc +0 -0
  51. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/runtime.pyc +0 -0
  52. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/workload.pyc +0 -0
  53. isagellm_core-0.3.0.6/tests/test_engine_server.py +154 -0
  54. isagellm_core-0.3.0.5/src/sagellm_core/__init__.pyc +0 -0
  55. isagellm_core-0.3.0.5/src/sagellm_core/__pycache__/__init__.cpython-311.pyc +0 -0
  56. isagellm_core-0.3.0.5/src/sagellm_core/engines/__pycache__/__init__.cpython-311.pyc +0 -0
  57. isagellm_core-0.3.0.5/src/sagellm_core/engines/__pycache__/cpu.cpython-311.pyc +0 -0
  58. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/MANIFEST.in +0 -0
  59. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/setup.cfg +0 -0
  60. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/setup.py +0 -0
  61. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/isagellm_core.egg-info/dependency_links.txt +0 -0
  62. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/isagellm_core.egg-info/top_level.txt +0 -0
  63. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/engines/__init__.py +0 -0
  64. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/src/sagellm_core/py.typed +0 -0
  65. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_ci_smoke.py +0 -0
  66. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_config.py +0 -0
  67. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_cpu_engine_contract.py +0 -0
  68. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_cpu_engine_error_handling.py +0 -0
  69. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_e2e_cpu_integration.py +0 -0
  70. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_engine.py +0 -0
  71. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_engine_behavior_parity.py +0 -0
  72. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_engine_contract.py +0 -0
  73. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_engine_contract_simplified.py +0 -0
  74. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_pd_separation.py +0 -0
  75. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_pytorch_engine.py +0 -0
  76. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_streaming_pd.py +0 -0
  77. {isagellm_core-0.3.0.5 → isagellm_core-0.3.0.6}/tests/test_task0_10_workload.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isagellm-core
3
- Version: 0.3.0.5
3
+ Version: 0.3.0.6
4
4
  Summary: sageLLM core runtime with PD separation (MVP)
5
5
  Author: IntelliStream Team
6
6
  License: Proprietary - IntelliStream
@@ -17,6 +17,8 @@ Requires-Dist: isagellm-protocol<0.4.0,>=0.3.0.2
17
17
  Requires-Dist: isagellm-backend<0.4.0,>=0.3.0.5
18
18
  Requires-Dist: isagellm-comm<0.4.0,>=0.3.0.1
19
19
  Requires-Dist: isagellm-kv-cache<0.4.0,>=0.3.0.1
20
+ Requires-Dist: fastapi>=0.100.0
21
+ Requires-Dist: uvicorn>=0.22.0
20
22
  Provides-Extra: dev
21
23
  Requires-Dist: pytest>=7.0.0; extra == "dev"
22
24
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -79,6 +81,12 @@ sageLLM Core - 引擎协调层与运行时系统
79
81
  - ⚙️ 配置系统 - YAML/JSON + Pydantic v2
80
82
  - ✅ CPU-First - 无 GPU 测试支持
81
83
 
84
+ ## MoE(规划中)
85
+
86
+ - MoE 路由/调度/执行图由 **sagellm-core** 主责
87
+ - 依赖 **sagellm-comm**(all-to-all/拓扑通信)与 **sagellm-backend**(专家算子/内核)
88
+ - 需先在 Protocol 中补充全局字段(如 router 元数据、专家负载指标)
89
+
82
90
  ## 安装
83
91
 
84
92
  ```bash
@@ -50,6 +50,12 @@ sageLLM Core - 引擎协调层与运行时系统
50
50
  - ⚙️ 配置系统 - YAML/JSON + Pydantic v2
51
51
  - ✅ CPU-First - 无 GPU 测试支持
52
52
 
53
+ ## MoE(规划中)
54
+
55
+ - MoE 路由/调度/执行图由 **sagellm-core** 主责
56
+ - 依赖 **sagellm-comm**(all-to-all/拓扑通信)与 **sagellm-backend**(专家算子/内核)
57
+ - 需先在 Protocol 中补充全局字段(如 router 元数据、专家负载指标)
58
+
53
59
  ## 安装
54
60
 
55
61
  ```bash
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "isagellm-core"
7
- version = "0.3.0.5"
7
+ version = "0.3.0.6"
8
8
  description = "sageLLM core runtime with PD separation (MVP)"
9
9
  readme = "README.md"
10
10
  requires-python = "==3.11.*"
@@ -24,6 +24,8 @@ dependencies = [
24
24
  "isagellm-backend>=0.3.0.5,<0.4.0",
25
25
  "isagellm-comm>=0.3.0.1,<0.4.0",
26
26
  "isagellm-kv-cache>=0.3.0.1,<0.4.0",
27
+ "fastapi>=0.100.0",
28
+ "uvicorn>=0.22.0",
27
29
  ]
28
30
 
29
31
  [project.optional-dependencies]
@@ -52,6 +54,9 @@ sagellm_core = ["py.typed"]
52
54
  [tool.ruff]
53
55
  line-length = 100
54
56
 
57
+ [project.scripts]
58
+ sage-engine = "sagellm_core.engine_server:main"
59
+
55
60
  [project.entry-points."sagellm.engines"]
56
61
  cpu = "sagellm_core.engines.cpu:create_cpu_engine"
57
62
  hf-cuda = "sagellm_core.engines.hf_cuda:create_hf_cuda_engine"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isagellm-core
3
- Version: 0.3.0.5
3
+ Version: 0.3.0.6
4
4
  Summary: sageLLM core runtime with PD separation (MVP)
5
5
  Author: IntelliStream Team
6
6
  License: Proprietary - IntelliStream
@@ -17,6 +17,8 @@ Requires-Dist: isagellm-protocol<0.4.0,>=0.3.0.2
17
17
  Requires-Dist: isagellm-backend<0.4.0,>=0.3.0.5
18
18
  Requires-Dist: isagellm-comm<0.4.0,>=0.3.0.1
19
19
  Requires-Dist: isagellm-kv-cache<0.4.0,>=0.3.0.1
20
+ Requires-Dist: fastapi>=0.100.0
21
+ Requires-Dist: uvicorn>=0.22.0
20
22
  Provides-Extra: dev
21
23
  Requires-Dist: pytest>=7.0.0; extra == "dev"
22
24
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -79,6 +81,12 @@ sageLLM Core - 引擎协调层与运行时系统
79
81
  - ⚙️ 配置系统 - YAML/JSON + Pydantic v2
80
82
  - ✅ CPU-First - 无 GPU 测试支持
81
83
 
84
+ ## MoE(规划中)
85
+
86
+ - MoE 路由/调度/执行图由 **sagellm-core** 主责
87
+ - 依赖 **sagellm-comm**(all-to-all/拓扑通信)与 **sagellm-backend**(专家算子/内核)
88
+ - 需先在 Protocol 中补充全局字段(如 router 元数据、专家负载指标)
89
+
82
90
  ## 安装
83
91
 
84
92
  ```bash
@@ -15,6 +15,7 @@ src/sagellm_core/config.pyc
15
15
  src/sagellm_core/demo.pyc
16
16
  src/sagellm_core/engine.pyc
17
17
  src/sagellm_core/engine_factory.pyc
18
+ src/sagellm_core/engine_server.pyc
18
19
  src/sagellm_core/factory.pyc
19
20
  src/sagellm_core/health.pyc
20
21
  src/sagellm_core/pd_executor.pyc
@@ -24,14 +25,19 @@ src/sagellm_core/runner.pyc
24
25
  src/sagellm_core/runtime.pyc
25
26
  src/sagellm_core/workload.pyc
26
27
  src/sagellm_core/__pycache__/__init__.cpython-311.pyc
28
+ src/sagellm_core/__pycache__/base_engine.cpython-311.pyc
27
29
  src/sagellm_core/__pycache__/config.cpython-311.pyc
28
30
  src/sagellm_core/__pycache__/demo.cpython-311.pyc
29
31
  src/sagellm_core/__pycache__/engine.cpython-311.pyc
30
32
  src/sagellm_core/__pycache__/engine_factory.cpython-311.pyc
33
+ src/sagellm_core/__pycache__/engine_server.cpython-311.pyc
31
34
  src/sagellm_core/__pycache__/factory.cpython-311.pyc
32
35
  src/sagellm_core/__pycache__/health.cpython-311.pyc
36
+ src/sagellm_core/__pycache__/mock_engine.cpython-311.pyc
37
+ src/sagellm_core/__pycache__/pd_executor.cpython-311.pyc
33
38
  src/sagellm_core/__pycache__/plugins.cpython-311.pyc
34
39
  src/sagellm_core/__pycache__/runner.cpython-311.pyc
40
+ src/sagellm_core/__pycache__/runtime.cpython-311.pyc
35
41
  src/sagellm_core/__pycache__/workload.cpython-311.pyc
36
42
  src/sagellm_core/engines/__init__.py
37
43
  src/sagellm_core/engines/__init__.pyc
@@ -42,9 +48,11 @@ src/sagellm_core/engines/hf_cuda.pyc
42
48
  src/sagellm_core/engines/pytorch.pyc
43
49
  src/sagellm_core/engines/pytorch_engine.pyc
44
50
  src/sagellm_core/engines/__pycache__/__init__.cpython-311.pyc
51
+ src/sagellm_core/engines/__pycache__/ascend.cpython-311.pyc
45
52
  src/sagellm_core/engines/__pycache__/cpu.cpython-311.pyc
46
53
  src/sagellm_core/engines/__pycache__/embedding.cpython-311.pyc
47
54
  src/sagellm_core/engines/__pycache__/hf_cuda.cpython-311.pyc
55
+ src/sagellm_core/engines/__pycache__/mock.cpython-311.pyc
48
56
  src/sagellm_core/engines/__pycache__/pytorch.cpython-311.pyc
49
57
  src/sagellm_core/engines/__pycache__/pytorch_engine.cpython-311.pyc
50
58
  tests/test_ci_smoke.py
@@ -56,6 +64,7 @@ tests/test_engine.py
56
64
  tests/test_engine_behavior_parity.py
57
65
  tests/test_engine_contract.py
58
66
  tests/test_engine_contract_simplified.py
67
+ tests/test_engine_server.py
59
68
  tests/test_pd_separation.py
60
69
  tests/test_pytorch_engine.py
61
70
  tests/test_streaming_pd.py
@@ -1,3 +1,6 @@
1
+ [console_scripts]
2
+ sage-engine = sagellm_core.engine_server:main
3
+
1
4
  [sagellm.engines]
2
5
  ascend = sagellm_core.engines.ascend:create_ascend_engine
3
6
  cpu = sagellm_core.engines.cpu:create_cpu_engine
@@ -4,6 +4,8 @@ isagellm-protocol<0.4.0,>=0.3.0.2
4
4
  isagellm-backend<0.4.0,>=0.3.0.5
5
5
  isagellm-comm<0.4.0,>=0.3.0.1
6
6
  isagellm-kv-cache<0.4.0,>=0.3.0.1
7
+ fastapi>=0.100.0
8
+ uvicorn>=0.22.0
7
9
 
8
10
  [dev]
9
11
  pytest>=7.0.0
@@ -12,7 +12,7 @@
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- __version__ = "0.3.0.5"
15
+ __version__ = "0.3.0.6"
16
16
 
17
17
  from sagellm_core.engine import BaseEngine, EngineInstanceConfig
18
18
  from sagellm_core.config import (
@@ -45,6 +45,10 @@ from sagellm_core.runner import DemoRunner, RunnerContext
45
45
  from sagellm_core.runtime import DistributedConfig, DistributedRuntime, RuntimeState
46
46
  from sagellm_core.pd_executor import PDExecutionContext, PDSeparatedExecutor
47
47
 
48
+ # Engine HTTP Server
49
+ from sagellm_core.engine_server import app as engine_server_app
50
+ from sagellm_core.engine_server import main as serve_engine
51
+
48
52
  # PyTorch engine (optional, loaded lazily)
49
53
  PyTorchEngine = None
50
54
  PyTorchEngineConfig = None
@@ -88,7 +92,7 @@ try:
88
92
  except Exception:
89
93
  pass # torch or transformers not available
90
94
 
91
- __version__ = "0.3.0.5"
95
+ __version__ = "0.3.0.6"
92
96
 
93
97
  __all__ = [
94
98
  # Version
@@ -136,4 +140,7 @@ __all__ = [
136
140
  "RuntimeState",
137
141
  "PDExecutionContext",
138
142
  "PDSeparatedExecutor",
143
+ # Engine HTTP Server
144
+ "engine_server_app",
145
+ "serve_engine",
139
146
  ]
@@ -0,0 +1,154 @@
1
+ """Engine Server 单元测试.
2
+
3
+ 测试 Engine HTTP Server 的端点和功能。
4
+
5
+ 注意:需要真实引擎环境的测试已标记为 @pytest.mark.integration,
6
+ 默认跳过,可通过 pytest -m integration 运行。
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import pytest
12
+
13
+ from sagellm_protocol.types import Request
14
+
15
+
16
+ # ─────────────────────────────────────────────────────────────────
17
+ # CompletionRequest Model Tests (不需要引擎)
18
+ # ─────────────────────────────────────────────────────────────────
19
+
20
+
21
+ def test_completion_request_to_protocol():
22
+ """测试 CompletionRequest 转换为 Protocol Request."""
23
+ from sagellm_core.engine_server import CompletionRequest
24
+
25
+ req = CompletionRequest(
26
+ request_id="req-1",
27
+ trace_id="trace-1",
28
+ model="test-model",
29
+ prompt="Hello",
30
+ max_tokens=100,
31
+ stream=False,
32
+ temperature=0.7,
33
+ top_p=0.9,
34
+ )
35
+
36
+ protocol_req = req.to_protocol_request()
37
+
38
+ assert protocol_req.request_id == "req-1"
39
+ assert protocol_req.trace_id == "trace-1"
40
+ assert protocol_req.model == "test-model"
41
+ assert protocol_req.prompt == "Hello"
42
+ assert protocol_req.max_tokens == 100
43
+ assert protocol_req.stream is False
44
+ assert protocol_req.temperature == 0.7
45
+ assert protocol_req.top_p == 0.9
46
+
47
+
48
+ def test_completion_request_minimal():
49
+ """测试 CompletionRequest 最小必需字段."""
50
+ from sagellm_core.engine_server import CompletionRequest
51
+
52
+ req = CompletionRequest(
53
+ request_id="req-1",
54
+ trace_id="trace-1",
55
+ model="test-model",
56
+ prompt="Hello",
57
+ max_tokens=50,
58
+ )
59
+
60
+ assert req.stream is False # 默认值
61
+ assert req.temperature is None
62
+ assert req.top_p is None
63
+
64
+
65
+ def test_completion_request_with_metadata():
66
+ """测试 CompletionRequest 带 metadata."""
67
+ from sagellm_core.engine_server import CompletionRequest
68
+
69
+ req = CompletionRequest(
70
+ request_id="req-1",
71
+ trace_id="trace-1",
72
+ model="test-model",
73
+ prompt="Hello",
74
+ max_tokens=50,
75
+ metadata={"user_id": "user-123", "session_id": "sess-456"},
76
+ )
77
+
78
+ protocol_req = req.to_protocol_request()
79
+ assert protocol_req.metadata == {"user_id": "user-123", "session_id": "sess-456"}
80
+
81
+
82
+ def test_completion_request_validation():
83
+ """测试 CompletionRequest 字段验证."""
84
+ from sagellm_core.engine_server import CompletionRequest
85
+ from pydantic import ValidationError
86
+
87
+ # max_tokens 必须 > 0
88
+ with pytest.raises(ValidationError):
89
+ CompletionRequest(
90
+ request_id="req-1",
91
+ trace_id="trace-1",
92
+ model="test-model",
93
+ prompt="Hello",
94
+ max_tokens=0, # Invalid
95
+ )
96
+
97
+ # temperature 必须在 (0, 2] 范围内
98
+ with pytest.raises(ValidationError):
99
+ CompletionRequest(
100
+ request_id="req-1",
101
+ trace_id="trace-1",
102
+ model="test-model",
103
+ prompt="Hello",
104
+ max_tokens=50,
105
+ temperature=3.0, # Invalid, > 2
106
+ )
107
+
108
+
109
+ # ─────────────────────────────────────────────────────────────────
110
+ # Module Import Tests
111
+ # ─────────────────────────────────────────────────────────────────
112
+
113
+
114
+ def test_engine_server_imports():
115
+ """测试 engine_server 模块可以正常导入."""
116
+ from sagellm_core.engine_server import (
117
+ app,
118
+ main,
119
+ get_engine,
120
+ set_engine,
121
+ CompletionRequest,
122
+ )
123
+
124
+ assert app is not None
125
+ assert callable(main)
126
+ assert callable(get_engine)
127
+ assert callable(set_engine)
128
+
129
+
130
+ def test_engine_server_app_routes():
131
+ """测试 FastAPI app 包含所需路由."""
132
+ from sagellm_core.engine_server import app
133
+
134
+ routes = [route.path for route in app.routes]
135
+
136
+ assert "/" in routes
137
+ assert "/health" in routes
138
+ assert "/info" in routes
139
+ assert "/v1/completions" in routes
140
+ assert "/v1/completions/stream" in routes
141
+
142
+
143
+ # ─────────────────────────────────────────────────────────────────
144
+ # CLI Tests
145
+ # ─────────────────────────────────────────────────────────────────
146
+
147
+
148
+ def test_cli_argparse():
149
+ """测试 CLI 参数解析."""
150
+ import argparse
151
+ from sagellm_core.engine_server import main
152
+
153
+ # 验证 main 是可调用的
154
+ assert callable(main)