背景

如果你的项目使用 JDK 17+,推荐学习 Spring AI 框架。本篇以 JDK 8 项目为例,手搓 AI 接口的接入。

依赖引入

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Gson for JSON processing -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
<!-- HttpClient for making HTTP requests -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.3</version>
</dependency>

AI 配置类

建议单独开一个配置类,后续可通过 Nacos 等方式动态更新:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AIConfig {
private String apiKey;
private String model;
private String URL;
private Double temperature;

public AIConfig() {
URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
apiKey = "sk-xxx";
model = "qwen-plus";
temperature = 0.8;
}
}

实体类

1
2
3
4
5
6
7
8
9
10
public class AIMessage {
private String role; // system / user
private String content;
}

public class AIRequst {
private String model;
private List<AIMessage> messages;
private double temperature;
}

核心调用实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public ResultBody AIImport(String userId, String issue) {
String key = "AI_" + userId;
Object cacheObject = redisService.getCacheObject(key);
String contextInfo = (cacheObject != null) ? (String) cacheObject : "";

AIRequst openaiReq = new AIRequst();
openaiReq.setModel(aiConfig.getModel());

List<AIMessage> messages = new ArrayList<>();
AIMessage systemMessage = new AIMessage();
systemMessage.setRole("system");
systemMessage.setContent("你是一个语音聊天助手,会讲冷笑话、鬼故事等。");
messages.add(systemMessage);

AIMessage userMessage = new AIMessage();
userMessage.setRole("user");
userMessage.setContent(String.format("上下文信息:\n%s\n\n用户问题:%s", contextInfo, issue));
messages.add(userMessage);

openaiReq.setMessages(messages);
openaiReq.setTemperature(aiConfig.getTemperature());

Gson gson = new Gson();
String jsonRequest = gson.toJson(openaiReq);

try {
URL url = new URL(aiConfig.getURL());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "Bearer " + aiConfig.getApiKey());
connection.setDoOutput(true);

try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonRequest.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}

JsonObject jsonResponse = gson.fromJson(response.toString(), JsonObject.class);
if (jsonResponse.getAsJsonArray("choices").isEmpty()) {
return ResultBody.error().message("AI 响应超时...");
}

JsonObject choice = jsonResponse.getAsJsonArray("choices").get(0).getAsJsonObject();
JsonObject message = choice.getAsJsonObject("message");
String answer = message.get("content").getAsString().trim();

if (answer.isEmpty()) {
return ResultBody.error().message("AI 响应超时");
}

redisService.setCacheObject(key, issue, 300L, TimeUnit.MINUTES);
return ResultBody.ok().message(answer);
}
} else {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) {
StringBuilder errorResponse = new StringBuilder();
String errorLine;
while ((errorLine = br.readLine()) != null) {
errorResponse.append(errorLine.trim());
}
System.err.println("错误响应: " + errorResponse);
}
return ResultBody.error().message("AI 响应超时...");
}
} catch (IOException e) {
e.printStackTrace();
return ResultBody.error().message("AI 响应超时");
}
}

小结

  • JDK 8 项目可通过 HttpURLConnection 手搓 AI 接口,不需要额外框架
  • 注意提取 AI 配置为独立配置类,方便后续热更新
  • 结合 Redis 缓存上下文信息,实现简单的对话记忆

参考:CSDN - Java接入AI接口