feat(market): agents by downloads

This commit is contained in:
Nicholas Tindle
2024-08-01 22:08:57 -05:00
parent 434628657f
commit 6e5948eb7c
2 changed files with 102 additions and 4 deletions

View File

@@ -48,6 +48,8 @@ async def create_agent_entry(
"keywords": keywords,
"categories": categories,
"graph": graph,
# Add analytics tracker maybe?
# "AnalyticsTracker": {"create": {"downloads": 0, "views": 0}},
}
)
@@ -194,7 +196,7 @@ async def search_db(
description_threshold: int = 60,
sort_by: str = "rank",
sort_order: typing.Literal["desc"] | typing.Literal["asc"] = "desc",
):
) -> typing.List[market.utils.extension_types.AgentsWithRank]:
"""Perform a search for agents based on the provided query string.
Args:
@@ -264,3 +266,51 @@ async def search_db(
raise AgentQueryError(f"Database query failed: {str(e)}")
except Exception as e:
raise AgentQueryError(f"Unexpected error occurred: {str(e)}")
async def get_top_agents_by_downloads(page: int = 1, page_size: int = 10):
"""Retrieve the top agents by download count.
Args:
page (int, optional): The page number. Defaults to 1.
page_size (int, optional): The number of agents per page. Defaults to 10.
Returns:
dict: A dictionary containing the list of agents, total count, current page number, page size, and total number of pages.
"""
try:
# Calculate pagination
skip = (page - 1) * page_size
# Execute the query
try:
# Agents with no downloads will not be included in the results... is this the desired behavior?
analytics = await prisma.models.AnalyticsTracker.prisma().find_many(
include={"agent": True},
order={"downloads": "desc"},
skip=skip,
take=page_size,
)
except prisma.errors.PrismaError as e:
raise AgentQueryError(f"Database query failed: {str(e)}")
# Get total count for pagination info
total_count = len(analytics)
return {
# should this be analytics as the top object?
"agents": [agent.agent for agent in analytics],
"total_count": total_count,
"page": page,
"page_size": page_size,
"total_pages": (total_count + page_size - 1) // page_size, # floor division
}
except AgentQueryError as e:
# Log the error or handle it as needed
raise e from e
except ValueError as e:
raise AgentQueryError(f"Invalid input parameter: {str(e)}") from e
except Exception as e:
# Catch any other unexpected exceptions
raise AgentQueryError(f"Unexpected error occurred: {str(e)}") from e

View File

@@ -128,7 +128,7 @@ async def get_agent_details_endpoint(
@router.get("/agents/{agent_id}/download")
async def download_agent(
background_tasks: fastapi.BackgroundTasks,
background_tasks: fastapi.BackgroundTasks,
agent_id: str = fastapi.Path(..., description="The ID of the agent to retrieve"),
version: typing.Optional[int] = fastapi.Query(
None, description="Specific version of the agent"
@@ -136,8 +136,8 @@ async def download_agent(
):
"""
Download details of a specific agent.
NOTE: This is the same as agent details, however it also triggers
NOTE: This is the same as agent details, however it also triggers
the "download" tracking. We don't actually want to download a file though
Args:
@@ -162,6 +162,7 @@ async def download_agent(
status_code=500, detail=f"An unexpected error occurred: {str(e)}"
)
@router.get("/agents/{agent_id}/download-file")
async def download_agent_file(
background_tasks: fastapi.BackgroundTasks,
@@ -200,3 +201,50 @@ async def download_agent_file(
return fastapi.responses.FileResponse(
tmp_file.name, filename=file_name, media_type="application/json"
)
# top agents by downloads
@router.get("/top-downloads/agents", response_model=market.model.AgentListResponse)
async def top_agents_by_downloads(
page: int = fastapi.Query(1, ge=1, description="Page number"),
page_size: int = fastapi.Query(
10, ge=1, le=100, description="Number of items per page"
),
):
"""
Retrieve a list of top agents based on the number of downloads.
Args:
page (int): Page number (default: 1).
page_size (int): Number of items per page (default: 10, min: 1, max: 100).
Returns:
market.model.AgentListResponse: A response containing the list of top agents and pagination information.
Raises:
HTTPException: If there is a client error (status code 400) or an unexpected error (status code 500).
"""
try:
result = await market.db.get_top_agents_by_downloads(
page=page,
page_size=page_size,
)
agents = [
market.model.AgentResponse(**agent.dict()) for agent in result["agents"]
]
return market.model.AgentListResponse(
agents=agents,
total_count=result["total_count"],
page=result["page"],
page_size=result["page_size"],
total_pages=result["total_pages"],
)
except market.db.AgentQueryError as e:
raise fastapi.HTTPException(status_code=400, detail=str(e)) from e
except Exception as e:
raise fastapi.HTTPException(
status_code=500, detail=f"An unexpected error occurred: {e}"
) from e