跳至主要内容

REFERENCE

開發者參考

認證、API、SDK、Flow Agent 處理節點與參數取值的完整參考。

知識庫查詢

使用 Asgard RAG 知識庫進行智慧問答的完整範例

Asgard 透過 Knowledge Base 搭配 Retrieve Knowledge Processor 實現 RAG(Retrieval-Augmented Generation)功能,讓 AI 能夠根據您上傳的文件與資料回答問題。

  1. 運作原理​

    RAG 查詢完全在 Workflow 伺服端執行,對外的 API 介面與一般發送訊息完全相同:

    使用者提問
    ↓
    Asgard API(相同端點)
    ↓
    Retrieve Knowledge Processor(從知識庫檢索相關內容)
    ↓
    LLM(結合檢索結果生成回答)
    ↓
    SSE 串流回應

    您無需修改 API 呼叫方式,只需在 Workflow 中加入 Retrieve Knowledge Processor 並設定對應的 Knowledge Base,RAG 功能即可自動運作。

  2. 前置設定​

    在呼叫 API 之前,請先完成以下 Asgard 平台設定:

    1. 建立 Knowledge Base — 上傳 PDF、文字檔、網頁等文件
    2. 設定 Embedding Model — 選擇向量化模型(如 OpenAI text-embedding-3-small)
    3. 在 Workflow 加入 Retrieve Knowledge Processor — 設定檢索策略與知識庫來源
    4. 發佈 App — 取得 namespace 與 bot-provider-name

    詳細設定步驟請參考 Knowledge Base 設定。

  3. 問題結構建議​

    良好的問題結構能顯著提升知識庫的檢索準確率:

    建議範例
    使用具體關鍵字✅ 退款流程需要幾個工作天?
    避免過於模糊的提問❌ 請告訴我所有資訊
    單次聚焦單一主題✅ 產品 A 的保固期是多久?
    提供適當背景脈絡✅ 我是企業用戶,請問合約續約的流程是?
  4. 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"
    }'
  5. 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);
  6. 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)} 字)")
  7. 解析包含知識庫來源的回應​

    當 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 說明。

  8. 下一步​

準備好開始了嗎?

想知道 Asgard 怎麼用在你的團隊?跟我們聊聊。

聯絡我們