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: 2 additions & 0 deletions api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from api.ai import ai_view
from api.ui import ui_router
from api.upload import media_view
from api.search import search_view
import uvicorn

api = FastAPI(
Expand All @@ -30,6 +31,7 @@ async def health_check():
api.include_router(assistant_view.assistant_router)
api.include_router(ai_view.ai_router)
api.include_router(media_view.media_router)
api.include_router(search_view.search_router)

if __name__ == "__main__":
uvicorn.run("api.app:api", host="127.0.0.1", port=8000, reload=True)
1 change: 1 addition & 0 deletions api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
CACHE_CONNECTION_STRING="your-redis-connection-string",
CACHE_PREFIX="agent_microservice:",
CACHE_ASSISTANT_TIMEOUT=3600,
EXTERNAL_PECHA_API_URL="your-external-pecha-api-url",
)

def get(key: str) -> str:
Expand Down
3 changes: 2 additions & 1 deletion api/constant.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class Constant:
CREATED_ASSISTANT_MESSAGE="Assistant created successfully"
IMAGE_UPLOAD_SUCCESS="Image uploaded successfully"
IMAGE_UPLOAD_SUCCESS="Image uploaded successfully"
INSTANCE_TYPE="critical"
21 changes: 21 additions & 0 deletions api/http_message_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from fastapi import HTTPException
import logging
import httpx

logger = logging.getLogger(__name__)


def handle_http_status_error(e: httpx.HTTPStatusError) -> None:
logger.error(f"External API error: {e.response.status_code} - {e.response.text}")
raise HTTPException(
status_code=e.response.status_code,
detail=f"External API error: {e.response.text}"
)


def handle_request_error(e: httpx.RequestError) -> None:
logger.error(f"Request to external API failed: {str(e)}")
raise HTTPException(
status_code=500,
detail="Failed to connect to the service. Please try again later."
)
7 changes: 7 additions & 0 deletions api/search/search_response_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pydantic import BaseModel

class SearchTextsDetailsResponse(BaseModel):
id: str
content: str
type: str
source: str
50 changes: 50 additions & 0 deletions api/search/search_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import httpx
from api.http_message_utils import handle_http_status_error, handle_request_error
from api.config import get
from api.constant import Constant
from api.search.search_response_model import SearchTextsDetailsResponse


client = httpx.AsyncClient(timeout=httpx.Timeout(30.0))

ACCEPT_JSON_HEADER = {"Accept": "application/json"}
EXTERNAL_PECHA_API_URL = get("EXTERNAL_PECHA_API_URL")

async def get_search_texts_details(text_id: str) -> list[SearchTextsDetailsResponse]:
instances = await call_external_pecha_api_instances(text_id)
if instances:
for instance in instances:
instance_id = instance.get("id")
if instance_id:
content = await call_external_pecha_api_instances_content(instance_id)
instance["content"] = content

return [SearchTextsDetailsResponse(**instance) for instance in instances]


async def call_external_pecha_api_instances(
text_id: str
) -> list[dict]:
endpoint = f"{EXTERNAL_PECHA_API_URL}/texts/{text_id}/instances?instance_type={Constant.INSTANCE_TYPE}"
try:
response = await client.get(endpoint, headers=ACCEPT_JSON_HEADER)
response.raise_for_status()
data = response.json()
return data if isinstance(data, list) else []

except httpx.HTTPStatusError as e:
handle_http_status_error(e)
except httpx.RequestError as e:
handle_request_error(e)

async def call_external_pecha_api_instances_content(instance_id: str) -> str:
endpoint = f"{EXTERNAL_PECHA_API_URL}/instances/{instance_id}?annotation=false&content=true"
try:
response = await client.get(endpoint, headers=ACCEPT_JSON_HEADER)
response.raise_for_status()
data = response.json()
return data.get("content", "")
except httpx.HTTPStatusError as e:
handle_http_status_error(e)
except httpx.RequestError as e:
handle_request_error(e)
20 changes: 20 additions & 0 deletions api/search/search_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from __future__ import annotations

from fastapi import APIRouter
from starlette import status
from api.search.search_service import get_search_texts_details
from api.search.search_response_model import SearchTextsDetailsResponse

search_router = APIRouter(
prefix="/search",
tags=["search"]
)


@search_router.get("/{text_id}", status_code=status.HTTP_200_OK, response_model=list[SearchTextsDetailsResponse])
async def read_texts_details(
text_id: str
)->list[SearchTextsDetailsResponse]:
return await get_search_texts_details(
text_id=text_id
)