From 14c5164c41a1ef6a8edf067ceb7abf1acc5e28c8 Mon Sep 17 00:00:00 2001 From: yuhalog Date: Tue, 17 Jun 2025 14:05:21 +0900 Subject: [PATCH] feat: Marketing Tip Summary --- .../services/marketing_tip_service.py | 11 +- .../service/MarketingTipService.java | 160 +++++++++++++++++- 2 files changed, 157 insertions(+), 14 deletions(-) diff --git a/smarketing-ai/services/marketing_tip_service.py b/smarketing-ai/services/marketing_tip_service.py index 956eaf7..deceb3c 100644 --- a/smarketing-ai/services/marketing_tip_service.py +++ b/smarketing-ai/services/marketing_tip_service.py @@ -102,7 +102,7 @@ class MarketingTipService: 당신의 임무는 매장 정보를 바탕으로, 적은 비용으로 효과를 낼 수 있는 현실적이고 실행 가능한 마케팅 팁을 제안하는 것입니다. 지역성, 지역의 현재 날씨 확인하고, 현재 트렌드까지 고려해주세요. 소상공인을 위한 현실적이고 바로 실행할 수 있는 실용적인 마케팅 팁을 생성해주세요. -협업보다는 할인, 포스팅 등 당장 실현 가능한 현실적인 방법을 추천해주세요. +협업보다는 할인, 포스팅 등 당장 실현 가능한 현실적이면서도 창의적인 방법을 추천해주세요. 매장 정보: - 매장명: {store_name} @@ -130,9 +130,7 @@ class MarketingTipService: 4. **시의성**: 현재 계절, 유행, 트렌드를 반영 5. **지역성**: 지역 특성 및 현재 날씨를 고려할 것 -응답 형식 (300자 내외, 간결하게): -html 형식으로 출력 - +출력해야할 내용: - 핵심 마케팅 팁 (1개) - 실행 방법 (1개) - 예상 비용과 기대 효과 @@ -140,7 +138,8 @@ html 형식으로 출력 - 참고했던 실제 성공한 마케팅 - 오늘의 응원의 문장 (간결하게 1개) -아래 형식대로 그대로 출력해주세요! +아래 HTML 템플릿 형식으로 응답해주세요.

태그는 절대 변경하지 말고,

태그 내용만 새로 작성해주세요 +

태그 내용 외에 다른 내용은 절대 넣지 마세요 :

✨ 핵심 마케팅 팁

[여기에 새로운 핵심 마케팅 팁 작성]

@@ -155,7 +154,7 @@ html 형식으로 출력

[여기에 새로운 주의사항 내용 작성]

📈 참고했던 실제 성공한 마케팅

-

[여기에 새로운 참고 사례 내용 작성]

+

[여기에 새로운 참고 사례 내용 작성, 존재하지 않는 사례는 절대 참고하지 말고, 실제 존재하는 마케팅 성공 사례로만 작성. 참고했던 존재하는 url로 함께 표기]

🙌 오늘의 응원의 문장

[여기에 응원의 문장 작성]

