SYSTEM NOTICE

Auto translation by AI. Be sure, accuracy, nuances and authorial intent may not be fully reflected.
見出し画像

Chapter 7 (Advanced): How to Automatically Generate Draft Responses by Linking AI with FAQ Data

■ Introduction

In Chapter 6, we organized how to link AI with the Jira API to automate past ticket searches.

Chapter 6 (Advanced): How to Automate Past Ticket Searches with AI and the Jira API

In Chapter 6, we created a workflow to find past tickets and use them for inquiry responses. In this Chapter 7, as a more practical application, we will organize how to link FAQ data with AI to automatically generate draft responses to inquiries.

In inquiry support, similar questions arrive repeatedly. For example, content such as forgetting a password, wanting to issue a receipt, wanting to change an email address, or wanting to know how to cancel a service.

It is inefficient to write a response from scratch every time for such inquiries. However, letting AI answer freely is dangerous. Even if the text sounds plausible, it may arbitrarily supplement content that is not in the FAQ.

Therefore, this time, we will provide the FAQ data to the AI as a basis and have it create a draft response based on that content. We will not use the AI as a "person who answers on their own," but as a "person who refines the response text based on the FAQ."

■ Related Chapters

This chapter is connected to the following chapters.

Chapter 1 (Advanced): How to Automatically Register Inquiry Emails to a Management Table with AI and APIs
Chapter 2 (Advanced): How to Create an Inquiry Management Table with AI and the Google Sheets API
Chapter 3 (Advanced): How to Automatically Create a Management Table with AI and the Google Sheets API
Chapter 4 (Advanced): How to Automate Notifications to Staff with AI and the Slack API
Chapter 5 (Advanced): How to Automate Meeting Minutes and Document Organization with AI and the Google Drive API
Chapter 6 (Advanced): How to Automate Past Ticket Searches with AI and the Jira API

If Chapter 6 is a "mechanism to find past tickets," then Chapter 7 is a "mechanism to create draft responses based on FAQs." Past tickets are useful when looking for actual response cases that have occurred. FAQs are useful when creating standard responses to frequently asked questions.

By combining these two, you can significantly streamline the initial response to inquiries.

■ What we will build in this chapter

What we will build in this chapter is a mechanism that, when an inquiry text is entered, references FAQ data to create a draft response.

For example, suppose an inquiry like the following arrives.

ログインできません。
パスワードを忘れてしまいました。

The following information is registered in the FAQ data.

Q:パスワードを忘れた場合はどうすればよいですか?
A:ログイン画面の「パスワードをお忘れですか」から再設定してください。

Based on this FAQ, the AI will create a draft response like the following.

お問い合わせありがとうございます。

パスワードをお忘れの場合は、ログイン画面にある「パスワードをお忘れですか」から再設定をお願いいたします。

ご確認のほどよろしくお願いいたします。

The point is that the AI is not answering from scratch. It is using the information in the FAQ as a basis and refining it into text that can be sent to the customer.

■ Why link FAQ data with AI?

FAQs are already organized business knowledge. However, just pasting the FAQ directly to the customer can sometimes give a cold impression. Also, it is necessary to adjust the wording according to the inquiry text.

This is where AI comes in. Based on the correct content in the FAQ, the AI organizes it into a draft response that can be used for handling inquiries.

This eliminates the need for staff to write text from scratch every time. It makes it easier even for new staff to create a consistent level of draft responses. It also reduces variations in response quality among different staff members.

However, there is no need to make it a fully automatic reply from the start. First, the AI creates a draft response. A human checks it. It is corrected if necessary. Finally, a human sends it. This format is safe for practical operations.

■ Overall Flow

The flow for this session is as follows.

1. 問い合わせ文を受け取る
2. FAQデータから関連しそうな項目を探す
3. 見つかったFAQをAIに渡す
4. AIが回答案を作成する
5. 担当者が確認する
6. 問題なければ送信する

In this chapter, we will implement this flow. The important thing is not to force the AI to answer when an FAQ cannot be found.

If an FAQ is not found, it is forwarded to a staff member for confirmation. If multiple FAQs are found, be careful as the response content may become mixed.

What is important in AI automation is not to automate everything. It is to separate the scope that can be automated from the scope that should be checked by humans.

■ Contents to be explained from here

  1. Design of the FAQ management table

  2. FAQ data samples

  3. Code to search for FAQ candidates from inquiry text

  4. Code to determine confidence levels

  5. Prompt template to pass to the AI

  6. Handling cases where no FAQ is found

  7. Completed code

  8. Points to note when using in practice

