尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Java调用Google PaLM API实战:文本生成、对话与Embedding集成

Java调用Google PaLM API实战:文本生成、对话与Embedding集成 生成式 AI 的应用越来越广但大量实战教程默认使用 PythonJava 开发者经常要自己翻译示例、处理依赖冲突、排查鉴权问题。这篇文章围绕 Google PaLM API从环境配置到 Java 代码集成完整走一遍文本生成、多轮对话和向量 Embedding 的开发流程。只要你掌握 Java 基础想快速把大模型能力集成到 Web 或 Spring Boot 项目中这篇文章可以直接作为起步参考。1. 生成式 AI 与 PaLM API 核心概念1.1 什么是生成式 AI生成式 AI 是一类能够根据输入内容生成全新文本、代码、图片等内容的人工智能技术。它和大数据时代常见的信息抽取、分类、推荐不同核心能力是“创作”。在文本领域这类模型通常被称为大型语言模型Large Language Model简称 LLM它通过大规模语料训练学会了词语之间的统计规律因此可以根据一段输入预测后续内容。对于 Java 开发者而言生成式 AI 并不神秘。你可以把它理解成一个“增强版的文本处理服务”你发送一个包含问题或指令的请求模型返回一段预测结果。真正的难点不在算法而在工程化如何把模型能力安全、稳定地嵌入已有系统如何处理超时、限流、异常如何通过 Prompt 控制输出质量。这些恰恰是 Java 后端开发者擅长的事情。1.2 PaLM API 能做什么Google PaLM API 是 Google 提供的生成式 AI 接口基于 PaLM 2 系列模型提供文本生成、多轮对话、文本向量化等能力。它的典型使用场景包括内容生成自动生成文章草稿、会议纪要、产品文案。代码辅助根据注释生成代码片段或者解释一段复杂方法的逻辑。智能客服通过多轮对话维护上下文回答用户问题。企业知识库将文档切块后转为 Embedding 向量再通过相似度检索实现“文档问答”。相比从零训练一个大模型调用 PaLM API 的成本更低、接入周期更短。你不需要 GPU也不需要维护模型环境只需要在网络可访问的环境中发起 HTTPS 请求即可。1.3 Java 开发者为什么要关注很多团队的核心业务系统是 Java 技术栈但生成式 AI 的官方示例却以 Python 为主。如果你只依赖 Python 脚本很难把它嵌入到现有的订单、权限、用户体系中。学会用 Java 调用生成式 AI 接口有以下几方面价值团队无需引入新的服务端语言统一技术栈降低维护成本。Java 生态的成熟框架可以直接复用比如 Spring Boot 的配置管理、日志、熔断、限流能力。对事务、幂等、并发控制等工程问题Java 生态有更完整的解决方案。可以把 AI 能力封装成内部 RPC 或 HTTP 服务供多个业务方复用。换句话说对于正处在 Java 学习路线中后段的开发者来说把生成式 AI 纳入自己的工具箱比单独学一套 Python 推理框架要更贴合业务落地场景。2. 环境准备与版本说明2.1 运行环境要求本文的示例项目使用 Java 11 以上版本通过 Maven 管理依赖核心 HTTP 调用使用 JDK 自带的java.net.http.HttpClient不需要额外引入 Spring 或第三方 HTTP 框架。需要准备的环境如下JDK 11 或更高版本推荐 JDK 17。Maven 3.6 以上或者直接使用 IDE 内嵌的 Maven。一个可以发起外呼 HTTPS 请求的网络环境。需要注意generativelanguage.googleapis.com是 Google 的服务域名如果你的办公网络限制外呼请向网络管理员确认是否放行。在代码层面不要尝试绕过安全策略而是通过正常的网络审批流程解决。JAVA_HOME 和 PATH 的配置属于 Java 基础环境问题。如果你在启动项目时遇到“无法加载主类”或“mvn 不是内部命令”的提示可以优先检查环境变量是否配置正确。2.2 获取 API Key调用 PaLM API 需要 API Key获取路径一般通过 Google AI Studio 的控制台创建。创建过程和大多数云平台类似登录 Google AI Studio。进入 API Key 管理页面。点击创建新 Key并选择对应的 Google Cloud 项目。复制 Key 并妥善保存。需要注意API Key 是敏感凭证必须避免提交到 Git 仓库。建议通过环境变量注入或者使用配置中心管理。在本地开发时可以把 Key 写进 IDE 的环境变量配置里。2.3 配置环境变量为了安全示例代码会从环境变量PALM_API_KEY中读取 Key。Linux 或 macOS 可以使用下面的命令export PALM_API_KEY你的APIKeyWindows 的 CMD 环境可以使用set PALM_API_KEY你的APIKey如果是 IDEA可以在 Run Configuration 的 Environment variables 中新增PALM_API_KEY。这样配置之后代码中不需要出现明文 Key也方便后续切换到不同项目的 Key。2.4 创建 Maven 项目本文的示例项目结构如下palm-api-demo ├── pom.xml └── src/main/java/com/example/palm ├── PalmApiClient.java ├── TextGenerationDemo.java ├── ChatDemo.java └── EmbeddingDemo.javaPalmApiClient负责封装 HTTP 调用和 JSON 解析三个 Demo 分别演示文本生成、对话和 Embedding。示例代码在编写时考虑了可读性不追求过度抽象便于你复制后快速验证。下面先创建pom.xmlproject xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdpalm-api-demo/artifactId version1.0-SNAPSHOT/version packagingjar/packaging properties maven.compiler.source11/maven.compiler.source maven.compiler.target11/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties dependencies dependency groupIdcom.google.code.gson/groupId artifactIdgson/artifactId version2.10.1/version /dependency /dependencies build plugins plugin groupIdorg.codehaus.mojo/groupId artifactIdexec-maven-plugin/artifactId version3.1.0/version /plugin /plugins /build /project这里使用 Gson 解析 JSON比手写String.replace更可靠。版本不需要刻意追求最新使用稳定的 2.10.1 即可。3. PaLM API 核心原理解析3.1 端点与模型PaLM API 是 REST 风格接口。你可以把它理解为向某个模型 URL 发送一个 POST 请求请求体里包含 Prompt 和生成参数响应体里则是模型生成的结果。以文本生成为例HTTP 请求结构如下请求方法POST请求路径https://generativelanguage.googleapis.com/v1beta2/models/{model}:generateText鉴权方式URL Query 参数key或AuthorizationHeader请求体JSON 格式的 Prompt 和参数常用的模型名包括模型名称能力典型场景text-bison-001通用文本生成文章撰写、代码生成、文本摘要chat-bison-001多轮对话客服机器人、助手embedding-gecko-001文本向量化知识库检索、语义匹配实际可用的模型列表会随账号和服务状态变化。如果你在调用的过程中遇到model not found错误可以前往官方文档查看当前账号可用的模型名再替换代码中的常量。3.2 请求体结构文本生成请求体包含一个prompt字段以及temperature、candidateCount、maxOutputTokens等参数。prompt必填开发者输入的指令或问题。temperature控制随机性。值越大输出越自由值越小输出越确定一般在 0.2 到 0.8 之间。candidateCount希望返回的候选结果数量通常设为 1。maxOutputTokens限制最多生成的 Token 数量默认值根据模型而定。对话模型的请求体略有不同包含prompt.context、prompt.messages等字段。context用来设定模型的角色或系统指令messages用来传递对话历史。Embedding 模型的请求体最简单通常只需要传入text字段返回结果会是一个浮点数数组也就是文本向量。3.3 响应体结构文本生成响应中核心内容在candidates数组中。数组的第一个元素包含output字段值就是生成文本。对话响应的每个候选人包含content字段。Embedding 响应一般包含embedding.value数组。这些字段是解析代码的依据。在实际开发中建议先打印原始响应 JSON再决定解析逻辑避免因为接口升级导致隐式错误。4. 实战Java 调用 PaLM API 实现文本生成4.1 编写 HTTP 客户端封装类在src/main/java/com/example/palm下创建PalmApiClient.java它负责发送 POST 请求并解析响应。这里使用 JDK 自带的HttpClient可以避免额外引入 OkHttp 或 Feign。package com.example.palm; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.List; public class PalmApiClient { private static final String API_BASE https://generativelanguage.googleapis.com/v1beta2; private final String apiKey; private final HttpClient httpClient; public PalmApiClient(String apiKey) { this.apiKey apiKey; this.httpClient HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(30)) .build(); } public String generateText(String model, String prompt, double temperature, int maxOutputTokens) throws Exception { JsonObject requestBody new JsonObject(); JsonObject promptObj new JsonObject(); promptObj.addProperty(text, prompt); requestBody.add(prompt, promptObj); requestBody.addProperty(temperature, temperature); requestBody.addProperty(candidateCount, 1); requestBody.addProperty(maxOutputTokens, maxOutputTokens); String endpoint API_BASE /models/ model :generateText?key apiKey; String response post(endpoint, requestBody.toString()); JsonObject root JsonParser.parseString(response).getAsJsonObject(); JsonArray candidates root.getAsJsonArray(candidates); if (candidates null || candidates.size() 0) { return ; } JsonObject candidate candidates.get(0).getAsJsonObject(); return candidate.get(output).getAsString(); } public String chat(String model, String context, ListString messages) throws Exception { JsonObject requestBody new JsonObject(); JsonObject promptObj new JsonObject(); if (context ! null !context.isBlank()) { promptObj.addProperty(context, context); } JsonArray messagesArr new JsonArray(); for (String message : messages) { JsonObject messageObj new JsonObject(); messageObj.addProperty(content, message); messagesArr.add(messageObj); } promptObj.add(messages, messagesArr); requestBody.add(prompt, promptObj); String endpoint API_BASE /models/ model :generateMessage?key apiKey; String response post(endpoint, requestBody.toString()); JsonObject root JsonParser.parseString(response).getAsJsonObject(); JsonArray candidates root.getAsJsonArray(candidates); if (candidates null || candidates.size() 0) { return ; } JsonObject candidate candidates.get(0).getAsJsonObject(); return candidate.get(content).getAsString(); } public float[] embedText(String model, String text) throws Exception { JsonObject requestBody new JsonObject(); requestBody.addProperty(text, text); String endpoint API_BASE /models/ model :embedText?key apiKey; String response post(endpoint, requestBody.toString()); JsonObject root JsonParser.parseString(response).getAsJsonObject(); JsonArray value root.getAsJsonObject(embedding).getAsJsonArray(value); float[] result new float[value.size()]; for (int i 0; i value.size(); i) { result[i] value.get(i).getAsFloat(); } return result; } private String post(String url, String json) throws Exception { HttpRequest request HttpRequest.newBuilder() .uri(URI.create(url)) .header(Content-Type, application/json; charsetutf-8) .POST(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8)) .build(); HttpResponseString response httpClient.send( request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8) ); if (response.statusCode() ! 200) { throw new RuntimeException(调用 PaLM API 失败HTTP response.statusCode() 响应 response.body()); } return response.body(); } }这段代码的核心逻辑是构建 JSON 请求体发送 POST 请求然后从响应中提取生成内容。post方法会统一校验 HTTP 状态码如果不是 200就抛出包含响应体的异常方便排查问题。需要注意PalmApiClient并不是线程安全的 HTTP 客户端专用工具但HttpClient本身是线程安全的。在实际项目中你完全可以把它注册成 Spring 单例 Bean多个调用方共用同一个实例。4.2 编写文本生成 Demo在同一个包下创建TextGenerationDemo.javapackage com.example.palm; public class TextGenerationDemo { public static void main(String[] args) throws Exception { String apiKey System.getenv(PALM_API_KEY); if (apiKey null || apiKey.isBlank()) { throw new IllegalArgumentException( 请先配置环境变量 PALM_API_KEY再运行本示例。 ); } PalmApiClient client new PalmApiClient(apiKey); String prompt 用 Java 写一个线程池示例并解释核心参数。; String result client.generateText(text-bison-001, prompt, 0.7, 1024); System.out.println(模型生成内容); System.out.println(result); } }这个 Demo 的功能非常简单从环境变量读取 API Key调用generateText打印结果。提示词可以任意替换比如让它生成代码、整理文案、做翻译。4.3 运行与验证在项目根目录执行mvn -q compile exec:java -Dexec.mainClasscom.example.palm.TextGenerationDemo如果环境变量没有配好程序会直接抛出异常提示。如果网络和 Key 正常你会看到类似下面的输出模型生成内容 可以使用 ThreadPoolExecutor 创建线程池核心参数包括 - corePoolSize核心线程数...由于生成模型的输出具有随机性实际内容不会每次完全一致。这一点是正常的因为temperature参数允许模型在概率范围内自由选择。5. 实战Java 调用 PaLM API 实现多轮对话5.1 聊天模型与文本生成模型的区别文本生成模型只关注当前 Prompt聊天模型则额外支持context和消息历史。context是系统级指令比如“你是一位耐心的 Java 技术导师”“你是一个电商客服助手”。这会让模型在每轮对话中都保持固定角色。与直接拼接历史文本相比PaLM API 的消息结构更清晰。你可以把历史消息放入messages数组最后一条通常是用户当前的问题。下面示例中的代码会在每次请求时把整段历史发送给模型。5.2 多轮对话 Java 示例创建ChatDemo.javapackage com.example.palm; import java.util.ArrayList; import java.util.List; public class ChatDemo { public static void main(String[] args) throws Exception { String apiKey System.getenv(PALM_API_KEY); if (apiKey null || apiKey.isBlank()) { throw new IllegalArgumentException(请先配置环境变量 PALM_API_KEY。); } PalmApiClient client new PalmApiClient(apiKey); String context 你是一位耐心的 Java 技术导师回答问题尽量简洁。; ListString messages new ArrayList(); messages.add(请用一句话告诉我什么是 Spring Boot。); messages.add(那它和 Spring Framework 是什么关系); String reply client.chat(chat-bison-001, context, messages); System.out.println(AI 回复); System.out.println(reply); } }这里故意发了两条“用户”消息用来演示消息数组的组装方式。在实际业务中你应该把用户和 AI 的历史消息都传进去让模型具备完整上下文记忆。比如第一轮messages只有用户问题得到回复后把问题和回复都加入messages再追加新的用户问题。运行命令mvn -q compile exec:java -Dexec.mainClasscom.example.palm.ChatDemo如果接口调用成功控制台会输出一段符合上下文的回复。因为 PaLM API 对对话历史的字段要求比较严格如果遇到参数错误可以打印请求体 JSON 逐项核对。尤其注意消息角色字段不同版本的 API 可能要求显式设置author或类似角色字段。6. 实战使用 Embedding 构造企业知识库检索6.1 为什么需要 Embedding文本生成能回答问题但它无法感知企业内部私有文档。要想让模型回答“我们公司处理退款的方式是什么”不能直接靠提示词而是需要先建立知识库。一种常见方案是把企业文档切分成小块。调用 Embedding 模型把每块文本转换成向量。把向量存入向量数据库。用户提问时把问题转换为向量在向量库中查找最相似的文本片段。将找到的片段拼进 Prompt交给文本生成模型回答。Embedding 模型的核心能力是“语义相似度计算”。它把非结构化文本映射为高维浮点数向量在向量空间中语义相近的内容距离更近。6.2 调用 Embedding 模型创建EmbeddingDemo.javapackage com.example.palm; import java.util.Arrays; public class EmbeddingDemo { public static void main(String[] args) throws Exception { String apiKey System.getenv(PALM_API_KEY); if (apiKey null || apiKey.isBlank()) { throw new IllegalArgumentException(请先配置环境变量 PALM_API_KEY。); } PalmApiClient client new PalmApiClient(apiKey); float[] embedding client.embedText( embedding-gecko-001, Java 生成式 AI 开发实践 ); System.out.println(向量维度 embedding.length); System.out.println(前 5 个值 Arrays.toString(Arrays.copyOf(embedding, 5))); } }运行命令mvn -q compile exec:java -Dexec.mainClasscom.example.palm.EmbeddingDemo正常输出会显示向量维度以及前几个浮点数例如向量维度768 前 5 个值[0.0123, -0.0456, 0.0789, ...]这里的维度值并不固定不同 Embedding 模型可能返回不同维度。你在业务中通常不需要关心具体数值含义只需要把向量存入数据库并计算余弦相似度。6.3 落地方案扩展完成了 Embedding 调用之后企业知识库项目的后续工作主要集中在数据管道和检索服务上文档解析使用 POI、Tika 等类库解析 PDF、Word、Markdown。切块策略按段落、标题或固定长度切分避免单个片段过长。向量存储可以使用 Redis、Elasticsearch、Hibernate Search 或专用向量数据库。检索接口根据向量相似度返回 Top N 片段。这部分属于典型的 Java 后端工程问题和生成式 AI 模型本身关系不大但决定了最终问答效果的上限。建议从切块和召回效果开始优化不要过早陷入繁琐的模型调参。7. 常见问题与排查思路在实际调用过程中你可能会遇到各种异常。下面整理了一张排查表覆盖大多数常见情况。问题现象常见原因解决思路HTTP 400 错误请求体字段不符合当前 API 版本打印请求 JSON和官方文档对比字段名HTTP 401 UnauthorizedAPI Key 错误或格式不对检查环境变量是否生效重新复制 KeyHTTP 403 Forbidden当前项目没有启用模型 API前往 Google Cloud Console 检查 API 是否启用HTTP 404 Model not found模型名称不可用或账号无权限查询当前可用模型列表并替换模型名HTTP 429 限流请求频率超出配额增加本地重试和退避机制降低并发量连接超时网络无法访问目标域名检查外呼网络策略确认域名可访问返回内容为空Prompt 设计不合理或输出被安全过滤调整 Prompt检查响应中的安全评分中文乱码编码没有使用 UTF-8确保请求体、HttpClient 和文件编码均为 UTF-8遇到报错时不要只盯着状态码先打印完整响应体。大多数错误信息会用英文描述具体原因比如API key not valid、Permission denied、Model not found。这些信息比任何猜测都可靠。另外在你的 Java 程序运行环境中如果出现OutOfMemoryError或者mvn命令卡死通常不是 PaLM API 引入的问题而是 Maven 或 JVM 本身的内存设置不足。可以先调整 MAVEN_OPTS再重新运行。8. 最佳实践与工程建议8.1 凭证管理不要在生产代码中硬编码 API Key。建议使用环境变量、Kubernetes Secret、配置中心或云平台 Secret Manager 管理凭证。如果代码需要提交到 Git一定要把.env文件加入.gitignore。8.2 超时与重试生成式 AI 接口的响应时间波动很大。短则几百毫秒长则几十秒。生产环境中的 HTTP 连接超时建议设置为 10 到 30 秒读超时不低于 60 秒。同时要设置合理的重试策略。对于超时和 429 限流可以采用指数退避重试对于 400 参数错误不应重试直接记录错误日志。8.3 响应内容安全大模型输出不受业务代码直接控制因此必须增加输出校验。尤其是面向公网用户的服务要在调用 AI 接口前后增加内容安全审核、敏感词过滤和用户输入长度限制。在金融、医疗等强监管场景中还应保留调用日志和人工审核机制。8.4 日志与监控每个 AI 调用都涉及外部网络必须记录关键链路信息。建议记录模型名称、Prompt 长度、响应耗时、状态码、错误摘要。但避免记录完整敏感 Prompt 和完整响应防止日志泄露用户数据或隐私信息。8.5 与 Spring Boot 集成在 Spring Boot 项目中可以把PalmApiClient定义成一个Bean通过构造器注入 API Key。示例片段如下Configuration public class AiConfig { Bean public PalmApiClient palmApiClient() { return new PalmApiClient(System.getenv(PALM_API_KEY)); } }然后在 Service 层注入使用Service public class ContentService { private final PalmApiClient palmApiClient; public ContentService(PalmApiClient palmApiClient) { this.palmApiClient palmApiClient; } public String summarize(String text) { String prompt 请对以下内容做摘要\n text; try { return palmApiClient.generateText(text-bison-001, prompt, 0.3, 512); } catch (Exception e) { throw new RuntimeException(调用生成式 AI 服务失败, e); } } }这样设计的好处是业务代码不直接感知 HTTP 细节后续可以平滑地替换为 Google 官方 Java SDK 或其他大模型服务。8.6 成本与性能控制大模型 API 通常按 Token 计费成本与输入输出长度直接相关。开发时建议给maxOutputTokens设置一个合理上限避免模型生成过长文本。同时在面向用户的场景中可以为每个用户设置调用频率限制防止恶意刷接口导致费用失控。9. 总结与下一步通过这篇文章我们从零搭建了一个 Java 项目并完成了 Google PaLM API 的文本生成、多轮对话和 Embedding 调用。你既看到了完整的HttpClient封装也了解了请求体、响应体、异常排查和 Spring Boot 集成思路。对于 Java 后端开发者来说生成式 AI 并不是一个孤立的新技术它更像是一种新的外部服务需要你继续用 Java 工程化的方式去设计、监控和保护它。下一步可以根据自己的项目方向继续深入如果要做智能助手可以重点研究对话上下文管理和 Prompt 调优如果要做企业知识库可以研究向量数据库选型和大文档切块策略如果打算长期依赖 Google AI 生态也可以关注官方 Java SDK 和 Vertex AI 上的托管接口。建议先跑通本文最简单的一条请求路径再逐步替换成适合你团队的封装方案这种由简入繁的方式能最大程度降低集成成本。
返回列表