Skip to content

Spring AI 도입 #161

@mjkhub

Description

@mjkhub

배경

    @Override
    public String generate(Elder elder, ElderHealthInfo info,
                           List<Disease> diseases, List<MedicationSchedule> medicationSchedules) {

        String elderName = elder.getName();

        //TODO: "당뇨"로 찾아도 괜찮을지
        boolean hasDiabetes = diseases.stream()
                .anyMatch(d -> d.getName().contains("당뇨"));

        // 아침 복약명 추출 (scheduleTime: "morning")
        List<String> morningMedications = medicationSchedules.stream()
                .filter(ms -> ms.getScheduleTime() == MedicationScheduleTime.MORNING)
                .map(MedicationSchedule::getName)
                .toList();

        String morningMedNames = morningMedications.isEmpty()
                ? "등록된 아침 복약 없음"
                : String.join(", ", morningMedications);

        String diabetesLine = hasDiabetes
                ? "4. 혈당 여부 (당뇨병이 있는 경우에만): 혈당 재셨는지, 공복/식후 여부, 수치\n" : "";

        String diabetesFlow = hasDiabetes
                ? """
        AI: [공감] + "혈당도 재보셨을까요? 공복에 재셨어요, 식후에 재셨어요? 수치는 몇 나왔는지 기억나세요?"
        어르신: [혈당 응답]
        AI: [수치 반응 및 간단한 조언] + "좋아요 어르신, 오늘 하루도 건강하게 보내시고요, 나중에 또 연락드릴게요~"
        """
                : "AI: \"좋아요 어르신, 오늘 하루도 건강하게 보내시고요, 나중에 또 연락드릴게요~\"\n";

        String prompt = String.format("""
                당신은 고령자를 위한 따뜻하고 친절한 AI 전화 상담원입니다.
                
                **역할**: 아침에 어르신께 전화드려 어제 수면 상태와 아침 식사·복약·혈당 여부를 자연스럽고 친근하게 확인하세요.
                
                **대화 목표**: 
                다음 항목들에 대해 의미 있는 응답을 반드시 확보하세요.
                1. 수면 상태: 어제 몇 시에 주무시고 오늘 몇 시에 일어나셨는지
                2. 아침 식사 여부: 식사 하셨는지, 무엇을 드셨는지
                3. 아침 복약 여부: [%s] 중 약을 드셨는지
                %s
           
                
                **대화 스타일 지침**:
                - 어르신의 응답은 반드시 한국어로만 인식하세요.
                - 한 질문에는 하나의 답변을 할 수 있도록 하세요
                - 모든 응답에는 공감하며 따뜻하게 반응하세요.
                - 혈당 수치가 높거나 낮으면 간단한 조언을 함께 드리세요.
                
                **대화 흐름 예시**:
                AI: "안녕하세요, %s 어르신~ 메디케어콜입니다. 오늘도 안부 전화 드렸어요!"
                어르신: [인사 응답]
                AI: "어르신 어제는 몇 시쯤 주무셨어요?"
                어르신: [취침시간 응답]
                AI: "오늘은 몇 시에 일어나셨어요?"
                어르신: [기상시간 응답]
                AI: [수면관련 공감] + "그럼 오늘 아침 식사는 하셨나요? 뭐 드셨어요?"
                어르신: [식사 응답]
                AI: [식사관련 공감] + "아침 약 중에 [%s] 드셨을까요"
                어르신: [복약 응답]
                %s


                **핵심 원칙**: 
                - [%s]는 아침 복약 데이터로 동적으로 삽입됩니다.
                - 모든 항목에 대해 어르신의 명확한 응답을 확보한 뒤 다음 질문으로 넘어가세요.
                - 어르신이 위축되지 않도록 항상 공감과 배려를 담아 말하세요.
                지금 첫 번째 인사를 해주세요.
                """,
                morningMedNames,                      // 1번째 %s - 대화 목표의 복약 목록
                diabetesLine,                         // 2번째 %s - 당뇨병 질문 라인
                elderName,                            // 3번째 %s - 대화 흐름의 어르신 이름
                morningMedNames,                      // 4번째 %s - 대화 흐름의 복약 목록
                diabetesFlow,                         // 5번째 %s - 혈당 관련 대화 흐름
                morningMedNames                       // 6번째 %s - 핵심 원칙의 복약 목록
        );
        return prompt;

    }

    private void sendPrompt(Integer settingId, Integer elderId, String phoneNumber, String prompt) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            String normalizedPhoneNumber = PhoneNumberUtil.normalizeKoreanPhoneNumber(phoneNumber);

            Map<String, Object> body = new HashMap<>();
            body.put("elderId", elderId);
            body.put("settingId", settingId);
            body.put("phoneNumber", normalizedPhoneNumber);
            body.put("prompt", prompt);

            HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
            ResponseEntity<String> response = restTemplate.postForEntity(callUrl, request, String.class);

            System.out.println("호출 성공: " + response.getBody());
        } catch (Exception e) {
            System.err.println("호출 실패: " + e.getMessage());
        }
    }

Todo

  • Spring Ai의 ChatClient를 폼한 추상화 코드를 활용해서 리팩토링
  • 프롬프트를 st(text)파일로 사용할수있도록 개선
  • "한 통화 내에서 어르신과의 대화 맥락"을 기억하고 답변하면 응답의 퀄리티를 높일 수 있을 것 같은데, 혹시 이런것도 고려되어있나요?

읽어보시면 좋은 자료

Metadata

Metadata

Labels

enhancementNew feature or requestrefactoringRefactoring should not change Test codes

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions