Gemini로 Google Chat용 앱 빌드

1. 시작하기 전에

Gemini를 사용하는 Google Chat 앱이란 무엇인가요?

Gemini를 사용하는 Google Chat 앱은 다음을 수행합니다.

  • 서비스와 리소스를 Google Chat으로 가져와 사용자가 대화에서 나가지 않고도 정보를 얻고 작업을 실행하도록 합니다.
  • 생성형 AI 모델인 Gemini와 통합하여 특정 시점에 텍스트나 이미지와 같은 데이터를 만들거나 검색하여 워크플로를 간소화할 수 있습니다.

Google Chat 앱을 Gemini와 통합해야 하는 이유는 무엇인가요?

Gemini와 같은 생성형 AI 모델의 일반적인 사용 사례는 다음과 같은 카테고리로 분류됩니다.

  • 콘텐츠 제작 및 개선. 마케팅 문구를 작성하거나, 소셜 미디어 게시물을 작성하거나, 사실적인 이미지를 만들거나, 음악을 작곡하거나, 동영상 콘텐츠 제작 관련 도움을 받을 수 있습니다.
  • 데이터 검색. 구조화되지 않은 기술 자료에서 주요 정보를 추출하거나, 긴 텍스트를 요약하거나, 콘텐츠를 분류하거나, 향상된 정확성과 속도로 언어를 번역할 수 있습니다.
  • 대화. 자연스럽고 유익하며 창의적인 대화를 나눌 수 있습니다.

이러한 기능을 익숙한 Google Chat 인터페이스 내에서 직접 통합할 수 있다는 것은 사용자 경험과 생산성을 개선하고자 하는 모든 사람에게 엄청난 기회입니다.

기본 요건

빌드할 항목

이 Codelab에서는 Gemini로 Google Chat 앱 3개를 빌드하여 이전 섹션에서 소개한 세 가지 사용 사례를 다룹니다.

문제 관리 앱(콘텐츠 제작 및 개선)

이 앱에서 다음 작업을 실행합니다.

  • 생성부터 종료까지 기본적인 상호작용, 앱 홈, 앱 인증을 통해 문제를 관리합니다.
  • 메시지를 모니터링하고 이벤트 및 액세서리 위젯을 사용하여 포용성 지원을 제공합니다.

Gemini를 사용하여 다음 작업을 할 수 있습니다.

  • 메시지 기록 및 문제 세부정보를 기반으로 문제 보고서를 생성합니다.
  • 비공개 프롬프트가 있는 메시지에서 포용적이지 않은 단어를 분류합니다.

사용되는 기본 기술은 Vertex AI, Gemini, Apps Script, Google Workspace API(Admin, Chat, Docs, Events)입니다.

22efdecff4601417.png

2d127c63518673b2.png

9aea694937f2f3ed.png

이 앱은 Gemini를 사용하여 자연어로 질문을 이해하고 답하며 구조화되지 않은 데이터에서 가져온 소스 참조를 반환합니다.

사용되는 주요 기술은 Dialogflow CX 데이터 스토어 에이전트, Dialogflow CX 웹훅, Google Cloud Functions, Gemini입니다.

9468866bfe848bb8.png

의견 앱(대화)

이 앱은 Gemini를 사용하여 자연어 대화를 통한 검토를 수집하고 저장합니다.

사용되는 주요 기술은 Dialogflow CX 에이전트, Dialogflow CX 도구, OpenAPI, Google Cloud Functions, Gemini입니다.

99a7a0295f122f31.png

학습 내용

  • Vertex AI를 통해 Google Chat 앱을 Gemini와 통합하는 방법
  • Google Chat 앱을 Dialogflow CX 에이전트와 통합하는 방법
  • Google Chat의 최신 기능(앱 홈, Google Chat 일정, 액세서리 위젯)을 사용하는 방법

필요한 항목

2. 설정

리소스 초기화

이 섹션에서는 원하는 웹브라우저에서 다음 리소스에 액세스하고 구성합니다.

Apps Script 프로젝트

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 설정을 클릭한 다음 Google Apps Script API를 사용 설정합니다.

ea06c593b347b9d1.png

  1. 프로젝트를 선택합니다.
  2. 프로젝트 설정을 클릭합니다.
  3. 편집기에 'appsscript.json' 매니페스트 파일 표시 체크박스를 선택합니다.
  4. 프로젝트 이름을 Chat Apps Gemini로 바꿉니다.

12c1485bd248b766.png

Google Cloud 프로젝트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 메뉴 ☰ > API 및 서비스 > OAuth 동의 화면 > 앱 수정을 클릭한 다음 앱 이름Chat Apps Gemini로 설정합니다.

  1. Google Chat API 구성으로 이동한 다음 앱 이름설명Chat Apps Gemini로 설정합니다.

a71f040755da3b8b.png

Google Chat

Google Chat에서 다음 단계를 따르세요.

  1. 필요한 경우 Google Chat 앱과 채팅을 시작합니다.
  2. Hello와 같은 메시지를 보내 제대로 작동하는지 확인합니다.

9625418251528ae9.png

로컬에서 소스 코드 및 리소스 다운로드

  1. 이 GitHub 저장소를 다운로드합니다.

  1. 원하는 개발 환경에서 apps-script/chat-apps-gemini 디렉터리를 열고 터미널에서 동일한 디렉터리로 이동합니다.

da9478df97c99194.png

clasp 설치 및 구성

Google에서는 clasp을 사용하여 소스 코드 버전을 쉽게 수정하고 로컬 환경에서 Apps Script 프로젝트로 푸시합니다.

  1. 로컬 환경에서 node, npm, clasp의 최신 버전을 설치합니다.
npm install -g @google/clasp
  1. 다음 계정으로 로그인합니다.
clasp login

8bc2434e6dc6f22a.png

성공하면 웹브라우저에 기본 확인 화면이 표시되고 클라이언트 사용자 인증 정보가 포함된 .clasprc.json 파일이 업데이트됩니다. 터미널에서 위치를 확인할 수 있습니다.

e1d833eb4d5b3a8f.png

3. 앱 1: 빌드

개념 검토

Vertex AI

Vertex AI는 AI 솔루션, 에이전트 빌더, 130개가 넘는 기반 모델, 통합 AI 플랫폼 등 생성형 AI를 빌드하고 사용하는 데 필요한 모든 것을 제공합니다.

c9e9c7a1945b22ac.png

Gemini

Gemini는 Vertex AI를 통해 액세스할 수 있는 Google의 멀티모달 LLM입니다. AI는 사람들이 상상력을 키우고, 호기심을 확대하고, 생산성을 높여 인간의 잠재력을 깨워주는 데 도움이 됩니다.

고급 Chat 서비스

고급 Chat 서비스를 통해 Apps Script에서 Google Chat API를 사용할 수 있습니다. 스크립트를 통해 Chat 스페이스를 검색, 생성, 수정하고, 스페이스에 참여자를 추가 또는 삭제하고, 텍스트, 카드, 첨부파일, 반응이 포함된 메시지를 읽거나 게시할 수 있습니다.

아키텍처 검토

8c9c7b7328a69ea6.png

이 Google Chat 앱은 Apps Script로 빌드되었습니다. 작동 방식은 다음과 같습니다.

  1. 사용자가 채팅 메시지 또는 스페이스를 통해 앱에 메시지를 보냅니다.
  2. Apps Script 프로젝트에 구현되고 Google Cloud 프로젝트와 연결된 앱이 메시지를 처리합니다.
  3. 앱은 Google Docs 및 Google Chat API와 통합됩니다.
  4. 앱이 속성 서비스를 사용하여 데이터를 스크립트 속성에 유지합니다.
  5. 앱이 채팅 메시지나 원래 스페이스에서 동기 응답을 보냅니다.

흐름 검토

문제 만들기

7ca0e8ba3c8255bb.png

전용 스페이스에서 문제 해결

51b47714c378a24b.png

전용 스페이스에서 문제 닫기

89e50228deeab0f9.png

소스 코드 검토

