v2.2.313~319: 보고 품질·조사 신뢰성 수술 + 네이버 쇼핑인사이트/검색어트렌드 연동
- 파트별 완성, 웹 실접속 증빙, 턴 의도 브리핑, 본문 불일치 검증, 하위 질문 체크리스트, 사이트 심층 수집 (PATCHNOTES.md v2.2.313~318 참조) - /naver-shopping, /naver-trend: 네이버 데이터랩 API 연동. compare/discover 자동 판별, API 배치 상한 캡슐화, 카테고리 트리 fuzzy 매칭, 자격증명은 Astra 설정 패널 SecretStorage 로 관리
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* [v2.2.314] 두 실사례 가드:
|
||||
* 1) LSEP 마커 뒤 "마무리 인사"만 남고 본문이 추론 구간에 갇혀 증발한 답변.
|
||||
* 2) "요청 요약/사용자 의도 추론/핵심 확인 질문" 내부 스캐폴딩 섹션 유출.
|
||||
*/
|
||||
import {
|
||||
splitLsepReasoning,
|
||||
isCloserOnlyAnswer,
|
||||
looksLikeReportBody,
|
||||
stripLeakedInternalSections,
|
||||
} from '../src/lib/contextBuilders/outputSanitization';
|
||||
|
||||
const MARKER = '__LM_STUDIO_INTERNAL_LSEP_SYNTHETIC_REASONING_END_a1b2c3d4e5f6__';
|
||||
|
||||
describe('splitLsepReasoning / isCloserOnlyAnswer / looksLikeReportBody', () => {
|
||||
test('마지막 END 마커 기준으로 before/after 분해', () => {
|
||||
const body = '## 1. 구조\n분석 본문. '.repeat(50);
|
||||
const r = splitLsepReasoning(`${body}${MARKER}이상으로 분석을 마칩니다.`);
|
||||
expect(r.hasMarker).toBe(true);
|
||||
expect(r.before).toContain('## 1. 구조');
|
||||
expect(r.after).toBe('이상으로 분석을 마칩니다.');
|
||||
});
|
||||
test('마커 없으면 hasMarker=false, after=원문', () => {
|
||||
const r = splitLsepReasoning('일반 답변');
|
||||
expect(r.hasMarker).toBe(false);
|
||||
expect(r.after).toBe('일반 답변');
|
||||
});
|
||||
test('마무리 인사만 = closer-only, 실질 본문은 아님', () => {
|
||||
expect(isCloserOnlyAnswer('이상으로 ConnectAI 프로젝트에 대한 분석을 마칩니다. 추가 검토가 필요하시면 언제든 요청해 주세요.')).toBe(true);
|
||||
expect(isCloserOnlyAnswer('## 구조 분석\n실제 본문이 여기 길게 이어진다.')).toBe(false);
|
||||
});
|
||||
test('헤딩 다수 장문 = 보고 본문, 짧은 텍스트 = 아님', () => {
|
||||
const report = ['## 개요', '본문 문단. '.repeat(60), '## 구조', '본문 문단. '.repeat(60)].join('\n\n');
|
||||
expect(looksLikeReportBody(report)).toBe(true);
|
||||
expect(looksLikeReportBody('짧은 생각')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripLeakedInternalSections — 내부 섹션 유출 제거', () => {
|
||||
test('금지 4종 섹션과 "질문 의도:" 줄을 제거하고 본문·출처는 보존', () => {
|
||||
const answer = [
|
||||
'## 프로젝트 개요', '실제 분석 본문.',
|
||||
'## 요청 요약', 'ConnectAI 프로젝트 분석 요청입니다.',
|
||||
'## 사용자 의도 추론', '전체 그림을 이해하고자 하는 의도로 판단됩니다.',
|
||||
'## 프로젝트 기록 대상 확인', '기록으로 관리될 예정입니다.',
|
||||
'## 핵심 확인 질문', '심층 분석이 필요하신가요?',
|
||||
'질문 의도: 범위 확장 여부 결정.',
|
||||
'## 분석 결과 요약', '요약 본문.',
|
||||
].join('\n');
|
||||
const out = stripLeakedInternalSections(answer);
|
||||
expect(out).toContain('## 프로젝트 개요');
|
||||
expect(out).toContain('## 분석 결과 요약');
|
||||
expect(out).not.toContain('요청 요약');
|
||||
expect(out).not.toContain('의도 추론');
|
||||
expect(out).not.toContain('기록 대상 확인');
|
||||
expect(out).not.toContain('핵심 확인 질문');
|
||||
expect(out).not.toContain('질문 의도');
|
||||
});
|
||||
test('금지 섹션이 없으면 원문 유지', () => {
|
||||
const clean = '## 개요\n본문\n\n## 다음 단계\n제안';
|
||||
expect(stripLeakedInternalSections(clean)).toBe(clean);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user