Skip to content

Commit

Permalink
feat(agents-api): Add docs routes
Browse files Browse the repository at this point in the history
Signed-off-by: Diwank Tomer <[email protected]>
  • Loading branch information
Diwank Tomer committed Aug 5, 2024
1 parent 160c76f commit c9c9a06
Show file tree
Hide file tree
Showing 17 changed files with 288 additions and 127 deletions.
27 changes: 4 additions & 23 deletions agents-api/agents_api/models/docs/delete_doc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from typing import Literal
from uuid import UUID

from beartype import beartype
Expand All @@ -13,7 +12,6 @@
partialclass,
rewrap_exceptions,
verify_developer_id_query,
verify_developer_owns_resource_query,
wrap_in_class,
)

Expand All @@ -39,30 +37,25 @@
def delete_doc(
*,
developer_id: UUID,
owner_type: Literal["user", "agent"],
owner_id: UUID,
doc_id: UUID,
) -> tuple[list[str], dict]:
"""Constructs and returns a datalog query for deleting documents and associated information snippets.
This function targets the 'cozodb' database, allowing for the removal of documents and their related information snippets based on the provided document ID and owner (user or agent).
Parameters:
owner_type (Literal["user", "agent"]): The type of the owner, either 'user' or 'agent'.
owner_id (UUID): The UUID of the owner.
doc_id (UUID): The UUID of the document to be deleted.
client (CozoClient): An instance of the CozoClient to execute the query.
Returns:
pd.DataFrame: The result of the executed datalog query.
"""
# Convert UUID parameters to string format for use in the datalog query
owner_id = str(owner_id)
doc_id = str(doc_id)

# The following query is divided into two main parts:
# 1. Deleting information snippets associated with the document
# 2. Deleting the document itself from the owner's collection
# 2. Deleting the document itself
delete_snippets_query = """
# This section constructs the subquery for identifying and deleting all information snippets associated with the given document ID.
# Delete snippets
Expand All @@ -81,29 +74,17 @@ def delete_doc(
"""

delete_doc_query = """
# This section constructs the subquery for deleting the document from the specified owner's (user or agent) document collection.
# Delete the docs
?[doc_id, owner_id, owner_type] <- [[
to_uuid($doc_id),
to_uuid($owner_id),
$owner_type,
]]
?[doc_id] <- [[ to_uuid($doc_id) ]]
:delete docs {
doc_id,
owner_type,
owner_id,
}
:delete docs { doc_id }
:returning
"""

queries = [
verify_developer_id_query(developer_id),
verify_developer_owns_resource_query(
developer_id, f"{owner_type}s", **{f"{owner_type}_id": owner_id}
),
delete_snippets_query,
delete_doc_query,
]

