Administrator
2025-09-05 14bff9c21f86ebced8436fa0d92ed20a1f8384aa
feat(ai): 添加 AI 生产题目功能

- 新增 AiProductQuestionAiDto 类作为 AI 生产题目的请求参数
- 在 AiProductQuestionController 中添加 aiCreate 方法处理 AI 生产题目请求
- 在 AiProductQuestionService 接口中定义 aiCreate 方法
- 实现 AiProductQuestionServiceImpl 中的 aiCreate 方法
- 新增 AiService 接口和 AiServiceImpl 实现类,用于调用 AI 模型生成题目
3 files modified
3 files added
118 ■■■■■ changed files
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/req/AiProductQuestionAiDto.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiService.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java 72 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java
@@ -2,6 +2,7 @@
import cc.mrbird.febs.ai.entity.AiProductPoint;
import cc.mrbird.febs.ai.entity.AiProductQuestion;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.ai.service.AiProductQuestionService;
import cc.mrbird.febs.common.annotation.ControllerEndpoint;
import cc.mrbird.febs.common.controller.BaseController;
@@ -68,6 +69,13 @@
        return aiProductQuestionService.delete(id);
    }
    @PostMapping("aiCreate/{id}")
    @ControllerEndpoint(operation = "AI生成题目", exceptionMessage = "操作失败")
    public FebsResponse aiCreate(@RequestBody @Valid AiProductQuestionAiDto dto) {
        return aiProductQuestionService.aiCreate(dto);
    }
    @GetMapping(value = "/questionTree")
    public FebsResponse questionTree() {
src/main/java/cc/mrbird/febs/ai/req/AiProductQuestionAiDto.java
New file
@@ -0,0 +1,18 @@
package cc.mrbird.febs.ai.req;
import lombok.Data;
@Data
public class AiProductQuestionAiDto {
    private String productCategoryId;
    private String query;
    private String promptAiSystem;
    private String jsonFormat;
    private Integer questionCnt;
}
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java
@@ -2,6 +2,7 @@
import cc.mrbird.febs.ai.entity.AiProductQuestion;
import cc.mrbird.febs.ai.entity.AiProductRole;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -37,4 +38,6 @@
    List<AiProductQuestion> questionTree();
    List<AiProductQuestion> productQuestionTree(LambdaQueryWrapper<AiProductQuestion> aiProductQuestionLambdaQueryWrapper);
    FebsResponse aiCreate(AiProductQuestionAiDto dto);
}
src/main/java/cc/mrbird/febs/ai/service/AiService.java
New file
@@ -0,0 +1,8 @@
package cc.mrbird.febs.ai.service;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
public interface AiService {
    String llmInvokeNonStreaming(AiProductQuestionAiDto dto);
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java
@@ -2,8 +2,10 @@
import cc.mrbird.febs.ai.entity.*;
import cc.mrbird.febs.ai.mapper.AiProductQuestionMapper;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.ai.service.AiProductQuestionItemService;
import cc.mrbird.febs.ai.service.AiProductQuestionService;
import cc.mrbird.febs.ai.service.AiService;
import cc.mrbird.febs.ai.util.UUID;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
@@ -35,6 +37,7 @@
    private final AiProductQuestionMapper aiProductQuestionMapper;
    private final AiProductQuestionItemService aiProductQuestionItemService;
    private final AiService aiService;
    @Override
    public AiProductQuestion getById(String id) {
@@ -162,4 +165,10 @@
        return aiProductQuestionMapper.selectList(aiProductQuestionLambdaQueryWrapper);
    }
    @Override
    public FebsResponse aiCreate(AiProductQuestionAiDto dto) {
        String questionAndAnswerStr = aiService.llmInvokeNonStreaming(dto);
        return null;
    }
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiServiceImpl.java
New file
@@ -0,0 +1,72 @@
package cc.mrbird.febs.ai.service.impl;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.ai.service.AiService;
import cc.mrbird.febs.common.exception.FebsException;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Slf4j
@Service
@RequiredArgsConstructor
public class AiServiceImpl implements AiService {
    private static final String apiKey = "sk-babdcf8799144134915cee2683794b2f";
    private static final String appId = "963b854d994a4f578d8207cd477a2464";
    private final String bizParam_1 = "question";
    private final String bizParam_2 = "prompt_ai_system";
    private final String bizParam_3 = "json_format";
    @Override
    public String llmInvokeNonStreaming(AiProductQuestionAiDto dto) {
        if (ObjectUtil.isNull(dto)){
            throw new FebsException("百炼工作流初始化异常");
        }
        HashMap<String, Object> bizParams = new HashMap<>();
        bizParams.put(bizParam_1,dto.getQuestionCnt());
        bizParams.put(bizParam_2,dto.getPromptAiSystem());
        bizParams.put(bizParam_3,dto.getJsonFormat());
        String query = dto.getQuery();
        long startTime = System.currentTimeMillis();
//        ApplicationParam param = ApplicationParam.builder()
//                // 若没有配置环境变量,可用百炼API Key将下行替换为:.apiKey("sk-xxx")。但不建议在生产环境中直接将API Key硬编码到代码中,以减少API Key泄露风险。
//                .apiKey(apiKey)
//                .appId(appId) //替换为实际的应用 ID
//                .flowStreamMode(FlowStreamMode.MESSAGE_FORMAT)
//                .prompt(query)
//                .bizParams(JsonUtils.toJsonObject( bizParams))
//                .build();
//
//        Application application = new Application();
//        Flowable<ApplicationResult> result;
//        try {
//            result = application.streamCall(param);
//        } catch (NoApiKeyException | InputRequiredException e) {
//            throw new FebsException(StrUtil.format("百炼工作流输出失败:{}",e.getMessage()));
//        }
//
//        return Flux.from(result)
//                .map(message -> {
//                    HashMap<String, String> stringStringHashMap = new HashMap<>();
//                    if (!message.getOutput().getFinishReason().equals("stop")){
//                        stringStringHashMap.put(LlmStrategyContextEnum.CONTENT.name(),message.getOutput().getWorkflowMessage().getMessage().getContent());
//                    }
//                    return new FebsResponse().success().data(stringStringHashMap);
//                })
//                .doOnComplete(() -> {
//                    long endTime = System.currentTimeMillis();
//                    System.out.println("百炼工作流输出:" + (endTime - startTime) + "毫秒");
//                })
//                .doOnError(error -> {
//                    throw new FebsException(StrUtil.format("百炼工作流输出失败:{}",error));
//                });
        return null;
    }
}