Apps Script 프로젝트에는 다음 스크립트가 포함되어 있습니다.

  • Configuration: 환경에 따라 수정할 상수입니다.
  • ChatApp: 메시지, 카드 클릭, 슬래시 명령어, 대화상자 등 Google Chat 상호작용 이벤트를 처리합니다.
  • Storage: 속성 서비스를 사용하는 유틸리티 함수입니다.
  • ChatAppAuth: Google Chat 앱 인증을 사용하는 유틸리티 함수입니다.
  • Docs: Google Docs를 사용하는 유틸리티 함수입니다.
  • VertexAi: Vertex AI를 사용하는 유틸리티 함수입니다.

Gemini 및 Chat 스페이스 기록으로 보고서 문서를 생성할 때 활발하게 사용되는 부분은 다음과 같습니다.

appsscript.json

// Enables the Admin SDK Directory and Chat services, which you need to retrieve
// messages and usernames.

"enabledAdvancedServices": [
  ...
  {
    "userSymbol": "AdminDirectory",
    "version": "directory_v1",
    "serviceId": "admin"
  },
  {
    "userSymbol": "Chat",
    "version": "v1",
    "serviceId": "chat"
  }
  ...
]
// Includes the OAuth scopes to request the Admin SDK Directory, Google Chat,
// Google Docs, and Vertex AI APIs.

"oauthScopes": [
  ...
  "https://www.googleapis.com/auth/admin.directory.user.readonly",
  "https://www.googleapis.com/auth/chat.messages.readonly",
  "https://www.googleapis.com/auth/documents",
  "https://www.googleapis.com/auth/cloud-platform",
  ...
]

Configuration.js

// Relies on two constants: the first one is the Google Cloud project ID and the
// second one is the Vertex AI location to be used.

...
const PROJECT_ID = 'replace-with-gcp-project-id';
const VERTEX_AI_LOCATION_ID = 'us-central1';
...

ChatApp.js

// The slash command process function retrieves history, generates content, and passes
// it to the report generator.

function processSlashCommand(event) {
  ...
  if (event.message.slashCommand.commandId == CLOSE_COMMAND_ID
    && event.message.space.type !== "DM") {
    ...
    const history = exportSpaceHistory(spaceId);
    const summary = summarizeSpace(history);
    const docUrl = createReport(
      issue.title, issue.description, resolution, history, summary
    );
    ...
  }
  ...
}
/**
 * Fetches and concatenates the 100 first space messages by using the Google Chat API.
 *
 * Messages with slash commands are filtered (app command invocations).
 *
 * @return {string} concatenate space messages in the format "Sender's name: Message"
 */
function exportSpaceHistory(spaceName) {
  const messages = Chat.Spaces.Messages.list(spaceName, { 'pageSize': 100 }).messages;
  // Returns results after fetching message sender display names.
  let users = new Map();
  return messages
    .filter(message => message.slashCommand === undefined)
    .map(message =>
      `${getUserDisplayName(users, message.sender.name)}: ${message.text}`
    ).join('\n');
}
/**
 * Fetches a user's display name by using the Admin Directory API.
 *
 * A cache is used to only call the API once per user.
 *
 * @param {Map} cache the map containing users previously fetched
 * @param {string} userId the user ID to fetch
 * @return {string} the user's display name
 */
function getUserDisplayName(cache, userId) {
  if (cache.has(userId)) {
    return cache.get(userId);
  }
  let displayName = 'Unknown User';
  try {
    const user = AdminDirectory.Users.get(
      userId.replace("users/", ""),
      { projection: 'BASIC', viewType: 'domain_public' });
    displayName = user.name.displayName ? user.name.displayName : user.name.fullName;
  } catch (e) {
    // Ignores errors, uses 'Unknown User' by default.
  }
  cache.set(userId, displayName);
  return displayName;
}

VertexAi.js

/**
 * Summarizes a Google Chat space history with the Gemini Pro model using
 * Vertex AI API.
 *
 * @param {string} history the history
 * @return {string} the summary
 */
