程序調用 AI 大模型 – Java
1、SDK 接入
安裝阿里云百煉SDK_大模型服務平臺百煉(Model Studio)-阿里云幫助中心
<dependency><groupId>com.alibaba</groupId><artifactId>dashscope-sdk-java</artifactId><!-- 請將 'the-latest-version' 替換為最新版本號:https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java --><version>the-latest-version</version>
</dependency>
// 建議dashscope SDK的版本 >= 2.12.0
import java.util.Arrays;
import java.lang.System;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.JsonUtils;public class Main {public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {Generation gen = new Generation();Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build();Message userMsg = Message.builder().role(Role.USER.getValue()).content("你是誰?").build();GenerationParam param = GenerationParam.builder()// 若沒有配置環境變量,請用百煉API Key將下行替換為:.apiKey("sk-xxx").apiKey(System.getenv("DASHSCOPE_API_KEY"))// 此處以qwen-plus為例,可按需更換模型名稱。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models.model("qwen-plus").messages(Arrays.asList(systemMsg, userMsg)).resultFormat(GenerationParam.ResultFormat.MESSAGE).build();return gen.call(param);}public static void main(String[] args) {try {GenerationResult result = callWithMessage();System.out.println(JsonUtils.toJson(result));} catch (ApiException | NoApiKeyException | InputRequiredException e) {// 使用日志框架記錄異常信息System.err.println("An error occurred while calling the generation service: " + e.getMessage());}System.exit(0);}
}
2、HTTP 接入
對于 SDK 不支持的編程語言或需要更靈活控制的場景,可以直接使用 HTTP 請求調用 AI 大模型的 API。
使用建議:優先使用 SDK ,不支持 SDK ,再考慮 HTTP 調用
curl --location "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation" \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header "Content-Type: application/json" \
--data '{"model": "qwen-plus","input":{"messages":[ {"role": "system","content": "You are a helpful assistant."},{"role": "user","content": "你是誰?"}]},"parameters": {"result_format": "message"}
}'
轉換為使用Hutool工具類的Java代碼
package com.ping.aiagent.demo.invoke;import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ping.aiagent.contant.TestAPI;/*** HTTP 方式調用 AI*/
public class DashscopeRequest {public static void main(String[] args) {// API密鑰String apiKey = TestAPI.API_KEY;// 構建請求URLString url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";// 構建請求JSON體JSONObject requestBody = new JSONObject();requestBody.set("model", "qwen-plus");JSONObject input = new JSONObject();// 創建消息數組JSONArray messages = new JSONArray();// 添加系統消息messages.add(new JSONObject().set("role", "system").set("content", "You are a helpful assistant."));// 添加用戶消息messages.add(new JSONObject().set("role", "user").set("content", "你是誰?"));input.set("messages", messages);JSONObject parameters = new JSONObject();parameters.set("result_format", "message");requestBody.set("input", input);requestBody.set("parameters", parameters);// 發送POST請求String response = HttpRequest.post(url).header("Authorization", "Bearer " + apiKey).header("Content-Type", "application/json").body(requestBody.toString()).timeout(20000).execute().body();System.out.println(response);}
}
3、Spring AI
Spring AI 是 Spring 生態系統的新成員,旨在簡化 AI 功能與 Spring 應用的集成。Spring AI 官方文檔
Spring AI 默認沒有支持所有的大模型(尤其是國產的)。
Spring AI AlibabaSpring AI Alibaba 官網_快速構建 JAVA AI 應用
阿里對 Spring AI 做了一個兼容和升級,可以更好的和阿里系的大模型兼容。
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId><version>1.0.0-M5.1</version>
</dependency><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository>
</repositories>
更改配置文件
spring:application:name: ping-ai-agentai:dashscope:api-key: < API KEY >chat:options:model: qwq-plus
package com.ping.aiagent.demo.invoke;import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;/*** Spring AI 模型框架調用 AI 大模型*/
@Component
public class SpringAiAiInvoke implements CommandLineRunner {@Resourceprivate ChatModel dashscopeChatModel; // 先通過名稱 找不到再通過類型 一定要是這個名稱// 還可以通過 ChatClient 對話客戶端的方式去調用 能夠提供更多的高級 AI 交互功能@Overridepublic void run(String... args) throws Exception {AssistantMessage assistantMessage = dashscopeChatModel.call(new Prompt("你好呀")).getResult().getOutput(); // 取出 getResult 對象的內容System.out.println(assistantMessage.getText()); // 拿到文本響應}
}
4、LangChain4j
知名 AI 框架 LangChain 的 Java 版本。
LangChain 官方是沒有支持阿里系大模型的,只能用社區版本整合的大模型包。LangChain4j模型集成。
接入阿里云靈積模型,參考官方文檔:DashScope 模型集成。
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-dashscope</artifactId><version>1.0.0-beta2</version>
</dependency>
本地部署和接入 AI 大模型
1、本地安裝大模型。
官網安裝
無需自己執行腳本安裝,也省去了復雜的環境配置。
Ollama 不僅提供了友好的命令行界面,還支持 API 調用,方便與各種應用程序集成。參考:官方 API 文檔。
檢測模型是否運行:localhost:11434。
2、Spring AI 調用 Ollama 大模型
Spring AI 原生支持調用 Ollama 大模型,直接參考 [官方文檔](Ollama-阿里云Spring AI Alibaba官網官網) 編寫配置和代碼即可。
配置依賴。
<!-- https://java2ai.com/docs/1.0.0-M6.1/models/ollama/ -->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-ollama-spring-boot-starter</artifactId><version>1.0.0-M6</version>
</dependency><!-- 需要引入倉庫配置,才能下載到最新的 Spring AI 的相關依賴 -->
<repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository>
</repositories>
調用配置
spring:ai:ollama:base-url: http://localhost:11434chat:model: llama3
擴展:火山引擎
火山方舟管理控制臺
1、HTTP 接入
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \-H "Content-Type: application/json" \-H "Authorization: Bearer <Your Api Key>" \-d $'{"model": "doubao-seed-1-6-250615","messages": [{"content": [{"image_url": {"url": "https://ark-project.tos-cn-beijing.ivolces.com/images/view.jpeg"},"type": "image_url"},{"text": "圖片主要講了什么?","type": "text"}],"role": "user"}]
}'
轉換為使用Hutool工具類的Java代碼
package com.ping.aiagent.demo.invoke;import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ping.aiagent.contant.TestAPI;public class VolcengineImageChat {public static void main(String[] args) {String url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";String token = TestAPI.VolcengineImageChat_Api_KET;if (token == null || token.trim().isEmpty()) {throw new IllegalArgumentException("API密鑰不能為空");}String imageUrl = "https://cdn.jsdmirror.com/gh/qiuping01/my-images/202508191817326.jpg";try {int statusCode = HttpRequest.get(imageUrl).timeout(10000).execute().getStatus();if (statusCode != 200) {System.err.println("警告: 圖片URL可能無法訪問,狀態碼: " + statusCode);}} catch (Exception e) {System.err.println("警告: 無法驗證圖片URL: " + e.getMessage());}JSONObject requestBody = new JSONObject();requestBody.set("model", "doubao-seed-1-6-250615");JSONArray messages = new JSONArray();JSONArray contentArray = new JSONArray();JSONObject imageObject = new JSONObject();imageObject.set("type", "image_url");JSONObject imageUrlObject = new JSONObject();imageUrlObject.set("url", imageUrl);imageObject.set("image_url", imageUrlObject);contentArray.add(imageObject);JSONObject textObject = new JSONObject();textObject.set("type", "text");textObject.set("text", "圖片主要講了什么?");contentArray.add(textObject);JSONObject userMessage = new JSONObject();userMessage.set("role", "user");userMessage.set("content", contentArray);messages.add(userMessage);requestBody.set("messages", messages);int maxRetries = 3;int retryCount = 0;String response = null;while (retryCount < maxRetries) {try {System.out.println("發送請求到: " + url);long startMs = System.currentTimeMillis();response = HttpRequest.post(url).header("Content-Type", "application/json").header("Authorization", "Bearer " + token).body(requestBody.toString()).timeout(120000).execute().body();long costMs = System.currentTimeMillis() - startMs;// 直觀輸出printPrettyResponse(response, imageUrl, "圖片主要講了什么?", costMs);break;} catch (Exception e) {retryCount++;System.err.println("請求失敗,第 " + retryCount + " 次重試...");System.err.println("錯誤信息: " + e.getMessage());if (retryCount >= maxRetries) {System.err.println("已達到最大重試次數,放棄請求");throw new RuntimeException("請求失敗,已達到最大重試次數", e);}try {Thread.sleep(2000L * retryCount);} catch (InterruptedException ie) {Thread.currentThread().interrupt();throw new RuntimeException("重試等待被中斷", ie);}}}}private static void printPrettyResponse(String response, String imageUrl, String userQuestion, long costMs) {if (response == null || response.isEmpty()) {System.out.println("未收到響應");return;}JSONObject resp;try {resp = JSONUtil.parseObj(response);} catch (Exception e) {System.out.println("收到非JSON響應,原始內容:\n" + response);return;}// 錯誤處理if (resp.containsKey("error")) {JSONObject error = resp.getJSONObject("error");System.out.println("\n================== 豆包 AI 響應(錯誤) ==================");System.out.println("錯誤代碼: " + error.getStr("code", "-"));System.out.println("錯誤信息: " + error.getStr("message", "-"));System.out.println("原始響應(JSON):\n" + JSONUtil.toJsonPrettyStr(resp));System.out.println("========================================================");return;}String id = resp.getStr("id", "-");String model = resp.getStr("model", "-");JSONObject usage = resp.getJSONObject("usage");Integer promptTokens = usage.getInt("prompt_tokens", null);Integer completionTokens = usage.getInt("completion_tokens", null);Integer totalTokens = usage.getInt("total_tokens", null);// 提取助手回答(兼容字符串或分段數組)String assistantAnswer = extractAssistantAnswer(resp);System.out.println("\n================== 豆包 AI 響應(已格式化) ===============");System.out.println("請求信息");System.out.println("- 圖片URL : " + imageUrl);System.out.println("- 用戶問題 : " + userQuestion);System.out.println("- 耗時 : " + costMs + " ms");System.out.println("\n元信息");System.out.println("- 請求ID : " + id);System.out.println("- 模型 : " + model);if (promptTokens != null || completionTokens != null || totalTokens != null) {System.out.println("- Token用量 : prompt=" + safeInt(promptTokens)+ ", completion=" + safeInt(completionTokens)+ ", total=" + safeInt(totalTokens));}System.out.println("\n助手回答");System.out.println(assistantAnswer == null || assistantAnswer.isEmpty() ? "(空)" : assistantAnswer);System.out.println("\n原始響應(JSON)"); // 便于排查System.out.println(JSONUtil.toJsonPrettyStr(resp));System.out.println("========================================================\n");}private static String extractAssistantAnswer(JSONObject resp) {try {JSONArray choices = resp.getJSONArray("choices");if (choices == null || choices.isEmpty()) {return "";}JSONObject first = choices.getJSONObject(0);if (first == null) return "";JSONObject message = first.getJSONObject("message");if (message == null) return "";Object content = message.get("content");if (content == null) return "";// 可能是字符串if (content instanceof CharSequence) {return String.valueOf(content).trim();}// 也可能是數組(多模態分段)if (content instanceof JSONArray) {JSONArray parts = (JSONArray) content;StringBuilder builder = new StringBuilder();for (int i = 0; i < parts.size(); i++) {JSONObject part = parts.getJSONObject(i);String type = part.getStr("type", "");if ("text".equalsIgnoreCase(type)) {builder.append(part.getStr("text", ""));} else if ("image_url".equalsIgnoreCase(type)) {JSONObject img = part.getJSONObject("image_url");String url = img == null ? "" : img.getStr("url", "");builder.append("\n[圖片] ").append(url);}}return builder.toString().trim();}return String.valueOf(content).trim();} catch (Exception e) {return "";}}private static String safeInt(Integer v) {return v == null ? "-" : String.valueOf(v);}
}
2、SDK 調用
<dependency><groupId>com.volcengine</groupId><artifactId>volcengine-java-sdk-ark-runtime</artifactId><version>LATEST</version>
</dependency>
package com.volcengine.ark.runtime;import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionContentPart;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionRequest;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessage;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessageRole;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;// 請確保您已將 API Key 存儲在環境變量 ARK_API_KEY 中
// 初始化Ark客戶端,從環境變量中讀取您的API Key
public class ChatCompletionsVisionExample {// 從環境變量中獲取您的 API Key。此為默認方式,您可根據需要進行修改static String apiKey = System.getenv("ARK_API_KEY");// 此為默認路徑,您可根據業務所在地域進行配置static String baseUrl = "https://ark.cn-beijing.volces.com/api/v3";static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);static Dispatcher dispatcher = new Dispatcher();static ArkService service = ArkService.builder().dispatcher(dispatcher).connectionPool(connectionPool).baseUrl(baseUrl).apiKey(apiKey).build();public static void main(String[] args) {System.out.println("----- image input -----");final List<ChatMessage> messages = new ArrayList<>();final List<ChatCompletionContentPart> multiParts = new ArrayList<>();multiParts.add(ChatCompletionContentPart.builder().type("image_url").imageUrl(new ChatCompletionContentPart.ChatCompletionContentPartImageURL("https://ark-project.tos-cn-beijing.ivolces.com/images/view.jpeg")).build());multiParts.add(ChatCompletionContentPart.builder().type("text").text("這是哪里?").build());final ChatMessage userMessage = ChatMessage.builder().role(ChatMessageRole.USER).multiContent(multiParts).build();messages.add(userMessage);ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()// 指定您創建的方舟推理接入點 ID,此處已幫您修改為您的推理接入點 ID.model("doubao-seed-1-6-250615").messages(messages).build();service.createChatCompletion(chatCompletionRequest).getChoices().forEach(choice -> System.out.println(choice.getMessage().getContent()));service.shutdownExecutor();}
}