@kangthink/q-engine
Version:
A question-answer generation engine that stimulates thinking
150 lines • 5.98 kB
JavaScript
;
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