function summarizeSpace(history) {
  const url = `https://${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1`
    + `/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION_ID}`
    + "/publishers/google/models/gemini-1.0-pro:generateContent";
  const options = {
    method: "POST",
    headers: { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    contentType: "application/json",
    payload: JSON.stringify({
      contents: {
        role: "user",
        parts: {
          text: "Summarize the following conversation between engineers resolving"
              + " an issue in a few sentences.\n\n" + history
        }
      },
      safetySettings: {
        category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
        threshold: "BLOCK_LOW_AND_ABOVE"
      },
      generationConfig: {
        temperature: 0.2,
        topP: 0.8,
        topK: 40
      }
    })
  };

  return JSON.parse(UrlFetchApp.fetch(url, options).getContentText())
    .candidates[0].content.parts[0].text;
}

Docs.js

// The report generator function adds two sections: the first one is for the summary and the second one is for history.
function createReport(..., history, summary) {
  ...
  body.appendParagraph("Summary").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(summary);
  body.appendParagraph("History").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(history);
  ...
}

Google Cloud 프로젝트 업데이트

API 사용 설정

  1. Google Cloud 콘솔에서 Google Docs, Google Admin SDK, Vertex AI API를 사용 설정합니다.

  1. 메뉴 ☰ > API 및 서비스 > 사용 설정된 API 및 서비스를 클릭한 다음 API가 사용 설정되었는지 확인합니다.

서비스 계정 시작

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > IAM 및 관리자 > 서비스 계정 > + 서비스 계정 만들기를 클릭합니다.

74cf57426419f39.png

  1. 서비스 계정 이름chat-app으로 설정합니다.
  2. 서비스 계정 설명Chat app auth로 설정합니다.
  3. 만들고 계속하기를 클릭합니다.
  4. 완료를 클릭합니다. 서비스 계정 페이지로 리디렉션되고 만든 서비스 계정을 볼 수 있습니다.

ca0468f1f93990f9.png

  1. 새로 만든 서비스 계정을 선택합니다.
  2. 탭을 선택합니다.
  3. 키 추가를 클릭합니다.
  4. 새 키 만들기를 클릭합니다.
  5. JSON을 선택합니다.
  6. 만들기를 클릭합니다.

9f7e6ea020978ab0.png

대화상자가 닫히고 새로 생성된 공개 키/비공개 키 쌍이 자동으로 로컬 환경에 JSON 파일로 다운로드됩니다. 이 파일은 나중에 Apps Script 프로젝트의 소스 코드를 수정할 때 사용됩니다.

Google Chat API 구성 업데이트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 슬래시 명령어를 추가합니다.
  2. 이름/create로 설정합니다.
  3. 명령어 ID1로 설정합니다.
  4. 설명Create a new issue로 설정합니다.
  5. 대화상자 열기 체크박스를 선택합니다.
  6. 다른 슬래시 명령어를 추가합니다.
  7. 이름/close로 설정합니다.
  8. 명령어 ID2로 설정합니다.
  9. 설명Close an issue로 설정합니다.
  10. 저장을 클릭합니다.

bee2e7b63659ab33.png

Apps Script 프로젝트 업데이트

  • 로컬 터미널의 현재 디렉터리를 issue-management/1-baseline으로 변경합니다. 여기에는 소스 코드가 포함되어 있습니다. 소스 코드를 Apps Script 프로젝트에 푸시하기 전에 몇 가지 사항을 구성해야 합니다.

소스 코드 구성

  1. Configuration.js 파일의 JSON 상수 CHAT_CREDENTIALS를 이전에 다운로드한 비공개 키 파일 콘텐츠로 설정합니다.

d721f6bff73c5304.png

  1. Google Cloud 콘솔에서 메뉴 ☰ > IAM 및 관리자 > 설정을 클릭합니다.

  1. 프로젝트 ID를 복사합니다.

82592fa0bd113469.png

  1. Configuration.js 파일에서 문자열 상수 PROJECT_ID를 프로젝트 ID로 설정합니다.

383cee561130ceba.png

clasp 설정 구성

clasp 설정을 초기화하여 소스 코드를 올바른 Apps Script 프로젝트에 푸시하려면 다음 단계를 따르세요.

  1. Apps Script 콘솔에서 프로젝트를 선택합니다.
  2. 프로젝트 설정을 선택합니다.
  3. ID에서 복사를 클릭합니다.

20ea033b6de882c6.png

  1. 현재 디렉터리에서 .clasp.json 파일을 만듭니다.
  2. <your-script-id>를 복사된 ID로 변경합니다.
  3. 결과를 .clasp.json 파일에 복사합니다.
  4. .clasp.json 파일을 저장합니다.
{
  "scriptId": "<your-script-id>"
}

소스 코드 푸시

  • 다음 명령어를 실행합니다.
$clasp push
? Manifest file has been updated. Do you want to push and overwrite? Yes
└─ appsscript.json
└─ ChatApp.js
└─ ChatAppAuth.js
└─ Configuration.js
└─ Docs.js
└─ Storage.js
└─ VertexAi.js
Pushed 7 files.

직접 해 보기

  1. Google Chat에서 앱에 보내는 채팅 메시지로 Hello!를 보냅니다. 앱이 응답하지 않지만 구성을 요청하는 메시지가 표시됩니다.

4c1fc68121dcffed.png

  1. 구성을 클릭합니다.
  2. Google 계정을 선택합니다.
  3. 인증합니다.
  4. 앱을 검토하고 액세스를 허용합니다.

4a2fd7ac5918bf1a.png

성공하면 웹페이지에 기본 확인 화면이 표시되고 원본 메시지에 대한 앱의 실제 응답이 표시됩니다.

acb9065568fe47d2.png

2d6ef9c62f47e082.png

  1. 앱에 다른 채팅 메시지를 보내되 슬래시 명령어 /create를 사용합니다.

be3f3c6eb0f929c1.png

  1. 대화상자에서 제목Issue Title 1로 설정합니다.
  2. 설명을 문제 Description 1로 설정합니다.
  3. 만들기를 클릭합니다.

22efdecff4601417.png

앱에서 다음 작업을 실행합니다.

  1. 대화상자를 닫습니다.
  2. 동일한 제목으로 새로 생성된 문제 전용 스페이스를 만듭니다.
  3. 새로 만든 스페이스에 참여합니다.
  4. 새로 만든 스페이스에 문제 설명이 포함된 메시지를 보냅니다.
  5. 새로 만든 스페이스 링크가 포함된 채팅 메시지를 보냅니다.

3253cec2392e281f.png

  1. 새로 생성된 스페이스에서 슬래시 명령어 /close 및 해결 방법(예: Not reproducible)을 사용하여 메시지를 보냅니다.

132cc4acfc10b98c.png

앱에서 다음 작업을 실행합니다.

  1. Google Docs에서 보고서 문서를 만듭니다.
  2. 새로 생성된 보고서 문서 링크가 포함된 메시지를 문제 전용 스페이스로 보냅니다.

2d127c63518673b2.png

  1. 보고서 문서를 엽니다. 여기에는 기본 정보, 기록, 요약이 포함되어 있습니다.

9aea694937f2f3ed.png

4. 선택사항: 앱 1: 앱 홈 추가

개념 검토

앱 홈은 사용자가 채팅 앱의 채팅 메시지에서 탭에 액세스할 때 채팅 앱이 사용자에게 전송하는 맞춤설정 가능한 카드 메시지입니다. 일반적으로 앱 문서 또는 개요를 표시하는 데 사용됩니다. 기술적으로 처리할 전용 이벤트가 있으며 카드 메시지와 동일한 핵심 원칙을 기반으로 합니다.

65f56f70f67a32e4.png

흐름 검토

문제 관리

10663f5fc107fb3f.png

소스 코드 검토

Apps Script 프로젝트를 수정해야 합니다.

ChatApp.js

/**
 * Handles app home requests in Google Chat.
 * 
 * Displays the latest status of all issues.
 */
function onAppHome() {
  // Generates one card section per issue.
  var sections = [];
  for (var issueKey in appProperties.getProperties()) {
    const issue = JSON.parse(appProperties.getProperty(issueKey));
    if (issue.spaceId) {
      sections.push({
        header: `${issue.status} - ${issue.title}`,
        widgets: [{ textParagraph: {
            text: `Description: ${issue.description}`
          }}, { textParagraph: {
            text: `Resolution: ${issue.resolution}`
          }}, { buttonList: { buttons: [{
              text: "Open space",
              onClick: { openLink: {
                url: `https://mail.google.com/mail/u/0/#chat/space/${issue.spaceId}`
              }}
            }, {
              text: "Open report",
              onClick: { openLink: {
                url: issue.reportUrl !== "" ? issue.reportUrl : "docs.new"
              }},
              disabled: issue.reportUrl === ""
          }]}
        }]
      });
    }
  }

  return { action: { navigations: [{ push_card: {
    sections: sections
  }}]}};
}

Google Cloud 프로젝트 업데이트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 양방향 기능 섹션에서 지원 앱 홈 체크박스를 선택합니다.

97159c1c69ca8303.png

로컬 환경에서 다음 단계를 따르세요.

  1. 터미널의 현재 디렉터리를 issue-management/2-app-home으로 변경합니다. 여기에는 사용해야 하는 소스 코드가 포함되어 있습니다.
  2. issue-management/1-baseline/.clasp.json 파일을 현재 디렉터리에 복사합니다.
  3. issue-management/1-baseline/Configuration.js 파일을 현재 디렉터리에 복사하여 기존 디렉터리를 대체합니다.
  4. 다음 명령어를 실행합니다.
clasp push

직접 해 보기

Google Chat에서 다음 단계를 따르세요.

  1. 슬래시 명령어 /create를 사용하여 앱에 채팅 메시지를 보냅니다. 앱에서 대화상자가 열립니다.
  2. 제목Issue Title 2로 설정합니다.
  3. 설명을 문제 Description 2로 설정합니다.
  4. 만들기를 클릭합니다.

3b2a8690e758f965.png

  1. Google Chat 앱이 있는 스페이스에서 탭을 선택합니다. 생성한 문제의 세부정보를 확인할 수 있습니다.

ed8e32da0e6f2ac6.png

5. 선택사항: 앱 1: 스페이스 모니터링 추가

개념 검토

Pub/Sub

Pub/Sub는 메시지를 생성하는 서비스를 해당 메시지를 처리하는 서비스에서 분리하는 확장 가능한 비동기 메시징 서비스입니다. Pub/Sub를 사용하면 게시자구독자라는 이벤트 제작자 및 소비자 시스템을 만들 수 있습니다. 게시자는 동기식 리모트 프로시져 콜(RPC)이 아니라 이벤트를 브로드캐스트하여 구독자와 비동기적으로 통신합니다.

게시자는 이러한 이벤트가 처리되는 방식이나 시기에 관계없이 Pub/Sub 서비스에 이벤트를 보냅니다. 그런 다음 Pub/Sub는 이벤트에 응답하는 모든 서비스에 이벤트를 전송합니다. RPC를 통해 통신하는 시스템에서 게시자는 구독자가 데이터를 수신할 때까지 기다려야 합니다. 그러나 Pub/Sub에서 비동기 통합은 전반적인 시스템의 유연성과 견고성을 높여줍니다.

주제: 메시지 피드를 나타내는, 이름이 지정된 리소스입니다. 주제를 게시하거나 구독하려면 먼저 주제를 만들어야 합니다.

구독: 주제에 게시된 메시지를 받으려면 해당 주제에 대한 구독을 생성해야 합니다. 구독자 클라이언트는 주제에 게시된 메시지를 수신하고 처리합니다. 한 주제에 여러 구독이 존재할 수 있지만, 한 구독은 하나의 주제에만 연결됩니다.

Google Workspace 이벤트

Google Workspace 이벤트는 리소스가 생성, 업데이트, 삭제되는 등 Google Workspace 리소스의 변경사항을 나타냅니다. 앱은 Google Workspace 리소스를 구독하여 관련 이벤트를 비동기식으로 수신하고 처리할 수 있습니다.

7816e477b112bfb6.png

Google Workspace Events API에서 구독을 통해 앱에 이벤트를 전송하는 방법은 다음과 같습니다.

  1. 앱이 Google Workspace 앱의 리소스(예: 스페이스)를 구독합니다.
  2. 앱이 구독한 리소스가 변경됩니다.
  3. Google Workspace 앱은 앱의 Google Workspace 구독에 대한 알림 엔드포인트 역할을 하는 Pub/Sub의 주제에 이벤트를 전송합니다. 이벤트에는 리소스에서 변경된 사항에 대한 데이터가 포함됩니다.
  4. 앱이 이벤트가 포함된 Pub/Sub 메시지를 처리하고 필요한 경우 작업을 수행합니다.

흐름 검토

문제 만들기(업데이트)

6d7a9d7a68666a80.png

전용 스페이스에서 문제 해결(업데이트)

17e60f052f222456.png

전용 스페이스에서 문제 닫기(업데이트)

742d490ea0b6fe3a.png

구독 처리

de3017100dec6401.png

소스 코드 검토

Apps Script 프로젝트를 수정해야 합니다.

appsscript.json

// Enables the Workspace Events service.

"enabledAdvancedServices": [
  ...
  {
    "userSymbol": "WorkspaceEvents",
    "version": "v1",
    "serviceId": "workspaceevents"
  }
  ...
]

Configuration.js

// Adds two constants: the first one is the Pub/Sub topic ID and the second one
// is the Pub/Sub subscription ID to be used to retrieve Google Workspace events.

...
const GWS_PUBSUB_TOPIC_ID = `projects/${PROJECT_ID}/topics/workspace-events`;
const GWS_PUBSUB_SUBSCRIPTION_ID =
  `projects/${PROJECT_ID}/subscriptions/workspace-events-sub`;
...

ChatApp.js

// Edits the function to delete the subscription at issue closure.

function processSlashCommand(event) {
  ...
  if (event.message.slashCommand.commandId == CLOSE_COMMAND_ID
    && event.message.space.type !== "DM") {
    ...
    deleteSubscription(issue.subscriptionId);
    ...
  }
  ...
}
// Edits the function to create the subscription.

function createIssue(event) {
  ...
  const subscriptionId = createSpaceSubscription(spaceUrl);
  const createdIssue = saveCreatedIssue(..., subscriptionId);
  ...
}
// Edits the function to delete the subscription.

function onRemoveFromSpace(event) {
  ...
  deleteSubscription(issue.subscriptionId);
  ...
}

Storage.js

// Edits the function to keep track of the subscription ID.

function saveCreatedIssue(..., spaceId, subscriptionId) {
  ...
  appProperties.setProperty(spaceId, JSON.stringify({
    ...
    subscriptionId: subscriptionId,
    ...
  }));
  ...
}

WorkspaceEvent.js

/**
 * Creates a new subscription to Google Workspace Events associated to a
 * Google Chat space.
 * 
 * The subscription scope includes message creation events and resources.
 * 
 * @param {string} spaceId the space ID to create a subscription for
 * @return the ID of the newly created subscription
 */
function createSpaceSubscription(spaceId) {
  const operation = WorkspaceEvents.Subscriptions.create({
    targetResource: `//chat.googleapis.com/${spaceId}`,
    eventTypes: ["google.workspace.chat.message.v1.created"],
    notificationEndpoint: { pubsubTopic: GWS_PUBSUB_TOPIC_ID },
    payloadOptions: { includeResource: true },
  });

  return operation.response.name;
}
/**
 * Processes events from subscription by using the Google Cloud PubSub API.
 * 
 * It pulls and acknowledges each event.
 */
function processSubscription() {
  const response = UrlFetchApp.fetch(
    `https://pubsub.googleapis.com/v1/${GWS_PUBSUB_SUBSCRIPTION_ID}:pull`,
    {
      method: "POST",
      contentType: "application/json",
      headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
      payload: JSON.stringify({ maxMessages: 10 })
    }
  );

  const messages = JSON.parse(response.getContentText()).receivedMessages;
  for (var messageIndex in messages) {
    const message = messages[messageIndex];
    const ceType = message.message.attributes["ce-type"];
    const dataStr = Utilities.newBlob(Utilities.base64Decode(message.message.data))
      .getDataAsString();
    if (ceType === "google.workspace.events.subscription.v1.expirationReminder") {
      // Renews subscription.
      renewSubscription(JSON.parse(dataStr).subscription.name);
    } else if (ceType === "google.workspace.chat.message.v1.created") {
      // Processes the message text when it's sent in a space.
      const chatMessage = JSON.parse(dataStr).message;
      if (chatMessage.sender.type !== "BOT") {
        console.log("Message was processed.");
      }
    }
    // Acknowledges successful processing to avoid getting it again next time.
    ackSubscription(message.ackId);
  }
}
/**
 * Acknowledges a subscription event by using the Google Cloud PubSub API.
 * 
 * @param {string} ackId the ID of the event acknowledgment to send
 */
function ackSubscription(ackId) {
  UrlFetchApp.fetch(
    `https://pubsub.googleapis.com/v1/${GWS_PUBSUB_SUBSCRIPTION_ID}:acknowledge`,
    {
      method: "POST",
      contentType: "application/json",
      headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
      payload: JSON.stringify({
        ackIds: [ackId]
      })
    }
  );
}
/**
 * Renews a subscription to Google Workspace Events.
 * 
 * The default time to live option is used.
 * 
 * @param {string} subscriptionId the ID of the subscription to renew
 */
function renewSubscription(subscriptionId) {
  WorkspaceEvents.Subscriptions.patch({ttl: '0s'}, subscriptionId);
}
/**
 * Deletes a subscription to Google Workspace Events.
 * 
 * @param {string} subscriptionId the ID of the subscription to delete
 */
function deleteSubscription(subscriptionId) {
  WorkspaceEvents.Subscriptions.remove(subscriptionId);
}

Google Cloud 프로젝트 업데이트

API 사용 설정

  1. Google Cloud 콘솔에서 Google Workspace 이벤트 및 Pub/Sub를 사용 설정합니다.

  1. 메뉴 ☰ > API 및 서비스 > 사용 설정된 API 및 서비스를 클릭한 다음 둘 다 사용 설정되었는지 확인합니다.

구독 시작

모든 작업공간 이벤트를 게시하려면 Pub/Sub 주제를 만들고 구독해야 합니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Pub/Sub > 주제로 이동합니다.

  1. 주제 만들기를 클릭합니다.
  2. 주제 IDworkspace-events로 설정합니다.
  3. 기본 구독 추가 체크박스를 선택합니다.
  4. 만들기를 클릭합니다.

b39f9a0aec7c9939.png

Google Chat에서 새로 만든 주제에 Pub/Sub 메시지를 게시할 수 있는 액세스 권한을 부여하려면 다음 단계를 따르세요.

  1. 목록에서 주제를 선택합니다.
  2. 권한 탭을 선택합니다.
  3. 새 주 구성원chat-api-push@system.gserviceaccount.com을 추가합니다.
  4. 역할Pub/Sub 게시자를 선택합니다.
  5. 저장을 클릭합니다.

8d4016c37532503.png

Apps Script 프로젝트 업데이트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > IAM 및 관리자 > 설정으로 이동합니다.

  1. 프로젝트 ID를 복사합니다.

82592fa0bd113469.png

로컬 환경에서 다음 단계를 따르세요.

  1. 터미널의 현재 디렉터리를 issue-management/3-message-monitoring로 변경합니다. 필요한 소스 코드가 포함되어 있습니다.
  2. Configuration.js 파일에서 문자열 상수 PROJECT_ID를 복사된 프로젝트 ID로 설정합니다.
  3. Configuration.js 파일의 JSON 상수 CHAT_CREDENTIALS를 이전에 다운로드한 비공개 키 파일 콘텐츠로 설정합니다.
  4. issue-management/2-app-home/.clasp.json 파일을 현재 디렉터리에 복사합니다.
  5. 다음 명령어를 실행합니다.
clasp push

직접 해 보기

Google Chat에서 다음 단계를 따르세요.

  1. 슬래시 명령어 /create를 사용하여 앱에 채팅 메시지를 보냅니다. 앱에서 대화상자가 열립니다.
  2. 제목Issue Title 3로 설정합니다.
  3. 설명을 문제 Description 3로 설정합니다.
  4. 만들기를 클릭합니다.
  5. 새로 생성된 스페이스에서 문제에 관해 설명하는 메시지를 몇 개 보냅니다.
  6. 슬래시 명령어 /close 및 해결 방법(예: Fixed)을 사용하여 메시지를 보냅니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Pub/Sub > 구독으로 이동합니다.

  1. workspace-events-sub 구독을 선택합니다.
  2. 메시지 탭을 선택합니다.
  3. 가져오기를 클릭합니다. 표에는 새로 만든 스페이스에 보낸 내용과 관련된 메시지가 표시됩니다.

82631c9792d83889.png

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 편집기를 선택합니다.
  3. WorkspaceEvent.gs 파일을 선택합니다.
  4. 실행 섹션에서 processSubscription을 선택합니다.
  5. Run을 클릭합니다. 실행 로그에서 메시지가 처리된 것을 확인할 수 있습니다.

c612e8fa2bd0a163.png

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Pub/Sub > 구독으로 이동합니다.

  1. workspace-events-sub 구독을 선택합니다.
  2. 메시지 탭을 선택합니다.
  3. 가져오기를 클릭합니다. 표에는 새로 만든 스페이스에 보낸 내용과 관련된 메시지가 더 이상 표시되지 않습니다.

e185454cac862a7b.png

  • Google Chat에서 슬래시 명령어 /create로 만든 세 번째 문제 전용 스페이스에서 문제를 논의하는 메시지를 몇 개 더 보냅니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Pub/Sub > 구독으로 이동합니다.

  1. workspace-events-sub 구독을 선택합니다.
  2. 메시지 탭을 선택합니다.
  3. 가져오기를 클릭합니다. 표에는 새로 만든 스페이스에 보낸 내용과 관련된 메시지가 표시되지 않습니다.

6. 선택사항: 앱 1: 포용성 도움말 추가

개념 검토

생성형 AI 프롬프팅은 원하는 특정 유형의 출력으로 생성형 AI 모델을 안내하기 위한 지침이나 질문을 작성하는 기술입니다. 프롬프트에 규칙과 조건을 추가하여 답변을 통제하는 것이 일반적입니다. 이를 통해 안전하고, 관련성이 있으며, 일관되고, 기대치에 부합하는 결과물을 제공할 수 있습니다.

흐름 검토

구독 처리(업데이트)

780d0802f77dd180.png

소스 코드 검토

Apps Script 프로젝트를 수정해야 합니다.

WorkspaceEvent.js

// Edits the function to replace logging by an actual card message.

function processSubscription() {
  ...
  for (var messageIndex in messages) {
    ...
    } else if (ceType === "google.workspace.chat.message.v1.created") {
      ...
      const inclusivityCheck = getInclusivityFeedback(chatMessage.text);
      if (inclusivityCheck !== "It's inclusive!") {
        createAppMessageUsingChatService({
          cardsV2: [{ cardId: "1", card: { header: {
              title: "Inclusivity",
              subtitle: `The following words are not inclusive: ${inclusivityCheck}`
          }}}]
        },
        chatMessage.space.name);
      }
      ...
    }
    ...
  }
  ...
}

