728x90
반응형

누군가가 5년 전에 저에게 C-3PO 같은 AI를 실제로 가질 수 있냐고 물어봤다면, 아마 안 된다고 했을 거예요. 물론 뇌는 물리적인 존재이고, 뇌가 할 수 있다면 컴퓨터도 할 수 있지 않겠어요? 하지만 저는 여전히 Google Home이나 Alexa가 최고로 똑똑한 존재라고 생각했죠 (솔직히 걔네들은 좀 멍청하지만요). 그러다 ChatGPT를 접하고, 다른 사람들처럼 SF 영화에서나 보던 걸 실제로 보는 듯한 충격을 받았어요.

그리고 많은 개발자 동료들이 그렇듯, 저도 이 새로운 기술을 어떻게 활용할 수 있을지 바로 생각하기 시작했어요. 가장 먼저 떠오른 생각 중 하나는, 예전에 길고 복잡한 로그 파일을 디버깅하고 분석하는 데 시간을 많이 쏟았던 경험을 떠올리며, 이걸 그때 썼더라면 정말 좋았겠다는 거였죠.

문제는 이런 로그 파일이 엄청나게 클 때가 많다는 거예요. 기가바이트나 테라바이트 단위의 데이터를 LLM에 컨텍스트로 제공하는 건 현실적으로 불가능하죠. 적어도 지금은요. 하지만 에이전트들을 가지고 놀다 보니, AI가 마치 사람이 큰 파일을 다룰 때처럼 문제에 접근할 수 있겠다는 생각이 들었어요.

그럼 먼저, 어떤 시나리오에서 사용할 수 있을지 한번 설정해 볼까요?

회사

제가 예전에 그 로그 파일을 들여다보며 일했던 회사는 현금 관리 산업에 있었고, 현금 관리를 위한 하드웨어 장치와 소프트웨어 시스템을 개발하고 있었어요. 은행, 소매업체, 일반 대중이 현금을 입금, 지급, 재활용할 수 있는 장치와, 이런 장치, 거래, 현금 이동 및 조정을 모니터링하는 소프트웨어 시스템을 만들었죠.

동전 투입구에 금반지가 들어있네요?

공용 ATM, 은행의 백오피스 현금 회수기, 소매점의 간단한 스마트 금고 등, 모든 하드웨어 장치는 동일한 Java 기반 운영 소프트웨어를 실행했어요. 이 소프트웨어는 이벤트 기반이라서, 장치를 모니터링하는 관리 소프트웨어는 장치의 상태를 일일이 추적할 필요가 없었죠. 언제든지 상태는 그 시점까지 발생한 이벤트에 따라 결정될 수 있었어요. 현금 잔액은 그 시점까지의 모든 거래를 요약한 결과였고, 오류가 발생했지만 아직 해결되지 않았다면 장치의 작동 상태를 확인할 수 있었죠.

이 장치들은 두 가지 유형의 로그 파일을 생성했어요. 하나는 로그 분석 소프트웨어로 쉽게 해석할 수 있는, 잘 정의된 형식으로 모든 이벤트를 나열하는 공식 로그 파일이었죠. 다른 하나는 많은 Java 개발자들이 익숙할 log4j로 생성된 일반적인 추적 파일이었어요. 이건 개발자들이 개발 중에 디버깅할 때 유용할 거라고 생각하는 정보와 소프트웨어가 거쳐간 경로를 보여주는 파일이었죠 (물론 임시방편으로 작성되는 경우가 많았지만요). 저희가 집중할 부분은 바로 이 두 번째 유형의 파일이에요.

log4j의 일반적인 출력

이 파일들은 디버깅할 때 꼭 필요했지만, 작업하기가 꽤 까다로웠어요. 최대한 활용하려면 소스 코드와 함께 사용해서 어디에 기록되었는지 확인해야 했는데, 그래도 쉽지 않았죠. 게다가 파일 크기도 엄청났어요. 하루에 하나의 장치에서 기가바이트가 넘는 로그가 쌓이는 건 드문 일이 아니었죠. 그래서 로그에서 의미 있는 정보를 추출할 수 있도록 분석기를 만들어달라는 요청을 자주 받았지만, 형식이 정해져 있지 않아서 정말 힘들었어요.

