mirror of
https://github.com/won-ktds/smarketing-backend.git
synced 2025-12-06 07:06:24 +00:00
feat: Marketing Tip Summary
This commit is contained in:
parent
f9a5007cfd
commit
14c5164c41
@ -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 템플릿 형식으로 응답해주세요. <h3> 태그는 절대 변경하지 말고, <p> 태그 내용만 새로 작성해주세요
|
||||
<p> 태그 내용 외에 다른 내용은 절대 넣지 마세요 :
|
||||
|
||||
<h3>✨ 핵심 마케팅 팁</h3>
|
||||
<p>[여기에 새로운 핵심 마케팅 팁 작성]</p>
|
||||
@ -155,7 +154,7 @@ html 형식으로 출력
|
||||
<p>[여기에 새로운 주의사항 내용 작성]</p>
|
||||
|
||||
<h3>📈 참고했던 실제 성공한 마케팅</h3>
|
||||
<p>[여기에 새로운 참고 사례 내용 작성]</p>
|
||||
<p>[여기에 새로운 참고 사례 내용 작성, 존재하지 않는 사례는 절대 참고하지 말고, 실제 존재하는 마케팅 성공 사례로만 작성. 참고했던 존재하는 url로 함께 표기]</p>
|
||||
|
||||
<h3>🙌 오늘의 응원의 문장</h3>
|
||||
<p>[여기에 응원의 문장 작성]</p>
|
||||
|
||||
@ -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 = {
|
||||
"✨ 핵심 마케팅 팁",
|
||||
"<h3>✨ 핵심 마케팅 팁</h3>",
|
||||
"핵심 마케팅 팁"
|
||||
};
|
||||
|
||||
// 다음 섹션 시작 패턴들
|
||||
String[] nextSectionPatterns = {
|
||||
"🚀 실행 방법",
|
||||
"<h3>🚀 실행 방법</h3>",
|
||||
"💰 예상 비용",
|
||||
"<h3>💰 예상 비용"
|
||||
};
|
||||
|
||||
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 "개인화된 마케팅 팁이 생성되었습니다.";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user