当前位置:   article > 正文

山东大学软件学院创新实训-研究通义千问大模型的Java调用笔记_通义千问api调用systemmsg

通义千问api调用systemmsg

关键网址:

如何快速开始通义千问_模型服务灵积(DashScope)-阿里云帮助中心

如何使用通义千问API_模型服务灵积(DashScope)-阿里云帮助中心

在官网文档中提及了通过Messages调用(推荐)和通过prompt调用两种方式,于是我调查了这两种调用方式的区别:

通过 prompt 调用和通过 messages 调用的主要区别在于输入数据的方式和适用场景:

  1. 通过 prompt 调用

    • 使用单个文本作为输入,称为提示文本(prompt),代表用户的一个请求或问题。
    • 适用于单次性的、独立的文本生成任务,不需要考虑上下文或历史消息。
    • 例如,当用户提出一个问题或请求时,可以直接将该问题或请求作为提示文本传递给模型进行文本生成。
  2. 通过 messages 调用

    • 使用消息管理器(MessageManager)来管理多个消息,包括用户消息和系统消息,形成消息队列。
    • 适用于需要考虑上下文、历史消息、多轮对话等情况。
    • 可以在多轮对话中保持上下文,模拟与用户的自然对话,根据之前的交互进行文本生成。
    • 例如,在一个聊天机器人的场景中,用户提出的问题可能需要结合之前的对话历史来进行回答,此时就需要使用消息管理器来管理上下文信息。

通过上面对比可以看出Messages通用性更高,因为智慧医疗问诊确实需要使用到累计的对话记录。

所以下面就重点研究通过Messages调用的方法。

首先是官方的示例代码,但是官方代码不能直接运行,还需要做相关配置。下面是我调试好的代码,为了保险,我把key值隐藏了,替换掉即可。

  1. package com.A611699;// Copyright (c) Alibaba, Inc. and its affiliates.
  2. import com.alibaba.dashscope.aigc.generation.Generation;
  3. import com.alibaba.dashscope.aigc.generation.GenerationResult;
  4. import com.alibaba.dashscope.aigc.generation.models.QwenParam;
  5. import com.alibaba.dashscope.common.Message;
  6. import com.alibaba.dashscope.common.MessageManager;
  7. import com.alibaba.dashscope.common.Role;
  8. import com.alibaba.dashscope.exception.ApiException;
  9. import com.alibaba.dashscope.exception.InputRequiredException;
  10. import com.alibaba.dashscope.exception.NoApiKeyException;
  11. public class Maintest {
  12. public static void callWithMessage()
  13. throws NoApiKeyException, ApiException, InputRequiredException {
  14. Generation gen = new Generation();
  15. com.alibaba.dashscope.utils.Constants.apiKey = "*********";
  16. MessageManager msgManager = new MessageManager(10);
  17. Message systemMsg =
  18. Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build();
  19. Message userMsg = Message.builder().role(Role.USER.getValue()).content("如何做西红柿鸡蛋?").build();
  20. msgManager.add(systemMsg);
  21. msgManager.add(userMsg);
  22. QwenParam param =
  23. QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get())
  24. .resultFormat(QwenParam.ResultFormat.MESSAGE)
  25. .build();
  26. GenerationResult result = gen.call(param);
  27. System.out.println(result);
  28. }
  29. public static void main(String[] args){
  30. try {
  31. callWithMessage();
  32. } catch (ApiException | NoApiKeyException | InputRequiredException e) {
  33. System.out.println(e.getMessage());
  34. }
  35. System.exit(0);
  36. }
  37. }

通义千问模型的调用有两种方式:使用DashScope SDK和HTTP接口

一、使用DashScope SDK调用

1、首先需要  安装DashScope SDK

2、开通服务并且获得通义千问的API-KEY  开通DashScope并创建API-KEY

3、推荐将API-KEY配置到环境变量中来降低API-KEY的泄露风险,可参考通过环境变量配置API-KEY,当然也可以在代码中配置API-KEY,但是这样泄露了话就可能就烧钱了。

