TL;DR
이 프로젝트는 Hinglish 페르소나의 대화형 허니팟을 통해 사기범의 자발적 정보를 회수하는 목표를 세우고, 세션 간 영속 메모리(Hindsight)와 단계별 관측 파이프라인(CascadeFlow)을 결합해 실시간으로 구조화된 인텔을 추출·저장하는 아키텍처를 구축했다. 구현은 OpenAI GPT-4o-mini 호출 전 Hindsight로부터 top-5 메모리를 질의해 KNOWN INTEL을 주입하고, 요청을 8개의 Typed 단계로 분해해 각 단계의 실패와 지연을 추적하는 방식으로 동작하며 문서에는 단계별 평균 지연(예: 메모리 조회 ~45ms, LLM 호출 ~800ms)과 파이프라인 코드 예시가 포함되어 있다. 엔지니어링 교훈으로는 데이터 레이어의 초기 분리, 정규표현식 기반의 인텔 파싱, Zod 변환을 통한 신뢰도 표시 통일 등이 제시되어 실무 적용 가능성이 높았다. 한계로는 법적·윤리적 고려와 관련된 논의가 문서에 상세히 포함되어 있지 않아 운영 전 추가 검토가 필요하다.
실용적 조언
- 데이터 레이어를 초기에 분리해 원시 채팅, 구조화 인텔, 영속 메모리를 각각 독립적으로 설계하면 마이그레이션과 인덱싱 충돌을 방지할 수 있다.
- 파이프라인을 Typed 단계로 구성해 각 단계의 평균 지연을 계측하면 병목과 실패 지점을 운영 중에 빠르게 찾을 수 있다.
- LLM이 생성한 인텔은 정규표현식 기반 파서와 원문 인용 규칙을 적용해 허위 인텔이 저장되지 않도록 엔지니어링 장치를 마련해야 한다.
섹션별 상세

const memories = await hindsight.query({ text : ctx.userMessage, topK : 5, filter: { type: { $in: ['upi', 'phone', 'url', 'bank'] } }, })Hindsight에 현재 사용자의 메시지를 질의해 상위 5개의 의미적 유사 메모리를 검색하는 예시 코드로, 검색 결과를 시스템 프롬프트로 주입하기 위한 전처리 단계이다.
ctx.knownIntel = memories.map(m => `KNOWN INTEL: ${m.type} "${m.value}" seen in ${m.sessionCount} session(s)` ).join('
')검색된 메모리들을 KNOWN INTEL 블록 형식의 문자열로 합쳐서 LLM의 시스템 프롬프트에 주입하는 로직 예시이다.

export const saraChatPipeline = cascade([ { name: 'validate-session', fn: validateSession }, // ~2ms { name: 'load-session-history', fn: loadSessionHistory }, // ~8ms { name: 'recall-hindsight-memory', fn: recallMemory }, // ~45ms ← vector { name: 'build-system-prompt', fn: buildSystemPrompt }, // ~1ms { name: 'call-openai', fn: callOpenAI }, // ~800ms ← LLM { name: 'strip-and-extract-intel', fn: stripAndExtractIntel }, // ~5ms { name: 'persist-messages', fn: persistMessages }, // ~6ms { name: 'dispatch-webhooks', fn: dispatchWebhooks }, // ~12ms ])CascadeFlow 기반으로 요청을 8개의 Typed 단계로 분해해 각 단계의 평균 지연을 주석으로 남긴 파이프라인 정의 코드로, 실패 시 어느 단계에서 중단됐는지 정확히 식별할 수 있게 한다.



const INTEL_RX = /\^INTEL:\\s*(\w+)\s+VALUE="([^\"]+)"\s+CONF=(\[\d.\]+)/gm
for (const [full, type, value, conf] of raw.matchAll(INTEL_RX)) {
intel.push({ type, value, confidence: parseFloat(conf) })
visible = visible.replace(full, '') // never reaches the UI
}LLM이 출력한 INTEL 라인에서 타입·값·신뢰도를 정규표현식으로 파싱해 데이터베이스에 저장하고, UI로 노출되는 텍스트에서는 INTEL 라인을 제거하는 추출 및 마스킹 로직이다.
confidence: z.number().min(0).max(1) .transform(v => Math.round(v * 100)) // every component gets % automaticallyZod 스키마 레벨에서 0.0–1.0 저장값을 퍼센트 정수로 변환해 프론트엔드 컴포넌트 간 신뢰도 표시 방식의 불일치를 해결한 변환 예시이다.
용어 해설
- 의미 기반 영속 메모리(Semantic Memory)
- — 대화에서 추출한 정보 조각을 임베딩으로 저장해 의미적 유사도를 기반으로 검색하는 저장소이다. 입력 문장을 임베딩으로 변환해 과거의 관련 항목을 top-k로 반환함으로써 문맥 주입에 사용된다. 허니팟 맥락에서는 세션 간 중복 인텔을 연결하고 재사용 가능하게 만드는 핵심 계층이다.
- 벡터 임베딩(Vector Embeddings)
- — 문장이나 텍스트를 고정 길이 실수 벡터로 변환해 의미적 유사도 검색을 가능하게 하는 표현 방식이다. 입력 텍스트와 저장된 메모리 간 코사인 유사도 등을 계산해 관련 과거 기록을 찾아준다. 실시간 인텔 회수와 유사 패턴 탐지에서 검색 정확도와 응답 지연을 결정하는 요소이다.
- 관측 가능한 파이프라인(Observable Pipeline)
- — 요청 처리 과정을 여러 Typed 단계로 분해하고 각 단계의 성공·실패와 지연을 추적 가능한 형태로 남기는 아키텍처 패턴이다. 단계별 에러와 실행 시간을 로그·트레이스로 기록해 운영 중 원인 규명을 빠르게 한다. 허니팟에서는 메시지 유입부터 인텔 추출·영속화까지의 원인 추적을 가능하게 해 운영 복구 시간을 단축시켰다.
- 신뢰도 점수화(Confidence Scoring)
- — 추출된 인텔 항목에 대해 0.0–1.0 범위의 부동소수점 신뢰도를 부여해 정량적으로 평가하는 방법이다. 저장 포맷과 UI 표시 방식의 불일치가 발생하지 않도록 스키마 수준에서 변환을 적용해야 실무에서 일관된 표시가 이루어진다. 본 사례에서는 Zod 변환으로 내부 저장값을 퍼센트 표기로 일괄 변환했다.
언급된 도구
벡터 기반의 의미 메모리 저장소로 세션 간 인텔을 검색·주입하는 용도
Typed 단계로 요청을 분해하고 실행 트레이스를 제공하는 파이프라인 라이브러리
대화 생성 및 인텔 원천으로 사용된 LLM
OpenAPI 스펙에서 React Query 훅과 Zod 밸리데이터를 자동 생성하는 코드 제너레이터
신뢰도 필드 등 스키마 수준 변환으로 프론트엔드 표시 계약을 일관되게 유지하는 유효성 라이브러리
원시 채팅과 인텔을 영속화하는 관계형 저장소 및 ORM
언급된 리소스
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.