feat(asr): 添加ASR语音识别的列表场景支持
- 新增extraProvider回调用于提供列表数据给服务端 - 实现list场景下的任务定位功能,支持通过taskId或taskIndex跳转 - 扩展RecognizeData模型支持extra和actions参数传递 - 在TaskListActivity中注册ASR回调处理决策中心跳转 - 更新HTTP请求头配置和用户身份信息 - 添加TaskExtraItem数据类用于列表项信息传递
这个提交包含在:
父节点
96671914ab
当前提交
2b3965da67
@ -65,6 +65,9 @@ object AsrHelper : OfflineCmdListener {
|
|||||||
/** goToTaskCenter 命中时的回调,由各 Activity 在 onResume/onPause 中注册/清空 */
|
/** goToTaskCenter 命中时的回调,由各 Activity 在 onResume/onPause 中注册/清空 */
|
||||||
var onGoToTaskCenter: ((action: RecognizeAction) -> Unit)? = null
|
var onGoToTaskCenter: ((action: RecognizeAction) -> Unit)? = null
|
||||||
|
|
||||||
|
/** list 场景下由 TaskListActivity 注册,返回当前列表数据作为 extra 传给服务端 */
|
||||||
|
var extraProvider: (() -> List<Any>)? = null
|
||||||
|
|
||||||
/** scene == "decision" 时直接用 ASR 文本发起对话,由 ChatActivity 注册 */
|
/** scene == "decision" 时直接用 ASR 文本发起对话,由 ChatActivity 注册 */
|
||||||
var onDirectChat: ((text: String) -> Unit)? = null
|
var onDirectChat: ((text: String) -> Unit)? = null
|
||||||
|
|
||||||
@ -192,16 +195,22 @@ object AsrHelper : OfflineCmdListener {
|
|||||||
if (scene == "decision") {
|
if (scene == "decision") {
|
||||||
onDirectChat?.invoke(text)
|
onDirectChat?.invoke(text)
|
||||||
} else {
|
} else {
|
||||||
|
val listActions = if (scene == "list")
|
||||||
|
listOf("goToDecisionCenter")
|
||||||
|
else
|
||||||
|
listOf("goToTaskCenter", "goToDecisionCenter")
|
||||||
IntentRecognizeHelper.recognize(
|
IntentRecognizeHelper.recognize(
|
||||||
text = text,
|
text = text,
|
||||||
scence = scene,
|
scence = scene,
|
||||||
|
extra = extraProvider?.invoke() ?: emptyList(),
|
||||||
|
actions = listActions,
|
||||||
onSuccess = { action ->
|
onSuccess = { action ->
|
||||||
when (action.name) {
|
when (action.name) {
|
||||||
"goToDecisionCenter" -> onGoToDecisionCenter?.invoke(action)
|
"goToDecisionCenter" -> onGoToDecisionCenter?.invoke(action)
|
||||||
"goToTaskCenter" -> onGoToTaskCenter?.invoke(action)
|
"goToTaskCenter" -> onGoToTaskCenter?.invoke(action)
|
||||||
else -> Log.d(TAG, "unhandled action: $action")
|
else -> Log.d(TAG, "unhandled action: $action")
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,19 +29,19 @@ object IntentRecognizeHelper {
|
|||||||
private var questionIndex = 0
|
private var questionIndex = 0
|
||||||
private var disposable: Disposable? = null
|
private var disposable: Disposable? = null
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context 用于显示 Toast
|
|
||||||
* @param text 指定问题文本;为 null 时自动轮换内置问题
|
* @param text 指定问题文本;为 null 时自动轮换内置问题
|
||||||
* @param scence 场景标识,默认 "home"
|
* @param scence 场景标识,默认 "home"
|
||||||
|
* @param extra 额外上下文数据(如 list 场景下的任务列表),原样传给服务端
|
||||||
|
* @param actions 允许的 action 列表,默认全部
|
||||||
* @param onSuccess 识别成功且 code=="0" 时回调,参数为 [RecognizeAction]
|
* @param onSuccess 识别成功且 code=="0" 时回调,参数为 [RecognizeAction]
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @param onComplete 无论成功失败都会回调,用于调用方重置 loading 状态
|
* @param onComplete 无论成功失败都会回调,用于调用方重置 loading 状态
|
||||||
*/
|
*/
|
||||||
fun recognize(
|
fun recognize(
|
||||||
text: String? = null,
|
text: String? = null,
|
||||||
scence: String = "home",
|
scence: String = "home",
|
||||||
|
extra: List<Any> = emptyList(),
|
||||||
|
actions: List<String> = listOf("goToTaskCenter", "goToDecisionCenter"),
|
||||||
onSuccess: (action: RecognizeAction) -> Unit,
|
onSuccess: (action: RecognizeAction) -> Unit,
|
||||||
onComplete: () -> Unit = {}
|
onComplete: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
@ -50,7 +50,7 @@ object IntentRecognizeHelper {
|
|||||||
disposable = HttpManager.getApi(
|
disposable = HttpManager.getApi(
|
||||||
MyApplication.appComponent1, Service::class.java
|
MyApplication.appComponent1, Service::class.java
|
||||||
)
|
)
|
||||||
.recognize(RecognizeData(text = question, scence = scence))
|
.recognize(RecognizeData(text = question, scence = scence, extra = extra, actions = actions))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe({ model ->
|
.subscribe({ model ->
|
||||||
@ -59,7 +59,7 @@ object IntentRecognizeHelper {
|
|||||||
} else {
|
} else {
|
||||||
model.message.showMessage()
|
model.message.showMessage()
|
||||||
}
|
}
|
||||||
onComplete() // 无论成功失败都执行
|
onComplete()
|
||||||
}, { e ->
|
}, { e ->
|
||||||
"请求失败: ${e.message}".showMessage()
|
"请求失败: ${e.message}".showMessage()
|
||||||
onComplete()
|
onComplete()
|
||||||
|
|||||||
@ -53,4 +53,7 @@ data class RecognizeParams(
|
|||||||
val taskType: String? = null,
|
val taskType: String? = null,
|
||||||
val tenantId: Int? = null,
|
val tenantId: Int? = null,
|
||||||
val userId: String? = null,
|
val userId: String? = null,
|
||||||
|
// list 场景下服务端返回的任务定位字段
|
||||||
|
val taskId: String? = null,
|
||||||
|
val taskIndex: Int? = null,
|
||||||
)
|
)
|
||||||
@ -3,14 +3,23 @@ package com.nova.brain.glass.model.data
|
|||||||
//{
|
//{
|
||||||
// "text": "查看下C919第45架机的零部件采购情况",
|
// "text": "查看下C919第45架机的零部件采购情况",
|
||||||
// "scence": "home",
|
// "scence": "home",
|
||||||
// "extra": [],
|
// "extra": [
|
||||||
// "actions": [
|
// { "index": 1, "id": "xxx", "taskType": "审核任务", "processStatus": "进行中", "aiDescription": "..." }
|
||||||
// "goToTaskCenter","goToDecisionCenter"
|
// ],
|
||||||
// ]
|
// "actions": ["goToDecisionCenter"]
|
||||||
//}
|
//}
|
||||||
data class RecognizeData(
|
data class RecognizeData(
|
||||||
val text: String,
|
val text: String,
|
||||||
val scence: String = "home",
|
val scence: String = "home",
|
||||||
val extra: List<String> = emptyList(),
|
val extra: List<Any> = emptyList(),
|
||||||
val actions: List<String> = listOf("goToTaskCenter", "goToDecisionCenter")
|
val actions: List<String> = listOf("goToTaskCenter", "goToDecisionCenter")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// list 场景下传给服务端,帮助 NLP 定位用户所说的任务
|
||||||
|
data class TaskExtraItem(
|
||||||
|
val index: Int, // 列表中的显示序号(1-based)
|
||||||
|
val id: String,
|
||||||
|
val taskType: String,
|
||||||
|
val processStatus: String,
|
||||||
|
val aiDescription: String
|
||||||
|
)
|
||||||
@ -23,11 +23,11 @@ class HeaderInterceptor(val context: Context) : Interceptor {
|
|||||||
|
|
||||||
//请求定制:添加请求头
|
//请求定制:添加请求头
|
||||||
val requestBuilder = original.newBuilder()
|
val requestBuilder = original.newBuilder()
|
||||||
.header("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJBSTAwMjIiLCJyblN0ciI6Im1OWUxobGZqWDJ2bEJMc21RdnFxSUE4dU9ZN0NOY3AzIiwidXNlckluZm8iOnsic3RhZmZObyI6IkFJMDAyMiJ9fQ.4BHcVpdkznqaQwPsyTn1my3_Zo0AliOILj_PjbCIK3k")
|
.header("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJyb2tpZCIsInJuU3RyIjoiQTU3NlV1VVV3V2s5NEpxSjlQcU9keDE1bE1tdU5JYmMiLCJ1c2VySW5mbyI6eyJzdGFmZk5vIjoicm9raWQifX0.qp1zWjYjqtmFS7Udo7Ga-a_XhVNwRUByXYomu6P6yxg")
|
||||||
.addHeader("Content-Type", "application/json;charset=UTF-8")
|
.addHeader("Content-Type", "application/json;charset=UTF-8")
|
||||||
.addHeader("Cookie", "__itrace_wid=87125211-8742-4f12-b5ca-32b9b6c860e4; locale=zh-Hans; _webtracing_device_id=t_13501877-b9b303fc-d3f52eb530e026b0")
|
.addHeader("Cookie", "__itrace_wid=87125211-8742-4f12-b5ca-32b9b6c860e4; locale=zh-Hans; _webtracing_device_id=t_13501877-b9b303fc-d3f52eb530e026b0")
|
||||||
.addHeader("Environment", "1")
|
.addHeader("Environment", "1")
|
||||||
.addHeader("currentUserId", "AI0022")
|
.addHeader("currentUserId", "rokid1")
|
||||||
.addHeader("terminal", "1")
|
.addHeader("terminal", "1")
|
||||||
.addHeader("modulename", "web")
|
.addHeader("modulename", "web")
|
||||||
.addHeader("currentUserName", "")
|
.addHeader("currentUserName", "")
|
||||||
|
|||||||
@ -6,9 +6,11 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.nova.brain.glass.R
|
import com.nova.brain.glass.R
|
||||||
import com.nova.brain.glass.databinding.ActivityTaskListBinding
|
import com.nova.brain.glass.databinding.ActivityTaskListBinding
|
||||||
|
import com.nova.brain.glass.helper.AsrHelper
|
||||||
import com.nova.brain.glass.helper.OfflineCmdListener
|
import com.nova.brain.glass.helper.OfflineCmdListener
|
||||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||||
import com.nova.brain.glass.model.TaskItem
|
import com.nova.brain.glass.model.TaskItem
|
||||||
|
import com.nova.brain.glass.model.data.TaskExtraItem
|
||||||
import com.nova.brain.glass.model.data.TaskListData
|
import com.nova.brain.glass.model.data.TaskListData
|
||||||
import com.nova.brain.glass.viewmodel.TaskListVM
|
import com.nova.brain.glass.viewmodel.TaskListVM
|
||||||
import com.xuqm.base.adapter.BasePagedAdapter
|
import com.xuqm.base.adapter.BasePagedAdapter
|
||||||
@ -190,12 +192,38 @@ class TaskListActivity :
|
|||||||
OfflineCmdServiceHelper.addListenerList()
|
OfflineCmdServiceHelper.addListenerList()
|
||||||
LogHelper.d(">>>>>>>>>>>>--------------------")
|
LogHelper.d(">>>>>>>>>>>>--------------------")
|
||||||
OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
|
OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
|
||||||
|
AsrHelper.scene = "list"
|
||||||
|
AsrHelper.extraProvider = {
|
||||||
|
viewModel.currentItems.mapIndexed { i, item ->
|
||||||
|
TaskExtraItem(
|
||||||
|
index = i + 1,
|
||||||
|
id = item.id,
|
||||||
|
taskType = item.taskType,
|
||||||
|
processStatus = item.processStatus,
|
||||||
|
aiDescription = item.aiDescription
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AsrHelper.onGoToDecisionCenter = { action ->
|
||||||
|
val taskId = action.params.taskId
|
||||||
|
val taskIndex = action.params.taskIndex
|
||||||
|
when {
|
||||||
|
taskId != null -> {
|
||||||
|
val position = viewModel.currentItems.indexOfFirst { it.id == taskId }
|
||||||
|
if (position >= 0) openTask(position)
|
||||||
|
}
|
||||||
|
taskIndex != null -> openVisibleTask(taskIndex - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
OfflineCmdServiceHelper.removeListenerList()
|
OfflineCmdServiceHelper.removeListenerList()
|
||||||
OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener)
|
OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener)
|
||||||
|
AsrHelper.scene = "home"
|
||||||
|
AsrHelper.extraProvider = null
|
||||||
|
AsrHelper.onGoToDecisionCenter = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private val adapter = object : CommonPagedAdapter<TaskItem>(R.layout.item_task_list) {
|
private val adapter = object : CommonPagedAdapter<TaskItem>(R.layout.item_task_list) {
|
||||||
|
|||||||
@ -18,9 +18,12 @@ class TaskListVM : BaseListViewModel<TaskItem>() {
|
|||||||
|
|
||||||
val taskCount = MutableLiveData<Int>()
|
val taskCount = MutableLiveData<Int>()
|
||||||
|
|
||||||
|
var currentItems: List<TaskItem> = emptyList()
|
||||||
|
private set
|
||||||
|
|
||||||
override fun loadData(page: Int, onResponse: Response<TaskItem>) {
|
override fun loadData(page: Int, onResponse: Response<TaskItem>) {
|
||||||
add(
|
add(
|
||||||
HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
|
HttpManager.getApi(Service::class.java)
|
||||||
.glassesTaskSearch(searchParams)
|
.glassesTaskSearch(searchParams)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -34,6 +37,7 @@ class TaskListVM : BaseListViewModel<TaskItem>() {
|
|||||||
aiDescription = it.aiDescription
|
aiDescription = it.aiDescription
|
||||||
)
|
)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
currentItems = items
|
||||||
taskCount.value = response.data?.total ?: items.size
|
taskCount.value = response.data?.total ?: items.size
|
||||||
onResponse.onResponse(ArrayList(items))
|
onResponse.onResponse(ArrayList(items))
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户