git 히스토리에 이미 있는 Phase 0~6 changelog, OPC UA 서버, 버그 수정 이력, 성능 분석, 구현 계획(Task 1~4) 전부 삭제. 작업 규칙 + 최신 1건(Phase 7)만 유지해 세션 컨텍스트 로드량 축소. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.7 KiB
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 요청 필드 → ComposeSystemPrompt에 AgentModeGuideKo (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, ToolGuideKo에 classify_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— OKpython3 -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 마이그레이션 (위험 대비 임계값 평가 필요)
- 모두 코드 작업 아닌 분석/결정 항목