[ChatGPT] 챗GPT로 문자 자동 응답하기 | 업무 자동화, AI 업무 활용

회사 업무 중에는 고객이나 직원들의 다양한 문의나 요청에 대응해야 하는 상황이 종종 발생합니다. 하루에 수십 건, 많게는 수백 건씩 발생하는 문의에 일일이 대응하는 건 효율적이지 않습니다.

이번에는 챗GPT를 이용해 문의에 대한 답변을 자동으로 생성하는 실습을 해보겠습니다. 챗GPT에게 어떤 식으로 답변을 생성할 것인지 미리 가이드라인을 만들어주고, 챗GPT는 가이드라인에 따라 답변을 생성하게 됩니다. 계획은 다음과 같습니다.

 

계획1 스프레드시트에 고객의 정보와 문의 내용을 정리합니다.

계획2 체크박스로 고객을 선택하고 [답변] 버튼을 누르면 챗GPT를 이용하여 답변을 자동으로 생성합니다.

계획3 사이드바에서 [전송] 버튼을 누르면 생성된 답변을 고객의 휴대폰으로 전송합니다.

 

이렇게 답변에 따른 템플릿을 자동으로 생성해 문자 메시지 전송까지 해주는 시스템을 구현해보겠습니다.

 

준비해주세요

스프레드시트와 HTML 설정

고객들의 요청 사항을 관리하는 시트를 구성합니다. 다음과 같이 문자를 보낼 고객의 정보와 문의 내용, [답변] 내용을 작성할 수 있도록 열 제목과 가상의 문의 내용을 준비해주세요. 그리고 [삽입→그림]을 클릭해서 [답변] 버튼을 넣고 sendCustomerService라는 이름의 함수를 할당해주세요. 시트 이름은 ‘고객claim’으로 수정합니다.

 

 

연결된 앱스 스크립트 프로젝트를 만들고 새 HTML 파일을 만든 후 ‘독자 제공 HTML 샘플’에서 customerService.html 파일의 내용을 복사해서 붙여넣기 해주세요.

 

API 사용에 필요한 변수와 함수 선언하기

그리고 차근차근 필요한 함수와 변수들을 생성하겠습니다. API를 불러오는 데 필요한 변수, 챗GPT에서 답변을 가져오는 함수, 스프레드시트에 알림을 띄우는 함수 등 다양한 함수를 작성해야 하므로 코드가 길고 복잡합니다. 필요에 따라 나눠서 보겠습니다.

 

챗GPT API 사용 설정

먼저 챗GPT의 환경변수 객체를 선언합니다.

 

// 챗GPT 환경설정
var GPT = {
   env: {
      'API_KEY' : "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",  
      'MODEL' : 'gpt-4',
      'MAX_TOKENS' : 1500,
      'TEMPERATURE' : 0.1,
      'TOP_P' : 1.0,
      'MESSAGE' : `You are an ‘앱스 스크립트 챗봇’ that responds to customer inquiries. Please fill out the following:
         1. Please answer the questions kindly.
         2. Please be sure to write your answer in Korean.
         3. Unify the response target as "{name} 고객님".
         4. The answer begins with an apology for the content of the inquiry.`
   }
};
// 시스템 메시지 설정
var conversation = [
  { role: "system", content: GPT.env.MESSAGE }
];

 

환경변수의 ‘MESSAGE’가 챗GPT에게 답변 가이드라인을 제공하는 변수, 즉 프롬프트입니다. 이 프롬프트를 개선하는 것을 프롬프트 엔지니어링이라고 부릅니다. 예를 들어 반품 요청, 교환 요청, 상품 질문 등 다양한 상황의 답변 예시나 가이드를 프롬프트로 작성하면 챗GPT는 해당 상황에 적합한 답변을 생성해 줍니다. 실습 예제에서는 챗GPT에게 고객 대응 챗봇이라는 역할을 주고 친절한 말투, 한글 사용, 호칭, 사과로 시작할 것이라는 4개의 답변 가이드라인을 입력했습니다.

 

문자 메시지 API 사용 설정

coolSMS API를 사용할 정보들을 선언하고 SMS 인증 시 signature를 생성하기 위한 함수들을 선언합니다.

 

// coolSMS 환경설정
const API_KEY = "NC****ZU";
const API_SECRET ="DD****FL";
const HostPhoneNumber = "본인인증한 발신자용 휴대전화 번호";

function signApiRequest(datetime, salt, appSecret) {
   // 서명에 사용할 데이터 생성
   var query = `${datetime}${salt}`;
   var bytes = null;
   try {
      // 비밀키와 데이터를 이용하여 HMAC-SHA256 서명 생성
      var secretKey = Utilities.newBlob(appSecret).getBytes();
      var dataBytes = Utilities.newBlob(query).getBytes();
      var hmac = Utilities.computeHmacSha256Signature(dataBytes, secretKey);
      bytes = hmac;
   } catch (e) {
      Logger.log(e.toString());
   }
   // 바이트를 16진수 문자열로 변환하여 반환
   return byte2hex(bytes);
}

