Files
onyx/backend/danswer/server/features/tool/api.py
T
josvdwandhagen-danswer 50c17438d5 Litellm bump (#2195)
* ran bump-pydantic

* replace root_validator with model_validator

* mostly working. some alternate assistant error. changed root_validator and typing_extensions

* working generation chat. changed type

* replacing .dict with .model_dump

* argument needed to bring model_dump up to parity with dict()

* fix a fewremaining issues -- working with llama and gpt

* updating requirements file

* more requirement updates

* more requirement updates

* fix to make search work

* return type fix:

* half way tpyes change

* fixes for mypy and pydantic:

* endpoint fix

* fix pydantic protected namespaces

* it works!

* removed unecessary None initializations

* better logging

* changed default values to empty lists

* mypy fixes

* fixed array defaulting

---------

Co-authored-by: hagen-danswer <hagen@danswer.ai>
2024-08-28 00:00:27 +00:00

139 lines
4.0 KiB
Python

from typing import Any
from fastapi import APIRouter
from fastapi import Depends
from fastapi import HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session
from danswer.auth.users import current_admin_user
from danswer.auth.users import current_user
from danswer.db.engine import get_session
from danswer.db.models import User
from danswer.db.tools import create_tool
from danswer.db.tools import delete_tool
from danswer.db.tools import get_tool_by_id
from danswer.db.tools import get_tools
from danswer.db.tools import update_tool
from danswer.server.features.tool.models import ToolSnapshot
from danswer.tools.custom.openapi_parsing import MethodSpec
from danswer.tools.custom.openapi_parsing import openapi_to_method_specs
from danswer.tools.custom.openapi_parsing import validate_openapi_schema
router = APIRouter(prefix="/tool")
admin_router = APIRouter(prefix="/admin/tool")
class CustomToolCreate(BaseModel):
name: str
description: str | None = None
definition: dict[str, Any]
class CustomToolUpdate(BaseModel):
name: str | None = None
description: str | None = None
definition: dict[str, Any] | None = None
def _validate_tool_definition(definition: dict[str, Any]) -> None:
try:
validate_openapi_schema(definition)
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@admin_router.post("/custom")
def create_custom_tool(
tool_data: CustomToolCreate,
db_session: Session = Depends(get_session),
user: User | None = Depends(current_admin_user),
) -> ToolSnapshot:
_validate_tool_definition(tool_data.definition)
tool = create_tool(
name=tool_data.name,
description=tool_data.description,
openapi_schema=tool_data.definition,
user_id=user.id if user else None,
db_session=db_session,
)
return ToolSnapshot.from_model(tool)
@admin_router.put("/custom/{tool_id}")
def update_custom_tool(
tool_id: int,
tool_data: CustomToolUpdate,
db_session: Session = Depends(get_session),
user: User | None = Depends(current_admin_user),
) -> ToolSnapshot:
if tool_data.definition:
_validate_tool_definition(tool_data.definition)
updated_tool = update_tool(
tool_id=tool_id,
name=tool_data.name,
description=tool_data.description,
openapi_schema=tool_data.definition,
user_id=user.id if user else None,
db_session=db_session,
)
return ToolSnapshot.from_model(updated_tool)
@admin_router.delete("/custom/{tool_id}")
def delete_custom_tool(
tool_id: int,
db_session: Session = Depends(get_session),
_: User | None = Depends(current_admin_user),
) -> None:
try:
delete_tool(tool_id, db_session)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
# handles case where tool is still used by an Assistant
raise HTTPException(status_code=400, detail=str(e))
class ValidateToolRequest(BaseModel):
definition: dict[str, Any]
class ValidateToolResponse(BaseModel):
methods: list[MethodSpec]
@admin_router.post("/custom/validate")
def validate_tool(
tool_data: ValidateToolRequest,
_: User | None = Depends(current_admin_user),
) -> ValidateToolResponse:
_validate_tool_definition(tool_data.definition)
method_specs = openapi_to_method_specs(tool_data.definition)
return ValidateToolResponse(methods=method_specs)
"""Endpoints for all"""
@router.get("/{tool_id}")
def get_custom_tool(
tool_id: int,
db_session: Session = Depends(get_session),
_: User | None = Depends(current_user),
) -> ToolSnapshot:
try:
tool = get_tool_by_id(tool_id, db_session)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
return ToolSnapshot.from_model(tool)
@router.get("")
def list_tools(
db_session: Session = Depends(get_session),
_: User | None = Depends(current_user),
) -> list[ToolSnapshot]:
tools = get_tools(db_session)
return [ToolSnapshot.from_model(tool) for tool in tools]