陈昶聿
4 天以前 50879bb28a51ae8c21cd00d273d106431e1d2c8f
smartor/src/main/java/com/smartor/common/QwenLLMUtil.java
@@ -33,15 +33,15 @@
    /** 百炼 API Key */
    @Value("${qwen.api-key:}")
    private String apiKey;
    private static String apiKey = "sk-712da9346f0940ff909b40dce17579b1";
    /** 模型名称 */
    @Value("${qwen.model:qwen-plus}")
    private String model;
    private static String model = "qwen-plus";
    /** 接口地址(OpenAI 兼容模式) */
    @Value("${qwen.url:https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions}")
    private String url;
    private static String url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
    /**
     * 判断语音文本最接近哪个选项。
@@ -97,21 +97,28 @@
    /**
     * 判断语音文本是否符合这个意思
     *
     * @param questionText
     * @param voiceText 语音识别得到的文本
     * @return 命中的选项原文;无法匹配任一选项时返回 {@code null}
     */
    public int matchRegex(String voiceText, String value, String regexText) {
    public static int matchRegex(String questionText, String voiceText, String value, String regexText) {
        if (StringUtils.isBlank(voiceText) || regexText == null || regexText.isEmpty()) {
            return -1;
        }
        String systemPrompt = "你是一个语义匹配助手。用户会给出一段语音识别文本、正则匹配文本、对应指标值"
                + "请判断这段文本是否接近正则匹配规则或者对应指标值的意思"
                + "不要做任何解释。若有相关意思,能匹配的上,直接输出 1;若与文本意思完全不相关,则输出 0。";
        String userPrompt = "语音文本:" + voiceText + "\n\n正则匹配文本:\n" + regexText
                +  "\n\n对应指标值:\n" + value
                + "\n请只输出一个数字(匹配输出 1,没有匹配则输出 0)。";
        String systemPrompt = "你是一个专业的语音识别文本语义匹配助手。你的任务是判断用户的语音文本是否在语义上符合给定的<正则匹配规则>或<对应指标值>。"
                + "由于正则表达式无法覆盖所有自然语言的同义表达,你需要作为语义兜底机制,判断语音文本是否表达了与正则规则或指标值相同或相近的核心意图。"
                + "【核心规则】"
                + "1. 如果语音文本在字面上匹配了正则,或者在语义上表达了正则/指标值的意思,请输出:1。"
                + "2. 如果语音文本与正则/指标值的意思完全无关、意思相反或无法推断出相关意图,请输出:0。"
                + "3. 绝对禁止输出任何解释、标点符号、换行符或其他无关字符。你的最终回复只能是一个数字(1 或 0)。"
                ;
        String userPrompt = "请根据以下信息进行语义匹配判断:\n" +
                "- 问题文本:" + questionText + "\n\n"
                + "- 语音识别文本:" + voiceText + "\n\n"
                + "- 正则匹配文本:\n" + regexText + "\n\n"
                + "- 对应指标值:\n" + value
                + "\n请判断这段语音文本是否接近正则匹配规则或者对应指标值的意思。若有相关意思、能匹配得上,直接输出 1;若与文本意思完全不相关,则输出 0。";
        String content = chat(systemPrompt, userPrompt);
        if (StringUtils.isBlank(content)) {
@@ -133,7 +140,7 @@
     * @param userPrompt   用户提示词
     * @return 模型回复正文;调用失败返回 {@code null}
     */
    public String chat(String systemPrompt, String userPrompt) {
    public static String chat(String systemPrompt, String userPrompt) {
        if (StringUtils.isBlank(apiKey)) {
            throw new IllegalStateException("通义千问 API Key 未配置(qwen.api-key)");
        }
@@ -178,7 +185,7 @@
        }
    }
    private JSONObject message(String role, String content) {
    private static JSONObject message(String role, String content) {
        JSONObject msg = new JSONObject();
        msg.put("role", role);
        msg.put("content", content);
@@ -188,7 +195,7 @@
    /**
     * 从模型回复中提取第一个整数。模型偶尔会回复 “选项2” “2。” 之类,做一次兜底解析。
     */
    private Integer extractFirstNumber(String text) {
    private static Integer extractFirstNumber(String text) {
        List<Character> digits = new ArrayList<>();
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);