尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Java实战:从零集成千帆大模型API,构建智能对话应用

Java实战:从零集成千帆大模型API,构建智能对话应用 1. 环境准备与项目搭建第一次接触千帆大模型API时我花了两天时间才把环境配好。为了让你们少走弯路我把踩过的坑都总结在这里。首先确保你的开发环境满足以下条件JDK 1.8或更高版本推荐JDK 11Maven 3.6用于依赖管理IntelliJ IDEA或Eclipse我用的是IDEA 2023.2创建Maven项目时有个小技巧不要直接用IDE自带的模板。我习惯用命令行先初始化基础结构mvn archetype:generate -DgroupIdcom.yourcompany -DartifactIdqa-bot -DarchetypeArtifactIdmaven-archetype-quickstart -DinteractiveModefalse然后在pom.xml里添加这些必备依赖比官方文档多加了几个实用工具dependencies !-- 核心HTTP客户端 -- dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.11.0/version /dependency !-- JSON处理 -- dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version2.0.34/version /dependency !-- 日志记录 -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-api/artifactId version2.0.7/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.4.8/version /dependency !-- 开发效率工具 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.28/version scopeprovided/scope /dependency !-- 单元测试 -- dependency groupIdorg.junit.jupiter/groupId artifactIdjunit-jupiter/artifactId version5.9.3/version scopetest/scope /dependency /dependencies配置日志时有个坑要注意在resources目录下新建logback.xml文件内容如下configuration appender nameSTDOUT classch.qos.logback.core.ConsoleAppender encoder pattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern /encoder /appender root levelDEBUG appender-ref refSTDOUT / /root /configuration2. 获取AccessToken实战千帆API的所有调用都需要AccessToken相当于你的临时身份证。我刚开始没仔细看文档直接拿API Key去调接口结果返回401错误折腾了半天。2.1 申请API密钥登录百度智能云控制台进入「千帆大模型平台」在「应用接入」页面创建新应用记录下API Key和Secret Key注意Secret Key只在创建时显示一次务必立即保存。我有次忘记保存不得不重新创建应用。2.2 实现Token获取类创建TokenUtil.java时要注意几个关键点import lombok.extern.slf4j.Slf4j; import okhttp3.*; import java.io.IOException; Slf4j public class TokenUtil { private static final String TOKEN_URL https://aip.baidubce.com/oauth/2.0/token; private final String apiKey; private final String secretKey; private final OkHttpClient client; public TokenUtil(String apiKey, String secretKey) { this.apiKey apiKey; this.secretKey secretKey; this.client new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); } public String getToken() throws QfanException { HttpUrl.Builder urlBuilder HttpUrl.parse(TOKEN_URL).newBuilder() .addQueryParameter(grant_type, client_credentials) .addQueryParameter(client_id, apiKey) .addQueryParameter(client_secret, secretKey); Request request new Request.Builder() .url(urlBuilder.build()) .post(RequestBody.create(, MediaType.get(application/json))) .addHeader(Content-Type, application/json) .addHeader(Accept, application/json) .build(); try (Response response client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new QfanException(获取Token失败: response.code()); } String body response.body().string(); JSONObject json JSON.parseObject(body); if (json.containsKey(error)) { throw new QfanException(json.getString(error_description)); } String token json.getString(access_token); log.debug(获取到Token: {}, token.substring(0, 10) ...); return token; } catch (IOException e) { throw new QfanException(网络请求异常, e); } } }测试时发现一个典型问题Token有效期默认是30天但实际项目中应该实现自动刷新机制。我改进后的方案是public class TokenHolder { private String currentToken; private long expireTime; private final TokenUtil tokenUtil; public TokenHolder(TokenUtil tokenUtil) { this.tokenUtil tokenUtil; } public synchronized String getValidToken() throws QfanException { if (currentToken null || System.currentTimeMillis() expireTime - 60000) { refreshToken(); } return currentToken; } private void refreshToken() throws QfanException { currentToken tokenUtil.getToken(); expireTime System.currentTimeMillis() 29 * 24 * 3600 * 1000L; // 提前1天刷新 } }3. 封装对话API服务直接调用原生API太麻烦我封装了一个更易用的服务层。先定义消息实体类Data AllArgsConstructor NoArgsConstructor public class ChatMessage { /** * 角色类型user/assistant */ private String role; /** * 消息内容 */ private String content; /** * 创建用户消息的快捷方法 */ public static ChatMessage user(String content) { return new ChatMessage(user, content); } /** * 创建助手消息的快捷方法 */ public static ChatMessage assistant(String content) { return new ChatMessage(assistant, content); } }然后实现核心的对话服务。这里我增加了重试机制和超时控制public class ChatService { private static final String CHAT_ENDPOINT https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant; private final TokenHolder tokenHolder; private final OkHttpClient client; public ChatService(TokenHolder tokenHolder) { this.tokenHolder tokenHolder; this.client new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); } public String chat(ListChatMessage history, String newMessage) throws QfanException { // 构造完整对话历史 ListMapString, String messages new ArrayList(); history.forEach(msg - messages.add(Map.of( role, msg.getRole(), content, msg.getContent() ))); messages.add(Map.of(role, user, content, newMessage)); // 构造请求体 MapString, Object requestBody new HashMap(); requestBody.put(messages, messages); requestBody.put(temperature, 0.7); requestBody.put(top_p, 0.8); Request request new Request.Builder() .url(CHAT_ENDPOINT ?access_token tokenHolder.getValidToken()) .post(RequestBody.create( JSON.toJSONString(requestBody), MediaType.get(application/json) )) .build(); // 带重试的请求执行 int retry 0; while (retry 3) { try (Response response client.newCall(request).execute()) { String body response.body().string(); JSONObject json JSON.parseObject(body); if (response.isSuccessful()) { return json.getString(result); } if (json.getInteger(error_code) 110) { // Token过期 tokenHolder.refreshToken(); retry; continue; } throw new QfanException(json.getString(error_msg)); } catch (IOException e) { if (retry 3) { throw new QfanException(API请求失败, e); } } } throw new QfanException(超过最大重试次数); } }4. 构建交互式命令行应用最后我们把这些封装好的组件组合起来创建一个可以实际运行的对话程序。我增加了上下文保持和历史记录功能public class ChatApp { private static final int MAX_HISTORY 10; private final ChatService chatService; private final ListChatMessage history new ArrayList(); public ChatApp(ChatService chatService) { this.chatService chatService; } public void start() { System.out.println(千帆对话助手已启动输入exit退出); Scanner scanner new Scanner(System.in); while (true) { System.out.print(\n你); String input scanner.nextLine().trim(); if (input.equalsIgnoreCase(exit)) { break; } try { String response chatService.chat(history, input); System.out.println(AI response); // 维护对话历史 history.add(ChatMessage.user(input)); history.add(ChatMessage.assistant(response)); if (history.size() MAX_HISTORY * 2) { history.subList(0, 2).clear(); // 移除最早的问答对 } } catch (Exception e) { System.err.println(出错 e.getMessage()); } } scanner.close(); System.out.println(对话已结束); } }启动类这样写public class Main { public static void main(String[] args) { try { // 从环境变量读取配置 String apiKey System.getenv(QIANFAN_API_KEY); String secretKey System.getenv(QIANFAN_SECRET_KEY); TokenUtil tokenUtil new TokenUtil(apiKey, secretKey); TokenHolder tokenHolder new TokenHolder(tokenUtil); ChatService chatService new ChatService(tokenHolder); new ChatApp(chatService).start(); } catch (Exception e) { System.err.println(系统初始化失败 e.getMessage()); e.printStackTrace(); } } }实际运行效果千帆对话助手已启动输入exit退出 你Java如何读取文件 AI在Java中可以使用以下几种方式读取文件内容 1. 使用BufferedReader try (BufferedReader br new BufferedReader(new FileReader(file.txt))) { String line; while ((line br.readLine()) ! null) { System.out.println(line); } } 2. 使用Files工具类 String content Files.readString(Path.of(file.txt)); 3. 使用Scanner类... 你哪种方式性能最好 AI对于大文件读取性能从高到低排序通常是 1. Files.readAllBytes() - 最快速但消耗内存 2. BufferedReader - 内存友好 3. Scanner - 功能多但速度慢 具体选择取决于你的使用场景...这个实现包含了我在实际项目中总结的几个实用技巧使用环境变量存储敏感信息避免硬编码对话历史采用滑动窗口机制防止上下文过长为网络请求添加合理的超时和重试策略完善的错误处理和日志记录如果你需要扩展到Web应用只需要把ChatApp替换为Controller即可。我已经用Spring Boot实现了Web版代码结构基本一致只是把命令行交互改成了HTTP接口。
返回列表