此篇接續上一篇?傳統業務對接AI-AI編程框架-Rasa的業務應用實戰(4)--Rasa成型可用 針對業務配置rasa并訓練和部署
?
上一篇我們已經讓Rasa準確識別了我們自然語言指令的開票和查詢發票的意圖和實體。
# 開具發票場景
用戶輸入:開具一張1000元的發票,稅率13%? ?// 識別開票意圖和實體
rasa輸出:好的,我將為您開具一張金額為1000元,稅率為13%的發票。
# 查詢發票場景
用戶輸入:查詢發票編號12345? // 識別發票查詢意圖和實體
rasa輸出:正在查詢發票編號12345的詳情,請稍候。
此篇我們要做進一步提升改造,內容如下:
1、當前是命令行界面輸入文本來交互,我則希望是前端發送http rest請求來輸入自然語言指令。?
比如:前端頁面訪問?http://localhost:xxx/xxx/?(rasa服務的交互接口)
2、Rasa 接收到前端的自然語言指令后,識別了意圖和實體,調用后端的開票/查詢業務服務接口
并最終將最后的業務操作結果,返回給前端。
http://localhost:8088/ai/rasa/issue_invoice(開票接口)
http://localhost:8088/ai/rasa/query_invoice/xxx(查票接口)
接下來就是我們具體的改造?
1、定義 Rasa 的后臺服務API地址,通過配置 endpoints.yml 文件來實現:(在其中添加以下配置內容)
action_endpoint:url: "http://localhost:5055/webhook"
解釋:http://localhost:5055/webhook 此即 rasa對外暴露的API接口,前端界面就可以通過這個url來傳入自然語言指令來與rasa交互
2、先改規則配置文件:
?
?開票和查票的兩個意圖的動作,都由原來的返回響應文本(utter_issue_invoice),改成執行動作(action_issue_invoice),即觸發對應domain.yml中配置的動作項:
?
3、實現rasa的開票和查票的兩個動作 即 action_issue_invoice 和?action_query_invoice 去調用業務系統的后臺服務接口
編輯工作目錄下的actions/actions.py文件 如下:
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.events import SlotSet
import requestsclass ActionIssueInvoice(Action):def name(self):return "action_issue_invoice"def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: dict):amount = tracker.get_slot("amount")tax_rate = tracker.get_slot("tax_rate")if amount and tax_rate:# 替換為你的發票系統 API 地址和參數try:response = requests.post("http://localhost:8088/ai/rasa/issue_invoice",json={"amount": amount.replace("元", ""), "tax_rate": tax_rate.replace("%", "")},headers={"Authorization": "Bearer YOUR_API_TOKEN"})if response.status_code == 200:dispatcher.utter_message(text=f"發票已開具,金額為{amount},稅率為{tax_rate}。")else:dispatcher.utter_message(text=f"發票開具失敗:{response.json().get('error', '未知錯誤')}。")except Exception as e:dispatcher.utter_message(text=f"發票開具失敗:{str(e)}。")return [SlotSet("amount", amount), SlotSet("tax_rate", tax_rate)]else:dispatcher.utter_message(text="抱歉,無法識別金額或稅率,請重新輸入。")return []class ActionQueryInvoice(Action):def name(self):return "action_query_invoice"def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: dict):invoice_number = tracker.get_slot("invoice_number")if invoice_number:# 替換為你的發票系統 API 地址和參數try:response = requests.get(f"http://localhost:8088/ai/rasa/query_invoice/{invoice_number}",headers={"Authorization": "Bearer YOUR_API_TOKEN"})if response.status_code == 200:invoice_data = response.json()dispatcher.utter_message(text=f"發票編號{invoice_number}的詳情:{invoice_data}。")else:dispatcher.utter_message(text=f"查詢失敗:{response.json().get('error', '未知錯誤')}。")except Exception as e:dispatcher.utter_message(text=f"查詢失敗:{str(e)}。")return [SlotSet("invoice_number", invoice_number)]else:dispatcher.utter_message(text="抱歉,無法識別發票編號,請重新輸入。")return []
此即意味著,當識別了開票意圖后, 會執行Python的action_issue_invoice方法,傳入識別的實體信息去調用開票的后端服務接口。當識別了查詢發票的意圖后,會執行Python的action_query_invoice方法,?傳入識別的實體信息去調用開票的后端服務接口。
?4、以服務方式(非殼方式 即不是shell命令行模式)啟動 rasa 執行以下命令:
rasa run --enable-api --cors "*" --port 5005
執行后運行如下:
這樣 rasa 就以http server模式啟動了,前端就可以通過http請求與之交互對話了。
5、啟動 rasa 的動作服務器。? 在工程目錄下,新開個 powershell 執行界面,執行以下命令:
rasa run actions
?此一步正是第3步中的?actions/actions.py 的服務端實現的部署啟動,用來對外調用業務接口
如上圖所示 就是啟動成功了 動作服務器的端口默認為:5055?
6、模擬業務前端界面發起開票的自然語言指令試試效果
如下圖,我用自然語言,作為傳入參數,調用rasa的server,它成功調用了業務端接口并返回了正確的預期結果。大功告成!
上圖是我的模擬開票服務的后端接口日志輸出,證明rasa在識別到開票的自然語言指令后確實成功調用了業務接口。?
再試試查票的識別:
也是OK 完美識別。?
末尾,順帶附上我測試用的業務接口的代碼 (模擬開發票和查發票的業務API)?
@RestController
@RequestMapping("/ai/rasa")
public class Ai4BizController extends BaseController {private static final Logger logger = LoggerFactory.getLogger(Ai4BizController.class);@PostMapping("/issue_invoice")public JSONObject issueInvoice(@RequestBody JSONObject reqObj) {String amount = reqObj.getString("amount");String taxRate = reqObj.getString("tax_rate");if (StringUtils.isEmpty(amount) || StringUtils.isEmpty(taxRate)) {return fail("開票失敗,缺少開票信息!");}logger.info("業務系統后臺成功開具了一張發票!金額:{}, 稅率:{}", reqObj.getString("amount"), reqObj.getString("tax_rate"));JSONObject data = new JSONObject().fluentPut("info", "發票開具成功!").fluentPut("fee", reqObj.getString("amount")).fluentPut("tax_rate", reqObj.getString("tax_rate"));return success(data);}@GetMapping("/query_invoice/{invoice_number}")public JSONObject queryInvoice(@PathVariable("invoice_number") String invoiceNumber) {if (StringUtils.isEmpty(invoiceNumber)) {return fail("查詢失敗,缺少發票號碼!");}return success(new JSONObject().fluentPut("info", "您查詢的發票號碼是:" + invoiceNumber));}
}