154 lines
4.9 KiB
Python
154 lines
4.9 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
from app.core.deps import CurrentUser, DbDep, require_perm
|
|
from app.core.exceptions import ok
|
|
from app.schemas.llm import (
|
|
ChatRequest,
|
|
ModelCreate,
|
|
ModelUpdate,
|
|
ProviderCreate,
|
|
ProviderUpdate,
|
|
RuleCreate,
|
|
RuleUpdate,
|
|
UsageRead,
|
|
)
|
|
from app.services import llm_service
|
|
|
|
router = APIRouter(prefix="/llm", tags=["llm"])
|
|
|
|
|
|
# -------- Providers --------
|
|
|
|
@router.get("/providers", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def list_providers(db: DbDep) -> dict:
|
|
return ok([p.model_dump() for p in await llm_service.list_providers(db)])
|
|
|
|
|
|
@router.post("/providers", dependencies=[Depends(require_perm("system:executor:update"))])
|
|
async def create_provider(data: ProviderCreate, db: DbDep) -> dict:
|
|
p = await llm_service.create_provider(db, data)
|
|
return ok(llm_service.provider_to_read(p).model_dump())
|
|
|
|
|
|
@router.patch(
|
|
"/providers/{pid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def update_provider(pid: int, data: ProviderUpdate, db: DbDep) -> dict:
|
|
p = await llm_service.update_provider(db, pid, data)
|
|
return ok(llm_service.provider_to_read(p).model_dump())
|
|
|
|
|
|
@router.delete(
|
|
"/providers/{pid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def delete_provider(pid: int, db: DbDep) -> dict:
|
|
await llm_service.delete_provider(db, pid)
|
|
return ok()
|
|
|
|
|
|
# -------- Models --------
|
|
|
|
@router.get("/models", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def list_models(db: DbDep) -> dict:
|
|
return ok([m.model_dump() for m in await llm_service.list_models(db)])
|
|
|
|
|
|
@router.post("/models", dependencies=[Depends(require_perm("system:executor:update"))])
|
|
async def create_model(data: ModelCreate, db: DbDep) -> dict:
|
|
m = await llm_service.create_model(db, data)
|
|
return ok((await llm_service.model_to_read(db, m)).model_dump())
|
|
|
|
|
|
@router.patch(
|
|
"/models/{mid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def update_model(mid: int, data: ModelUpdate, db: DbDep) -> dict:
|
|
m = await llm_service.update_model(db, mid, data)
|
|
return ok((await llm_service.model_to_read(db, m)).model_dump())
|
|
|
|
|
|
@router.delete(
|
|
"/models/{mid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def delete_model(mid: int, db: DbDep) -> dict:
|
|
await llm_service.delete_model(db, mid)
|
|
return ok()
|
|
|
|
|
|
# -------- Routing --------
|
|
|
|
@router.get("/rules", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def list_rules(db: DbDep) -> dict:
|
|
return ok([r.model_dump() for r in await llm_service.list_rules(db)])
|
|
|
|
|
|
@router.post("/rules", dependencies=[Depends(require_perm("system:executor:update"))])
|
|
async def create_rule(data: RuleCreate, db: DbDep) -> dict:
|
|
r = await llm_service.create_rule(db, data)
|
|
return ok({
|
|
"id": r.id, "name": r.name, "priority": r.priority,
|
|
"conditions": r.conditions, "model_id": r.model_id,
|
|
"enabled": r.enabled, "description": r.description,
|
|
})
|
|
|
|
|
|
@router.patch(
|
|
"/rules/{rid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def update_rule(rid: int, data: RuleUpdate, db: DbDep) -> dict:
|
|
r = await llm_service.update_rule(db, rid, data)
|
|
return ok({
|
|
"id": r.id, "name": r.name, "priority": r.priority,
|
|
"conditions": r.conditions, "model_id": r.model_id,
|
|
"enabled": r.enabled, "description": r.description,
|
|
})
|
|
|
|
|
|
@router.delete(
|
|
"/rules/{rid}", dependencies=[Depends(require_perm("system:executor:update"))]
|
|
)
|
|
async def delete_rule(rid: int, db: DbDep) -> dict:
|
|
await llm_service.delete_rule(db, rid)
|
|
return ok()
|
|
|
|
|
|
# -------- Chat / Usage --------
|
|
|
|
@router.post("/chat", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def chat(body: ChatRequest, db: DbDep, user: CurrentUser) -> dict:
|
|
resp = await llm_service.call_chat(
|
|
db,
|
|
operator=user,
|
|
messages=body.messages,
|
|
model_label=body.model,
|
|
conditions=body.conditions,
|
|
temperature=body.temperature,
|
|
max_tokens=body.max_tokens,
|
|
source=body.source,
|
|
)
|
|
return ok(resp.model_dump())
|
|
|
|
|
|
@router.get("/usage", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def list_usage(
|
|
db: DbDep,
|
|
page: int = Query(1, ge=1),
|
|
size: int = Query(20, ge=1, le=200),
|
|
provider_id: int | None = None,
|
|
source: str | None = None,
|
|
) -> dict:
|
|
rows, total = await llm_service.paginate_usage(db, page, size, provider_id, source)
|
|
return ok({
|
|
"list": [UsageRead.model_validate(r).model_dump(mode="json") for r in rows],
|
|
"total": total,
|
|
"page": page,
|
|
"size": size,
|
|
})
|
|
|
|
|
|
@router.get("/usage/summary", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def usage_summary(db: DbDep) -> dict:
|
|
return ok(await llm_service.usage_summary(db))
|