VertexAi.js

/**
 * Gets feedback on inclusivity for a text with the Gemini Pro model using
 * Vertex AI API.
 * 
 * Returns "It's inclusive!" when it is otherwise a list of word(s) that might not
 * be optimal.
 *
 * @param {string} text the text
 * @return {string} the feedback
 */
function getInclusivityFeedback(text) {
  const url = `https://${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1`
    + `/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION_ID}`
    + "/publishers/google/models/gemini-1.0-pro:generateContent";
  const options =  {
    method: "POST",
    headers: { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    contentType: "application/json",
    payload: JSON.stringify({
      contents: {
        role: "user",
        parts: {
          text: "Are there any words that obviously go against inclusivity "
            + "in this text:"
            + `\n\n----------\n${text}\n----------\n\n`
            + "If there are not, answer \"It's inclusive!\" "
            + "otherwise answer by listing them separated by commas. "
            + "Do not answer with any explanation."
        }
      },
      safetySettings: {
        category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
        threshold: "BLOCK_LOW_AND_ABOVE"
      },
      generationConfig: {
        temperature: 0.2,
        topP: 0.8,
        topK: 40
      }
    })
  };

  return JSON.parse(UrlFetchApp.fetch(url, options).getContentText())
    .candidates[0].content.parts[0].text;
}

Apps Script 프로젝트 업데이트

로컬 환경에서 다음 단계를 따르세요.

  1. 터미널의 현재 디렉터리를 issue-management/4-inclusivity-help로 변경합니다. 필요한 소스 코드가 포함되어 있습니다.
  2. issue-management/3-message-monitoring/.clasp.json 파일을 현재 디렉터리에 복사합니다.
  3. issue-management/3-message-monitoring/Configuration.js 파일을 현재 디렉터리에 복사하여 기존 디렉터리를 대체합니다.
  4. 다음 명령어를 실행합니다.
clasp push

직접 해 보기

Google Chat에서 다음 단계를 따르세요.

  1. 슬래시 명령어 /create를 사용하여 앱에 채팅 메시지를 보냅니다. 앱에서 대화상자가 열립니다.
  2. 제목Issue Title 4로 설정합니다.
  3. 설명을 문제 Description 4로 설정합니다.
  4. 만들기를 클릭합니다.
  5. 새로 만든 스페이스에서 It happened to me last week as well을 전송합니다.

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 편집기를 선택합니다.
  3. WorkspaceEvent.gs 파일을 선택합니다.
  4. 실행 섹션에서 processSubscription을 선택합니다.
  5. 실행을 클릭합니다. 실행 로그에서 메시지가 처리된 것을 확인할 수 있습니다.

Google Chat에서 다음 단계를 따르세요.

  1. 앱이 새로 만들어진 스페이스에 포용성 도움말을 보내지 않았음을 확인합니다.
  2. 새로 만든 스페이스에서 I had to add myself from the master to fix it 메시지를 전송합니다.

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 편집기를 선택합니다.
  3. WorkspaceEvent.gs 파일을 선택합니다.
  4. 실행 섹션에서 processSubscription을 선택합니다.
  5. 실행을 클릭합니다. 실행 로그에서 메시지가 처리된 것을 확인할 수 있습니다. Google Chat에서 앱이 새로 만든 스페이스에 포용성 도움말 메시지를 보냈습니다.

7936342847acbe2d.png

7. 선택사항: 앱 1: 환경설정 추가

.

개념 검토

액세서리 위젯은 앱에서 보낸 메시지의 하단에 첨부된 테두리 없는 위젯입니다. 일반적으로 메시지의 특정 컨텍스트에서 사용자의 빠른 반응을 지원하는 데 사용됩니다. 기술적으로는 카드 버튼과 동일한 핵심 원칙을 기반으로 합니다.

eebe88238f6b13f.png

흐름 검토

포용성 도움말 사용 중지

1bb7a8592ee6221e.png

소스 코드 검토

Apps Script 프로젝트를 수정해야 합니다.

ChatApp.js

// Edits the function to handle the inclusivity help disablement action for a
// given space.

function onCardClick(event) {
  ...
  if (event.action.actionMethodName === "disableInclusivityHelp") {
    disableInclusivityHelp(event.common.parameters.spaceId);
  }
}

Storage.js

// Edits the function to keep track of the inclusivity help setting.

function saveCreatedIssue(title, description, spaceId, subscriptionId) {
  appProperties.setProperty(spaceId, JSON.stringify({
    ...
    inclusivityHelp: true,
    ...
  }));
  ...
}
/**
 * Disables inclusivity help in a space.
 * 
 * @param {string} spaceId the ID of dedicated space of the issue
 */
function disableInclusivityHelp(spaceId) {
  var issue = JSON.parse(appProperties.getProperty(spaceId));
  issue.inclusivityHelp = false;
  appProperties.setProperty(spaceId, JSON.stringify(issue));
}
/**
 * Checks whether the app should help with inclusivity in a given space.
 * 
 * @param {string} spaceId the ID of dedicated space of the issue
 * @return whether the app should help with inclusivity
 */
function shouldHelpWithInclusivity(spaceId) {
  return JSON.parse(appProperties.getProperty(spaceId)).inclusivityHelp;
}

WorkspaceEvent.js

// Edits the function to display the accessory widget to the existing card message.

function processSubscription() {
  ...
  for (var messageIndex in messages) {
    ...
    } else if (ceType === "google.workspace.chat.message.v1.created") {
      ...
      if (... && shouldHelpWithInclusivity(chatMessage.space.name)) {
        createAppMessageUsingChatService({
          ...
          accessoryWidgets: [{ buttonList: { buttons: [{
            altText: "Disable inclusivity help",
            icon: {
              iconUrl: "https://upload.wikimedia.org/.../Stop_hand_rugen.png"
            },
            onClick: { action: {
              function: "disableInclusivityHelp",
              parameters: [{
                key: "spaceId",
                value: chatMessage.space.name
              }]
            }}
          }]}}]
        }, ...);
        ...
      }
      ...
    }
    ...
  }
  ...
}

