语音识别-3,添加ai问答

目录

1.基础请求:

2.关联上下文


语音app一般都会添加问答功能.最常见的几deepseek.本文就以它为例.

申请api不说了.

https://api.deepseek.com/chat/completions 这是接口.

Authorization:Bearer sk-xxxxxxx( 这是你的key)

最简的调用方式:rest客户端的

复制代码
{
  "messages": [
    {
      "content": "用中文回复:北京常住人口,各区人口.",
      "role": "user"
    }
  ],
  "model": "deepseek-chat",
  "stream": true
}

"stream": true表示以流的方式返回数据.一般,流的方式让人感觉快一些.等流全部返回了,时间也差不多了.如果不用流的方式,一次调用可能一分钟.

deepseek-chat和deepseek-reasoner是不一样的.deepseek-reasoner是r1.有思考的过程.

1.基础请求:

先有一个okhttp:

复制代码
fun streamPost(json: String, callback: Callback) {
        val client = OkHttpClient.Builder()
            .connectTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(180, TimeUnit.SECONDS)
            .readTimeout(180, TimeUnit.SECONDS)
            .callTimeout(180, TimeUnit.SECONDS)
            .build()
        val builder = Request.Builder()
            .url("https://api.deepseek.com/chat/completions")
        builder.addHeader(
            "Authorization", "Bearer sk-xxxxxxxxxx"
        )
        builder.addHeader("content-type", "application/json")
        if (!TextUtils.isEmpty(json.toString())) {
            val body = json.toString().toRequestBody(JSON)
            builder.post(body)
        }
        client.newCall(builder.build()).enqueue(callback)
    }

接着调用:

复制代码
OKHttpHelper.streamPost(
            json.toString(),
            object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    Timber.tag(TAG).d("sendToDsStreamAI请求失败: ${e.message}")
                    setErrorMsg()
                    isLoading = false
                }

                override fun onResponse(call: Call, response: Response) {
                    if (!response.isSuccessful) {
                        Timber.tag(TAG).e("sendToDsStreamAI请求返回失败: ${response.code}")
                        setErrorMsg()
                        isLoading = false
                        return
                    }

                    // 使用源码流读取 SSE 数据
                    response.body?.source()?.use { source ->
                        streamResp(source, type_msg_assistant)
                        isLoading = false
                    } ?: {
                        isLoading = false
                    }
                }
            })

解析:

复制代码
private fun streamResp(source: BufferedSource, type: Int) {
        footerUserView?.hide()
        val builder = StringBuilder()
        try {
            while (!source.exhausted()) {
                try {
                    val line = source.readUtf8LineStrict()
                    if (line.startsWith("data:")) {
                        //Timber.tag(TAG).d("接收到数据: $line")
                        val data = line.substringAfter("data:")
                        if (TextUtils.equals("[DONE]", data.trim())) {
                            Timber.tag(TAG).d("接收到结束: $builder")
                            addAssistant(builder, "")
                            return
                        }
                        val resp = Gson().fromJson<DSResp>(data, DSResp::class.java)
                        //Timber.tag(TAG).d("useDs.result:%s", resp)
                        if (resp?.choices?.isNotEmpty() == true) {
                            AppExecutors.instance.mainThread().execute {
                                val content = resp.choices!![0].delta?.content
                                if (!TextUtils.isEmpty(content)) {
                                    builder.append(content)
                                    footerView?.setText(builder.toString())
                                }
                            }
                        }
                    }
                } catch (e: Exception) {
                    Timber.tag(TAG).e(e)
                    setErrorMsg()
                }
            }
        } catch (e: Exception) {
            Timber.tag(TAG).e(e)
            setErrorMsg()
        }
    }

关于流返回的格式,从官方的文档可以得到.

2.关联上下文

文档里说明了,要想在刚才的问题继续下去,需要把前面的问题一起给后端.

复制代码
val json = JSONObject()
        json.put("model", "deepseek-chat")
        json.put("stream", true)

        val messages = getHistories(input, oldList)
        json.put("messages", messages)
        Timber.tag(TAG).d("请求json: $json")

定义一个实体:

class Assistant:

var type: Int = type_msg_user

const val type_msg_user = 0

const val type_msg_assistant = -2

这定义了两种,一种是用户的问题,一种是ai的回答.

在列表中,可能一个ai,一个用户问题.

复制代码
private fun getHistories(input: String, list: List<Assistant>): JSONArray {
        var messages = JSONArray()

        //只能一个ai,一个用户这样间隔的对话.把不符合的过滤了.
        if (list.isNotEmpty()) {
            val msgList = arrayListOf<Assistant>()
            var count = list.size
            var last: Assistant? = null
            for (i in count - 1 downTo 0) {
                val item = list[i]
                if (item.type == type_msg_assistant) {
                    if (last != null && last.type == type_msg_assistant) {
                        Timber.tag(TAG).d("上一个消息是助手消息: $last")
                        continue
                    }
                    if (!item.success) {
                        Timber.tag(TAG).d("助手失败的消息: $item, last:$last")
                        last = null
                        continue
                    } else {
                        last = item
                        msgList.add(item)
                    }
                } else {
                    if (last == null) {
                        Timber.tag(TAG).d("上一个消息是空,用户消息跳过,可能是出错的消息: $last")
                        continue
                    }
                    if (last.type == type_msg_user) {
                        Timber.tag(TAG).d("上一个消息是用户消息,跳过: $last")
                        continue
                    }
                    if (!item.success) {
                        Timber.tag(TAG).d("上一个消息是用户失败的消息,跳过: $last")
                        continue
                    } else {
                        last = item
                        msgList.add(item)
                    }
                }
            }
            if (msgList.isNotEmpty()) {
                count = msgList.size
                for (i in count - 1 downTo 0) {
                    val item = msgList[i]
                    val content = JSONObject()
                    content.put("content", item.content)
                    if (item.type == type_msg_assistant) {
                        content.put("role", "assistant")
                    } else {
                        content.put("role", "user")
                    }
                    messages.put(content)
                }
            }
        }

        val content = JSONObject()
        content.put("role", "user")
        content.put("content", input)
        messages.put(content)
        return messages
    }

这样得到数据,发送,ai就会有上下文了.

相关推荐
武子康11 分钟前
大语言模型 09 - 从0开始训练GPT 0.25B参数量 补充知识之数据集 Pretrain SFT RLHF
人工智能·gpt·ai·语言模型·自然语言处理
androidwork14 分钟前
Android 中使用通知(Kotlin 版)
android·kotlin
davysiao23 分钟前
AG-UI 协议:重构多模态交互,开启智能应用新纪元
人工智能
沃洛德.辛肯25 分钟前
PyTorch 的 F.scaled_dot_product_attention 返回Nan
人工智能·pytorch·python
sy_cora1 小时前
IEEE 列表会议第五届机器人、自动化与智能控制国际会议
运维·人工智能·机器人·自动化
吹风看太阳1 小时前
机器学习08-损失函数
人工智能·机器学习
m0_740154671 小时前
《k-means 散点图可视化》实验报告
人工智能·机器学习·kmeans
zhz52141 小时前
AI数字人融合VR全景:开启未来营销与交互新篇章
人工智能·ai·交互·vr·ai编程·智能体
智源研究院官方账号1 小时前
智源联合南开大学开源Chinese-LiPS中文多模态语音识别数据集
人工智能·语音识别
Thomas_YXQ1 小时前
Unity3D Overdraw性能优化详解
开发语言·人工智能·性能优化·unity3d