게시일: 2024년 10월 21일
온라인 상점은 제품 리뷰를 표시하여 전환수를 270% 증가시킬 수 있습니다. 부정적인 리뷰도 신뢰성을 구축하는 데 중요한 역할을 합니다. 온라인 쇼핑객의 82%가 구매 전에 리뷰를 확인합니다.
특히 부정적인 리뷰인 경우 고객이 유용한 제품 리뷰를 남기도록 유도하는 것은 쉽지 않을 수 있습니다. 여기에서는 생성형 AI를 사용하여 사용자가 다른 사용자의 구매 결정에 도움이 되는 유용한 리뷰를 작성하도록 지원하는 방법을 살펴봅니다.
데모 및 코드
제품 리뷰 데모를 살펴보고 GitHub의 코드를 살펴보세요.
빌드 방법
클라이언트 측 AI
이 데모에서는 다음과 같은 이유로 클라이언트 측에 기능을 구현했습니다.
- 지연 시간. 사용자가 입력을 중지하는 즉시 추천 단어를 빠르게 제공하고자 합니다. 서버 왕복을 피하여 이를 제공할 수 있습니다.
- 비용. 이 기능은 데모이지만 프로덕션에서 유사한 기능을 출시하려는 경우 기능이 사용자에게 적합한지 확인할 수 있을 때까지 서버 측 비용 없이 실험해 보는 것이 좋습니다.
MediaPipe 생성형 AI
다음과 같은 이유로 MediaPipe LLM 추론 API(MediaPipe GenAI 패키지)를 통해 Gemma 2B 모델을 사용하기로 했습니다.
- 모델 정확성: Gemma 2B는 크기와 정확성 간에 균형이 잘 잡혀 있습니다. 올바른 메시지가 표시되면 이 데모에 적합한 결과를 제공했습니다.
- 교차 브라우저 지원: MediaPipe는 WebGPU를 지원하는 모든 브라우저에서 지원됩니다.
사용자 환경
성능 권장사항 적용
Gemma 2B는 소규모 LLM이지만 다운로드 크기가 큽니다. 웹 워커 사용을 비롯한 성능 권장사항 적용
기능을 선택사항으로 설정
Google은 AI 기반 리뷰 추천을 통해 사용자의 제품 리뷰 게시 워크플로를 개선하고자 합니다. Google의 구현에서는 모델이 로드되지 않아 개선 도움말이 제공되지 않더라도 사용자가 리뷰를 게시할 수 있습니다.
UI 상태 및 애니메이션
추론은 일반적으로 즉각적으로 느껴지는 것보다 시간이 더 걸리므로 모델이 추론을 실행 중임을 사용자에게 알립니다. 애니메이션을 사용하여 기다리는 시간을 줄이고 애플리케이션이 의도한 대로 작동하고 있다고 사용자에게 알립니다. Adam Argyle이 설계한 대로 데모에서 구현한 다양한 UI 상태를 살펴보세요.
기타 고려사항
프로덕션 환경에서는 다음을 수행할 수 있습니다.
- 의견 메커니즘을 제공합니다. 추천이 좋지 않거나 적절하지 않은 경우 어떻게 해야 하나요? 빠른 의견 메커니즘(예: 좋아요 및 싫어요)을 구현하고 휴리스틱을 사용하여 사용자가 유용하다고 생각하는 항목을 결정합니다. 예를 들어 이 기능을 사용하는 사용자 수가 얼마나 되는지, 이 기능을 사용 중지하는지 평가합니다.
- 선택 해제 허용. 사용자가 AI 지원 없이 직접 말을 사용하고 싶어 하거나 이 기능이 불편하다고 생각하는 경우 어떻게 해야 하나요? 사용자가 원하는 경우 선택 해제하고 다시 선택할 수 있도록 허용합니다.
- 이 기능이 있는 이유를 설명합니다. 간단한 설명을 제공하면 사용자가 의견 도구를 사용하도록 유도할 수 있습니다. 예를 들어 '더 나은 의견을 제공하면 다른 쇼핑객들이 구매할 제품을 결정하고 Google에서 원하는 제품을 만드는 데 도움이 됩니다.'와 같은 문구를 사용할 수 있습니다. 기능의 작동 방식과 제공 이유에 관한 자세한 설명을 추가할 수 있습니다(예: 링크를 통해 자세히 알아보기).
- 해당하는 경우 AI 사용을 공개하세요. 클라이언트 측 AI를 사용하면 사용자의 콘텐츠가 처리를 위해 서버로 전송되지 않으므로 비공개로 유지할 수 있습니다. 하지만 서버 측 대체를 빌드하거나 AI를 사용하여 정보를 수집하는 경우 개인정보처리방침, 서비스 약관 또는 기타 위치에 이를 추가하는 것이 좋습니다.
구현
제품 리뷰 제안 도구의 구현은 다양한 사용 사례에 적용할 수 있습니다. 다음 정보를 향후 클라이언트 측 AI 기능의 기반으로 고려하세요.
웹 작업자의 MediaPipe
MediaPipe LLM 추론을 사용하면 AI 코드는 몇 줄 밖에 되지 않습니다. 모델 URL을 전달하여 파일 리졸버와 LLM 추론 객체를 만들고 나중에 이 LLM 추론 인스턴스를 사용하여 응답을 생성합니다.
그러나 코드 샘플은 좀 더 광범위합니다. 이는 웹 워커에 구현되어 있으므로 맞춤 메시지 코드를 통해 메인 스크립트와 함께 메시지를 전달하기 때문입니다. 이 패턴에 대해 자세히 알아보세요.
// Trigger model preparation *before* the first message arrives
self.postMessage({ code: MESSAGE_CODE.PREPARING_MODEL });
try {
// Create a FilesetResolver instance for GenAI tasks
const genai = await FilesetResolver.forGenAiTasks(MEDIAPIPE_WASM);
// Create an LLM Inference instance from the specified model path
llmInference = await LlmInference.createFromModelPath(genai, MODEL_URL);
self.postMessage({ code: MESSAGE_CODE.MODEL_READY });
} catch (error) {
self.postMessage({ code: MESSAGE_CODE.MODEL_ERROR });
}
// Trigger inference upon receiving a message from the main script
self.onmessage = async function (message) {
// Run inference = Generate an LLM response
let response = null;
try {
response = await llmInference.generateResponse(
// Create a prompt based on message.data, which is the actual review
// draft the user has written. generatePrompt is a local utility function.
generatePrompt(message.data),
);
} catch (error) {
self.postMessage({ code: MESSAGE_CODE.INFERENCE_ERROR });
return;
}
// Parse and process the output using a local utility function
const reviewHelperOutput = generateReviewHelperOutput(response);
// Post a message to the main thread
self.postMessage({
code: MESSAGE_CODE.RESPONSE_READY,
payload: reviewHelperOutput,
});
};
export const MESSAGE_CODE ={
PREPARING_MODEL: 'preparing-model',
MODEL_READY: 'model-ready',
GENERATING_RESPONSE: 'generating-response',
RESPONSE_READY: 'response-ready',
MODEL_ERROR: 'model-error',
INFERENCE_ERROR: 'inference-error',
};
입력 및 출력
전체 프롬프트는 퓨샷 프롬프팅으로 빌드되었습니다. 여기에는 사용자의 입력, 즉 사용자가 작성한 리뷰 초안이 포함됩니다.
사용자 입력을 기반으로 프롬프트를 생성하려면 런타임 시 유틸리티 함수 generatePrompt
를 호출합니다.
클라이언트 측 AI 모델 및 라이브러리에는 일반적으로 서버 측 AI보다 유틸리티가 적습니다. 예를 들어 JSON 모드를 사용할 수 없는 경우가 많습니다. 즉, 프롬프트 내에 원하는 출력 구조를 제공해야 합니다. 이는 모델 구성을 통해 스키마를 제공하는 것보다 깔끔하고 유지 관리가 쉽지 않으며 안정적이지 않습니다. 또한 클라이언트 측 모델은 더 작으므로 출력에서 구조적 오류가 발생할 가능성이 더 높습니다.
실제로 Gemma 2B는 JSON이나 JavaScript에 비해 구조화된 출력을 텍스트로 제공하는 데 더 효과적입니다. 따라서 이 데모에서는 텍스트 기반 출력 형식을 선택했습니다. 모델은 텍스트를 생성하고, 웹 앱 내에서 추가로 처리할 수 있도록 출력을 자바스크립트 객체로 파싱합니다.
프롬프트 개선
LLM을 사용하여 프롬프트를 반복했습니다.
- 퓨샷 프롬프팅 퓨샷 프롬프트의 예시를 생성하기 위해 Gemini Chat을 사용했습니다. Gemini Chat은 가장 강력한 Gemini 모델을 사용합니다. 이를 통해 고품질 예시를 생성할 수 있었습니다.
- 프롬프트 다듬기. 프롬프트 구조가 준비되면 Gemini Chat을 사용하여 프롬프트를 다듬었습니다 이렇게 하여 출력 품질이 개선되었습니다.
맥락을 사용하여 품질 향상
제품 유형을 프롬프트에 포함하면 모델이 더 관련성 높고 품질이 우수한 추천을 제공할 수 있었습니다. 이 데모에서 제품 유형은 정적입니다. 실제 애플리케이션에서는 사용자가 방문하는 페이지를 기반으로 프롬프트에 제품을 동적으로 포함할 수 있습니다.
Review: "I love these."
Helpful: No
Fix: Be more specific, explain why you like these **socks**.
Example: "I love the blend of wool in these socks. Warm and not too heavy."
프롬프트의 몇 장의 섹션에 있는 예시 중 하나입니다. 제품 유형('양말')이 추천 해결 방법과 리뷰 예시로 포함되어 있습니다.
LLM 관련 문제 및 해결 방법
Gemma 2B에는 일반적으로 더 강력한 대규모 서버 측 모델보다 더 많은 프롬프트 엔지니어링이 필요합니다.
Gemma 2B에 몇 가지 문제가 발생했습니다. 결과가 개선된 방법은 다음과 같습니다.
- 너무 친절합니다. Gemma 2B는 리뷰를 '유용하지 않음'으로 표시하는 데 어려움을 겪었고 판단하기 주저하는 듯 보였습니다. 라벨 언어를 더 중립적으로('유용함' 및 '도움이 되지 않음') 대신 '구체적' 및 '구체적'으로 만들기 위해 노력했으나 결과가 개선되지 않았습니다. 결과를 개선한 것은 프롬프트의 주문과 반복이었습니다. 생각의 연쇄 접근 방식도 개선에 도움이 될 수 있습니다.
명확하지 않은 안내: 모델이 프롬프트를 과도하게 해석하는 경우가 있었습니다. 리뷰를 평가하는 대신 예시 목록을 계속 작성했습니다. 이 문제를 해결하기 위해 프롬프트에 명확한 전환을 포함했습니다.
I'll give you example reviews and outputs, and then give you one review to analyze. Let's go: Examples: <... Examples> Review to analyze: <... User input>
프롬프트를 명확하게 구성하면 모델이 예시 목록(몇 장의 샷)과 실제 입력을 구분하는 데 도움이 됩니다.
잘못된 타겟. 경우에 따라 모델이 리뷰 텍스트 대신 제품 변경을 제안하기도 했습니다. 예를 들어 '이 양말이 싫어요'라는 리뷰에 대해 모델이 '양말을 다른 브랜드나 스타일로 교체해 보세요'라고 제안할 수 있는데, 이는 원하는 효과가 아닙니다. 프롬프트를 분할하면 작업을 명확히 하고 모델의 검토에 대한 집중도를 개선할 수 있었습니다.