Apps Script 프로젝트 업데이트

로컬 환경에서 다음 단계를 따르세요.

  1. 터미널의 현재 디렉터리를 issue-management/5-disable-help로 변경합니다. 필요한 소스 코드가 포함되어 있습니다.
  2. issue-management/4-inclusivity-help/.clasp.json 파일을 현재 디렉터리에 복사합니다.
  3. issue-management/4-inclusivity-help/Configuration.js 파일을 현재 디렉터리에 복사하여 기존 디렉터리를 대체합니다.
  4. 다음 명령어를 실행합니다.
clasp push

직접 해 보기

도움말 사용 중지

  • Google Chat에서 슬래시 명령어 /create로 만든 네 번째 문제 전용 스페이스에서 I had to add myself from the master to fix 메시지를 보냅니다.

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 편집기를 선택합니다.
  3. WorkspaceEvent.gs 파일을 선택합니다.
  4. 실행 섹션에서 processSubscription을 선택합니다.
  5. 실행을 클릭합니다. 실행 로그에서 메시지가 처리된 것을 확인할 수 있습니다.

Google Chat에서 다음 단계를 따르세요.

  1. 앱에서 액세서리 위젯 관련 문제 전용 스페이스에 포용성 도움말이 포함된 메시지를 보냈습니다.
  2. 포용성 도움말을 사용 중지하려면 액세서리 위젯을 클릭합니다.

