From 1f7c85d6c632f50fd145bd8517933bd55202aef1 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 01 Sep 2025 16:18:34 +0800
Subject: [PATCH] feat(ai): 集成火山和阿里大模型

---
 src/main/java/cc/mrbird/febs/ai/controller/TestController.java |  208 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 204 insertions(+), 4 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/ai/controller/TestController.java b/src/main/java/cc/mrbird/febs/ai/controller/TestController.java
index a019a22..7d7f0fe 100644
--- a/src/main/java/cc/mrbird/febs/ai/controller/TestController.java
+++ b/src/main/java/cc/mrbird/febs/ai/controller/TestController.java
@@ -2,8 +2,11 @@
 
 import cc.mrbird.febs.ai.entity.AiMember;
 import cc.mrbird.febs.ai.mapper.AiMemberMapper;
-import cc.mrbird.febs.ai.req.product.ApiProductInfoDto;
-import cc.mrbird.febs.ai.res.product.ApiProductInfoVo;
+import cc.mrbird.febs.ai.req.talk.AiTalkAnswerStream;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVo;
+import cc.mrbird.febs.ai.strategy.LlmStrategyEnum;
+import cc.mrbird.febs.ai.strategy.LlmStrategyFactory;
+import cc.mrbird.febs.ai.strategy.param.LlmStrategyDto;
 import cc.mrbird.febs.ai.utils.UUID;
 import cc.mrbird.febs.common.entity.FebsResponse;
 import cc.mrbird.febs.common.utils.AppContants;
@@ -15,8 +18,11 @@
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.asymmetric.KeyType;
 import cn.hutool.crypto.asymmetric.RSA;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import io.reactivex.Flowable;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
