Skip to content

Commit 326d96f

Browse files
authored
Merge pull request #42 from CogStack/v3
Enhance LLM capabilities, multi-engine support, and HF NER pipeline features
2 parents 86e4e68 + 351e155 commit 326d96f

74 files changed

Lines changed: 10216 additions & 914 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/api/api.py

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os.path
55
import app.api.globals as cms_globals
66

7-
from typing import Dict, Any, Optional, Union, Type
7+
from typing import Dict, Any, Optional
88
from concurrent.futures import ThreadPoolExecutor
99
from anyio.lowlevel import RunVar
1010
from anyio import CapacityLimiter
@@ -18,9 +18,14 @@
1818
from app.api.auth.db import make_sure_db_and_tables
1919
from app.api.auth.users import Props
2020
from app.api.dependencies import ModelServiceDep
21-
from app.api.utils import add_exception_handlers, add_rate_limiter, init_vllm_engine
21+
from app.api.utils import (
22+
add_exception_handlers,
23+
add_rate_limiter,
24+
init_vllm_engine,
25+
init_sglang_engine,
26+
ForwardedPrefixMiddleware,
27+
)
2228
from app.config import Settings
23-
from app.domain import Tags, TagsStreamable, TagsGenerative
2429
from app.management.tracker_client import TrackerClient
2530
from app.utils import get_settings, unpack_model_data_package, get_model_data_package_base_name
2631
from app.exception import ConfigurationException
@@ -29,7 +34,6 @@
2934
logging.getLogger("asyncio").setLevel(logging.ERROR)
3035
logger = logging.getLogger("cms")
3136