de722cff1928dec9.png

사용 중지 확인

  • Google Chat에서 슬래시 명령어 /create로 만든 네 번째 문제 전용 스페이스에서 I had to add myself from the master to fix 메시지를 보냅니다.

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 편집기를 선택합니다.
  3. WorkspaceEvent.gs 파일을 선택합니다.
  4. 실행 섹션에서 processSubscription을 선택합니다.
  5. 실행을 클릭합니다. 실행 로그에서 메시지가 처리된 것을 확인할 수 있습니다. 앱이 사용 중지되었기 때문에 Google Chat에서는 문제 전용 스페이스에 포용성 도움이 포함된 메시지를 보내지 않았습니다.

347d659db53b73e9.png

8. 앱 2: 빌드

개념 검토

생성형 AI 그라운딩

검증 가능한 지식 출처에 AI 모델을 연결하여 보다 사실에 입각하고 신뢰할 수 있는 모델을 만드는 것입니다. 이 기법은 AI가 정보를 만드는 것을 방지하고 대답을 맥락과 관련성이 높으며 편향되지 않은 상태로 만드는 데 도움이 될 수 있습니다.

자연어

인공 또는 컴퓨터 기반 언어와 달리 인간이 일상적으로 의사소통하기 위해 사용하거나 쓰는 언어입니다.

Cloud Storage

Cloud Storage를 사용하면 데이터 양에 관계없이 언제 어디서나 데이터를 저장하고 가져올 수 있습니다. 웹사이트 콘텐츠를 제공하거나, 데이터를 보관처리하고 재해 복구를 위해 저장하거나, 사용자의 직접 다운로드를 통해 대량의 데이터 객체를 배포하는 등 다양한 용도로 사용할 수 있습니다.

Dialogflow CX 데이터 스토어

Dialogflow CX데이터 스토어 에이전트가 특정 데이터에서 최종 사용자의 질문에 대한 답변을 찾는 데 사용하는 웹사이트 및 문서 모음인 데이터 스토어와 통합됩니다. 특정 질문에 대해 데이터 스토어 에이전트는 제공된 소스 콘텐츠에서 답변을 검색하고 결과를 일관된 응답으로 요약합니다. 또한 최종 사용자가 자세히 알아볼 수 있도록 응답 소스에 대한 지원 링크를 제공합니다.

아키텍처 검토

9d3342d12f3b4dda.png

이 Google Chat 앱은 Dialogflow CX로 빌드되었으며 다음과 같이 작동합니다.

  1. 사용자가 채팅 메시지 또는 스페이스를 통해 앱에 메시지를 보냅니다.
  2. Dialogflow CX 에이전트이며 Google Cloud 프로젝트와 연결된 앱이 메시지를 처리합니다.
  3. 앱이 Cloud Storage에 있는 데이터 스토어와 통합됩니다.
  4. 앱이 채팅 메시지나 원래 스페이스에서 동기 응답을 보냅니다.

흐름 검토

질문에 답하기

aad9fb5a7ca48956.png

소스 코드 검토

필요한 유일한 소스는 코드가 아니라 그라운딩에 사용하는 데이터입니다.

google-chat-overview.pdf

Google Workspace 개발자 웹사이트의 페이지 인쇄 버전인 Google Chat 앱의 구조화되지 않은 정보를 포함합니다.

e9b91c4587b1a3a0.png

Google Cloud 프로젝트 업데이트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. Dialogflow 및 Cloud Storage API를 사용 설정합니다.

  1. Vertex AI Agent Builder API를 사용 설정합니다.

  1. 메뉴 ☰ > API 및 서비스 > 사용 설정된 API 및 서비스를 클릭한 다음 API가 사용 설정되었는지 확인합니다.

.

Dialogflow CX 데이터 스토어 에이전트 만들기

지식 데이터 시작

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Cloud Storage > 버킷을 클릭합니다.

4f15978ae9f1b687.png

  1. 만들기를 클릭합니다.
  2. 이름gchat-knowledge로 설정합니다.
  3. 만들기를 클릭합니다.

6b38c6d4d2c41bba.png

  1. gchat-knowledge 버킷을 선택합니다.
  2. 파일 업로드를 클릭합니다.
  3. 로컬 환경에서 knowledge-app/grounding/google-chat-overview.pdf 파일을 선택합니다.

df89acb22e1762af.png

앱 만들기

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭합니다.

  1. 새 앱을 클릭합니다.
  2. 채팅 유형을 선택합니다.

44276003074bcf14.png

  1. Company name을 회사 이름으로 설정합니다.
  2. Agent nameknowledge로 설정합니다.
  3. 계속을 클릭합니다.

c4fedfd7556f723b.png

  1. 새 데이터 스토어 만들기를 클릭합니다.
  2. 데이터 소스로 Cloud Storage를 선택합니다.

6e2440ecf0f8f9bd.png

  1. 파일을 선택합니다.
  2. 탐색을 클릭합니다.
  3. google-chat-overview.pdf 파일을 선택합니다.
  4. 계속을 클릭합니다.
  5. 데이터 스토어 이름을 gchat-knowledge-ds로 설정합니다.
  6. 만들기를 클릭합니다.

a675df7490b83900.png

  1. 표에서 gchat-knowledge-ds 데이터 스토어를 선택합니다.
  2. 만들기를 클릭합니다.

f121d580771ed96.png

  1. 몇 분 후에 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭하면 앱이 표시됩니다.

d929a7431dd84968.png

  1. 메뉴 ☰ > 에이전트 빌더 > 데이터 스토어를 클릭합니다.

  1. gchat-knowledge-ds 데이터 스토어를 클릭합니다. 문서 수는 1이며, 이는 준비되었음을 나타냅니다.

558319790a0accf2.png

앱 완료 및 테스트

Dialogflow CX 콘솔에서 다음 단계를 따르세요.

  1. Google Cloud 프로젝트를 선택합니다.
  2. 지식 에이전트를 선택합니다.

ca9b2fb4be92e8e4.png

  1. 에이전트 설정 > 생성형 AI > 생성형 에이전트를 선택합니다.
  2. 모델을 Text Bison에서 Gemini Pro로 전환합니다.
  3. 저장을 클릭합니다.

68cc4713ec9b25a0.png

  1. 에이전트 테스트를 클릭합니다.
  2. What is Google Chat?을 보냅니다. 에이전트가 의미 있는 내용으로 응답합니다.

8e3a2cb02469041a.png

Google Chat 앱 통합

