当前位置: 首页 > news >正文

语音识别-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 = falsereturn}// 使用源码流读取 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?.contentif (!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.sizevar last: Assistant? = nullfor (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 = nullcontinue} else {last = itemmsgList.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 = itemmsgList.add(item)}}}if (msgList.isNotEmpty()) {count = msgList.sizefor (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就会有上下文了.

http://www.xdnf.cn/news/463411.html

相关文章:

  • IT系统的基础设施:流量治理、服务治理、资源治理,还有数据治理。
  • 工作实战之关于数据库表的备份
  • 『已解决』Python virtualenv_ error_ unrecognized arguments_--wheel-bundle
  • 浏览器验证证书
  • 【AI News | 20250515】每日AI进展
  • 蓝牙BLE协议之——LL层
  • 【LeetCode 热题 100】56. 合并区间 —— 一文弄懂排序+遍历经典解法(附Python代码)
  • 使用Mathematica绘制Clifford奇异吸引子
  • 香港科技大学广州|智能制造学域硕博招生宣讲会-西北工业大学
  • Windows AD 域客户端电脑时间不准解决方案
  • 解决xxx.jar中没有主清单属性的问题
  • Linux文件操作系统接口介绍,以及文件描述符的本质
  • 大语言模型 08 - 从0开始训练GPT 0.25B参数量 - MiniMind 单机多卡 torchrun deepspeed
  • Maven 插件参数注入与Mojo开发详解
  • journal of Electronic Imaging(JEI)投稿咨询
  • ZFile与Cpolar技术结合实现远程数据实时访问与集中管理的可行性分析
  • 15:00开始面试,15:06就出来了,问的问题有点变态。。。
  • 【hadoop】Flume日志采集系统的安装部署
  • element ui 级联列表Cascader懒加载数据回显的优雅解决方案
  • 学习黑客什么是TPS?
  • 课程11. 计算机视觉、自编码器和生成对抗网络 (GAN)
  • apt 安装 postgres vector插件
  • mac docker弹窗提示Docker 启动没有响应
  • 计算机视觉----常见卷积汇总
  • [服务器面板对比] 宝塔、aaPanel、Plesk、cPanel 哪家强?功能、性能与价格横评 (2025)
  • JAVA中异常体系总结
  • Ubuntu shell指定conda的python环境启动脚本
  • 构建RAG混合开发---PythonAI+JavaEE+Vue.js前端的实践
  • 【论信息系统项目的合同管理】
  • VTEP是什么