Spaces:
Build error
Build error
from flask import request | |
from flask_login import current_user | |
from flask_restful import Resource, marshal, reqparse | |
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound | |
import services | |
from controllers.console import api | |
from controllers.console.datasets.error import DatasetNameDuplicateError | |
from controllers.console.wraps import account_initialization_required, setup_required | |
from fields.dataset_fields import dataset_detail_fields | |
from libs.login import login_required | |
from services.dataset_service import DatasetService | |
from services.external_knowledge_service import ExternalDatasetService | |
from services.hit_testing_service import HitTestingService | |
from services.knowledge_service import ExternalDatasetTestService | |
def _validate_name(name): | |
if not name or len(name) < 1 or len(name) > 100: | |
raise ValueError("Name must be between 1 to 100 characters.") | |
return name | |
def _validate_description_length(description): | |
if description and len(description) > 400: | |
raise ValueError("Description cannot exceed 400 characters.") | |
return description | |
class ExternalApiTemplateListApi(Resource): | |
def get(self): | |
page = request.args.get("page", default=1, type=int) | |
limit = request.args.get("limit", default=20, type=int) | |
search = request.args.get("keyword", default=None, type=str) | |
external_knowledge_apis, total = ExternalDatasetService.get_external_knowledge_apis( | |
page, limit, current_user.current_tenant_id, search | |
) | |
response = { | |
"data": [item.to_dict() for item in external_knowledge_apis], | |
"has_more": len(external_knowledge_apis) == limit, | |
"limit": limit, | |
"total": total, | |
"page": page, | |
} | |
return response, 200 | |
def post(self): | |
parser = reqparse.RequestParser() | |
parser.add_argument( | |
"name", | |
nullable=False, | |
required=True, | |
help="Name is required. Name must be between 1 to 100 characters.", | |
type=_validate_name, | |
) | |
parser.add_argument( | |
"settings", | |
type=dict, | |
location="json", | |
nullable=False, | |
required=True, | |
) | |
args = parser.parse_args() | |
ExternalDatasetService.validate_api_list(args["settings"]) | |
# The role of the current user in the ta table must be admin, owner, or editor, or dataset_operator | |
if not current_user.is_dataset_editor: | |
raise Forbidden() | |
try: | |
external_knowledge_api = ExternalDatasetService.create_external_knowledge_api( | |
tenant_id=current_user.current_tenant_id, user_id=current_user.id, args=args | |
) | |
except services.errors.dataset.DatasetNameDuplicateError: | |
raise DatasetNameDuplicateError() | |
return external_knowledge_api.to_dict(), 201 | |
class ExternalApiTemplateApi(Resource): | |
def get(self, external_knowledge_api_id): | |
external_knowledge_api_id = str(external_knowledge_api_id) | |
external_knowledge_api = ExternalDatasetService.get_external_knowledge_api(external_knowledge_api_id) | |
if external_knowledge_api is None: | |
raise NotFound("API template not found.") | |
return external_knowledge_api.to_dict(), 200 | |
def patch(self, external_knowledge_api_id): | |
external_knowledge_api_id = str(external_knowledge_api_id) | |
parser = reqparse.RequestParser() | |
parser.add_argument( | |
"name", | |
nullable=False, | |
required=True, | |
help="type is required. Name must be between 1 to 100 characters.", | |
type=_validate_name, | |
) | |
parser.add_argument( | |
"settings", | |
type=dict, | |
location="json", | |
nullable=False, | |
required=True, | |
) | |
args = parser.parse_args() | |
ExternalDatasetService.validate_api_list(args["settings"]) | |
external_knowledge_api = ExternalDatasetService.update_external_knowledge_api( | |
tenant_id=current_user.current_tenant_id, | |
user_id=current_user.id, | |
external_knowledge_api_id=external_knowledge_api_id, | |
args=args, | |
) | |
return external_knowledge_api.to_dict(), 200 | |
def delete(self, external_knowledge_api_id): | |
external_knowledge_api_id = str(external_knowledge_api_id) | |
# The role of the current user in the ta table must be admin, owner, or editor | |
if not current_user.is_editor or current_user.is_dataset_operator: | |
raise Forbidden() | |
ExternalDatasetService.delete_external_knowledge_api(current_user.current_tenant_id, external_knowledge_api_id) | |
return {"result": "success"}, 200 | |
class ExternalApiUseCheckApi(Resource): | |
def get(self, external_knowledge_api_id): | |
external_knowledge_api_id = str(external_knowledge_api_id) | |
external_knowledge_api_is_using, count = ExternalDatasetService.external_knowledge_api_use_check( | |
external_knowledge_api_id | |
) | |
return {"is_using": external_knowledge_api_is_using, "count": count}, 200 | |
class ExternalDatasetCreateApi(Resource): | |
def post(self): | |
# The role of the current user in the ta table must be admin, owner, or editor | |
if not current_user.is_editor: | |
raise Forbidden() | |
parser = reqparse.RequestParser() | |
parser.add_argument("external_knowledge_api_id", type=str, required=True, nullable=False, location="json") | |
parser.add_argument("external_knowledge_id", type=str, required=True, nullable=False, location="json") | |
parser.add_argument( | |
"name", | |
nullable=False, | |
required=True, | |
help="name is required. Name must be between 1 to 100 characters.", | |
type=_validate_name, | |
) | |
parser.add_argument("description", type=str, required=False, nullable=True, location="json") | |
parser.add_argument("external_retrieval_model", type=dict, required=False, location="json") | |
args = parser.parse_args() | |
# The role of the current user in the ta table must be admin, owner, or editor, or dataset_operator | |
if not current_user.is_dataset_editor: | |
raise Forbidden() | |
try: | |
dataset = ExternalDatasetService.create_external_dataset( | |
tenant_id=current_user.current_tenant_id, | |
user_id=current_user.id, | |
args=args, | |
) | |
except services.errors.dataset.DatasetNameDuplicateError: | |
raise DatasetNameDuplicateError() | |
return marshal(dataset, dataset_detail_fields), 201 | |
class ExternalKnowledgeHitTestingApi(Resource): | |
def post(self, dataset_id): | |
dataset_id_str = str(dataset_id) | |
dataset = DatasetService.get_dataset(dataset_id_str) | |
if dataset is None: | |
raise NotFound("Dataset not found.") | |
try: | |
DatasetService.check_dataset_permission(dataset, current_user) | |
except services.errors.account.NoPermissionError as e: | |
raise Forbidden(str(e)) | |
parser = reqparse.RequestParser() | |
parser.add_argument("query", type=str, location="json") | |
parser.add_argument("external_retrieval_model", type=dict, required=False, location="json") | |
args = parser.parse_args() | |
HitTestingService.hit_testing_args_check(args) | |
try: | |
response = HitTestingService.external_retrieve( | |
dataset=dataset, | |
query=args["query"], | |
account=current_user, | |
external_retrieval_model=args["external_retrieval_model"], | |
) | |
return response | |
except Exception as e: | |
raise InternalServerError(str(e)) | |
class BedrockRetrievalApi(Resource): | |
# this api is only for internal testing | |
def post(self): | |
parser = reqparse.RequestParser() | |
parser.add_argument("retrieval_setting", nullable=False, required=True, type=dict, location="json") | |
parser.add_argument( | |
"query", | |
nullable=False, | |
required=True, | |
type=str, | |
) | |
parser.add_argument("knowledge_id", nullable=False, required=True, type=str) | |
args = parser.parse_args() | |
# Call the knowledge retrieval service | |
result = ExternalDatasetTestService.knowledge_retrieval( | |
args["retrieval_setting"], args["query"], args["knowledge_id"] | |
) | |
return result, 200 | |
api.add_resource(ExternalKnowledgeHitTestingApi, "/datasets/<uuid:dataset_id>/external-hit-testing") | |
api.add_resource(ExternalDatasetCreateApi, "/datasets/external") | |
api.add_resource(ExternalApiTemplateListApi, "/datasets/external-knowledge-api") | |
api.add_resource(ExternalApiTemplateApi, "/datasets/external-knowledge-api/<uuid:external_knowledge_api_id>") | |
api.add_resource(ExternalApiUseCheckApi, "/datasets/external-knowledge-api/<uuid:external_knowledge_api_id>/use-check") | |
# this api is only for internal test | |
api.add_resource(BedrockRetrievalApi, "/test/retrieval") | |