【异常记录Java-20250204】调用讯飞星火AI(Spark lite 版本)Api 授权错误问题处理

问题重现

  • 依赖

    xml 复制代码
    <!--讯飞开放平台sdk-->
    <dependency>
        <groupId>io.github.briqt</groupId>
        <artifactId>xunfei-spark4j</artifactId>
        <version>1.3.0</version>
    </dependency>
  • yml配置文件

    yaml 复制代码
    # 讯飞Api配置
    xunfei:
      client:
        appId: "别只顾着抄,这里要写自己的"
        apiKey: "别只顾着抄,这里要写自己的"
        apiSecret: "别只顾着抄,这里要写自己的"
  • SparkConfig 配置类

    java 复制代码
    @Configuration
    @ConfigurationProperties(prefix = "xunfei.client")
    @Data
    public class SparkConfig {
        private String appid;
        private String apiKey;
        private String apiSecret;
    
        @Bean
        public SparkClient sparkClient() {
            SparkClient sparkClient = new SparkClient();
            sparkClient.appid = this.appid;
            sparkClient.apiKey = this.apiKey;
            sparkClient.apiSecret = this.apiSecret;
            return sparkClient;
        }
    }
  • SparkManager 实现类

    java 复制代码
    @Component
    @Slf4j
    public class SparkManager {
        @Resource
        private SparkClient sparkClient;
    
        /**
         * AI生成问题的预设条件
         */
        public static final  String PRECONDITION = "" +
                "你是一名Java程序员\n" +
                "给我一些软件开发方面的知识\n";
    
        public String sendHttpToSpark(final String content){
            // 消息列表,可以再此列表添加历史对话记录
            List<SparkMessage> messages = new ArrayList<>();
            messages.add(SparkMessage.systemContent(PRECONDITION));
            // 用户输入内容
            messages.add(SparkMessage.userContent(content));
            // 构造请求
            SparkRequest sparkRequest = SparkRequest.builder()
                    // 指定请求版本,lite为V1_5
                    .apiVersion(SparkApiVersion.V1_5)
                    .messages(messages)     // 消息列表
                    .build();
            // 同步调用
            SparkSyncChatResponse chatResponse = sparkClient.chatSync(sparkRequest);
            String responseContent = chatResponse.getContent();
            log.info("spark返回内容:{}",responseContent);
            return responseContent;
        }
    }

    可以到讯飞星火官网免费领取不限量的免费AI

完成以上步骤后,不出意外的话就能正常通过java代码调用Spark lite 的API进行 AI 对话,但遗憾的是出了意外

  • 测试代码
java 复制代码
@SpringBootTest
public class SparkManagerTest {

    @Resource
    private SparkManager sparkManager;

    private final String userInput = "如何调用api";

    @Test
    public void testApi(){
        String result = sparkManager.sendHttpToSpark(userInput);
        System.out.println(result);
    }
}
  • 报错截图

问题处理

一开始我怀疑的是自己的配置出了问题,但CV大法除了CV错地方外,还能怎么错呢?

刚好讯飞星火提供了免费的Spark Lite的同时,还赠送了不少Spark4.0 Uitra的token数,刚好可以拿来做验证

修改指定请求版本

java 复制代码
public String sendHttpToSpark(final String content){
    List<SparkMessage> messages = new ArrayList<>();
    messages.add(SparkMessage.systemContent(PRECONDITION));
    messages.add(SparkMessage.userContent(content));
    SparkRequest sparkRequest = SparkRequest.builder()
            // 修改指定请求版本为4_0,其对应4.0Ultra
            .apiVersion(SparkApiVersion.V4_0)
            .messages(messages)    
            .build();
    SparkSyncChatResponse chatResponse = sparkClient.chatSync(sparkRequest);
    String responseContent = chatResponse.getContent();
    log.info("spark返回内容:{}",responseContent);
    return responseContent;
}

此时再运行测试代码可正常获取返回内容