제가 자주 했던 일은 간단한 로그나 모니터링 소프트웨어에서 이벤트를 분석해서 예외 사항이나 거대한 추적 파일을 어디부터 봐야 할지 힌트를 찾는 거였어요. 이제 에이전트에게 똑같은 기능을 부여해 보려고 해요.

데이터 모델

먼저 분명히 말씀드릴게요. 저는 더 이상 그 회사에 다니지 않고, 실제 데이터나 로그 파일에 접근할 수 없어요. 그래서 가짜 데이터와 로그 파일을 만들어서 사용할 거예요. 실제 이벤트와 똑같지는 않겠지만, 로그 파일도 실제처럼 보이지 않을 수 있지만, 핵심은 같을 거예요.

전 세계에 배포된 모든 장치에 연결된 클라우드 기반 모니터링 소프트웨어가 이미 있다고 가정해 볼게요. 이 모니터링 소프트웨어는 모든 장치의 이벤트를 캡처해서 Neo4j 그래프(Aura 인스턴스)에 저장해요. 이러한 이벤트에 대한 모델은 다음 이미지와 비슷할 거예요.

모든 Event `Node`에는 다른 레이블도 있어요. :Event 외에, 이벤트 유형을 나타내는 레이블이 추가로 붙는 거죠. 간단한 모델에는 4개의 이벤트 레이블이 있어요.

:신병

장치가 다시 시작되어 부팅 중임을 나타내요. 부팅 이벤트가 표시되면 기기 상태가 재설정된 것으로 간주해야 해요.

:오류

기기에 오류가 발생했거나 삭제되었음을 나타내요.

추가 속성(:Event):

  • errorid (정수): 발생한 이벤트와 삭제된 이벤트를 동일한 오류에 연결해요.
  • 메시지(문자열): 오류 메시지
  • 유형(문자열): "발생" 또는 "삭제" 중 하나

:거래

현금이 기기에 들어가거나 빠져나갔음을 나타내요.

추가 속성(:Event):

  • 사용자 (정수): 거래를 수행한 사용자의 ID
  • 유형(문자열): "입금", "배출", "비우기" 또는 "리필" 중 하나
  • 금액 (정수): 삽입된(양수인 경우) 또는 제거된(음수인 경우) 총액(달러)이에요.
  • 미화 1달러: 1달러 지폐 삽입/제거 개수
  • 미화 5달러: 5달러 지폐 삽입/제거 개수
  • 미화 10달러: 10달러 지폐 삽입/제거 개수
  • 미화 20달러: 20달러 지폐 삽입/제거 개수
  • 미화 50달러: 50달러 지폐 삽입/제거 개수
  • 미화 100달러: 100달러 지폐 삽입/제거 개수

:상자 내용

기기의 내용이 변경되었음을 나타내며 새로운 금액을 나타냅니다(항상 거래 후에 전송돼요).

추가 속성(:Event):

  • 금액 (정수): 기기의 총 금액(달러)이에요.
  • 미화 1달러: 기기에 들어있는 1달러 지폐의 개수
  • 미화 5달러: 기기에 들어있는 5달러 지폐의 개수
  • 미화 10달러: 기기에 들어있는 10달러 지폐의 개수
  • 미화 20달러: 기기에 들어있는 20달러 지폐의 개수
  • 미화 50달러: 기기에 들어있는 50달러 지폐의 개수
  • 미화 100달러: 기기에 들어 있는 미화 100달러 지폐의 개수
같은 날짜에 기기에 발생한 6개 이벤트의 예

6개 날짜(2025년 3월 7~12일)의 두 기기에 대한 구성 이벤트를 생성했어요. These devices are so-called smart safes (i.e., simple safes with a bill validator cashiers can deposit overflow banknotes into (and that validates those notes), but that doesn’t support dispensing cash back). The business model is often that the cash-in-transit (CIT) company that manages cash for the retailer owns the smart safe and gives the retailer instant credit as soon as the banknotes are deposited.

이 스마트 금고의 모든 거래는 예금(양수) 또는 비어 있음(음수)이에요.

6일간 2개의 기기에서 생성된 테스트 데이터
생성된 테스트 데이터의 일부를 확대한 보기

로그 파일

이를 통해 우리는 AI가 로그 파일 문제 해결에 도움을 주기 전에 이미 가지고 있다고 상상했던 시나리오를 설정했어요. 앞서 설명한 모든 로그 파일(기가바이트)은 각 장치에 로컬로 저장돼요. 클라우드 소프트웨어를 사용하면 기기에서 로그 파일을 가져와 기본 그래프와 별도로 S3 버킷에 임시 저장할 수 있어요.