function byte2hex(bytes) {
   var sign = '';
   for (var i = 0; i < bytes.length; i++) {
      var hex = (bytes[i] & 0xFF).toString(16);
      if (hex.length == 1) {
         sign += '0';
      }
      sign += hex.toUpperCase();
   }
   return sign;
}


function getDateTime() {
   const today = new Date();
   const date = today.getFullYear() + "-" + (today.getMonth() + 1).toString().padStart(2, "0") + "-" + today.getDate().toString().padStart(2, "0");
   const time = today.getHours().toString().padStart(2, "0") + ":" + today.getMinutes().toString().padStart(2, "0") + ":" + today.getSeconds().toString().padStart(2, "0");
   const result = date + "T" + time + "Z";
   return result;
}

 

각 함수와 변수를 간단히 설명하면 다음과 같습니다.

  • API_KEY : 문자 메시지를 전송하는 API키를 입력하는 변수
  • API_SECRET : 문자 메시지를 전송하는 API Secret를 입력하는 변수
  • HostPhoneNumber( ) : 문자 메시지를 전송하는 발신번호를 입력하는 변수
  • signApiRequest( ) : 서명을 생성하는 함수
  • byte2hex( ) : 바이트를 16진수 문자열로 변환하는 함수
  • getDateTimeSms( ) : 현재 시간을 출력하는 함수

 

문자 메시지 보내기를 더 자세히 배우고 싶다면 <이게 되네? 업무 자동화 미친 활용 앱스 스크립트 with 챗GPT> [프로젝트 34: 앱스 스크립트로 문자 메시지 보내기]를 참고하세요.

 

챗GPT로 답변 생성해서 문자 보내기

답변 처리를 위해 원하는 행의 체크박스를 선택하고 [답변] 버튼을 클릭하면, 선택한 행의 정보를 추출하고 챗GPT를 활용하여 문의 사항에 대한 답변 템플릿을 생성하여 스프레드시트의 사이드바에 입력하는 기능을 구현합니다. 또한, 사이드바에서 [전송] 버튼을 클릭하면 등록된 고객 휴대폰 번호로 문자 메시지를 전송하는 기능도 구현합니다.

 

챗GPT로 답변 생성하기

챗GPT로 문의 사항에 맞는 답변을 받는 기능부터 작성해봅시다.

 

//챗GPT로 답변 생성하기
function sendCustomerService() {
   const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("고객claim");
   // 선택된 체크박스에 해당하는 행 데이터 가져오기
   const values = sheet.getRange("A2:J"+sheet.getLastRow()).getValues();
   const row = values.filter(row => row[0] === true)[0];
   const idx = values.findIndex(row => row[0] === true);
   
   // 선택된 데이터가 없을 경우 알림을 표시하고 함수 종료
   if ( row.length < 1 ) {
      console.log("선택된 데이터가 없습니다.");
      alertMessage("알림", "선택된 데이터가 없습니다.");
      return;
   }
   const content = row[7];
   var html = HtmlService.createTemplateFromFile("customerService.html");
   // ① 필요한 데이터들을 html로 전달
   html.idx = idx;
   html.name = row[1];
   html.phone = row[2];
   html.email = row[3];
   html.product = row[6];
   html.content = content;
   // ② 챗GPT로 생성된 답변 템플릿을 html로 전달
   html.answerTemplate = creatingAnswerWithGpt(content);
   var htmlOutput = html.evaluate();
   htmlOutput.setTitle("고객 응대");
   SpreadsheetApp.getUi().showSidebar(htmlOutput);
}

function creatingAnswerWithGpt(message) {
   // ③ 챗GPT를 이용해 문의사항에 대한 답변 템플릿을 생성
   // 질문을 위한 챗GPT 설정
   conversation.push(({ 'role': 'user', 'content': message }))
   const url = 'https://api.openai.com/v1/chat/completions';
   var formData = {
      'model': GPT.env.MODEL,
      'max_tokens': GPT.env.MAX_TOKENS,
      'messages': conversation
   };
   // 챗GPT 질문
   const options = {
      method: 'POST',
      headers: {
         'Authorization': 'Bearer ' + GPT.env.API_KEY,
         'Content-Type': 'application/json'
      },
      payload: JSON.stringify(formData)
   };
   // 챗GPT 답변 추출 및 콘솔에 출력
   const response = UrlFetchApp.fetch(url, options);
   const data = JSON.parse(response.getContentText());
   const result = data.choices[0].message.content;
   return result;
}

 

