logo

  • 로그인
  • 회원가입
  • 페이스북 트위터 블로그

  • HOME
    • 메인페이지
    • link
  • 교무업무자료
    • 교무업무자료
      • 교무업무유틸
      • 교무업무 PPT
    • 학습지도안
    • 브로슈어
    • 교육정보자료
    • 제작영상
  • 수능학습자료
    • 수능기출문제
    • 모의수능기출
    • 학력평가기출
    • 인터넷 강의
      • 인터넷 강의2
      • my_vod
      • 해설강의와이드
      • 해설강의
    • 자기소개서
    • 학교생활종합
    • 세특참고자료
    • 자율활동기록
  • 교육 과정 자료
    • 교육과정자료
      • 수학
      • 수학1
      • 수학2
      • 미적분
      • 단원별기출문제
      • 기하 와 벡터
    • 학력평가1학년
    • 학력평가2학년
    • 학력평가3학년
    • 영재교육
    • 수학교재
      • 플래시학습자료
  • 커뮤니티
    • 커뮤니티
    • 공지사항
    • 자료실
    • 멀티 포토
      • 갤러리
    • 홈페이지
      • 사용방법
    • 웹하드
  • 홈페이지 자료
    • 플래시 자료
    • 디자인 자료
    • PPT 자료
    • 학습하기(NEW)
    • 폰트소스
    • php java
      • 홈피update
    • sound 자료
  • goodnews
    • good news
    • 수화찬양
    • CCM찬양
    • 동영상
    • 동영상자료
      • 영어듣기
    • 교회자료실

브라우저를 닫더라도 로그인이 계속 유지될 수 있습니다. 로그인 유지 기능을 사용할 경우 다음 접속부터는 로그인할 필요가 없습니다. 단, PC방, 학교, 도서관 등 공공장소에서 이용 시 개인정보가 유출될 수 있으니 꼭 로그아웃을 해주세요.

  • 아이디/비밀번호찾기  신규회원가입
  • 인증메일재발송
  • 커뮤니티
  • 공지사항
  • 자료실
  • 멀티 포토
    • 갤러리
  • 홈페이지
    • 사용방법
  • 웹하드

피드백 예시

2026.01.31 13:51

맥가이버 조회 수:15

const OPENAI_API_KEY = "본인APIKEY";

// ⚠️ 반드시 여기에 본인의 OpenAI API 키를 넣으세요! (sk-로 시작)

 

function onOpen() {

  const ui = SpreadsheetApp.getUi();

  ui.createMenu('✨ AI 기능')

    .addItem('기존 데이터 피드백 생성 (전체)', 'processExistingRows')

    .addItem('🔍 단일 행 테스트 (현재 선택)', 'testSingleRow')

    .addToUi();

}

 

// ✨ 테스트용 함수

function testSingleRow() {

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  const currentRow = sheet.getActiveRange().getRow();

 

  if (currentRow < 2) {

    SpreadsheetApp.getUi().alert("3행 이상을 선택해주세요.");

    return;

  }

 

  const row = sheet.getRange(currentRow, 1, 1, 10).getValues()[0];

  const data5to11 = row.slice(4, 10);

  const combinedAnswers = data5to11.join("\n- ");

 

  const prompt = createPrompt(combinedAnswers);

  Logger.log("=== 프롬프트 ===");

  Logger.log(prompt);

 

  const result = callOpenAI(prompt);

  Logger.log("=== 결과 ===");

  Logger.log(result);

 

  sheet.getRange(currentRow, 11).setValue(result);

  SpreadsheetApp.getUi().alert(`결과:\n${result}`);

}

 

function processExistingRows() {

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  const lastRow = sheet.getLastRow();

 

  if (lastRow < 2) {

    SpreadsheetApp.getUi().alert("처리할 데이터가 없습니다.");

    return;

  }

 

  const dataRange = sheet.getRange(2, 1, lastRow - 1, 10);

  const data = dataRange.getValues();

 

  let successCount = 0;

  let failCount = 0;

 

  data.forEach((row, index) => {

    const currentRow = index + 2;

    const existingFeedback = sheet.getRange(currentRow, 11).getValue();

   

    if (!existingFeedback || existingFeedback.toString().includes("오류")) {

      const data5to11 = row.slice(4, 10);

      const combinedAnswers = data5to11.join("\n- ");

     

      const prompt = createPrompt(combinedAnswers);

      const result = callOpenAI(prompt);

     

      if (result && !result.includes("오류")) {

        successCount++;

      } else {

        failCount++;

      }

     

      sheet.getRange(currentRow, 11).setValue(result);

      Utilities.sleep(1000);

    }

  });

 

  SpreadsheetApp.getUi().alert(`작업 완료!\n성공: ${successCount}개\n실패: ${failCount}개`);

}

 

// ✨ 프롬프트 생성 함수

function createPrompt(combinedAnswers) {

  return `다음은 중학교 학생의 수학 학습 설문 답변입니다.

학생의 답변을 읽고, 따뜻하고 격려하는 피드백을 정확히 2문장으로 작성해주세요.

 

[작성 규칙]

- 1문장: 학생 답변의 긍정적인 부분을 구체적으로 칭찬

- 2문장: 성장을 위한 실천 가능한 조언이나 격려

- 반말 사용 (예: ~야, ~거야, ~네, ~어)

- 반드시 2문장으로 완성

- 문장 끝을 명확하게 (마침표, 느낌표 사용)

 

[예시]

답변: 수학은 어렵지만 문제를 풀면 뿌듯해요.

피드백: 어려움 속에서도 문제를 해결하려는 노력이 정말 멋져. 그 성취감을 계속 느끼면서 한 걸음씩 나아가면 수학 실력이 쑥쑥 자랄 거야.

 

[학생 답변]

${combinedAnswers}

 

위 답변에 대한 피드백 (정확히 3문장):`;

}

 