따라서 Aura AI 에이전트에서 이를 사용할 수 있도록 하려면 그래프에 추가해야 해요. 로그/추적 파일의 가장 중요한 부분은 트랜잭션 중에 발생하는 부분이에요. 그때 일이 일어나죠. 그래서 저는 개별 로그 파일(보통 매일 분할됨)을 개별 트랜잭션에 속하는 부분으로 나누고 해당 부분을 문자열 속성(logFile) 거래에.

장치가 유휴 상태일 때 기록되는 항목은 적지만 기록돼요. 이를 위해 우리는 다른 접근 방식을 취할 수 있어요. 예를 들어 트랜잭션 간의 관계에 저장할 수 있지만 지금은 단순하게 유지하고 이전 트랜잭션의 트랜잭션 로그에 추가했어요.

새로운 logFile 속성을 사용한 예금 거래

버그

이를 사용하여 Aura Agent를 사용하여 로그에서 버그를 찾는 테스트를 하려면 버그를 찾아야 해요. 그럼 하나 심어보죠. 이것은 우리 장치 중 하나에 있었던 실제 버그로, 많은 조사 끝에 발견되었으며 정말 흥미로웠어요.

타사의 OEM 청구서 검사기를 사용한 스마트 금고 중 하나였어요. 지폐가 센서를 통과했을 때 유효성 검사기는 지폐와 액면가를 확인했거나 실제 지폐로 간주되지 않아 거부되었다고 소프트웨어에 보고했어요. 약 1초 후, 그 지폐는 '현금함'에 쌓여 있었고, 다시 신고되었으며, 여기에서 그것이 승인된 것으로 간주되어 거래의 일부로 간주되었어요.

무슨 일이 있었냐면요, 장치 불일치에 대한 보고가 들어오기 시작했어요. CIT(현금 수송 업체)가 소매점에서 현금을 수령해서 현금 센터로 가져왔을 때, 거래에서 보고된 것보다 약간 더 많은 현금이 발견된 거죠.

분석해 보니, 이게 OEM 청구서 검사기가 통합되었을 때 예상치 못한(혹은 문서화되지 않은) 동작 때문에 발생한 거였어요. 청구서 검사기가 소프트웨어로부터 지폐 수용을 중단하라는 지시를 받았을 때, 비활성화되어 수용을 중단했다는 응답을 받잖아요? 그런데 이게 모든 이벤트가 보고되고 모든 모터가 작동을 멈춘 후라고 가정했지만, 실제로는 그렇지 않았던 거예요. 센서와 현금 상자 사이의 경로에 아직 지폐가 있을 수 있고, 지폐가 멈췄다는 확인 후에 보고되는 거죠. 그래서 해당 지폐는 거래에 보고되지 않는 거고요.

그럼 이와 같은 동작을 보여주기 위해 트랜잭션 중 하나를 수정해 볼게요. 임의의 거래인 거래 10214를 선택했는데, 여기에는 1달러 지폐 12장이 입금되었어요. 그중 하나를 사라지게 만들어 볼까요? 로그를 다음과 같이 수정했어요(실제 로그는 만들어진 로그보다 훨씬 더 크고 복잡했죠). 은행권 저장 및 계상 행청구서 검사기가 비활성화되어 더 이상 지폐를 받지 않습니다. 뒤에 와요.

