From aaf9c18292a0194cccfe22e9bddd1feefc75ce2d Mon Sep 17 00:00:00 2001 From: sunny Date: Sun, 13 Jul 2025 00:01:19 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20Colab=20=EC=BD=94=EB=93=9C=EB=A5=BC?= =?UTF-8?q?=20FastAPI=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0(app/,=20se?= =?UTF-8?q?rvices/,=20models/)=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 1 + app/api/news_transform.py | 36 +++++++++++++++++++++++++++++++ app/main.py | 5 +++++ app/models/news.py | 24 +++++++++++++++++++++ app/services/difficulty_filter.py | 8 +++++++ app/services/summarizer.py | 14 ++++++++++++ 6 files changed, 88 insertions(+) create mode 100644 app/api/news_transform.py create mode 100644 app/models/news.py diff --git a/.env.example b/.env.example index e69de29..d426827 100644 --- a/.env.example +++ b/.env.example @@ -0,0 +1 @@ +NGROK_AUTH_TOKEN=your_ngrok_token_here \ No newline at end of file diff --git a/app/api/news_transform.py b/app/api/news_transform.py new file mode 100644 index 0000000..75497e0 --- /dev/null +++ b/app/api/news_transform.py @@ -0,0 +1,36 @@ +from fastapi import APIRouter +from app.models.news import NewsTransferRequest, NewsTransferResponse, DifficultWord, NewsTransferResult +from app.services.summarizer import build_transform_prompt, build_summary_prompt, generate_content +from app.services.difficulty_filter import build_difficult_word_prompt +from typing import List + +router = APIRouter() + +@router.post("/transfer", response_model=NewsTransferResponse) +async def transform_news(request: NewsTransferRequest): + transform_prompt = build_transform_prompt(request.title, request.originalContent, request.level) + summary_prompt = build_summary_prompt(request.title, request.originalContent) + word_prompt = build_difficult_word_prompt(request.originalContent, request.level) + + transformed_content = generate_content(transform_prompt) + summary = generate_content(summary_prompt) + difficult_words_raw = generate_content(word_prompt) + + difficult_words = [] + for line in difficult_words_raw.splitlines(): + if ":" in line: + term, description = line.split(":", 1) + difficult_words.append(DifficultWord(term=term.strip(), description=description.strip())) + + return NewsTransferResponse( + code="NEWS200", + message="난이도별 뉴스 변환 및 단어 추출 성공", + result=NewsTransferResult( + level=request.level, + title=request.title, + transformedContent=transformed_content, + summarized=summary, + difficultWords=difficult_words + ), + success=True + ) \ No newline at end of file diff --git a/app/main.py b/app/main.py index e69de29..723b2b8 100644 --- a/app/main.py +++ b/app/main.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI +from app.api.v1.news_transform import router + +app = FastAPI() +app.include_router(router, prefix="/api/news") \ No newline at end of file diff --git a/app/models/news.py b/app/models/news.py new file mode 100644 index 0000000..60bd028 --- /dev/null +++ b/app/models/news.py @@ -0,0 +1,24 @@ +from pydantic import BaseModel +from typing import List + +class NewsTransferRequest(BaseModel): + title: str + originalContent: str + level: str + +class DifficultWord(BaseModel): + term: str + description: str + +class NewsTransferResult(BaseModel): + level: str + title: str + transformedContent: str + summarized: str + difficultWords: List[DifficultWord] + +class NewsTransferResponse(BaseModel): + code: str + message: str + result: NewsTransferResult + success: bool \ No newline at end of file diff --git a/app/services/difficulty_filter.py b/app/services/difficulty_filter.py index e69de29..f20cddf 100644 --- a/app/services/difficulty_filter.py +++ b/app/services/difficulty_filter.py @@ -0,0 +1,8 @@ +def build_difficult_word_prompt(content: str, level: str) -> str: + if level == "상": + instruction = "다음 뉴스 본문에서 성인이 어려워할 수 있는 단어 3~5개를 골라줘. 각 단어의 뜻을 전문적으로 설명해줘." + elif level == "중": + instruction = "다음 뉴스 본문에서 중학생이 어려워할 수 있는 단어 5~10개를 골라줘. 각 단어의 뜻을 중학생 눈높이에 맞게 설명해줘." + else: + instruction = "다음 뉴스 본문에서 초등학생이 어려워할 수 있는 단어 5~10개를 골라줘. 각 단어의 뜻을 아주 쉽게 설명해줘." + return f"{instruction}\n\n뉴스 본문:\n{content}" \ No newline at end of file diff --git a/app/services/summarizer.py b/app/services/summarizer.py index e69de29..56b6dc4 100644 --- a/app/services/summarizer.py +++ b/app/services/summarizer.py @@ -0,0 +1,14 @@ +# 비즈니스 로직 / AI 추론 모듈 + +def build_transform_prompt(title: str, content: str, level: str) -> str: + base = f"다음 뉴스 제목과 본문을 사용자의 이해 수준에 맞게 다시 써줘.\n\n뉴스 제목: {title}\n뉴스 본문: {content}\n" + if level == "상": + instruction = "원문에 가깝게 유지해." + elif level == "중": + instruction = "간결하고 이해하기 쉬운 문장으로 재구성해줘. 핵심 내용만 유지해도 좋아." + else: + instruction = "초등학생도 이해할 수 있도록 아주 쉽게 설명해줘. 쉬운 단어와 짧은 문장을 써줘." + return base + "\n요청 사항: " + instruction + +def build_summary_prompt(title: str, content: str) -> str: + return f"다음 뉴스 제목과 본문을 한문장으로 간단히 요약해줘.\n\n뉴스 제목: {title}\n뉴스 본문: {content}"