Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aperag/api/components/schemas/audit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
20 changes: 10 additions & 10 deletions aperag/api/components/schemas/collection.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -313,20 +313,20 @@ 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:
$ref: '#/fulltextSearchParams'
graph_search:
$ref: '#/graphSearchParams'

searchTestResultItem:
searchResultItem:
type: object
properties:
rank:
Expand All @@ -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:
Expand All @@ -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'
8 changes: 4 additions & 4 deletions aperag/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
66 changes: 35 additions & 31 deletions aperag/api/paths/collections.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -331,23 +333,30 @@ 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:
application/json:
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:
Expand All @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions aperag/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions aperag/db/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -58,7 +58,7 @@ class AsyncDatabaseOps(
AsyncUserRepositoryMixin,
AsyncLlmProviderRepositoryMixin,
AsyncSystemRepositoryMixin,
AsyncSearchTestRepositoryMixin,
AsyncSearchRepositoryMixin,
):
pass

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion aperag/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion aperag/migration/versions/20250621002836-2768dfee8bbc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)'),
Expand Down
50 changes: 50 additions & 0 deletions aperag/migration/versions/20250623110658-23c0533b6b63.py
Original file line number Diff line number Diff line change
@@ -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')
Loading
Loading