@@ -26,8 +32,17 @@
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.alibaba.dashscope.aigc.generation.Generation;
+import com.alibaba.dashscope.aigc.generation.GenerationParam;
+import com.alibaba.dashscope.aigc.generation.GenerationResult;
+import com.alibaba.dashscope.common.Message;
+import com.alibaba.dashscope.common.Role;
+import com.alibaba.dashscope.exception.ApiException;
+import com.alibaba.dashscope.exception.InputRequiredException;
+import com.alibaba.dashscope.exception.NoApiKeyException;
+import reactor.core.publisher.Flux;
+
+import java.util.*;
 
 /**
  * @author Administrator
@@ -43,6 +58,7 @@
     private final MallMemberMapper mallMemberMapper;
     private final AiMemberMapper aiMemberMapper;
     private final RedisUtils redisUtils;
+    private final LlmStrategyFactory llmStrategyFactory;
     @ApiOperation(value = "登录测试", notes = "登录测试")
     @GetMapping(value = "/login")
     public FebsResponse info() {
@@ -84,4 +100,188 @@
         //去掉时间戳
         return rsa.encryptBase64(token, KeyType.PublicKey);
     }
+
+
+
+    @ApiOperation("提问AI(流式)V2")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "流式响应", response = ApiMemberTalkStreamVo.class),
+    })
+    @PostMapping("/answer-streamV2")
+    public Flux<FebsResponse> answerStreamV2(@RequestBody @Validated AiTalkAnswerStream dto) {
+        if (StrUtil.isEmpty(dto.getQuestion())){
+            return Flux.just(new FebsResponse().fail().message("请输入问题"));
+        }
+        String question = dto.getQuestion();
+        String prompt = dto.getPrompt() ;
+
+        long startTime = System.currentTimeMillis();
+
+        Flowable<GenerationResult> result;
+        try {
+            result = callWithMessageStream(question,prompt);
+        } catch (NoApiKeyException | InputRequiredException e) {
+            e.printStackTrace();
+            return Flux.just(new FebsResponse().fail().message("调用AI服务失败: " + e.getMessage()));
+        }
+
+        return Flux.from(result)
+                .map(message -> {
+                    String content = message.getOutput().getChoices().get(0).getMessage().getContent();
+                    System.out.print(content);
+                    return new FebsResponse().success().data(content);
+                })
+                .doOnComplete(() -> {
+                    long endTime = System.currentTimeMillis();
+                    System.out.println("运行时间:" + (endTime - startTime) + "毫秒");
+                })
+                .doOnError(error -> {
+                    long endTime = System.currentTimeMillis();
+                    System.err.println("运行时间:" + (endTime - startTime) + "毫秒,发生错误:" + error.getMessage());
+                });
+    }
+
+
+
+    @ApiOperation("提问AI(流式)V3")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "流式响应", response = ApiMemberTalkStreamVo.class),
+    })
+    @PostMapping("/answerStreamV3")
+    public Flux<FebsResponse> answerStreamV3(@RequestBody @Validated AiTalkAnswerStream dto) {
+        if (StrUtil.isEmpty(dto.getQuestion())){
+            return Flux.just(new FebsResponse().fail().message("请输入问题"));
+        }
+
+        ArrayList<LlmStrategyDto> llmStrategyDtoList = new ArrayList<>();
+        if (dto.getPrompt() != null){
+            LlmStrategyDto llmStrategyDto = new LlmStrategyDto();
+            llmStrategyDto.setRole(Role.SYSTEM.getValue());
+            llmStrategyDto.setContent(dto.getPrompt());
+            llmStrategyDtoList.add(llmStrategyDto);
+        }
+        if (dto.getQuestion() != null){
+            LlmStrategyDto llmStrategyDto = new LlmStrategyDto();
+            llmStrategyDto.setRole(Role.USER.getValue());
+            llmStrategyDto.setContent(dto.getQuestion());
+            llmStrategyDtoList.add(llmStrategyDto);
+        }
+        String modelName = LlmStrategyEnum.getName(dto.getType());
+
+        return llmStrategyFactory.getCalculationStrategyMap().get(modelName).llmInvokeStreaming(llmStrategyDtoList);
+    }
+
+
+
+    @ApiOperation("提问AI(非流式响应)V4")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "非流式响应", response = ApiMemberTalkStreamVo.class),
+    })
+    @PostMapping("/answerStreamV4")
+    public FebsResponse answerStreamV4(@RequestBody @Validated AiTalkAnswerStream dto) {
+        if (StrUtil.isEmpty(dto.getQuestion())){
+            return new FebsResponse().fail().message("请输入问题");
+        }
+        ArrayList<LlmStrategyDto> llmStrategyDtoList = new ArrayList<>();
+        if (dto.getPrompt() != null){
+            LlmStrategyDto llmStrategyDto = new LlmStrategyDto();
+            llmStrategyDto.setRole(Role.SYSTEM.getValue());
+            llmStrategyDto.setContent(dto.getPrompt());
+            llmStrategyDtoList.add(llmStrategyDto);
+        }
+        if (dto.getQuestion() != null){
+            LlmStrategyDto llmStrategyDto = new LlmStrategyDto();
+            llmStrategyDto.setRole(Role.USER.getValue());
+            llmStrategyDto.setContent(dto.getQuestion());
+            llmStrategyDtoList.add(llmStrategyDto);
+        }
+        String modelName = LlmStrategyEnum.getName(dto.getType());
+
+        return llmStrategyFactory.getCalculationStrategyMap().get(modelName).llmInvokeNonStreaming(llmStrategyDtoList);
+    }
+
+
+    public static Flowable<GenerationResult> callWithMessageStream(String question,String prompt) throws NoApiKeyException, InputRequiredException {
+        Generation gen = new Generation();
+        Message systemMsg = Message.builder()
+                .role(Role.SYSTEM.getValue())
+                .content(prompt)
+                .build();
+        Message userMsg = Message.builder()
+                .role(Role.USER.getValue())
+                .content(question)
+                .build();
+        GenerationParam param = GenerationParam.builder()
+                // 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:.apiKey("sk-xxx")
+                .apiKey("sk-babdcf8799144134915cee2683794b2f")
+                // 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
+                .model("qwen-plus")
+//                .model("deepseek-r1")
+//                .model("qwen-turbo-0624-ft-202508281725-c2dc")
+                .messages(Arrays.asList(systemMsg, userMsg))
+//                .resultFormat(GenerationParam.ResultFormat.TEXT)
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .incrementalOutput(true)
+                .build();
+        return gen.streamCall(param);
+    }
+
+
+    public static GenerationResult callWithMessage(String question,String prompt) throws ApiException, NoApiKeyException, InputRequiredException {
+        Generation gen = new Generation();
+        Message systemMsg = Message.builder()
+                .role(Role.SYSTEM.getValue())
+                .content(prompt)
+                .build();
+        Message userMsg = Message.builder()
+                .role(Role.USER.getValue())
+                .content(question)
+                .build();
+        GenerationParam param = GenerationParam.builder()
+                // 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:.apiKey("sk-xxx")
+                .apiKey("sk-babdcf8799144134915cee2683794b2f")
+                // 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
+                .model("qwen-plus")
+                .messages(Arrays.asList(systemMsg, userMsg))
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .build();
+        return gen.call(param);
+    }
+    public static void main(String[] args) {
+        //定义一个开始时间为启动这个main方法的开始时间,用于计算运行时间
+        long startTime = System.currentTimeMillis();
+        String question = "干的漂亮";
+        String prompt = "{\"task\": \"作为专业的表扬能力评估分析师,分析question和用户输入内容,对用户输入内容进行评估与指导。\",\"question\":\"当资深骨干员工在突发场景中迅速响应并解决了持续一周的客户投诉达成客户满意度成就时,作为上级的你应如何表达赞赏?\",\"highlight\": \"识别符合表扬原则的积极策略,关注角色视角适配性、员工类型特点、具体行为描述、情感表达真诚度与个性化认可方式\"}";
+        String prompt1 = "{\"task\": \"作为专业的表扬能力评估分析师,分析question和用户输入内容,对用户输入内容进行评估与指导。\",\"question\":\"当资深骨干员工在突发场景中迅速响应并解决了持续一周的客户投诉达成客户满意度成就时,作为上级的你应如何表达赞赏?\",\"suggestion\": \"提供针对性优化方案,涵盖场景要素匹配度提升(如正式场合需增加公开认可环节)、成就类型适配改进(如创新贡献应强调思维突破而非仅结果)、具体维度强化方向(如增加 STAR 法则中的 Result 部分描述)、跨文化 / 远程场景特殊策略(如虚拟团队可采用异步表扬 + 公开认可组合)\"}";
+        String prompt2 = "{\"task\": \"作为专业的表扬能力评估分析师,分析question和用户输入内容,对用户输入内容进行评估与指导。\",\"question\":\"当资深骨干员工在突发场景中迅速响应并解决了持续一周的客户投诉达成客户满意度成就时,作为上级的你应如何表达赞赏?\",\"reference_answer\": \"根据问题用户的回答,生成参考示例\"}";
+        String prompt3 = "{\"task\": \"作为专业的表扬能力评估分析师,分析question和用户输入内容,对用户输入内容进行评估与指导。\",\"question\":\"当资深骨干员工在突发场景中迅速响应并解决了持续一周的客户投诉达成客户满意度成就时,作为上级的你应如何表达赞赏?\",\"key_knowledge\": \"结合理论与实践深度解析\"}";
+        GenerationResult result = null;
+        try {
+            result = callWithMessage(question, prompt);
+        } catch (NoApiKeyException e) {
+            e.printStackTrace();
+        } catch (InputRequiredException e) {
+            e.printStackTrace();
+        }
+        System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent());
+        long endTime = System.currentTimeMillis();
+        System.out.println("运行时间:" + (endTime - startTime) + "毫秒");
+        long startTimeStream = System.currentTimeMillis();
+        Flowable<GenerationResult> resultStream = null;
+        try {
+            resultStream = callWithMessageStream(question, prompt);
+        } catch (NoApiKeyException e) {
+            e.printStackTrace();
+        } catch (InputRequiredException e) {
+            e.printStackTrace();
+        }
+        Flux.from(resultStream)
+                .doOnNext(message -> {
+                    String content = message.getOutput().getChoices().get(0).getMessage().getContent();
+                    System.out.print(content);
+                })
+                .subscribe();
+        long endTimeStream = System.currentTimeMillis();
+        System.out.println("运行时间:" + (endTimeStream - startTimeStream) + "毫秒");
+    }
 }

--
Gitblit v1.9.1