① 스프레드시트의 사이드바에서 사용할 HTML에 변수들을 전달합니다. 기존에는 사이드바를 활성화할 때 HtmlService 클래스의 createHtmlOutputFromFile( ) 메서드를 이용해 HTML 객체를 생성했지만, HTML에서 변수를 사용할 수 있도록 createTemplateFromFile( ) 메서드를 이용해 HTML 템플릿을 먼저 생성합니다. 생성된 HTML 템플릿에 행 번호, 이름, 전화번호 등 사이드바에서 보여줄 데이터들을 담습니다. 템플릿 구성이 완성되면 evaluate( ) 메서드를 이용해 사이드바에서 표현될 HTML을 생성합니다.

② creatingAnswerWithGpt( ) 메서드에 content를 매개변수로 문의 내용을 전달해 챗GPT로 답변을 생성합니다. 생성된 답변을 HTML의 answerTemplate라는 변수에 담습니다.

③ 챗GPT를 이용해 문의 내용에 대한 답변 템플릿을 생성합니다.

 

답변 문자로 전송하기 스프레드시트에 입력하기

이제는 챗GPT로 생성한 답변을 문자 메시지로 전송하고 스프레드시트에 입력하는 코드를 작성해보겠습니다.

 

// 답변 문자로 전송하고 스프레드시트에 입력하
function sendSmsSelectedUser(phoneNo, name, message, idx) {
  console.log('hi');
   // ① 답변을 SMS로 전송
   const confirm = confirmMessage('확인',`${name} 님에게 답변 문자 메시지를 전송하시겠습니까?`);
   if (!confirm) { return; }
   message = message.replace(/{name}/g, name);
   // SMS 발송 API 설정
   const url = "https://api.coolsms.co.kr/messages/v4/send";
   // header 설정
   var datetime = getDateTime();
   var salt = Date.now().toString();
   var sign = signApiRequest(datetime, salt, API_SECRET);
   // body 설정
   var formData = {"message":{"to":phoneNo, "from":HostPhoneNumber, "text":message, "autoTypeDetect":true}};
   // SMS API에 POST 요청을 보내기
   const response = UrlFetchApp.fetch(url, {
      method : "POST",
      headers:{
         "Authorization": `HMAC-SHA256 apiKey=${API_KEY}, date=${datetime}, salt=${salt}, signature=${sign}`,
         "Content-Type": "application/json"
      }
      , payload: JSON.stringify(formData)
   });
   const responseCode = response.getResponseCode();
   if ( responseCode == "200" ) {
      const json = response.getContentText();
      const returndData = JSON.parse(json);
      console.log(returndData);
      // ② 전송한 답변을 시트에 저장
      const sheet = SpreadsheetApp.getActive().getSheetByName("고객claim");
      sheet.getRange(`I${parseInt(idx)+2}:J${parseInt(idx)+2}`).setValues([[message, getDateTime()]]);
      alertMessage("성공", `${name} 님에게 답변 문자 메시지를 전송하였습니다.`);
      return true;
   } else {
      alertMessage("성공", `${name} 님에게 답변 문자 메시지를 전송을 실패하였습니다.`);
      return false;
   }
}

function alertMessage(tit, msg) {
 var ui = SpreadsheetApp.getUi();
 ui.alert(tit, msg, ui.ButtonSet.OK);
}

function confirmMessage(tit, msg) {
  const ui = SpreadsheetApp.getUi();
  const response = ui.alert(tit, msg, ui.ButtonSet.YES_NO);
  if ( response == ui.Button.YES ) {
     return true;
  } else {
     return false;
  }
}

 

① 답변 내용을 등록된 고객의 휴대폰 번호로 전송합니다.

② 전송한 답변과 문자 메시지를 전송한 시간을 시트에 저장합니다.

 

체크박스 선택 관리하기

체크박스로 답변을 원하는 행을 선택하기 때문에 한 번에 하나의 행만 체크해야 합니다. onEdit() 트리거로 시트의 체크박스 변경을 확인하고, 하나의 행만 선택해서 챗GPT 답변을 요청하도록 관리하는 함수도 작성하여 사용성을 더욱 높여보겠습니다.

 

//체크박스 설정 관리하기 
function onEdit(e) {
  const getValue = e.value;
  const spreadSheet = e.source;
  const sheetName = spreadSheet.getActiveSheet().getName();
  const column = e.range.getColumn();
  const row = e.range.getRow();
  const activeCell = spreadSheet.getActiveCell();
  // "고객claim" 시트에서 데이터 변경 발생 시
  if ( sheetName == "고객claim" ) {
     // 변경된 행이 1열의 3번째 행 이상일 경우
     if ( column == 1 && row >= 3 ) {
        var lastRow = spreadSheet.getLastRow();
        // 모든 체크박스 선택 해제
        unckeckAll(lastRow);
        // 선택된 셀의 값이 'FALSE'인 경우 함수 종료
        if ( getValue == 'FALSE' ) {  return; }
        // 선택된 셀을 'TRUE'로 설정
        activeCell.setValue(true);
     }
  }
}

