← Docs hub

Day 3: Cloud LLM 개선 작업 및 테스트

1. 학습 목표

1. 학습 목표

Day 3은 Cloud LLM 서버 구조, Case 응답 계약, RAG 개입 조건, 온디바이스 재진입 구조를 정리합니다. 핵심은 Cloud가 제품 기능을 직접 실행하지 않는다는 점입니다. Cloud는 사용자 의도를 Case로 분류하고, 제품 기능이면 rewrite_query를 통해 다시 온디바이스 로컬 라우팅으로 돌려보냅니다.

이 장을 읽은 후에는 다음을 수행할 수 있어야 합니다.

참조:

2. 본문 개요

2. 본문 개요

Cloud LLM은 다음 관점에서 이해해야 합니다.
Cloud LLM은 일반 질문이나 로컬 이해 실패를 보완하는 중요한 경로지만,
제품 기능을 직접 실행하는 주체는 아닙니다.

Cloud가 "이건 제품 기능이다"라고 판단하면 Case 2로 응답하고,
온디바이스가 다시 이해할 수 있는 rewrite_query를 내려줍니다.
그 rewrite_query가 다시 온디바이스 딕셔너리와 로컬 LLM을 통과해야 실제 기능이 실행됩니다.

3. On-device Cloud 요청 소스

3. On-device Cloud 요청 소스

주요 파일:

app/src/main/java/com/skmagic/ondeviceai/agent/service/ForegroundService.kt
app/src/main/java/com/skmagic/ondeviceai/agent/service/repository/ChatRepository.kt
app/src/main/java/com/skmagic/ondeviceai/agent/common/NetworkModule.kt
app/src/main/assets/LLM_PROMPT_ko.text
app/src/main/assets/LLM_PROMPT_en.text

핵심 함수:

processVoiceCmd()
processCloudLLM()
callCloudLLMAPI()
runCloudResolvedQueryThroughLocalPipeline()

Cloud 진입 조건:

1. isCloudContinue == true && Wi-Fi connected
2. 로컬 결과가 error_answer && Wi-Fi connected
3. 특정 token handler에서 tossToCloudLlm() 호출

4. Cloud request 구조

Cloud request 구성

callCloudLLMAPI()는 아래 4종류 메시지를 구성합니다.

Persona system

loadPrompt()
LLM_PROMPT_ko.text 또는 LLM_PROMPT_en.text

역할:

Cloud LLM의 페르소나, 기능 라우팅 기준, Case Router, 미지원 기능 정책을 정의합니다.

Information system

#Information
- Date
- Time
- DayOfWeek
- TimeZone

역할:

오늘/현재/요일/시간 관련 질문에 Cloud가 기기 기준 컨텍스트를 알 수 있게 합니다.

Environment system

#Environment
- Current Location
- Weather
- Humidity
- Temperature low/high
- PM 10
- PM 2.5

역할:

날씨/공기질/외출복장 질문에서 현재 환경 컨텍스트를 제공합니다.

User message

originalSttResult 기반

중요:

Cloud로 넘어가는 user content는 로컬 dictionary용 filteredSttResult가 아닙니다.
따라서 Cloud 오분류를 분석할 때는 STT raw/originalSttResult를 확인해야 합니다.

4-1. 국내 프롬프트 구성 기준

4-1. 국내 프롬프트 구성 기준

국내 프롬프트는 Cloud LLM이 제품 기능과 일반 질의를 섞지 않도록 아래 계층으로 구성됩니다.

계층 역할 주요 내용
Persona 응답 성격과 제품 정체성 Namuh X, SK 계열 제품, 정중하고 간결한 응답
Capabilities 수행 가능한 기능 범위 청정, 이동, 바이탈, 고객센터, 일반 대화
Router Case 분류 기준 Case 1/2/3/4, 제품 기능 우선순위, 미지원 정책
Anti-hallucination 과장/실시간 정보 제한 최신 정보 제한, 외부 정보 제한, 불확실 시 짧게 안내
Time/Weather 기기 컨텍스트 사용 기준 device clock, weather context, 위치/날씨 질의 처리
Output Contract JSON 응답 계약 case, response, rewrite_query, there_is_question_mark