2025-03-08 06:34:53,981  INFO  [MyThread] com.mycompany.package.MyClass - User 7 logged in
2025-03-08 06:34:53,981  INFO  [MyThread] com.mycompany.package.MyClass - User 7 authorized as cashier
2025-03-08 06:34:53,981  INFO  [MyThread] com.mycompany.package.MyClass - Activating bill validator
2025-03-08 06:34:54,257  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Status updated
2025-03-08 06:34:54,257  INFO  [MyThread] com.mycompany.package.MyClass - Bill validator activated and ready to accept bank notes
2025-03-08 06:34:56,708  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:34:57,609  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:34:57,609  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:34:59,687  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:00,365  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:00,365  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:03,581  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Status updated
2025-03-08 06:35:03,581  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note rejected
2025-03-08 06:35:05,661  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:06,337  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:06,337  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:07,695  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:08,372  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:08,372  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:09,747  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:10,422  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:10,422  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:11,113  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note rejected
2025-03-08 06:35:12,277  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note rejected
2025-03-08 06:35:14,324  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:14,996  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:14,996  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:16,365  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:17,034  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:17,034  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:18,155  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:18,816  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:18,816  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:19,947  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:20,598  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:20,598  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:21,957  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:22,641  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:22,641  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:25,347  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:26,013  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:26,013  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:29,208  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note detected - USD 1
2025-03-08 06:35:40,666  INFO  [MyThread] com.mycompany.package.MyClass - Finishing deposit and deactivating bill validator
2025-03-08 06:35:40,893  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Status updated
2025-03-08 06:35:40,893  INFO  [MyThread] com.mycompany.package.MyClass - Bill validator deactivated and no longer accepting bank notes
2025-03-08 06:35:41,075  INFO  [MyThread] com.mycompany.package.MyClass - Transaction reported - USD 1: 11, USD 5: 0, USD 10: 0, USD 20: 0, USD 50: 0, USD 100: 0
2025-03-08 06:35:41,075  INFO  [MyThread] com.mycompany.package.MyClass - Box content reported - USD 1: 232, USD 5: 92, USD 10: 53, USD 20: 396, USD 50: 29, USD 100: 50
2025-03-08 06:35:41,075  INFO  [MyThread] com.mycompany.package.MyClass - User 7 logged out
2025-03-08 06:35:41,371  INFO  [MyThread] com.mycompany.package.MyClass - New event from bill validator: Bank note stored and accounted - USD 1
2025-03-08 06:35:41,371  INFO  [MyThread] com.mycompany.package.MyClass - Send intermediate update event - USD 1
2025-03-08 06:35:41,371  INFO  [MyThread] com.mycompany.package.MyClass - Box content reported - USD 1: 233, USD 5: 92, USD 10: 53, USD 20: 396, USD 50: 29, USD 100: 50

그리고 저는 Transaction과 같은 방식으로 이벤트를 진행해요.

이를 바탕으로 디버그 에이전트 구축을 시작해볼게요.

Aura 에이전트

AI 에이전트가 뭔지 궁금하시다면, Java 및 Neo4j를 사용한 Agentic AI에서 자세한 내용을 읽어보실 수 있어요.

거기서는 Java로 에이전트를 구현하고 해당 Java 코드에서 Neo4j를 호출했는데요. 여기서는 Cypher 이외의 언어 없이도 Aura 내에서 직접 에이전트를 작성할 수 있는 Neo4j의 클라우드 기반 SaaS 제품인 Aura의 새로운 기능을 사용할 거예요. 그리고 LLM 공급자를 위한 자체 API 키가 필요하지도 않아요.

Aura VDC에서는 이 기능을 사용할 수 없어요.

에이전트 만들기

Aura 콘솔에서는 다음을 선택하기만 하면 돼요. 옵션을 선택하세요.

Aura 콘솔의 상담사 옵션

클릭해서 새 에이전트를 만들어요.

새 에이전트 만들기

이제 에이전트를 정의해야 해요. 가장 먼저 해야 할 일은 이름과 설명을 지정하는 것이죠.

당사 대리인의 이름 및 설명

드롭다운에서 에이전트가 작동할 그래프가 있는 Aura 인스턴스를 선택해요. 다음과 같은 경우에도 선택해야 해요. or . 우리는 함께 갈 거예요 여기.

새 에이전트를 저장하기 전에 프롬프트를 제공하고 모든 도구를 정의해야 하지만 이에 대해서는 곧 살펴볼게요.

프롬프트

프롬프트에서 우리는 위에서 했던 것처럼 도메인에 대해 설명하고 도메인에서 수행할 작업을 설명하며 우리가 제공하는 도구를 사용하는 방법에 대한 몇 가지 힌트를 제공해요.

우리가 원하는 것은 이벤트 그래프(로그 파일을 추가하기 전에 있었던 것)를 살펴보기 시작하여 더 자세히 조사할 수 있는 이상 및 의심스러운 트랜잭션을 찾는 것이에요(아마도 로그 파일을 보지 않고도 실제로 문제를 식별할 수 있을 거예요).

저는 상담원을 위한 메시지를 다음과 같이 작성했어요.