diff --git a/smarketing-java/ai-recommend/src/main/java/com/won/smarketing/recommend/application/service/MarketingTipService.java b/smarketing-java/ai-recommend/src/main/java/com/won/smarketing/recommend/application/service/MarketingTipService.java index a960a0a..ee19059 100644 --- a/smarketing-java/ai-recommend/src/main/java/com/won/smarketing/recommend/application/service/MarketingTipService.java +++ b/smarketing-java/ai-recommend/src/main/java/com/won/smarketing/recommend/application/service/MarketingTipService.java @@ -142,23 +142,167 @@ public class MarketingTipService implements MarketingTipUseCase { } /** - * 마케팅 팁 요약 생성 (첫 50자 또는 첫 번째 문장) + * 마케팅 팁 요약 생성 (핵심 마케팅 팁 섹션에서 첫 번째 문장 추출) + * + * @param fullContent AI로 생성된 전체 마케팅 팁 HTML 콘텐츠 + * @return 핵심 마케팅 팁의 첫 번째 문장 */ private String generateTipSummary(String fullContent) { if (fullContent == null || fullContent.trim().isEmpty()) { return "마케팅 팁이 생성되었습니다."; } - // 첫 번째 문장으로 요약 (마침표 기준) - String[] sentences = fullContent.split("[.!?]"); - String firstSentence = sentences.length > 0 ? sentences[0].trim() : fullContent; + try { + // 1. "✨ 핵심 마케팅 팁" 섹션 추출 + String coreSection = extractCoreMarketingTipSection(fullContent); - // 50자 제한 - if (firstSentence.length() > 50) { - return firstSentence.substring(0, 47) + "..."; + if (coreSection != null && !coreSection.trim().isEmpty()) { + // 2. HTML 태그 제거 + String cleanText = removeHtmlTags(coreSection); + + // 3. 첫 번째 의미있는 문장 추출 + String summary = extractFirstMeaningfulSentence(cleanText); + + // 4. 길이 제한 (100자 이내) + if (summary.length() > 100) { + summary = summary.substring(0, 97) + "..."; + } + + return summary; + } + + // 핵심 팁 섹션을 찾지 못한 경우 fallback 처리 + return extractFallbackSummary(fullContent); + + } catch (Exception e) { + log.warn("마케팅 팁 요약 생성 중 오류 발생, 기본 메시지 반환: {}", e.getMessage()); + return "맞춤형 마케팅 팁이 생성되었습니다."; + } + } + + /** + * "✨ 핵심 마케팅 팁" 섹션 추출 + */ + private String extractCoreMarketingTipSection(String fullContent) { + // 핵심 마케팅 팁 섹션 시작 패턴들 + String[] corePatterns = { + "✨ 핵심 마케팅 팁", + "

✨ 핵심 마케팅 팁

", + "핵심 마케팅 팁" + }; + + // 다음 섹션 시작 패턴들 + String[] nextSectionPatterns = { + "🚀 실행 방법", + "

🚀 실행 방법

", + "💰 예상 비용", + "

💰 예상 비용" + }; + + for (String pattern : corePatterns) { + int startIndex = fullContent.indexOf(pattern); + if (startIndex != -1) { + // 패턴 뒤부터 시작 + int contentStart = startIndex + pattern.length(); + + // 다음 섹션까지의 내용 추출 + int endIndex = fullContent.length(); + for (String nextPattern : nextSectionPatterns) { + int nextIndex = fullContent.indexOf(nextPattern, contentStart); + if (nextIndex != -1 && nextIndex < endIndex) { + endIndex = nextIndex; + } + } + + return fullContent.substring(contentStart, endIndex).trim(); + } } - return firstSentence; + return null; + } + + /** + * HTML 태그 제거 + */ + private String removeHtmlTags(String htmlText) { + if (htmlText == null) return ""; + + return htmlText + .replaceAll("<[^>]+>", "") // HTML 태그 제거 + .replaceAll(" ", " ") // HTML 엔티티 처리 + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll("&", "&") + .replaceAll("\\s+", " ") // 연속된 공백을 하나로 + .trim(); + } + + /** + * 첫 번째 의미있는 문장 추출 + */ + private String extractFirstMeaningfulSentence(String cleanText) { + if (cleanText == null || cleanText.trim().isEmpty()) { + return "마케팅 팁이 생성되었습니다."; + } + + // 문장 분할 (마침표, 느낌표, 물음표 기준) + String[] sentences = cleanText.split("[.!?]"); + + for (String sentence : sentences) { + String trimmed = sentence.trim(); + + // 의미있는 문장인지 확인 (10자 이상, 특수문자만으로 구성되지 않음) + if (trimmed.length() >= 10 && + !trimmed.matches("^[\\s\\p{Punct}]*$") && // 공백과 구두점만으로 구성되지 않음 + !isOnlyEmojisOrSymbols(trimmed)) { // 이모지나 기호만으로 구성되지 않음 + + // 문장 끝에 마침표 추가 (없는 경우) + if (!trimmed.endsWith(".") && !trimmed.endsWith("!") && !trimmed.endsWith("?")) { + trimmed += "."; + } + + return trimmed; + } + } + + // 의미있는 문장을 찾지 못한 경우 원본의 처음 50자 반환 + if (cleanText.length() > 50) { + return cleanText.substring(0, 47) + "..."; + } + + return cleanText; + } + + /** + * 이모지나 기호만으로 구성되었는지 확인 + */ + private boolean isOnlyEmojisOrSymbols(String text) { + // 한글, 영문, 숫자가 포함되어 있으면 의미있는 텍스트로 판단 + return !text.matches(".*[\\p{L}\\p{N}].*"); + } + + /** + * 핵심 팁 섹션을 찾지 못한 경우 대체 요약 생성 + */ + private String extractFallbackSummary(String fullContent) { + // HTML 태그 제거 후 첫 번째 의미있는 문장 찾기 + String cleanContent = removeHtmlTags(fullContent); + + // 첫 번째 문단에서 의미있는 문장 추출 + String[] paragraphs = cleanContent.split("\\n\\n"); + + for (String paragraph : paragraphs) { + String trimmed = paragraph.trim(); + if (trimmed.length() >= 20) { // 충분히 긴 문단 + String summary = extractFirstMeaningfulSentence(trimmed); + if (summary.length() >= 10) { + return summary; + } + } + } + + // 모든 방법이 실패한 경우 기본 메시지 + return "개인화된 마케팅 팁이 생성되었습니다."; } /**