mirror of
https://github.com/theroyallab/tabbyAPI.git
synced 2026-03-14 15:57:27 +00:00
* improve validation * remove to_gen_params functions * update changes for all endpoint types * OAI: Fix calls to generation Chat completion and completion need to have prompt split out before pushing to the backend. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Convert Top-K values of -1 to 0 Some OAI implementations use -1 as disabled instead of 0. Therefore, add a coalesce case. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Format and space out Make the code more readable. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Fix mirostat Field items are nested in data within a Pydantic FieldInfo Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Format Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Fix banned_tokens and allowed_tokens conversion If the provided string has whitespace, trim it before splitting. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Add helpful log to dry_sequence_breakers Let the user know if the sequence errors out. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Apply validators in right order Validators need to be applied in order from top to bottom, this is why the after validator was not being applied properly. Set the model to validate default params for sampler override purposes. This can be turned off if there are unclear errors. Signed-off-by: kingbri <bdashore3@proton.me> * Endpoints: Format Cleanup and semantically fix field validators Signed-off-by: kingbri <bdashore3@proton.me> * Kobold: Update validators and fix parameter application Validators on parent fields cannot see child fields. Therefore, validate using the child fields instead and alter the parent field data from there. Also fix badwordsids casting. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Remove validate defaults and fix mirostat If a user sets an override to a non-default value, that's their own fault. Run validator on the actual mirostat_mode parameter rather than the alternate mirostat parameter. Signed-off-by: kingbri <bdashore3@proton.me> * Kobold: Rework badwordsids Currently, this serves to ban the EOS token. All other functionality was legacy, so remove it. Signed-off-by: kingbri <bdashore3@proton.me> * Model: Remove HuggingfaceConfig This was only necessary for badwordsids. All other fields are handled by exl2. Keep the class as a stub if it's needed again. Signed-off-by: kingbri <bdashore3@proton.me> * Kobold: Bump kcpp impersonation TabbyAPI supports XTC now. Signed-off-by: kingbri <bdashore3@proton.me> * Sampling: Change alias to validation_alias Reduces the probability for errors and makes the class consistent. Signed-off-by: kingbri <bdashore3@proton.me> * OAI: Use constraints for validation Instead of adding a model_validator, use greater than or equal to constraints provided by Pydantic. Signed-off-by: kingbri <bdashore3@proton.me> * Tree: Lint Signed-off-by: kingbri <bdashore3@proton.me> --------- Co-authored-by: SecretiveShell <84923604+SecretiveShell@users.noreply.github.com> Co-authored-by: kingbri <bdashore3@proton.me>
162 lines
4.3 KiB
Python
162 lines
4.3 KiB
Python
from sys import maxsize
|
|
from fastapi import APIRouter, Depends, Request
|
|
from sse_starlette import EventSourceResponse
|
|
|
|
from common import model
|
|
from common.auth import check_api_key
|
|
from common.model import check_model_container
|
|
from common.utils import unwrap
|
|
from endpoints.core.utils.model import get_current_model
|
|
from endpoints.Kobold.types.generation import (
|
|
AbortRequest,
|
|
AbortResponse,
|
|
CheckGenerateRequest,
|
|
GenerateRequest,
|
|
GenerateResponse,
|
|
)
|
|
from endpoints.Kobold.types.model import CurrentModelResponse, MaxLengthResponse
|
|
from endpoints.Kobold.types.token import TokenCountRequest, TokenCountResponse
|
|
from endpoints.Kobold.utils.generation import (
|
|
abort_generation,
|
|
generation_status,
|
|
get_generation,
|
|
stream_generation,
|
|
)
|
|
|
|
|
|
api_name = "KoboldAI"
|
|
router = APIRouter(prefix="/api")
|
|
urls = {
|
|
"Generation": "http://{host}:{port}/api/v1/generate",
|
|
"Streaming": "http://{host}:{port}/api/extra/generate/stream",
|
|
}
|
|
|
|
kai_router = APIRouter()
|
|
extra_kai_router = APIRouter()
|
|
|
|
|
|
def setup():
|
|
router.include_router(kai_router, prefix="/v1")
|
|
router.include_router(kai_router, prefix="/latest", include_in_schema=False)
|
|
router.include_router(extra_kai_router, prefix="/extra")
|
|
|
|
return router
|
|
|
|
|
|
@kai_router.post(
|
|
"/generate",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def generate(request: Request, data: GenerateRequest) -> GenerateResponse:
|
|
response = await get_generation(data, request)
|
|
|
|
return response
|
|
|
|
|
|
@extra_kai_router.post(
|
|
"/generate/stream",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def generate_stream(request: Request, data: GenerateRequest) -> GenerateResponse:
|
|
response = EventSourceResponse(stream_generation(data, request), ping=maxsize)
|
|
|
|
return response
|
|
|
|
|
|
@extra_kai_router.post(
|
|
"/abort",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def abort_generate(data: AbortRequest) -> AbortResponse:
|
|
response = await abort_generation(data.genkey)
|
|
|
|
return response
|
|
|
|
|
|
@extra_kai_router.get(
|
|
"/generate/check",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
@extra_kai_router.post(
|
|
"/generate/check",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def check_generate(data: CheckGenerateRequest) -> GenerateResponse:
|
|
response = await generation_status(data.genkey)
|
|
|
|
return response
|
|
|
|
|
|
@kai_router.get(
|
|
"/model", dependencies=[Depends(check_api_key), Depends(check_model_container)]
|
|
)
|
|
async def current_model() -> CurrentModelResponse:
|
|
"""Fetches the current model and who owns it."""
|
|
|
|
current_model_card = get_current_model()
|
|
return {"result": f"{current_model_card.owned_by}/{current_model_card.id}"}
|
|
|
|
|
|
@extra_kai_router.post(
|
|
"/tokencount",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def get_tokencount(data: TokenCountRequest) -> TokenCountResponse:
|
|
raw_tokens = model.container.encode_tokens(data.prompt)
|
|
tokens = unwrap(raw_tokens, [])
|
|
return TokenCountResponse(value=len(tokens), ids=tokens)
|
|
|
|
|
|
@kai_router.get(
|
|
"/config/max_length",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
@kai_router.get(
|
|
"/config/max_context_length",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
@extra_kai_router.get(
|
|
"/true_max_context_length",
|
|
dependencies=[Depends(check_api_key), Depends(check_model_container)],
|
|
)
|
|
async def get_max_length() -> MaxLengthResponse:
|
|
"""Fetches the max length of the model."""
|
|
|
|
max_length = model.container.get_model_parameters().get("max_seq_len")
|
|
return {"value": max_length}
|
|
|
|
|
|
@kai_router.get("/info/version")
|
|
async def get_version():
|
|
"""Impersonate KAI United."""
|
|
|
|
return {"result": "1.2.5"}
|
|
|
|
|
|
@extra_kai_router.get("/version")
|
|
async def get_extra_version():
|
|
"""Impersonate Koboldcpp."""
|
|
|
|
return {"result": "KoboldCpp", "version": "1.74"}
|
|
|
|
|
|
@kai_router.get("/config/soft_prompts_list")
|
|
async def get_available_softprompts():
|
|
"""Used for KAI compliance."""
|
|
|
|
return {"values": []}
|
|
|
|
|
|
@kai_router.get("/config/soft_prompt")
|
|
async def get_current_softprompt():
|
|
"""Used for KAI compliance."""
|
|
|
|
return {"value": ""}
|
|
|
|
|
|
@kai_router.put("/config/soft_prompt")
|
|
async def set_current_softprompt():
|
|
"""Used for KAI compliance."""
|
|
|
|
return {}
|