Swift应用中API.AI Webhook使用及动态创建实体/意图咨询
嘿,我来帮你理清这个问题的解决方向,其实有两种核心思路可以实现你想要的效果,咱们一步步说:
一、用Swift调用DialogFlow Admin API,手动创建/更新实体、意图
如果你确实需要通过Swift代码直接往DialogFlow里添加实体、意图或者响应内容,得用到DialogFlow Admin API(注意不是客户端集成API,这个是用来管理DialogFlow后台资源的)。具体步骤是这样的:
先搞定认证:
去DialogFlow控制台的「设置」→「服务账号」,下载你的服务账号JSON密钥。之后你可以用Google官方的Swift SDK(比如GoogleAPIClientForREST)来处理认证,或者手动生成OAuth2访问令牌来调用REST API。从网页拉取JSON数据,转成DialogFlow需要的格式:
先写个Swift方法获取网页里的Studies数据,然后把这些数据转换成DialogFlow实体要求的JSON结构。比如你的Studies实体每个值对应的同义词就是它自己,结构大概是["value": "Science", "synonyms": ["Science"]]这样的数组。调用Admin API创建实体:
用URLSession发送POST请求到DialogFlow的实体创建端点,把构造好的实体数据传过去。给你个简单的代码示例:import Foundation // 第一步:从网页获取Studies数据 func fetchWebStudies(completion: @escaping ([String]?) -> Void) { guard let webUrl = URL(string: "你的网页JSON地址") else { completion(nil) return } URLSession.shared.dataTask(with: webUrl) { data, _, error in guard let data = data, error == nil else { completion(nil) return } do { // 假设网页返回的是字符串数组,比如["Science", "Math", "History"] let studies = try JSONSerialization.jsonObject(with: data) as? [String] completion(studies) } catch { print("解析网页JSON失败:\(error)") completion(nil) } }.resume() } // 第二步:调用Admin API创建Studies实体 func createDialogFlowEntity(projectId: String, authToken: String, studies: [String]) { let apiUrl = "https://dialogflow.googleapis.com/v2/projects/\(projectId)/agent/entities" guard let url = URL(string: apiUrl) else { return } // 构造DialogFlow实体的请求体 let entityPayload: [String: Any] = [ "displayName": "Studies", "kind": "KIND_MAP", "entities": studies.map { ["value": $0, "synonyms": [$0]] } ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") do { request.httpBody = try JSONSerialization.data(withJSONObject: entityPayload) } catch { print("序列化实体数据失败:\(error)") return } URLSession.shared.dataTask(with: request) { _, response, error in if let error = error { print("创建实体出错:\(error)") return } if let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 { print("Studies实体创建成功!") } else { print("创建实体失败,状态码:\((response as? HTTPURLResponse)?.statusCode ?? 0)") } }.resume() } // 使用示例 fetchWebStudies { studies in if let studies = studies { // 这里的authToken是用服务账号生成的OAuth2令牌 createDialogFlowEntity(projectId: "你的DialogFlow项目ID", authToken: "你的认证令牌", studies: studies) } }同理,如果你要创建意图或者更新响应,也可以调用对应的Admin API端点,比如创建意图用
/v2/projects/{PROJECT_ID}/agent/intents,把响应内容配置到意图的messages字段里就行。
二、用Webhook实现动态响应(更推荐,不用手动维护实体)
其实你想要的「用户触发意图时,响应来自网页JSON数据」这个需求,用Webhook来实现会更灵活,而且不需要每次更新数据都去调用Admin API。这个思路是:
搭一个简单的Webhook后端服务:
这个服务的作用是,当DialogFlow收到用户的asking for a type of study意图请求时,会调用你的Webhook,Webhook去拉取网页的JSON数据,然后返回符合DialogFlow格式的响应。你可以用Node.js、Python甚至Swift的Vapor来写,比如用Node.js的Express写个简单的:const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); app.post('/dialogflow-webhook', async (req, res) => { const intentName = req.body.queryResult.intent.displayName; if (intentName === 'asking for a type of study') { // 拉取网页的JSON数据 const webData = await axios.get('你的网页JSON地址'); const studies = webData.data; // 随便选一个返回,或者返回列表 const randomStudy = studies[Math.floor(Math.random() * studies.length)]; res.json({ fulfillmentText: randomStudy }); } else { res.json({ fulfillmentText: "抱歉,我没明白你的问题。" }); } }); app.listen(3000, () => console.log('Webhook服务启动在3000端口'));在DialogFlow控制台配置Webhook:
把你的Webhook部署到公开可访问的服务器(比如Heroku、Vercel),然后在DialogFlow的「Fulfillment」页面里填入Webhook的URL,接着在asking for a type of study意图的「Fulfillment」部分,勾选「Enable webhook call for this intent」。Swift端正常交互:
你之前已经集成了Swift和DialogFlow,现在不需要改太多代码,用户触发意图时,DialogFlow会自动调用你的Webhook,把动态获取的Studies数据返回给Swift应用,你直接接收响应就行。
总结一下
- 如果你需要长期维护实体/意图的结构,或者需要批量导入数据,就用Admin API的方式;
- 如果你只是想实时动态返回网页里的数据作为响应,Webhook的方式更简单高效,不用手动去更新DialogFlow的后台资源。
内容的提问来源于stack exchange,提问作者Mau

