ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring AI 04 · 第一个 ChatClient 对话

2026/8/24 23:29:30 拓冰建站 浏览量
Spring AI 04 · 第一个 ChatClient 对话 04 · 第一个 ChatClient 对话 学完能做什么用 ChatClient 跑通同步与流式对话会读回答内容和 Token 用量理解 prompt/call/stream。⏱️ 预计耗时35 分钟含动手 依赖前置第 03 章环境已就绪 难度一句话chatClient.prompt().user(问题).call().content()就是一次完整对话把call()换成stream()就是打字机流式输出。1. 最小可运行示例RestControllerclassChatController{privatefinalChatClientchatClient;ChatController(ChatClient.Builderbuilder){this.chatClientbuilder.defaultSystem(你是一个简洁、专业的技术助手回答尽量精炼。).build();}GetMapping(/chat)Stringchat(RequestParamStringq){returnchatClient.prompt().user(q).call().content();}}访问/chat?q什么是RAG即可得到模型回答。defaultSystem(...)设了默认人设之后每次调用都会带上。2. 拆解链式调用chatClient.prompt()// 开启一次请求构建.system(...)// (可选) 本次的系统指令覆盖 defaultSystem.user(...)// 用户消息.call()// 同步执行.content();// 取纯文本回答四类常见「结尾」取法// 1) 只要文本StringtextchatClient.prompt().user(q).call().content();// 2) 要完整响应含 metadata、token 用量、结束原因ChatResponserespchatClient.prompt().user(q).call().chatResponse();Usageusageresp.getMetadata().getUsage();System.out.println(prompt tokens usage.getPromptTokens());System.out.println(total tokens usage.getTotalTokens());// 3) 直接映射成 Java 对象结构化输出第 25 章详解recordWeather(Stringcity,inttemp){}WeatherwchatClient.prompt().user(北京今天多少度给个大概).call().entity(Weather.class); 关注getUsage()很重要Token 成本。养成看用量的习惯第 38 章讲成本优化会用到。3. 流式输出打字机效果聊天类应用体验的关键别等整段生成完边生成边吐字。把call()换成stream()GetMapping(value/chat-stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)FluxStringchatStream(RequestParamStringq){returnchatClient.prompt().user(q).stream().content();// 返回 FluxString一段段推给前端}返回FluxString配合text/event-streamSSE推给前端。前端拿到就是「一个字一个字冒出来」的效果前端对接细节在第 20 章。4. 传多条消息 / 动态参数用户问题里可以带占位符用PromptTemplate思路下一章专讲 Prompt 工程StringanswerchatClient.prompt().system(你是资深 Java 面试官).user(u-u.text(请就「{topic}」出一道面试题).param(topic,Spring AI 的 Advisor)).call().content();5. 调参temperature 等运行时选项同一次调用可临时覆盖模型参数StringanswerchatClient.prompt().user(给我三个项目命名的创意).options(OpenAiChatOptions.builder().temperature(1.2)// 更高 更发散有创意.maxTokens(200).build()).call().content();temperature低0~0.3→ 更确定、适合事实问答高0.8~1.5→ 更发散、适合创意。RAG 场景通常用较低 temperature减少胡编。6. 一个能直接跑的完整 ControllerRestControllerRequestMapping(/ai)classDemoChatController{privatefinalChatClientchatClient;DemoChatController(ChatClient.Builderbuilder){this.chatClientbuilder.defaultSystem(你是简洁的中文技术助手).build();}GetMapping(/ask)MapString,Objectask(RequestParamStringq){ChatResponserespchatClient.prompt().user(q).call().chatResponse();returnMap.of(answer,resp.getResult().getOutput().getText(),totalTokens,resp.getMetadata().getUsage().getTotalTokens());}GetMapping(value/ask-stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)FluxStringaskStream(RequestParamStringq){returnchatClient.prompt().user(q).stream().content();}}7. 一句话总结prompt().user(...).call().content()是对话的最小骨架换stream()得到Flux流式输出用chatResponse()拿 Token 用量用options(...)临时调参。➡️ 下一章05-Prompt工程基础.md学会写好 system/user、用模板和少样本这是 RAG 效果的地基。