Dialogflow CX 콘솔에서 다음 단계를 따르세요.

  1. Google Cloud 프로젝트를 선택합니다.
  2. 지식 에이전트 행에서 1e7ede7abae4aa3c.png > 이름 복사를 클릭합니다.

e19f61185158110d.png

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. Google Chat API 구성으로 이동합니다.

  1. 연결 설정에서 Dialogflow를 선택합니다.
  2. Dialogflow 설정에서 Dialogflow CX를 선택합니다.
  3. 에이전트 또는 환경 리소스 이름을 복사한 에이전트 이름으로 설정합니다.
  4. 슬래시 명령어 2개를 삭제합니다.

505ff39a50880904.png

  1. Google Chat에서 Google Chat 앱에 보내는 채팅 메시지로 What is Google Chat?을 보냅니다. 에이전트가 의미 있는 내용으로 응답합니다.

abda9e43b81fb0ea.png

9. 선택사항: 앱 2: 소스 추가

개념 검토

Dialogflow CX 웹훅

비즈니스 로직을 호스팅하거나 다른 서비스를 호출하는 서비스입니다. Dialogflow CX 세션 중에 웹훅은 자연어 처리에서 추출된 데이터를 사용하여 동적 응답을 생성하거나, 수집된 데이터를 검증하거나, 백엔드에서 작업을 트리거할 수 있습니다.

Cloud Functions

Cloud Functions는 서버리스 백엔드 빌드, 실시간 데이터 처리 수행, 지능형 앱 제작에 적합합니다. 프로비저닝, 관리, 패치, 업데이트가 필요한 서버가 없습니다. 자동으로 확장되며 가용성과 내결함성이 높습니다.

흐름 검토

질문에 답변(업데이트)

92767c07c7b252aa.png

소스 코드 검토

필요한 소스 코드는 Google Chat 메시지에 대한 에이전트 응답을 조정하기 위한 함수뿐입니다. 웹훅으로 사용됩니다.

package.json

// The function relies on the Cloud Functions framework to run.

{
  "name": "agent-response-adapter",
  "version": "0.0.1",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  },
  ...
}

index.js

/** 
 * Handles all incoming requests.
 *
 * It takes a Dialogflow CX agent response as input and returns a
 * valid Google Chat card message with both the text and source links
 */
functions.http('agent-response-adapter', (request, response) => {
  // Creates Google Chat buttons based on the data store agent response
  // grounding details.
  var linkTitles = [];
  var linkButtons = [];
  const grounding = request.body.messages[1].payload.richContent[0][0];
  if (grounding.type === "match_citations") {
    // Supports citation match type.
    grounding.citations.forEach((citation) => {
      // Avoid duplications.
      if (linkTitles.indexOf(citation.title) < 0) {
        linkButtons.push({
          text: citation.title,
          onClick: { openLink: {
            url: citation.actionLink
          }}
        });
        linkTitles.push(citation.title);
      }
    });
  } else if (grounding.type === "info") {
    // Supports info type.
    if (linkTitles.indexOf(grounding.title) < 0) {
      linkButtons.push({
        text: grounding.title,
        onClick: { openLink: {
          url: grounding.actionLink
        }}
      });
      linkTitles.push(grounding.title);
    }
  }

  // Sends the Dialogflow CX fulfillment response to replace the agent response
  // with the Chat message with text and source buttons.
  response.send({ fulfillment_response: {
    merge_behavior: "REPLACE",
    messages: [{ payload: {
      // Reuses the original data store agent response text.
      text: request.body.messages[0].text.text[0],
      cardsV2: [{
        cardId: "sourcesCard",
        card: { sections: [{
          header: "Sources",
          widgets: [{ buttonList: {
            buttons: linkButtons
          }}]
        }]}
      }]
    }}]
  }});
});

Google Cloud 프로젝트 업데이트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. Enable the Cloud Build, Cloud Functions, Cloud Logging, Artifact Registry, Cloud Run API를 사용 설정합니다.

  1. 메뉴 ☰ > API 및 서비스 > 사용 설정된 API 및 서비스를 클릭한 다음 API가 사용 설정되었는지 확인합니다.

Dialogflow CX 데이터 스토어 에이전트 업데이트

가능한 경우 여러 소스로 트리거하도록 Cloud 함수를 배포하고 Dialogflow CX 웹훅을 업데이트해야 합니다.

여러 소스 반환

기본적으로 새 데이터 스토어 에이전트는 최대 한 개의 소스만 반환하지만 여러 소스를 반환하도록 변경할 수 있습니다.

Dialogflow CX 콘솔에서 다음 단계를 따르세요.

  1. Google Cloud 프로젝트를 선택합니다.
  2. 지식 에이전트를 선택합니다.
  3. 시작 페이지를 선택합니다.
  4. 데이터 스토어 수정을 선택합니다.
  5. 에이전트 응답 섹션에서 데이터 스토어 응답 옵션5로 설정합니다.
  6. 저장을 클릭합니다.

f5932d03057df645.png

Cloud 함수 시작

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Cloud Functions를 클릭합니다.

  1. 함수 만들기를 클릭합니다.
  2. 기본설정에서 이름function-1로 설정합니다.
  3. 인증에서 인증되지 않은 호출 허용 라디오 버튼을 선택합니다.
  4. 런타임, 빌드, 연결, 보안 설정에서 최대 인스턴스 수3으로 설정합니다.
  5. 다음을 클릭합니다.

bd3790a9285f9c07.png

  1. 진입점agent-response-adapter로 설정합니다.
  2. 기본 콘텐츠를 knowledge-app/agent-response-adapter 디렉터리에 있는 파일로 바꿉니다.
  3. 배포를 클릭합니다.

b379bb8ca0fc1079.png

  1. 함수가 배포될 때까지 몇 분 정도 기다리는 동안 URL을 복사합니다.

eaae08cf048b9b1c.png

웹훅 시작

새로 배포된 함수를 트리거하는 웹훅을 사용하도록 Dialogflow CX 에이전트를 구성해야 합니다.

Dialogflow CX 콘솔에서 다음 단계를 따르세요.

  1. Google Cloud 프로젝트를 선택합니다.
  2. 지식 에이전트를 선택합니다.
  3. 관리 > 웹훅 > 만들기를 선택합니다.
  4. 표시 이름Google Chat Response Adapter로 설정합니다.
  5. 웹훅 URL을 이전에 복사한 URL로 설정합니다.
  6. 저장을 클릭합니다.

5f3c6804d52b87c1.png

  1. 빌드를 클릭합니다.
  2. 시작 페이지를 선택합니다.
  3. 데이터 스토어 수정을 선택합니다.
  4. 웹훅 설정에서 웹훅 사용 설정 전환 버튼을 클릭합니다.
  5. 웹훅용 Google Chat 응답 어댑터를 선택합니다.
  6. 태그arbitrary_tag로 설정합니다.
  7. 저장을 클릭합니다.

442fcaaec9b8f2e3.png

앱 테스트

  • Google Chat에서 Google Chat 앱에 보내는 채팅 메시지로 What is Google Chat?을 보냅니다. 에이전트가 의미 있는 내용과 소스가 표시된 카드(있는 경우)로 응답합니다.

9468866bfe848bb8.png

10. 앱 3: 빌드

개념 검토

대화형 상호작용

자연어를 통해 두 명 이상의 사람 간에 정보나 아이디어를 주고받는 과정입니다. 이는 종종 스테이트리스(Stateless)이고, 고도로 구조화되고, 편협한 교환에 의존하는 기술 인터페이스와 대조됩니다.

OpenAPI 사양

API 수명 주기의 각 단계를 통해 정보를 전달하는 일관된 수단을 제공합니다. 이는 API가 만들어진 프로그래밍 언어와 일치하지 않는 방식으로 구조와 문법을 정의하는 HTTP API를 위한 사양 언어입니다. API 사양은 일반적으로 YAML 또는 JSON으로 작성되므로 사양을 쉽게 공유하고 사용할 수 있습니다.

Dialogflow CX 에이전트

에이전트 앱의 기본 구성요소입니다. 에이전트 앱에는 일반적으로 여러 에이전트가 있으며 각 에이전트는 특정 태스크를 처리하도록 정의됩니다. 에이전트 데이터는 LLM에 제공되므로, 질문에 답변하고 태스크를 수행하는 데 필요한 정보가 포함됩니다. 각 에이전트는 정보를 제공하거나 쿼리를 외부 서비스에 보내거나 하위 태스크를 처리하도록 대화 처리를 Dialogflow CX 흐름이나 다른 에이전트로 연기할 수 있습니다.

