第7章(応用編):AIとFAQデータを連携して回答案を自動生成する方法
■はじめに
第6章では、AIとJira APIを連携し、過去チケット検索を自動化する方法を整理しました。
第6章(応用編):AIとJira APIで過去チケット検索を自動化する方法
第6章では、過去チケットを探して問い合わせ対応に活用する流れを作りました。この第7章では、さらに実務で使いやすい形として、FAQデータとAIを連携し、問い合わせへの回答案を自動生成する方法を整理します。
問い合わせ対応では、同じような質問が何度も届きます。たとえば、パスワードを忘れた、領収書を発行したい、メールアドレスを変更したい、解約方法を知りたい、といった内容です。
このような問い合わせに対して、毎回ゼロから回答文を書くのは非効率です。ただし、AIに自由に回答させるのは危険です。もっともらしい文章でも、FAQにない内容を勝手に補ってしまうことがあるためです。
そこで今回は、FAQデータを根拠としてAIに渡し、その内容をもとに回答案を作らせます。AIを「勝手に答える人」として使うのではなく、「FAQをもとに回答文を整える人」として使います。
■関連章
この章は、以下の章とつながっています。
第1章(応用編):AIとAPIで問い合わせメールを管理表へ自動登録する方法
第2章(応用編):AIとGoogle Sheets APIで問い合わせ管理表を作る方法
第3章(応用編):AIとGoogle Sheets APIで管理表を自動作成する方法
第4章(応用編):AIとSlack APIで担当者通知を自動化する方法
第5章(応用編):AIとGoogle Drive APIで議事録・資料整理を自動化する方法
第6章(応用編):AIとJira APIで過去チケット検索を自動化する方法
第6章が「過去チケットを探す仕組み」だとすれば、第7章は「FAQをもとに回答案を作る仕組み」です。過去チケットは、実際に起きた対応事例を探すときに役立ちます。FAQは、よくある質問に対して標準的な回答を作るときに役立ちます。
この2つを組み合わせることで、問い合わせ対応の初動をかなり効率化できます。
■この章で作るもの
この章で作るのは、問い合わせ文を入力すると、FAQデータを参照して回答案を作成する仕組みです。
たとえば、以下のような問い合わせが届いたとします。
ログインできません。
パスワードを忘れてしまいました。FAQデータには、以下のような情報が登録されています。
Q:パスワードを忘れた場合はどうすればよいですか?
A:ログイン画面の「パスワードをお忘れですか」から再設定してください。このFAQをもとに、AIが以下のような回答案を作成します。
お問い合わせありがとうございます。
パスワードをお忘れの場合は、ログイン画面にある「パスワードをお忘れですか」から再設定をお願いいたします。
ご確認のほどよろしくお願いいたします。ポイントは、AIがゼロから回答しているわけではないことです。FAQにある情報を根拠にして、お客様へ送れる文章へ整えています。
■なぜFAQデータとAIを連携するのか
FAQは、すでに整理された業務知識です。ただし、FAQをそのままお客様へ貼り付けるだけでは、少し冷たい印象になることがあります。また、問い合わせ文に合わせて言い回しを調整する必要もあります。
そこでAIを使います。FAQの正しい内容をもとに、AIが問い合わせ対応に使える回答案へ整えます。
これにより、担当者は毎回ゼロから文章を書く必要がなくなります。新人担当者でも一定レベルの回答案を作りやすくなります。担当者ごとの回答品質のばらつきも減らせます。
ただし、最初から完全自動返信にする必要はありません。まずは、AIが回答案を作る。人間が確認する。必要に応じて修正する。最後に人間が送信する。この形が実務では安全です。
■全体の流れ
今回の流れは以下です。
1. 問い合わせ文を受け取る
2. FAQデータから関連しそうな項目を探す
3. 見つかったFAQをAIに渡す
4. AIが回答案を作成する
5. 担当者が確認する
6. 問題なければ送信するこの章では、この流れを実装できる形にしていきます。大事なのは、FAQが見つからない場合にAIへ無理に回答させないことです。
FAQが見つからない場合は、担当者確認に回します。複数のFAQが見つかった場合も、回答内容が混ざる可能性があるため注意します。
AI自動化で重要なのは、何でも自動化することではありません。自動化してよい範囲と、人間が確認すべき範囲を分けることです。
■ここから解説する内容
FAQ管理表の設計
FAQデータのサンプル
問い合わせ文からFAQ候補を探すコード
信頼度を判定するコード
AIに渡すプロンプトテンプレート
FAQが見つからない場合の処理
完成版コード
実務で使うときの注意点
この章の有料部分を使うと、FAQをAIに渡して回答案を作る基本形を作れます。完全自動返信ではなく、担当者が確認できる回答案生成として使う設計です。そのため、実務にも導入しやすい形になっています。
■FAQ管理表の設計
まず、FAQデータを管理する表を用意します。最初はGoogleスプレッドシートで十分です。本格的なデータベースを用意しなくても、FAQ連携の基本形は作れます。
FAQ管理表の列は、以下のようにします。
id
category
keyword
question
answer
status
updated_atそれぞれの意味は以下です。
id:FAQの管理番号
category:問い合わせカテゴリ
keyword:検索用キーワード
question:FAQの質問文
answer:FAQの回答文
status:有効・無効の状態
updated_at:最終更新日重要なのは、keyword と status です。keyword は、問い合わせ文からFAQを探すために使います。お客様はFAQの質問文と同じ言葉で問い合わせてくるとは限りません。
たとえば、FAQでは「解約方法」と書いていても、お客様は以下のように書くことがあります。
退会したいです
契約を止めたいです
キャンセルしたいです
もう使わないので解約したいですこのような表現を keyword に入れておくと、FAQを探しやすくなります。status は、AIに参照させてよいFAQかどうかを判断するために使います。
古いFAQや一時的に使わないFAQを、AIに渡してはいけません。そのため、使えるFAQは active、使わないFAQは inactive にします。
■FAQデータのサンプル
FAQ管理表のサンプルは以下です。
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このように、FAQの質問文と回答文だけでなく、検索用キーワードも持たせます。コード上で扱う場合は、以下のようなJavaScript配列として表現できます。
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"
}
];実務では、FAQをコード内に直接書くより、Googleスプレッドシートで管理する方が便利です。ただし、仕組みを理解する段階では、このように配列で確認すると分かりやすいです。
■問い合わせ文からFAQ候補を探すコード
次に、問い合わせ文から関連FAQを探すコードを作ります。ここでは、FAQの keyword に含まれる言葉が、問い合わせ文に含まれているかを確認します。
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;
}実行例です。
const userMessage = "ログインできません。パスワードを忘れました。";
const matchedFaqs = searchFaq(userMessage);
console.log(matchedFaqs);この場合、login カテゴリのFAQが候補として返ります。この検索はシンプルですが、最初の業務自動化では十分使えます。
本格的には、Embeddingやベクトル検索を使って意味の近いFAQを探す方法もあります。しかし、最初から複雑にしすぎると導入しづらくなります。まずは、キーワード一致でFAQ候補を探す。それで足りない部分を後から改善する。この進め方が現実的です。
■信頼度を判定するコード
FAQ候補が見つかったら、次に信頼度を判定します。信頼度は、担当者が回答案を確認するときの目安になります。
ここでは、以下のように分類します。
high:FAQが1件だけ見つかった
medium:FAQが複数見つかった
low:FAQが見つからなかったコードは以下です。
function judgeConfidence(matchedFaqs) {
if (matchedFaqs.length === 0) {
return "low";
}
if (matchedFaqs.length === 1) {
return "high";
}
return "medium";
}この判定は単純ですが、実務では役に立ちます。FAQが1件だけ見つかった場合は、回答案を作りやすいです。複数のFAQが見つかった場合は、AIが内容を混ぜる可能性があります。FAQが見つからない場合は、AIに無理に回答させるべきではありません。
つまり、信頼度によって処理を分けます。
high:回答案を作成する
medium:回答案を作成するが、担当者確認を強める
low:回答案を作成せず、担当者確認に回す■AIに渡すプロンプトテンプレート
FAQ候補が見つかったら、AIに渡すプロンプトを作成します。ここで重要なのは、問い合わせ文だけをAIに渡さないことです。
問い合わせ文だけを渡すと、AIが推測で回答する可能性があります。そのため、FAQ情報を一緒に渡し、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}
【回答案】
`;
}このプロンプトでは、AIに対して「何をしてよいか」と「何をしてはいけないか」を明確にしています。
特に重要なのは以下です。
FAQに書かれている内容を最優先する
FAQにない内容を断定しない
推測で手順を追加しない
判断が難しい場合は担当者確認にする業務でAIを使う場合、プロンプトにはブレーキが必要です。「いい感じに回答して」では危険です。どの情報を根拠にするのか、どこから先は断定してはいけないのか。このルールを入れることで、実務で使いやすい回答案になります。
■FAQが見つからない場合の処理
FAQが見つからない場合、AIに無理やり回答させてはいけません。その場合は、担当者確認に回します。
function handleNoFaqFound() {
return {
status: "needs_review",
confidence: "low",
draft_reply: "関連FAQが見つかりませんでした。担当者確認が必要です。"
};
}FAQが見つからないのに、AIに回答させると危険です。AIは親切な文章を作ることはできます。しかし、その内容が業務上正しいとは限りません。そのため、FAQがない場合は回答案を作らない。これは安全運用の基本です。
■完成版コード
ここまでの処理をまとめた完成版コードです。
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
};
}実行例です。
const userMessage = "ログインできません。パスワードを忘れました。";
const result = handleInquiry(userMessage);
console.log(result);このコードにより、問い合わせ文を受け取り、FAQ候補を探し、信頼度を判定し、FAQがなければ担当者確認にし、FAQがあればAI用プロンプトを作成できます。
この時点では、まだAI APIを直接呼び出していません。しかし、AIに渡すための入力は完成しています。第8章では、この流れをGoogle Apps Scriptと組み合わせて、問い合わせ対応フローとして動かす方向へ進めます。
■実務で使うときの注意点
FAQ連携は便利ですが、導入時には注意点があります。まず、FAQの更新ルールを決める必要があります。FAQが古いままだと、AIも古い回答案を作ります。そのため、FAQには更新日を持たせます。
次に、FAQの責任者を決めます。誰がFAQを更新するのか。誰が内容を確認するのか。古いFAQをいつ無効化するのか。この運用が決まっていないと、AI自動化は不安定になります。
また、AIの回答案をそのまま自動送信しないことも重要です。最初は必ず担当者確認を入れます。
安全な運用は以下です。
FAQ一致あり
→ AIが回答案を作成
→ 担当者が確認
→ 必要に応じて修正
→ 送信
FAQ一致なし
→ AI回答なし
→ 担当者確認
複数FAQ一致
→ AIが慎重に回答案を作成
→ 担当者が必ず確認このようにすると、AIの便利さと安全性を両立できます。
■この章のまとめ
この章では、AIとFAQデータを連携して、問い合わせへの回答案を自動生成する方法を整理しました。ポイントは、AIにゼロから回答させないことです。FAQデータを根拠として渡し、その内容をもとに回答案を作らせます。
これにより、問い合わせ対応の時間を減らせます。回答品質のばらつきも抑えられます。新人担当者でも、一定レベルの回答案を作りやすくなります。
ただし、最初から完全自動返信にする必要はありません。まずは、AIが回答案を作る。人間が確認する。問題なければ送信する。この形が現実的です。
第8章では、このFAQ回答案生成の考え方を、Google Apps Scriptと組み合わせて、問い合わせ対応フローとして自動化していきます。
■次回