By using the paid section of this chapter, you can create the basic form for passing FAQs to the AI to generate draft responses. It is designed to be used as a draft response generator that staff can check, rather than a fully automatic reply system. Therefore, it is in a form that is easy to introduce into practical operations.


■ Design of the FAQ management table

First, prepare a table to manage FAQ data. A Google Spreadsheet is sufficient to start with. You can create the basic form of FAQ integration without preparing a full-scale database.

The columns of the FAQ management table should be as follows.

id
category
keyword
question
answer
status
updated_at

The meanings of each are as follows.

id:FAQの管理番号
category:問い合わせカテゴリ
keyword:検索用キーワード
question:FAQの質問文
answer:FAQの回答文
status:有効・無効の状態
updated_at:最終更新日

The important ones are keyword and status. The keyword is used to find FAQs from inquiry text. Customers do not always inquire using the same words as the FAQ question text.

For example, even if the FAQ says "How to cancel," customers may write as follows.

退会したいです
契約を止めたいです
キャンセルしたいです
もう使わないので解約したいです

Including such expressions in the keyword makes it easier to find the FAQ. The status is used to determine whether the FAQ is suitable for the AI to reference.

You must not pass old FAQs or FAQs that are not used temporarily to the AI. Therefore, set usable FAQs to active and unused FAQs to inactive.

■ FAQ Data Sample

A sample of the FAQ management table is as follows.

id | category | keyword | question | answer | status | updated_at
1 | login | ログイン,パスワード,サインイン | パスワードを忘れた場合はどうすればよいですか? | ログイン画面の「パスワードをお忘れですか」から再設定してください。 | active | 2026-05-01
2 | payment | 領収書,支払い,決済,請求 | 領収書は発行できますか? | マイページの購入履歴から領収書をダウンロードできます。 | active | 2026-05-01
3 | account | メールアドレス,アカウント,変更 | メールアドレスを変更できますか? | アカウント設定画面からメールアドレスを変更できます。 | active | 2026-05-01
4 | cancel | 解約,キャンセル,退会,契約を止めたい | 解約方法を教えてください。 | マイページの契約情報から解約手続きができます。 | active | 2026-05-01

In this way, you should include not only the FAQ question and answer text but also search keywords. When handling it in code, it can be represented as a JavaScript array like the following.

const faqData = [
  {
    id: 1,
    category: "login",
    keyword: ["ログイン", "パスワード", "サインイン"],
    question: "パスワードを忘れた場合はどうすればよいですか?",
    answer: "ログイン画面の「パスワードをお忘れですか」から再設定してください。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 2,
    category: "payment",
    keyword: ["領収書", "支払い", "決済", "請求"],
    question: "領収書は発行できますか?",
    answer: "マイページの購入履歴から領収書をダウンロードできます。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 3,
    category: "account",
    keyword: ["メールアドレス", "アカウント", "変更"],
    question: "メールアドレスを変更できますか?",
    answer: "アカウント設定画面からメールアドレスを変更できます。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 4,
    category: "cancel",
    keyword: ["解約", "キャンセル", "退会", "契約を止めたい"],
    question: "解約方法を教えてください。",
    answer: "マイページの契約情報から解約手続きができます。",
    status: "active",
    updated_at: "2026-05-01"
  }
];

In practice, it is more convenient to manage FAQs in a Google Spreadsheet than to write them directly in the code. However, at the stage of understanding the mechanism, it is easier to understand by checking it as an array like this.

■ Code to find FAQ candidates from inquiry text

Next, we will create code to find related FAQs from the inquiry text. Here, we check whether the words included in the FAQ's keyword are included in the inquiry text.

function searchFaq(userMessage) {
  const matchedFaqs = [];

  for (const faq of faqData) {
    if (faq.status !== "active") {
      continue;
    }

    const isMatched = faq.keyword.some(word => {
      return userMessage.includes(word);
    });

    if (isMatched) {
      matchedFaqs.push(faq);
    }
  }

  return matchedFaqs;
}

This is an execution example.

const userMessage = "ログインできません。パスワードを忘れました。";
const matchedFaqs = searchFaq(userMessage);

console.log(matchedFaqs);

In this case, the FAQ for the login category is returned as a candidate. This search is simple, but it is sufficient for initial business automation.