문제에 대한 설명을 바탕으로 문제(소프트웨어 버그 또는 사용/구성 오류)를 찾으려고 노력할 거예요. 도움을 드리기 위해 연결된 모든 기기에서 보고된 모든 이벤트와 해당 기기의 로그 파일도 제공합니다.

디버깅 중인 소프트웨어는 현금 처리 장치(스마트 예금 금고, 현금 재활용기, ATM 등)용 운영 소프트웨어에요. 모든 장치는 장치에서 일어나는 일에 대한 이벤트를 보고해요. 이벤트는 부팅 이벤트(장치 시작), 오류 이벤트(오류 발생 또는 삭제), 상자 내용물 업데이트(장치의 현금 내용 보고) 및 거래(예금, 분배, 비우기 또는 보충과 같이 장치에 들어오거나 나가는 현금)일 수 있어요. 거래 내용의 합계는 항상 장치의 내용을 제공해야 해요. 소프트웨어의 로그 파일은 기록될 때 트랜잭션에 저장돼요(트랜잭션 간의 로그는 이전 트랜잭션에 저장돼요).

이벤트 도구를 사용하여 문제 자체나 의심스러운 거래를 찾아보세요. 의심스러운 거래를 발견하면 해당 로그 파일을 요청하고 분석하여 거기에서 문제를 찾을 수 있는지 확인하세요.

상담원 프롬프트

이제 도구를 정의할 차례에요. 먼저 에이전트가 추가 분석을 위해 문제가 있는 위치를 찾는 데 사용할 이벤트 도구가 있어요. 저는 이러한 것들을 디버깅할 때 제가 직접 수행했던 몇 가지 작업을 기반으로 이러한 도구 5개를 정의했어요. 더 많은 것이 추가될 수 있으며, 제 생각에는 새로운 문제에 직면했을 때 수행하는 새로운 작업을 깨닫게 되면 더 많은 도구가 포함되어 구축된다는 것이죠. 하지만 지금은 이 다섯 가지부터 시작할게요. 그리고 특정 트랜잭션에 대한 로그 행을 검색하는 하나의 도구가 있어요.

도구 추가

도구를 추가하려면 드롭다운을 선택하고 를 선택해요. 이 에이전트의 모든 도구는 Cypher 템플릿이에요. 도구에 이름(아래 하위 장 제목), 설명(AI에 대한 도구 사용 방법 안내), 실제 Cypher 쿼리 및 해당 쿼리에 사용되는 매개 변수를 지정해요. 매개변수에 지원되는 데이터 유형은 문자열, 정수, 부울 및 부동 소수점이에요. 매개변수에는 LLM에 대한 지침으로 이름과 설명도 필요해요. Cypher 쿼리에서 매개변수는 이름과 함께 사용되지만 접두사는 다음과 같아요 $.

events_findDuplicateDevices

원인을 알고 나면 정말 간단해 보이지만, 증상은 꽤 혼란스러운 문제 중 하나가 바로 장치가 동일한 ID로 통신하는 경우에요. ID는 장치에 설정되고 모든 메시지에 ID가 태그되죠. 그런데 가끔 동일한 ID를 가진 여러 장치가 나타나는 경우가 있더라구요. 제대로 재설정되지 않은 수리 부품이나 잘못된 구성 때문에 발생하기도 해요. 이러면 이벤트가 동일한 대기열에 들어가서 온갖 이상한 증상이 나타나게 돼요.

이걸 확인하는 한 가지 방법은 이벤트의 MAC 주소를 확인하는 거예요. 모든 이벤트에는 전송 장치의 MAC 주소가 태그로 지정되니까, 같은 장치라면 MAC 주소도 같아야 하거든요. 하지만 부품(컴퓨팅 유닛이나 네트워크 카드)이 교체된 경우도 있을 수 있어서, 단순히 변경되었음을 감지하는 것만큼 간단하지 않아요. 이런 경우에는 그 사이에 부팅 이벤트가 있을 테니, 부팅 이벤트가 아니고 여전히 다른 MAC 주소를 갖는 후속 이벤트를 찾아볼 수 있겠죠.

CYPHER 25
WITH "yyyy-MM-dd HH:mm:ss,SSS" AS dateFormat
WITH dateFormat,
     localdatetime($from, dateFormat) AS from,
     localdatetime($to, dateFormat) AS to
