8기에서 캔로봇님의 특강을 통해서 구글 스프레드시트에서 ChatGPT를 호출하는 것을 처음 접하였고, 그 때 OpenAI api 요금을 5달러 결제하고 지금까지 잘 사용하고 있습니다.
그 때 사용했던 함수는 GPT for Sheets and Docs라는 익스텐션의 GPT()라는 함수입니다.
그런데, 얼마 전 이 익스텐션이 유료로 바뀌어서..
구글 스프레드시트에서 GPT() 함수를 사용하게 되면 과금이 되게 됩니다.
유료로 바뀌면서 0.1달러(유효 기간 90일)를 기본으로 제공해 주는데, 몇 번 테스트로 호출했더니 벌써 0.07달러가 소진되었다고 나옵니다.
이제 구글 스프레드시트에서 GPT() 함수를 사용하게 되면
OpenAI API 비용
GPT fot Sheets and Docs 비용
이렇게 2중으로 비용이 발생하게 되는데요.
이왕 결제를 한 OpenAI API 비용만 가지고 구글 스프레드시트에서 ChatGPT를 이용하기 위해서 Apps Script로 함수를 직접 만들어 보았습니다.
늘 그렇지만, 이 과정 또한 우리의 ChatGPT(Grimoire GPTs)의 도움으로 진행하였습니다.
※ 참… ChatGPT 유료 구독과는 별개로 OpenAI API Key 가 있어야 합니다.
OpenAI API자, 이제 시작하겠습니다.
먼저, Grimoire 한테 Apps Script를 만들고 싶다고 얘기를 합니다.
이러면.. Grimoire가 자기 소개와 함께 이 작업을 진행하는 단계, 그리고 예시 코드를 만들어 줍니다.
(거의 80% 이상 ??? 작업이 끝납니다..ㅎㅎ)
참고로 Grimoire GPTs는 답변을 할 때, 이렇게 문제 해결의 단계를 먼저 안내를 해 줍니다.(Recipe Prompt Pattern이 적용 된 듯)
예시로 준 코드에서 몇 가지 수정이 필요해 보이는데요.
( 9기 문과생도AI 실습 과제가 도움이 되었습니다~^^)
1) 사용하는 모델 : davinci가 아니라 gpt-3.5-turbo 모델로 변경
2) 모델 변경에 따른 endpoint url 수정.
3) 보안을 위해 API_Key를 apps script 속성으로 지정.
여기서 잠시 Grimoire와의 대화를 이어가기 전에 구글 스프레드시트에서 준비 작업을 진행합니다.
“제목 없는 프로젝트”를 적당한 다른 이름으로 변경합니다. (예 : GPT함수 만들기)
이제 위의 내용을 반영하여 Grimoire에게 수정해 달라고 요청합니다.
function callChatGPT() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var questionCell = sheet.getRange("A1"); // 질문이 입력될 셀
var responseCell = sheet.getRange("B1"); // 응답이 표시될 셀
var question = questionCell.getValue();
if (question) {
var response = getChatGPTResponse(question);
responseCell.setValue(response);
} else {
responseCell.setValue("질문을 입력하세요.");
}
}
function getChatGPTResponse(question) {
var url = "https://api.openai.com/v1/completions";
var payload = {
model: "gpt-3.5-turbo",
prompt: question,
max_tokens: 150
};
var scriptProperties = PropertiesService.getScriptProperties();
var apiKey = scriptProperties.getProperty("API_KEY");
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + apiKey
},
payload: JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(response.getContentText());
return result.choices[0].text.trim();
}
수정된 Apps Script 코드를 복사한 다음, 위에서 열어 놓은 Apps Script 편집기의 “function myFunction()~~~” 라는 곳에 붙여 넣습니다.(기존 myFunction ~~~ 은 삭제)
그리고, 저장(1번) → 실행(2번) !!
이 때, 권한 승인이 필요하다는 창이 뜨는데요. 이것은 계속 오케이 하는 방향으로 진행하시면 됩니다.
이제 OpenAI API Key를 스크립트 속성에 추가해 줍니다.
여기까지 한 다음 스크립트 편집기 위에 있는 “실행” 버튼을 누르면 다음과 같은 error가 나오는데요.
말 그대로 endpoint 주소가 v1/completions 이 아닌, v1/chat/completions 이라는 뜻인데요.
이 에러문을 그대로 Grimoire에게 넣고 물어 보면, 다음과 같은 답변과 함께 수정 코드를 생성해 줍니다.
function callChatGPT() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var questionCell = sheet.getRange("A1"); // 질문이 입력될 셀
var responseCell = sheet.getRange("B1"); // 응답이 표시될 셀
var question = questionCell.getValue();
if (question) {
var response = getChatGPTResponse(question);
responseCell.setValue(response);
} else {
responseCell.setValue("질문을 입력하세요.");
}
}
function getChatGPTResponse(question) {
var url = "https://api.openai.com/v1/chat/completions"; // URL 수정
var payload = {
model: "gpt-3.5-turbo",
messages: [{
role: "system",
content: "This is a test message for the ChatGPT model."
}, {
role: "user",
content: question
}]
};
var scriptProperties = PropertiesService.getScriptProperties();
var apiKey = scriptProperties.getProperty("API_KEY");
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + apiKey
},
payload: JSON.stringify(payload)
};
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(response.getContentText());
return result.choices[0].message.content.trim();
}
이렇게 수정된 코드를 다시 Script 편집기에 복사 / 붙여 넣기 한 후 실행을 시키면.. 이상 없이 실행이 되었습니다.
아.. 그런데.. 이제 다 되었다고 생각하는 찰나.. 이상한 걸 발견했습니다.
function callChatGPT() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var questionCell = sheet.getRange("A1"); // 질문이 입력될 셀
var responseCell = sheet.getRange("B1"); // 응답이 표시될 셀
var question = questionCell.getValue();
if (question) {
이 부분인데요. 질문이 입력된 셀이 A1, 응답이 표시될 셀이 B1으로 고정되어 있는 겁니다…
원래 GPT() 함수 처럼.. 프롬프트가 있는 셀의 값을 함수의 파라미터로 넣고.. 함수가 사용된 셀에 결과값이 나오도록 되어야 하는데 말이죠..
그래서 , 마지막으로 이 부분에 대한 수정을 요청하였습니다. 그리고, 함수명도 너무 긴 것 같아서 myGPT()로 수정하였습니다.
이렇게 해서 나온 최종 결과는 다음과 같습니다.
/**
* 스프레드시트의 셀에서 직접 호출할 수 있는 myGPT 함수
*
* @param {string} prompt ChatGPT에게 전달할 프롬프트
* @return {string} ChatGPT의 응답
* @customfunction
*/
function myGPT(prompt) {
if (!prompt) {
return "프롬프트를 입력하세요.";
}
var url = "https://api.openai.com/v1/chat/completions";
var payload = {
model: "gpt-3.5-turbo",
messages: [{
role: "system",
content: "This is a test message for the ChatGPT model."
}, {
role: "user",
content: prompt
}]
};
var scriptProperties = PropertiesService.getScriptProperties();
var apiKey = scriptProperties.getProperty("API_KEY");
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + apiKey
},
payload: JSON.stringify(payload)
};
try {
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(response.getContentText());
return result.choices[0].message.content.trim();
} catch (e) {
return "오류: " + e.message;
}
}
최종 스크립트를 복사해 넣고, 실행을 눌려 보면 이상이 없다고 나오고.. 이제 스프레드 시트 창으로 돌아 와서 함수를 사용하면 다음과 같은 결과를 얻을 수 있습니다.
마지막으로 이 상태로 두게 되면 이 파일을 열 때 마다 자동으로 OpenAI API가 호출이 되어 비용이 발생하게 됩니다. 이를 방지하기 위해 8기 때 캔로봇님이 알려 주신 팁을 적용해 보았습니다.
이상으로 구글 스프레드시트에서 OpenAI API를 호출하는 함수를 Apps Script로 만드는 과정을 정리해 보았는데요.
과정 자체가 실제로는 그리 복잡하지 않지만, Apps Script나 OpenAI API를 잘 모르는 상태에서 조금씩 배우면서 하려다 보니.. 중간 중간 고민의 포인트 가 있었는데요..
그런 경험을 최대한 살려서 가급적 세세하게 작성해 보았습니다.
이 점 참고해 주세요~
그럼, 이만!!
(선 등록 후 수정하도록 하겠습니다.)
#9기문과생도AI