In a full-scale implementation, there is also a method of using Embedding or vector search to find FAQs with similar meanings. However, if you make it too complex from the beginning, it will be difficult to introduce. First, find FAQ candidates by keyword matching. Then, improve the parts that are insufficient later. This approach is realistic.

■ Code to determine reliability

Once FAQ candidates are found, the next step is to determine the reliability. Reliability serves as a guide for staff when checking draft answers.

Here, we classify them as follows.

high:FAQが1件だけ見つかった
medium:FAQが複数見つかった
low:FAQが見つからなかった

The code is as follows.

function judgeConfidence(matchedFaqs) {
  if (matchedFaqs.length === 0) {
    return "low";
  }

  if (matchedFaqs.length === 1) {
    return "high";
  }

  return "medium";
}

This judgment is simple, but it is useful in practice. If only one FAQ is found, it is easy to create a draft answer. If multiple FAQs are found, the AI may mix the content. If no FAQ is found, the AI should not be forced to answer.

In other words, we process based on the confidence level.

high:回答案を作成する
medium:回答案を作成するが、担当者確認を強める
low:回答案を作成せず、担当者確認に回す

■ Prompt template to pass to the AI

Once FAQ candidates are found, we create a prompt to pass to the AI. What is important here is not to pass only the inquiry text to the AI.

If you pass only the inquiry text, the AI might answer based on guesswork. Therefore, we pass the FAQ information along with it and have the AI create a draft response based on the FAQ.

function createPrompt(userMessage, matchedFaqs, confidence) {
  const faqText = matchedFaqs.map(faq => {
    return [
      `FAQ ID: ${faq.id}`,
      `カテゴリ: ${faq.category}`,
      `Q: ${faq.question}`,
      `A: ${faq.answer}`,
      `更新日: ${faq.updated_at}`
    ].join("\n");
  }).join("\n\n");

  return `
あなたは問い合わせ対応担当者です。
以下のFAQ情報を根拠に、お客様への回答案を作成してください。

【重要ルール】
・FAQに書かれている内容を最優先してください
・FAQにない内容を断定しないでください
・推測で手順を追加しないでください
・複数FAQがある場合は、問い合わせ内容に最も近いFAQを中心にしてください
・判断が難しい場合は、担当者確認が必要な旨を含めてください
・丁寧で分かりやすい文章にしてください
・最後に「ご確認のほどよろしくお願いいたします。」を入れてください

【信頼度】
${confidence}

【お客様からの問い合わせ】
${userMessage}

【関連FAQ】
${faqText}

【回答案】
`;
}

In this prompt, we clarify to the AI 'what it should do' and 'what it should not do'.

The following is particularly important.

FAQに書かれている内容を最優先する
FAQにない内容を断定しない
推測で手順を追加しない
判断が難しい場合は担当者確認にする

When using AI for business, the prompt needs a brake. 'Answer nicely' is dangerous. What information should be the basis, and where should it not make definitive statements? By including these rules, the draft response becomes easier to use in practical work.

■ Processing when no FAQ is found

If no FAQ is found, you must not force the AI to answer. In that case, route it to a staff member for confirmation.

function handleNoFaqFound() {
  return {
    status: "needs_review",
    confidence: "low",
    draft_reply: "関連FAQが見つかりませんでした。担当者確認が必要です。"
  };
}

It is dangerous to have the AI answer when no FAQ is found. The AI can create polite sentences, but that content is not necessarily correct for business purposes. Therefore, if there is no FAQ, do not create a draft response. This is the basis of safe operation.

■ Completed code

This is the completed code that summarizes the processing up to this point.

const faqData = [
  {
    id: 1,
    category: "login",
    keyword: ["ログイン", "パスワード", "サインイン"],
    question: "パスワードを忘れた場合はどうすればよいですか?",
    answer: "ログイン画面の「パスワードをお忘れですか」から再設定してください。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 2,
    category: "payment",
    keyword: ["領収書", "支払い", "決済", "請求"],
    question: "領収書は発行できますか?",
    answer: "マイページの購入履歴から領収書をダウンロードできます。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 3,
    category: "account",
    keyword: ["メールアドレス", "アカウント", "変更"],
    question: "メールアドレスを変更できますか?",
    answer: "アカウント設定画面からメールアドレスを変更できます。",
    status: "active",
    updated_at: "2026-05-01"
  },
  {
    id: 4,
    category: "cancel",
    keyword: ["解約", "キャンセル", "退会", "契約を止めたい"],
    question: "解約方法を教えてください。",
    answer: "マイページの契約情報から解約手続きができます。",
    status: "active",
    updated_at: "2026-05-01"
  }
];

