讯飞星火认知大模型智能语音交互调用

        随着国内外大模型热度的兴起,依托于大模型的智能化,传统的人机交互已经不能满足人们交互的需求。而结合语音和大模型的交互拜托传统互联网获取知识的文字限制,用语音也可以轻松获取想要的知识和思路。

一、大模型智能语音交互调用实现思路

唤醒的持久运行--->合成能力加持(唤醒成功后语音答复:主人 我在)--->调用在线或离线听写能力(建议用讯飞在线效果好)--->识别用户说的语音成文字后发给大模型--->建议调用讯飞星火认知大模型--->获取大模型答案后调用语音合成(合成在线离线均可)进行答案输出。

这样就顺利实现了用纯语音与大模型进行交互!

难点:唤醒+听写同时读取麦克风音频的节奏控制

持续语音交互调用大模型效果图:

二、离线环境常量定义

package com.day.config;import com.sun.jna.ptr.IntByReference;import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;public class Constants {// 构造16K 16BIT 单声道音频public static final String APPID = "5e11538f";  // APPIDpublic static final String WORK_DIR = "src/main/resources";// 1、唤醒相关  ssb_param,一定注意IVW_SSB_PARAMS的fo|xxx资源的路径,xxx取值是指WORK_DIR目录下/msc/xxx   xxx是以后的路径开始拼接的!!!!!!!!!!!public static final AudioFormat IVW_ASR_AUDIO_FORMAT = new AudioFormat(16000F, 16, 1, true, false);public static final String IVW_DLL_PATH = "src/main/resources/ivw_msc_x64.dll"; // windows动态库路径public static final String IVW_LOGIN_PARAMS = "appid = " + APPID + ", work_dir = " + WORK_DIR;public static final String IVW_SSB_PARAMS = "ivw_threshold=0:1500,sst=wakeup,ivw_shot_word=1,ivw_res_path =fo|res/ivw/wakeupresource.jet";public static IntByReference IVW_ERROR_CODE = new IntByReference(-100);public static Integer IVW_FRAME_SIZE = 6400;  // 一定要每200ms写10帧,否则会出现唤醒一段时间后无法唤醒的问题,一帧的大小为640B,其他大小可能导致无法唤醒。public static Integer IVW_AUDIO_STATUS = 1;public static DataLine.Info IVW_ASR_DATA_LINE_INFO = new DataLine.Info(TargetDataLine.class, IVW_ASR_AUDIO_FORMAT);public static TargetDataLine IVW_ASR_TARGET_DATA_LINE; // 录音static {try {IVW_ASR_TARGET_DATA_LINE = (TargetDataLine) AudioSystem.getLine(IVW_ASR_DATA_LINE_INFO);} catch (LineUnavailableException e) {e.printStackTrace();}}// 2、合成相关public static final AudioFormat TTS_AUDIO_FORMAT = new AudioFormat(16000F, 16, 1, true, false);public static final String TTS_DLL_PATH = "src/main/resources/tts_msc_x64.dll"; // windows动态库路径public static final String TTS_LOGIN_PARAMS = "appid = " + APPID + ", work_dir = " + WORK_DIR;public static final String TTS_SESSION_BEGIN_PARAMS = "engine_type = local, voice_name = xiaoyuan, text_encoding = UTF8," + " tts_res_path = fo|res/tts/xiaoyuan.jet;fo|res/tts/common.jet, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";public static IntByReference TTS_ERROR_CODE = new IntByReference(-100);public static IntByReference TTS_AUDIO_LEN = new IntByReference(-100);public static IntByReference TTS_SYNTH_STATUS = new IntByReference(-100);public static String TTS_TEXT; // 合成文本public static Integer TTS_TOTAL_AUDIO_LENGTH; // 合成音频长度public static ByteArrayOutputStream TTS_BYTE_ARRAY_OUTPUT_STREAM; // 合成音频流public static DataLine.Info TTS_DATA_LINE_INFO = new DataLine.Info(SourceDataLine.class, TTS_AUDIO_FORMAT, AudioSystem.NOT_SPECIFIED);public static SourceDataLine TTS_SOURCE_DATA_LINE; // 播放static {try {TTS_SOURCE_DATA_LINE = (SourceDataLine) AudioSystem.getLine(Constants.TTS_DATA_LINE_INFO);} catch (LineUnavailableException e) {e.printStackTrace();}}public static final String YELLOW_BACKGROUND = "\u001B[43m"; // ANSI code for yellow backgroundpublic static final String RESET = "\u001B[0m"; // ANSI code to reset to default
}

三、唤醒+合成代码