然后看了源码后,也算是找到 Spark Lite 授权错误的原因,API版本枚举类(SparkApiVersion.class)中lite对应的V1_5版本中的domain属性是general 而不是 lite

为了使用免费版本的AI(仅限学习,经济压力大,学习阶段就搞付费的承受不起),自然得想方法处理。

需要注意的是,SparkApiVersion类中的构造方法是私有的,无法直接设值,所以我采用的是利用反射去修改值(不推荐,但这不对外,仅是学习AI才使用该方法;如有更好的方法,烦请告知)

编写EnumReflectionUtil工具类,用于修改枚举值

java 复制代码
public class EnumReflectionUtil {
    public static void setEnumField(Enum<?> enumConstant, String fieldName, Object newValue) throws Exception {
        Field field = enumConstant.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(enumConstant, newValue);
    }
}

修改SparkManager类

java 复制代码
@Component
@Slf4j
public class SparkManager {
    @Resource
    private SparkClient sparkClient;

    @PostConstruct
    public void init(){
        try {
            // 修改 V1_5 的版本信息
            EnumReflectionUtil.setEnumField(SparkApiVersion.V1_5, "version", "v1.1");
            EnumReflectionUtil.setEnumField(SparkApiVersion.V1_5, "url", "https://spark-api.xf-yun.com/v1.1/chat");
            EnumReflectionUtil.setEnumField(SparkApiVersion.V1_5, "domain", "lite");
        } catch (Exception e) {
            log.error("尝试修改枚举字段异常:", e);
        }
    }

    /**
     * AI生成问题的预设条件
     */
    public static final  String PRECONDITION = "" +
            "你是一名Java程序员\n" +
            "给我一些软件开发方面的知识\n";


    public String sendHttpToSpark(final String content){
        // 消息列表,可以再此列表添加历史对话记录
        List<SparkMessage> messages = new ArrayList<>();
        messages.add(SparkMessage.systemContent(PRECONDITION));
        // 用户输入内容
        messages.add(SparkMessage.userContent(content));
        // 构造请求
        SparkRequest sparkRequest = SparkRequest.builder()
                // 此时SparkApiVersion.V1_5的内容为修改后的内容
                .apiVersion(SparkApiVersion.V1_5)
                .messages(messages)     // 消息列表
                .build();
        // 同步调用
        SparkSyncChatResponse chatResponse = sparkClient.chatSync(sparkRequest);
        String responseContent = chatResponse.getContent();
        log.info("spark返回内容:{}",responseContent);
        return responseContent;
    }
}

此时再运行测试代码可正常获取返回内容,且增加的是Spark Lite的token数而非Spark4.0的,说明调用的是Spark Lite 无误

相关推荐
web182854825121 小时前
MySQL 篇 - Java 连接 MySQL 数据库并实现数据交互
java·数据库·mysql
CS创新实验室1 小时前
《机器学习数学基础》补充资料:矩阵基本子空间
人工智能·机器学习·矩阵
五行星辰1 小时前
用 Java 轻松读取 Word 文档内容
java·开发语言·word
zhyhgx2 小时前
【Spring】什么是Spring?
java·后端·spring·java-ee
G.E.N.3 小时前
DeepSeek最新图像模型Janus-Pro论文阅读
人工智能·神经网络·语言模型·自然语言处理·aigc·transformer
青椒大仙KI113 小时前
25/2/7 <机器人基础>雅可比矩阵计算 雅可比伪逆
人工智能·机器人
金融OG3 小时前
100.5 AI量化面试题:在使用LSTM预测股票价格时,如何有效处理金融时间序列的非平稳性?
大数据·人工智能·python·机器学习·金融·lstm
老余捞鱼3 小时前
用NeuralProphet预测股价:AI金融新利器(附源码)
人工智能·神经网络·金融·neuralprophe·股价预测
violin-wang3 小时前
Intellij IDEA如何查看当前文件的类
java·ide·intellij-idea
圆圆同学3 小时前
Springboot实现TLS双向认证
java·spring boot·后端