在springboot项目中调用通义千问api多轮对话并实现流式输出

这篇具有很好参考价值的文章主要介绍了在springboot项目中调用通义千问api多轮对话并实现流式输出。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

官网文档

阿里灵积提供了详细的官方文档

如何实现多轮对话

官方文档中提到只需要把每轮对话中返回结果添加到消息管理器中,就可以实现多轮对话。本质上就是将历史对话再次发送给接口。

springboot整合通义千问,spring boot,spring,java,人工智能

如何实现流式输出

官方文档中提出使用streamCall()方法就可以实现流式输出,在ResultCallback<GenerationResult>参数中可以指点每个事件的处理动作。

springboot整合通义千问,spring boot,spring,java,人工智能

流式调用方法没有返回GenerationResult结果类,如何实现多轮对话

方法一

我们每次调用完成后把得到的结果手动构建消息对象并加入消息管理类。

不知道是不是我使用的sdk版本问题(因为老的版本有出现调用okhttp报错的情况,我的在阿里云提交工单后,工作人员给我的最新版本是2.10.1,我当前就在使用这个版本)。经过实际测试,msgManager.get()方法可能会出现第一条对话的发送对象是assistant的情况。

如果第一条对话的发送对象不是user或者system,并且user和assistant没有在历史对话中轮流出现接口会报错的!!!!(我没有报错的截图,哈哈哈哈)

Message assistantMsg = Message.builder().role(Role.ASSISTANT.getValue()).content("如何做西红柿炖牛腩?").build();
msgManager.add(assistantMsg);

方法二

我们自己来控制历史对话文章来源地址https://www.toymoban.com/news/detail-848511.html

@Component
public class QwenModelService{

    private Generation gen;

    @Resource
    private AiWebsocketService aiWebsocketService;

    public void createGen(){
        gen = new Generation();
    };

    private static final Logger logger = LoggerFactory.getLogger(QwenModelService.class);

    /**
     * prompt 用户对话
     * request 用户请求对象
     * identity 用户身份标识
     */
    public String answer(String prompt, HttpServletRequest request, String identity) {

        // 通过身份标识在缓存中获取对话对象、历史消息对象、参数对象
        List<AiDialogue> dialogues = CachePool.AI_DIALOGUE_LIST_MAP.get(identity)
                .computeIfAbsent(ConstValuePool.QWEN_DIALOGUES, k -> new LinkedList<>());
        dialogues.add(AiDialogue.createUserDialogue(prompt));
        List<Message> msgManager = CachePool.QWEN_MESSAGE_DIALOGUES_MAP.get(identity);
        QwenParam param = CachePool.QWEN_PARAM_MAP.get(identity);

        // 如果第一次发送消息需要初始化历史消息对象
        if (msgManager == null) {
            msgManager = new ArrayList<>();
            CachePool.QWEN_MESSAGE_DIALOGUES_MAP.put(identity, msgManager);
            Message systemMsg = Message.builder()
                    .role(Role.SYSTEM.getValue())
                    .content("You are a helpful assistant.")
                    .build();
            msgManager.add(systemMsg);
            Message userMsg = Message.builder()
                    .role(Role.USER.getValue())
                    .content(prompt)
                    .build();
            msgManager.add(userMsg);
        }else {
            msgManager.add(Message.builder().role("user").content(prompt).build());
            param.setMessages(msgManager);
        }

        // 如果第一次发送消息需要初始化参数对象
        if (param == null) {
            param = QwenParam.builder()
                    .model(Generation.Models.QWEN_MAX)
                    .messages(msgManager)
                    .resultFormat(QwenParam.ResultFormat.MESSAGE)
                    .topP(0.8)
                    .enableSearch(true)
                    .incrementalOutput(true)
                    .build();
            CachePool.QWEN_PARAM_MAP.put(identity, param);
        }


        try {
            logger.debug("发送的请求为{}",param);
            // 同步信号量
            Semaphore semaphore = new Semaphore(0);
            // 结果拼接对象
            StringBuilder resultBuilder = new StringBuilder();
            // 流式调用
            gen.streamCall(param, new ResultCallback<GenerationResult>(){

                @Override
                public void onEvent(GenerationResult generationResult) {
                    String newMessage = generationResult.getOutput().getChoices().get(0).getMessage().getContent();
                    StringBuilder finalResBuilder = resultBuilder.append(newMessage);

                    // 这里是对markdown代码块进行判断,如果当前代码块未结束,需要手动结束
                    // 否则前端的代码块显示会出问题
                    // 代码块判断的功能就是对"```"字符串计数,偶数个就是结束了,奇数个就是没结束
                    if (1 == (1 & StringUtil.countSubStr(finalResBuilder,ConstValuePool.MARKDOWN_CODE_BLOCK_START))) {
                        finalResBuilder = new StringBuilder(finalResBuilder)
                                .append(ConstValuePool.MARKDOWN_CODE_BLOCK_END);
                    }
                    // 通过websocket返回给前端
                    aiWebsocketService.sendMessage(finalResBuilder.toString(), identity);
                }

                // 结束或者报错需要释放同步信号量
                @Override
                public void onComplete() {
                    semaphore.release();
                }

                @Override
                public void onError(Exception e) {
                    semaphore.release();
                    logger.error("通义千问运行出错, 报错栈如下");
                    Throwable t = e;
                    while (t != null) {
                        logger.error( t.toString());
                        t = e.getCause();
                    }
                }
            });
            semaphore.acquire();
            String resString = resultBuilder.toString();
            
            // 把返回消息加入历史消息中
msgManager.add(Message.builder().role("assistant").content(resString).build());
            // 如果历史消息量过大或者第一条消息发送对象不是user,删除历史消息
            // 下标0是system消息
            while (msgManager.size() > ConstValuePool.QWEN_MAX_MESSAGE
                    || !"user".equals(msgManager.get(1).getRole())) {
                msgManager.remove(1);
            }
            // 添加到对话记录中,方便前端查询对话记录
            dialogues.add(AiDialogue.createAssistantDialogue(resString));
            return "";
        } catch (NoApiKeyException e) {
            logger.error("调用通义千问缺少ApiKey");
            throw new AiException("没有ApiKey", e);
        } catch (Exception e) {
            logger.error("调用通义千问出现问题:{}",e.getMessage());
            throw new AiException("出现了一些问题", e);
        }
    }

}

