package cc.mrbird.febs.ai.controller; import cc.mrbird.febs.ai.entity.AiMember; import cc.mrbird.febs.ai.mapper.AiMemberMapper; import cc.mrbird.febs.ai.req.talk.AiTalkAnswerStream; import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVo; import cc.mrbird.febs.ai.utils.UUID; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.utils.AppContants; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.mall.entity.MallMember; import cc.mrbird.febs.mall.mapper.MallMemberMapper; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; 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; import io.swagger.annotations.ApiResponses; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; 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.Arrays; import java.util.HashMap; import java.util.Map; /** * @author Administrator */ @Slf4j @Validated @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/test") @Api(value = "ApiProductController", tags = "AI-登录测试") public class TestController { private final MallMemberMapper mallMemberMapper; private final AiMemberMapper aiMemberMapper; private final RedisUtils redisUtils; @ApiOperation(value = "登录测试", notes = "登录测试") @GetMapping(value = "/login") public FebsResponse info() { MallMember mallMember = mallMemberMapper.selectById(3634); if(StrUtil.isEmpty(mallMember.getMemberUuid())){ AiMember aiMember = new AiMember(); aiMember.setId(UUID.getSimpleUUIDString()); aiMemberMapper.insert(aiMember); mallMember.setMemberUuid(aiMember.getId()); mallMemberMapper.update(null, Wrappers.lambdaUpdate(MallMember.class) .set(MallMember::getMemberUuid, aiMember.getId()) .eq(MallMember::getId, mallMember.getId()) ); } // 存放redis String redisKey = AppContants.XCX_LOGIN_PREFIX + mallMember.getId(); String existToken = redisUtils.getString(redisKey); if (StrUtil.isNotBlank(existToken)) { Object o = redisUtils.get(existToken); if (ObjectUtil.isNotEmpty(o)) { redisUtils.del(existToken); } } String token = IdUtil.simpleUUID(); redisUtils.set(token, JSONObject.toJSONString(mallMember), -1); redisUtils.set(redisKey, token, -1); Map authInfo = new HashMap<>(); authInfo.put("token", token); authInfo.put("member", mallMember); authInfo.put("rasToken", generateAsaToken(token)); return new FebsResponse().success().data(authInfo); } public String generateAsaToken(String token) { RSA rsa = new RSA(null, AppContants.PUBLIC_KEY); // return rsa.encryptBase64(token + "_" + System.currentTimeMillis(), KeyType.PublicKey); //去掉时间戳 return rsa.encryptBase64(token, KeyType.PublicKey); } @ApiOperation("提问AI(流式)V2") @ApiResponses({ @ApiResponse(code = 200, message = "流式响应", response = ApiMemberTalkStreamVo.class), }) @PostMapping("/answer-streamV2") public Flux answerStreamV2(@RequestBody @Validated AiTalkAnswerStream dto) { if (StrUtil.isEmpty(dto.getQuestion())){ return Flux.just(new FebsResponse().fail().message("请输入问题")); } long startTime = System.currentTimeMillis(); Flowable result; try { result = callWithMessage(); } 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().message(content); }) .doOnComplete(() -> { long endTime = System.currentTimeMillis(); System.out.println("运行时间:" + (endTime - startTime) + "毫秒"); }) .doOnError(error -> { long endTime = System.currentTimeMillis(); System.err.println("运行时间:" + (endTime - startTime) + "毫秒,发生错误:" + error.getMessage()); }); } public static Flowable callWithMessage() throws NoApiKeyException, InputRequiredException { Generation gen = new Generation(); Message systemMsg = Message.builder() .role(Role.SYSTEM.getValue()) .content("You are a helpful assistant.") .build(); Message userMsg = Message.builder() .role(Role.USER.getValue()) .content("你是谁?") .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 void main(String[] args) { //定义一个开始时间为启动这个main方法的开始时间,用于计算运行时间 long startTime = System.currentTimeMillis(); Flowable result = null; try { result = callWithMessage(); } catch (NoApiKeyException e) { e.printStackTrace(); } catch (InputRequiredException e) { e.printStackTrace(); } Flux.from(result) .doOnNext(message -> { String content = message.getOutput().getChoices().get(0).getMessage().getContent(); System.out.print(content); }) .subscribe(); long endTime = System.currentTimeMillis(); System.out.println("运行时间:" + (endTime - startTime) + "毫秒"); // result.blockingForEach(item -> { //// log.info("item: {}", JSONUtil.toJsonStr(item)); // // 提取文本内容 // if (item.getOutput() != null && item.getOutput().getChoices() != null) { // item.getOutput().getChoices().forEach(choice -> { // if (choice.getMessage() != null) { // // 根据实际 API 文档确定使用哪个方法 //// if (choice.getMessage().getContents() != null) { //// try { //// choice.getMessage().getContents().forEach(content -> { //// if (content != null) { //// System.out.print(content.getType()); //// } //// }); //// } catch (NullPointerException e) { //// log.error("Error processing contents", e); //// } //// } // if (choice.getMessage().getContent() != null) { // System.out.print(choice.getMessage().getContent()); // } // } // }); // } // }); } }