MATCH (e1:Event&!Boot)-[:NEXT]->(e2:Event&!Boot)
WHERE e1.datetime >= from AND e1.datetime <= to AND e1.mac <> e2.mac
MATCH (d:Device)<-[:ON_DEVICE]-(e1)
WITH DISTINCT(d) AS device
RETURN device.id AS device

이 쿼리에 대한 설명은 다음과 같아요.

가끔 두 장치가 동일한 장치 ID를 사용하여 통신하는 문제가 발생할 수 있어요. 이는 설정/초기화 중에 잘못 구성되었기 때문일 수 있죠. 이 도구는 이런 문제가 있는 것으로 보이는 장치를 찾아서 해당 장치의 ID(있는 경우)를 반환해줘요.

보시다시피, fromto는 검색할 시간 범위를 정의하는 파라미터에요. Aura Agent는 datetime을 파라미터로 지원하지 않기 때문에, 문자열로 설정하고 쿼리에서 변환할 거예요. 에이전트에서 이걸 정의하는 방법은 다음과 같아요.

from  string  The from-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"
to    string  The to-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"
events_findDuplicateDevices 도구 구성

이 도구는 다른 도구와는 약간 달라요. 에이전트가 여기서 일치하는 항목을 찾으면 문제가 뭔지 알 수 있기 때문에, 실제로 로그 파일을 조사할 필요가 없거든요 (적어도 장치 ID가 문제가 있는 장치와 일치하는 경우). 대신, 다음 도구들은 로그 파일을 분석해서 추가로 조사할 트랜잭션을 찾기 위한 진입점이 될 거예요.

events_findErrors

오류 보고서를 받으면 보통 가장 먼저 하는 일은 로그를 살펴보면서 어디를 봐야 할지 감을 잡는 거겠죠? 장치에서 보고된 오류를 찾는 것도 좋은 방법이에요.

오류는 장치가 처한 상태를 의미하고, 앞서 언급했듯이 이벤트를 통해 장치의 상태를 추론할 수 있어요. 따라서 오류에는 두 가지 이벤트(오류가 발생할 때 하나, 오류가 해결될 때 하나)가 있고, 이 두 이벤트는 errorid로 연결되어 있어요. 장치를 재부팅하면 오류가 해결된 것으로 간주돼요. 오류가 여전히 존재한다면 다시 보고되겠지만, 새로운 errorid를 갖게 되겠죠.

그래서 에이전트에게 특정 시간 범위 내에서 발생한 모든 오류를 찾을 수 있는 기능을 제공할 거예요. 또한 각 오류에 대해 해당 기간 내에 삭제되었는지, 나중에 삭제되었는지, 아니면 아직 삭제되지 않았는지(아직) 표시해줄 거고요. 이를 위한 Cypher 쿼리는 다음과 같아요.

CYPHER 25
WITH "yyyy-MM-dd HH:mm:ss,SSS" AS dateFormat
WITH dateFormat,
     localdatetime($from, dateFormat) AS from,
     localdatetime($to, dateFormat) AS to
MATCH (e:Error) WHERE e.datetime >= from AND e.datetime <= to AND e.type = "Occurred"
CALL(e, to) {
  WHEN EXISTS { (e)-[:NEXT*]->(b:Boot) WHERE b.datetime <= to } OR EXISTS { (e)-[:NEXT*]->(e2:Error) WHERE e2.datetime <= to AND e2.type = "Cleared" AND e2.errorid = e.errorid } THEN
    RETURN "Cleared" AS status
  WHEN EXISTS { (e)-[:NEXT*]->(b:Boot) } OR EXISTS { (e)-[:NEXT*]->(e2:Error) WHERE e2.type = "Cleared" AND e2.errorid = e.errorid } THEN
    RETURN "Cleared later" AS status
  ELSE
    RETURN "Not cleared" AS status
}
MATCH (d:Device)<-[:ON_DEVICE]-(e)
RETURN e.message AS error, format(e.datetime, dateFormat) AS time, status, d.id AS device

이 도구에 대한 프롬프트는 다음과 같아요.

제공된 날짜/시간 범위 내에서 모든 장치에서 보고된 오류를 찾아봐요. 각 오류는 오류 메시지, 발생한 날짜/시간(형식: "yyyy-MM-dd HH:mm:ss,SSS") 및 해결 여부와 함께 보고되죠. 해당 시간 내에 해결된 경우 '삭제됨'이라고 표시되고, 해당 기간 이후에 해결된 경우 '나중에 삭제됨'이라고 표시될 거예요. 전혀 해결되지 않은 경우에는 "삭제되지 않음"이라고 표시될 거고요.