官方的单轮对话代码:已经调试好了,替换掉API-KEY就行

  1. package com.A611699;// Copyright (c) Alibaba, Inc. and its affiliates.
  2. // 建议dashscope SDK的版本 >= 2.12.0
  3. import java.util.Arrays;
  4. import com.alibaba.dashscope.aigc.generation.Generation;
  5. import com.alibaba.dashscope.aigc.generation.GenerationParam;
  6. import com.alibaba.dashscope.aigc.generation.GenerationResult;
  7. import com.alibaba.dashscope.common.Message;
  8. import com.alibaba.dashscope.common.Role;
  9. import com.alibaba.dashscope.exception.ApiException;
  10. import com.alibaba.dashscope.exception.InputRequiredException;
  11. import com.alibaba.dashscope.exception.NoApiKeyException;
  12. public class Maintest {
  13. public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
  14. Generation gen = new Generation();
  15. com.alibaba.dashscope.utils.Constants.apiKey = "**********";
  16. Message systemMsg = Message.builder()
  17. .role(Role.SYSTEM.getValue())
  18. .content("You are a helpful assistant.")
  19. .build();
  20. Message userMsg = Message.builder()
  21. .role(Role.USER.getValue())
  22. .content("如何做西红柿炒鸡蛋?")
  23. .build();
  24. GenerationParam param = GenerationParam.builder()
  25. .model("qwen-turbo")
  26. .messages(Arrays.asList(systemMsg, userMsg))
  27. .resultFormat(GenerationParam.ResultFormat.MESSAGE)
  28. .topP(0.8)
  29. .build();
  30. return gen.call(param);
  31. }
  32. public static void main(String[] args) {
  33. try {
  34. GenerationResult result = callWithMessage();
  35. System.out.println(result);
  36. } catch (ApiException | NoApiKeyException | InputRequiredException e) {
  37. // 使用日志框架记录异常信息
  38. // Logger.error("An error occurred while calling the generation service", e);
  39. System.err.println("An error occurred while calling the generation service: " + e.getMessage());
  40. }
  41. System.exit(0);
  42. }
  43. }

相对于单轮对话,多轮对话可以参考历史聊天信息,更符合日常交流的场景。但由于调用时会引入历史聊天信息,使用的token量会增多。下面是多轮对话的代码。但是多轮的提问问题已经在代码中写死了。

  1. package com.A611699;// Copyright (c) Alibaba, Inc. and its affiliates.
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import com.alibaba.dashscope.aigc.generation.Generation;
  5. import com.alibaba.dashscope.aigc.generation.GenerationParam;
  6. import com.alibaba.dashscope.aigc.generation.GenerationResult;
  7. import com.alibaba.dashscope.common.Message;
  8. import com.alibaba.dashscope.common.Role;
  9. import com.alibaba.dashscope.exception.ApiException;
  10. import com.alibaba.dashscope.exception.InputRequiredException;
  11. import com.alibaba.dashscope.exception.NoApiKeyException;
  12. import com.alibaba.dashscope.utils.JsonUtils;
  13. public class Maintest {
  14. // 设置 API key
  15. static {
  16. com.alibaba.dashscope.utils.Constants.apiKey = "sk****************";
  17. }
  18. public static GenerationParam createGenerationParam(List<Message> messages) {
  19. return GenerationParam.builder()
  20. .model("qwen-turbo")
  21. .messages(messages)
  22. .resultFormat(GenerationParam.ResultFormat.MESSAGE)
  23. .topP(0.8)
  24. .build();
  25. }
  26. public static GenerationResult callGenerationWithMessages(GenerationParam param) throws ApiException, NoApiKeyException, InputRequiredException {
  27. Generation gen = new Generation();
  28. return gen.call(param);
  29. }
  30. public static void main(String[] args) {
  31. try {
  32. List<Message> messages = new ArrayList<>();
  33. messages.add(createMessage(Role.SYSTEM, "You are a helpful assistant."));
  34. messages.add(createMessage(Role.USER, "如何做西红柿炖牛腩?"));
  35. GenerationParam param = createGenerationParam(messages);
  36. GenerationResult result = callGenerationWithMessages(param);
  37. printResult(result);
  38. // 添加assistant返回的消息到列表
  39. messages.add(result.getOutput().getChoices().get(0).getMessage());
  40. // 添加新的用户消息
  41. messages.add(createMessage(Role.USER, "不放糖可以吗?"));
  42. result = callGenerationWithMessages(param);
  43. printResult(result);
  44. printResultAsJson(result);
  45. } catch (ApiException | NoApiKeyException | InputRequiredException e) {
  46. e.printStackTrace();
  47. }
  48. System.exit(0);
  49. }
  50. private static Message createMessage(Role role, String content) {
  51. return Message.builder().role(role.getValue()).content(content).build();
  52. }
  53. private static void printResult(GenerationResult result) {
  54. System.out.println(result);
  55. }
  56. private static void printResultAsJson(GenerationResult result) {
  57. System.out.println(JsonUtils.toJson(result));
  58. }
  59. }

