-
Notifications
You must be signed in to change notification settings - Fork 0
component chat assistant
JJong-03 edited this page Jun 17, 2026
·
4 revisions
본사 관제자가 자연어로 공장 상태·원인·보고서·증빙 이미지를 물어보는 Dashboard의 챗봇 QA 기능이다. 질문은 Dashboard Backend가 해석하고, Backend가 직접 read model을 조회해 근거(Evidence)를 만든 뒤 답변을 생성한다. LLM은 질문 해석과 최종 설명에만 쓰며, 데이터 조회 자체는 항상 Backend 코드가 수행한다.
Dashboard Web (/chat)
-> POST /chat/query (Cognito JWT)
-> 질문 해석 (intent + 시간 + 공장) services.chat / services.bedrock
-> RBAC: 공장/시스템 범위 강제 (데이터 조회 이전) deps.rbac
-> 데이터 도구 실행 (Backend가 데이터를 찾음) services.ddb / services.s3
-> Evidence 구성 (확인 / 추정 / 데이터 한계)
-> 답변 생성 (Bedrock 또는 규칙 템플릿) services.bedrock / services.chat
-> 답변 + Evidence 패널 + 증빙 이미지 렌더링
핵심 원칙:
- RBAC가 단일 경계다. 공장/시스템 범위 검사를 어떤 데이터 도구보다 먼저 수행한다. 사용자가 접근할 수 없는 공장에 대해서는 DynamoDB/S3 호출 자체를 하지 않는다. LLM이 고른 대상도 같은 검사로 재검증해, 채팅이 RBAC 우회 통로가 되지 않게 한다.
- 답변은 Backend가 찾은 근거에만 기반한다. LLM은 자유롭게 사실을 만들어내는 주체가 아니라, Backend가 만든 Evidence를 사람이 읽기 좋게 정리하는 역할이다.
- LLM 장애에 우아하게 degrade한다. Bedrock 해석/설명이 실패하면 결정론적 규칙 파서·템플릿으로 fallback하며, 그 사이 데이터 파이프라인은 동일하다.
routers/chat.py가 다음 순서로 처리한다.
-
질문 해석 —
_resolve_parsed. 라우팅이 켜져 있고 Bedrock이 활성이면 LLM이 intent·시간·공장을 추출(router="llm")하고, 아니면/실패 시 결정론적 규칙 파서로 해석(router="rule")한다. 해석 입력은 질문 텍스트뿐이라 RBAC 이전에 실행해도 공장 데이터가 새지 않는다. -
선행 종료 — intent가
unknown이거나, 공장이 필요한데 식별되지 않으면 데이터 조회 없이 안내 답변을 돌려준다. -
RBAC 강제 — 대상이
cloud-infra면require_system_access, 일반 공장이면require_factory_access. 통과해야만 데이터 도구가 실행된다. -
Evidence 수집 —
_fetch_evidence가 intent/시간에 맞는 도구를 고른다(아래 표). -
증빙 이미지(선택) — 질문에 이미지 키워드가 있으면
_maybe_fetch_image_ref가require_system_access후 S3 이미지 스냅샷을 조회해image_ref로 동봉한다. -
답변 생성 —
_explain. Bedrock 활성 시 LLM이 Evidence 위에서 설명을 쓰고(generator="bedrock"), 아니면/실패 시 규칙 템플릿(generator="rule").
| Intent | 의미 | 주 데이터 소스 |
|---|---|---|
current_status |
지금 상태 | DynamoDB LATEST
|
cause_analysis |
점수 급락/이상 원인 | DynamoDB HISTORY 또는 S3 processed 상세(risk_score drill-down) |
history_trend |
구간 추이 | DynamoDB HISTORY/GRAPH#5M, 필요 시 S3 state_snapshot 보강 |
spike_check |
특정 지표 임계 초과/급등 여부 | S3 processed_agg/metrics_5m + state_snapshot 상세 |
report |
일간 보고서 근거 요약 | S3 reports/daily/ Markdown |
unknown |
해석 불가 | 없음(안내만) |
- 과거 시점·구간 질문은 TTL이 있는 DynamoDB 대신 S3 processed 를 우선 읽어 오래된 데이터도 조회한다.
-
spike_check는 지표(risk_score/ai_detection/temperature)와 임계·비교(이상/이하)를 파싱해 결정론적으로 판정한다.
답변과 별개로, 화면에는 근거가 출처와 함께 노출된다. Evidence는 세 묶음으로 나뉜다.
| 구분 | 의미 | 예 |
|---|---|---|
confirmed |
read model에서 직접 확인한 값 | 안전점수, 평균/최저~최고, 점수 변화, 온도, AI 탐지 최대, 표본 수, 이미지 개수·시각 범위 |
inferred |
확인값으로부터의 추정·해석 | "AI 탐지 상승과 이미지 스냅샷이 같은 시간대에 확인됨" |
missing |
조회했으나 없거나 실패한 데이터 한계 | "요청 시각 범위에서 S3 image_snapshot 객체를 찾지 못함" |
이 구분은 답변 신뢰성의 핵심이다. 확인된 사실과 추정을 섞지 않고, 데이터 한계를 숨기지 않는다.
POST /chat/query 응답:
{
"answer": "<Markdown 답변>",
"intent": "cause_analysis",
"factory_id": "factory-a",
"time_scope": { "...": "해석된 시간 범위/시점" },
"evidence": { "confirmed": { }, "inferred": [], "missing": [] },
"image_ref": {
"kind": "image_snapshots",
"factory_id": "factory-a",
"time_range_kst": "2026-06-09 09:25~09:45 KST",
"count": 3,
"items": [ { "s3_key": "...", "filename": "...", "url": "<presigned GET>", "detection_type": "FIRE" } ]
},
"generator": "bedrock",
"model_tier": "precise",
"router": "llm"
}-
generator:bedrock|rule— 답변을 LLM이 썼는지 규칙 템플릿이 썼는지. -
model_tier:fast|precise|null— 응답 모드. 실제 model id는 노출하지 않는다(관리자 전용). -
router:llm|rule— intent/시간을 LLM이 해석했는지 규칙이 해석했는지. -
image_ref: 증빙 이미지가 있을 때만. presigned GET URL은 Image Snapshot Pipeline의 대시보드 조회 경로와 동일하다.
apps/dashboard-web의 ChatPage가 대화형 UI를 그린다.
- 추천 질문과 자유 입력(최대 500자)을 제공한다. 공장 selector("질문에서 식별" 포함)와 응답 모드 selector(자동/빠른 답변/정밀 분석)를 함께 보낸다.
- 응답 대기 동안 진행 단계(질문 해석 → 접근 범위 확인 → DynamoDB 조회 → S3 상세 확인 → 답변 정리)를 표시한다. 실제 단계 진행을 그대로 반영하는 것이 아니라 사용자 체감용 progress이다.
- 답변은 Markdown으로 렌더링하고, 그 아래 Evidence 패널에 증빙 이미지 / 확인된 값 / 추정 / 데이터 한계를 구분해 보여준다. 증빙 이미지는 presigned URL
<img>이며 클릭 시 원본을 새 탭으로 연다.
- 모든 요청은 Cognito JWT가 필요하다(
get_current_principal). - 공장/시스템 범위는 데이터 조회 이전에 강제되며, LLM이 선택한 대상도 재검증한다.
- 증빙 이미지 경로는 별도로
require_system_access를 통과해야 한다. presigned URL은 짧은 만료와 대상 object key로 제한되고, S3 객체에 public ACL을 부여하지 않는다. - 응답에 raw model id, 토큰, 전체 endpoint 주소 같은 민감 정보를 싣지 않는다.
- 쓰기 기능이 아니다. 채팅은 read model 조회만 하며 관제 데이터를 수정하지 않는다.
| 설정 | 질문 해석 | 답변 생성 |
|---|---|---|
| Bedrock 활성 + 라우팅 on | LLM(router="llm") |
LLM(generator="bedrock") |
| Bedrock 활성 + 라우팅 off | 규칙 파서(router="rule") |
LLM(generator="bedrock") |
| Bedrock 비활성 | 규칙 파서 | 규칙 템플릿(generator="rule") |
| LLM 호출 실패 | 규칙 파서로 fallback | 규칙 템플릿으로 fallback |
어느 모드에서도 RBAC 강제와 Evidence 구성 단계는 동일하다. LLM은 해석과 표현만 담당하고, 데이터 출처는 항상 Backend가 통제한다.
채팅은 두 가지 LLM 사용 지점을 가진다.
- Resolve: 질문에서 intent, 공장, 시간 범위를 구조화한다. ADR 0034 기준으로 Bedrock Converse tool-use를 사용하며, 실패하거나 비활성화되면 규칙 파서로 fallback한다.
- Explain: Backend가 만든 Evidence만 받아 사람이 읽기 좋은 답변을 만든다. ADR 0033 기준으로 fast/precise tier를 분리한다.
현재 docs 기준 모델 정책:
| 단계 | 기준 |
|---|---|
| Resolve | Claude Haiku 4.5 |
| Explain fast | Claude Haiku 4.5 |
| Explain precise | Claude Sonnet 4.6 |
/chat/query 응답은 tier label만 노출하고 raw model id는 노출하지 않는다.
관련 문서
- 시스템 아키텍처
- 제어 & 데이터 플레인
- Dashboard VPC 설계
- 하드웨어 배치
- Hub EKS 네임스페이스
- Tailscale Mesh VPN
- 데이터 생명주기
- 데이터 조회 모델
- 실시간 갱신 구조
- IoT 데이터 계약
- Reporting Pipeline
- 로컬 스토리지
- 클라우드 스토리지
- Edge Agent
- Edge AI 탐지
- Factory-A Log Adapter
- Dummy Sensor
- Edge IoT Publisher
- Lambda Data Processor
- Risk Normalizer
- Risk Score Engine
- Pipeline Status Aggregator
- Graph Aggregator 5m
- Cloud Infra Collector
- Daily Report Generator
- Risk Alert Dispatcher
- Image Snapshot Pipeline
- Dashboard Backend
- Dashboard Web
- AI 채팅 어시스턴트