Dialogflow CX 도구

에이전트 앱을 외부 시스템에 연결하는 데 사용되는 도구입니다. 이러한 시스템은 에이전트 앱의 지식을 강화하고 복잡한 작업을 효율적으로 실행할 수 있도록 지원합니다.

아키텍처 검토

9d3342d12f3b4dda.png

이 Google Chat 앱은 Dialogflow CX로 빌드되었으며 다음과 같이 작동합니다.

  1. 사용자가 채팅 메시지 또는 스페이스를 통해 앱에 메시지를 보냅니다.
  2. Dialogflow CX 에이전트이며 Google Cloud 프로젝트와 연결된 앱이 메시지를 처리합니다.
  3. 앱이 에이전트와 통합됩니다.
  4. 앱이 채팅 메시지나 원래 스페이스에서 동기 응답을 보냅니다.

흐름 검토

검토 수집

a67a5b8b513bfc2c.png

소스 코드 검토

필요한 유일한 소스 코드는 에이전트가 도구로 사용하는 백엔드 서비스를 모의 처리하는 함수입니다.

package.json

// The function relies on the Cloud Functions framework to run.

{
  "name": "feedback-app-backend",
  "version": "0.0.1",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  },
  ...
}

index.js

/** 
 * Handles all incoming requests.
 * 
 * It always returns OK in plain text.
 */
functions.http('feedback-app-backend', (request, response) => {
    response.send('OK');
});

service-openapi.yaml

// Defines the backend service structure and how to request it.

openapi: 3.1.0
info:
  title: Review Store
  license:
    name: Apache 2.0
    identifier: Apache-2.0
  version: 0.0.1
servers:
  - url: https://us-central1-project-0.cloudfunctions.net
paths:
  /store-review:
    post:
      operationId: storeReview
      summary: Store a new review
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                stars:
                  type: integer
                  format: int64
      responses:
        '200':
          description: success
          content:
            application/json:
              schema:
                type: string

백엔드 서비스 모의 시작

Cloud 함수를 배포하여 Dialogflow CX 에이전트 앱이 통합하고 도구로 호출해야 하는 백엔드 서비스를 시뮬레이션합니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Cloud Functions를 클릭합니다.

  1. 함수 만들기를 클릭합니다.
  2. 기본설정에서 이름function-2로 설정합니다.
  3. 인증에서 인증되지 않은 호출 허용 라디오 버튼을 선택합니다.
  4. 런타임, 빌드, 연결, 보안 설정에서 최대 인스턴스 수3으로 설정합니다.
  5. 다음을 클릭합니다.

e8cf0ee7441bf634.png

  1. 진입점feedback-app-backend로 설정합니다.
  2. 기본 콘텐츠를 feedback-app 디렉터리에 있는 파일로 바꿉니다.
  3. 배포를 클릭합니다.

bdb5cf9f503aa7f6.png

  1. 함수가 배포될 때까지 몇 분 정도 기다리는 동안 URL을 복사합니다.

Dialogflow CX 에이전트 앱 만들기

앱 만들기

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭합니다.

  1. 새 앱을 클릭합니다.
  2. 에이전트를 선택합니다.
  3. 표시 이름Feedback App으로 설정합니다.
  4. 만들기를 클릭합니다.

7ef3dbacee96c5aa.png

도구 시작

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭합니다.

  1. 의견 앱 에이전트를 선택합니다.
  2. 도구 > + 만들기를 클릭합니다.
  3. 이름review로 설정합니다.
  4. OpenAPI를 선택합니다.
  5. 설명을 다음 값으로 설정합니다.
The tool takes the number of stars as a parameter of the store review method and saves it in a database for later use.
  1. feedback-app/service-openapi.yaml 파일의 $URL을 이전에 복사한 URL로 바꿉니다.
  2. YAML Schemafeedback-app/service-openapi.yaml 파일의 수정된 콘텐츠로 설정합니다.
  3. 저장을 클릭합니다.

58085d6d56b603f7.png

에이전트 시작

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭합니다.

  1. 의견 앱 에이전트를 선택합니다.
  2. 에이전트 > 기본 생성형 에이전트를 선택합니다.
  3. 에이전트 이름Feedback collector로 설정합니다.
  4. goal을 다음 값으로 설정합니다.
You are an agent that collects reviews from Google Chat app developers.
A review may be between 0 and 5 stars. The more stars, the more positive the review.
  1. 요청 사항을 다음 값으로 설정합니다.
If the developer didn't provide the number of stars, ask for the number of stars.
After the developer provides the number of stars of the review, confirm the number with the developer and use ${TOOL: review} to store the review with the number of stars.
If ${TOOL: review} fails, apologize and ask to try again later. Otherwise, thank the developer for the review.
  1. 저장을 클릭합니다.

ebee7fdfa826b487.png

앱 테스트

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > 에이전트 빌더 > 앱을 클릭합니다.

  1. 의견 앱 에이전트를 선택합니다.
  2. 에이전트 미리보기로 이동합니다.
  3. 에이전트에서 의견 수집기를 선택합니다.
  4. 생성 모델 선택에서 gemini-pro를 선택합니다.
  5. 시작하려면 Hello! 메시지를 보냅니다.

90ca8cb7b2c1cb4b.png

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > Cloud Functions를 클릭합니다.

  1. function-2 > 로그를 선택합니다. 일부 로그에는 Google-Dialogflow가 호출자로 표시됩니다.

48bfdf1788004d18.png

Google Chat 앱 통합

Dialogflow CX 콘솔에서 다음 단계를 따르세요.

  1. Google Cloud 프로젝트를 선택합니다.
  2. Feedback App 에이전트의 작업 메뉴를 클릭합니다.
  3. 이름 복사를 클릭합니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. Google Chat API 구성으로 이동합니다.

  1. 에이전트 또는 환경 리소스 이름을 이전에 복사한 에이전트 이름으로 설정합니다.

df16619a1cb85cf8.png

  • 시작하려면 Google Chat에서 Google Chat 앱에 채팅 메시지로 Hello!를 보냅니다. 에이전트는 Dialogflow CX 콘솔에서 진행한 테스트와 유사하게 응답합니다.

99a7a0295f122f31.png

11. 삭제

Google Cloud 프로젝트 삭제

이 Codelab에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 Google Cloud 프로젝트를 삭제하는 것이 좋습니다.

Google Cloud 콘솔에서 다음 단계를 따르세요.

  1. 메뉴 ☰ > IAM 및 관리자 > 설정을 클릭합니다.

  1. 종료를 클릭합니다.
  2. 프로젝트 ID를 입력합니다.
  3. 무시하고 종료를 클릭합니다.

407699a4e03afea6.png

Apps Script 프로젝트 삭제

Apps Script 프로젝트도 삭제하는 것이 좋습니다.

Apps Script 콘솔에서 다음 단계를 따르세요.

  1. 프로젝트를 선택합니다.
  2. 작업 메뉴를 클릭합니다.
  3. 삭제를 클릭합니다.

fa3a42d7d2201eb9.png

12. 축하합니다

축하합니다. Gemini로 Google Chat 앱을 빌드하셨습니다.

다음 단계

이 Codelab에서는 간단한 사용 사례만 보여드렸지만, Google Chat 앱에서 고려해 볼 만한 다양한 확대 영역이 있습니다. 예를 들면 다음과 같습니다.

  • 커스텀 모델을 비롯한 다른 생성형 AI 모델과 통합
  • 오디오, 이미지, 동영상과 같은 다른 유형의 미디어 지원
  • 멀티모달리티 사용
  • 더 넓은 컨텍스트 범위와 피드백 루프 사용
  • 프로덕션에서 사용할 수 있는 Google Chat 앱을 Marketplace에 게시. YouTube 동영상, 문서 웹사이트, 코드 샘플, 가이드 등 개발자를 위한 다양한 리소스가 마련되어 있습니다.
  • 조직에 Google Chat 사용 설정. 가져오기 모드 기능을 사용하면 쉽게 시작할 수 있습니다.

자세히 알아보기