下面再做改进,体验实时在线多轮对话功能,但是对话轮数已经写固定了(10轮),可以在代码中修改。

  1. package com.A611699;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import com.alibaba.dashscope.aigc.generation.Generation;
  5. import com.alibaba.dashscope.aigc.generation.GenerationParam;
  6. import com.alibaba.dashscope.aigc.generation.GenerationResult;
  7. import com.alibaba.dashscope.common.Message;
  8. import com.alibaba.dashscope.common.Role;
  9. import com.alibaba.dashscope.exception.ApiException;
  10. import com.alibaba.dashscope.exception.InputRequiredException;
  11. import com.alibaba.dashscope.exception.NoApiKeyException;
  12. import java.util.Scanner;
  13. public class Maintest {
  14. // 设置 API key
  15. static {
  16. com.alibaba.dashscope.utils.Constants.apiKey = "sk-****************";
  17. }
  18. public static GenerationParam createGenerationParam(List<Message> messages) {
  19. return GenerationParam.builder()
  20. .model("qwen-turbo")
  21. .messages(messages)
  22. .resultFormat(GenerationParam.ResultFormat.MESSAGE)
  23. .topP(0.8)
  24. .build();
  25. }
  26. public static GenerationResult callGenerationWithMessages(GenerationParam param) throws ApiException, NoApiKeyException, InputRequiredException {
  27. Generation gen = new Generation();
  28. return gen.call(param);
  29. }
  30. public static void main(String[] args) {
  31. try {
  32. List<Message> messages = new ArrayList<>();
  33. messages.add(createMessage(Role.SYSTEM, "You are a helpful assistant."));
  34. for (int i = 0; i < 10;i++) {
  35. Scanner scanner = new Scanner(System.in);
  36. System.out.print("请输入:");
  37. String userInput = scanner.nextLine();
  38. if ("exit".equalsIgnoreCase(userInput)) {
  39. break;
  40. }
  41. messages.add(createMessage(Role.USER, userInput));
  42. GenerationParam param = createGenerationParam(messages);
  43. GenerationResult result = callGenerationWithMessages(param);
  44. System.out.println("模型输出:"+result.getOutput().getChoices().get(0).getMessage().getContent());
  45. messages.add(result.getOutput().getChoices().get(0).getMessage());
  46. }
  47. } catch (ApiException | NoApiKeyException | InputRequiredException e) {
  48. e.printStackTrace();
  49. }
  50. System.exit(0);
  51. }
  52. private static Message createMessage(Role role, String content) {
  53. return Message.builder().role(role.getValue()).content(content).build();
  54. }
  55. }