32-
3337
def get_model_server(config: Settings, msd_overwritten: Optional[ModelServiceDep] = None) -> FastAPI:
3438
"""
3539
Initialises a FastAPI app instance configured for the CMS model service.
@@ -111,7 +115,10 @@ def get_stream_server(config: Settings, msd_overwritten: Optional[ModelServiceDe
111115
return app
112116

113117

114-
def get_generative_server(config: Settings, msd_overwritten: Optional[ModelServiceDep] = None) -> FastAPI:
118+
def get_generative_server(
119+
config: Settings,
120+
msd_overwritten: Optional[ModelServiceDep] = None,
121+
) -> FastAPI:
115122
"""
116123
Initialises a FastAPI instance configured for a generative server.
117124
@@ -134,6 +141,9 @@ def get_generative_server(config: Settings, msd_overwritten: Optional[ModelServi
134141
if config.ENABLE_TRAINING_APIS == "true":
135142
app = _load_supervised_training_router(app)
136143
logger.debug("Supervised training router loaded")
144+
if config.DISABLE_UNSUPERVISED_TRAINING != "true":
145+
app = _load_unsupervised_training_router(app)
146+
logger.debug("Unsupervised training router loaded")
137147
app = _load_training_operations(app)
138148

139149
if config.AUTH_USER_ENABLED == "true":
@@ -147,25 +157,71 @@ def get_generative_server(config: Settings, msd_overwritten: Optional[ModelServi
147157

148158
return app
149159

150-
def get_vllm_server(config: Settings, model_package_path: str, model_name: str, log_level: str = "info") -> FastAPI:
160+
def get_vllm_server(
161+
config: Settings,
162+
model_package_path: str,
163+
model_name: str,
164+
log_level: str = "info",
165+
server_args: Optional[str] = None,
166+
) -> FastAPI:
151167
"""
152168
Initialises a FastAPI instance configured for a vLLM server.
153169
154170
Args:
155171
config (Settings): The CMS configuration.
156172
model_package_path (str): The path to the model package file.
157173
model_name (str): The name of the model.
158-
log_level (str): The log level for the VLLM engine. Default to "info".
174+
log_level (str): The log level for the vLLM engine. Default to "info".
175+
server_args (Optional[str]): The arguments to pass to the vLLM engine.
176+
177+
Returns:
178+
FastAPI: A FastAPI app instance.
179+
"""
180+
181+
app = _get_app(None, streamable=False)
182+
model_dir_path = os.path.join(
183+
os.path.dirname(model_package_path), get_model_data_package_base_name(model_package_path)
184+
)
185+
if unpack_model_data_package(model_package_path, model_dir_path):
186+
async def _startup() -> None:
187+
await init_vllm_engine(app, config, model_dir_path, model_name, log_level, server_args)
188+
189+
app.add_event_handler("startup", _startup)
190+
else:
191+
raise ConfigurationException(f"Model package archive format is not supported: {model_package_path}")
192+
193+
return app
159194

195+
196+
def get_sglang_server(
197+
config: Settings,
198+
model_package_path: str,
199+
model_name: str,
200+
log_level: str = "info",
201+
server_args: Optional[str] = None,
202+
) -> FastAPI:
203+
"""
204+
Initialises a FastAPI instance configured for an SGLang server.
205+
206+
Args:
207+
config (Settings): The CMS configuration.
208+
model_package_path (str): The path to the model package file.
209+
model_name (str): The name of the model.
210+
log_level (str): The log level for the SGLang engine. Default to "info".
211+
server_args (Optional[str]): The arguments to pass to the SGLang engine.
160212
Returns:
161213
FastAPI: A FastAPI app instance.
162214
"""
163215

164216
app = _get_app(None, streamable=False)
165-
model_dir_path = os.path.join(os.path.dirname(model_package_path), get_model_data_package_base_name(model_package_path))
217+
model_dir_path = os.path.join(
218+
os.path.dirname(model_package_path), get_model_data_package_base_name(model_package_path)
219+
)
166220
if unpack_model_data_package(model_package_path, model_dir_path):
167-
loop = asyncio.get_event_loop()
168-
app = loop.run_until_complete(init_vllm_engine(app, model_dir_path, model_name, log_level))
221+
async def _startup() -> None:
222+
await init_sglang_engine(app, config, model_dir_path, model_name, log_level, server_args)
223+
224+
app.add_event_handler("startup", _startup)
169225
else:
170226
raise ConfigurationException(f"Model package archive format is not supported: {model_package_path}")
171227

@@ -204,32 +260,21 @@ def _get_app(
204260
generative: bool = False,
205261
) -> FastAPI:
206262
config = get_settings()
207-
tags: Union[Type[Tags], Type[TagsStreamable], Type[TagsGenerative]]
208-
if generative:
209-
tags = TagsGenerative
210-
elif streamable:
211-
tags = TagsStreamable
212-
else:
213-
tags = Tags
214-
tags_metadata = [{
215-
"name": tag.name,
216-
"description": tag.value
217-
} for tag in tags]
263+
218264
app = FastAPI(
219265
title="CogStack ModelServe",
220266
summary="A model serving and governance system for CogStack NLP solutions",
221267
docs_url=None,
222268
redoc_url=None,
223269
debug=(config.DEBUG == "true"),
224-
openapi_tags=tags_metadata,
225270
)
271+
272+
app.add_middleware(ForwardedPrefixMiddleware) # type: ignore
226273
add_exception_handlers(app)
227274

228-
instrumentator = None
229-
if not generative:
230-
instrumentator = Instrumentator(
231-
excluded_handlers=["/docs", "/redoc", "/metrics", "/openapi.json", "/favicon.ico", "none"]
232-
).instrument(app)
275+
instrumentator = Instrumentator(
276+
excluded_handlers=["/docs", "/redoc", "/metrics", "/openapi.json", "/favicon.ico", "none"]
277+
).instrument(app)
233278

234279
if msd_overwritten is not None:
235280
cms_globals.model_service_dep = msd_overwritten
@@ -279,8 +324,9 @@ async def redoc_doc(req: Request) -> HTMLResponse:
279324
)
280325

281326
@app.get("/", include_in_schema=False)
282-
async def root_redirect() -> RedirectResponse:
283-
return RedirectResponse(url="/docs")
327+
async def root_redirect(req: Request) -> RedirectResponse:
328+
root_path = req.scope.get("root_path", "").rstrip("/")
329+
return RedirectResponse(url=f"{req.url.scheme}://{req.url.netloc}{root_path}/docs")
284330

285331
@app.on_event("shutdown")
286332
async def on_shutdown() -> None:

app/api/dependencies.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from fastapi import HTTPException, Query
77
from starlette.status import HTTP_400_BAD_REQUEST
8-
98
from typing import Optional
109
from app.config import Settings
1110
from app.domain import ModelType
@@ -14,11 +13,10 @@
1413
from app.model_services.base import AbstractModelService
1514
from app.management.model_manager import ModelManager
1615

17-
TRACKING_ID_REGEX = re.compile(r"^[a-zA-Z0-9][\w\-]{0,255}$")
1816

17+
TRACKING_ID_REGEX = re.compile(r"^[a-zA-Z0-9][\w\-]{0,255}$")
1918
logger = logging.getLogger("cms")
2019

21-
2220
class ModelServiceDep(object):
2321
"""Dependency class for injecting the CMS model service based on the given model type."""
2422

0 commit comments

Comments
 (0)