概述
开通华为云账号——>开通DeepSeek-V3-32K服务——>得到API KEY——>根据URL和KEY发送请求——>解析SSE数据
一、先开通服务
- 注册华为云deepseek的账号开通
- deepSeek接入需要费用,华为云给每个新用户提供了200万个token的免费额度 推理
- 每推理一个字大约耗费1000个token
如果欠费则充值1块钱即可
开通后就可以查看调用说明
这里就可以看到API地址了,然后去生成KEY
创建KEY随便填,只要描述能一目了然这个KEY是干啥申请来的,再点击确定,此时,不要关闭页面!copy好这个KEY,因为这个KEY只有此时一次机会才能看到明文
API到这里就结束了
上代码
1,封装调用请求
这里用的harmonyOS5推荐的RPC通信,整体逻辑与HTTP无异。做一个post请求,然后在拦截器干点事儿就没了
// deepSeek的数据和我们平时请求的数据有什么区别
import { rcp } from "@kit.RemoteCommunicationKit"
import { util } from "@kit.ArkTS";
import { logger } from ".";
// 推理模型-一个字一个字在推-记录当前的文本属于哪个上下文
// 接口一口气把所有的结果都给用户
// 拦截器的class实现并继承 rcp.Interceptor
const APIKey = "Mq2__BD-yEN53auAxivaZu2cywgkU_3BkbIedR2PI9eCZAR5rfC9PMIyUMOU46pw46dl00_fP7PQrvb5V6_Oyg"; // APIkey
const url = "https://api.modelarts-maas.com/v1/chat/completions" // 请求url地址
class DeepSeekRcpRequest implements rcp.Interceptor {
intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
// 注入token
context.request.headers!.authorization = `Bearer ${APIKey}`; // 注入apikey
return next.handle(context)
}
}
export class DeepSeekRcp {
session: rcp.Session | null = null // rcp的请求实例对象
initSession() {
this.session = rcp.createSession({
// 配置拦截器
interceptors: [new DeepSeekRcpRequest()], // 注入token的拦截器
// 接收二进制数据流
requestConfiguration: {
tracing: {
httpEventsHandler: {
// 接收数据
onDataReceive: (bf)=>{
// SSE数据
// bf => Json
// ArrayBuffer => Uint8Array
const uin8 = new Uint8Array(bf)
// 解码器 =>
const decoder = new util.TextDecoder()
const str = decoder.decodeToString(uin8); // 输出结果
logger.info(str) //
}
}
}
}
})
}
// 发送问题给deepSeek
postDeepSeek(data: object) {
if (!this.session) {
this.initSession()
}
// 发送deepSeek请求 不能立刻渴望得到结果 内容推理 一个字一个字在推
this.session?.post(url, data);
}
}
export const deepSeekRcp = new DeepSeekRcp()
UI代码:
// 调用rcp的方法
sendData() {
let params: DeepSeekParams = {
model: 'DeepSeek-V3',
max_tokens: 1024,
messages = [
//整个对话过程分为两个角色,system为deepseeek方,user为客户端方
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "你好"},
],
stream: true,
temperature: 1
}
deepSeekRcp.postDeepSeek(params);
}
build() {
Column() {
Button('测试DeepSeek')
.onClick(()=>{
this.sendData()
})
}
.width("100%")
.height("100%")
}
.hideTitleBar(true)
}
以上一个简单的测试demo就好了,你可以拿去测一下了哦
2,解析SSE消息
// deepSeek的数据和我们平时请求的数据有什么区别
import { rcp } from "@kit.RemoteCommunicationKit"
import { util } from "@kit.ArkTS";
import { logger } from ".";
// 推理模型-一个字一个字在推-记录当前的文本属于哪个上下文
// 接口一口气把所有的结果都给用户
// 拦截器的class实现并继承 rcp.Interceptor
const APIKey = "Mq2__BD-yEN53auAxivaZu2cywgkU_3BkbIedR2PI9eCZAR5rfC9PMIyUMOU46pw46dl00_fP7PQrvb5V6_Oyg"; // APIkey
const url = "https://api.modelarts-maas.com/v1/chat/completions" // 请求url地址
class DeepSeekRcpRequest implements rcp.Interceptor {
intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
// 注入token
context.request.headers!.authorization = `Bearer ${APIKey}`; // 注入apikey
return next.handle(context)
}
}
export class DeepSeekRcp {
session: rcp.Session | null = null // rcp的请求实例对象
private textCallBack?: (message: String[], finished: boolean) => void // 不间断调用
private cacheMessage: Map<String, String[]> = new Map(); // 暂存消息
initSession() {
this.session = rcp.createSession({
// 配置拦截器
interceptors: [new DeepSeekRcpRequest()], // 注入token的拦截器
// 接收二进制数据流
requestConfiguration: {
tracing: {
httpEventsHandler: {
// 接收数据
onDataReceive: (bf)=>{
// SSE数据
// bf => Json
// ArrayBuffer => Uint8Array
const uin8 = new Uint8Array(bf)
// 解码器 =>
const decoder = new util.TextDecoder()
const str = decoder.decodeToString(uin8); // 输出结果
logger.info(str)
//********************************************解析开始了哦********************************************//
// 把消息取出放入数组,你现在看到内容都是一行一行的,所以我们先去掉换行组织称一个数组
const list = str.split('\n\n')
// 针对数组的每一条数据处理
// 把data:截取出
for(let item of list){
const dealStr = item.substring(5);
if (dealStr) {
// 1. 把消息转换出来
const message = JSON.parse(dealStr) as ChatCompletionChunk
// 2. 判断map中是否缓存过同一条消息的部分内容
if(!this.cacheMessage.has(message.id)){
this.cacheMessage.set(message.id, [])
}
// 3. 把消息放入缓存
const list = this.cacheMessage.get(message.id)
message.choices.map(obj => {
// logger.info(obj.delta.content, '-----')
list?.push(obj.delta.content)
})
// 4. 判断消息是否结束
let isFinished = false
if(message.choices[0].finish_reason === 'stop'){
// 此时消息结束
isFinished = true
}
// 5. 把消息写入临时缓存
this.cacheMessage.set(message.id, list)
// 6.把消息回调出去
this.textCallBack?.(list, isFinished)
// 7. 判断消息是否完成
if(isFinished){
this.cacheMessage.delete(message.id)
}
}
}
}
}
}
}
})
}
// 发送问题给deepSeek
postDeepSeek(data: object, callback?: (message: String[], finished: boolean) => void) {
if (!this.session) {
this.initSession()
}
// 方便上面方法调用该回调函数
this.textCallBack = callback
// 发送deepSeek请求 不能立刻渴望得到结果 内容推理 一个字一个字在推
this.session?.post(url, data);
}
}
export const deepSeekRcp = new DeepSeekRcp()
UI修改
// 调用rcp的方法
sendData() {
let params: DeepSeekParams = {
model: 'DeepSeek-V3',
max_tokens: 1024,
messages = [
//整个对话过程分为两个角色,system为deepseeek方,user为客户端方
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "你好"},
],
stream: true,
temperature: 1
}
deepSeekRcp.postDeepSeek(params, (cacheMessage, finished) => {
this.response = cacheMessage.join("");
if (finished) {
AlertDialog.show({ message: "消息发完了" });
}
});
}
build() {
Column() {
Button('测试DeepSeek')
.onClick(()=>{
this.sendData()
})
}
.width("100%")
.height("100%")
}
.hideTitleBar(true)
}
看懂了啵,鼓励一个一键三连叭,一起创建harmonyOS5的生态环境叭