大模型并不是一次性生成最终结果,而是逐步地生成中间结果,最终结果由这些中间结果拼接而成。在非流式输出方式中,等待模型生成结束后,所有中间结果将被拼接成最终结果,然后返回。相比之下,流式输出可以实时地将中间结果返回,您可以在模型继续进行输出的同时进行阅读,从而减少等待模型回复的时间。要使用流式输出,您需要进行一些配置。在 DashScope Python SDK 中,您需要设置 stream 参数为 True;在 DashScope Java SDK 中,您需要使用 streamCall 接口调用。下面是调试好的代码:

  1. package com.A611699;// Copyright (c) Alibaba, Inc. and its affiliates.
  2. import java.util.Arrays;
  3. import java.util.concurrent.Semaphore;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import java.util.concurrent.Semaphore;
  7. import com.alibaba.dashscope.aigc.generation.Generation;
  8. import com.alibaba.dashscope.aigc.generation.GenerationParam;
  9. import com.alibaba.dashscope.aigc.generation.GenerationResult;
  10. import com.alibaba.dashscope.common.Message;
  11. import com.alibaba.dashscope.common.ResultCallback;
  12. import com.alibaba.dashscope.common.Role;
  13. import com.alibaba.dashscope.exception.ApiException;
  14. import com.alibaba.dashscope.exception.InputRequiredException;
  15. import com.alibaba.dashscope.exception.NoApiKeyException;
  16. import com.alibaba.dashscope.utils.JsonUtils;
  17. import io.reactivex.Flowable;
  18. public class Maintest {
  19. static {
  20. // 设置 API key
  21. com.alibaba.dashscope.utils.Constants.apiKey = "sk-***********************";
  22. }
  23. private static final Logger logger = LoggerFactory.getLogger(Main.class);
  24. private static void handleGenerationResult(GenerationResult message, StringBuilder fullContent) {
  25. fullContent.append(message.getOutput().getChoices().get(0).getMessage().getContent());
  26. logger.info("Received message: {}", JsonUtils.toJson(message));
  27. }
  28. public static void streamCallWithMessage(Generation gen, Message userMsg)
  29. throws NoApiKeyException, ApiException, InputRequiredException {
  30. GenerationParam param = buildGenerationParam(userMsg);
  31. Flowable<GenerationResult> result = gen.streamCall(param);
  32. StringBuilder fullContent = new StringBuilder();
  33. result.blockingForEach(message -> handleGenerationResult(message, fullContent));
  34. logger.info("Full content: \n{}", fullContent.toString());
  35. }
  36. public static void streamCallWithCallback(Generation gen, Message userMsg)
  37. throws NoApiKeyException, ApiException, InputRequiredException, InterruptedException {
  38. GenerationParam param = buildGenerationParam(userMsg);
  39. Semaphore semaphore = new Semaphore(0);
  40. StringBuilder fullContent = new StringBuilder();
  41. gen.streamCall(param, new ResultCallback<GenerationResult>() {
  42. @Override
  43. public void onEvent(GenerationResult message) {
  44. handleGenerationResult(message, fullContent);
  45. }
  46. @Override
  47. public void onError(Exception err) {
  48. logger.error("Exception occurred: {}", err.getMessage());
  49. semaphore.release();
  50. }
  51. @Override
  52. public void onComplete() {
  53. logger.info("Completed");
  54. semaphore.release();
  55. }
  56. });
  57. semaphore.acquire();
  58. logger.info("Full content: \n{}", fullContent.toString());
  59. }
  60. private static GenerationParam buildGenerationParam(Message userMsg) {
  61. return GenerationParam.builder()
  62. .model("qwen-turbo")
  63. .messages(Arrays.asList(userMsg))
  64. .resultFormat(GenerationParam.ResultFormat.MESSAGE)
  65. .topP(0.8)
  66. .incrementalOutput(true)
  67. .build();
  68. }
  69. public static void main(String[] args) {
  70. try {
  71. Generation gen = new Generation();
  72. Message userMsg = Message.builder().role(Role.USER.getValue()).content("如何做西红柿炖牛腩?").build();
  73. streamCallWithMessage(gen, userMsg);
  74. streamCallWithCallback(gen, userMsg);
  75. } catch (ApiException | NoApiKeyException | InputRequiredException | InterruptedException e) {
  76. logger.error("An exception occurred: {}", e.getMessage());
  77. }
  78. }
  79. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/615126
推荐阅读
相关标签
  

闽ICP备14008679号