function searchFaq(userMessage) {
  const matchedFaqs = [];

  for (const faq of faqData) {
    if (faq.status !== "active") {
      continue;
    }

    const isMatched = faq.keyword.some(word => {
      return userMessage.includes(word);
    });

    if (isMatched) {
      matchedFaqs.push(faq);
    }
  }

  return matchedFaqs;
}

function judgeConfidence(matchedFaqs) {
  if (matchedFaqs.length === 0) {
    return "low";
  }

  if (matchedFaqs.length === 1) {
    return "high";
  }

  return "medium";
}

function createPrompt(userMessage, matchedFaqs, confidence) {
  const faqText = matchedFaqs.map(faq => {
    return [
      `FAQ ID: ${faq.id}`,
      `カテゴリ: ${faq.category}`,
      `Q: ${faq.question}`,
      `A: ${faq.answer}`,
      `更新日: ${faq.updated_at}`
    ].join("\n");
  }).join("\n\n");

  return `
あなたは問い合わせ対応担当者です。
以下のFAQ情報を根拠に、お客様への回答案を作成してください。

【重要ルール】
・FAQに書かれている内容を最優先してください
・FAQにない内容を断定しないでください
・推測で手順を追加しないでください
・複数FAQがある場合は、問い合わせ内容に最も近いFAQを中心にしてください
・判断が難しい場合は、担当者確認が必要な旨を含めてください
・丁寧で分かりやすい文章にしてください
・最後に「ご確認のほどよろしくお願いいたします。」を入れてください

【信頼度】
${confidence}

【お客様からの問い合わせ】
${userMessage}

【関連FAQ】
${faqText}

【回答案】
`;
}

function handleInquiry(userMessage) {
  const matchedFaqs = searchFaq(userMessage);
  const confidence = judgeConfidence(matchedFaqs);

  if (confidence === "low") {
    return {
      status: "needs_review",
      confidence: confidence,
      draft_reply: "関連FAQが見つかりませんでした。担当者確認が必要です。"
    };
  }

  const prompt = createPrompt(userMessage, matchedFaqs, confidence);

  return {
    status: "draft_ready",
    confidence: confidence,
    faq_count: matchedFaqs.length,
    prompt: prompt
  };
}

This is an execution example.

const userMessage = "ログインできません。パスワードを忘れました。";
const result = handleInquiry(userMessage);

console.log(result);

With this code, you can receive an inquiry, search for FAQ candidates, determine the confidence level, route to staff confirmation if there is no FAQ, and create an AI prompt if there is an FAQ.

At this point, we have not yet called the AI API directly. However, the input to pass to the AI is complete. In Chapter 8, we will proceed to combine this flow with Google Apps Script to run it as an inquiry response flow.

■ Points to note when using in practice

FAQ integration is convenient, but there are points to note when introducing it. First, you need to decide on FAQ update rules. If the FAQ remains outdated, the AI will also create outdated draft responses. Therefore, include an update date in the FAQ.

Next, decide on an FAQ owner. Who will update the FAQ? Who will check the content? When will old FAQs be invalidated? If this operation is not decided, AI automation will become unstable.

Also, it is important not to automatically send the AI's draft response as is. At first, always include staff confirmation.

Safe operation is as follows.

FAQ一致あり
→ AIが回答案を作成
→ 担当者が確認
→ 必要に応じて修正
→ 送信

FAQ一致なし
→ AI回答なし
→ 担当者確認

複数FAQ一致
→ AIが慎重に回答案を作成
→ 担当者が必ず確認

By doing this, you can achieve both the convenience and safety of AI.

■ Summary of this chapter

In this chapter, we organized how to link AI with FAQ data to automatically generate answer drafts for inquiries. The key point is not to have the AI generate answers from scratch. You provide the FAQ data as a basis and have it create answer drafts based on that content.

This allows you to reduce the time spent on inquiry responses. It also suppresses variations in response quality. Even new staff members can easily create answer drafts at a consistent level.

However, there is no need to make it a fully automatic reply from the start. First, the AI creates an answer draft. A human checks it. If there are no issues, it is sent. This form is realistic.

In Chapter 8, we will combine this concept of FAQ answer draft generation with Google Apps Script to automate it as an inquiry response flow.

■ Next time

Chapter 8 (Advanced): How to Automate Inquiry Response Flows with AI and Google Apps Script

いいなと思ったら応援しよう!