국내 프롬프트에서 가장 중요한 점은 제품 기능을 직접 실행하지 않게 하는 것입니다.

제품 기능 의도:
  Cloud가 직접 "실행했습니다"라고 말하지 않음
  Case 2 + rewrite_query로 온디바이스 재진입

일반 설명:
  Case 1로 짧고 정중하게 답변

미지원 기능:
  Case 4로 지원 불가 안내

말레이시아용 프롬프트를 만들 때도 이 구조는 유지합니다. 바뀌는 것은 제품 정책 문장, 현지 FAQ, 서비스 연락처, 현지 표현, RAG 문서셋입니다.

5. Cloud Lambda 구조

5. Cloud Lambda 구조

대상 저장소:

~/work/8.cloudLLM/backend-cloud-llm-lambda

핵심 파일:

lambda_function.py
gemini/gemini_full_rag_api.py
gemini/gemini_file_rag_api.py
gemini/gemini_rag_judge_api.py
gemini/gemini_gsearch_rag_api.py
gemini/search_keyword_generator.py
gemini/prompt_formatting.py

처리 개념:

API Gateway
  -> lambda_handler
  -> request body parse
  -> CloudLLMRequest
  -> full_rag()
  -> 기본 Gemini 응답 / File RAG / Web RAG 후보
  -> 최종 response JSON
  -> OpenAI ChatCompletion 스타일 wrapper

6. Case 응답 계약

Case 응답 계약

Case 1: 일반 답변

{
  "case": 1,
  "response": "짧고 정중한 답변입니다.",
  "there_is_question_mark": false
}

온디바이스 처리:

response를 TTS로 출력합니다.
there_is_question_mark가 true거나 response가 ?로 끝나면 Cloud continue 상태를 유지합니다.

Case 2: 제품 기능 재해석

Cloud Rewrite Quality Gate

{
  "case": 2,
  "function": "Air quality map",
  "available_function": "check for status",
  "rewrite_query": "Check the air quality map history, please"
}

온디바이스 처리:

1. 현재 user turn 제거
2. resetMultiturn()
3. resetCloudMultiturn()
4. runCloudResolvedQueryThroughLocalPipeline(rewrite_query)
5. processLLAMA(rewrite_query)
6. 최종 `<sk_xx>` 생성

검증:

Case 2가 맞아도 rewrite_query가 온디바이스에서 기대 토큰으로 매칭되지 않으면 실패입니다.

rewrite_query 품질 기준:

항목 기준
문장 형태 사용자가 다시 말할 법한 명령형 문장
금지 형태 I will..., ...하겠습니다처럼 실행 완료를 의미하는 문장
기능명 온디바이스 dictionary가 인식할 수 있는 기능명을 포함
action check/show/set/stop/start 같은 실제 action 포함
slot 공간명, 단위, 모드, 상태조회 대상 등 필수 slot 보존
최종 판정 runCloudResolvedQueryThroughLocalPipeline() 이후 기대 <sk_xx> 매칭

Cloud rewrite 강화 기준:

Cloud Rewrite Prompt Hardening

단계 확인 항목 실패 시 수정 위치
Cloud user content originalSttResult가 실제 사용자 발화와 같은지 STT/전처리/Cloud request 구성
Case Router 제품 기능 요청이 Case 2로 분류되는지 Cloud prompt router 예시/규칙
rewrite_query 기능명, action, slot이 보존된 명령형 문장인지 Cloud prompt rewrite rule
Local re-entry rewrite가 기대 <sk_xx>로 재매칭되는지 온디바이스 dictionary 또는 rewrite 표현 제한

운영 기준:

Case 2만 맞으면 성공이 아닙니다.
Cloud가 만든 rewrite_query가 로컬 딕셔너리와 FunctionCallHandler까지 이어져야 최종 성공입니다.
따라서 Cloud prompt 강화 작업은 항상 온디바이스 dictionary 테스트 결과와 함께 판단합니다.

