UNPKG

@kangthink/q-engine

Version:

A question-answer generation engine that stimulates thinking

150 lines 5.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeDetector = void 0; const types_1 = require("../types"); /** * 텍스트 내용을 분석하여 질문인지 답변/진술인지 자동으로 판단하는 유틸리티 */ class TypeDetector { /** * 내용을 분석하여 NodeType을 반환 */ static detectType(content) { const trimmedContent = content.trim(); // 빈 문자열 처리 if (!trimmedContent) { return types_1.NodeType.ANSWER; // 기본값으로 답변 처리 } // 질문 패턴 확인 for (const pattern of this.questionPatterns) { if (pattern.test(trimmedContent)) { return types_1.NodeType.QUESTION; } } // 답변/진술 패턴 확인 for (const pattern of this.statementPatterns) { if (pattern.test(trimmedContent)) { return types_1.NodeType.ANSWER; } } // 물음표로 끝나는 경우는 질문 if (trimmedContent.endsWith('?')) { return types_1.NodeType.QUESTION; } // 마침표나 느낌표로 끝나는 경우는 일반적으로 답변/진술 if (trimmedContent.endsWith('.') || trimmedContent.endsWith('!')) { return types_1.NodeType.ANSWER; } // 문장의 길이와 구조를 기반으로 추가 판단 // 짧고 단정적인 문장은 일반적으로 답변 if (trimmedContent.length < 20 && !trimmedContent.includes('?')) { return types_1.NodeType.ANSWER; } // 기본값: 답변/진술로 분류 // (질문보다 답변/진술이 더 일반적이므로) return types_1.NodeType.ANSWER; } /** * 감지 결과에 대한 신뢰도를 반환 (0-1) */ static getConfidence(content) { const trimmedContent = content.trim(); // 명확한 질문 패턴 if (trimmedContent.endsWith('?') || /^(누가|무엇을|언제|어디서|왜|어떻게)/.test(trimmedContent)) { return 0.9; } // 명확한 답변 패턴 if (/(이다|입니다|습니다|다)$/.test(trimmedContent)) { return 0.8; } // 패턴 매칭 결과에 따른 신뢰도 const questionMatches = this.questionPatterns.filter(p => p.test(trimmedContent)).length; const statementMatches = this.statementPatterns.filter(p => p.test(trimmedContent)).length; if (questionMatches > statementMatches && questionMatches > 0) { return Math.min(0.7 + (questionMatches * 0.1), 0.9); } if (statementMatches > questionMatches && statementMatches > 0) { return Math.min(0.6 + (statementMatches * 0.1), 0.8); } // 불확실한 경우 return 0.3; } /** * 타입 감지 결과를 설명과 함께 반환 */ static analyzeType(content) { const type = this.detectType(content); const confidence = this.getConfidence(content); let reason = ''; const trimmedContent = content.trim(); if (type === types_1.NodeType.QUESTION) { if (trimmedContent.endsWith('?')) { reason = '물음표로 끝남'; } else if (/^(누가|무엇을|언제|어디서|왜|어떻게)/.test(trimmedContent)) { reason = '의문사로 시작'; } else if (/(인가|나요|까요|을까|일까)[\s]*$/.test(trimmedContent)) { reason = '의문형 어미 사용'; } else { reason = '질문 패턴 감지'; } } else { if (/(이다|입니다|습니다|다)$/.test(trimmedContent)) { reason = '단정적 어미 사용'; } else if (/(있다|없다|한다|된다|크다|작다|비싸다|싸다)[\s]*$/.test(trimmedContent)) { reason = '서술형 어미 사용'; } else if (trimmedContent.endsWith('.') || trimmedContent.endsWith('!')) { reason = '서술문 구조'; } else { reason = '답변/진술 패턴'; } } return { type, confidence, reason }; } } exports.TypeDetector = TypeDetector; /** * 질문을 나타내는 패턴들 */ TypeDetector.questionPatterns = [ // 의문사로 시작하는 패턴 /^(누가|무엇을|무엇이|언제|어디서|어디에|왜|어떻게|어떤|얼마나|몇|어느)/, // 질문 어미 패턴 /\?([\s]*$)|인가\?|나요\?|까요\?|을까\?|일까\?/, // 의문형 어미 패턴 /(인가|나요|까요|을까|일까|인지|는지|든지)[\s]*$/, // 영어 질문 패턴 /^(what|who|when|where|why|how|which|does|do|did|is|are|was|were|can|could|will|would|should)/i, // 질문형 구조 /입니까|습니까|나요|까요|인가요|을까요|일까요/, // "~은 무엇인가?" 형태 /는\s*(무엇|뭐|어떤)/, ]; /** * 답변/진술을 나타내는 패턴들 */ TypeDetector.statementPatterns = [ // 단정적 어미 /(이다|다|입니다|습니다|됩니다|합니다)[\s]*$/, // 설명/서술형 어미 /(있다|없다|한다|된다|같다|크다|작다|좋다|나쁘다|많다|적다|높다|낮다|비싸다|싸다)[\s]*$/, // 과거형 서술 /(었다|았다|였다|했다|됐다|됐습니다|었습니다|았습니다)[\s]*$/, // 현재 진행형/상태 /(고\s*있다|어\s*있다|아\s*있다|여\s*있다)[\s]*$/, // 영어 서술문 패턴 (주어 + 동사) /^[A-Z][a-z]*\s+(is|are|was|were|has|have|had|do|does|did|will|would|can|could)/, // 명사 + 조사 + 형용사/동사 패턴 /\w+는\s*\w+다$/, /\w+가\s*\w+다$/, /\w+을\s*\w+다$/, /\w+를\s*\w+다$/, ]; //# sourceMappingURL=typeDetector.js.map