diff --git a/aperag/api/components/schemas/audit.yaml b/aperag/api/components/schemas/audit.yaml index dd8710d49..85b867829 100644 --- a/aperag/api/components/schemas/audit.yaml +++ b/aperag/api/components/schemas/audit.yaml @@ -15,7 +15,7 @@ auditLog: description: Username for display resource_type: type: string - enum: [collection, document, bot, chat, message, api_key, llm_provider, llm_provider_model, model_service_provider, user, flow, search_test] + enum: [collection, document, bot, chat, message, api_key, llm_provider, llm_provider_model, model_service_provider, user, flow, search] nullable: true description: Type of resource resource_id: diff --git a/aperag/api/components/schemas/collection.yaml b/aperag/api/components/schemas/collection.yaml index 43d4196aa..f8433386f 100644 --- a/aperag/api/components/schemas/collection.yaml +++ b/aperag/api/components/schemas/collection.yaml @@ -313,12 +313,12 @@ graphSearchParams: type: integer description: Top K results -searchTestRequest: +searchRequest: type: object + description: Search request properties: query: type: string - description: The user input query vector_search: $ref: '#/vectorSearchParams' fulltext_search: @@ -326,7 +326,7 @@ searchTestRequest: graph_search: $ref: '#/graphSearchParams' -searchTestResultItem: +searchResultItem: type: object properties: rank: @@ -349,12 +349,12 @@ searchTestResultItem: - graph_search - fulltext_search -searchTestResult: +searchResult: type: object properties: id: type: string - description: The id of the search test result + description: The id of the search result query: type: string vector_search: @@ -366,17 +366,17 @@ searchTestResult: items: type: array items: - $ref: '#/searchTestResultItem' + $ref: '#/searchResultItem' created: type: string format: date-time - description: The creation time of the search test result + description: The creation time of the search result -searchTestResultList: +searchResultList: type: object - description: A list of search test results + description: A list of search results properties: items: type: array items: - $ref: '#/searchTestResult' + $ref: '#/searchResult' diff --git a/aperag/api/openapi.yaml b/aperag/api/openapi.yaml index 43f2c119d..4b0a1120e 100644 --- a/aperag/api/openapi.yaml +++ b/aperag/api/openapi.yaml @@ -47,10 +47,10 @@ paths: $ref: './paths/collections.yaml#/documents' /collections/{collection_id}/documents/{document_id}: $ref: './paths/collections.yaml#/document' - /collections/{collection_id}/searchTests: - $ref: './paths/collections.yaml#/searchTests' - /collections/{collection_id}/searchTests/{search_test_id}: - $ref: './paths/collections.yaml#/searchTest' + /collections/{collection_id}/searches: + $ref: './paths/collections.yaml#/searches' + /collections/{collection_id}/searches/{search_id}: + $ref: './paths/collections.yaml#/search_detail' # apikeys /apikeys: diff --git a/aperag/api/paths/collections.yaml b/aperag/api/paths/collections.yaml index fd3a244a8..2a0ca9bd8 100644 --- a/aperag/api/paths/collections.yaml +++ b/aperag/api/paths/collections.yaml @@ -296,10 +296,10 @@ document: schema: $ref: '../components/schemas/common.yaml#/failResponse' -searchTest: - delete: - summary: Delete a search test - description: Delete a search test +searches: + get: + summary: Get search history + description: Get the history of searches security: - BearerAuth: [] parameters: @@ -308,21 +308,23 @@ searchTest: required: true schema: type: string - - name: search_test_id - in: path - required: true - schema: - type: string responses: - '204': - description: Search test deleted successfully + '200': + description: Search history + content: + application/json: + schema: + $ref: '../components/schemas/collection.yaml#/searchResultList' '401': description: Unauthorized + content: + application/json: + schema: + $ref: '../components/schemas/common.yaml#/failResponse' -searchTests: - get: - summary: Get search test history - description: Get the history of search tests + post: + summary: Search in collection + description: Search in a collection with different search types security: - BearerAuth: [] parameters: @@ -331,13 +333,19 @@ searchTests: required: true schema: type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/collection.yaml#/searchRequest' responses: '200': - description: Search test history + description: Search results content: application/json: schema: - $ref: '../components/schemas/collection.yaml#/searchTestResultList' + $ref: '../components/schemas/collection.yaml#/searchResult' '401': description: Unauthorized content: @@ -345,9 +353,10 @@ searchTests: schema: $ref: '../components/schemas/common.yaml#/failResponse' - post: - summary: Test search in collection - description: Test search in a collection with different search types +search_detail: + delete: + summary: Delete a search + description: Delete a search security: - BearerAuth: [] parameters: @@ -356,19 +365,14 @@ searchTests: required: true schema: type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/collection.yaml#/searchTestRequest' + - name: search_id + in: path + required: true + schema: + type: string responses: '200': - description: Search results - content: - application/json: - schema: - $ref: '../components/schemas/collection.yaml#/searchTestResult' + description: Search deleted successfully '401': description: Unauthorized content: diff --git a/aperag/db/models.py b/aperag/db/models.py index 363d7246a..030d2e23d 100644 --- a/aperag/db/models.py +++ b/aperag/db/models.py @@ -588,10 +588,10 @@ async def use(self, session): # self.expires_at = utc_now() -class SearchTestHistory(Base): - __tablename__ = "searchtesthistory" +class SearchHistory(Base): + __tablename__ = "searchhistory" - id = Column(String(24), primary_key=True, default=lambda: "sth" + random_id()) + id = Column(String(24), primary_key=True, default=lambda: "sh" + random_id()) user = Column(String(256), nullable=False, index=True) # Add index for user queries collection_id = Column(String(24), nullable=True, index=True) # Add index for collection queries query = Column(Text, nullable=False) @@ -766,7 +766,7 @@ class AuditResource(str, Enum): INVITATION = "invitation" AUTH = "auth" CHAT_COMPLETION = "chat_completion" - SEARCH_TEST = "search_test" + SEARCH = "search" LLM = "llm" FLOW = "flow" SYSTEM = "system" diff --git a/aperag/db/ops.py b/aperag/db/ops.py index aed215e1f..37efbc4a0 100644 --- a/aperag/db/ops.py +++ b/aperag/db/ops.py @@ -31,7 +31,7 @@ AsyncLlmProviderRepositoryMixin, LlmProviderRepositoryMixin, ) -from aperag.db.repositories.search_test import AsyncSearchTestRepositoryMixin +from aperag.db.repositories.search import AsyncSearchRepositoryMixin from aperag.db.repositories.system import AsyncSystemRepositoryMixin from aperag.db.repositories.user import AsyncUserRepositoryMixin @@ -58,7 +58,7 @@ class AsyncDatabaseOps( AsyncUserRepositoryMixin, AsyncLlmProviderRepositoryMixin, AsyncSystemRepositoryMixin, - AsyncSearchTestRepositoryMixin, + AsyncSearchRepositoryMixin, ): pass diff --git a/aperag/db/repositories/search_test.py b/aperag/db/repositories/search.py similarity index 68% rename from aperag/db/repositories/search_test.py rename to aperag/db/repositories/search.py index 2edae2224..bdf6683d4 100644 --- a/aperag/db/repositories/search_test.py +++ b/aperag/db/repositories/search.py @@ -16,12 +16,12 @@ from sqlalchemy import desc, select -from aperag.db.models import SearchTestHistory +from aperag.db.models import SearchHistory from aperag.db.repositories.base import AsyncRepositoryProtocol -class AsyncSearchTestRepositoryMixin(AsyncRepositoryProtocol): - async def create_search_test( +class AsyncSearchRepositoryMixin(AsyncRepositoryProtocol): + async def create_search( self, user: str, collection_id: str, @@ -30,9 +30,9 @@ async def create_search_test( fulltext_search: dict = None, graph_search: dict = None, items: List[dict] = None, - ) -> SearchTestHistory: + ) -> SearchHistory: async def _operation(session): - instance = SearchTestHistory( + instance = SearchHistory( user=user, collection_id=collection_id, query=query, @@ -48,28 +48,28 @@ async def _operation(session): return await self.execute_with_transaction(_operation) - async def query_search_tests(self, user: str, collection_id: str) -> List[SearchTestHistory]: - """Query search tests by user and collection""" + async def query_searches(self, user: str, collection_id: str) -> List[SearchHistory]: + """Query searches by user and collection""" async def _query(session): stmt = ( - select(SearchTestHistory) - .where(SearchTestHistory.user == user, SearchTestHistory.collection_id == collection_id) - .order_by(desc(SearchTestHistory.gmt_created)) + select(SearchHistory) + .where(SearchHistory.user == user, SearchHistory.collection_id == collection_id) + .order_by(desc(SearchHistory.gmt_created)) ) result = await session.execute(stmt) return result.scalars().all() return await self._execute_query(_query) - async def delete_search_test(self, user: str, collection_id: str, search_test_id: str) -> bool: - """Delete search test by ID""" + async def delete_search(self, user: str, collection_id: str, search_id: str) -> bool: + """Delete search by ID""" async def _operation(session): - stmt = select(SearchTestHistory).where( - SearchTestHistory.id == search_test_id, - SearchTestHistory.user == user, - SearchTestHistory.collection_id == collection_id, + stmt = select(SearchHistory).where( + SearchHistory.id == search_id, + SearchHistory.user == user, + SearchHistory.collection_id == collection_id, ) result = await session.execute(stmt) instance = result.scalars().first() diff --git a/aperag/exceptions.py b/aperag/exceptions.py index bf9fa09a4..e82fdcc00 100644 --- a/aperag/exceptions.py +++ b/aperag/exceptions.py @@ -65,7 +65,7 @@ class ErrorCode(Enum): AUTH_TOKEN_EXPIRED = ("AUTH_TOKEN_EXPIRED", 1602, HTTPStatus.UNAUTHORIZED) # Search errors (1700-1799) - SEARCH_TEST_NOT_FOUND = ("SEARCH_TEST_NOT_FOUND", 1701, HTTPStatus.NOT_FOUND) + SEARCH_NOT_FOUND = ("SEARCH_NOT_FOUND", 1701, HTTPStatus.NOT_FOUND) # LLM Provider errors (1800-1899) LLM_PROVIDER_ALREADY_EXISTS = ("LLM_PROVIDER_ALREADY_EXISTS", 1801, HTTPStatus.CONFLICT) diff --git a/aperag/migration/versions/20250621002836-2768dfee8bbc.py b/aperag/migration/versions/20250621002836-2768dfee8bbc.py index 6ca1ff9e7..4217149f2 100644 --- a/aperag/migration/versions/20250621002836-2768dfee8bbc.py +++ b/aperag/migration/versions/20250621002836-2768dfee8bbc.py @@ -25,7 +25,7 @@ def upgrade() -> None: sa.Column('id', sa.String(length=36), nullable=False), sa.Column('user_id', sa.String(length=36), nullable=True, comment='User ID'), sa.Column('username', sa.String(length=255), nullable=True, comment='Username'), - sa.Column('resource_type', sa.Enum('collection', 'document', 'bot', 'chat', 'message', 'api_key', 'llm_provider', 'llm_provider_model', 'model_service_provider', 'user', 'config', 'invitation', 'auth', 'chat_completion', 'search_test', 'llm', 'flow', 'system', name='auditresource'), nullable=True, comment='Resource type'), + sa.Column('resource_type', sa.Enum('collection', 'document', 'bot', 'chat', 'message', 'api_key', 'llm_provider', 'llm_provider_model', 'model_service_provider', 'user', 'config', 'invitation', 'auth', 'chat_completion', 'search', 'llm', 'flow', 'system', name='auditresource'), nullable=True, comment='Resource type'), sa.Column('resource_id', sa.String(length=255), nullable=True, comment='Resource ID (extracted at query time)'), sa.Column('api_name', sa.String(length=255), nullable=False, comment='API operation name'), sa.Column('http_method', sa.String(length=10), nullable=False, comment='HTTP method (POST, PUT, DELETE)'), diff --git a/aperag/migration/versions/20250623110658-23c0533b6b63.py b/aperag/migration/versions/20250623110658-23c0533b6b63.py new file mode 100644 index 000000000..8b64332e8 --- /dev/null +++ b/aperag/migration/versions/20250623110658-23c0533b6b63.py @@ -0,0 +1,50 @@ +"""empty message + +Revision ID: 23c0533b6b63 +Revises: 2768dfee8bbc +Create Date: 2025-06-23 11:06:58.841005 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = '23c0533b6b63' +down_revision: Union[str, None] = '2768dfee8bbc' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # Rename table from searchtesthistory to searchhistory + op.rename_table('searchtesthistory', 'searchhistory') + op.rename_table('document_indexes', 'document_index') + + # Update any indexes that reference the old table name + op.drop_index('ix_searchtesthistory_collection_id', table_name='searchhistory') + op.drop_index('ix_searchtesthistory_gmt_deleted', table_name='searchhistory') + op.drop_index('ix_searchtesthistory_user', table_name='searchhistory') + + # Create new indexes with updated names + op.create_index('ix_searchhistory_collection_id', 'searchhistory', ['collection_id'], unique=False) + op.create_index('ix_searchhistory_gmt_deleted', 'searchhistory', ['gmt_deleted'], unique=False) + op.create_index('ix_searchhistory_user', 'searchhistory', ['user'], unique=False) + + +def downgrade() -> None: + # Reverse the operation + op.drop_index('ix_searchhistory_user', table_name='searchhistory') + op.drop_index('ix_searchhistory_gmt_deleted', table_name='searchhistory') + op.drop_index('ix_searchhistory_collection_id', table_name='searchhistory') + + # Recreate old indexes + op.create_index('ix_searchtesthistory_user', 'searchtesthistory', ['user'], unique=False) + op.create_index('ix_searchtesthistory_gmt_deleted', 'searchtesthistory', ['gmt_deleted'], unique=False) + op.create_index('ix_searchtesthistory_collection_id', 'searchtesthistory', ['collection_id'], unique=False) + + # Rename table back + op.rename_table('searchhistory', 'searchtesthistory') + op.rename_table('document_index', 'document_indexes') \ No newline at end of file diff --git a/aperag/schema/view_models.py b/aperag/schema/view_models.py index 6d2b1e10f..993469ab0 100644 --- a/aperag/schema/view_models.py +++ b/aperag/schema/view_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.merged.yaml -# timestamp: 2025-06-20T16:37:07+00:00 +# timestamp: 2025-06-23T03:26:47+00:00 from __future__ import annotations @@ -590,7 +590,7 @@ class GraphSearchParams(BaseModel): topk: Optional[int] = Field(None, description='Top K results') -class SearchTestResultItem(BaseModel): +class SearchResultItem(BaseModel): rank: Optional[int] = Field(None, description='Result rank') score: Optional[float] = Field(None, description='Result score') content: Optional[str] = Field(None, description='Result content') @@ -600,28 +600,32 @@ class SearchTestResultItem(BaseModel): ] = Field(None, description='Recall type') -class SearchTestResult(BaseModel): - id: Optional[str] = Field(None, description='The id of the search test result') +class SearchResult(BaseModel): + id: Optional[str] = Field(None, description='The id of the search result') query: Optional[str] = None vector_search: Optional[VectorSearchParams] = None fulltext_search: Optional[FulltextSearchParams] = None graph_search: Optional[GraphSearchParams] = None - items: Optional[list[SearchTestResultItem]] = None + items: Optional[list[SearchResultItem]] = None created: Optional[datetime] = Field( - None, description='The creation time of the search test result' + None, description='The creation time of the search result' ) -class SearchTestResultList(BaseModel): +class SearchResultList(BaseModel): """ - A list of search test results + A list of search results """ - items: Optional[list[SearchTestResult]] = None + items: Optional[list[SearchResult]] = None -class SearchTestRequest(BaseModel): - query: Optional[str] = Field(None, description='The user input query') +class SearchRequest(BaseModel): + """ + Search request + """ + + query: Optional[str] = None vector_search: Optional[VectorSearchParams] = None fulltext_search: Optional[FulltextSearchParams] = None graph_search: Optional[GraphSearchParams] = None @@ -1070,7 +1074,7 @@ class AuditLog(BaseModel): 'model_service_provider', 'user', 'flow', - 'search_test', + 'search', ] ] = Field(None, description='Type of resource') resource_id: Optional[str] = Field( diff --git a/aperag/service/collection_service.py b/aperag/service/collection_service.py index c3fb64a8c..7d14f4e89 100644 --- a/aperag/service/collection_service.py +++ b/aperag/service/collection_service.py @@ -26,9 +26,9 @@ from aperag.schema.utils import dumpCollectionConfig, parseCollectionConfig from aperag.schema.view_models import ( Collection, - SearchTestResult, - SearchTestResultItem, - SearchTestResultList, + SearchResult, + SearchResultItem, + SearchResultList, ) from aperag.utils.constant import QuotaType from aperag.views.utils import validate_source_connect_config @@ -153,16 +153,16 @@ async def delete_collection(self, user: str, collection_id: str) -> Optional[vie return None - async def create_search_test( - self, user: str, collection_id: str, data: view_models.SearchTestRequest - ) -> view_models.SearchTestResult: + async def create_search( + self, user: str, collection_id: str, data: view_models.SearchRequest + ) -> view_models.SearchResult: from aperag.exceptions import CollectionNotFoundException collection = await self.db_ops.query_collection(user, collection_id) if not collection: raise CollectionNotFoundException(collection_id) - # Build flow for search test execution + # Build flow for search execution nodes = {} edges = [] end_node_id = "merge" @@ -223,8 +223,8 @@ async def create_search_test( # Execute search flow flow = FlowInstance( - name="search_test", - title="Search Test", + name="search", + title="Search", nodes=nodes, edges=edges, ) @@ -240,7 +240,7 @@ async def create_search_test( items = [] for idx, doc in enumerate(docs): items.append( - SearchTestResultItem( + SearchResultItem( rank=idx + 1, score=doc.score, content=doc.text, @@ -249,7 +249,7 @@ async def create_search_test( ) ) - record = await self.db_ops.create_search_test( + record = await self.db_ops.create_search( user=user, collection_id=collection_id, query=data.query, @@ -258,7 +258,7 @@ async def create_search_test( graph_search=data.graph_search.dict() if data.graph_search else None, items=[item.dict() for item in items], ) - return SearchTestResult( + return SearchResult( id=record.id, query=record.query, vector_search=record.vector_search, @@ -268,36 +268,36 @@ async def create_search_test( created=record.gmt_created.isoformat(), ) - async def list_search_tests(self, user: str, collection_id: str) -> view_models.SearchTestResultList: + async def list_searches(self, user: str, collection_id: str) -> view_models.SearchResultList: from aperag.exceptions import CollectionNotFoundException collection = await self.db_ops.query_collection(user, collection_id) if not collection: raise CollectionNotFoundException(collection_id) - # Use DatabaseOps to query search tests - search_tests = await self.db_ops.query_search_tests(user, collection_id) + # Use DatabaseOps to query searches + searches = await self.db_ops.query_searches(user, collection_id) items = [] - for search_test in search_tests: - test_result_items = [] - for item_data in search_test.items: - test_result_items.append(SearchTestResultItem(**item_data)) + for search in searches: + search_result_items = [] + for item_data in search.items: + search_result_items.append(SearchResultItem(**item_data)) items.append( - SearchTestResult( - id=search_test.id, - query=search_test.query, - vector_search=search_test.vector_search, - fulltext_search=search_test.fulltext_search, - graph_search=search_test.graph_search, - items=test_result_items, - created=search_test.gmt_created.isoformat(), + SearchResult( + id=search.id, + query=search.query, + vector_search=search.vector_search, + fulltext_search=search.fulltext_search, + graph_search=search.graph_search, + items=search_result_items, + created=search.gmt_created.isoformat(), ) ) - return SearchTestResultList(items=items) + return SearchResultList(items=items) - async def delete_search_test(self, user: str, collection_id: str, search_test_id: str) -> Optional[bool]: - """Delete search test by ID (idempotent operation) + async def delete_search(self, user: str, collection_id: str, search_id: str) -> Optional[bool]: + """Delete search by ID (idempotent operation) Returns True if deleted, None if already deleted/not found """ @@ -307,7 +307,7 @@ async def delete_search_test(self, user: str, collection_id: str, search_test_id if not collection: raise CollectionNotFoundException(collection_id) - return await self.db_ops.delete_search_test(user, collection_id, search_test_id) + return await self.db_ops.delete_search(user, collection_id, search_id) # Create a global service instance for easy access diff --git a/aperag/views/main.py b/aperag/views/main.py index 716f776d7..cd26fab37 100644 --- a/aperag/views/main.py +++ b/aperag/views/main.py @@ -274,35 +274,35 @@ async def frontend_chat_completions_view(request: Request, user: User = Depends( return await chat_service_global.frontend_chat_completions(str(user.id), message, stream, bot_id, chat_id, msg_id) -@router.post("/collections/{collection_id}/searchTests") -@audit(resource_type="search_test", api_name="CreateSearchTest") -async def create_search_test_view( +@router.post("/collections/{collection_id}/searches") +@audit(resource_type="search", api_name="CreateSearch") +async def create_search_view( request: Request, collection_id: str, - data: view_models.SearchTestRequest, + data: view_models.SearchRequest, user: User = Depends(current_user), -) -> view_models.SearchTestResult: - return await collection_service.create_search_test(str(user.id), collection_id, data) +) -> view_models.SearchResult: + return await collection_service.create_search(str(user.id), collection_id, data) @router.delete( - "/collections/{collection_id}/searchTests/{search_test_id}", tags=["search_test"], name="DeleteSearchTest" + "/collections/{collection_id}/searches/{search_id}", tags=["search"], name="DeleteSearch" ) -@audit(resource_type="search_test", api_name="DeleteSearchTest") -async def delete_search_test_view( +@audit(resource_type="search", api_name="DeleteSearch") +async def delete_search_view( request: Request, collection_id: str, - search_test_id: str, + search_id: str, user: User = Depends(current_user), ): - return await collection_service.delete_search_test(str(user.id), collection_id, search_test_id) + return await collection_service.delete_search(str(user.id), collection_id, search_id) -@router.get("/collections/{collection_id}/searchTests") -async def list_search_tests_view( +@router.get("/collections/{collection_id}/searches") +async def list_searches_view( request: Request, collection_id: str, user: User = Depends(current_user) -) -> view_models.SearchTestResultList: - return await collection_service.list_search_tests(str(user.id), collection_id) +) -> view_models.SearchResultList: + return await collection_service.list_searches(str(user.id), collection_id) @router.post("/bots/{bot_id}/flow/debug") diff --git a/frontend/src/api/apis/audit-api.ts b/frontend/src/api/apis/audit-api.ts index 4c1c42a4d..be60c5705 100644 --- a/frontend/src/api/apis/audit-api.ts +++ b/frontend/src/api/apis/audit-api.ts @@ -68,20 +68,14 @@ export const AuditApiAxiosParamCreator = function (configuration?: Configuration /** * List audit logs with filtering options * @summary List audit logs - * @param {string} [userId] Filter by user ID - * @param {string} [username] Filter by username - * @param {ListAuditLogsResourceTypeEnum} [resourceType] Filter by resource type - * @param {string} [resourceId] Filter by resource ID * @param {string} [apiName] Filter by API name - * @param {ListAuditLogsHttpMethodEnum} [httpMethod] Filter by HTTP method - * @param {number} [statusCode] Filter by status code * @param {string} [startDate] Filter by start date * @param {string} [endDate] Filter by end date * @param {number} [limit] Maximum number of records * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listAuditLogs: async (userId?: string, username?: string, resourceType?: ListAuditLogsResourceTypeEnum, resourceId?: string, apiName?: string, httpMethod?: ListAuditLogsHttpMethodEnum, statusCode?: number, startDate?: string, endDate?: string, limit?: number, options: RawAxiosRequestConfig = {}): Promise => { + listAuditLogs: async (apiName?: string, startDate?: string, endDate?: string, limit?: number, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/audit-logs`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -94,34 +88,10 @@ export const AuditApiAxiosParamCreator = function (configuration?: Configuration const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - if (userId !== undefined) { - localVarQueryParameter['user_id'] = userId; - } - - if (username !== undefined) { - localVarQueryParameter['username'] = username; - } - - if (resourceType !== undefined) { - localVarQueryParameter['resource_type'] = resourceType; - } - - if (resourceId !== undefined) { - localVarQueryParameter['resource_id'] = resourceId; - } - if (apiName !== undefined) { localVarQueryParameter['api_name'] = apiName; } - if (httpMethod !== undefined) { - localVarQueryParameter['http_method'] = httpMethod; - } - - if (statusCode !== undefined) { - localVarQueryParameter['status_code'] = statusCode; - } - if (startDate !== undefined) { localVarQueryParameter['start_date'] = (startDate as any instanceof Date) ? (startDate as any).toISOString() : @@ -175,21 +145,15 @@ export const AuditApiFp = function(configuration?: Configuration) { /** * List audit logs with filtering options * @summary List audit logs - * @param {string} [userId] Filter by user ID - * @param {string} [username] Filter by username - * @param {ListAuditLogsResourceTypeEnum} [resourceType] Filter by resource type - * @param {string} [resourceId] Filter by resource ID * @param {string} [apiName] Filter by API name - * @param {ListAuditLogsHttpMethodEnum} [httpMethod] Filter by HTTP method - * @param {number} [statusCode] Filter by status code * @param {string} [startDate] Filter by start date * @param {string} [endDate] Filter by end date * @param {number} [limit] Maximum number of records * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listAuditLogs(userId?: string, username?: string, resourceType?: ListAuditLogsResourceTypeEnum, resourceId?: string, apiName?: string, httpMethod?: ListAuditLogsHttpMethodEnum, statusCode?: number, startDate?: string, endDate?: string, limit?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listAuditLogs(userId, username, resourceType, resourceId, apiName, httpMethod, statusCode, startDate, endDate, limit, options); + async listAuditLogs(apiName?: string, startDate?: string, endDate?: string, limit?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAuditLogs(apiName, startDate, endDate, limit, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['AuditApi.listAuditLogs']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -222,7 +186,7 @@ export const AuditApiFactory = function (configuration?: Configuration, basePath * @throws {RequiredError} */ listAuditLogs(requestParameters: AuditApiListAuditLogsRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.listAuditLogs(requestParameters.userId, requestParameters.username, requestParameters.resourceType, requestParameters.resourceId, requestParameters.apiName, requestParameters.httpMethod, requestParameters.statusCode, requestParameters.startDate, requestParameters.endDate, requestParameters.limit, options).then((request) => request(axios, basePath)); + return localVarFp.listAuditLogs(requestParameters.apiName, requestParameters.startDate, requestParameters.endDate, requestParameters.limit, options).then((request) => request(axios, basePath)); }, }; }; @@ -275,34 +239,6 @@ export interface AuditApiGetAuditLogRequest { * @interface AuditApiListAuditLogsRequest */ export interface AuditApiListAuditLogsRequest { - /** - * Filter by user ID - * @type {string} - * @memberof AuditApiListAuditLogs - */ - readonly userId?: string - - /** - * Filter by username - * @type {string} - * @memberof AuditApiListAuditLogs - */ - readonly username?: string - - /** - * Filter by resource type - * @type {'collection' | 'document' | 'bot' | 'chat' | 'message' | 'api_key' | 'llm_provider' | 'llm_provider_model' | 'model_service_provider' | 'user' | 'config'} - * @memberof AuditApiListAuditLogs - */ - readonly resourceType?: ListAuditLogsResourceTypeEnum - - /** - * Filter by resource ID - * @type {string} - * @memberof AuditApiListAuditLogs - */ - readonly resourceId?: string - /** * Filter by API name * @type {string} @@ -310,20 +246,6 @@ export interface AuditApiListAuditLogsRequest { */ readonly apiName?: string - /** - * Filter by HTTP method - * @type {'POST' | 'PUT' | 'DELETE'} - * @memberof AuditApiListAuditLogs - */ - readonly httpMethod?: ListAuditLogsHttpMethodEnum - - /** - * Filter by status code - * @type {number} - * @memberof AuditApiListAuditLogs - */ - readonly statusCode?: number - /** * Filter by start date * @type {string} @@ -374,33 +296,7 @@ export class AuditApi extends BaseAPI implements AuditApiInterface { * @memberof AuditApi */ public listAuditLogs(requestParameters: AuditApiListAuditLogsRequest = {}, options?: RawAxiosRequestConfig) { - return AuditApiFp(this.configuration).listAuditLogs(requestParameters.userId, requestParameters.username, requestParameters.resourceType, requestParameters.resourceId, requestParameters.apiName, requestParameters.httpMethod, requestParameters.statusCode, requestParameters.startDate, requestParameters.endDate, requestParameters.limit, options).then((request) => request(this.axios, this.basePath)); + return AuditApiFp(this.configuration).listAuditLogs(requestParameters.apiName, requestParameters.startDate, requestParameters.endDate, requestParameters.limit, options).then((request) => request(this.axios, this.basePath)); } } -/** - * @export - */ -export const ListAuditLogsResourceTypeEnum = { - collection: 'collection', - document: 'document', - bot: 'bot', - chat: 'chat', - message: 'message', - api_key: 'api_key', - llm_provider: 'llm_provider', - llm_provider_model: 'llm_provider_model', - model_service_provider: 'model_service_provider', - user: 'user', - config: 'config' -} as const; -export type ListAuditLogsResourceTypeEnum = typeof ListAuditLogsResourceTypeEnum[keyof typeof ListAuditLogsResourceTypeEnum]; -/** - * @export - */ -export const ListAuditLogsHttpMethodEnum = { - POST: 'POST', - PUT: 'PUT', - DELETE: 'DELETE' -} as const; -export type ListAuditLogsHttpMethodEnum = typeof ListAuditLogsHttpMethodEnum[keyof typeof ListAuditLogsHttpMethodEnum]; diff --git a/frontend/src/api/apis/default-api.ts b/frontend/src/api/apis/default-api.ts index 5462a8334..922845c9a 100644 --- a/frontend/src/api/apis/default-api.ts +++ b/frontend/src/api/apis/default-api.ts @@ -104,11 +104,11 @@ import type { PromptTemplateList } from '../models'; // @ts-ignore import type { Register } from '../models'; // @ts-ignore -import type { SearchTestRequest } from '../models'; +import type { SearchRequest } from '../models'; // @ts-ignore -import type { SearchTestResult } from '../models'; +import type { SearchResult } from '../models'; // @ts-ignore -import type { SearchTestResultList } from '../models'; +import type { SearchResultList } from '../models'; // @ts-ignore import type { TagFilterRequest } from '../models'; // @ts-ignore @@ -1284,16 +1284,16 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }; }, /** - * Get the history of search tests - * @summary Get search test history + * Get the history of searches + * @summary Get search history * @param {string} collectionId * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsGet: async (collectionId: string, options: RawAxiosRequestConfig = {}): Promise => { + collectionsCollectionIdSearchesGet: async (collectionId: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'collectionId' is not null or undefined - assertParamExists('collectionsCollectionIdSearchTestsGet', 'collectionId', collectionId) - const localVarPath = `/collections/{collection_id}/searchTests` + assertParamExists('collectionsCollectionIdSearchesGet', 'collectionId', collectionId) + const localVarPath = `/collections/{collection_id}/searches` .replace(`{${"collection_id"}}`, encodeURIComponent(String(collectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1322,19 +1322,19 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }; }, /** - * Test search in a collection with different search types - * @summary Test search in collection + * Search in a collection with different search types + * @summary Search in collection * @param {string} collectionId - * @param {SearchTestRequest} searchTestRequest + * @param {SearchRequest} searchRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsPost: async (collectionId: string, searchTestRequest: SearchTestRequest, options: RawAxiosRequestConfig = {}): Promise => { + collectionsCollectionIdSearchesPost: async (collectionId: string, searchRequest: SearchRequest, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'collectionId' is not null or undefined - assertParamExists('collectionsCollectionIdSearchTestsPost', 'collectionId', collectionId) - // verify required parameter 'searchTestRequest' is not null or undefined - assertParamExists('collectionsCollectionIdSearchTestsPost', 'searchTestRequest', searchTestRequest) - const localVarPath = `/collections/{collection_id}/searchTests` + assertParamExists('collectionsCollectionIdSearchesPost', 'collectionId', collectionId) + // verify required parameter 'searchRequest' is not null or undefined + assertParamExists('collectionsCollectionIdSearchesPost', 'searchRequest', searchRequest) + const localVarPath = `/collections/{collection_id}/searches` .replace(`{${"collection_id"}}`, encodeURIComponent(String(collectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1358,7 +1358,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(searchTestRequest, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(searchRequest, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1366,21 +1366,21 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }; }, /** - * Delete a search test - * @summary Delete a search test + * Delete a search + * @summary Delete a search * @param {string} collectionId - * @param {string} searchTestId + * @param {string} searchId * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsSearchTestIdDelete: async (collectionId: string, searchTestId: string, options: RawAxiosRequestConfig = {}): Promise => { + collectionsCollectionIdSearchesSearchIdDelete: async (collectionId: string, searchId: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'collectionId' is not null or undefined - assertParamExists('collectionsCollectionIdSearchTestsSearchTestIdDelete', 'collectionId', collectionId) - // verify required parameter 'searchTestId' is not null or undefined - assertParamExists('collectionsCollectionIdSearchTestsSearchTestIdDelete', 'searchTestId', searchTestId) - const localVarPath = `/collections/{collection_id}/searchTests/{search_test_id}` + assertParamExists('collectionsCollectionIdSearchesSearchIdDelete', 'collectionId', collectionId) + // verify required parameter 'searchId' is not null or undefined + assertParamExists('collectionsCollectionIdSearchesSearchIdDelete', 'searchId', searchId) + const localVarPath = `/collections/{collection_id}/searches/{search_id}` .replace(`{${"collection_id"}}`, encodeURIComponent(String(collectionId))) - .replace(`{${"search_test_id"}}`, encodeURIComponent(String(searchTestId))); + .replace(`{${"search_id"}}`, encodeURIComponent(String(searchId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -2587,44 +2587,44 @@ export const DefaultApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * Get the history of search tests - * @summary Get search test history + * Get the history of searches + * @summary Get search history * @param {string} collectionId * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async collectionsCollectionIdSearchTestsGet(collectionId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchTestsGet(collectionId, options); + async collectionsCollectionIdSearchesGet(collectionId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchesGet(collectionId, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchTestsGet']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchesGet']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * Test search in a collection with different search types - * @summary Test search in collection + * Search in a collection with different search types + * @summary Search in collection * @param {string} collectionId - * @param {SearchTestRequest} searchTestRequest + * @param {SearchRequest} searchRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async collectionsCollectionIdSearchTestsPost(collectionId: string, searchTestRequest: SearchTestRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchTestsPost(collectionId, searchTestRequest, options); + async collectionsCollectionIdSearchesPost(collectionId: string, searchRequest: SearchRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchesPost(collectionId, searchRequest, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchTestsPost']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchesPost']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * Delete a search test - * @summary Delete a search test + * Delete a search + * @summary Delete a search * @param {string} collectionId - * @param {string} searchTestId + * @param {string} searchId * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async collectionsCollectionIdSearchTestsSearchTestIdDelete(collectionId: string, searchTestId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchTestsSearchTestIdDelete(collectionId, searchTestId, options); + async collectionsCollectionIdSearchesSearchIdDelete(collectionId: string, searchId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.collectionsCollectionIdSearchesSearchIdDelete(collectionId, searchId, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchTestsSearchTestIdDelete']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['DefaultApi.collectionsCollectionIdSearchesSearchIdDelete']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** @@ -3204,34 +3204,34 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa return localVarFp.collectionsCollectionIdPut(requestParameters.collectionId, requestParameters.collectionUpdate, options).then((request) => request(axios, basePath)); }, /** - * Get the history of search tests - * @summary Get search test history - * @param {DefaultApiCollectionsCollectionIdSearchTestsGetRequest} requestParameters Request parameters. + * Get the history of searches + * @summary Get search history + * @param {DefaultApiCollectionsCollectionIdSearchesGetRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsGet(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsGetRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.collectionsCollectionIdSearchTestsGet(requestParameters.collectionId, options).then((request) => request(axios, basePath)); + collectionsCollectionIdSearchesGet(requestParameters: DefaultApiCollectionsCollectionIdSearchesGetRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.collectionsCollectionIdSearchesGet(requestParameters.collectionId, options).then((request) => request(axios, basePath)); }, /** - * Test search in a collection with different search types - * @summary Test search in collection - * @param {DefaultApiCollectionsCollectionIdSearchTestsPostRequest} requestParameters Request parameters. + * Search in a collection with different search types + * @summary Search in collection + * @param {DefaultApiCollectionsCollectionIdSearchesPostRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsPost(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsPostRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.collectionsCollectionIdSearchTestsPost(requestParameters.collectionId, requestParameters.searchTestRequest, options).then((request) => request(axios, basePath)); + collectionsCollectionIdSearchesPost(requestParameters: DefaultApiCollectionsCollectionIdSearchesPostRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.collectionsCollectionIdSearchesPost(requestParameters.collectionId, requestParameters.searchRequest, options).then((request) => request(axios, basePath)); }, /** - * Delete a search test - * @summary Delete a search test - * @param {DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest} requestParameters Request parameters. + * Delete a search + * @summary Delete a search + * @param {DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - collectionsCollectionIdSearchTestsSearchTestIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.collectionsCollectionIdSearchTestsSearchTestIdDelete(requestParameters.collectionId, requestParameters.searchTestId, options).then((request) => request(axios, basePath)); + collectionsCollectionIdSearchesSearchIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.collectionsCollectionIdSearchesSearchIdDelete(requestParameters.collectionId, requestParameters.searchId, options).then((request) => request(axios, basePath)); }, /** * Get a list of collections @@ -3735,34 +3735,34 @@ export interface DefaultApiInterface { collectionsCollectionIdPut(requestParameters: DefaultApiCollectionsCollectionIdPutRequest, options?: RawAxiosRequestConfig): AxiosPromise; /** - * Get the history of search tests - * @summary Get search test history - * @param {DefaultApiCollectionsCollectionIdSearchTestsGetRequest} requestParameters Request parameters. + * Get the history of searches + * @summary Get search history + * @param {DefaultApiCollectionsCollectionIdSearchesGetRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApiInterface */ - collectionsCollectionIdSearchTestsGet(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsGetRequest, options?: RawAxiosRequestConfig): AxiosPromise; + collectionsCollectionIdSearchesGet(requestParameters: DefaultApiCollectionsCollectionIdSearchesGetRequest, options?: RawAxiosRequestConfig): AxiosPromise; /** - * Test search in a collection with different search types - * @summary Test search in collection - * @param {DefaultApiCollectionsCollectionIdSearchTestsPostRequest} requestParameters Request parameters. + * Search in a collection with different search types + * @summary Search in collection + * @param {DefaultApiCollectionsCollectionIdSearchesPostRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApiInterface */ - collectionsCollectionIdSearchTestsPost(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsPostRequest, options?: RawAxiosRequestConfig): AxiosPromise; + collectionsCollectionIdSearchesPost(requestParameters: DefaultApiCollectionsCollectionIdSearchesPostRequest, options?: RawAxiosRequestConfig): AxiosPromise; /** - * Delete a search test - * @summary Delete a search test - * @param {DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest} requestParameters Request parameters. + * Delete a search + * @summary Delete a search + * @param {DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApiInterface */ - collectionsCollectionIdSearchTestsSearchTestIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest, options?: RawAxiosRequestConfig): AxiosPromise; + collectionsCollectionIdSearchesSearchIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest, options?: RawAxiosRequestConfig): AxiosPromise; /** * Get a list of collections @@ -4519,59 +4519,59 @@ export interface DefaultApiCollectionsCollectionIdPutRequest { } /** - * Request parameters for collectionsCollectionIdSearchTestsGet operation in DefaultApi. + * Request parameters for collectionsCollectionIdSearchesGet operation in DefaultApi. * @export - * @interface DefaultApiCollectionsCollectionIdSearchTestsGetRequest + * @interface DefaultApiCollectionsCollectionIdSearchesGetRequest */ -export interface DefaultApiCollectionsCollectionIdSearchTestsGetRequest { +export interface DefaultApiCollectionsCollectionIdSearchesGetRequest { /** * * @type {string} - * @memberof DefaultApiCollectionsCollectionIdSearchTestsGet + * @memberof DefaultApiCollectionsCollectionIdSearchesGet */ readonly collectionId: string } /** - * Request parameters for collectionsCollectionIdSearchTestsPost operation in DefaultApi. + * Request parameters for collectionsCollectionIdSearchesPost operation in DefaultApi. * @export - * @interface DefaultApiCollectionsCollectionIdSearchTestsPostRequest + * @interface DefaultApiCollectionsCollectionIdSearchesPostRequest */ -export interface DefaultApiCollectionsCollectionIdSearchTestsPostRequest { +export interface DefaultApiCollectionsCollectionIdSearchesPostRequest { /** * * @type {string} - * @memberof DefaultApiCollectionsCollectionIdSearchTestsPost + * @memberof DefaultApiCollectionsCollectionIdSearchesPost */ readonly collectionId: string /** * - * @type {SearchTestRequest} - * @memberof DefaultApiCollectionsCollectionIdSearchTestsPost + * @type {SearchRequest} + * @memberof DefaultApiCollectionsCollectionIdSearchesPost */ - readonly searchTestRequest: SearchTestRequest + readonly searchRequest: SearchRequest } /** - * Request parameters for collectionsCollectionIdSearchTestsSearchTestIdDelete operation in DefaultApi. + * Request parameters for collectionsCollectionIdSearchesSearchIdDelete operation in DefaultApi. * @export - * @interface DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest + * @interface DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest */ -export interface DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest { +export interface DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest { /** * * @type {string} - * @memberof DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDelete + * @memberof DefaultApiCollectionsCollectionIdSearchesSearchIdDelete */ readonly collectionId: string /** * * @type {string} - * @memberof DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDelete + * @memberof DefaultApiCollectionsCollectionIdSearchesSearchIdDelete */ - readonly searchTestId: string + readonly searchId: string } /** @@ -5183,39 +5183,39 @@ export class DefaultApi extends BaseAPI implements DefaultApiInterface { } /** - * Get the history of search tests - * @summary Get search test history - * @param {DefaultApiCollectionsCollectionIdSearchTestsGetRequest} requestParameters Request parameters. + * Get the history of searches + * @summary Get search history + * @param {DefaultApiCollectionsCollectionIdSearchesGetRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public collectionsCollectionIdSearchTestsGet(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsGetRequest, options?: RawAxiosRequestConfig) { - return DefaultApiFp(this.configuration).collectionsCollectionIdSearchTestsGet(requestParameters.collectionId, options).then((request) => request(this.axios, this.basePath)); + public collectionsCollectionIdSearchesGet(requestParameters: DefaultApiCollectionsCollectionIdSearchesGetRequest, options?: RawAxiosRequestConfig) { + return DefaultApiFp(this.configuration).collectionsCollectionIdSearchesGet(requestParameters.collectionId, options).then((request) => request(this.axios, this.basePath)); } /** - * Test search in a collection with different search types - * @summary Test search in collection - * @param {DefaultApiCollectionsCollectionIdSearchTestsPostRequest} requestParameters Request parameters. + * Search in a collection with different search types + * @summary Search in collection + * @param {DefaultApiCollectionsCollectionIdSearchesPostRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public collectionsCollectionIdSearchTestsPost(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsPostRequest, options?: RawAxiosRequestConfig) { - return DefaultApiFp(this.configuration).collectionsCollectionIdSearchTestsPost(requestParameters.collectionId, requestParameters.searchTestRequest, options).then((request) => request(this.axios, this.basePath)); + public collectionsCollectionIdSearchesPost(requestParameters: DefaultApiCollectionsCollectionIdSearchesPostRequest, options?: RawAxiosRequestConfig) { + return DefaultApiFp(this.configuration).collectionsCollectionIdSearchesPost(requestParameters.collectionId, requestParameters.searchRequest, options).then((request) => request(this.axios, this.basePath)); } /** - * Delete a search test - * @summary Delete a search test - * @param {DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest} requestParameters Request parameters. + * Delete a search + * @summary Delete a search + * @param {DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public collectionsCollectionIdSearchTestsSearchTestIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchTestsSearchTestIdDeleteRequest, options?: RawAxiosRequestConfig) { - return DefaultApiFp(this.configuration).collectionsCollectionIdSearchTestsSearchTestIdDelete(requestParameters.collectionId, requestParameters.searchTestId, options).then((request) => request(this.axios, this.basePath)); + public collectionsCollectionIdSearchesSearchIdDelete(requestParameters: DefaultApiCollectionsCollectionIdSearchesSearchIdDeleteRequest, options?: RawAxiosRequestConfig) { + return DefaultApiFp(this.configuration).collectionsCollectionIdSearchesSearchIdDelete(requestParameters.collectionId, requestParameters.searchId, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/frontend/src/api/models/audit-log.ts b/frontend/src/api/models/audit-log.ts index 21673bf2c..5c960a80c 100644 --- a/frontend/src/api/models/audit-log.ts +++ b/frontend/src/api/models/audit-log.ts @@ -147,7 +147,8 @@ export const AuditLogResourceTypeEnum = { llm_provider_model: 'llm_provider_model', model_service_provider: 'model_service_provider', user: 'user', - config: 'config' + flow: 'flow', + search: 'search' } as const; export type AuditLogResourceTypeEnum = typeof AuditLogResourceTypeEnum[keyof typeof AuditLogResourceTypeEnum]; diff --git a/frontend/src/api/models/index.ts b/frontend/src/api/models/index.ts index 16c6dea67..08172cf23 100644 --- a/frontend/src/api/models/index.ts +++ b/frontend/src/api/models/index.ts @@ -86,10 +86,10 @@ export * from './rerank-request-documents-one-of-inner'; export * from './rerank-response'; export * from './rerank-usage'; export * from './schema-definition'; -export * from './search-test-request'; -export * from './search-test-result'; -export * from './search-test-result-item'; -export * from './search-test-result-list'; +export * from './search-request'; +export * from './search-result'; +export * from './search-result-item'; +export * from './search-result-list'; export * from './tag-filter-condition'; export * from './tag-filter-request'; export * from './user'; diff --git a/frontend/src/api/models/search-test-request.ts b/frontend/src/api/models/search-request.ts similarity index 81% rename from frontend/src/api/models/search-test-request.ts rename to frontend/src/api/models/search-request.ts index 431ad6f76..e1ae66042 100644 --- a/frontend/src/api/models/search-test-request.ts +++ b/frontend/src/api/models/search-request.ts @@ -24,33 +24,33 @@ import type { GraphSearchParams } from './graph-search-params'; import type { VectorSearchParams } from './vector-search-params'; /** - * + * Search request * @export - * @interface SearchTestRequest + * @interface SearchRequest */ -export interface SearchTestRequest { +export interface SearchRequest { /** - * The user input query + * * @type {string} - * @memberof SearchTestRequest + * @memberof SearchRequest */ 'query'?: string; /** * * @type {VectorSearchParams} - * @memberof SearchTestRequest + * @memberof SearchRequest */ 'vector_search'?: VectorSearchParams; /** * * @type {FulltextSearchParams} - * @memberof SearchTestRequest + * @memberof SearchRequest */ 'fulltext_search'?: FulltextSearchParams; /** * * @type {GraphSearchParams} - * @memberof SearchTestRequest + * @memberof SearchRequest */ 'graph_search'?: GraphSearchParams; } diff --git a/frontend/src/api/models/search-test-result-item.ts b/frontend/src/api/models/search-result-item.ts similarity index 62% rename from frontend/src/api/models/search-test-result-item.ts rename to frontend/src/api/models/search-result-item.ts index 66a23e7fa..7e9cb64f8 100644 --- a/frontend/src/api/models/search-test-result-item.ts +++ b/frontend/src/api/models/search-result-item.ts @@ -17,47 +17,47 @@ /** * * @export - * @interface SearchTestResultItem + * @interface SearchResultItem */ -export interface SearchTestResultItem { +export interface SearchResultItem { /** * Result rank * @type {number} - * @memberof SearchTestResultItem + * @memberof SearchResultItem */ 'rank'?: number; /** * Result score * @type {number} - * @memberof SearchTestResultItem + * @memberof SearchResultItem */ 'score'?: number; /** * Result content * @type {string} - * @memberof SearchTestResultItem + * @memberof SearchResultItem */ 'content'?: string; /** * Source document or metadata * @type {string} - * @memberof SearchTestResultItem + * @memberof SearchResultItem */ 'source'?: string; /** * Recall type * @type {string} - * @memberof SearchTestResultItem + * @memberof SearchResultItem */ - 'recall_type'?: SearchTestResultItemRecallTypeEnum; + 'recall_type'?: SearchResultItemRecallTypeEnum; } -export const SearchTestResultItemRecallTypeEnum = { +export const SearchResultItemRecallTypeEnum = { vector_search: 'vector_search', graph_search: 'graph_search', fulltext_search: 'fulltext_search' } as const; -export type SearchTestResultItemRecallTypeEnum = typeof SearchTestResultItemRecallTypeEnum[keyof typeof SearchTestResultItemRecallTypeEnum]; +export type SearchResultItemRecallTypeEnum = typeof SearchResultItemRecallTypeEnum[keyof typeof SearchResultItemRecallTypeEnum]; diff --git a/frontend/src/api/models/search-test-result-list.ts b/frontend/src/api/models/search-result-list.ts similarity index 59% rename from frontend/src/api/models/search-test-result-list.ts rename to frontend/src/api/models/search-result-list.ts index 00ef9356b..e9318aea3 100644 --- a/frontend/src/api/models/search-test-result-list.ts +++ b/frontend/src/api/models/search-result-list.ts @@ -15,19 +15,19 @@ // May contain unused imports in some cases // @ts-ignore -import type { SearchTestResult } from './search-test-result'; +import type { SearchResult } from './search-result'; /** - * A list of search test results + * A list of search results * @export - * @interface SearchTestResultList + * @interface SearchResultList */ -export interface SearchTestResultList { +export interface SearchResultList { /** * - * @type {Array} - * @memberof SearchTestResultList + * @type {Array} + * @memberof SearchResultList */ - 'items'?: Array; + 'items'?: Array; } diff --git a/frontend/src/api/models/search-test-result.ts b/frontend/src/api/models/search-result.ts similarity index 69% rename from frontend/src/api/models/search-test-result.ts rename to frontend/src/api/models/search-result.ts index 7c4fa7d31..fbb165453 100644 --- a/frontend/src/api/models/search-test-result.ts +++ b/frontend/src/api/models/search-result.ts @@ -21,7 +21,7 @@ import type { FulltextSearchParams } from './fulltext-search-params'; import type { GraphSearchParams } from './graph-search-params'; // May contain unused imports in some cases // @ts-ignore -import type { SearchTestResultItem } from './search-test-result-item'; +import type { SearchResultItem } from './search-result-item'; // May contain unused imports in some cases // @ts-ignore import type { VectorSearchParams } from './vector-search-params'; @@ -29,49 +29,49 @@ import type { VectorSearchParams } from './vector-search-params'; /** * * @export - * @interface SearchTestResult + * @interface SearchResult */ -export interface SearchTestResult { +export interface SearchResult { /** - * The id of the search test result + * The id of the search result * @type {string} - * @memberof SearchTestResult + * @memberof SearchResult */ 'id'?: string; /** * * @type {string} - * @memberof SearchTestResult + * @memberof SearchResult */ 'query'?: string; /** * * @type {VectorSearchParams} - * @memberof SearchTestResult + * @memberof SearchResult */ 'vector_search'?: VectorSearchParams; /** * * @type {FulltextSearchParams} - * @memberof SearchTestResult + * @memberof SearchResult */ 'fulltext_search'?: FulltextSearchParams; /** * * @type {GraphSearchParams} - * @memberof SearchTestResult + * @memberof SearchResult */ 'graph_search'?: GraphSearchParams; /** * - * @type {Array} - * @memberof SearchTestResult + * @type {Array} + * @memberof SearchResult */ - 'items'?: Array; + 'items'?: Array; /** - * The creation time of the search test result + * The creation time of the search result * @type {string} - * @memberof SearchTestResult + * @memberof SearchResult */ 'created'?: string; } diff --git a/frontend/src/api/openapi.merged.yaml b/frontend/src/api/openapi.merged.yaml index f32c4bb50..e2e49be48 100644 --- a/frontend/src/api/openapi.merged.yaml +++ b/frontend/src/api/openapi.merged.yaml @@ -686,10 +686,10 @@ paths: application/json: schema: $ref: '#/components/schemas/failResponse' - /collections/{collection_id}/searchTests: + /collections/{collection_id}/searches: get: - summary: Get search test history - description: Get the history of search tests + summary: Get search history + description: Get the history of searches security: - BearerAuth: [] parameters: @@ -700,11 +700,11 @@ paths: type: string responses: '200': - description: Search test history + description: Search history content: application/json: schema: - $ref: '#/components/schemas/searchTestResultList' + $ref: '#/components/schemas/searchResultList' '401': description: Unauthorized content: @@ -712,8 +712,8 @@ paths: schema: $ref: '#/components/schemas/failResponse' post: - summary: Test search in collection - description: Test search in a collection with different search types + summary: Search in collection + description: Search in a collection with different search types security: - BearerAuth: [] parameters: @@ -727,24 +727,24 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/searchTestRequest' + $ref: '#/components/schemas/searchRequest' responses: '200': description: Search results content: application/json: schema: - $ref: '#/components/schemas/searchTestResult' + $ref: '#/components/schemas/searchResult' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/failResponse' - /collections/{collection_id}/searchTests/{search_test_id}: + /collections/{collection_id}/searches/{search_id}: delete: - summary: Delete a search test - description: Delete a search test + summary: Delete a search + description: Delete a search security: - BearerAuth: [] parameters: @@ -753,16 +753,20 @@ paths: required: true schema: type: string - - name: search_test_id + - name: search_id in: path required: true schema: type: string responses: - '204': - description: Search test deleted successfully + '200': + description: Search deleted successfully '401': description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/failResponse' /apikeys: get: summary: Get API keys @@ -1669,64 +1673,12 @@ paths: description: List audit logs with filtering options operationId: list_audit_logs parameters: - - name: user_id - in: query - required: false - schema: - type: string - description: Filter by user ID - - name: username - in: query - required: false - schema: - type: string - description: Filter by username - - name: resource_type - in: query - required: false - schema: - type: string - enum: - - collection - - document - - bot - - chat - - message - - api_key - - llm_provider - - llm_provider_model - - model_service_provider - - user - - config - description: Filter by resource type - - name: resource_id - in: query - required: false - schema: - type: string - description: Filter by resource ID - name: api_name in: query required: false schema: type: string description: Filter by API name - - name: http_method - in: query - required: false - schema: - type: string - enum: - - POST - - PUT - - DELETE - description: Filter by HTTP method - - name: status_code - in: query - required: false - schema: - type: integer - description: Filter by status code - name: start_date in: query required: false @@ -2866,7 +2818,7 @@ components: topk: type: integer description: Top K results - searchTestResultItem: + searchResultItem: type: object properties: rank: @@ -2888,12 +2840,12 @@ components: - vector_search - graph_search - fulltext_search - searchTestResult: + searchResult: type: object properties: id: type: string - description: The id of the search test result + description: The id of the search result query: type: string vector_search: @@ -2905,25 +2857,25 @@ components: items: type: array items: - $ref: '#/components/schemas/searchTestResultItem' + $ref: '#/components/schemas/searchResultItem' created: type: string format: date-time - description: The creation time of the search test result - searchTestResultList: + description: The creation time of the search result + searchResultList: type: object - description: A list of search test results + description: A list of search results properties: items: type: array items: - $ref: '#/components/schemas/searchTestResult' - searchTestRequest: + $ref: '#/components/schemas/searchResult' + searchRequest: type: object + description: Search request properties: query: type: string - description: The user input query vector_search: $ref: '#/components/schemas/vectorSearchParams' fulltext_search: @@ -3605,7 +3557,8 @@ components: - llm_provider_model - model_service_provider - user - - config + - flow + - search nullable: true description: Type of resource resource_id: diff --git a/frontend/src/locales/en-US.ts b/frontend/src/locales/en-US.ts index a749b091b..bb7eb6031 100644 --- a/frontend/src/locales/en-US.ts +++ b/frontend/src/locales/en-US.ts @@ -302,22 +302,23 @@ export default { 'feedback.tag.unhelpful': 'Not Helpful', 'feedback.tag.other': 'Other Issue', - 'searchTest.title': 'Search Test', - 'searchTest.pleaseInputQuestion': 'Please enter your question', - 'searchTest.test': 'Test', - 'searchTest.type.vector_search': 'Vector Search', - 'searchTest.type.fulltext_search': 'Fulltext Search', - 'searchTest.type.graph_search': 'Graph Search', - 'searchTest.similarityThreshold': 'Similarity Threshold', - 'searchTest.vectorTopK': 'Vector TopK', - 'searchTest.fulltextTopK': 'Fulltext TopK', - 'searchTest.graphsearchTopK': 'Graph TopK', - 'searchTest.searchResults': 'Search Results', - 'searchTest.searchResults.detail': + 'search.title': 'Search', + 'search.pleaseInputQuestion': 'Please enter your question', + 'search.test': 'Test', + 'search.type.vector_search': 'Vector Search', + 'search.type.fulltext_search': 'Fulltext Search', + 'search.type.graph_search': 'Graph Search', + 'search.similarityThreshold': 'Similarity Threshold', + 'search.vectorTopK': 'Vector TopK', + 'search.fulltextTopK': 'Fulltext TopK', + 'search.graphsearchTopK': 'Graph TopK', + 'search.searchResults': 'Search Results', + 'search.searchResults.detail': 'There are {count} search results in total', - 'searchTest.searchResults.empty': 'No search results', - 'searchTest.history_question': 'History Questions', - 'searchTest.confirmDeleteHistory': + 'search.searchResults.empty': 'No search results', + 'search.history_question': 'History Questions', + 'search.confirmDeleteHistory': 'Are you sure you want to delete this history record?', - 'searchTest.similarity': 'Similarity', + 'search.similarity': 'Similarity', + 'searchType.title': 'Select Search Types', }; diff --git a/frontend/src/locales/en-US/collection.ts b/frontend/src/locales/en-US/collection.ts index 66ed8e71b..7c3d922f2 100644 --- a/frontend/src/locales/en-US/collection.ts +++ b/frontend/src/locales/en-US/collection.ts @@ -2,7 +2,7 @@ export const collection = { 'collection.name': 'Dataset', 'collection.files': 'All files', 'collection.settings': 'Settings', - 'collection.search_test': 'Search Test', + 'collection.search': 'Search', 'collection.add': 'Add Dataset', 'collection.select': 'Select Dataset', 'collection.tips': diff --git a/frontend/src/locales/zh-CN.ts b/frontend/src/locales/zh-CN.ts index 5272f902a..78f3898bf 100644 --- a/frontend/src/locales/zh-CN.ts +++ b/frontend/src/locales/zh-CN.ts @@ -299,20 +299,21 @@ export default { 'feedback.tag.unhelpful': '没有帮助', 'feedback.tag.other': '其他问题', - 'searchTest.title': '检索测试', - 'searchTest.pleaseInputQuestion': '请输入要测试的问题', - 'searchTest.test': '测试', - 'searchTest.type.vector_search': '向量检索', - 'searchTest.type.fulltext_search': '全文检索', - 'searchTest.type.graph_search': '图检索', - 'searchTest.similarityThreshold': '相似度阈值', - 'searchTest.vectorTopK': '向量TopK', - 'searchTest.fulltextTopK': '全文TopK', - 'searchTest.graphsearchTopK': '图TopK', - 'searchTest.searchResults': '检索结果', - 'searchTest.searchResults.detail': '共有{count}条检索结果', - 'searchTest.searchResults.empty': '没有检索结果', - 'searchTest.history_question': '历史问题', - 'searchTest.confirmDeleteHistory': '确定要删除这条历史记录吗?', - 'searchTest.similarity': '相似度', + 'search.title': '检索测试', + 'search.pleaseInputQuestion': '请输入要测试的问题', + 'search.test': '测试', + 'search.type.vector_search': '向量检索', + 'search.type.fulltext_search': '全文检索', + 'search.type.graph_search': '图检索', + 'search.similarityThreshold': '相似度阈值', + 'search.vectorTopK': '向量TopK', + 'search.fulltextTopK': '全文TopK', + 'search.graphsearchTopK': '图TopK', + 'search.searchResults': '检索结果', + 'search.searchResults.detail': '共有{count}条检索结果', + 'search.searchResults.empty': '没有检索结果', + 'search.history_question': '历史问题', + 'search.confirmDeleteHistory': '确定要删除这条历史记录吗?', + 'search.similarity': '相似度', + 'searchType.title': '选择检索类型', }; diff --git a/frontend/src/locales/zh-CN/collection.ts b/frontend/src/locales/zh-CN/collection.ts index 2b496c82e..d50a91891 100644 --- a/frontend/src/locales/zh-CN/collection.ts +++ b/frontend/src/locales/zh-CN/collection.ts @@ -2,7 +2,7 @@ export const collection = { 'collection.name': '知识库', 'collection.files': '全部文件', 'collection.settings': '设置', - 'collection.search_test': '检索测试', + 'collection.search': '检索测试', 'collection.add': '添加知识库', 'collection.select': '请选择知识库', 'collection.tips': '你可以在知识库里导入和管理你的数据源以增强LLM的上下文。', @@ -32,3 +32,8 @@ export const collection = { 'collection.lightrag_model': 'Light RAG模型', 'collection.lightrag_model.required': '请选择Light RAG模型', }; + +export default { + 'collection.documents': '文档管理', + 'collection.flow': '流程编辑器', +}; diff --git a/frontend/src/pages/bots/$botId/flow/_nodes/_outputs.tsx b/frontend/src/pages/bots/$botId/flow/_nodes/_outputs.tsx index bbbf0b5df..4fdc78467 100644 --- a/frontend/src/pages/bots/$botId/flow/_nodes/_outputs.tsx +++ b/frontend/src/pages/bots/$botId/flow/_nodes/_outputs.tsx @@ -63,7 +63,7 @@ export const NodeOutputs = ({ node }: OutputProps) => { {output.metadata?.recall_type ? ( {formatMessage({ - id: `searchTest.type.${output.metadata.recall_type}`, + id: `search.type.${output.metadata.recall_type}`, })} ) : null} diff --git a/frontend/src/pages/collections/$collectionId/_navbar.tsx b/frontend/src/pages/collections/$collectionId/_navbar.tsx index 5d5f46cec..ab01564c4 100644 --- a/frontend/src/pages/collections/$collectionId/_navbar.tsx +++ b/frontend/src/pages/collections/$collectionId/_navbar.tsx @@ -23,8 +23,8 @@ export const NavbarCollection = () => { key: `/collections/${collectionId}/documents`, }, { - label: , - key: `/collections/${collectionId}/search-test`, + label: , + key: `/collections/${collectionId}/search`, }, { label: , diff --git a/frontend/src/pages/collections/$collectionId/search-test.tsx b/frontend/src/pages/collections/$collectionId/search.tsx similarity index 85% rename from frontend/src/pages/collections/$collectionId/search-test.tsx rename to frontend/src/pages/collections/$collectionId/search.tsx index 43ba60ddb..0cd2fb888 100644 --- a/frontend/src/pages/collections/$collectionId/search-test.tsx +++ b/frontend/src/pages/collections/$collectionId/search.tsx @@ -1,4 +1,4 @@ -import { SearchTestRequest, SearchTestResult } from '@/api'; +import { SearchRequest, SearchResult } from '@/api'; import { ApeMarkdown } from '@/components'; import { DATETIME_FORMAT } from '@/constants'; import { api } from '@/services'; @@ -34,7 +34,7 @@ type SearchTypeEnum = 'vector_search' | 'fulltext_search' | 'graph_search'; export default () => { const { formatMessage } = useIntl(); - const [form] = Form.useForm(); + const [form] = Form.useForm(); const { collectionId } = useParams(); const { loading, setLoading } = useModel('global'); const [modal, contextHolder] = Modal.useModal(); @@ -43,16 +43,16 @@ export default () => { 'vector_search', ]); - const [records, setRecords] = useState([]); + const [records, setRecords] = useState([]); const [historyModal, setHistoryModal] = useState<{ visible: boolean; - record: SearchTestResult | undefined; + record: SearchResult | undefined; }>(); const { token } = theme.useToken(); const fetchHistory = async () => { if (!collectionId) return; - const res = await api.collectionsCollectionIdSearchTestsGet({ + const res = await api.collectionsCollectionIdSearchesGet({ collectionId, }); setRecords(res?.data?.items || []); @@ -63,10 +63,10 @@ export default () => { const values = await form.validateFields(); setLoading(true); api - .collectionsCollectionIdSearchTestsPost( + .collectionsCollectionIdSearchesPost( { collectionId, - searchTestRequest: values, + searchRequest: values, }, { timeout: 30 * 1000, @@ -86,29 +86,29 @@ export default () => { }); }; - const onDeleteRecord = async (record: SearchTestResult) => { + const onDeleteRecord = async (record: SearchResult) => { if (!collectionId || !record.id) return; const confirmed = await modal.confirm({ title: formatMessage({ id: 'action.confirm' }), - content: formatMessage({ id: 'searchTest.confirmDeleteHistory' }), + content: formatMessage({ id: 'search.confirmDeleteHistory' }), okButtonProps: { danger: true, loading, }, }); if (confirmed) { - await api.collectionsCollectionIdSearchTestsSearchTestIdDelete({ + await api.collectionsCollectionIdSearchesSearchIdDelete({ collectionId, - searchTestId: record.id, + searchId: record.id, }); toast.success(formatMessage({ id: 'tips.delete.success' })); fetchHistory(); } }; - const columns: TableProps['columns'] = [ + const columns: TableProps['columns'] = [ { - title: formatMessage({ id: 'searchTest.history_question' }), + title: formatMessage({ id: 'search.history_question' }), dataIndex: 'query', render: (_value, record) => { return ( @@ -131,7 +131,7 @@ export default () => { }, }, { - title: formatMessage({ id: 'searchTest.searchResults' }), + title: formatMessage({ id: 'search.searchResults' }), align: 'center', render: (text, record) => ( @@ -362,7 +362,7 @@ export default () => { setHistoryModal({ visible: false, record: undefined })} footer={false} size="large" @@ -375,7 +375,7 @@ export default () => { extra={ {formatMessage( - { id: 'searchTest.searchResults.detail' }, + { id: 'search.searchResults.detail' }, { count: _.size(historyModal?.record?.items) }, )} @@ -411,7 +411,7 @@ export default () => { {item.recall_type ? ( {formatMessage({ - id: `searchTest.type.${item.recall_type}`, + id: `search.type.${item.recall_type}`, })} ) : null} @@ -439,7 +439,7 @@ export default () => { icon={ } - subTitle={} + subTitle={} /> )} diff --git a/tests/e2e_test/test_collection.py b/tests/e2e_test/test_collection.py index ee2e46ead..cc8cd573b 100644 --- a/tests/e2e_test/test_collection.py +++ b/tests/e2e_test/test_collection.py @@ -25,7 +25,7 @@ EMBEDDING_MODEL_NAME, EMBEDDING_MODEL_PROVIDER, ) -from tests.e2e_test.utils import assert_collection_config, assert_search_test_result +from tests.e2e_test.utils import assert_collection_config, assert_search_result def test_list_collections(benchmark, client, collection): @@ -73,19 +73,19 @@ def test_update_collection(benchmark, client, collection): def run_search_test(client, collection, document, search_data): - resp = client.post(f"/api/v1/collections/{collection['id']}/searchTests", json=search_data) + resp = client.post(f"/api/v1/collections/{collection['id']}/searches", json=search_data) assert resp.status_code == HTTPStatus.OK, resp.text result = resp.json() - assert_search_test_result(search_data, result) + assert_search_result(search_data, result) - resp = client.get(f"/api/v1/collections/{collection['id']}/searchTests") + resp = client.get(f"/api/v1/collections/{collection['id']}/searches") assert resp.status_code == HTTPStatus.OK, resp.text data = resp.json() assert len(data["items"]) == 1 assert data["items"][0]["id"] == result["id"] test_id = result["id"] - resp = client.delete(f"/api/v1/collections/{collection['id']}/searchTests/{test_id}") + resp = client.delete(f"/api/v1/collections/{collection['id']}/searches/{test_id}") assert resp.status_code == HTTPStatus.OK, resp.text diff --git a/tests/e2e_test/utils.py b/tests/e2e_test/utils.py index 710ccc455..6c5902af4 100644 --- a/tests/e2e_test/utils.py +++ b/tests/e2e_test/utils.py @@ -46,7 +46,7 @@ def assert_collection_config(expected, actual): assert expected["config"]["completion"][key] == actual["config"]["completion"][key] -def assert_search_test_result(expected, actual): +def assert_search_result(expected, actual): """ Assert that result contains all the expected values from search_data, key by key. """ @@ -55,7 +55,7 @@ def assert_search_test_result(expected, actual): if "vector_search" not in expected and "fulltext_search" not in expected and "graph_search" not in expected: pytest.fail("No search type specified") - def assert_search_test_result_item(search_type, items): + def assert_search_result_item(search_type, items): for item in items: if search_type != "graph_search": assert isinstance(item["score"], float) @@ -66,16 +66,25 @@ def assert_search_test_result_item(search_type, items): assert actual["vector_search"] is not None for key in ["topk", "similarity"]: assert expected["vector_search"][key] == actual["vector_search"][key] - assert_search_test_result_item("vector_search", actual["items"]) + assert_search_result_item("vector_search", actual["items"]) if "fulltext_search" in expected: assert actual["fulltext_search"] is not None for key in ["topk"]: assert expected["fulltext_search"][key] == actual["fulltext_search"][key] - assert_search_test_result_item("fulltext_search", actual["items"]) + assert_search_result_item("fulltext_search", actual["items"]) if "graph_search" in expected: assert actual["graph_search"] is not None for key in ["topk"]: assert expected["graph_search"][key] == actual["graph_search"][key] - assert_search_test_result_item("graph_search", actual["items"]) + assert_search_result_item("graph_search", actual["items"]) + + +def assert_search_result_item(search_type, items): + found = False + for item in items: + if item.get("recall_type") == search_type: + found = True + break + assert found, f"No {search_type} item found in search results"