function unckeckAll(lastRow){
  const range = `A3:A${lastRow}`;
  const value = false;
  allCheckbox(range, value);
}

function allCheckbox(range, value) {
  const checkRange = SpreadsheetApp.getActiveSpreadsheet().getRange(range);
  checkRange.setValue(value);
}

 

HTML 확인하기

HTML 파일의 구성도 살펴보겠습니다.

 

...생략...
<script type="text/javascript">
  function sendAnswer() {
    <!-- ① 전송한 답변을 시트에 저장 -->
    var phone = document.getElementById('phone').value;
    console.log(phone);
    var username = document.getElementById('username').value;
    console.log(username);
    var answer = document.getElementById('answer').value;
    console.log(answer);
    var idx = document.getElementById('idx').value;
    console.log(idx);
    google.script.run.sendSmsSelectedUser2(phone, username, answer, idx);
    // .withSuccessHandler()
  }
</script>
...생략...
<body>
  <input type="hidden" id="idx" name="idx" value="<?= idx ?>" disabled/>
  <div>
      <p class="title">고객명 : </p>
      <!-- ② 보여줄 값들 입력하고 비활성화 -->
      <input type="text" class="form-control inp mb-3" id="username" name="username" value="<?= name ?>" disabled/>
  </div>
..생략...
  <div class="box">
    <p class="title">답변 : </p>
    <!-- ③ 답변 템플릿을 입력하고 수정할 수 있도록 구성 -->
    <textarea id="answer" class="text_input textarea"><?= answerTemplate ?></textarea>
  </div>
  <div style="margin-top:10px">
    <!-- ④ 전송 버튼에 이벤트 할당 -->
    <button id="btnSendAnswer" onclick="sendAnswer()">전송</button>
   </div>
</body>

 

① 사이드바에 입력된 값들을 앱스 스크립트의 sendSmsSelectedUser( ) 함수의 매개변수로 전달하여 함수를 실행합니다.

② 스크립틀릿 코드로 고객명을 보여주고 입력을 비활성화합니다. 이후 전화번호, 상품명, 문의 내용도 모두 같은 방식으로 구성했습니다.

③ 챗GPT로 생성한 answerTemplate변수를 textarea에 입력하고 수정할 수 있도록 구성합니다.

④ 전송 버튼의 onClick 이벤트에 앞서 생성한 sendAnswer( ) 함수를 할당합니다.

 

작동 확인하기

코드를 저장한 다음 답변할 행의 체크박스를 선택하고 [답변] 버튼을 클릭합니다. 스프레드시트의 사이드바에 선택된 행의 데이터들이 입력되고, 챗GPT를 이용해 생성된 답변 템플릿도 답변에 입력됩니다. 답변의 내용은 프롬프트에서 설정한 대로 고객의 이름을 입력하기 위한 {name} 변수를 시작으로 메시지가 생성된 것까지 확인할 수 있습니다.

 

 

답변 내용을 확인한 후 수정할 부분이 있으면 수정하고, [전송] 버튼을 클릭하면 답변은 입력된 고객의 전화번호로 전송됩니다.

 

 

{name} 변수에 고객의 이름이 입력되어 문자 메시지가 전송되었습니다.

 

 

‘고객claim’ 시트에는 선택된 문의 내용에 대한 문자 메시지로 전송된 답변과 답변 시간이 저장됩니다.

 

 

지금까지 챗GPT와 앱스 스크립트를 활용하여 문자 메시지 응답 자동화를 만들어보았습니다.

더 많은 업무 자동화 방법은 신간 <이게 되네? 업무 자동화 미친 활용 앱스 스크립트 with 챗GPT>를 참고하세요!

서휘승 

ERP, 핀테크 등 다양한 도메인에서 백엔드 개발을 두루 경험하며, 안정적이고 확장 가능한 시스템을 개발하는 다양한 경험을 쌓아왔습니다. 데이터의 중요성을 깊이 인식하고, 데이터 엔지니어로서 다양한 파이프라인을 구축했습니다. 현재는 클라우드 MSP 기업인 클루커스의 Gen AI 팀에서 애저 OpenAI를 활용한 맞춤형 인공지능 솔루션을 개발하고 있습니다.

앱스 스크립트와 구글 클라우드 플랫폼을 활용한 업무 자동화 프로젝트를 성공적으로 완수했고, 이후 앱스 스크립트의 매력에 빠져 다양한 분야에서 업무 자동화를 구현하고 확장하기 위해 고민하고 있습니다.

 

블로그 : whiseung.tistory.com

링크드인 : linkedin.com/in/seo-whiseung-b5428827

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내