ナレッジベースへの問い合わせ
Asgard は Knowledge Base と Retrieve Knowledge Processor で RAG(Retrieval-Augmented Generation)を実現します。アップロードした文書やデータに基づいて AI が質問に答えられるようになります。
仕組み
RAG の問い合わせはすべて Workflow のサーバー側で行われ、外から呼ぶ API は通常のメッセージ送信とまったく同じです。
利用者が質問する
↓
Asgard API(同じエンドポイント)
↓
Retrieve Knowledge Processor(ナレッジベースから関連する内容を検索)
↓
LLM(検索結果をもとに回答を生成)
↓
SSE のストリーミング応答
API の呼び方を変える必要はありません。Workflow に Retrieve Knowledge Processor を追加してナレッジベースを指定すれば、RAG はそのまま動きます。
事前の設定
API を呼ぶ前に、Asgard プラットフォームで次の設定を済ませてください。
- Knowledge Base を作る — PDF、テキストファイル、ウェブページなどをアップロードします
- Embedding Model を設定する — ベクトル化のモデルを選びます(OpenAI text-embedding-3-small など)
- Workflow に Retrieve Knowledge Processor を追加する — 検索の方針と対象のナレッジベースを設定します
- App を公開する — namespace と bot-provider-name が得られます
詳しい手順は Knowledge Base の設定 をご覧ください。
質問の組み立て方
質問の組み立て方によって、ナレッジベースの検索精度は大きく変わります。
| 指針 | 例 |
|---|---|
| 具体的なキーワードを使う | ✅ 返金の手続きには何営業日かかりますか |
| 曖昧すぎる質問を避ける | ❌ すべての情報を教えてください |
| 1 回につき 1 つの話題に絞る | ✅ 製品 A の保証期間はどれくらいですか |
| 適切な前提を添える | ✅ 法人の利用者です。契約更新の手続きを教えてください |
cURL の例
curl -X POST "https://api.asgard-ai.com/generic/ns/your-namespace/bot-provider/your-bot-provider/message/sse" \
-H "Content-Type: application/json" \
-H "X-API-KEY: your-api-key" \
-d '{
"customChannelId": "kb-query-channel-001",
"customMessageId": "kb-msg-001",
"text": "返金の申請に必要な書類と、その手続きを教えてください",
"action": "NONE"
}'
JavaScript の例
const BASE_URL = 'https://api.asgard-ai.com';
const NAMESPACE = 'your-namespace';
const BOT_PROVIDER = 'your-bot-provider';
const API_KEY = process.env.ASGARD_API_KEY;
/**
* ナレッジベースに質問し、RAG の回答を受け取る
* @param {string} question - 利用者の質問
* @param {string} channelId - 対話チャネルの ID(同じチャネルなら対話の記憶が保たれます)
*/
async function queryKnowledgeBase(question, channelId = 'kb-channel-001') {
const url = `${BASE_URL}/generic/ns/${NAMESPACE}/bot-provider/${BOT_PROVIDER}/message/sse`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': API_KEY,
},
body: JSON.stringify({
customChannelId: channelId,
text: question,
action: 'NONE',
}),
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let fullAnswer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (!line.startsWith('data:')) continue;
const jsonStr = line.slice(5).trim();
if (!jsonStr) continue;
try {
const event = JSON.parse(jsonStr);
if (event.eventType === 'asgard.message.delta') {
const delta = event.fact.messageDelta.message.text;
fullAnswer += delta;
// 届いた順に表示する(タイプライター風の表示)
process.stdout.write(delta);
}
if (event.eventType === 'asgard.run.done') {
console.log('\n\n問い合わせ完了');
return fullAnswer;
}
} catch (_) {}
}
}
return fullAnswer;
}
// 使用例: 同じ channelId で続けて質問する(対話の記憶が保たれます)
async function main() {
const channelId = `kb-session-${Date.now()}`;
console.log('質問 1:');
await queryKnowledgeBase('返金の申請に必要な書類は何ですか', channelId);
console.log('\n\n質問 2(追加の質問):');
await queryKnowledgeBase('完了までにおおよそ何営業日かかりますか', channelId);
}
main().catch(console.error);
Python の例
import requests
import json
import os
import time
BASE_URL = "https://api.asgard-ai.com"
NAMESPACE = "your-namespace"
BOT_PROVIDER = "your-bot-provider"
API_KEY = os.environ.get("ASGARD_API_KEY")
def query_knowledge_base(question: str, channel_id: str) -> str:
"""
Asgard のナレッジベースに質問し、RAG の回答を受け取ります。
Args:
question: 利用者の質問
channel_id: 対話チャネルの ID(同じチャネルなら対話の記憶が保たれます)
Returns:
回答の全文
"""
url = f"{BASE_URL}/generic/ns/{NAMESPACE}/bot-provider/{BOT_PROVIDER}/message/sse"
headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
}
payload = {
"customChannelId": channel_id,
"text": question,
"action": "NONE",
}
full_answer = ""
with requests.post(url, headers=headers, json=payload, stream=True) as response:
response.raise_for_status()
for line in response.iter_lines():
if not line:
continue
decoded = line.decode("utf-8")
if not decoded.startswith("data:"):
continue
json_str = decoded[5:].strip()
if not json_str:
continue
try:
event = json.loads(json_str)
event_type = event.get("eventType")
if event_type == "asgard.message.delta":
delta = event["fact"]["messageDelta"]["message"]["text"]
full_answer += delta
print(delta, end="", flush=True)
elif event_type == "asgard.run.done":
print("\n")
break
except json.JSONDecodeError:
pass
return full_answer
if __name__ == "__main__":
channel_id = f"kb-session-{int(time.time())}"
questions = [
"返金の申請に必要な書類は何ですか",
"返金の完了までおおよそ何営業日かかりますか",
"返金の期限を過ぎていても申請できますか",
]
for i, question in enumerate(questions, 1):
print(f"\n質問 {i}: {question}")
print("回答: ", end="")
answer = query_knowledge_base(question, channel_id)
print(f"(全 {len(answer)} 文字)")
出典を含む応答の解析
Workflow がナレッジベースの出典を返す設定になっている場合、その情報は asgard.message.complete イベントの template フィールドに入ります。
if (event.eventType === 'asgard.message.complete') {
const message = event.fact.messageComplete.message;
// 回答の全文
const answerText = message.text;
// ナレッジベースの出典(Workflow が返す設定になっている場合)
const template = message.template;
if (template && template.sources) {
console.log('参照した出典:');
template.sources.forEach((source, i) => {
console.log(` ${i + 1}. ${source.title} — ${source.url || source.fileName}`);
});
}
}
ヒント
template フィールドの中身は Workflow での設定によって決まります。詳しくは Message Template の説明 をご覧ください。
次に読む
- ストリーミング応答の処理 — タイプライター風の表示の実装
- Webhook 連携 — Workflow を自動で起動する
- Knowledge Base の設定 — ナレッジベースの文書のアップロードと管理