安卓接入通义千问AI的实现记录
·
官网:https://help.aliyun.com/zh/model-studio/use-qwen-by-calling-api#b1320a1664b9a
创建网络请求
- 创建一个BaseNetworkApi基类用于实现各种拦截器等。
abstract class BaseNetworkApi {
fun <T> getApi(serviceClass: Class<T>, baseUrl: String): T {
val retrofitBuilder = Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
return setRetrofitBuilder(retrofitBuilder).build().create(serviceClass)
}
/**
* 实现重写父类的setHttpClientBuilder方法,
* 在这里可以添加拦截器,可以对 OkHttpClient.Builder 做任意操作
*/
abstract fun setHttpClientBuilder(builder: OkHttpClient.Builder): OkHttpClient.Builder
/**
* 实现重写父类的setRetrofitBuilder方法,
* 在这里可以对Retrofit.Builder做任意操作,比如添加GSON解析器,Protocol
*/
abstract fun setRetrofitBuilder(builder: Retrofit.Builder): Retrofit.Builder
/**
* 配置http
*/
private val okHttpClient: OkHttpClient
get() {
var builder = RetrofitUrlManager.getInstance().with(OkHttpClient.Builder())
builder = setHttpClientBuilder(builder)
return builder.build()
}
}
- 完成BaseNetworkApi的具体实现类。
val aiService : AiService by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
AiApi.INSTANCE.getApi(AiService::class.java, AiService.getBaseUrl())
}
class AiApi : BaseNetworkApi() {
companion object {
val INSTANCE: AiApi by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
AiApi()
}
}
/**
* 实现重写父类的setHttpClientBuilder方法,
* 在这里可以添加拦截器,可以对 OkHttpClient.Builder 做任意操作
*/
override fun setHttpClientBuilder(builder: OkHttpClient.Builder): OkHttpClient.Builder {
builder.apply {
//设置缓存配置 缓存最大10M
cache(Cache(File(appContext.cacheDir, "cxk_cache"), 10 * 1024 * 1024))
//添加Cookies自动持久化
cookieJar(cookieJar)
addInterceptor(AiInterceptor())
//超时时间 连接、读、写
connectTimeout(10, TimeUnit.SECONDS)
readTimeout(120, TimeUnit.SECONDS)
writeTimeout(30, TimeUnit.SECONDS)
}
return builder
}
/**
* 实现重写父类的setRetrofitBuilder方法,
* 在这里可以对Retrofit.Builder做任意操作,比如添加GSON解析器,protobuf等
*/
override fun setRetrofitBuilder(builder: Retrofit.Builder): Retrofit.Builder {
return builder.apply {
addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
}
}
val cookieJar: PersistentCookieJar by lazy {
PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(appContext))
}
}
- 在AiInterceptor完成公共Header的添加。
class AiInterceptor : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val builder = chain.request().newBuilder()
builder.addHeader("Authorization", "Bearer sk-xxxxxxxxxxxxxxxxxxxx")
builder.addHeader("Content-Type", "application/json")
.build()
return chain.proceed(builder.build())
}
}
此处的Key可在阿里云百炼自行申请。
- 通过第三方框架retrofit2完成网络请求注解。
interface AiService {
companion object {
fun getBaseUrl(): String {
return "https://dashscope.aliyuncs.com"
}
}
@POST("compatible-mode/v1/chat/completions")
suspend fun askQuestion(@Body request: AiRequest): AiResponse<List<Choice>>
}
@Keep
data class AiResponse<T>(val error: Error?, val choices: T) : BaseResponse<T>() {
override fun isSucces() = error == null
override fun getResponseCode(): Int {
return if (error == null) {
200
} else {
400
}
}
override fun getResponseData() = choices
override fun getResponseMsg(): String {
return error?.message?: ""
}
}
data class Error(val message: String?, val type: String?, val param: String?, val code: String?)
data class Message(var role: String?, var content: String?)
data class Choice(var message: Message?, var finish_reason: String?, var index: Int?)
data class AiRequest(var model: String?, var messages: List<Message>?, var stream :Boolean? = false)
@Keep
abstract class BaseResponse<T> {
abstract fun isSucces(): Boolean
abstract fun getResponseData(): T
abstract fun getResponseCode(): Int
abstract fun getResponseMsg(): String
}
- 在需要的地方直接调用即可,亦可编辑请求类对异常情况进行处理。
val message = Message("user", "你好")
val messageList = ArrayList<Message>()
messageList.add(message)
val request1 = AiRequest("qwen-max", messageList)
lifecycleScope.launch {
val response = aiService.askQuestion(request1)
Log.d("AI-test", response.toString())
}

- 实现效果如下。

- 遇到的问题
● 在请求时,报java.net.SocketTimeoutException: timeout
遇到的 java.net.SocketTimeoutException: timeout 是网络请求超时问题,在调用阿里通义千问API时很常见。以下是建议方案:
① 增加超时时间配置
connectTimeout(10, TimeUnit.SECONDS)
readTimeout(120, TimeUnit.SECONDS)
writeTimeout(30, TimeUnit.SECONDS)
② 网络状态检查
③ 使用 qwen-turbo,响应速度最快
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)