diff --git a/.gitignore b/.gitignore index b7faf40..9568693 100644 --- a/.gitignore +++ b/.gitignore @@ -204,4 +204,4 @@ cython_debug/ # Marimo marimo/_static/ marimo/_lsp/ -__marimo__/ +__marimo__/ \ No newline at end of file diff --git a/app/models/fraud_response.py b/app/models/fraud_response.py index 4fb0ea3..027b107 100644 --- a/app/models/fraud_response.py +++ b/app/models/fraud_response.py @@ -5,4 +5,4 @@ class FraudResponse(BaseModel): estimatedFraudType: str # 분류된 사기 유형 keywords: List[str] = Field(..., min_items=1, max_items=3, description="주요 위험 키워드 (최대 3개)") explanation: str # 해당 유형으로 판단한 이유 - score: float = Field(..., ge=0, le=100, description="위험도(0~100)") \ No newline at end of file + score: float = Field(..., ge=0, le=70, description="위험도(0~70)") \ No newline at end of file diff --git a/app/prompts/data/fraud_examples.py b/app/prompts/data/fraud_examples.py index 7be5e4f..5a5362a 100644 --- a/app/prompts/data/fraud_examples.py +++ b/app/prompts/data/fraud_examples.py @@ -1,28 +1,407 @@ from typing import List -from app.prompts.fraud_prompts import FraudExample +from app.prompts.fraud_example import FraudExample -# 여기에 18개 유형 × 3~4개 예시만큼 리스트를 정의 FRAUD_EXAMPLES: List[FraudExample] = [ FraudExample( - type_name="피싱", - message_content="귀하의 계정이 잠길 수 있습니다. 비밀번호를 확인하려면 여기를 클릭하세요.", - additional_description="늦은 밤, 낯선 번호로 온 SMS를 우연히 열어보았습니다.", - keywords=["계정 잠금", "비밀번호 확인", "SMS 링크"], - image_content="은행알림 Bot: 당신의 계좌가 비정상적으로 활동되어 잠길 예정입니다. https://bit.ly/secure-link" + type_name="기관 사칭형", + message_content=[ + "[Web발신]\n[서울강북경찰서] 귀하의 사건\n[송치번호 : 2021-439857]호를\n서울북부지방검찰청으로 인계하였습니다.\n담당 검사가 지정되기까지 1~3일 소요될 수 있습니다.", + "서울중앙지방검찰청 민원실\n수신인:\n문서번호: 중앙-2023-XXXX\n귀하 명의의 계좌가 명의도용으로 사용되어\n금융감독원으로부터 신고 접수되었습니다.\n관련 서류는 등기 발송하였으나 반송되어 본 고지로 대체하며 신속히 연락 주시기 바랍니다.\n연락처: 010-XXXX-XXXX", + "[Web발신]\n[금융감독원] 고객님 명의 계좌에서\n수상한 거래 및 불법 송금 시도가 감지되었습니다.\n긴급 보안조치 및 신분 확인 바랍니다.\n확인링크: bit.ly/xxxx" + ], + additional_description=[ + "검찰로 사건이 송치되었다며 담당 검사 지정까지 대기하라는 문자 수신. 실제 경찰서 발신 여부 확인 필요해 의심됨.", + "명의도용 신고가 접수되었으며 문서번호와 연락처가 포함됨. 해당 번호가 기관과 다르고 신속 연락을 요구해 사기 가능성 높음.", + "수상한 거래 발생 안내와 함께 링크로 신분 확인을 유도. 링크가 수상하고 발신자 정보가 불분명해 의심됨." + ], + keywords=[ + "전화", + "수사기관", + "공공기관", + "개인정보", + "송금 요청", + "링크 클릭 요청", + "수상한 링크 포함", + "실제 기관/지인 연락처와 달랐다", + "무리한 정보 요청이 있었다", + "링크나 파일이 수상해 보였다", + "긴급하게 행동을 요구했다" + ] ), FraudExample( - type_name="투자 사기", - message_content="2주 만에 30% 수익 보장! 지금 투자하세요.", - additional_description="점심시간 카페에서 친구가 공유한 링크를 클릭했습니다.", - keywords=["30% 수익", "지금 투자", "보장된 수익"], - image_content="InvestPro: 한정 시간 30% 수익, 투자하기 ▶ http://invest.example.com" + type_name="대출 사기형", + message_content=[ + "[Web발신]\nKB국민은행 고객님께 안내드립니다.\n정부지원 서민금융상품 신청 대상자로 선정되셨습니다.\n\n【상품 특징】\n최대 1,500만원, 금리 2.3%~5.2%\n무직자 가능, 신용등급 무관, 무서류 진행, 중도상환 수수료 없음\n대환대출, 생활안정자금 지원 가능\n\n【신청 방법】\n상담원 연결 후 1번 누르시면 접수 완료!\n대표번호 02-1577-XXXX\n※ 접수자 많을 시 상담 지연될 수 있습니다.", + "[Web발신]\n안녕하세요, 현대캐피탈 박대리입니다.\n대출 진행을 위해 아래 서류 제출 바랍니다.\n\n신분증 사본\n등본, 초본\n재직증명서, 통장사본\n거래내역서 (주거래은행 3개월)\n※ 카카오톡으로 사진 전송 가능\n※ 아래 링크 통해 앱 설치 후 신청서 작성 부탁드립니다.\nhxxp://xxxxx.bank.top/신청앱.apk", + "고객님 대출 승인 완료되었습니다.\n대출금 수령을 위해 아래 파일을 다운로드 후 설치해주세요.\n압축 해제 시 상담신청 앱 실행됩니다.\n\nKB국민은행.zip (용량 7.9MB)\n※ 신청서 삭제 시 대출 자동취소될 수 있으니 반드시 유지 바랍니다.\n문의사항은 바로 메시지 주세요.\n당일 수령 가능하며 전자서명 완료 후 입금됩니다." + ], + keywords=[ + "전화", + "금융기관", + "송금 요청", + "개인정보 입력", + "링크 클릭 요청", + "앱 설치 / 파일 다운로드 유도", + "신분증", + "대출 이력", + "주민등록번호", + "무리한 정보 요청이 있었다", + "링크나 파일이 수상해 보였다", + "긴급하게 행동을 요구했다" + ], + additional_description=[ + "정부지원 대출 대상자로 선정되었다며 상담을 유도하는 문자 수신. 국민은행을 사칭하고 상담번호가 수상해 의심됨.", + "대출 진행을 위해 신분증 등 서류를 요구하고 apk 파일 설치를 유도하는 메시지. 링크가 수상하여 사기 의심됨.", + "대출 승인을 사칭하여 zip 파일 설치를 유도. 설치하지 않으면 대출이 취소된다고 하여 위기감을 조성함." + ] ), FraudExample( - type_name="복권 사기", - message_content="축하합니다! 당신은 1,000,000달러에 당첨되었습니다. 수수료를 지불하면 수령 가능합니다.", - additional_description="출근길 지하철에서 받은 이메일에 포함된 링크를 클릭했습니다.", - keywords=["당첨", "수수료", "이메일 링크"], - image_content="LotteryKingdom: Congratulations! You've won $1,000,000. Click here https://lotto.fake/claim" + type_name="카드사 사칭형", + message_content=[ + "[Web발신] KB국민카드 승인불가\n본인 미신청 시 02-XXX-XXXX로 문의 바랍니다.", + "[Web발신] 신한카드 개통완료.\n개통내용이 본인과 다를 경우 즉시 상담접수 바랍니다.", + "[Web발신] 현대카드에서 이상 거래가 감지되었습니다.\n본인 아닌 경우 1644-XXXX로 취소 요청 바랍니다." + ], + keywords=[ + "전화", + "금융기관", + "개인정보 입력", + "보안카드 번호", + "신분증", + "실제 기관/지인 연락처와 달랐다", + "무리한 정보 요청이 있었다", + "긴급하게 행동을 요구했다" + ], + additional_description=[ + "KB국민카드 승인불가 문자 수신. 본인이 신청하지 않았으면 전화하라는 내용으로 긴급히 대응을 유도함.", + "신한카드 개통완료라는 문자 수신. 본인과 다를 경우 상담 요청을 유도하여 개인정보 입력을 유도할 우려가 있었음.", + "현대카드 이상 거래 감지 문자 수신. 본인이 아닐 경우 즉시 취소 요청하라는 문구로 위기감을 조성하여 행동을 유도함." + ] ), - # … (총 60~70개 항목) -] + FraudExample( + type_name = "돌잔치 초대장형", + message_content = [ + "[Web발신] 저희 아들 첫돌 잔치에 초대합니다 모바일 초대장 oa.to/invite123", + "[Web발신] 축하해주세요~ 우리 아이 돌잔치 초대장이 도착했어요 vo.to/happybaby", + "아들 돌잔치 초대장 보내드렸습니다. 시간 되시면 꼭 참석해주세요! http://baby.partyapp.apk" + ], + keywords = [ + "문자", + "가족 / 친구 / 지인", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description = [ + "지인인 척 하며 아들 돌잔치 초대 문자를 보냈고, 생소한 링크 클릭을 유도. 돌잔치 초대장이 문자로 오는 게 이상해서 의심", + "축하해 달라는 내용과 함께 링크로 접속을 유도하는 메시지를 받음. 돌잔치라는 표현이 감성적으로 다가왔지만 링크 주소가 수상", + "시간 되면 참석해 달라며 파일이 포함된 초대장을 보냄" + ] + ), + FraudExample( + type_name="모바일 청첩장형", + message_content=[ + "[Web발신] 안녕하세요~ 저 결혼합니다\n사랑의 결실을 맺게 되어 모바일 청첩장 보내드립니다 han.gl/wedding2025", + "[Web발신] 청첩장이 도착했습니다.\nWedding Invitation c11.kr/loveyou\n참석해주시면 큰 기쁨이 될 거예요!", + "재혼을 결심하고 소중한 분들께 모바일 청접장을 보내드립니다\n청첩장 확인 http://mywedding.invite.apk" + ], + keywords=[ + "문자", + "가족 / 친구 / 지인", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description=[ + "지인처럼 결혼 소식을 전하며 모바일 청첩장을 보냈고, 단축 링크 클릭을 유도. 결혼 소식이 갑작스럽고 링크가 수상해 의심되었습니다.", + "Wedding Invitation이라는 제목으로 링크가 포함된 청첩장을 받았습니다. 정식 청첩장이 아닌 문자로 온 점이 이상해서 사기로 의심했습니다.", + "재혼 안내와 함께 .apk 파일이 포함된 청첩장 링크를 받았고, 설치를 유도하는 방식이라 매우 의심스러웠습니다." + ] + ), + FraudExample( + type_name="부고문자형", + message_content=[ + "[Web발신] 안타깝게도 부친께서 별세하셨습니다.\n부고 및 장례식장 안내 buly.kr/funeral123", + "[Web발신] 삼가 고인의 명복을 빕니다.\n○○○님 모친상 부고 안내드립니다. 빈소 위치 확인 gg.gg/빈소위치", + "[訃告] ○○○님의 아버님께서 소천하셨습니다.\n조문 오시는 길 iplogger.com/funeral" + ], + keywords=[ + "문자", + "가족 / 친구 / 지인", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description=[ + "부친 별세 소식과 함께 장례식장 안내라는 명목으로 링크 클릭을 유도하였고, 링크 도메인이 낯설어 의심되었습니다.", + "모친상 부고 문자를 받았는데, 단축 링크가 포함되어 있었고 감성적 표현으로 클릭을 유도하여 사기 가능성이 있다고 판단했습니다.", + "訃告라는 제목과 함께 조문 안내 링크가 왔지만 전혀 모르는 사람 이름과 수상한 링크 주소로 사기로 강하게 의심되었습니다." + ] + ), + FraudExample( + type_name="범칙금/과태료 부과형", + message_content=[ + "[Web발신] [도로교통공단] 정지선 위반으로 과태료가 부과되었습니다.\n자세한 고지서 확인 paso.mobilecar.pe.kr/warning", + "[Web발신] 민원24에서 쓰레기 무단투기에 대한 민원이 접수되었습니다.\n내용 확인 homes-go.com/violation", + "[Web발신] [관세청] 귀하의 통관번호에 수입세금 미납이 있어 고지서를 발송하였습니다.\n goosmsi.com/tax" + ], + keywords=[ + "문자", + "공공기관", + "링크 클릭 요청", + "개인정보 입력", + "수상한 링크 포함", + "링크나 파일이 수상해 보였다" + ], + additional_description=[ + "도로교통법 위반으로 과태료가 부과되었다며 고지서 확인을 유도하는 문자 수신. 발신기관 명칭은 있었지만 링크 주소가 낯설어 의심됨.", + "쓰레기 무단투기 민원 접수 안내와 함께 내용을 확인하라는 문자. 공식 사이트가 아닌 생소한 링크를 보내 사기로 의심됨.", + "관세청을 사칭하여 세금 미납 고지서를 링크로 확인하라는 문자 수신. 관세청 링크가 아니었고 사기 가능성이 높아보였음." + ] + ), + FraudExample( + type_name="건강보험공단 사칭형", + message_content=[ + "[Web발신] [국민건강보험공단] 종합건강검진 통지서가 발송되었습니다.\n dokdo.in/healthcheck", + "[Web발신] [건강지키미] 건강보험료 환급금 신청이 마감됩니다. 신청 요망 nhisis.xyz/refund", + "[Web발신] 보험료 미납으로 인해 건강검진 통보문이 반송되었습니다.\n확인바랍니다 cloud-check.kr/notice" + ], + keywords=[ + "문자", + "건강보험공단 / 의료기관", + "링크 클릭 요청", + "수상한 링크 포함", + "긴급하게 행동을 요구했다", + "링크나 파일이 수상해 보였다" + ], + additional_description=[ + "건강검진 통지서를 확인하라는 문자였고, 공단을 사칭하며 수상한 링크로 접속을 유도해 의심.", + "보험료 환급 신청 마감이라며 긴급하게 신청을 유도하고 이상한 링크를 보냄", + "보험료 미납으로 건강검진 통보문이 반송됐다며 확인을 요청하고 의심스러운 링크를 제공해 사기 같았음" + ] + ), + FraudExample( + type_name="경찰 출석 요구형", + message_content=[ + "[Web발신] [검찰청] 형사소송건과 관련하여 긴급출석요구가 발부되었습니다.\n사건번호: 13-093157 sc-police.co.kr/confirm", + "[Web발신] ○○○님께 형사소송 관련 출석요구서가 발송되었습니다. 즉시 확인 바랍니다.\n xuto.tk/doc", + "[Web발신] [법원] 귀하의 사건번호 경기13고단758에 대한 민사소송이 접수되었습니다.\n확인 is.gd/lawsuit" + ], + keywords=[ + "문자", + "수사기관", + "출석 / 소환 요구", + "개인정보 입력", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "긴급하게 행동을 요구했다", + "긴급성이나 위기감을 느끼게 하는 표현이 있었다" + ], + additional_description=[ + "검찰청에서 형사소송건 출석요구서를 발부했다며 사건번호와 수상한 링크를 보내와 사기 의심이 들었음.", + "형사소송 관련 문서를 확인하라며 링크를 통해 즉시 확인을 요구하여 긴급하고 위협적인 분위기였음.", + "법원에서 민사소송 접수 안내와 함께 링크를 보내왔고, 사건번호까지 있어 실제처럼 보였지만 의심스러웠음." + ] + ), + FraudExample( + type_name="국세청 사칭형", + message_content=[ + "[Web발신] [국세청] 종합소득세 환급 대상자입니다. 환급금 수령을 위해 신청하세요 han.gl/refund123", + "[Web발신] 홈택스 연말정산 환급금 내역 조회가 가능합니다. 확인 me2.do/taxcheck", + "[국민연금공단] 세금 미납 내역이 확인되어 납부 통지서가 발급되었습니다.\n goo.gl/notify123" + ], + keywords=[ + "문자", + "공공기관", + "금융기관", + "지원금 / 환급금 수령 유도", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description=[ + "국세청을 사칭하여 환급 대상임을 강조하고 링크를 클릭해 신청하라고 하여 사기 의심이 들었음.", + "홈택스 연말정산 환급금 조회가 가능하다며 링크를 보내왔고, 환급 유도 방식이 수상했음.", + "국민연금공단 명의로 세금 미납 통지서를 보냈고 링크를 통해 확인을 요구해 사기 가능성이 높다고 판단됨." + ] + ), + FraudExample( + type_name="알바/부업 사기형", + message_content=[ + "[Web발신] 안녕하세요! 당사 유통사에서 상품 검수 및 단순 작업을 도와주실 분을 모집합니다. 하루 20분 작업, 일당 최대 14만원 지급. 카카오톡 open.kakao.com/abcd 로 문의주세요.", + "[광고] 온라인 부업 모집! 나이/경력 무관, 하루 30분 휴대폰으로 간단한 수익 가능. 급여 당일 정산. 관심 있으시면 http://bit.ly/jobapply 로 접속하세요.", + "[Web발신] [TE MTV VIP] 채용 공고 – 재택근무 알바 모집 중! 20~50세 대상, 카카오톡 아이디 통해 1:1 채용 상담 진행 중. 지금 바로 문의 주세요!" + ], + keywords=[ + "문자", + "송금 요청", + "앱 설치 / 파일 다운로드 유도", + "링크 클릭 요청", + "개인정보 입력", + "신분증", + "휴대폰 인증번호", + "긴급하게 행동을 요구했다", + "링크나 파일이 수상해 보였다" + ], + additional_description=[ + "open.kakao 링크를 포함하여 단순 재택근무를 빙자하고 높은 급여를 약속하며 개인정보 유도.", + "초단기 고수익 부업을 미끼로 링크 클릭을 유도하고, 당일 정산이라는 문구로 사용자의 판단을 흐리는 사례.", + "카카오톡 ID 또는 상담 링크를 통해 접촉을 유도하며, 연령 조건을 제시해 신뢰감을 조성하는 형태의 스미싱 메시지." + ] + ), + FraudExample( + type_name="정부지원금 위장형", + message_content=[ + "[Web발신] [고용노동부] 민생안정지원금 330,000원 지급 대상자입니다. 예산 소진 전 신청하세요 han.gl/abcd", + "[Web발신] [중소벤처기업부] 방역지원금 신청마감 임박! 신청자에 한해 신속지급됩니다 bit.ly/abcd", + "[국세청] 재난지원금 관련 신분증 사본 제출이 누락되었습니다. 제출하지 않으면 미지급 처리 is.gd/abcd" + ], + keywords=[ + "문자", + "공공기관", + "지원금 / 환급금 수령 유도", + "개인정보 입력", + "링크 클릭 요청", + "신분증", + "주민등록번호", + "링크나 파일이 수상해 보였다", + "긴급하게 행동을 요구했다" + ], + additional_description=[ + "고용노동부를 사칭해 민생안정지원금 33만원 수령 대상자라고 하며, 예산 소진 전 신청을 유도한 메시지.", + "방역지원금 신청 마감이 임박했다며 긴급하게 링크 클릭을 유도하는 메시지.", + "국세청을 사칭하여 신분증 사본 제출을 요구하며 미제출 시 미지급 처리된다는 위협성 문구를 포함한 사기형 메시지." + ] + ), + FraudExample( + type_name="택배 사기형", + message_content=[ + "[Web발신] [CJ대한통운] 배송지 오류로 인해 상품이 반송되었습니다. 주소 확인 bit.ly/배송확인", + "[Web발신] 택배 배송이 지연되고 있습니다. 주소를 다시 입력해 주세요 han.gl/재확인", + "[CJ택배] 고객님의 택배가 도착하지 못했습니다. 정확한 배송을 위해 앱 다운로드 바랍니다 http://xgo.kr/tpapp.apk" + ], + keywords=[ + "문자", + "택배기사", + "링크 클릭", + "앱 설치 / 파일 다운로드 유도", + "링크나 파일이 수상해 보였다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description=[ + "CJ대한통운을 사칭하여 주소 오류로 인한 반송을 알리며 링크 클릭을 유도하는 사례.", + "배송 지연을 명목으로 주소 재입력을 유도하며 단축 URL로 링크를 유도하는 사기형 메시지.", + "앱 설치를 유도하는 악성 APK 다운로드 유도형 스미싱 메시지." + ] + ), + FraudExample( + type_name="가상화폐 사기형", + message_content=[ + "[Web발신] [Upbit] 귀하의 계정에서 해외IP 로그인이 감지되었습니다. 본인이 아닐 경우 즉시 확인 bit.ly/secure-eth", + "[Web발신] [Binance] 잔여 ETH 소각 예정입니다. 소각 전 자산 복구를 원하시면 상담 요청 line.me/xyz123", + "[알림] 비트코인 휴면계정 자산 소멸 예정입니다. 로그인 후 기기 등록 후 이용 가능 me2.kr/login-warning" + ], + keywords=[ + "문자", + "암호화폐 거래소", + "링크 클릭 요청", + "앱 설치 / 파일 다운로드 유도", + "개인정보 입력", + "신분증", + "긴급하게 행동을 요구했다", + "링크나 파일이 수상해 보였다", + ], + additional_description=[ + "업비트를 사칭하여 해외 로그인 감지라는 명목으로 긴급하게 링크 클릭을 유도하는 메시지.", + "바이낸스를 사칭해 ETH 소각 예정이라며 자산 복구를 미끼로 라인 상담 링크를 유도하는 사례.", + "비트코인 자산 소멸 예정이라는 경고와 함께 me2.kr 링크 클릭 및 기기 등록을 유도하는 메시지." + ] + ), + FraudExample( + type_name="주식투자 사기형", + message_content=[ + "[Web발신] 이번주 급등주 5개 공개! 가입 후 종목 수령하세요\n에넥스, 덕신하우징 등 급등 예상 종목\n수익률 최대 150% 보장, 손실 발생 시 전액 보상!\nhttps://bit.ly/vvipstock", + "[Web발신] (광고) 2차전지 유망주 유진테크놀로지 특별공급 안내\nNH증권 주관, 상장 전 선착순 신청\n공모가 14,000원 공급가 6,000원\n수익 극대화 기회! 지금 신청하세요\nhttps://bit.ly/yujinipo", + "[Web발신] 전문가 추천 종목 단타방 오픈!\n매일 수익 인증, 무료혜택 제공\n가입 후 '666' 입력 시 입장\n단기 수익률 30% 목표\nhttps://t.me/stockvip" + ], + keywords=[ + "문자", + "투자회사 / 증권사", + "링크 클릭 요청", + "개인정보 입력", + "지원금 / 환급금 수령 유도", + "신분증", + "긴급하게 행동을 요구했다", + "링크나 파일이 수상해 보였다", + ], + additional_description=[ + "에넥스 등 실제 종목명을 활용하여 고수익 보장과 손실 보상을 미끼로 단축 URL을 통해 가입을 유도하는 메시지", + "2차전지 유망주를 빙자해 할인 공급과 수익 극대화를 강조하며 선착순 신청을 유도하는 사기 사례", + "전문가 단타방 입장을 유도하며 무료 혜택, 수익 인증 등을 통해 사용자의 심리를 자극하고 링크 클릭을 유도하는 메시지" + ] + ), + FraudExample( + type_name="청약 공모주 사기형", + message_content=[ + "[Web발신]\n(광고) IPO 공모 청약 신청\n24년 첫 코스피 상장 APR에이피알(KOSPI)\n상장일정: 2024년 2월 26일\n주관사: 신한투자증권\n공모가: 250,000원 공급가: 70,000원\n청약 담당자: 010-8014-XXXX\n빠른회신 부탁드립니다.", + "[Web발신]\n축하드립니다. 공모주 청약 당첨 안내\n두산로보틱스 10주 무상배정\n상장일: 2023년 10월 2일\n주관사: 미래에셋증권, 한국투자증권\n공모가: 25,000원 ~ 28,000원\n당첨자에 한해 순차적으로 안내 전화 드리겠습니다.", + "[Web발신]\n청약 가능한 공모주 안내\n이노스페이스 (발사체 제작, 우주항공)\n일반 공모가: 36,400~43,300원\n사전신청 시 할인 공급가 적용\n청약 일정: 6월 20~21일\n신청링크: hxxps://poo-ipo.net" + ], + keywords=[ + "문자", + "투자회사 / 증권사", + "링크 클릭 요청", + "링크나 파일이 수상해 보였다", + "긴급하게 행동을 요구했다" + ], + additional_description=[ + "실제 증권사를 언급하며 낮은 공급가로 공모주 청약을 유도", + "공모주 당첨을 위장해 무상배정과 안내 전화를 강조하여 응답을 유도", + "실제 기업명을 사용하고, 사전 신청을 통해 할인된 공급가로 청약할 수 있다는 내용으로 유인" + ] + ), + FraudExample( + type_name="허위결제 사기형", + message_content=[ + "[Web발신] 아마존 해외결제 354,000원 승인완료. 본인 아닌 경우 즉시 신고 1544-XXXX", + "[Web발신] 해외 승인 결제 요청: $299.99 / 본인 아닐 경우 http://checkpay.co.kr/verify", + "[소비자보호원] 본인 아닌 카드 결제건이 발생했습니다. 취소를 원하시면 즉시 확인 http://card-cancel.com" + ], + keywords=[ + "문자", + "금융기관", + "링크 클릭 요청", + "긴급하게 행동을 요구했다" + ], + additional_description=[ + "해외 결제가 본인도 모르게 진행된 것처럼 꾸며져 즉시 신고를 유도", + "해외 결제건 승인 요청으로 가장해 링크 클릭을 유도", + "소비자보호 기관을 사칭하여 카드결제를 취소하라며 링크 클릭을 유도" + ] + ), + FraudExample( + type_name="가족/지인 사칭형", + message_content=[ + "엄마 나 폰 액정 깨져서 수리 맡기고 급하게 문자나라로 문자하는 거야\n지금 급한 부탁 있어서 그래 문자 확인하면 답장 줘\n무슨 일이야?\n지금 기프트카드 필요한데 엄마가 먼저 20만원권 3장만 구매해줘", + "아빠 폰 고장나서 임시로 문자하는 거야 급하게 부탁이 있어서\n보험 신청하려는데 내 폰 인증이 안돼서 아빠 명의로 진행해도 돼?\n민증이랑 카드 앞뒤 사진 보내줘\n알았어 보내줄게\n그리고 계좌번호랑 비번 4자리 필요해", + "이모 부탁 하나만 드려도 될까요?\n공인인증서 오류로 이체가 안돼서요\n이모가 대신 송금해주실 수 있나요?\n내가 오늘 중으로 바로 갚을게요\n얼마 보내야 해?\n95만원이에요\n계좌번호 알려줘" + ], + keywords=[ + "메신저", + "가족 / 친구 / 지인", + "송금 요청", + "기프트카드 구매 요청", + "개인정보 입력", + "신분증", + "주민등록번호", + "긴급하게 행동을 요구했다", + "무리한 정보 요청이 있었다", + "실제 기관/지인 연락처와 달랐다" + ], + additional_description=[ + "메신저 문자앱을 통해 접근하고 급하게 기프트카드를 사달라고 요청함", + "폰 고장 핑계로 메신저 접근, 가족 명의 정보 요구 및 보험 명목 사기", + "공인인증서 오류 핑계로 이체 요청, 계좌 정보 요구 및 긴급한 어투" + ] + ) +] \ No newline at end of file diff --git a/app/prompts/data/score_rules.txt b/app/prompts/data/score_rules.txt new file mode 100644 index 0000000..79b82b0 --- /dev/null +++ b/app/prompts/data/score_rules.txt @@ -0,0 +1,131 @@ +CAT01 기관 사칭형 + A:30:검찰청|경찰서|금융감독원|형사기동대 + B:10:사건 송치|수사 협조|조사 회신 + C:10:문서번호|공문 발송|사건번호 + D:10:주민등록번호|주소|성명 + E:10:명의 도용|압수|보안 강화|검찰소환 + F:10:bit.ly|han.gl|is.gd|vo.la|me2.do|http|https + +CAT02 대출 사기형 + A:30:은행|농협|신한저축|금융복지정책 + B:15:대출진행|대환대출|생계자금|정부지원상품 + C:10:무직자 가능|신용등급 무관|무서류|저금리 + D:10:신분증|등본|통장사본|재직증명서 + E:10:신청서.zip|앱설치|.apk|hxxp + F:5:상담신청|접수완료|한도조회|대표번호 + +CAT03 카드사 사칭형 + A:30:KB국민카드|현대카드|롯데카드|신한카드|카드 + B:15:카드 신청완료|카드 발급완료|개통완료 + C:15:본인 신청 아니면 신고|본인 아닐 경우 문의|본인 아님 신고 + D:10:개인정보 유출|승인 거절|이상 거래 감지 + E:5:상담접수|즉시 문의|콜센터|취소 요청 + F:5:Web발신|승인불가|개통내용 아닌 경우 + +CAT04 돌잔치 초대장형 + A:35:돌잔치|첫돌|아들 돌잔치|축하해주세요|많이많이 축하 + B:20:모바일 초대장|초대장을 보내드렸습니다|참석하여 주시기 바랍니다 + C:5:축복해주세요|모두 축하 + D:20:oa.to|vo.to|pa.to|pro.ps|.apk|bit.ly|han.gl|is.gd|http|https + +CAT05 모바일 청첩장형 + A:35:결혼식|재혼|웨딩홀|결혼합니다|사랑의 결실 + B:20:모바일청첩장|청첩장 도착|청접장|Wedding Invitation + C:5:축하해주세요|참석 부탁|인연으로 하나됩니다 + D:20:han.gl|bit.ly|c11.kr|na.to|.apk|is.gd|vo.la|me2.do|http|https + +CAT06 부고문자형 + A:40:별세|소천|사망하셨습니다|부고|訃告 + B:10:아버님|어머님|부모님|부친|모친 + C:10:삼가 고인의 명복|안타깝게도|불행하게도 + D:10:장례식장|빈소|오시는 길 + E:10:buly.kr|vo.la|iplogger.com|xgo.kr|gg.gg|bit.ly|han.gl|is.gd|http|https + +CAT07 범칙금/과태료 부과형 + A:30:도로교통법 위반|정지선 위반|어린이 보호구역 + B:15:과태료 부과|벌점 통지서|고지서 발송|가압류|장기연체대상자 + C:10:민원24|신고 접수|단속되어|민원내용 확인 + D:10:쓰레기 무단투기|음식물분리수거 위반|층간소음행위 + E:10:관세청|수입세금|관세징수과|통관번호|세금 미납 안내 + F:5:paso.mobilecar.pe.kr|goosmsi.com|homes|mobilecar|bit.ly|han.gl|is.gd|http|https + +CAT08 건강보험공단 사칭형 + A:35:국민건강보험|건강보험공단|건강지키미 + B:10:건강검진 통지서|건강검사 통보문|종합건강검진 + C:15:환급금 신청마감|보험료 환급금|건강보험료 미납 + D:10:확인바랍니다|조회하기|신청요망 + E:10:dokdo.in|nhisis.xyz|cloud|nhis|nhi|bit.ly|han.gl|is.gd|http|https + +CAT09 경찰 출석 요구형 + A:30:검찰청|경찰서|법원|국정원 + B:10:출석요구서|소환장|사건조회번호 + C:10:형사소송건|민사소송|재산몰수 통지서 + D:10:긴급출석요구|발부되었습니다|즉시 확인 + E:10:사건번호|고단 + F:10:sc-police.co.kr|xuto.tk|is.gd|bit.ly|han.gl|http|https + +CAT10 국세청 사칭형 + A:35:국세청|홈택스|국민연금공단|납세자연맹 + B:10:종합소득세|연말정산|세금 미납|세금 환급금 + C:15:환급 대상자|환급금 수령|금액 확인|환급 내역 조회 + D:10:신청하세요|수령 확인|조회 및 납부|통지서 확인 + E:10:han.gl|goo.gl|me2.do|hometax.go.kr|bit.ly|is.gd|http|https + +CAT11 알바/부업 사기형 + A:30:재택근무|단기 알바|쉬운 업무|문자 알바 + B:15:시급 3만원|고수익 보장|일 10만 이상|당일 정산 + C:10:누구나 가능|자격무관|당일 지급 + D:15:오픈채팅|카톡 추가|링크 클릭|접속하세요 + E:10:open.kakao.com|bit.ly|t.me|reurl.kr|han.gl|is.gd|http|https + +CAT12 정부지원금 위장형 + A:30:재난지원금|방역지원금|민생안정지원금 + B:10:국세청|고용노동부|중소벤처기업부 + C:10:신청마감|신속지급|신청하기 클릭 + D:10:신분증 사본|본인 확인|제출서류 + E:10:예산소진|원 도착|예산 초과 시 부지급 + F:5:bit.ly|han.gl|is.gd|me2.do|vo.la|http|https + G:5:민생 회복|꼭 확인해주세요|확인 안 될 경우 미지급 + +CAT13 택배 사기형 + A:30:택배|쿠팡|택배기사 + B:15:주소 오류|주소 불일치|배송지 오류|주소 확인 요망 + C:15:배송 지연|배송 실패|미수령 택배|통관번호 오류 + D:10:bit.ly|han.gl|is.gd|vo.la|me2.do|http|https + E:10:앱 다운로드|배송조회 바로가기|주소 입력 페이지 + +CAT14 가상화폐 사기형 + A:30:소각 예정|자산 복구|소멸 예정|휴면계정 소각 + B:20:해외IP 로그인|로그인 감지|수상한 기기|기기등록 후 사용|본인이 아닐 경우|로그인 알림 + C:15:ETH|BTC|이더리움|비트코인|테더|잔여 ETH + D:15:line.me|bit.ly|me2.kr|카톡|상담 바로가기|t.me|http|https + +CAT15 주식투자 사기형 + A:35:고수익|수익보장|원금보장|손실보상 + B:15:에넥스|덕신하우징|2차전지|바이오|유진테크놀로지 + C:5:bit.ly|t.me|open-kakao|open.kakao|han.gl|reurl.kr|is.gd|http|https + D:5:쿠폰 증정|단타 무료방|무료혜택|선착순 모집 + E:10:단타|매수|매도|수급|테마|상장특별공급|종목추천 + F:5:지금 가입|링크 클릭|바로 입장|채팅방 이동|666 + G:5:마지막 기회|안정수익|실시간 인증|장마감공개 + +CAT16 청약 공모주 사기형 + A:30:공모주|청약|상장예정|IPO|무료배정 + B:15:미래에셋|신한증권|하나증권|증권사|청약담당자 + C:15:할인공급가|수익률|급등|이익률 + D:10:문자상담|상담전화|빠른회신|순차연락 + E:5:할인혜택|무상입고|무료거부|종목확인|IR안내 + F:5:두산로보틱스|이노스페이스|APR|에이피알 + +CAT17 허위결제 사기형 + A:35:결제완료|승인요청|인증번호|해외승인|본인아님 + B:15:신용카드|휴대폰결제|이니시스|모빌리언스|위메프|아마존 + C:15:단축URL|의심URL|IP링크|http|https|hxxp|hxxps|bit.ly|han.gl|is.gd|vo.la|me2.do + D:15:고객센터|소비자보호|문의전화|신고요청 + +CAT18 가족/지인 사칭형 + A:30:가족|친구|지인 + B:15:폰고장|액정깨짐|임시폰|문자접속 + C:15:급해|갚을게|부탁|수리중|지금바로 + D:10:송금|계좌이체|기프트카드|입금요청 + E:10:신분증|주민번호|카드사진|인증번호 \ No newline at end of file diff --git a/app/prompts/fraud_example.py b/app/prompts/fraud_example.py index 6d768bf..2e0f2e4 100644 --- a/app/prompts/fraud_example.py +++ b/app/prompts/fraud_example.py @@ -3,7 +3,6 @@ class FraudExample(BaseModel): type_name: str - message_content: str + message_content: List[str] keywords: List[str] - additional_description: str - image_content: str \ No newline at end of file + additional_description: List[str] diff --git a/app/prompts/fraud_prompts.py b/app/prompts/fraud_prompts.py index 4733a15..0596adf 100644 --- a/app/prompts/fraud_prompts.py +++ b/app/prompts/fraud_prompts.py @@ -1,7 +1,44 @@ from typing import List, Dict +from pathlib import Path from app.prompts.fraud_example import FraudExample from app.prompts.data.fraud_examples import FRAUD_EXAMPLES +SYSTEM_PROMPT = """ +너는 보이스피싱 사기 탐지 전문가다. +다음 규칙표를 사용해 입력 텍스트를 분석하고, +1) 사기 유형(카테고리) 선택 +2) 핵심 키워드(최소1~최대3) 추출 +3) 점수는 최소 0점에서 최대 70점 + +[점수 규칙] +- 규칙표는 "카테고리ID 카테고리명" 한 줄 + 그 아래 여러 룰 라인으로 구성된다. +- 룰 라인 형식: "룰ID:배점:키워드1|키워드2|...". +- 텍스트에 해당 룰의 키워드 중 1개라도 의미/표현상 매칭되면 그 룰의 배점을 가산(룰별 최대 1회). +- 유저가 입력한 'keywords'에서 점수 계산을 하고, 'additionalDescription'과 'imageContent'를 참고하여 점수 계산. +- 키워드는 의미가 같으면 띄어쓰기/대소문자/오타 등과 동의어 허용. +- 동일 카테고리에서 여러 룰이 적중할 수 있으며, 합산 후 카테고리 점수는 70을 초과하지 않는다(상한 70점). +- 최종적으로 가장 점수가 높은 카테고리를 estimatedFraudType으로 선택. +- 동점이면 적중 룰 개수가 더 많은 카테고리를 선택. 그래도 동률이면 의미상 더 근접한 쪽. +- 링크/단축URL은 http/https, bit.ly/han.gl/is.gd/vo.la/me2.do 등도 매칭으로 본다(표기 변형 허용). + +출력은 반드시 valid JSON 객체로만 응답. 오직 JSON만 출력. +코드블록(```), 주석, 추가 텍스트, 설명 모두 금지. +'estimatedFraudType' 에는 오로지 카테고리명만 넣을 것. +아래는 응답 예시. +{ + "estimatedFraudType": "<카테고리명>", + "keywords": ["<키워드1>", "<키워드2>", "<키워드3>"], + "explanation": "<왜 이 유형이고 어떤 이유로 판단하였는지 간결히 설명>", + "score": <0~70의 실수값> +} + +""".strip() + + +def _load_rules() -> str: + rules_path = Path(__file__).parent / "data" / "score_rules.txt" + return rules_path.read_text(encoding="utf-8") + def get_fraud_detection_prompt( message_content: str, additional_description: str, @@ -9,33 +46,13 @@ def get_fraud_detection_prompt( image_content: str, examples: List[FraudExample] = FRAUD_EXAMPLES ) -> List[Dict[str, str]]: - - system = { - "role": "system", - "content": ( - "당신은 사기 탐지 어시스턴트입니다. " - "입력된 텍스트를 반드시 미리 정의된 사기 유형 중 하나로 분류하고, " - "최소 1개에서 최대 3개의 주요 위험 키워드를 추출하며, 그 이유를 설명하고, " - "위험 점수(0–100%)를 제공해야 합니다.\n" - "출력은 반드시 valid JSON 객체로만 응답하세요. 아래는 응답 예시입니다:\n" - "{\n" - " \"estimatedFraudType\": \"복권 사기\",\n" - " \"keywords\": [\"키워드1\", \"키워드2\"],\n" - " \"explanation\": \"...\",\n" - " \"score\": 92.4\n" - "}\n" - ) - } + rules_text = _load_rules() + example_text = "".join(build_example_lines(examples)) - example_lines = build_example_lines(examples) - assistant_content = "".join(example_lines) - assistant_content += ( - "이제 아래 입력을 같은 형식으로 분류하세요:\n" - ) - assistant = { - "role": "assistant", - "content": assistant_content + system = { + "role": "system", + "content": f"{SYSTEM_PROMPT}\n\n[규칙표]\n{rules_text}\n\n[예시]\n{example_text}" } user = { @@ -48,7 +65,8 @@ def get_fraud_detection_prompt( ) } - return [system, assistant, user] + return [system, user] + def build_example_lines(examples): example_lines = ["사기 유형 및 예시:\n"] @@ -57,11 +75,5 @@ def build_example_lines(examples): example_lines.append(f" messageContent: '{ex.message_content}'\n") example_lines.append(f" additionalDescription: '{ex.additional_description}'\n") example_lines.append(f" keywords: '{ex.keywords}'\n") - example_lines.append(f" imageContent: '{ex.image_content}'\n") - example_lines.append(" 출력 JSON 예시:\n") - example_lines.append( - f" {{\"estimatedFraudType\": \"{ex.type_name}\", " - f"\"keywords\": [...], \"explanation\": \"...\", \"score\": ...}}\n\n" - ) - return example_lines + return example_lines \ No newline at end of file diff --git a/app/services/gpt_service.py b/app/services/gpt_service.py index 19722b0..ef5d290 100644 --- a/app/services/gpt_service.py +++ b/app/services/gpt_service.py @@ -22,7 +22,7 @@ async def call_gpt(request: FraudRequest): response = client.responses.create( model="gpt-4o-mini", input = messages, - temperature = 0.5, # 생성된 텍스트의 무작위성을 결정 + temperature = 0.1, # 생성된 텍스트의 무작위성을 결정 max_output_tokens = 200 ) logger.info(f"GPT API 호출 성공: {response}")