Case 3: 준비 질문

{
  "case": 3,
  "prepared_question_list_number": "56"
}

처리:

일부 번호는 로컬 string resource로 즉시 응답합니다.
그 외에는 getRewriteQuery(number)로 문장화한 뒤 로컬 재진입할 수 있습니다.

Case 4: 미지원 기능

{
  "case": 4,
  "response": "현재 이 기능은 지원되지 않습니다.",
  "there_is_question_mark": false
}

처리:

Cloud 응답을 TTS로 출력합니다.
제품 기능을 수행한 것처럼 말하면 안 됩니다.

7. RAG 선택 기준

RAG 선택 기준

File RAG

용도:

사전에 구축된 제품 문서/뉴스/FAQ성 문서에서 근거를 찾아 답변합니다.
근거가 없으면 False 또는 fallback 성격의 결과가 나올 수 있습니다.

Web Search RAG

용도:

최신성/외부 정보가 필요한 질문에서 Google Custom Search 결과를 Gemini가 재구성합니다.

RAG가 필요 없는 예

보안모드는 뭐야?
올타임 모드는 언제 써?
필터 청소 주기는 어떻게 돼?

RAG가 필요한 예

최근 공기질 관련 뉴스 알려줘
요즘 미세먼지 이슈 알려줘
오늘 외부 날씨와 관련된 최신 정보를 알려줘

7-1. 말레이시아 Custom RAG 운영 기준

말레이시아 현지 운영 의사결정 라우터

말레이시아 현지 운영에서는 국내 문서 기준 답변을 그대로 쓰면 안 되는 영역이 있습니다. 현지 RAG는 아래 자료를 별도 문서셋으로 구성하는 것을 기준으로 합니다.

문서셋 포함 내용 RAG 선택 기준
제품 기능 FAQ 현지 판매 모델 기능, 앱 메뉴, 제한 사항 제품 설명 질문이지만 기능 실행이 아닌 경우
고객지원/서비스 현지 고객센터, 보증, AS 정책 연락처/서비스/보증 질문
설치/사용 가이드 현지 언어 사용 설명, 초기 설정, Wi-Fi 연결 사용법 질문
공기질/웰니스 콘텐츠 현지 환경 기준, PM 설명, 건강 관련 일반 가이드 제품 외 일반 설명, 단 의료 진단 금지
미지원/제한 정책 현지 앱 미지원 기능, 국가별 미제공 기능 사용자가 요구한 기능이 제품/지역에서 불가한 경우

주의:

1. 말레이시아 RAG는 제품 기능 실행 경로가 아닙니다.
2. 기능 실행은 여전히 On-device token과 Device API 경로에서 수행됩니다.
3. RAG 답변은 근거 문서가 없으면 추정으로 만들지 않습니다.
4. 현지 연락처/요금/정책은 최신 문서 기준으로만 답변합니다.
5. 한국 사양과 말레이시아 사양이 다르면 말레이시아 운영 문서를 우선합니다.

말레이시아 RAG와 제품 기능 실행의 경계:

현지 서비스/보증/앱 사용법 질문:
  Case 1 + Malaysia Custom RAG

제품 기능 실행 요청:
  Case 2 + rewrite_query + On-device 재진입

예: "Register the cleaning schedule"
  Cloud가 RAG 답변으로 설명하지 않고,
  schedule 기능 명령형 rewrite_query를 생성하거나
  온디바이스 dictionary에서 직접 <sk_48>로 처리되어야 합니다.

말레이시아 Custom RAG 테스트 케이스:

질문 유형 기대 판정
현지 고객센터 What is the Malaysia service center number? 현지 서비스 문서 근거 답변
현지 앱 사용법 How do I connect the device to the app in Malaysia? 현지 앱 가이드 근거 답변
제품 기능 실행 Turn on security mode RAG 답변이 아니라 Case 2 또는 로컬 기능 경로
제품 외부 최신 정보 What is today's haze condition in KL? Web/RAG 필요 여부 판단, 불확실 시 제한 안내
미지원 기능 Open YouTube on the device Case 4 미지원 안내

