在阿里雲上只需 10 分鐘即可為您的網站添加一個 AI 助手,以便全天候(7x24)回應客戶諮詢,提升使用者體驗、增強業務競爭力。
方案概覽
在網站中引入一個 AI 助手,只需 4 步:
建立大模型問答應用:我們將先通過百鍊建立一個大模型應用,並擷取調用大模型應用 API 的相關憑證。
搭建樣本網站:然後我們將通過Function Compute,來快速搭建一個網站,類比您的企業官網或者其他網站。
引入 AI 助手:接著我們將通過修改幾行代碼,實現在網站中引入一個 AI 助手。
增加私人知識:最後可以通過準備一些私人知識,讓 AI 助手能回答原本無法準確回答的問題,協助您更好的應對客戶諮詢。
1. 建立大模型問答應用
首先我們可以通過建立一個百鍊應用,來擷取大模型的推理 API 服務,用於實現 AI 助手。
百鍊提供的新使用者免費額度可以完全覆蓋本教程所需資源消耗。額度消耗完後按 token 計費,相比自行部署大模型可以顯著降低初期投入成本。
1.1 建立應用
進入百鍊控制台的我的應用程式,在頁面右側點擊新增應用。在對話方塊,選擇智能體應用並建立。
在應用設定頁面,模型選擇通義千問-Plus,其他參數保持預設。
您也可以選擇輸入一些 Prompt,比如設定一些人設以引導大模型更好的應對客戶諮詢。
你叫小助,可以協助使用者解答產品選購、使用等方面的問題。
在頁面右側可以提問驗證模型效果。不過您會發現,目前它還無法準確回答你們公司的商品資訊。點擊右上方的發布,我們將在後面的步驟中去解決這一問題。
1.2 擷取調用 API 所需的憑證
為了在後續通過 API 呼叫大模型應用的能力,我們需要擷取一個百鍊應用的 API-KEY 和應用 ID:
在我的應用程式 > 應用列表中可以查看所有百鍊應用 ID。儲存應用 ID 到本地用於後續配置。
在頂部導覽列右側,點擊人型表徵圖,點擊API-KEY進入我的API-KEY頁面。在頁面右側,點擊建立我的API-KEY,在快顯視窗中建立一個新 API-KEY。儲存 API-KEY 到本地用於後續配置。
2. 搭建樣本網站
在讓 AI 助手能準確回答問題之前,我們可以先嘗試快速將 AI 助手整合到網站中。
您可以通過我們提前準備好的應用模板,快速搭建一個空白的樣本網站,用於類比您的企業官網或者其他網站。詳細步驟如下:
Function Compute提供的免費試用額度可以完全覆蓋本教程所需資源消耗。額度消耗完後隨用隨付,對於本教程所涉及的Web服務,只在有訪問的情況下會產生費用。
2.1 建立應用
請點擊這裡開啟我們提供的Function Compute應用模板,參考下圖選擇直接部署、並填寫前面擷取到的百鍊應用 ID 以及 API-KEY。
然後其他表單項保持預設,點擊頁面左下角的建立並部署預設環境,等待專案部署完成即可(預計耗時 1 分鐘)。
這裡需要填寫百鍊應用 ID 和 API-KEY,是因為我們預置的應用模板中包含了通過百鍊應用調用大模型的代碼,以便您在後續快速完成體驗。
2.2 訪問網站
應用部署完成後,您可以在應用詳情的環境資訊中找到樣本網站的訪問網域名稱,點擊即可查看,確認樣本網站已經部署成功。
本方案提供的網站為樣本網站,網站本身細節內容僅展示樣式,效果如下圖。
3. 為網站增加 AI 助手
在網站中增加 AI 助手非常簡單,您只需要在網站的 html 檔案中插入幾行代碼。
3.1 增加 AI 助手相關代碼
樣本工程中包含了被注釋的引入 AI 助手代碼,您需要找到並解除注釋。詳細操作步驟如下:
回到應用詳情頁,在環境詳情的最底部找到函數資源,點擊函數名稱,進入函數詳情頁。
在代碼視圖中找到
index.js
檔案,將hostname
的值修改為dashscope-intl.aliyuncs.com
。在代碼視圖中找到
public/index.html
檔案,然後取消③所在位置的代碼注釋即可。最後點擊部署代碼,等待部署完成即可。
3.2 驗證網站上的 AI 助手
現在,您可以重新訪問樣本網站頁面以查看最新效果。此時您會發現網站的右下角出現了 AI 助手表徵圖,點擊即可喚起 AI 助手。
本方案提供的網站為樣本網站,網站本身細節內容僅展示樣式,效果如下圖。
4. 為 AI 助手增加私人知識
通過前面的步驟,您已經擁有了一個可以和客戶對話的 AI 助手。但是,如果想讓 AI 助手像公司員工一樣,更加精準且專業地回答與商品相關的問題,我們還需要為大模型應用配置知識庫。
假設您在一家售賣智能手機的公司工作。您的網站上會有很多與智能手機相關的資訊,如支援雙卡雙待、螢幕、電池容量、記憶體等資訊。不同機型的詳細配置清單參考:百鍊系列手機產品介紹.docx。
4.1 配置知識庫
接下來,我們可以嘗試讓大模型在面對客戶問題時參考這份文檔,以產出一個更準確的回答和建議。
上傳檔案:在百鍊控制台的資料管理中的非結構化資料頁簽中點擊匯入資料,根據引導上傳我們虛構的百鍊系列手機產品介紹:
根據您上傳的文檔大小,百鍊需要一定時間解析,通常佔用1~6分鐘,請您耐心等待。
建立索引:進入知識索引,根據引導建立一個新的知識庫,並選擇剛才上傳的檔案,其他參數保持預設即可。知識庫將為上一步驟中準備的文檔建立索引,以便後續大模型回答時檢索參考。
選擇向量儲存類型時,如果您希望集中儲存、靈活管理多個應用的向量資料,可選擇ADB-PG。
引用知識:完成知識庫的建立後,可以返回我的應用程式進入到剛才建立的應用設定介面,開啟知識檢索增強開關、選擇目標知識庫,測實驗證符合預期後點擊發布。Prompt 中會被自動添加一段資訊,以便大模型在後續回答時參考檢索出來的資訊。
4.2 檢驗效果
有了參考知識,AI 助手就能準確回答關於您公司的商品的問題了。
總結
通過前面的學習,您已經能在10分鐘內免費(免費使用額度內)搭建一個大模型 RAG 應用,並且將其以 AI 助手的形式添加到網站中,以應對客戶諮詢。
應用於生產環境
在正式的將 AI 助手引入到您的生產環境之前,建議您瞭解如下資訊:
前端代碼
前面建立的網站 AI 助手,是基於NLUX(一個用於開發大模型對話機器人的前端庫)開發的樣本,功能還比較簡單。
如果您對於 AI 助手有更多定製化的需求,如希望調整樣式、支援歷史會話管理等,可以參考 NLUX 的文檔進行定製開發。
本文檔的 AI 助手組件前端原始碼從 web-chatbot-ui 倉庫擷取。
服務端代碼
前面建立的樣本網站代碼中,包含了一個調用大模型擷取答案的介面POST /chat
,具體實現代碼在檔案index.js
中。
Function Compute應用在沒有訪問時不產生任何費用,您完全可以保留此函數應用,在後續用作調用大模型的轉寄服務。
如果您想要使用Java和Python SDK在自己的服務實現服務端,可以參考下面的代碼:
package com.aliyun.webdemo.controller;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.reactivex.Flowable;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import java.util.concurrent.atomic.AtomicInteger;
import com.alibaba.dashscope.utils.Constants;
/**
* pom 配置依賴項
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>dashscope-sdk-java</artifactId>
* <!-- 請將 'the-latest-version' 替換為查詢到的最新版本號碼:https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
* <version>the-latest-version</version>
* </dependency>
*
* 將API Key配置到環境變數 https://www.alibabacloud.com/help/zh/model-studio/developer-reference/configure-api-key-through-environment-variables
*/
@RestController
@RequestMapping("/chatbot")
public class ChatbotController {
static {
Constants.baseHttpApiUrl="https://dashscope-intl.aliyuncs.com/api/v1";
}
/**
* 實現 chat 介面,支援流式返回資料
*
* @param query
* @return
*/
@RequestMapping(value = "/chat", method = RequestMethod.POST)
public ResponseBodyEmitter streamData(@RequestBody String query) {
ResponseBodyEmitter emitter = new ResponseBodyEmitter(180000L);
JsonObject jsonObject = new JsonParser().parse(query).getAsJsonObject();
try {
streamCall(emitter, jsonObject.get("prompt").getAsString());
} catch (NoApiKeyException | InputRequiredException e) {
e.printStackTrace();
}
return emitter;
}
/**
* 調用百鍊應用,封裝流式返回資料
* 返回資料格式
* id:1
* event:result
* :HTTP_STATUS/200
* data:{"output":{"session_id":"xxx","finish_reason":"null","text":"相關的問題"}}
*
* @param emitter
* @param query
* @throws NoApiKeyException
* @throws InputRequiredException
*/
public void streamCall(ResponseBodyEmitter emitter, String query) throws NoApiKeyException, InputRequiredException {
// appId 填入百鍊應用 ID
ApplicationParam param = ApplicationParam.builder()
.appId("xxx")
.prompt(query)
.incrementalOutput(true)
.build();
Application application = new Application();
Flowable<ApplicationResult> result = application.streamCall(param);
AtomicInteger counter = new AtomicInteger(0);
result.blockingForEach(data -> {
int newValue = counter.incrementAndGet();
String resData = "id:" + newValue + "\nevent:result\n:HTTP_STATUS/200\ndata:" + new Gson().toJson(data) + "\n\n";
emitter.send(resData.getBytes(java.nio.charset.StandardCharsets.UTF_8));
if ("stop".equals(data.getOutput().getFinishReason())) {
emitter.complete();
}
});
}
}
from flask import Flask, request, render_template, Response
from http import HTTPStatus
from dashscope import Application
import json
import dashscope
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'
app = Flask(__name__)
@app.route("/")
def home(path=""):
"""
首頁
"""
return render_template("index.html")
def call_with_stream(query):
"""
流式調用百鍊 API
需要將API Key配置到環境變數
https://www.alibabacloud.com/help/zh/model-studio/developer-reference/configure-api-key-through-environment-variables
返回資料格式
id:1
event:result
:HTTP_STATUS/200
data:{"output":{"session_id":"xxx","finish_reason":"null","text":"相關的問題"}}
"""
# appId 填入百鍊應用 ID
responses = Application.call(
app_id="xxx",
prompt=query,
stream=True,
incremental_output=True,
)
i = 0
for response in responses:
if response.status_code != HTTPStatus.OK:
print(
"request_id=%s\n output=%s\n usage=%s\n"
% (response.request_id, response.output, response.usage)
)
else:
data = (
"id:"
+ str(i)
+ "\nevent:result\n:HTTP_STATUS/200\ndata:"
+ json.stringfy(response)
+ "\n\n"
)
yield data
@app.route("/chat", methods=["POST"])
def create():
raw_data = request.data
data = json.loads(raw_data.decode("utf-8"))
return Response(
call_with_stream(data["prompt"]), mimetype="application/octet-stream"
)
if __name__ == "__main__":
app.run(debug=True, port=8080)
<?php
// 開始新會話或恢複現有會話
session_start();
// 非請求 退出
if(!isset($_SERVER['REQUEST_METHOD'])){
exit;
}
// 初始化首頁
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
home();
}
// AI助手post請求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
chat();
}
/**
* 展示首頁
* 首頁內容請參考上述前端代碼
* 註:測試的時候請將修改前端代碼中endpoint為"/"
*/
function home() {
// HTML檔案路徑
$file = 'home.html';
if (file_exists($file)) {
// 檔案存在,則顯示內容
header('Content-Type: text/html');
readfile($file);
} else {
// 提示檔案不存在
echo "404 Not Found. The file does not exist.";
}
}
/**
* AI助手post請求
*/
function chat() {
/**
* 佈建要求的URL和百鍊API-KEY,將<APP_ID>替換為百鍊應用ID
*/
$url = 'https://dashscope-intl.aliyuncs.com/api/v1/apps/<APP_ID>/completion'; // 請求的URL
$apiKey = 'sk-xxx';
/**
* 佈建要求頭資訊
*/
$headers = [ // 要求標頭數組
'Authorization: Bearer ' . $apiKey, // 認證頭部
'Content-Type: application/json', // 內容類型
'X-DashScope-SSE: enable' // SSE啟用標誌
];
// 初始化提示詞為空白字串
$prompt = '';
// 擷取輸入資料流的內容
$json = file_get_contents('php://input');
// 嘗試將JSON轉換為關聯陣列
$data = json_decode($json, true);
// 檢查JSON解析是否成功
if (json_last_error() === JSON_ERROR_NONE) {
$prompt = $data['prompt'] ?? null; // 提取prompt欄位值
}
/**
* 構建請求體
*/
$requestBody = [ // 請求體數組
'input' => ['prompt' => $prompt], // 輸入項
'parameters' => ['incremental_output' => true], // 參數設定
'debug' => new stdClass(), // 調試選項(Null 物件)
];
// 流式調用百鍊 API
call_with_stream($url, $headers, $requestBody);
}
// 流式調用百鍊 API
function call_with_stream($url, $headers, $requestBody){
/**
* 初始化cURL會話並設定相關屬性
*/
$ch = curl_init();
curl_setopt_array($ch, [ // 設定cURL選項
CURLOPT_URL => $url, // 目標URL
CURLOPT_POST => true, // 使用POST方法
CURLOPT_POSTFIELDS => json_encode($requestBody), // POST資料
CURLOPT_HTTPHEADER => $headers, // 要求標頭
CURLOPT_WRITEFUNCTION => function ($curl, $data) { // 自訂寫回調
echo $data; // 輸出資料
ob_flush(); // 重新整理輸出緩衝
flush(); // 重新整理所有輸出緩衝
return strlen($data); // 返回資料長度
},
CURLOPT_BUFFERSIZE => 128, // 緩衝區大小
CURLOPT_TIMEOUT => 300, // 逾時時間
CURLOPT_RETURNTRANSFER => true, // 是否返回傳輸資料
CURLOPT_HEADER => false // 不包含HTTP頭部
]);
/**
* 執行cURL會話並擷取響應
*/
$response = curl_exec($ch);
/**
* 錯誤處理及響應輸出
*/
if (curl_errno($ch)) { // 檢查是否存在cURL錯誤
http_response_code(500); // 設定HTTP響應狀態代碼為500
echo 'Curl error: ' . curl_error($ch); // 輸出錯誤資訊
} else {
echo $response; // 輸出響應結果
}
curl_close($ch); // 關閉cURL會話
}
?>
Function Compute應用部署時附帶的 **.devsapp.net 網域名稱會在下發後 30 天內回收,且不支援HTTPS訪問,只適合於測實驗證。如果您希望在您的網站上直接調用Function Compute中部署的POST /chat
介面,建議使用Function ComputeHTTP觸發器中提供的網域名稱,如:https://web-chat****.fcapp.run/chat
。與此同時,建議您修改index.js
中的 cors 配置,禁止其他網站對此介面的訪問。
持續改進
大模型課程
系統體驗的改進最佳化永遠沒有終點,您可以考慮學習並通過阿里雲大模型 ACA 認證,該認證配套的免費課程能協助您進一步瞭解大模型的能力和應用情境,以及如何最佳化通過大模型的應用效果。