不学 Python,Java 也能调大模型?15 分钟跑通第一个 AI 接口(Java 架构师的 AI 工程笔记 01)
文章目录Java 架构师的 AI 工程笔记一5 个概念 第一次跟 AI 对话理论篇一、Java 工程师为什么能搞 AI Agent二、开始写代码之前你得搞懂这 5 个概念2.1 Token——LLM 的计费单位2.2 Prompt——你给 LLM 的指令2.3 Temperature——控制输出的稳定性2.4 Context Window——对话的内存大小2.5 Function Calling——Agent 的核心引擎三、Spring AI 的分层架构四、幻觉——LLM 一本正经地胡说实战篇五、跑通第一个对话程序5.1 申请通义千问 API Key5.2 项目结构5.3 配置文件5.4 启动类5.5 第一个对话接口5.6 Temperature 对比实验六、与机票比价 Agent 的集成七、FAQ 与踩坑记录本章小结Java 架构师的 AI 工程笔记一5 个概念 第一次跟 AI 对话这是 Spring AI Alibaba 系列的第一篇。目标让你的 Spring Boot 项目在 15 分钟内接入大模型对话能力。理论篇一、Java 工程师为什么能搞 AI Agent带团队做 AI 转型时最先被问到的问题就是“AI 不都是 Python 的吗我们 Java 团队能搞得了”想明白一件事就不纠结了。AI Agent 的核心不是训练模型而是工程化——把大模型的能力串起来做成一个能干活的系统。这恰恰是 Java 工程师擅长的工具注册和调度 → 你写了多年的 Spring 依赖注入多步编排和状态管理 → 你熟悉的工作流引擎高可用、可观测、分布式 → Java 生态的强项企业级落地 → Spring Boot 就是事实标准所以问题不是Java 能不能搞 AI而是有没有好用的框架。Spring AI Alibaba 就是答案——Spring 团队和阿里一起做的API 风格跟 Spring 全家桶一脉相承。二、开始写代码之前你得搞懂这 5 个概念不需要懂 Transformer 和 Attention 机制。但下面 5 个概念直接影响你写代码时的每一个决策跳过任何一个后面都会踩坑。2.1 Token——LLM 的计费单位Token 不是字也不是词是模型处理文本的最小单位。中文大约 1 个字 ≈ 1-2 个 Token。我想查北京到上海的机票 → 大约 12-15 个 Token为什么要关心这个因为它影响三件事影响说明钱API 按 Token 数计费输入和输出分别算容量一次对话能装的信息有上限Context Window速度Token 越多响应越慢通义千问的价格参考2025模型输入每百万 Token输出每百万 Token上下文长度qwen-turbo¥2¥6128Kqwen-plus¥4¥12128Kqwen-max¥20¥6032K开发建议调试用 qwen-turbo便宜上线用 qwen-plus均衡核心场景用 qwen-max最强。2.2 Prompt——你给 LLM 的指令Prompt 是你发给大模型的文本。它不是简单的输入而是有结构的角色作用示例System设定 AI 的人格和规则“你是一个专业机票分析师只回答机票相关问题”User用户的实际问题“帮我查北京到上海明天的机票”Assistant模型之前的回答用于多轮对话“已为您查到以下航班…”System Prompt 是 Agent 的灵魂。后面你会发现很多时候调 System Prompt 比改代码有用 10 倍。2.3 Temperature——控制输出的稳定性Temperature 是一个 0 到 1 之间的参数决定了 LLM 回答的随机程度。用 Java 来类比temperature0 就像一个确定性的switch-case给同样的输入永远走同一个分支temperature1 更像Random.nextInt()每次执行结果都不一样。Temperature效果适用场景0每次回答几乎相同Agent 工具调用、数据分析0.3轻微变化Agent 推荐值0.7默认值有一定随机性普通对话1.0每次都不一样创意写作怎么选一个合理的值看你的业务对一致性的要求场景推荐值原因Function Calling / 工具调用0参数必须精确随机性会导致 JSON 格式错误或传错参数Agent 决策与推理0 - 0.3推理链路要稳定但允许微小灵活性客服 / FAQ 问答0.3 - 0.5回答要准确但措辞可以自然一点不要像机器人普通对话 / 聊天0.7平衡准确性和趣味性大多数模型的默认值营销文案 / 创意写作0.8 - 1.0需要发散思维每次生成不同的表达一个实用的定值策略先从 0.7默认值开始发现输出太飘就往下调太死板就往上调。线上环境建议把 temperature 写进配置文件而不是硬编码方便随时调整。⚠️重点Agent 中涉及工具调用、结构化输出的环节建议用较低的 temperature0-0.3。但 Agent 不只有工具调用——如果某个环节需要生成面向用户的自然语言回复比如总结、推荐理由适当提高到 0.5-0.7 反而更自然。关键是按环节分别设置而不是整个 Agent 一刀切。2.4 Context Window——对话的内存大小Context Window 是一次对话能容纳的总 Token 数。所有东西都要塞进去System Prompt、历史对话、当前问题、工具描述、模型回答。超出上限怎么办旧的对话会被截断模型会忘掉之前聊过的内容。这就是为什么后面要专门学 Memory 管理第 4 章。2.5 Function Calling——Agent 的核心引擎这是最重要的概念。没有 Function Calling就没有 Agent。传统 LLM 只能输出文本。Function Calling 让 LLM 能够调用函数——准确说是 LLM 告诉你它想调用什么函数、传什么参数真正的执行由你的代码完成。关键点LLM 不直接调用 API——它只输出 JSON 格式的调用意图你的代码负责执行——接收意图调真正的 API结果喂回给 LLM——LLM 拿到结果后组织成自然语言回复用 Java 类比LLM 就像一个智能路由器根据用户请求决定调用哪个 Service 方法但它自己不执行方法。你写的 Service 才是干活的。三、Spring AI 的分层架构Spring AI 的设计跟 Spring Data 一个思路——统一抽象多种实现{SpringApplication.run(QuickStartApplication.class,args);}}5.5 第一个对话接口Spring AI 推荐用ChatClient高层 API而不是底层的ChatModel。关系就像JdbcTemplate和DataSourcepackagecom.ai.course.quickstart.controller;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.web.bind.annotation.*;importreactor.core.publisher.Flux;RestControllerRequestMapping(/api/chat)publicclassChatController{// 用 ChatClient 而不是 ChatModel —— 链式 API 更简洁支持 Advisor 拦截privatefinalChatClientchatClient;publicChatController(ChatClient.BuilderchatClientBuilder){this.chatClientchatClientBuilder.defaultSystem(你是一个友好的AI助手。).build();}/** * 同步对话 * 试试GET /api/chat?message你好 */GetMappingpublicStringchat(RequestParam(valuemessage,defaultValue你好)Stringmessage){returnchatClient.prompt().user(message).call().content();}/** * 流式对话 —— 打字机效果 * 试试GET /api/chat/stream?message介绍一下春季热门航线 */GetMapping(value/stream,producestext/html;charsetUTF-8)publicFluxStringchatStream(RequestParam(valuemessage,defaultValue你好)Stringmessage){returnchatClient.prompt().user(message).stream().content();}}启动项目打开浏览器访问http://localhost:8080/api/chat?message你好你应该能看到通义千问的回复。流式接口/api/chat/stream会一个字一个字地吐出来体验明显好很多。LLM 生成完整回答可能要 5-10 秒流式让用户边生成边看到不用干等。5.6 Temperature 对比实验理论篇讲了 Temperature 影响输出稳定性现在亲眼看看。加一个实验接口packagecom.ai.course.quickstart.controller;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.prompt.ChatOptions;importorg.springframework.web.bind.annotation.*;importjava.util.*;importjava.util.concurrent.CompletableFuture;RestControllerRequestMapping(/api/experiment)publicclassExperimentController{privatestaticfinalLoggerlogLoggerFactory.getLogger(ExperimentController.class);privatefinalChatClientchatClient;publicExperimentController(ChatClient.Builderbuilder){// 通过 System Prompt 限制回答长度让对比更直观this.chatClientbuilder.defaultSystem(你是一个简洁的助手回答限制在20字以内。).build();}/** * Temperature 对比实验 * GET /api/experiment/temperature?message用一个词形容春天 * * 同一问题分别用 temperature 0 和 1.0 各调用 3 次 * temperature0 的回答几乎相同temperature1.0 每次都不一样 */GetMapping(/temperature)publicMapString,ListStringtemperatureExperiment(RequestParam(valuemessage,defaultValue用一个词形容春天)Stringmessage){double[]temperatures{0.0,1.0};introunds3;log.info(开始 Temperature 对比实验消息{},message);MapString,CompletableFutureListStringfuturesnewLinkedHashMap();for(doubletemp:temperatures){Stringkeytemperature_temp;futures.put(key,CompletableFuture.supplyAsync(()-{ListStringresponsesnewArrayList();for(inti0;irounds;i){log.info([{}] 第 {} 次调用开始...,key,i1);longstartSystem.currentTimeMillis();StringcontentchatClient.prompt().user(message).options(ChatOptions.builder().temperature(temp).build()).call().content();longcostSystem.currentTimeMillis()-start;log.info([{}] 第 {} 次调用完成耗时 {}ms回答{},key,i1,cost,content);responses.add(content);}returnresponses;}));}MapString,ListStringresultsnewLinkedHashMap();futures.forEach((key,future)-results.put(key,future.join()));log.info(Temperature 对比实验完成);returnresults;}}直接访问GET /api/experiment/temperature默认问题用一个词形容春天你会看到类似结果{temperature_0.0:[温暖,温暖,温暖],temperature_1.0:[生机,温柔,绚烂]}temperature0三次回答完全一样——输出稳定可预测temperature1.0每次回答都不同——充满随机性和创意这就是为什么 Agent 场景要用低 temperature——你需要 LLM 的输出稳定可预测。六、与机票比价 Agent 的集成本章搭建的 quick-start 是整个系列的起点。后面的章节会在这个基础上逐步加能力第 2 章用 ChatClient 的 Advisor 和 Prompt 模板让对话更可控第 3 章通过 Function Calling 接入机票查询工具从编造数据进化为查真实数据第 4 章加 Memory实现多轮对话“北京飞上海” → “明天的” → “最便宜的”当前模块的配置模型、温度和父 POM 的依赖管理会被所有后续模块复用。七、FAQ 与踩坑记录Q1启动报错No qualifying bean of type ChatModel最常见的原因是缺依赖或者环境变量没设确认 pom.xml 里有spring-ai-alibaba-starter-dashscope确认环境变量AI_DASHSCOPE_API_KEY已设置且值正确确认 application.yml 里用的是${AI_DASHSCOPE_API_KEY}而不是写死的 KeyQ2调用报401 Unauthorized或InvalidApiKeyKey 无效或过期。到百炼平台检查 Key 状态。新账号第一次使用需要先开通百炼服务并创建 API Key。另外看看环境变量里的 Key 有没有多余的空格或换行。Q3流式接口返回乱码三个排查方向GetMapping的produces必须是text/event-stream;charsetUTF-8如果有 Nginx 反代加proxy_buffering off;浏览器直接访问 SSE 显示可能不友好用curl或前端EventSource测Q4第一次调用特别慢10 秒以上正常。第一次请求涉及到底层 HTTP 连接建立、模型加载等。后续请求会快很多。如果持续很慢检查网络是否需要代理。本章小结理论篇实战篇Token 与计费环境搭建Prompt 三种角色同步对话Temperature 稳定性流式输出Context Window 容量Temperature 实验Function Calling 核心下一章ChatClient 的高级用法和 Prompt 工程。会用到 Advisor 拦截器、Prompt 模板、结构化输出——让 LLM 的返回直接变成 Java 对象。本文代码GitHub - quick-start 模块如果这篇文章对你有帮助欢迎点赞收藏。有问题欢迎评论区交流。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2426729.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!