8. Cloud 테스트 방법

8. Cloud 테스트 방법

테스트는 단순히 “대답이 자연스러운가”가 아니라 아래를 봅니다.

1. request messages가 기대대로 구성됐는가
2. user content가 실제 STT 원문과 같은가
3. case가 기대와 맞는가
4. response 또는 rewrite_query가 사양과 맞는가
5. Case 2 rewrite_query가 온디바이스에서 기대 토큰으로 매칭되는가
6. Cloud continue가 불필요하게 켜지지 않는가
7. RAG가 필요한 질문에서만 RAG가 개입했는가

추가 판정 기준:

  1. JSON 형식이 자연스러워도 case가 틀리면 실패입니다.
  2. Case 2는 rewrite_query가 온디바이스에서 기대 token으로 재매칭되어야 성공입니다.
  3. originalSttResult가 잘못 들어가면 프롬프트 수정만으로 해결되지 않을 수 있습니다.
  4. 말레이시아 질의는 국내 프롬프트와 현지 RAG 문서셋 중 어느 근거를 사용했는지 기록합니다.
  5. there_is_question_mark가 불필요하게 true이면 다음 turn 상태관리 문제가 발생할 수 있습니다.

Cloud rewrite_query 검증 절차:

1. Cloud response raw에서 case/function/available_function/rewrite_query를 기록
2. case == 2이면 rewrite_query 문장이 사용자 명령형인지 확인
3. 온디바이스 로그에서 `Cloud rewrite_query enters local routing pipeline` 확인
4. 이어지는 `[DICTIONARY_MATCH]` 또는 `parsedLlamaResponse` 확인
5. 기대 `<sk_xx>`와 실제 token/parameter 비교
6. Validator/API/TTS까지 최종 결과 확인
7. 실패하면 Cloud prompt 수정인지 dictionary 보강인지 분리

9. 실습 케이스

9. 실습 케이스

운영 예제:

발화: Please show me the air quality map history
Cloud response: case=2, rewrite_query="Check the air quality map history, please"
온디바이스 재진입 기대: <sk_29>(get=True)

판정:

Cloud Case 2는 제품 기능 의도 분류가 맞다는 의미입니다.
하지만 최종 성공은 rewrite_query가 온디바이스 dictionary에서 `<sk_29>(get=True)`로 매칭되어야 확정됩니다.

잘못된 예:

발화: 공기질 맵 히스토리 보여줘
Cloud 답변: 공기질 맵 히스토리를 보여드릴게요.

판정:

Cloud가 직접 화면을 띄우거나 Device API를 호출한 것처럼 말하면 안 됩니다.
제품 기능은 Case 2 rewrite_query로 온디바이스에 돌려보내야 합니다.
발화 기대 Cloud 판정
오늘 날씨 어때 환경 컨텍스트 기반 응답 또는 날씨 경로
공기질 맵 히스토리 보여줘 Case 2 + rewrite_query 또는 로컬 직접 매칭
보안모드는 뭐야 Case 1 설명
Please show me the air quality map history Case 2 또는 로컬 재진입 가능한 rewrite
유튜브 틀어줘 Case 4 미지원

10. 정리 과제

10. 정리 과제

1. Cloud request message 구조 요약
2. Case 1/2/3/4 예시와 온디바이스 처리 방식
3. RAG 필요/불필요 질문 10개 분류
4. rewrite_query 검증표
5. Cloud 테스트 결과 리포트 1건

11. 점검 질문

11. 점검 질문

1. Cloud Case 2와 Case 1의 가장 큰 차이는 무엇인가?
2. rewrite_query가 좋아 보여도 최종 기능 실행이 실패할 수 있는 이유는 무엇인가?
3. Cloud user content는 originalSttResult와 filteredSttResult 중 어느 쪽인가?
4. RAG는 제품 기능 실행을 위한 경로인가?
5. Cloud continue가 true가 되는 조건은 무엇인가?

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date