package com.day;import com.day.config.Constants;
import com.day.service.IvwService;
import com.day.service.TtsService;
import com.day.service.imp.IvwCallback;
import com.sun.jna.Pointer;import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;// 主函数入口
public class AIMain {public static boolean ttsFlag = false;public static boolean ivwFlag = false;public static byte[] audioDataByteArray;public static int len;public static void main(String[] args) throws Exception {// 调用流程:唤醒--->// System.out.println(Constants.yellowBackground + "呼叫大飞" + Constants.reset);// 以线程的方式启动唤醒MyThread myThread = new MyThread();myThread.start();}static class MyThread extends Thread {public void run() {startIvw();}}// 1、唤醒调用public static void startIvw() {Integer ret = IvwService.INSTANCE.MSPLogin(null, null, Constants.IVW_LOGIN_PARAMS); // 登录if (ret != 0) {System.out.println("唤醒登录失败...:" + ret);}String sessionId = IvwService.INSTANCE.QIVWSessionBegin(null, Constants.IVW_SSB_PARAMS, Constants.IVW_ERROR_CODE); // 开启会话if (Constants.IVW_ERROR_CODE.getValue() != 0) {System.out.println("开启唤醒会话失败...:" + Constants.IVW_ERROR_CODE.getValue());}ret = IvwService.INSTANCE.QIVWRegisterNotify(sessionId, new IvwCallback(), null); // 注册唤醒回调函数if (ret != 0) {System.out.println("注册唤醒回调函数失败...:" + ret);}try {while (true) {// System.err.println("唤醒监听中");Constants.IVW_ASR_TARGET_DATA_LINE.open(Constants.IVW_ASR_AUDIO_FORMAT);Constants.IVW_ASR_TARGET_DATA_LINE.start();audioDataByteArray = new byte[Constants.IVW_FRAME_SIZE];len = new AudioInputStream(Constants.IVW_ASR_TARGET_DATA_LINE).read(audioDataByteArray);if (len == -1) {   //    调用麦克风时候,这段将不会被执行...Constants.IVW_AUDIO_STATUS = 4;ret = IvwService.INSTANCE.QIVWAudioWrite(sessionId, "".getBytes(), 0, Constants.IVW_AUDIO_STATUS);System.out.println("最后一帧返回的错误码:" + ret + ",即将执行退出...");break;  //文件读完,跳出循环} else {// 反复调用QIVWAudioWrite写音频方法,直到音频写完为止!!!!!!!!!!!!ret = IvwService.INSTANCE.QIVWAudioWrite(sessionId, audioDataByteArray, len, Constants.IVW_AUDIO_STATUS);// System.out.println("写入音频中");}Constants.IVW_AUDIO_STATUS = 2; // 中间帧if (ret != 0) {System.err.println("唤醒音频写入失败...:" + ret);}Thread.sleep(200); // 模拟人说话时间间隙,10帧的音频200ms写入一次if (ivwFlag) {IvwService.INSTANCE.QIVWSessionEnd(sessionId, "");IvwService.INSTANCE.MSPLogout();Constants.IVW_ASR_TARGET_DATA_LINE.stop();Constants.IVW_ASR_TARGET_DATA_LINE.close();ivwFlag = false;break;}// System.err.println("唤醒监听中");}startIvw();} catch (Exception e) {e.printStackTrace();}}// 2、合成调用public static void startTts(String ttsText) {if (!AIMain.ttsFlag) {ttsFlag = true;Constants.TTS_TEXT = ttsText;Constants.TTS_TOTAL_AUDIO_LENGTH = 0;Integer ret = TtsService.INSTANCE.MSPLogin(null, null, Constants.TTS_LOGIN_PARAMS); // 登录if (ret != 0) {System.out.println("合成登录失败...:" + ret);}String session_id = TtsService.INSTANCE.QTTSSessionBegin(Constants.TTS_SESSION_BEGIN_PARAMS, Constants.TTS_ERROR_CODE); // 开启合成会话if (Constants.TTS_ERROR_CODE.getValue() != 0) {System.out.println("合成开启会话失败...:" + Constants.TTS_ERROR_CODE.getValue());}ret = TtsService.INSTANCE.QTTSTextPut(session_id, Constants.TTS_TEXT, Constants.TTS_TEXT.getBytes().length, null); // 正式合成if (ret != 0) {System.out.println("合成音频失败...:" + ret);}try {    //实时播放Constants.TTS_SOURCE_DATA_LINE.open(Constants.TTS_AUDIO_FORMAT);Constants.TTS_SOURCE_DATA_LINE.start();} catch (Exception e) {e.printStackTrace();}while (true) {Pointer audioPointer = TtsService.INSTANCE.QTTSAudioGet(session_id, Constants.TTS_AUDIO_LEN, Constants.TTS_SYNTH_STATUS, Constants.TTS_ERROR_CODE); // 获取音频byte[] audioDataByteArray = null;if (audioPointer != null) {audioDataByteArray = audioPointer.getByteArray(0, Constants.TTS_AUDIO_LEN.getValue());}if (Constants.TTS_ERROR_CODE.getValue() != 0) {System.out.println("合成获取音频失败...+:" + Constants.TTS_ERROR_CODE);break;}if (audioDataByteArray != null) {try {Constants.TTS_SOURCE_DATA_LINE.write(audioDataByteArray, 0, Constants.TTS_AUDIO_LEN.getValue()); //实时写音频流} catch (Exception e) {e.printStackTrace();}Constants.TTS_TOTAL_AUDIO_LENGTH = Constants.TTS_TOTAL_AUDIO_LENGTH + Constants.TTS_AUDIO_LEN.getValue();     //计算总音频长度,用来生成音频文件}if (Constants.TTS_SYNTH_STATUS.getValue() == 2) {// 说明音频已经取完,退出本次循环try {// Constants.TTS_SOURCE_DATA_LINE.drain();// Constants.TTS_SOURCE_DATA_LINE.close();} catch (Exception e) {e.printStackTrace();}break;}}ret = TtsService.INSTANCE.QTTSSessionEnd(session_id, "正常退出"); //结束会话if (ret != 0) {System.out.println("合成结束会话失败...:" + ret);}ret = TtsService.INSTANCE.MSPLogout(); // 退出if (ret != 0) {System.out.println("合成退出失败...:" + ret);}} else {Constants.TTS_SOURCE_DATA_LINE.stop();Constants.TTS_SOURCE_DATA_LINE.close();}AIMain.ttsFlag = false;}
}

唤醒+合成库加载

package com.day.service;import com.day.config.Constants;
import com.day.service.imp.IvwCallback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;public interface IvwService extends Library {/*** 重点:* 1.char *   对应  String* 2.int *    对应  IntByReference* 3.void *   对应  Pointer或byte[]* 4.int      对应  int* 5.无参     对应  无参* 6.回调函数  对应  根据文档自定义回调函数,实现接口Callback*///加载dll动态库并实例化,从而使用其内部的方法IvwService INSTANCE = Native.loadLibrary(Constants.IVW_DLL_PATH, IvwService.class);//定义登录方法    MSPLogin(const char *usr, const char *pwd, const char *params)public Integer MSPLogin(String usr, String pwd, String params);//定义开始方法    QIVWSessionbegin(const char *grammarList, const char *params, int *errorCode)public String QIVWSessionBegin(String grammarList, String params, IntByReference errorCode);//定义写音频方法  QIVWAudioWrite(const char *sessionID, const void *audioData, unsigned int audioLen, int audioStatus)public Integer QIVWAudioWrite(String sessionID, byte[] audioData, int audioLen, int audioStatus);//定义结束方法    QIVWSessionEnd(const char *sessionID, const char *hints)public Integer QIVWSessionEnd(String sessionID, String hints);//定义获取结果方法 QIVWRegisterNotify(const char *sessionID, ivw_ntf_handler msgProcCb, void *userData)public Integer QIVWRegisterNotify(String sessionID, IvwCallback ivwCallback, byte[] userData);//定义退出方法 唤醒一般不用退出public Integer MSPLogout();
}
package com.day.service;import com.day.config.Constants;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;public interface TtsService extends Library {/*** 重点:* 1.char *   对应  String* 2.int *    对应  IntByReference* 3.void *   对应  byte[]/Pointer,回调函数里此类型需用String来对应。* 4.int      对应  int* 5.无参     对应  void* 6.回调函数  对应  根据文档自定义回调函数,实现接口Callback,离线语音合成无回调*///加载dll动态库并实例化,从而使用其内部的方法TtsService INSTANCE = Native.loadLibrary(Constants.TTS_DLL_PATH, TtsService.class);//定义登录方法public Integer MSPLogin(String usr, String pwd, String params);//开始一次普通离线语音合成public String QTTSSessionBegin(String params, IntByReference errorCode);//写入需要合成的文本public Integer QTTSTextPut(String sessionID, String textString, int textLen, String params);//获取离线合成的音频public Pointer QTTSAudioGet(String sessionID, IntByReference audioLen, IntByReference synthStatus, IntByReference errorCode);//结束本次普通离线语音合成public Integer QTTSSessionEnd(String sessionID, String hints);//定义退出方法public Integer MSPLogout();
}

四、唤醒回调

package com.day.service.imp;import com.day.AIMain;
import com.day.ability.IatMic;
import com.day.config.Constants;
import com.sun.jna.Callback;import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;public class IvwCallback implements Callback {public int cb_ivw_msg_proc(String sessionID, int msg, int param1, int param2, String info, String userData) throws Exception {System.out.println("机器人大飞:主人,您请说~");AIMain.startTts("主人,您请说~");// 先录音后调用听写IatMic.iatWork();return 0;}
}

五、听写代码(重点是和唤醒公用一个麦克风音频流)

package com.day.ability;import com.day.AIMain;
import com.day.config.Constants;
import com.day.service.IvwService;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import okhttp3.*;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.sound.sampled.AudioInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;// 麦克风传流听写public class IatMic extends WebSocketListener {private static final String hostUrl = "https://iat-api.xfyun.cn/v2/iat"; //中英文,http url 不支持解析 ws/wss schema// private static final String hostUrl = "https://iat-niche-api.xfyun.cn/v2/iat";//小语种private static final String appid = ""; //在控制台-我的应用获取private static final String apiSecret = ""; //在控制台-我的应用-语音听写(流式版)获取private static final String apiKey = ""; //在控制台-我的应用-语音听写(流式版)获取//private static final String file = "./zMusic/pcm/科大讯飞.pcm"; // 中文public static final int StatusFirstFrame = 0;public static final int StatusContinueFrame = 1;public static final int StatusLastFrame = 2;public static final Gson json = new Gson();Decoder decoder = new Decoder();// 开始时间private static Date dateBegin = new Date();// 结束时间private static Date dateEnd = new Date();private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");static int status = 0;  // 音频的状态public static boolean IAT_FLAG = true;public static String fileName = "";public static void main(String[] args) throws Exception {iatWork();}static class MyThread extends Thread {public void run() {/* // 录制用户说话ByteArrayOutputStream outputStream = new ByteArrayOutputStream();long startTime1 = System.currentTimeMillis();long endTime1 = startTime1 + 500; // 10 secondswhile (System.currentTimeMillis() < endTime1) {System.out.print("");}// Step 4: Start recordingbyte[] buffer = new byte[Constants.IVW_ASR_TARGET_DATA_LINE.getBufferSize() / 5]; // Adjust buffer size as neededint bytesRead;long startTime = System.currentTimeMillis();long endTime = startTime + 4000; // 10 seconds// Step 5: Loop until recording time reaches 10 secondswhile (System.currentTimeMillis() < endTime) {bytesRead = Constants.IVW_ASR_TARGET_DATA_LINE.read(buffer, 0, buffer.length);if (bytesRead > 0) {outputStream.write(buffer, 0, bytesRead);}}byte[] audioBytes = outputStream.toByteArray();// Step 9: Write byte array to audio file or other destination using AudioSystem.write method// Example: Save audioBytes to a WAV filetry {File audioFile = new File("src/main/resources/1.wav");AudioInputStream audioInputStream = new AudioInputStream(new ByteArrayInputStream(audioBytes), Constants.IVW_ASR_AUDIO_FORMAT, audioBytes.length / Constants.IVW_ASR_AUDIO_FORMAT.getFrameSize());AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, audioFile);} catch (IOException e) {e.printStackTrace();}fileName = "src/main/resources/1.wav";*/// 需要初始化的参数都在这里添加IatMic.IAT_FLAG = true;status = 0;// 结束初始化IatMic iatMic = new IatMic();// 构建鉴权urlString authUrl = null;try {authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);} catch (Exception e) {throw new RuntimeException(e);}OkHttpClient client = new OkHttpClient.Builder().build();//将url中的 schema http://和https://分别替换为ws:// 和 wss://String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");// System.err.println(url);Request request = new Request.Builder().url(url).build();WebSocket webSocket = client.newWebSocket(request, iatMic);}}public static void iatWork() throws Exception {// 用线程方式启动,不影响唤醒,里面不要执行任何长时间的代码MyThread myThread = new MyThread();myThread.start();}@Overridepublic void onOpen(WebSocket webSocket, Response response) {// System.out.println("建立连接成功");System.out.println(Constants.YELLOW_BACKGROUND + "机器人正在听,您请说:" + Constants.RESET);super.onOpen(webSocket, response);new Thread(() -> {//连接成功,开始发送数据//  int interval = 200;try {Constants.IVW_ASR_TARGET_DATA_LINE.open(Constants.IVW_ASR_AUDIO_FORMAT);Constants.IVW_ASR_TARGET_DATA_LINE.start();while (true) {// System.err.println(AIMain.len + "" + AIMain.audioDataByteArray);if (AIMain.len == -1) {status = 2;// 标志读取完毕}switch (status) {case StatusFirstFrame:   // 第一帧音频status = 0JsonObject frame = new JsonObject();JsonObject business = new JsonObject();  //第一帧必须发送JsonObject common = new JsonObject();  //第一帧必须发送JsonObject data = new JsonObject();  //每一帧都要发送// 填充commoncommon.addProperty("app_id", appid);//填充businessbusiness.addProperty("language", "zh_cn");////business.addProperty("language", "en_us");//英文//business.addProperty("language", "ja_jp");//日语,在控制台可添加试用或购买//business.addProperty("language", "ko_kr");//韩语,在控制台可添加试用或购买//business.addProperty("language", "ru-ru");//俄语,在控制台可添加试用或购买//business.addProperty("ptt", 1);business.addProperty("domain", "iat");//mandarin中文普通话  广东话cantonesebusiness.addProperty("accent", "mandarin");//中文方言请在控制台添加试用,添加后即展示相应参数值cantonese//mandarin//business.addProperty("nunum", 0);//business.addProperty("ptt", 1);//标点符号//business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文(默认值)zh-hk :繁体香港(若未授权不生效,在控制台可免费开通)business.addProperty("vinfo", 1);business.addProperty("dwa", "wpgs");//动态修正(若未授权不生效,在控制台可免费开通)business.addProperty("vad_eos", 3000);//business.addProperty("fa_nbest", true);//business.addProperty("fa_sch", true);//business.addProperty("vinfo", 1);//business.addProperty("speex_size", 70);//business.addProperty("nbest", 5);// 句子多候选(若未授权不生效,在控制台可免费开通)//business.addProperty("wbest", 3);// 词级多候选(若未授权不生效,在控制台可免费开通)//填充datadata.addProperty("status", StatusFirstFrame);data.addProperty("format", "audio/L16;rate=16000");//data.addProperty("encoding", "speex-wb");data.addProperty("encoding", "raw");data.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(AIMain.audioDataByteArray, AIMain.len)));//填充frameframe.add("common", common);frame.add("business", business);frame.add("data", data);// System.out.println("即将发送第一帧数据...");// System.err.println(frame.toString());webSocket.send(frame.toString());status = StatusContinueFrame;  // 发送完第一帧改变status 为 1break;case StatusContinueFrame:  //中间帧status = 1JsonObject frame1 = new JsonObject();JsonObject data1 = new JsonObject();data1.addProperty("status", StatusContinueFrame);data1.addProperty("format", "audio/L16;rate=16000");//data1.addProperty("encoding", "speex-wb");data1.addProperty("encoding", "raw");String temp = Base64.getEncoder().encodeToString(Arrays.copyOf(AIMain.audioDataByteArray, AIMain.len));data1.addProperty("audio", temp);frame1.add("data", data1);//System.out.println(temp);webSocket.send(frame1.toString());break;}try {Thread.sleep(200);if (!IAT_FLAG) {//System.out.println("本次会话结束");break;}} catch (Exception e) {e.printStackTrace();}}//说明读完了status = StatusLastFrame;JsonObject frame2 = new JsonObject();JsonObject data2 = new JsonObject();data2.addProperty("status", StatusLastFrame);data2.addProperty("audio", "");data2.addProperty("format", "audio/L16;rate=16000");//data2.addProperty("encoding", "speex-wb");data2.addProperty("encoding", "raw");frame2.add("data", data2);webSocket.send(frame2.toString());// System.err.println(frame2.toString());// System.out.println("all data is send");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}).start();}@Overridepublic void onMessage(WebSocket webSocket, String text) {// System.out.println(text);super.onMessage(webSocket, text);ResponseData resp = json.fromJson(text, ResponseData.class);if (resp != null) {if (resp.getCode() != 0) {AIMain.ivwFlag = true; // 如果报错也需要恢复唤醒System.out.println("code=>" + resp.getCode() + " error=>" + resp.getMessage() + " sid=" + resp.getSid());System.out.println("错误码查询链接:https://www.xfyun.cn/document/error-code");return;}if (resp.getData() != null) {if (resp.getData().getResult() != null) {Text te = resp.getData().getResult().getText();//System.out.println(te.toString());try {decoder.decode(te);dateEnd = new Date();// System.out.println("耗时:" + (dateEnd.getTime() - dateBegin.getTime()) + "ms");System.out.println(Constants.YELLOW_BACKGROUND + "用户说话识别中:" + decoder.toString() + Constants.RESET);//System.err.println("中间识别JSON结果 ----" + text);} catch (Exception e) {e.printStackTrace();}}if (resp.getData().getStatus() == 2) {// todo  resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源//System.err.println("我的getStatus() == 2");// System.out.println("session end ");dateEnd = new Date();// System.out.println(sdf.format(dateBegin) + "开始");// System.out.println(sdf.format(dateEnd) + "结束");//  System.out.println("耗时:" + (dateEnd.getTime() - dateBegin.getTime()) + "ms");System.out.println(Constants.YELLOW_BACKGROUND + "用户说话识别最终结果:" + decoder.toString() + Constants.RESET);AIMain.ivwFlag = true; // 恢复唤醒// System.out.println("本次识别sid ==》" + resp.getSid());try {BigModelNew.doSpark(decoder.toString()); // 调用大模型回答问题!!!} catch (Exception e) {throw new RuntimeException(e);}decoder.discard();webSocket.close(1000, "");IatMic.IAT_FLAG = false;// System.exit(0);} else {// todo 根据返回的数据处理}}}}@Overridepublic void onFailure(WebSocket webSocket, Throwable t, Response response) {super.onFailure(webSocket, t, response);try {if (null != response) {int code = response.code();System.out.println("onFailure code:" + code);System.out.println("onFailure body:" + response.body().string());if (101 != code) {System.out.println("connection failed");System.exit(0);}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {URL url = new URL(hostUrl);SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);format.setTimeZone(TimeZone.getTimeZone("GMT"));String date = format.format(new Date());//String date = format.format(new Date());//System.err.println(date);StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//append("date: ").append(date).append("\n").//append("GET ").append(url.getPath()).append(" HTTP/1.1");//System.err.println(builder);Charset charset = Charset.forName("UTF-8");Mac mac = Mac.getInstance("hmacsha256");SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");mac.init(spec);byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));String sha = Base64.getEncoder().encodeToString(hexDigits);//System.err.println(sha);String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);//System.err.println(authorization);HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//addQueryParameter("date", date).//addQueryParameter("host", url.getHost()).//build();return httpUrl.toString();}public static class ResponseData {private int code;private String message;private String sid;private Data data;public int getCode() {return code;}public String getMessage() {return this.message;}public String getSid() {return sid;}public Data getData() {return data;}}public static class Data {private int status;private Result result;public int getStatus() {return status;}public Result getResult() {return result;}}public static class Result {int bg;int ed;String pgs;int[] rg;int sn;Ws[] ws;boolean ls;JsonObject vad;public Text getText() {Text text = new Text();StringBuilder sb = new StringBuilder();for (Ws ws : this.ws) {sb.append(ws.cw[0].w);}text.sn = this.sn;text.text = sb.toString();text.sn = this.sn;text.rg = this.rg;text.pgs = this.pgs;text.bg = this.bg;text.ed = this.ed;text.ls = this.ls;text.vad = this.vad == null ? null : this.vad;return text;}}public static class Ws {Cw[] cw;int bg;int ed;}public static class Cw {int sc;String w;}public static class Text {int sn;int bg;int ed;String text;String pgs;int[] rg;boolean deleted;boolean ls;JsonObject vad;@Overridepublic String toString() {return "Text{" + "bg=" + bg + ", ed=" + ed + ", ls=" + ls + ", sn=" + sn + ", text='" + text + '\'' + ", pgs=" + pgs + ", rg=" + Arrays.toString(rg) + ", deleted=" + deleted + ", vad=" + (vad == null ? "null" : vad.getAsJsonArray("ws").toString()) + '}';}}//解析返回数据,仅供参考public static class Decoder {private Text[] texts;private int defc = 10;public Decoder() {this.texts = new Text[this.defc];}public synchronized void decode(Text text) {if (text.sn >= this.defc) {this.resize();}if ("rpl".equals(text.pgs)) {for (int i = text.rg[0]; i <= text.rg[1]; i++) {this.texts[i].deleted = true;}}this.texts[text.sn] = text;}public String toString() {StringBuilder sb = new StringBuilder();for (Text t : this.texts) {if (t != null && !t.deleted) {sb.append(t.text);}}return sb.toString();}public void resize() {int oc = this.defc;this.defc <<= 1;Text[] old = this.texts;this.texts = new Text[this.defc];for (int i = 0; i < oc; i++) {this.texts[i] = old[i];}}public void discard() {for (int i = 0; i < this.texts.length; i++) {this.texts[i] = null;}}}
}

六、大模型调用代码

package com.day.ability;import com.day.AIMain;
import com.day.util.MyUtil;
import com.google.gson.Gson;
import okhttp3.HttpUrl;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;// 主函数入口
public class BigModelNew {public static final String hostUrl = "https://spark-api.xf-yun.com/v3/completions";private static final String appid = "";private static final String apiSecret = "";private static final String apiKey = "";private static final Gson gson = new Gson();public static void main(String[] args) throws Exception {doSpark("我想吃鸡。");}public static void doSpark(String content) throws Exception {MyThread myThread = new MyThread(content);myThread.start();}static class MyThread extends Thread {String content;public MyThread(String content) {this.content = content;}public void run() {String authUrl = null;try {authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);} catch (Exception e) {throw new RuntimeException(e);}// URL地址正确// System.err.println(authUrl);String json = "{\n" + "  \"app_id\": \"" + appid + "\",\n" + "  \"uid\": \"" + UUID.randomUUID().toString().substring(0, 10) + "\",\n" + "  \"domain\": \"generalv2\",\n" + "  \"temperature\": 0.5,\n" + "  \"max_tokens\": 4096,\n" + "  \"auditing\": \"default\",\n" + "  \"stream\": true,\n" + "  \"messages\": [\n" + "    {\n" + "      \"role\": \"user\",\n" + "     \"content\": \"" + content + "\"\n" + "    }\n" + "  ]\n" + "}";// 发起Post请求String res = MyUtil.doPostJson(authUrl, null, json);String finalRes = "";String[] resArray = res.split("\n");for (int i = 0; i < resArray.length; i++) {if (resArray[i].contains("data:")) {String jsonStr = resArray[i].replace("data:", "");BigJsonParse bigJsonParse = gson.fromJson(jsonStr, BigJsonParse.class);List<Choices> choicesList = bigJsonParse.choices;if (choicesList != null && choicesList.size() > 0) {for (Choices choice : choicesList) {finalRes = finalRes + choice.content;}} else {finalRes = "您好,我是讯飞星火认知大模型";}}}System.out.println(finalRes);String temp = finalRes.replaceAll("\r\n", "").replaceAll("\n", "");System.out.println("*****************************************************************************************************");AIMain.startTts(temp);}}// 鉴权方法public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {URL url = new URL(hostUrl);// 时间SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);format.setTimeZone(TimeZone.getTimeZone("GMT"));String date = format.format(new Date());// date="Thu, 12 Oct 2023 03:05:28 GMT";// 拼接String preStr = "host: " + url.getHost() + "\n" + "date: " + date + "\n" + "POST " + url.getPath() + " HTTP/1.1";// System.err.println(preStr);// SHA256加密Mac mac = Mac.getInstance("hmacsha256");SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");mac.init(spec);byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));// Base64加密String sha = Base64.getEncoder().encodeToString(hexDigits);// System.err.println(sha);// 拼接String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);// 拼接地址HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//addQueryParameter("date", date).//addQueryParameter("host", url.getHost()).//build();// System.err.println(httpUrl.toString());return httpUrl.toString();}
}// JSON
class BigJsonParse {List<Choices> choices;
}class Choices {String content;
}

七、HTTP PSOT请求代码

package com.day.util;import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;public class MyUtil {/*** 1.发起post请求*/public static String doPostJson(String url, Map<String, String> urlParams, String json) {CloseableHttpClient closeableHttpClient = HttpClients.createDefault();CloseableHttpResponse closeableHttpResponse = null;String resultString = "";try {// 创建Http Post请求String asciiUrl = URI.create(url).toASCIIString();RequestBuilder builder = RequestBuilder.post(asciiUrl);builder.setCharset(StandardCharsets.UTF_8);if (urlParams != null) {for (Map.Entry<String, String> entry : urlParams.entrySet()) {builder.addParameter(entry.getKey(), entry.getValue());}}// 创建请求内容StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);builder.setEntity(entity);HttpUriRequest request = builder.build();// 执行http请求closeableHttpResponse = closeableHttpClient.execute(request);resultString = EntityUtils.toString(closeableHttpResponse.getEntity(), StandardCharsets.UTF_8);} catch (Exception e) {e.printStackTrace();} finally {try {if (closeableHttpResponse != null) {closeableHttpResponse.close();}if (closeableHttpClient != null) {closeableHttpClient.close();}} catch (Exception e) {e.printStackTrace();}}return resultString;}
}

八、整体项目结构目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/579617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为ipv6配置之ospf案例

R1 ipv6 ospfv3 1 router-id 1.1.1.1 //必须要手动配置ospf id&#xff0c;它不会自动生成 interface GigabitEthernet0/0/0 ipv6 enable ipv6 address 2000::2/96 ospfv3 1 area 0.0.0.0 interface LoopBack0 ipv6 enable ipv6 address 2001::1/96 ospfv3 1 area 0.0.0.0 R2…

创新科技赋能,易点易动设备管理系统助力企业实现设备管理升级

在当今竞争激烈的商业环境中&#xff0c;企业对设备管理的要求越来越高。高效的设备管理不仅可以提高生产效率&#xff0c;降低成本&#xff0c;还可以确保设备安全和可靠性。然而&#xff0c;传统的手工管理方式已经无法满足企业快速发展的需求。为了解决这一问题&#xff0c;…

electron autoUpdater自动更新使用示例 客户端+服务端

封装好的 update.js 模块 use strict; const { autoUpdater } require(electron) // 更新检测 // https://www.electronjs.org/zh/docs/latest/api/auto-updaterconst checkUpdate (serverUrl) >{const updateUrl ${serverUrl}/update?platform${process.platform}&am…

论文阅读——TÜLU

How Far Can Camels Go? Exploring the State of Instruction Tuning on Open Resources 统一输入格式&#xff1a;将所有数据集格式化为遵循聊天机器人风格的模式&#xff0c;以统一指令数据集的各种风格和格式。用户输入和目标话语之前特殊token&#xff1a;&#xff0c;助手…

Xcode 编译速度慢是什么原因?如何提高编译速度?

作为一个开发者&#xff0c;我们都希望能够高效地开发应用程序&#xff0c;而编译速度是影响开发效率的重要因素之一。然而&#xff0c;有时候我们会发现在使用 Xcode 进行开发时&#xff0c;译速度非常慢&#xff0c;这给我们带来了不少困扰。那么&#xff0c;为什么 Xcode 的…

Android apk安装包反编译——apktool工具

apk 文件结构 首先是 apk&#xff0c;即安卓程序的安装包。Apk 是一种类似于 Symbian Sis 或 Sisx 的文件格式。通过将 APK 文件直接传到 Android 模拟器或 Android 手机中执行即可安装。 而 apk 文件实际上就是一个 MIME 为 ZIP 的压缩包&#xff0c;只不过后缀名进行了更改。…

线上3DVR展厅拉近客户距离,提升谈单转化效率

随着互联网的普及和数字化技术的发展&#xff0c;越来越多的企业开始利用3D虚拟展厅来展示自己的产品和服务。虚拟展厅作为一种新型的展示方式&#xff0c;能够迅速拉近客户与企业的距离&#xff0c;提高客户的信任感&#xff0c;从而促进订单的达成。 720云3D空间漫游 在传统…

【HBase】——简介

1 HBase 定义 Apache HBase™ 是以 hdfs 为数据存储的&#xff0c;一种分布式、可扩展的 NoSQL 数据库。 2 HBase 数据模型 • HBase 的设计理念依据 Google 的 BigTable 论文&#xff0c;论文中对于数据模型的首句介绍。 Bigtable 是一个稀疏的、分布式的、持久的多维排序 m…

分布式下如何实现统一日志系统?

在业务系统开发中&#xff0c;日志的收集和分析很重要&#xff0c;特别是在进行故障分析时&#xff0c;日志记录得好&#xff0c;可以帮我们快速定位问题原因。在互联网分布式系统下&#xff0c;日志变得越来越分散&#xff0c;数据规模也越来越大&#xff0c;如何更好地收集和…

初见 Amazon Q

前言 如果今年要写一篇年终总结的话&#xff0c;生成式 Ai 一定是绕不过的一个话题&#xff0c;自从去年的 chatGPT 火爆全球后&#xff0c;今年各种生成式 Ai 的产品络绎不绝地出现大众视线&#xff0c;版本迭代的速度也是非常快&#xff0c;大家甚至开始在自己的生活和工作中…

亿赛通电子文档安全管理系统 dump任意文件读取漏洞(CNVD-2023-09184)

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

开集目标检测-标签提示目标检测大模型(吊打YOLO系列-自动化检测标注)

背景 大多数现有的对象检测模型都经过训练来识别一组有限的预先确定的类别。将新类添加到可识别对象列表中需要收集和标记新数据&#xff0c;并从头开始重新训练模型&#xff0c;这是一个耗时且昂贵的过程。该大模型的目标是开发一个强大的系统来检测由人类语言输入指定的任意…

十一.MyBatis的缓存

11.1缓存介绍 为什么使用缓存&#xff1f; 使用缓存的主要原因是为了提高应用程序的性能和响应速度。缓存可以存储经常访问的数据或计算结果&#xff0c;从而避免重复进行相同的计算或查询数据库等耗时的操作。通过使用缓存&#xff0c;你可以减少对原始数据源的访问次数&…

2022年山东省职业院校技能大赛高职组云计算赛项试卷第二场-容器云

2022年山东省职业院校技能大赛高职组云计算赛项试卷 目录 【赛程名称】云计算赛项第二场-容器云 需要竞赛软件包以及资料可以私信博主&#xff01; 【赛程名称】云计算赛项第二场-容器云 【赛程时间】2022-11-27 09:00:00至2022-11-27 16:00:00 说明&#xff1a;完成本任务…

【流复制环境PostgreSQL-14.1到PostgreSQL-16.1大版本升级】

PostgreSQL大版本会定期添加新特性&#xff0c;这些新特性通常会改变系统表的布局&#xff0c;但内部数据存储格式很少改变。pg_upgrade通过创建新的系统表和重用旧的用户数据文件来执行快速升级。 pg_upgrade升级主要有三种用法&#xff1a; 1、使用pg_upgrade拷贝升级。 2、…

【工具】windeployqt 在windows + vscode环境下打包

目录 0.背景简介 1.windeployqt简介 2.打包具体过程 1&#xff09;用vscode编译&#xff0c;生成Release文件夹&#xff08;也有Debug文件夹&#xff0c;但是发布版本一般都是用Release&#xff09; 2&#xff09;此时可以看下Release文件夹内&#xff0c;一般是.exe可执行…

【学习笔记】Java函数式编程03 Stream流-终结操作

书接上回 3.3.3 终结操作 3.3.3.1 forEach 对集合的每一个元素进行处理 接触很多了不赘述 3.3.3.2 count 用来获取当前流中的元素的个数 比如&#xff0c;打印出所有作家的作品的总数 System.out.println(authors.stream().flatMap(author -> author.getBooks().stre…

文献研读|Prompt窃取与保护综述

本文介绍与「Prompt窃取与保护」相关的几篇工作。 目录 1. Prompt Stealing Attacks Against Text-to-Image Generation Models&#xff08;PromptStealer&#xff09;2. Hard Prompts Made Easy: Gradient-Based Discrete Optimization for Prompt Tuning and Discovery&#…

汽车零配件装配产线中使用RFID技术和不使用RFID技术的优缺点

汽车零配件装配产线中使用RFID技术和不使用RFID技术的优缺点 RFID(射频识别技术)是非接触式自动识别技术&#xff0c;经常被使用于工业制造、物流管理、仓储物品盘点等领域。我们聊一聊在汽车零配件装配产线中使用和不使用RFID技术的优缺点 在汽车零配件装配线使用RFID技术可以…

.NetCore NPOI 读取excel内容及单元格内图片

由于数据方提供的数据在excel文件中不止有文字内容还包含图片信息&#xff0c;于是编写相关测试代码&#xff0c;读取excel文件内容及图片信息. 本文使用的是 NPOI-2.6.2 版本&#xff0c;此版本持.Net4.7.2;.NetStandard2.0;.NetStandard2.1;.Net6.0。 测试文档内容&#xf…