mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-21 14:12:42 +02:00
welcome to onyx
This commit is contained in:
98
backend/ee/onyx/server/manage/models.py
Normal file
98
backend/ee/onyx/server/manage/models.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import field_validator
|
||||
from pydantic import model_validator
|
||||
|
||||
from onyx.db.models import StandardAnswer as StandardAnswerModel
|
||||
from onyx.db.models import StandardAnswerCategory as StandardAnswerCategoryModel
|
||||
|
||||
|
||||
class StandardAnswerCategoryCreationRequest(BaseModel):
|
||||
name: str
|
||||
|
||||
|
||||
class StandardAnswerCategory(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
@classmethod
|
||||
def from_model(
|
||||
cls, standard_answer_category: StandardAnswerCategoryModel
|
||||
) -> "StandardAnswerCategory":
|
||||
return cls(
|
||||
id=standard_answer_category.id,
|
||||
name=standard_answer_category.name,
|
||||
)
|
||||
|
||||
|
||||
class StandardAnswer(BaseModel):
|
||||
id: int
|
||||
keyword: str
|
||||
answer: str
|
||||
categories: list[StandardAnswerCategory]
|
||||
match_regex: bool
|
||||
match_any_keywords: bool
|
||||
|
||||
@classmethod
|
||||
def from_model(cls, standard_answer_model: StandardAnswerModel) -> "StandardAnswer":
|
||||
return cls(
|
||||
id=standard_answer_model.id,
|
||||
keyword=standard_answer_model.keyword,
|
||||
answer=standard_answer_model.answer,
|
||||
match_regex=standard_answer_model.match_regex,
|
||||
match_any_keywords=standard_answer_model.match_any_keywords,
|
||||
categories=[
|
||||
StandardAnswerCategory.from_model(standard_answer_category_model)
|
||||
for standard_answer_category_model in standard_answer_model.categories
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class StandardAnswerCreationRequest(BaseModel):
|
||||
keyword: str
|
||||
answer: str
|
||||
categories: list[int]
|
||||
match_regex: bool
|
||||
match_any_keywords: bool
|
||||
|
||||
@field_validator("categories", mode="before")
|
||||
@classmethod
|
||||
def validate_categories(cls, value: list[int]) -> list[int]:
|
||||
if len(value) < 1:
|
||||
raise ValueError(
|
||||
"At least one category must be attached to a standard answer"
|
||||
)
|
||||
return value
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_only_match_any_if_not_regex(self) -> Any:
|
||||
if self.match_regex and self.match_any_keywords:
|
||||
raise ValueError(
|
||||
"Can only match any keywords in keyword mode, not regex mode"
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_keyword_if_regex(self) -> Any:
|
||||
if not self.match_regex:
|
||||
# no validation for keywords
|
||||
return self
|
||||
|
||||
try:
|
||||
re.compile(self.keyword)
|
||||
return self
|
||||
except re.error as err:
|
||||
if isinstance(err.pattern, bytes):
|
||||
raise ValueError(
|
||||
f'invalid regex pattern r"{err.pattern.decode()}" in `keyword`: {err.msg}'
|
||||
)
|
||||
else:
|
||||
pattern = f'r"{err.pattern}"' if err.pattern is not None else ""
|
||||
raise ValueError(
|
||||
" ".join(
|
||||
["invalid regex pattern", pattern, f"in `keyword`: {err.msg}"]
|
||||
)
|
||||
)
|
143
backend/ee/onyx/server/manage/standard_answer.py
Normal file
143
backend/ee/onyx/server/manage/standard_answer.py
Normal file
@@ -0,0 +1,143 @@
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ee.onyx.db.standard_answer import fetch_standard_answer
|
||||
from ee.onyx.db.standard_answer import fetch_standard_answer_categories
|
||||
from ee.onyx.db.standard_answer import fetch_standard_answer_category
|
||||
from ee.onyx.db.standard_answer import fetch_standard_answers
|
||||
from ee.onyx.db.standard_answer import insert_standard_answer
|
||||
from ee.onyx.db.standard_answer import insert_standard_answer_category
|
||||
from ee.onyx.db.standard_answer import remove_standard_answer
|
||||
from ee.onyx.db.standard_answer import update_standard_answer
|
||||
from ee.onyx.db.standard_answer import update_standard_answer_category
|
||||
from ee.onyx.server.manage.models import StandardAnswer
|
||||
from ee.onyx.server.manage.models import StandardAnswerCategory
|
||||
from ee.onyx.server.manage.models import StandardAnswerCategoryCreationRequest
|
||||
from ee.onyx.server.manage.models import StandardAnswerCreationRequest
|
||||
from onyx.auth.users import current_admin_user
|
||||
from onyx.db.engine import get_session
|
||||
from onyx.db.models import User
|
||||
|
||||
router = APIRouter(prefix="/manage")
|
||||
|
||||
|
||||
@router.post("/admin/standard-answer")
|
||||
def create_standard_answer(
|
||||
standard_answer_creation_request: StandardAnswerCreationRequest,
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> StandardAnswer:
|
||||
standard_answer_model = insert_standard_answer(
|
||||
keyword=standard_answer_creation_request.keyword,
|
||||
answer=standard_answer_creation_request.answer,
|
||||
category_ids=standard_answer_creation_request.categories,
|
||||
match_regex=standard_answer_creation_request.match_regex,
|
||||
match_any_keywords=standard_answer_creation_request.match_any_keywords,
|
||||
db_session=db_session,
|
||||
)
|
||||
return StandardAnswer.from_model(standard_answer_model)
|
||||
|
||||
|
||||
@router.get("/admin/standard-answer")
|
||||
def list_standard_answers(
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> list[StandardAnswer]:
|
||||
standard_answer_models = fetch_standard_answers(db_session=db_session)
|
||||
return [
|
||||
StandardAnswer.from_model(standard_answer_model)
|
||||
for standard_answer_model in standard_answer_models
|
||||
]
|
||||
|
||||
|
||||
@router.patch("/admin/standard-answer/{standard_answer_id}")
|
||||
def patch_standard_answer(
|
||||
standard_answer_id: int,
|
||||
standard_answer_creation_request: StandardAnswerCreationRequest,
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> StandardAnswer:
|
||||
existing_standard_answer = fetch_standard_answer(
|
||||
standard_answer_id=standard_answer_id,
|
||||
db_session=db_session,
|
||||
)
|
||||
|
||||
if existing_standard_answer is None:
|
||||
raise HTTPException(status_code=404, detail="Standard answer not found")
|
||||
|
||||
standard_answer_model = update_standard_answer(
|
||||
standard_answer_id=standard_answer_id,
|
||||
keyword=standard_answer_creation_request.keyword,
|
||||
answer=standard_answer_creation_request.answer,
|
||||
category_ids=standard_answer_creation_request.categories,
|
||||
match_regex=standard_answer_creation_request.match_regex,
|
||||
match_any_keywords=standard_answer_creation_request.match_any_keywords,
|
||||
db_session=db_session,
|
||||
)
|
||||
return StandardAnswer.from_model(standard_answer_model)
|
||||
|
||||
|
||||
@router.delete("/admin/standard-answer/{standard_answer_id}")
|
||||
def delete_standard_answer(
|
||||
standard_answer_id: int,
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> None:
|
||||
return remove_standard_answer(
|
||||
standard_answer_id=standard_answer_id,
|
||||
db_session=db_session,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/admin/standard-answer/category")
|
||||
def create_standard_answer_category(
|
||||
standard_answer_category_creation_request: StandardAnswerCategoryCreationRequest,
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> StandardAnswerCategory:
|
||||
standard_answer_category_model = insert_standard_answer_category(
|
||||
category_name=standard_answer_category_creation_request.name,
|
||||
db_session=db_session,
|
||||
)
|
||||
return StandardAnswerCategory.from_model(standard_answer_category_model)
|
||||
|
||||
|
||||
@router.get("/admin/standard-answer/category")
|
||||
def list_standard_answer_categories(
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> list[StandardAnswerCategory]:
|
||||
standard_answer_category_models = fetch_standard_answer_categories(
|
||||
db_session=db_session
|
||||
)
|
||||
return [
|
||||
StandardAnswerCategory.from_model(standard_answer_category_model)
|
||||
for standard_answer_category_model in standard_answer_category_models
|
||||
]
|
||||
|
||||
|
||||
@router.patch("/admin/standard-answer/category/{standard_answer_category_id}")
|
||||
def patch_standard_answer_category(
|
||||
standard_answer_category_id: int,
|
||||
standard_answer_category_creation_request: StandardAnswerCategoryCreationRequest,
|
||||
db_session: Session = Depends(get_session),
|
||||
_: User | None = Depends(current_admin_user),
|
||||
) -> StandardAnswerCategory:
|
||||
existing_standard_answer_category = fetch_standard_answer_category(
|
||||
standard_answer_category_id=standard_answer_category_id,
|
||||
db_session=db_session,
|
||||
)
|
||||
|
||||
if existing_standard_answer_category is None:
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Standard answer category not found"
|
||||
)
|
||||
|
||||
standard_answer_category_model = update_standard_answer_category(
|
||||
standard_answer_category_id=standard_answer_category_id,
|
||||
category_name=standard_answer_category_creation_request.name,
|
||||
db_session=db_session,
|
||||
)
|
||||
return StandardAnswerCategory.from_model(standard_answer_category_model)
|
Reference in New Issue
Block a user