import time from typing import Optional from fastapi import Request, HTTPException, Depends from fastapi.security import HTTPAuthorizationCredentials from modules.logger import log from .generate import execute_generation, enforce_rolling_context from .helpers import get_prompt_template from .classes import Stats, Req def setup_routes(self): """Exposes standard endpoints and safely routes traffic requests.""" async def verify_api_key(credentials: Optional[HTTPAuthorizationCredentials] = Depends(self._security)): if not self.api_key: return if credentials is None or credentials.credentials != self.api_key: raise HTTPException( status_code=401, detail="Invalid or missing API key in Authorization header." ) @self.app.get("/health") async def health_check(): return {"status": "healthy", "timestamp": time.time()} @self.app.get("/v1/models", dependencies=[Depends(verify_api_key)]) async def list_models(): model_name = getattr(self.model.config, "_name_or_path", "local-transformer") return { "object": "list", "data": [{ "id": model_name, "object": "model", "created": int(time.time()), "owned_by": "transformers" }] } @self.app.get("/v1/models/{model_id}", dependencies=[Depends(verify_api_key)]) async def retrieve_model(model_id: str): model_name = getattr(self.model.config, "_name_or_path", "local-transformer") if model_id != model_name: raise HTTPException( status_code=404, detail=f"Model '{model_id}' not found. Active model is '{model_name}'." ) return { "id": model_name, "object": "model", "created": int(time.time()), "owned_by": "transformers" } @self.app.post("/v1/completions", dependencies=[Depends(verify_api_key)], tags=["production_hardened"]) async def text_completions(request: Request): json_body = await request.json() prompt_str = json_body.get("prompt", "") if isinstance(prompt_str, list): prompt_str = prompt_str[0] if prompt_str else "" temperature = float(json_body.get("temperature", self.config.temperature)) config = { "max_new_tokens": json_body.get("max_tokens", self.config.max_new_tokens), "temperature": temperature, "top_p": float(json_body.get("top_p", self.config.top_p)), "top_k": int(json_body.get("top_k", self.config.top_k)), "repetition_penalty": float(json_body.get("frequency_penalty", self.config.repetition_penalty)), "do_sample": True if temperature > 0.0 else False } stats = Stats() stats.id = id(request) stats.prompt = len(prompt_str) req = Req(id=id(request), config=config, client=request.scope.get('client', ('0:0.0.0', 0))[0], url=request.scope.get('path', 'err')) log.debug(f"OpenAI: {req}") return await execute_generation( self, stats=stats, request=request, prompt=prompt_str, config=config, stream=json_body.get("stream", self.config.stream), stream_options=json_body.get("stream_options", None), images=None ) @self.app.post("/v1/chat/completions", dependencies=[Depends(verify_api_key)], tags=["production_hardened"]) async def chat_completions(request: Request): json_body = await request.json() messages = json_body.get("messages", []) tools = json_body.get("tools", None) stream_options = json_body.get("stream_options", None) images = json_body.get("images", None) temperature = float(json_body.get("temperature", self.config.temperature)) config = { "max_new_tokens": json_body.get("max_tokens", self.config.max_new_tokens), "temperature": temperature, "top_p": float(json_body.get("top_p", self.config.top_p)), "top_k": int(json_body.get("top_k", self.config.top_k)), "repetition_penalty": float(json_body.get("frequency_penalty", self.config.repetition_penalty)), "do_sample": True if temperature > 0.0 else False } sanitized_messages = enforce_rolling_context(self, messages) try: prompt_str = get_prompt_template(self, sanitized_messages, tools) except Exception as e: raise HTTPException(status_code=400, detail=f"LLM: template execution failure: {str(e)}") from e stats = Stats() stats.id = id(request) stats.messages = len(messages) stats.prompt = len(prompt_str) req = Req(id=id(request), config=config, client=request.scope.get('client', ('0:0.0.0', 0))[0], url=request.scope.get('path', 'err')) log.debug(f"OpenAI: {req}") return await execute_generation( self, stats=stats, request=request, prompt=prompt_str, config=config, stream=json_body.get("stream", self.config.stream), stream_options=stream_options, images=images )