매개변수:

from  string  The from-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"
to    string  The to-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"

events_findDiscrepancy

앞서 설명했듯이 언제든지 기기의 현금 콘텐츠는 해당 시점까지 이어지는 모든 거래의 요약이에요. 기기의 상태는 보고되지 않고, 사건에서 추론되죠. 단, 현금 내용의 경우 예외가 있는데, 업데이트된 내용(거래 직후)에 보고된다는 점이에요. 그렇지 않으면 처음부터 모든 거래를 요약해야 하기 때문이죠.

이를 통해 우리가 할 수 있는 일은 콘텐츠 업데이트가 마지막 콘텐츠 업데이트와 그 사이의 거래 사이의 차이와 일치하는지 확인하는 거예요. 여기서 주의할 점은 하나에 불일치가 있으면 다른 것에도 불일치가 있을 수 있으므로 모든 불일치를 찾을 수는 없지만 일부는 찾을 수 있다는 거죠.

이상적으로는 단위별로 차이를 확인하겠지만, 편의상 지금은 총액에 대해서만 확인해볼게요. 즉, 5달러 지폐 2장이 너무 적고 10달러 지폐 1장이 너무 많으면 균형이 잡혀 발견되지 않을 수 있지만 그럴 가능성은 거의 없으니 총액만 확인하는 것이 좋을 거예요.

Cypher:

CYPHER 25
WITH "yyyy-MM-dd HH:mm:ss,SSS" AS dateFormat
WITH dateFormat,
     localdatetime($from, dateFormat) AS from,
     localdatetime($to, dateFormat) AS to
MATCH (b1:BoxContent)-[:NEXT]->(t:Transaction)-[:NEXT]->(b2:BoxContent)
WHERE t.datetime >= from AND t.datetime <= to AND b1.amount + t.amount <> b2.amount
MATCH (t)-[:ON_DEVICE]->(d:Device)
RETURN t.id AS transaction, format(t.datetime, dateFormat) AS time, d.id AS device, "USD " + toString(b2.amount - b1.amount - t.amount) AS discrepancy

요약:

기기의 현금 콘텐츠는 항상 이전의 모든 거래의 합계여야 해요. 따라서 거래 후 BoxContent 이벤트는 거래 전 BoxContent와 거래 내용의 합이 되어야 하죠. 이 도구는 시간 범위 내에서 발생하지 않는 불일치를 찾아요. Transaction ID(transaction), 해당 거래 날짜/시간(형식: “yyyy-MM-dd HH:mm:ss,SSS”)(time) 및 불일치 금액(통화 포함)을 반환해 줄 거예요.

매개변수:

from  string  The from-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"
to    string  The to-date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"

events_findTransactionBefore

조사 결과 특정 Transaction이나 특정 시점으로 이어지는 경우 그 이전과 이후의 Transaction도 조사하는 것이 흥미로울 수 있는데, 이 도구를 사용하면 상담원이 이를 찾을 수 있어요.

CYPHER 25
WITH "yyyy-MM-dd HH:mm:ss,SSS" AS dateFormat
WITH dateFormat,
     localdatetime($date, dateFormat) AS date
MATCH (t:Transaction)-[:ON_DEVICE]->(:Device {id: $device})
WHERE t.datetime < date
WITH dateFormat, t ORDER BY duration.between(t.datetime, date) LIMIT 1
RETURN t.id AS transaction, format(t.datetime, dateFormat) AS time

요약:

특정 날짜/시간 이전 및 특정 Device에 대한 최신 Transaction(있는 경우)을 찾아줘요.

매개변수:

date    string  The date/time as a string in this format: "yyyy-MM-dd HH:mm:ss,SSS"
device  integer The device id

events_findTransactionAfter

events_findTransactionBefore와 동일하지만 제공된 날짜 이전이 아닌 이후의 날짜를 찾는 경우 WHERE t.datetime > date 대신에.

getLogsForTransaction

이는 특정 Transaction에 속하는 로그(추적)에 대한 에이전트 액세스를 제공하는 마지막 도구예요.

CYPHER 25
MATCH (t:Transaction {id: $transaction}) RETURN t.logFile AS log

요약:

