AI 에이전트 (Layer 2): - GONGSA: 공사 담당 (공정 브리핑, 공기 지연 감지, 날씨 연동 작업 조정) - PUMJIL: 품질 담당 (시공 전 체크리스트, Vision 보조 판독, 시험 기한 추적) - ANJEON: 안전 담당 (위험 공정 경보, TBM 생성, 중대재해처벌법 Q&A) - GUMU: 공무 담당 (인허가 능동 추적, 기성청구 제안, 보고서 초안) - 에이전트 라우터 (키워드 기반 자동 분배), 아침 브리핑 엔드포인트 EVMS 기본: - PV·EV·AC·SPI·CPI 산출 (WBS/Task 기반) - EAC·ETC 예측, 스냅샷 이력 저장 Vision AI: - Level 1: 현장 사진 분류 (Claude Vision), 작업일보 자동 첨부 - Level 2: 안전장비(안전모/조끼) 착용 감지 Geofence 위험구역: - 구역 CRUD (굴착면, 크레인 반경, 밀폐공간 등) - 진입 이벤트 웹훅 (익명 — 개인 이동 경로 비수집) 인허가 자동도출: - 공종 입력 → AI가 필요 인허가 목록 자동 도출 + 체크리스트 생성 DB 마이그레이션 (002): - agent_conversations, agent_messages, evms_snapshots, geofence_zones Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.8 KiB
Python
47 lines
1.8 KiB
Python
"""
|
|
에이전트 라우터
|
|
사용자 메시지의 의도를 파악하여 적절한 에이전트로 분배합니다.
|
|
"""
|
|
from app.models.agent import AgentType
|
|
from .gongsa import gongsa_agent
|
|
from .pumjil import pumjil_agent
|
|
from .anjeon import anjeon_agent
|
|
from .gumu import gumu_agent
|
|
from .base import BaseAgent
|
|
|
|
# 에이전트 레지스트리
|
|
AGENTS: dict[AgentType, BaseAgent] = {
|
|
AgentType.GONGSA: gongsa_agent,
|
|
AgentType.PUMJIL: pumjil_agent,
|
|
AgentType.ANJEON: anjeon_agent,
|
|
AgentType.GUMU: gumu_agent,
|
|
}
|
|
|
|
# 키워드 기반 자동 라우팅
|
|
_ROUTING_RULES: list[tuple[list[str], AgentType]] = [
|
|
# 공사/공정
|
|
(["공정", "일정", "지연", "타설", "굴착", "공기", "브리핑", "작업", "일보", "진도"], AgentType.GONGSA),
|
|
# 품질
|
|
(["품질", "시험", "검사", "슬럼프", "압축강도", "합격", "불합격", "KCS", "시방서", "체크리스트"], AgentType.PUMJIL),
|
|
# 안전
|
|
(["안전", "사고", "위험", "TBM", "교육", "중대재해", "보호구", "추락", "굴착 안전", "Geofence", "지오펜스"], AgentType.ANJEON),
|
|
# 공무
|
|
(["인허가", "허가", "신고", "기성", "보고서", "발주처", "행정", "서류", "청구"], AgentType.GUMU),
|
|
]
|
|
|
|
|
|
def route_by_keyword(message: str) -> AgentType:
|
|
"""키워드 매칭으로 적절한 에이전트 타입을 반환. 매칭 없으면 GONGSA."""
|
|
msg_lower = message.lower()
|
|
scores: dict[AgentType, int] = {t: 0 for t in AgentType}
|
|
for keywords, agent_type in _ROUTING_RULES:
|
|
for kw in keywords:
|
|
if kw in msg_lower:
|
|
scores[agent_type] += 1
|
|
best = max(scores, key=lambda t: scores[t])
|
|
return best if scores[best] > 0 else AgentType.GONGSA
|
|
|
|
|
|
def get_agent(agent_type: AgentType) -> BaseAgent:
|
|
return AGENTS[agent_type]
|