【异常记录Java-20250204】调用讯飞星火AI(Spark lite 版本)Api 授权错误问题处理
问题重现
-
依赖
<!--讯飞开放平台sdk--> <dependency> <groupId>io.github.briqt</groupId> <artifactId>xunfei-spark4j</artifactId> <version>1.3.0</version> </dependency>
-
yml配置文件
# 讯飞Api配置 xunfei: client: appId: "别只顾着抄,这里要写自己的" apiKey: "别只顾着抄,这里要写自己的" apiSecret: "别只顾着抄,这里要写自己的"
-
SparkConfig 配置类
@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 实现类
@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 对话,但遗憾的是出了意外
- 测试代码
@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数,刚好可以拿来做验证
修改指定请求版本
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工具类,用于修改枚举值
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类
@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 无误