Skip to content

Commit

Permalink
Merge pull request #7 from yangwu1227/update-schema
Browse files Browse the repository at this point in the history
Update schema
  • Loading branch information
yangwu1227 authored Sep 17, 2024
2 parents 7c6f418 + fe0e3f4 commit b8c0f1c
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 59 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ This project creates an asynchronous RESTful API built with Python, FastAPI, and
```

The payload also supports two additional optional parameters:
- `summarizer_specifier`: Specifies the summarization algorithm. Supported values are `lsa`, `lex_rank`, `text_rank`, and `edmundson`. If not provided, the default is `lsa`.
- `summarization_method`: Specifies the summarization algorithm. Supported values are `lsa`, `lex_rank`, `text_rank`, and `edmundson`. If not provided, the default is `lsa`.
- `sentence_count`: Specifies the number of sentences in the generated summary, with a range of 5 to 30. If not provided, the default is 10.

Example request with all parameters:

```bash
curl -X POST "https://text-summarizer-d918be4fb9c8.herokuapp.com/summaries/" \
-H "Content-Type: application/json" \
-d '{"url": "https://realpython.com/pointers-in-python/", "summarizer_specifier": "lex_rank", "sentence_count": 15}'
-d '{"url": "https://realpython.com/pointers-in-python/", "summarization_method": "lex_rank", "sentence_count": 15}'
```

For more information on the supported summarization algorithms, see the [sumy documentation](https://github.com/miso-belica/sumy/blob/main/docs/summarizators.md).
Expand Down
7 changes: 6 additions & 1 deletion project/app/api/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ async def post(payload: SummaryPayloadSchema) -> int:
int
The ID of the newly created summary.
"""
summary = TextSummary(url=payload.url, summary="")
summary = TextSummary(
url=payload.url,
summary="",
summarization_method=payload.summarization_method,
sentence_count=payload.sentence_count,
)
# Create/update the model object
await summary.save()
# Return the key
Expand Down
34 changes: 17 additions & 17 deletions project/app/api/summaries.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Annotated, Dict, List
from typing import Annotated, List

from fastapi import APIRouter, BackgroundTasks, Path

Expand All @@ -9,7 +9,7 @@
SummaryResponseSchema,
SummaryUpdatePayloadSchema,
)
from app.models.tortoise import SummarySchema
from app.models.tortoise import TextSummarySchema
from app.summarizer import generate_summary

router = APIRouter()
Expand All @@ -32,28 +32,28 @@ async def create_summary(
Returns
-------
SummaryResponseSchema
The newly created summary's response, including the `url`, `id`, `summarizer_specifier`, and `sentence_count`.
The newly created summary's response, including the `url`, `id`, `summarization_method`, and `sentence_count`.
"""
summary_id = await crud.post(payload)
# Generate summary as a background task
background_tasks.add_task(
generate_summary,
summary_id,
str(payload.url),
payload.summarizer_specifier,
payload.summarization_method,
int(payload.sentence_count),
)
response = SummaryResponseSchema(
url=payload.url,
id=summary_id,
summarizer_specifier=payload.summarizer_specifier,
summarization_method=payload.summarization_method,
sentence_count=payload.sentence_count,
)
return response


@router.get("/{id}/", response_model=SummarySchema)
async def read_summary(id: Annotated[int, Path(title="The ID of the text summary to query", gt=0)]) -> SummarySchema: # type: ignore
@router.get("/{id}/", response_model=TextSummarySchema)
async def read_summary(id: Annotated[int, Path(title="The ID of the text summary to query", gt=0)]) -> TextSummarySchema: # type: ignore
"""
Retrieve a single summary based on its ID (i.e., primary key).
Expand All @@ -64,7 +64,7 @@ async def read_summary(id: Annotated[int, Path(title="The ID of the text summary
Returns
-------
SummarySchema
TextSummarySchema
The retrieved summary object.
Raises
Expand All @@ -79,23 +79,23 @@ async def read_summary(id: Annotated[int, Path(title="The ID of the text summary
return summary


@router.get("/", response_model=List[SummarySchema]) # type: ignore
async def read_all_summaries() -> List[SummarySchema]: # type: ignore
@router.get("/", response_model=List[TextSummarySchema]) # type: ignore
async def read_all_summaries() -> List[TextSummarySchema]: # type: ignore
"""
Retrieve all summaries.
Returns
-------
List[SummarySchema]
List[TextSummarySchema]
A list of all the summaries.
"""
return await crud.get_all()


@router.delete("/{id}/", response_model=SummarySchema)
@router.delete("/{id}/", response_model=TextSummarySchema)
async def remove_summary(
id: Annotated[int, Path(title="The ID of the text summary to delete", gt=0)]
) -> SummarySchema: # type: ignore
) -> TextSummarySchema: # type: ignore
"""
Delete a single summary based on its ID (i.e., primary key).
Expand All @@ -106,7 +106,7 @@ async def remove_summary(
Returns
-------
SummarySchema
TextSummarySchema
The retrieved summary response containing an ID and url.
Raises
Expand All @@ -124,11 +124,11 @@ async def remove_summary(
return summary


@router.put("/{id}/", response_model=SummarySchema)
@router.put("/{id}/", response_model=TextSummarySchema)
async def update_summary(
id: Annotated[int, Path(title="The ID of the text summary to update", gt=0)],
payload: SummaryUpdatePayloadSchema,
) -> SummarySchema: # type:ignore
) -> TextSummarySchema: # type:ignore
"""
Update a text summary by its ID. Both the URL and the summary text are updated based on the provided payload.
Expand All @@ -141,7 +141,7 @@ async def update_summary(
Returns
-------
SummarySchema
TextSummarySchema
The updated summary object if the update is successful.
Raises
Expand Down
8 changes: 4 additions & 4 deletions project/app/models/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pydantic import AnyHttpUrl, BaseModel, Field


class SummarizerSpecifier(str, Enum):
class SummarizationMethod(str, Enum):
"""
Enum representing available summarizer options.
Expand All @@ -30,14 +30,14 @@ class SummaryPayloadSchema(BaseModel):
url : AnyHttpUrl
The URL of the text for which a summary will be generated. This must be a
valid HTTP or HTTPS URL.
summarizer_specifier : str
summarization_method : str
The name of the summarizer to be used for generating the summary.
sentence_count : Optional[int]
The number of sentences to include in the summary. This field is optional.
"""

url: AnyHttpUrl
summarizer_specifier: SummarizerSpecifier = SummarizerSpecifier.lsa
summarization_method: SummarizationMethod = SummarizationMethod.lsa
sentence_count: int = Field(default=10, ge=5, le=30)


Expand All @@ -58,7 +58,7 @@ class SummaryResponseSchema(SummaryPayloadSchema):
url : AnyHttpUrl
The URL of the text for which a summary will be generated. This must be a
valid HTTP or HTTPS URL.
summarizer_specifier : str
summarization_method : str
The name of the summarizer to be used for generating the summary.
sentence_count : Optional[int]
The number of sentences to include in the summary. This field is optional.
Expand Down
5 changes: 4 additions & 1 deletion project/app/models/tortoise.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class TextSummary(Model):
id = fields.IntField(primary_key=True)
url = fields.TextField()
summary = fields.TextField()
# Allow null to handle existing records before these were added to the schema
summarization_method = fields.TextField(null=True)
sentence_count = fields.IntField(null=True)
# Automatically set the field to now when the object is first created
created_at = fields.DatetimeField(auto_now_add=True)

Expand All @@ -49,4 +52,4 @@ def __str__(self) -> str:
in a FastAPI application. It ensures that the fields from the Tortoise ORM model are properly
validated when used within API endpoints.
"""
SummarySchema = pydantic_model_creator(TextSummary)
TextSummarySchema = pydantic_model_creator(TextSummary)
8 changes: 4 additions & 4 deletions project/app/summarizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from sumy.summarizers.text_rank import TextRankSummarizer
from sumy.utils import get_stop_words

from app.models.pydantic import SummarizerSpecifier
from app.models.pydantic import SummarizationMethod
from app.models.tortoise import TextSummary

LANGUAGE = "english"
Expand All @@ -23,7 +23,7 @@


async def generate_summary(
id: int, url: str, summarizer_specifier: SummarizerSpecifier, sentence_count: int
id: int, url: str, summarization_method: SummarizationMethod, sentence_count: int
) -> None:
"""
Create a summary of an article from a given URL using the `sumy` package. The summarization methods available include:
Expand All @@ -38,7 +38,7 @@ async def generate_summary(
The generated id for this summary record.
url : str
The URL of the article to summarize.
summarizer_specifier : SummarizerSpecifier
summarization_method : SummarizationMethod
The summarization algorithm to use.
sentence_count : int
The number of sentences in the summary.
Expand All @@ -55,7 +55,7 @@ async def generate_summary(

try:
# Note that this is an enum instance
summarizer_name = summarizer_specifier.value
summarizer_name = summarization_method.value
# Parse content from the provided URL
parser = HtmlParser.from_url(url, Tokenizer(LANGUAGE))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from tortoise import BaseDBAsyncClient


async def upgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE "textsummary" ADD "summarization_method" TEXT;
ALTER TABLE "textsummary" ADD "sentence_count" INT;"""


async def downgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE "textsummary" DROP COLUMN "summarization_method";
ALTER TABLE "textsummary" DROP COLUMN "sentence_count";"""
Loading

0 comments on commit b8c0f1c

Please sign in to comment.