generative-ai-use-cases-jp
generative-ai-use-cases-jp copied to clipboard
RAGチャットからkendraのFAQSを利用する方法について
kendraのFAQSを利用して、RAGチャットの回答を生成できるようにしていただけると助かります 個人的に色々と試していのですが、今のところ解決ができてないので、出来れば機能として実装いただけると助かります
よろしくお願いします
お問い合わせありがとうございます! 現在、RAGチャット時のKendra検索は、Retrieve APIを利用しているためFAQが検索できない仕様となっております。
https://docs.aws.amazon.com/ja_jp/kendra/latest/APIReference/API_Retrieve.html
This doesn't include question-answer or FAQ type responses from your index.
Query APIだとFAQを検索できますので、以下のように実装いただければと思います。
https://github.com/aws-samples/generative-ai-use-cases-jp/blob/7d206325587016b4022e9a40ceb375eadf7cd199/packages/web/src/hooks/useRag.ts#L46
const faq = await (
await query(searchQuery)
).data.ResultItems?.filter((item) => item.Type === 'QUESTION_ANSWER'); // <= これを追加して、referenceItemsに渡す
https://github.com/aws-samples/generative-ai-use-cases-jp/blob/7d206325587016b4022e9a40ceb375eadf7cd199/packages/web/src/prompts/index.ts#L166-L170
export type RagParams = {
promptType: 'RETRIEVE' | 'SYSTEM_CONTEXT';
retrieveQueries?: string[];
referenceItems?: (RetrieveResultItem | QueryResultItem)[];
};
https://github.com/aws-samples/generative-ai-use-cases-jp/blob/7d206325587016b4022e9a40ceb375eadf7cd199/packages/web/src/prompts/index.ts#L214-L224
// 以下のように修正
${params
.referenceItems!.map((item) => {
return `${JSON.stringify({
DocumentId: item.DocumentId,
DocumentTitle: item.DocumentTitle,
DocumentURI: item.DocumentURI,
Content: (item as RetrieveResultItem).Content
? (item as RetrieveResultItem).Content
: (item as QueryResultItem).AdditionalAttributes?.find(
(a) => a.Key === 'AnswerText'
),
})}`;
})
.join(',\n')}
FAQの正式対応については、検討させていただきます!
お世話になっております ご教授ありがとうございます
いただきました、アドバイスについて一点、ご教授をお願いできますと幸いです https://github.com/aws-samples/generative-ai-use-cases-jp/blob/7d206325587016b4022e9a40ceb375eadf7cd199/packages/web/src/hooks/useRag.ts#L46 上記のコードの部分を以下の通りに変更をするという理解でよろしかったでしょうか
const faq = await (
await query(searchQuery)
).data.ResultItems?.filter((item) => item.Type === 'QUESTION_ANSWER'); // <= これを追加して、referenceItemsに渡す
上記のコードを46行目に差し込みますと、VS Studio Codeで添付の画像のような形でErrorが発生するのですがこれはどの様に対応すればよいかご教授いただけますと幸いです
どうぞよろしくお願い申し上げます
以下のように修正いただくとどうでしょうか?
// Kendra から 参考ドキュメントを Retrieve してシステムコンテキストとして設定する
const retrievedItems = await retrieve(searchQuery);
const faq = await (
await query(searchQuery)
).data.ResultItems?.filter((item) => item.Type === 'QUESTION_ANSWER');
updateSystemContext(
ragPrompt({
promptType: 'SYSTEM_CONTEXT',
referenceItems: [
...(retrievedItems.data.ResultItems ?? []),
...(faq ?? []),
],
})
);
早速のご教授、ありがとうございます! いただきましたコードを既存のコードと差し替えますと、添付の様な状況になります ご確認とご教授いただけますと幸いです よろしくお願い申し上げます
小出しにしてすみません! 以下が全文です。こちらでいかがでしょうか?
import useChat from './useChat';
import useChatApi from './useChatApi';
import useRagApi from './useRagApi';
import { ragPrompt } from '../prompts';
const useRag = (id: string) => {
const {
messages,
postChat,
clear,
loading,
setLoading,
updateSystemContext,
popMessage,
pushMessage,
isEmpty,
} = useChat(id);
const { retrieve, query } = useRagApi();
const { predict } = useChatApi();
return {
isEmpty,
clear,
loading,
messages,
postMessage: async (content: string) => {
// Kendra から Retrieve する際に、ローディング表示する
setLoading(true);
pushMessage('user', content);
pushMessage('assistant', '[Kendra から参照ドキュメントを取得中...]');
const searchQuery = await predict({
messages: [
{
role: 'user',
content: ragPrompt({
promptType: 'RETRIEVE',
retrieveQueries: [content],
}),
},
],
});
// Kendra から 参考ドキュメントを Retrieve してシステムコンテキストとして設定する
const retrievedItems = await retrieve(searchQuery);
const faq = await (
await query(searchQuery)
).data.ResultItems?.filter((item) => item.Type === 'QUESTION_ANSWER');
updateSystemContext(
ragPrompt({
promptType: 'SYSTEM_CONTEXT',
referenceItems: [
...(retrievedItems.data.ResultItems ?? []),
...(faq ?? []),
],
})
);
// ローディング表示を消してから通常のチャットの POST 処理を実行する
popMessage();
popMessage();
postChat(content);
},
};
};
export default useRag;
ありがとうございます! itemの型が無いので、Errorになっているようなのですが、以下の様に変更しても良いでしょうか
上記の様に変更をすると、Errorは全て解消できます ご教授をよろしくお願い申し上げます
私の貼ったコードはあくまで実装例ですので、ご自由に改廃いただいて問題ございません!
ありがとうございます! いただきましたコードでdeployをして、後ほど、結果をご報告させて頂きます ご教授ありがとうございます
お世話になっております いただきました、コードを改変してdeployをした所、RAGチャットでFAQsの内容を確認することができました
const retrievedItems = await retrieve(searchQuery);
const faq = await (
await query(searchQuery)
).data.ResultItems?.filter((item: {Type: string}) => item.Type === 'QUESTION_ANSWER'); //この部分
${params
.referenceItems!.map((item) => {
return `${JSON.stringify({
DocumentId: item.DocumentId,
DocumentTitle: item.DocumentTitle,
DocumentURI: item.DocumentURI,
Content: (item as RetrieveResultItem).Content
? (item as RetrieveResultItem).Content
: (item as QueryResultItem).AdditionalAttributes?.find(
(a: { Key: string }) => a.Key === 'AnswerText' //この部分
),
})}`;
})
.join(',\n')}
上記の「この部分」で型宣言をすると、CDKがErrorになったので、型宣言を削除するとcdk deployも問題なく行えました ぜひ、本機能の実装についても前向きなご検討をいただけますと幸いです
この度はご指導、誠にありがとうございました 引き続きよろしくお願い申し上げます
@wadabee お世話になっております 本件について、改めて質問をさせてください
最新のgenerative-ai-use-cases-jpのリポジトリでkendraのfaqsを利用できるように、ご教授いただきましたコードの改変をおこなったのですが、index.tsで添付の通りのErrorとなってしまいます
一旦、この状態で、cloud9から以下のコマンドでcdkをbuildしたのですが、いかの様なErrorになってしまいます 誠にお忙しいところ、恐縮ですがこれはどのようにすれば解決ができますでしょうか
ご指導をいただけますと助かります どうぞよろしくお願いもうしあげます
[cloudwatchに記録されたError]
上で提示されている実装とは異なる部分がいくつかありますが、以下の実装でFAQを含むRAGが行えますので参考にしていただければと思います。aws-samples/generative-ai-use-cases-jp/packages/web/src/hooks/useRag.ts
を以下に置き換えてみてください。
import { RetrieveResultItem } from '@aws-sdk/client-kendra';
import { Model, ShownMessage } from 'generative-ai-use-cases-jp';
import { ragPrompt } from '../prompts';
import useChat from './useChat';
import useChatApi from './useChatApi';
import useRagApi from './useRagApi';
const useRag = (id: string) => {
const {
messages,
postChat,
clear,
loading,
setLoading,
updateSystemContext,
popMessage,
pushMessage,
isEmpty,
} = useChat(id);
const { retrieve, query } = useRagApi();
const { predict } = useChatApi();
return {
isEmpty,
clear,
loading,
messages,
postMessage: async (content: string, model: Model) => {
// Kendra から Retrieve する際に、ローディング表示する
setLoading(true);
pushMessage('user', content);
pushMessage('assistant', 'Kendra から参照ドキュメントを取得中...');
const queryContent = await predict({
model: model,
messages: [
{
role: 'user',
content: ragPrompt.generatePrompt({
promptType: 'RETRIEVE',
retrieveQueries: [content],
}),
},
],
});
// Kendra から 参考ドキュメントを Retrieve してシステムコンテキストとして設定する
const retrieveItemsp = retrieve(queryContent);
const queryItemsp = query(queryContent)
const [retrieveItems, queryItems] = await Promise.all([retrieveItemsp, queryItemsp])
console.log({
retrieveResult: retrieveItems
})
console.log({
queryResult: queryItems
})
const faqs: RetrieveResultItem[] = queryItems.data.ResultItems?.filter((item) => item.Type === 'QUESTION_ANSWER').map((item)=>{
const res = {
Content: item.DocumentExcerpt?.Text || "",
Id: item.Id,
DocumentId: item.DocumentId,
DocumentTitle: item.DocumentTitle?.Text || "",
DocumentURI: item.DocumentURI,
DocumentAttributes: item.DocumentAttributes,
ScoreAttributes: item.ScoreAttributes
}
console.log({
faq:res
})
return res
})||[];
if ((retrieveItems.data.ResultItems ?? []).length === 0) {
popMessage();
pushMessage(
'assistant',
`参考ドキュメントが見つかりませんでした。次の対応を検討してください。
- Amazon Kendra の data source に対象のドキュメントが追加されているか確認する
- Amazon Kendra の data source が sync されているか確認する
- 入力の表現を変更する`
);
setLoading(false);
return;
}
updateSystemContext(
ragPrompt.generatePrompt({
promptType: 'SYSTEM_CONTEXT',
referenceItems: [...retrieveItems.data.ResultItems!, ...faqs!] ?? [],
})
);
// ローディング表示を消してから通常のチャットの POST 処理を実行する
popMessage();
popMessage();
postChat(
content,
false,
model,
(messages: ShownMessage[]) => {
// 前処理:Few-shot で参考にされてしまうため、過去ログから footnote を削除
return messages.map((message) => ({
...message,
content: message.content.replace(/\[\^(\d+)\]:.*/g, ''),
}));
},
(message: string) => {
// 後処理:Footnote の付与
const footnote = retrieveItems.data.ResultItems?.map((item, idx) => {
// 参考にしたページ番号がある場合は、アンカーリンクとして設定する
const _excerpt_page_number = item.DocumentAttributes?.find(
(attr) => attr.Key === '_excerpt_page_number'
)?.Value?.LongValue;
return message.includes(`[^${idx}]`)
? `[^${idx}]: [${item.DocumentTitle}${
_excerpt_page_number ? `(${_excerpt_page_number} ページ)` : ''
}](${item.DocumentURI}${
_excerpt_page_number ? `#page=${_excerpt_page_number}` : ''
})`
: '';
})
.filter((x) => x)
.join('\n');
return message + '\n' + footnote;
}
);
},
};
};
export default useRag;
動作確認用のconsole.log()を三箇所あえて残しておりますので、適宜削除いただければと思います。また、FAQにおけるQuestion側をコンテキストに含めるかどうかなど、上記実装に関してまだまだ考慮点はあるかと思いますので適宜修正ください。
以上、参考になれば幸いです。