到了这里,关于在springboot项目中调用通义千问api多轮对话并实现流式输出的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 阿里发布通义千问!1行代码,免费对话GPT大模型

    大家好,这里是程序员晚枫,今天给大家分享一个好用的东西👉1行代码,使用阿里的GPT聊天大模型:通义千问。 GPT刚推出的时候,百度推出了文心一言、腾讯推出了混元大模型,阿里一直没动静。 自从马云回归,阿里的大模型也开始发力了,推出了自己的大模型:通义千问

    2024年01月22日
    浏览(43)
  • 5分钟实现调用ChatGPT接口API实现多轮问答

    5分钟实现调用ChatGPT接口API完成多轮问答 最近ChatGPT也是火爆异常啊,在亲自使用了几个月之后,我发现这东西是真的好用,实实在在地提高了生产力。那么对于开发人员来说,有时候可能需要在自己的代码里加入这样一个智能问答的功能,我最近就出现了这样的想法和需求,

    2024年02月03日
    浏览(35)
  • 初步体验通过 Semantic Kernel 与自己部署的通义千问开源大模型进行对话

    春节之前被 Semantic Kernel 所吸引,开始了解它,学习它。 在写这篇博文之前读了一些英文博文,顺便在这里分享一下: Intro to Semantic Kernel – Part One Intro to Semantic Kernel – Part Two Build a custom Copilot experience with your private data using and Kernel Memory Semantic Kernel: The New Way to Create Artific

    2024年02月19日
    浏览(40)
  • Java调用ChatGPT(基于SpringBoot),实现可连续对话和流式输出的ChatGPT API(可自定义实现AI助手)

    源码及更详细的介绍说明参见Git上的 README.md 文档 https://github.com/asleepyfish/chatgpt 本文Demo(SpringBoot和Main方法Demo均包括)的Git地址:https://github.com/asleepyfish/chatgpt-demo 流式输出结合Vue前端的Demo的Git地址:https://github.com/asleepyfish/chatgpt-vue 后续使用方法和api版本更新均在Github的READM

    2023年04月13日
    浏览(42)
  • java对接阿里云通义千问API

    前提条件 1.已经获取申请名额,开通服务并获得API-KEY:开通DashScope并创建API-KEY。 2.maven安装对应的jar包组件 3.java代码调用接口 返回结果

    2024年02月22日
    浏览(45)
  • Java调用ChatGPT(基于SpringBoot和Vue),实现可连续对话和流式输出的ChatGPT API(可自定义实现AI助手)

    源码及更详细的介绍说明参见Git上的 README.md 文档 https://github.com/asleepyfish/chatgpt 本文Demo(SpringBoot和Main方法Demo均包括)的Git地址:https://github.com/asleepyfish/chatgpt-demo 流式输出结合Vue前端的Demo的Git地址:https://github.com/asleepyfish/chatgpt-vue 后续使用方法和api版本更新均在Github的READM

    2023年04月24日
    浏览(42)
  • 通义千问本地化部署不调用GPU只调用CPU的检查方法

    今天部署本地版通义千问的时候遇到一个问题。 启动他的cli_demo.py调用的一直都是CPU模式的。 检查cuda已经正确安装,后面发现是torch即PyTorch的安装问题。 我安装torch的时候,用的是默认指令,没有增加别的参数。 检测一下,输出False即是错误的。 根据网上说的,可以在网上

    2024年02月10日
    浏览(39)
  • LLM(大语言模型)——Springboot集成文心一言、讯飞星火、通义千问、智谱清言

    目录 引言 代码完整地址 入参  出参 Controller Service Service实现类  模型Service  入参转换类 文心一言实现类 讯飞星火实现类  通义千问实现类 智谱清言实现类 本文将介绍如何使用Java语言,结合Spring Boot框架,集成国内热门大模型API,包括文心一言、讯飞星火、通义千问、智

    2024年04月12日
    浏览(40)
  • Java调用ChatGPT的API接口实现对话与图片生成

    有些魔法是需要做配置的。否则无法正确实现代码测试。这里以我使用的工具为例说明。 在pom.xml文件中添加: Constants类中,声明自己的API Key 其中,查看API Key的位置: https://platform.openai.com/account/api-keys 余额查询: https://platform.openai.com/account/usage pom.xml文件中需要增加依赖:

    2024年02月07日
    浏览(45)
  • 大模型开发(六):OpenAI Completions模型详解并实现多轮对话机器人

    授权声明: 本文基于九天Hector的原创课程资料创作,已获得其正式授权。 原课程出处:九天Hector的B站主页,感谢九天Hector为学习者带来的宝贵知识。 请尊重原创,转载或引用时,请标明来源。 全文共7000余字,预计阅读时间约15~30分钟 | 满满干货(附代码),建议收藏! 本文

    2024年02月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包