return (queries, {"doc_id": doc_id, "owner_id": owner_id, "owner_type": owner_type})
return (queries, {"doc_id": doc_id})
8 changes: 1 addition & 7 deletions agents-api/agents_api/models/docs/get_doc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Module for retrieving document snippets from the CozoDB based on document IDs."""

from typing import Literal
from uuid import UUID

from beartype import beartype
Expand Down Expand Up @@ -38,14 +37,12 @@
def get_doc(
*,
developer_id: UUID,
owner_type: Literal["user", "agent"],
doc_id: UUID,
) -> tuple[list[str], dict]:
"""
Retrieves snippets of documents by their ID from the CozoDB.
Parameters:
owner_type (Literal["user", "agent"]): The type of the owner of the document.
doc_id (UUID): The unique identifier of the document.
client (CozoClient, optional): The CozoDB client instance. Defaults to a pre-configured client.
Expand All @@ -67,16 +64,13 @@ def get_doc(
snippet_data = [index, content]
?[
owner_type,
id,
title,
snippet_data,
created_at,
metadata,
] := input[id],
owner_type = $owner_type,
*docs {
owner_type,
doc_id: id,
title,
created_at,
Expand All @@ -90,4 +84,4 @@ def get_doc(
get_query,
]

return (queries, {"doc_id": doc_id, "owner_type": owner_type})
return (queries, {"doc_id": doc_id})
8 changes: 8 additions & 0 deletions agents-api/agents_api/routers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@
Each sub-module defines its own set of API endpoints and is responsible for handling requests and responses related to its domain, ensuring a modular and organized approach to API development.
"""

# ruff: noqa: F401

from .agents import router as agents_router
from .docs import router as docs_router
from .jobs import router as jobs_router
from .sessions import router as sessions_router
from .users import router as users_router
6 changes: 6 additions & 0 deletions agents-api/agents_api/routers/docs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ruff: noqa: F401
from .create_doc import create_agent_doc, create_user_doc
from .delete_doc import delete_doc
from .get_doc import get_doc
from .list_docs import list_agent_docs, list_user_docs
from .router import router
42 changes: 42 additions & 0 deletions agents-api/agents_api/routers/docs/create_doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import Annotated

from fastapi import Depends
from pydantic import UUID4
from starlette.status import HTTP_201_CREATED

from ...autogen.openapi_model import CreateDocRequest, ResourceCreatedResponse
from ...dependencies.developer_id import get_developer_id
from ...models.docs.create_doc import create_doc as create_doc_query
from .router import router


@router.post("/users/{user_id}/docs", status_code=HTTP_201_CREATED, tags=["docs"])
async def create_user_doc(
user_id: UUID4,
data: CreateDocRequest,
x_developer_id: Annotated[UUID4, Depends(get_developer_id)],
) -> ResourceCreatedResponse:
doc = create_doc_query(
developer_id=x_developer_id,
owner_type="user",
owner_id=user_id,
data=data,
)

return ResourceCreatedResponse(id=doc.id, created_at=doc.created_at)


@router.post("/agents/{agent_id}/docs", status_code=HTTP_201_CREATED, tags=["docs"])
async def create_agent_doc(
agent_id: UUID4,
data: CreateDocRequest,
x_developer_id: Annotated[UUID4, Depends(get_developer_id)],
) -> ResourceCreatedResponse:
doc = create_doc_query(
developer_id=x_developer_id,
owner_type="agent",
owner_id=agent_id,
data=data,
)

return ResourceCreatedResponse(id=doc.id, created_at=doc.created_at)
17 changes: 17 additions & 0 deletions agents-api/agents_api/routers/docs/delete_doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Annotated

from fastapi import Depends
from pydantic import UUID4
from starlette.status import HTTP_202_ACCEPTED

from ...autogen.openapi_model import ResourceDeletedResponse
from ...dependencies.developer_id import get_developer_id
from ...models.docs.delete_doc import delete_doc as delete_doc_query
from .router import router


@router.delete("/docs/{doc_id}", status_code=HTTP_202_ACCEPTED, tags=["docs"])
async def delete_doc(
doc_id: UUID4, x_developer_id: Annotated[UUID4, Depends(get_developer_id)]
) -> ResourceDeletedResponse:
return delete_doc_query(developer_id=x_developer_id, doc_id=doc_id)
17 changes: 17 additions & 0 deletions agents-api/agents_api/routers/docs/get_doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Annotated

from fastapi import Depends
from pydantic import UUID4

from ...autogen.openapi_model import Doc
from ...dependencies.developer_id import get_developer_id
from ...models.docs.get_doc import get_doc as get_doc_query
from .router import router


@router.get("/docs/{doc_id}", tags=["docs"])
async def get_doc(
x_developer_id: Annotated[UUID4, Depends(get_developer_id)],
doc_id: UUID4,
) -> Doc:
return get_doc_query(developer_id=x_developer_id, doc_id=doc_id)
75 changes: 75 additions & 0 deletions agents-api/agents_api/routers/docs/list_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import json
from json import JSONDecodeError
from typing import Annotated, Literal

from fastapi import Depends, HTTPException, status
from pydantic import UUID4

from ...autogen.openapi_model import Doc, ListResponse
from ...dependencies.developer_id import get_developer_id
from ...models.docs.list_docs import list_docs as list_docs_query
from .router import router


@router.get("/users/{user_id}/docs", tags=["docs"])
async def list_user_docs(
x_developer_id: Annotated[UUID4, Depends(get_developer_id)],
user_id: UUID4,
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Doc]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

docs = list_docs_query(
developer_id=x_developer_id,
owner_type="user",
owner_id=user_id,
limit=limit,
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
)

return ListResponse[Doc](items=docs)


@router.get("/agents/{agent_id}/docs", tags=["docs"])
async def list_agent_docs(
x_developer_id: Annotated[UUID4, Depends(get_developer_id)],
agent_id: UUID4,
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Doc]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

docs = list_docs_query(
developer_id=x_developer_id,
owner_type="agent",
owner_id=agent_id,
limit=limit,
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
)

return ListResponse[Doc](items=docs)
3 changes: 3 additions & 0 deletions agents-api/agents_api/routers/docs/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from fastapi import APIRouter

router = APIRouter()
1 change: 1 addition & 0 deletions agents-api/agents_api/routers/sessions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .create_session import create_session
from .delete_session import delete_session
from .get_session import get_session
from .get_session_history import get_session_history
from .list_sessions import list_sessions
from .patch_session import patch_session
from .router import router
Expand Down
16 changes: 16 additions & 0 deletions agents-api/agents_api/routers/sessions/get_session_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Annotated

from fastapi import Depends
from pydantic import UUID4

from ...autogen.openapi_model import Session
from ...dependencies.developer_id import get_developer_id
from ...models.entry.get_history import get_history as get_history_query
from .router import router


@router.get("/sessions/{session_id}/history", tags=["sessions"])
async def get_session_history(
session_id: UUID4, x_developer_id: Annotated[UUID4, Depends(get_developer_id)]
) -> Session:
return get_history_query(developer_id=x_developer_id, session_id=session_id)
Loading

0 comments on commit c9c9a06

Please sign in to comment.