liusheng
4 天以前 0bbbd746e8c39d91ad7b47a4e36e29ab972dc98c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.ruoyi.common.core.service;
 
import java.util.List;
 
/**
 * 「AI 选项匹配」的对外契约。
 *
 * <h3>它是什么</h3>
 * 原 {@code IServiceSubtaskService#matchOptionIndex}(smartor):
 * 把「用户问题 + 语音识别结果 + 候选选项」序列化成 JSON,<b>POST 到一个外部 AI 服务</b>,
 * 把返回的数字解析为命中的选项下标(解析失败或 url 为空返回 {@code -1})。
 *
 * <h3>为什么要下沉成契约</h3>
 * 模板模块的 {@code IvrLibaTargetServiceImpl} 需要调它,但它是 smartor 的方法。
 * 模板模块**绝不能依赖 smartor**(smartor 已依赖模板模块 → 会成环,Maven 直接构建失败)。
 * 所以按既有手法({@link VisitTaskCreateApi} / {@link ServiceTaskMatchApi} 等):
 * 接口放 ruoyi-common,smartor 侧提供过渡实现。
 *
 * <h3>⚠️ 入参为什么用<b>泛型</b> {@code List<T>} 而不是模板实体</h3>
 * 原方法签名是 {@code List<IvrTaskTemplateTargetoption>},而那个类型已搬进
 * {@code ruoyi-template}。若契约直接写具体类型,ruoyi-common 就得依赖 ruoyi-template ——
 * 方向不对。
 * <p>
 * 也不能简单写成 {@code List<Object>}:调用方拿到返回值后要
 * {@code options.get(matched).getOptiondesc()} —— 参数若是 {@code List<Object>},
 * {@code get()} 返回 {@code Object},那行就编译不过。用泛型 {@code <T>} 可以让
 * 调用点的类型保持原样,而 ruoyi-common 无需知道 {@code T} 是什么。
 * <p>
 * 语义上也安全:原方法对 options **只做一件事 —— {@code jsonObject.put("options", options)}**
 * 然后整体序列化,从不读它的字段,所以 {@code T} 具体是什么都不影响结果。
 *
 * <h3>实现方必须保持的行为</h3>
 * <ul>
 *   <li>{@code url} 为空 → 不发请求,返回 {@code -1};</li>
 *   <li>请求抛异常 → 打日志后返回 {@code -1}(<b>吞异常</b>,原实现如此);</li>
 *   <li>响应非纯整数(允许前导负号)→ 返回 {@code -1}。</li>
 * </ul>
 */
public interface SubtaskOptionMatchApi {
 
    /**
     * 调外部 AI 服务做选项匹配。
     *
     * @param url          AI 服务地址(原 {@code ivrTaskTemplate.url});为空则直接返回 -1
     * @param questionText 用户问题
     * @param voiceText    语音识别结果
     * @param options      候选选项(原为 {@code List<IvrTaskTemplateTargetoption>});
     *                     仅用于 JSON 序列化,故用泛型承载
     * @param uuid         本次会话 uuid
     * @param <T>          选项元素类型(调用方决定,实现方不需要知道)
     * @return 命中的下标;无法匹配返回 {@code -1}
     */
    <T> Integer matchOptionIndex(String url, String questionText, String voiceText,
                                 List<T> options, String uuid);
}