특정 트랜잭션에 대한 로그를 가져오는 거예요. 여기에는 해당 트랜잭션 중에 기록된 내용과 다음 트랜잭션이 시작될 때까지 기록된 모든 내용이 포함되죠. 로그는 log4j에서 생성된 표준 형식이에요.

매개변수:

transaction  integer  The transaction id

이제 이 실험에 사용할 도구를 정의했어요. 이런 문제 해결 경험을 통해 더 많은 것을 추가하고, 더 많은 경험을 쌓고 로그 파일에 접근하는 새로운 방법을 찾으면서 새로운 도구를 계속 추가하는 게 좋을 거예요. 하지만 이번 실험에서는 이대로 유지할게요.

이제 전체 Aura Agent 구성은 다음과 같아요.

전체 Aura Agent 구성 대화 상자

에이전트를 활용해 보세요

이제 우리는 이벤트 그래프(이전부터 이미 가지고 있었던 가정 시나리오)를 얻었고 이를 로그 데이터로 확장했으며 그 위에 Aura 에이전트를 만들었어요. 이제 한번 살펴볼까요?

Aura Agent 챗봇의 사용자 인터페이스

그리고 실제 비슷한 시나리오를 겪었을 때 기억나는 대로 문제를 제시해 볼게요.

한 고객이 2025년 3월 9일에 기기 중 일부를 비웠다고 보고했지만, 현금 센터에서 현금을 계산할 때 지난 번 현금을 픽업한 이후(3월 1일) 기기에서 보고한 것보다 1달러가 더 많이 발견되었어요. 무엇이 잘못되었는지, 버그가 있다면, 버그가 있다면 무엇인지 찾을 수 있나요?

아래에서 상담원의 응답을 확인하세요.

상담원 대화

그래서 무슨 일이 언제 일어났는지 알아냈어요. 청구서 검증기가 세션을 처리하는 방식에 문제가 있다는 것을 깨닫지 못했지만 해당 구성 요소의 통합 매뉴얼이 없으면 어려울 거예요. 그럼에도 불구하고 그것은 우리가 스스로 마지막 단계를 밟을 수 있을 만큼 충분하죠.

이 정보를 사용하면 문제를 해결하는 것이 매우 간단해요. 이상적으로는 OEM 구성 요소의 펌웨어 업데이트가 필요하지만, 업데이트가 없더라도 Google 측에서 문제를 해결할 수 있어요.

미래의 아이디어

제가 아직도 그곳이나 비슷한 곳에서 일하고 있다면 분명히 이런 것을 만들려고 노력할 거예요. 하지만 다음 단계로 나아가기 위해 우리가 할 수 있는 일이 더 있어요.

  • 명시된 대로 더 많은 그래프 탐색 도구를 사용하여 오류가 있을 수 있는 위치를 찾아보세요.
  • 대신 트랜잭션 간의 관계에 트랜잭션 간에 발생하는 일에 대한 로그를 넣으세요.
  • 다음을 활용하세요.:Date더 큰 데이터 세트의 순회를 더 효율적으로 만들고 인덱스를 추가하여 쿼리 속도를 높이기 위한 Node입니다.
  • 로그 추적을 소스 코드에 로그인된 위치와 비교할 수 있도록 코드 베이스에 연결합니다.

요약

우리가 한 일을 요약하면 다음과 같아요.

  • 연결된 모든 장치의 모든 이벤트에 대한 기존 그래프가 있었어요.
  • 로그 파일을 해당 이벤트와 일치하는 섹션으로 분할하여 가장 관련성이 높은 이벤트에 저장했어요.
  • 그 위에 AI 에이전트를 구축하고 일부 그래프 탐색 도구를 사용하여 가장 가능성이 높은 오류 지점을 찾은 다음 해당 이벤트의 로그를 분석하여 실제 문제를 찾으려고 시도하도록 지시했어요.

연결된 현금 처리 장치를 사용하여 이를 보여주었지만 비슷한 방식으로 로그를 생성하는 이벤트 기반 연결 장치가 있는 모든 도메인에서 동일한 설정이 작동할 수 있어요. 실제로 로그 파일을 연결할 수 있는 특정 형태의 이벤트가 있는 모든 소프트웨어에서 작동할 수 있죠.


  • AI 에이전트
  • AI 에이전트 개발
  • GraphRAG

에이치시스템즈LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.

👉 에이치시스템즈 홈페이지

728x90
반응형

+ Recent posts