Files
ExperionCrawler/CLAUDE.md
windpacer 0ccec38c18 docs: CLAUDE.md 정리 — 변경 이력 압축 (963→81줄)
git 히스토리에 이미 있는 Phase 0~6 changelog, OPC UA 서버,
버그 수정 이력, 성능 분석, 구현 계획(Task 1~4) 전부 삭제.
작업 규칙 + 최신 1건(Phase 7)만 유지해 세션 컨텍스트 로드량 축소.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 07:13:39 +09:00

5.7 KiB

ExperionCrawler — 작업 이력

작업 규칙

  • 복잡한 작업은 항상 todo 목록 먼저 생성
  • 각 단계 시작 전 todo 목록 확인
  • 단계 완료 후 즉시 completed 표시

완료된 작업

Phase 7 + Phase 5 후순위 일괄 구현 (2026-05-14)

배경

plans/빅피클-잔여작업-코딩계획.md의 1~6번 항목을 일괄 구현. Phase 7 옵션 4종 + Phase 5 후순위 2종으로 채팅 UX·관리 편의·운영자 분석 능력을 강화.

구현 내역

# 항목 핵심
1 툴 카드 영구 보존 sess.messages[*].toolCalls[] 저장 → llmRenderMessages에서 재렌더링. F5 새로고침 후에도 툴 카드 유지
2 KB 청크 미리보기 UI Qdrant Scroll API → /api/kb/documents/{id}/chunks → 모달에 청크 카드 (접기/펼침)
3 시계열 미니 스파클라인 llmDetectTimeSeries (timestamp+value 키 자동 감지) → uPlot 90px 차트가 표 위에 자동 렌더링
4 NL2SQL 의도 라우터 _classify_intent 정규식 6규칙 → query_with_nl 진입 시 알람/요약/태그검색/이벤트로 위임. classify_intent MCP 도구로도 노출
5 대화 요약 sess.summary + summarizedUpTo 인덱스, LLM_MAX_HISTORY=20 초과 시 /api/ollama/summarize 호출 → systemPrompt에 누적 요약 prepend
6 에이전트 모드 #llm-agent-mode 토글 → AgentMode 요청 필드 → ComposeSystemPromptAgentModeGuideKo (ReAct 사이클) 주입

수정 파일

파일 변경 요약
src/Web/wwwroot/js/app.js llmRenderToolCardsHtml(영구 렌더), llmDetectTimeSeries+llmBuildSparklineHtml+llmMountSparkline(uPlot), kbShowChunks+kbRenderChunks(모달), LLM_MAX_HISTORY+llmEnsureSummary+sess.summary 표시, llmAgentMode+llmToggleAgentMode, 툴 카드 표시 + 요약 prepend 로직
src/Web/wwwroot/index.html #kb-chunk-modal 모달, #llm-agent-row/#llm-agent-mode 토글
src/Web/wwwroot/css/style.css .kb-chunk-*(청크 카드/뱃지/locator), .llm-sparkline-box/-chart, .llm-summary-card(접기/펼침)
src/Web/Controllers/OllamaController.cs AgentMode request 필드, ComposeSystemPrompt(agentMode), AgentModeGuideKo ReAct 가이드, POST /api/ollama/summarize 엔드포인트, OllamaSummarizeRequest DTO, ToolGuideKoclassify_intent 추가
src/Web/Controllers/KbController.cs GET /api/kb/documents/{id}/chunks (admin) — KbQdrantClient Scroll 호출
src/Infrastructure/Kb/KbQdrantClient.cs GetChunksByDocIdAsync(collection, docId, limit) — payload-only Scroll API
mcp-server/server.py _CLASSIFY_RULES+_classify_intent+@mcp.tool() classify_intent, query_with_nl 진입부에서 라우팅 후 5개 전용 도구로 위임 (실패 시 SQL fallback)

의도 라우터 규칙

정규식 라우팅 대상
활성.*알람|현재.*알람|지금.*알람|active.*alarm active_alarms
트립|trip active_alarms
상태\s*보고서|교대.*보고|status.*report|운전.*보고 generate_status_report
요약|보고서|리포트|summary|summarize|report summarize_events
태그.*찾|tag.*찾|찾아\s*줘|find.*tag|어떤.*태그 find_tags
이벤트.*조회|이벤트.*목록|event.*list|event.*query|로그.*조회 query_events
(그 외) query_with_nl (기본 SQL 경로)

스모크 테스트 10건 모두 통과 — "지금 알람 알려줘"→active_alarms / "FIC-6113.PV 값 보여줘"→query_with_nl / "안녕"→query_with_nl 등.

설계 결정

항목 결정
툴 카드 영구화 assistantMsg.toolCalls{id,name,args,ok,preview,length,payload} 누적 저장. 기존 세션에 toolCalls 없으면 렌더링 생략(역호환)
AbortError 시 content 또는 toolCalls가 비어있지 않으면 메시지 유지 (도구만 호출하고 중단된 경우도 보존)
시계열 감지 timestamp/recorded_at/ts/time/datetime + value/pv/val/fieldvalue/sp/op 페어. 3건 이상이어야 차트 생성. uPlot 미로딩 시 렌더 생략
스파클라인 부착 innerHTML로 컨테이너만 만든 후 requestAnimationFrame에서 uPlot 생성 (DOM 마운트 후 실행 보장)
요약 임계 LLM_MAX_HISTORY=20 초과 시 오래된 절반을 요약. 누적 요약은 이전 요약을 system 메시지로 함께 전송
요약 송신 sess.summary가 있으면 systemPrompt 맨 앞에 [이전 대화 요약] 블록 prepend. 사용자에게는 접이식 카드로 표시
의도 라우터 fallback 라우팅 시도 실패(예외) 시 조용히 SQL 경로로 fallback
에이전트 모드 조건부 표시 llmType==='vllm' && llmUseTools 일 때만 토글 노출. localStorage 영속
청크 미리보기 권한 admin 토큰 필요. payload만 조회(vector 제외), 최대 500개/문서

빌드/검증

  • dotnet build src/Web/ExperionCrawler.csproj — 경고 0건, 에러 0건
  • python3 -m py_compile mcp-server/server.py mcp-server/worker/nl2sql_worker.py — OK
  • python3 -c "import server" — 9개 도구 모두 attribute로 노출 확인
  • node -c src/Web/wwwroot/js/app.js — syntax OK
  • 의도 분류기 10/10 통과

런타임 셋업

  • mcp-server 재시작 — classify_intent 신규 도구 인식
  • 브라우저 캐시 무효화 (Ctrl+F5) — 신규 JS/CSS 적용
  • 사용자 첫 진입 시 에이전트 모드 토글은 OFF (옵트인)

잔여

  • 결정 보류: 현장 재고 데이터 출처 (KB 엑셀 업로드로 즉시 가능, 별도 개발 불필요), 임베딩 모델 BGE-M3 마이그레이션 (위험 대비 임계값 평가 필요)
  • 모두 코드 작업 아닌 분석/결정 항목