반응형

샘플데이터베이스

postgresql용도 데이터베이스 샘플인 dvdrental 을 활용

DVDRental ERD

 

 

PostgreSQL Sample Database

This tutorial introduces you to a PostgreSQL sample database that you can use for learning and practicing with PostgreSQL.

neon.com

구현

Prompt

sqlTool 에 기능을 분류하여 agent가 테이블 스키마를 조회하고 테이블을 조죄할 수 있도록 했다.

그리고 잘못된 컬럼을 요청했을 때 자기 수정 규칙을 두어 최대 3번까지 수정을 재시도할 수 있다.

당신은 PostgreSQL 전문가입니다. 데이터베이스 이름은 'aidb'이며, DVD 대여 시스템입니다.

1. [탐색]: 질문에 관련된 테이블이 무엇인지 'listTables'로 확인합니다.
2. [분석]: 해당 테이블의 구조를 'describeTable'로 파악하여 정확한 컬럼명을 확인합니다.
3. [계획]: 위 정보를 바탕으로 쿼리 실행 순서를 계획합니다.
4. [실행]: 'executeSqlQuery'로 최종 데이터를 가져옵니다.                    

반드시 제공된 도구를 사용해 SQL을 실행한 후, 그 결과를 바탕으로 자연스럽게 답변하세요.

[자기 수정 규칙]
1. 'executeSqlQuery' 실행 결과 'SQL 에러 발생'이 포함되어 있다면, 에러 메시지를 분석하세요.
2. 잘못된 컬럼명이나 테이블명 때문이라면, 스키마를 추측하지 말고 information_schema를 조회하거나 쿼리를 수정하세요.
3. 최대 3번까지 수정을 시도할 수 있습니다.
4. 최종적으로 성공한 결과만 요약해서 사용자에게 전달하세요.

 

승인 Service

그리고 생성된 쿼리를 DB에 수행요청 하기 전에 사용자에게 승인을 위임한다.

사용자는 60sec 이내에 승인API를 전송해야한다.

approvalService.request(chatId, query).get(60, TimeUnit.SECONDS);

 

agent.service.ApprovalService.java

// AI가 호출: 승인 요청을 등록하고 UI에 알림
public CompletableFuture<Boolean> request(String chatId, String query) {
    String id = UUID.randomUUID().toString().substring(0, 8);// 60초 후 자동 만료되는 로직 추가 (Optional)
    CompletableFuture<Boolean> future = new CompletableFuture<Boolean>()
            .orTimeout(60, TimeUnit.SECONDS);
    pendingApprovals.put(id, future);
 // 1. DTO 객체 생성
    ApprovalRequest approvalRequest = ApprovalRequest.builder()
            .id(id)
            .query(query)
            .message("쿼리가 생성되어 사용자 승인을 기다립니다.")
            .requestedAt(LocalDateTime.now())
            .build();

    // ⭐️ 해당 ChatId에 연결된 Sink를 찾아 데이터 방출
    Sinks.Many<ApprovalRequest> sink = userSinks.get(chatId);
    if (sink != null) {
        Sinks.EmitResult result = sink.tryEmitNext(approvalRequest);
        log.info("📢 [백엔드] ChatId: {} 에게 승인 요청 전송 - ID: {}, 결과: {}", chatId, id, result);
    } else {
        log.warn("⚠️ ChatId: {} 에 대한 활성화된 구독자가 없습니다.", chatId);
        // 구독자가 없으면 즉시 실패 처리하거나 로직에 따라 조절
        future.complete(false);
    }        
    return future;
}

 

승인 요청 화면

채팅이 생성되면 클라이언트는 서버에 sse 구독을 해놓고,

서버가 sse를 전달하면 modal event가 발생되어 생성된 쿼리를 보여준다.

승인API

agent.web.ApprovalUiController.java

// 2. UI 버튼 클릭 시 호출
@PostMapping("/{id}/respond")
public Mono<ResponseEntity<String>> respond(@PathVariable("id") String id, 
        @RequestParam("approved") boolean approved) {
    return Mono.just(id)
        .publishOn(Schedulers.boundedElastic()) // 승인 처리를 별도 스레드에서 수행
        .map(requestId -> {
            approvalService.handleDecision(requestId, approved);
            return ResponseEntity.ok("Success");
        });
}

 

agent.web.ApprovalService.java

// 1. UI로 실시간 알림을 보내기 위한 통로 (SSE)
private final Map<String, Sinks.Many<ApprovalRequest>> userSinks = new ConcurrentHashMap<>();
// 2. 대기 중인 요청 저장소
private final Map<String, CompletableFuture<Boolean>> pendingApprovals = new ConcurrentHashMap<>();
// UI 버튼 클릭 시 호출: 승인 또는 취소
public void handleDecision(String id, boolean approved) {
    log.info("📥 [백엔드] 결정 수신 - ID: {}, 승인여부: {}", id, approved);
    CompletableFuture<Boolean> future = pendingApprovals.get(id);
    if (future != null) {
        future.complete(approved);
        pendingApprovals.remove(id); // 결정 완료 후 삭제
    } else {
        log.warn("⚠️ 이미 만료되었거나 존재하지 않는 승인 ID입니다: {}", id);
    }
}

상태를 complete로 만들어 중단되었던 쿼리를 수행한다.

 

검색해보기

이제 이런 검색을 해볼 수 있다!!

기초 조회

  • "영화(film) 테이블에서 상영 시간이 180분 이상인 영화 제목 5개만 알려줘.”
  • "특정 조건 + 리미트

통계/집계

  • "우리 서비스에 등록된 전체 고객(customer)은 총 몇 명이야?"
  • COUNT 함수 유도

조인(Join)

  • "가장 많이 대여(rental)된 영화 제목 TOP 3가 뭐야?"
  • film + inventory + rental 조인

수익 분석

  • "각 영화 카테고리별로 총 매출(payment) 합계를 계산해줘."
  • category + payment 집계

고객 분석

  • "이메일 주소가 'P'로 시작하는 고객들의 이름과 성을 나열해줘."
  • LIKE 패턴 검색

 

에이전트 협업

더 나아가 분석된 데이터를 수치화 할 수도 있다.

chartService 를 만들어 놨는데 "차트" 라는 단어가 질문에 포함되어있을 경우 sql+chart 두개의 Tool을 사용하도록 만들었다.

사용자 수 증가 추이 그래프
특정 영화 관람 건수 그래프
DVD 장르별 매출 순위

 

[Spring AI] 1편: 토이 프로젝트 개요 

[Spring AI] 2편: RAG 문서 임베딩

[Spring AI] 4편: MCP 서버 구동과 실행

 

GitHub - joonhyeok95/spring-ai-google-gen: 제미나이 무료API로 구현하는 PDF RAG, 데이터베이스 추출, LLM 서비

제미나이 무료API로 구현하는 PDF RAG, 데이터베이스 추출, LLM 서비스. Contribute to joonhyeok95/spring-ai-google-gen development by creating an account on GitHub.

github.com

 

반응형
복사했습니다!