// ✨ OpenAI API 호출 함수

function callOpenAI(prompt) {

  if (!OPENAI_API_KEY || OPENAI_API_KEY.trim() === "" || !OPENAI_API_KEY.startsWith("sk-")) {

    return "⚠️ 오류: OpenAI API 키를 입력해주세요. (sk-로 시작해야 합니다)";

  }

 

  try {

    const url = "https://api.openai.com/v1/chat/completions";

   

    const payload = {

      "model": "gpt-4o-mini",  // 비용 효율적인 모델 (gpt-4o, gpt-4-turbo, gpt-3.5-turbo도 가능)

      "messages": [

        {

          "role": "system",

          "content": "당신은 학생 개개인의 생각을 존중하고 성장을 응원하는 중학교 수학 선생님입니다. 항상 2문장으로 피드백을 작성합니다."

        },

        {

          "role": "user",

          "content": prompt

        }

      ],

      "temperature": 0.8,

      "max_tokens": 700

    };

   

    const options = {

      "method": "post",

      "contentType": "application/json",

      "headers": {

        "Authorization": `Bearer ${OPENAI_API_KEY}`

      },

      "payload": JSON.stringify(payload),

      "muteHttpExceptions": true

    };

   

    const response = UrlFetchApp.fetch(url, options);

    const responseCode = response.getResponseCode();

    const responseText = response.getContentText();

   

    Logger.log(`응답 코드: ${responseCode}`);

   

    if (responseCode !== 200) {

      Logger.log(`응답 내용: ${responseText}`);

      const errorJson = JSON.parse(responseText);

      if (errorJson.error) {

        return `⚠️ OpenAI API 오류: ${errorJson.error.message}`;

      }

      return `⚠️ HTTP 오류 ${responseCode}`;

    }

   

    const json = JSON.parse(responseText);

   

    if (json.error) {

      Logger.log(`API 에러: ${JSON.stringify(json.error)}`);

      return `⚠️ API 에러: ${json.error.message}`;

    }

   

    if (!json.choices || json.choices.length === 0) {

      Logger.log("choices 없음");

      return "⚠️ 응답 생성 실패";

    }

   

    const choice = json.choices[0];

   

    // finish_reason 체크

    Logger.log(`finish_reason: ${choice.finish_reason}`);

   

    if (choice.finish_reason === "content_filter") {

      return "⚠️ 콘텐츠 필터에 의해 차단됨";

    }

   

    if (choice.finish_reason === "length") {

      return "⚠️ 토큰 제한 초과";

    }

   

    if (!choice.message || !choice.message.content) {

      Logger.log("message.content 없음");

      return "⚠️ 응답 내용 없음";

    }

   

    const text = choice.message.content.trim();

   

    if (text === "") {

      return "⚠️ 빈 응답";

    }

   

    Logger.log(`생성된 텍스트: ${text}`);

    return text;

   

  } catch (e) {

    Logger.log(`예외 발생: ${e.toString()}`);

    return `⚠️ 시스템 오류: ${e.message}`;

  }

}

이 게시물을
  • Twitter
  • Facebook
  • Delicious
목록

댓글 0

목록
번호 제목 글쓴이 날짜 조회 수
공지 2023worship 맥가이버 2023.01.01 329
공지 worship 맥가이버 2021.03.21 541
공지 새소식반 맥가이버 2021.03.21 476
1017 수열의 합 장영조 2006.06.01 380
1016 하노이 탑 장영조 2006.06.01 590
1015 123 file 장영조 2006.06.23 350
1014 연습문제 장영조 2006.09.09 394
1013 링크 장영조 2006.09.12 357
1012 ping 테스트에서 time,ttl,lost 의 개념이 무엇인지 알려주세요 장영조 2006.09.19 542
1011 SATA는 뭐고 RAID는 뭡니까? 장영조 2007.01.28 367
1010 학습관리시스템 트리 file 장영조 2008.04.05 364
1009 견적서 장영조 2008.04.20 494
1008 로그인 에러 file 장영조 2009.03.09 364
1007 720*489변환 file 장영조 2009.04.04 387
1006 보이스 웨어 자료 장영조 2009.06.22 402
1005 하나님의꿈 file 장영조 2010.04.21 351
1004 코덱설정 divx v5.0.2 file 장영조 2010.04.23 346
1003 검정 교과서 구입방법 장영조 2010.05.31 374
1002 날세우시네 file 장영조 2010.06.21 401
1001 특수 효과 안내 장영조 2010.07.21 392
1000 jw 플레이어 설정 안내 장영조 2010.08.24 365
999 에펙 에러 장영조 2010.11.02 1721
998 윈도우 탐색기에서 mov(QuickTime) 파일 미리보기 file 장영조 2010.11.08 1446
첫 페이지 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 끝 페이지
쓰기
태그
logo
  • 학습도움방
  • 주간계획
  • 각종통계조사
  • api 연동
  • 업로드
COPYRIGHT © ALL RIGHTS RESERVED.
관련사이트