package com.smartor.common;
|
|
;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import lombok.extern.slf4j.Slf4j;
|
import okhttp3.*;
|
import org.apache.commons.lang3.StringUtils;
|
|
import java.io.IOException;
|
import java.util.*;
|
|
@Slf4j
|
public class DeepSeekApi {
|
// 替换为你自己的key
|
private static final String API_KEY = "sk-4e489637e105411596be6c72e2dacdbd";
|
private static final String API_URL = "https://api.deepseek.com/v1/chat/completions";
|
|
public static void main(String[] args) {
|
String questionText = "您好,请问您是患者本人还是家属?\n";
|
String voiceText = "我自己";
|
// List<String> options = new ArrayList<>(Arrays.asList("本人","亲属","其他"));
|
String optionText = "亲属";
|
Integer resp = matchQuestionAnswer(questionText, voiceText, optionText);
|
System.out.println("DeepSeek返回结果:\n" + resp);
|
}
|
|
public static String chatCompletion(String systemPrompt, String userPrompt) {
|
OkHttpClient client = new OkHttpClient();
|
|
// 1. 组装消息体
|
List<Map<String, String>> messages = new ArrayList<>();
|
// 系统角色(可选,用于设定AI身份)
|
Map<String, String> sysMsg = new HashMap<>();
|
sysMsg.put("role", "system");
|
sysMsg.put("content", systemPrompt);
|
messages.add(sysMsg);
|
// 用户提问
|
Map<String, String> userMsg = new HashMap<>();
|
userMsg.put("role", "user");
|
userMsg.put("content", userPrompt);
|
messages.add(userMsg);
|
|
// 2. 请求参数
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("model", "deepseek-chat");
|
requestBody.put("messages", messages);
|
requestBody.put("temperature", 0.7); // 随机性0~1,越低越严谨
|
requestBody.put("max_tokens", 1024);
|
|
// 3. 构建请求
|
String jsonBody = JSON.toJSONString(requestBody);
|
RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonBody);
|
|
Request request = new Request.Builder()
|
.url(API_URL)
|
.header("Authorization", "Bearer " + API_KEY)
|
.header("Content-Type", "application/json")
|
.post(body)
|
.build();
|
|
// 4. 发送请求
|
try (Response response = client.newCall(request).execute()) {
|
if (!response.isSuccessful()) {
|
return "请求失败,状态码:" + response.code() + ",错误信息:" + response.body().string();
|
}
|
String resJson = response.body().string();
|
JSONObject jsonObj = JSON.parseObject(resJson);
|
// 提取AI回答内容
|
return jsonObj.getJSONArray("choices")
|
.getJSONObject(0)
|
.getJSONObject("message")
|
.getString("content");
|
} catch (IOException e) {
|
e.printStackTrace();
|
return "接口调用异常:" + e.getMessage();
|
}
|
}
|
|
/**
|
* 判断语音文本最接近哪个选项,返回选项在列表中的下标。
|
*
|
* @param voiceText 语音识别得到的文本
|
* @param options 候选选项列表
|
* @return 命中选项的下标(从 0 开始);无法匹配任一选项时返回 {@code -1}
|
*/
|
public static int matchOptionIndex(String questionText, String voiceText, List<String> options) {
|
if (StringUtils.isBlank(voiceText) || options == null || options.isEmpty()) {
|
return -1;
|
}
|
// 只有一个选项时无需调用模型
|
if (options.size() == 1) {
|
return 0;
|
}
|
|
StringBuilder optionText = new StringBuilder();
|
for (int i = 0; i < options.size(); i++) {
|
optionText.append(i + 1).append(". ").append(options.get(i)).append('\n');
|
}
|
|
String systemPrompt = "\"你是一个专业的语音识别文本语义匹配助手。你的任务是判断用户的语音文本在语义上最符合的选项。用户会给出一段语音识别文本和若干个带编号的选项,"
|
+ "请判断这段文本在语义上最接近哪一个选项。只允许从给定选项中选择,"
|
+ "不要做任何解释。直接输出最匹配选项的编号数字;若没有任何选项与文本相关,则输出 0。";
|
String userPrompt = "请根据以下信息进行语义匹配判断:\n" +
|
"- 问题文本:" + questionText + "\n\n"
|
+ "- 语音识别文本:" + voiceText + "\n\n"
|
+ "- 选项:\n" + optionText
|
+ "\n请只输出一个数字(最匹配选项的编号,没有匹配则输出 0)。";
|
|
String content = chatCompletion(systemPrompt, userPrompt);
|
if (StringUtils.isBlank(content)) {
|
return -1;
|
}
|
|
Integer number = extractFirstNumber(content);
|
if (number == null || number <= 0 || number > options.size()) {
|
log.warn("DeepSeek 选项匹配未命中,voiceText={}, options={}, modelReturn={}", voiceText, options, content);
|
return -1;
|
}
|
return number - 1;
|
}
|
|
/**
|
* 判断语音文本最接近哪个选项,返回选项在列表中的下标。
|
*
|
* @param questionText 语音识别得到的文本
|
* @param answerText 答案文本
|
* @param optionText 选项文本
|
* @return 命中选项的下标(从 0 开始);无法匹配任一选项时返回 {@code -1}
|
*/
|
public static int matchQuestionAnswer(String questionText, String answerText, String optionText) {
|
if (StringUtils.isBlank(questionText) || StringUtils.isBlank(answerText) || StringUtils.isBlank(optionText)) {
|
return -1;
|
}
|
|
String systemPrompt = "\"你是一个专业的语音识别文本语义匹配助手。你的任务是判断用户的语音文本在语义上最符合的选项。用户会给出一段语音识别文本和选项文本,"
|
+ "请判断这段文本在语义上是否匹配选项, 匹配则输出 1,没有匹配则输出 0, 只允许输出1或者0,"
|
+ "不要做任何解释。直接输出最匹配选项的编号数字;若没有任何选项与文本相关,则输出 0。";
|
String userPrompt = "请根据以下信息进行语义匹配判断:\n" +
|
"- 问题文本:" + questionText + "\n\n"
|
+ "- 语言识别文本:" + answerText + "\n\n"
|
+ "- 选项文本:" + optionText + "\n\n"
|
+ "\n请只输出一个数字(匹配则输出 1,没有匹配则输出 0,只允许输出1或者0)。";
|
|
String content = chatCompletion(systemPrompt, userPrompt);
|
if (StringUtils.isBlank(content)) {
|
return -1;
|
}
|
return extractFirstNumber(content);
|
}
|
|
/**
|
* 从模型回复中提取第一个整数。模型偶尔会回复 “选项2” “2。” 之类,做一次兜底解析。
|
*/
|
private static Integer extractFirstNumber(String text) {
|
List<Character> digits = new ArrayList<>();
|
for (int i = 0; i < text.length(); i++) {
|
char c = text.charAt(i);
|
if (c >= '0' && c <= '9') {
|
digits.add(c);
|
} else if (!digits.isEmpty()) {
|
break;
|
}
|
}
|
if (digits.isEmpty()) {
|
return null;
|
}
|
StringBuilder sb = new StringBuilder();
|
for (char c : digits) {
|
sb.append(c);
|
}
|
try {
|
return Integer.parseInt(sb.toString());
|
} catch (NumberFormatException e) {
|
return null;
|
}
|
}
|
}
|