使用 JavaFX + LangChain4J 构建流式聊天桌面应用:javafx-example 实战指南 示例工程【免费下载链接】langchain4j-examples项目地址https://gitcode.com/GitHub_Trending/la/langchain4j-examples点击查看免费下载导读本指南基于langchain4j-examples仓库中的 javafx-example/README.md完整讲解如何用 JavaFX 构建一个原生桌面聊天界面并通过 LangChain4J 的流式Streaming能力把 OpenAI 的回复逐字实时渲染到界面上。文章从环境准备、项目结构到核心源码逐层拆解你将掌握 JavaFX 属性绑定如何驱动流式 Token 渲染、LangChain4JTokenStream的三段式回调模型、AiServices 窗口消息记忆的配置方式最终能以此为起点搭建自己的桌面端 AI 助手。一、项目定位为什么要用 JavaFX 做 LangChain4J 桌面端javafx-example是一个独立的 Maven 模块见 javafx-example/pom.xml其目标非常聚焦演示如何用 JavaFX 用户界面把 OpenAI 流式返回的答案一边接收一边可视化。核心诉求有三点答案在收到过程中就实时渲染到右侧文本框同一答案同步呈现在左侧历史表格Table中每次提问的历史记录时间戳、问题、答案、完成状态都保留在表格里且模型通过聊天记忆维持多轮对话上下文。从源码结构看javafx-example/src/main/java/该模块把 UI、流式处理、业务服务、数据模型分层得很清晰共 7 个 Java 类Launcher、ChatApp、AnswerService、Assistant、CustomStreamingResponseHandler、SearchAction、ApiKeys。这种「UI 层只负责展示、服务层只负责编排模型、模型类只负责声明接口」的组织方式是后续构建任何桌面 AI 应用都可以复用的骨架。二、环境准备与运行方式运行该示例的前提是使用自带 JavaFX 的 JDK。README 给出的推荐方式是使用 SDKMAN 安装 Azul Zulu 的 JavaFX 捆绑版 JDK然后直接通过 Maven JavaFX 插件启动$ sdk install java 21.fx-zulu $ mvn javafx:run围绕这两条命令结合 pom.xml 补充几个可验证的细节Java 编译级别为 17maven.compiler.source/target均为17而运行示例用 21 版捆绑 JDK说明代码可在 Java 17 上编译、用含 JavaFX 的 JDK 运行。JavaFX 依赖仅引入javafx-controls版本21.0.1因为界面只用到了控件层Application、Scene、TableView、TextArea、TextField、Button等无需javafx-fxml。LangChain4J 依赖langchain4j核心库与langchain4j-open-aiOpenAI 模型实现均为1.17.0流式能力由OpenAiStreamingChatModel提供。日志依赖log4j-apilog4j-slf4j2-impl2.22.1用于记录启动、请求、流式完成等过程日志。启动入口javafx-maven-plugin版本0.0.8配置了mainClassLauncher/mainClassLauncher只是一个转发入口main直接调用ChatApp.main(args)启动 JavaFX 应用。注意模型调用需要有效的 OpenAI API Key。源码 ApiKeys.java 中默认使用demo占位 Key注释说明可前往 OpenAI 平台获取自己的 Key 后替换OPENAI_API_KEY常量。三、整体架构一条提问在 UI 与模型之间的流转链路应用虽小却构成了一条完整的「用户输入 → 线程化服务 → 流式模型 → JavaFX 主线程更新 UI」链路可以用下面这张运行时截图直观对照截图来自 javafx-example/screenshot.png界面包含标题「JavaFX Chat Langchain4J Demo」、输入区「What is your question?」、带 Timestamp/Question/Answer/Finished 四列的表格以及右侧完整回答文本框。链路各环节对应源码如下UI 事件触发ChatApp.java 中TextField的setOnAction回车与Search按钮的setOnAction都指向doSearch(input.getText())空输入会被直接忽略。新建会话记录并绑定doSearch创建一个新的SearchAction(question)加入ObservableListSearchAction data同时执行lastAnswer.textProperty().bind(searchAction.getAnswerProperty())—— 右侧文本框直接与这条记录的答案属性绑定。后台线程执行new Thread(() - docsAnswerService.ask(searchAction)).start()把模型调用放到独立线程避免阻塞 JavaFX 的 UI 线程。流式回调AnswerService调用assistant.chat(...)得到TokenStream分别注册onPartialResponse、onCompleteResponse、onError回调。回主线程更新CustomStreamingResponseHandler.java 中每个回调都通过Platform.runLater(...)把 UI 更新切回 JavaFX Application Thread这是 JavaFX 并发编程的硬性要求——模型线程不能直接操作 UI。这个设计同时回答了 README 里强调的「如何用 JavaFX bindings 处理流式答案」把模型返回的 Token 追加写入 JavaFX 属性再由属性绑定自动推送到界面。四、核心代码逐层拆解4.1 入口与界面装配ChatAppChatApp.java 是整个应用的 UI 核心几个值得注意的装配细节全局单例数据源FXCollections.observableArrayList()的data作为TableView的 items表格各列通过setCellValueFactory绑定SearchAction的 JavaFX 属性时间戳、问题、答案、完成状态四列分别设了 250/250/300/50 的最小宽度。启动即初始化start()中先插入一条new SearchAction(Application started, true)再插入Initializing search engine, please stand by...的初始化条目并用lastAnswer.textProperty().bind(initAction.getAnswerProperty())让右侧文本框显示初始化进度随后在新线程中执行docsAnswerService.init(initAction)。布局VBox外层 15px 内边距依次放入标题 Label25px 加粗、输入区HBox输入框 500px 宽 Search 按钮、以及new HBox(table, lastAnswer)构成的「左表右文」双栏布局lastAnswer.setWrapText(true)保证长答案自动换行。4.2 流式模型与记忆装配AnswerServiceAnswerService.java 负责模型生命周期管理是 README 中「模型保持对话记忆」这一承诺的直接实现StreamingChatModel model OpenAiStreamingChatModel.builder() .apiKey(ApiKeys.OPENAI_API_KEY) .modelName(GPT_4_O_MINI) // 静态导入自 OpenAiChatModelName .build(); assistant AiServices.builder(Assistant.class) .streamingChatModel(model) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) // 最多保留 10 条消息 .build();关键点流式模型使用OpenAiStreamingChatModel模型名取自OpenAiChatModelName.GPT_4_O_MINIAI 服务通过AiServices.builder(Assistant.class)把流式模型和聊天记忆注入到Assistant接口得到可调用的代理对象窗口记忆MessageWindowChatMemory.withMaxMessages(10)说明记忆采用「消息窗口」策略只保留最近 10 条消息既维持多轮上下文又控制 Token 开销初始化流程init会先appendAnswer(Initiating...)模型构建完成后追加Done并调用setFinished()让表格中该行「Finished」列变为true。4.3 流式回调的三种形态CustomStreamingResponseHandlerCustomStreamingResponseHandler.java 演示了 LangChain4JTokenStream最核心的三段式回调回调触发时机UI 行为onNext(String token)收到一个流式分片 TokenPlatform.runLater内action.appendAnswer(token)答案逐字增长onComplete(ChatResponse response)整个响应结束打印完整响应日志与答案长度action.setFinished()置完成标志onError(Throwable error)出错日志记录错误答案尾部追加\nSomething went wrong: error.getMessage()并置完成标志这里有一个值得学习的健壮性细节onError并不会让界面卡在「加载中」而是把错误信息作为答案的一部分追加显示同时把Finished置为true保证表格状态始终一致。4.4 AI 服务接口AssistantAssistant.java 是 LangChain4J 的 AI Service 声明式接口只有一行方法签名public interface Assistant { TokenStream chat(String message); }返回类型TokenStream正是流式能力的入口——在 AnswerService.java 的ask方法中对它链式注册回调后调用.start()才真正发起请求assistant.chat(action.getQuestion()) .onPartialResponse(responseHandler::onNext) .onCompleteResponse(responseHandler::onComplete) .onError(responseHandler::onError) .start();这种「接口声明 AiServices动态代理」的编程模型把记忆、模型、流式处理全部收敛到声明层业务代码只关心回调即可。4.5 数据模型SearchAction 与 JavaFX 属性绑定SearchAction.java 是整个「绑定驱动流式渲染」方案的基石。它不依赖javafx.beans之外的任何模型代码用四个 JavaFX 属性承载一条完整会话记录StringProperty timestampLocalDateTime.now().toString()生成提问时间戳StringProperty question用户问题StringProperty answer答案appendAnswer(String token)通过this.answer.set(this.answer.getValue() token)实现 Token 追加BooleanProperty finished是否已完成。正因为answer是StringPropertyChatApp里的lastAnswer.textProperty().bind(searchAction.getAnswerProperty())才能做到「模型线程每追加一个 Token右侧文本框和表格单元格就同步刷新一次」——这正是 README 强调的「用 JavaFX bindings 处理答案」的底层机制。五、实战要点总结与扩展建议5.1 值得直接复用的四个模式后台线程 Platform.runLater凡是模型/IO 操作一律放非 UI 线程凡是要更新界面一律经Platform.runLater切回 JavaFX 主线程属性绑定替代手动刷新把流式答案写入StringProperty让TextArea和TableView通过绑定自动感知变化无需手动重绘AiServicesTokenStream声明式流式编程接口返回TokenStream链式注册onPartialResponse/onCompleteResponse/onError后.start()窗口记忆保持多轮语境MessageWindowChatMemory.withMaxMessages(10)是控制上下文长度最简单直接的方式。5.2 改造为自有应用的切入点README 明确指出该项目「可以作为构建自己 JavaFX 版 LangChain4J 实现的起点」。从当前源码出发可以清晰看到哪些地方适合替换扩展更换模型AnswerService.initChat中把OpenAiStreamingChatModel换成其他StreamingChatModel实现如 Azure OpenAI、本地 Ollama 等可参考仓库中 ollama-examples/ 等其他模块即可Assistant接口与 UI 层无需改动扩展服务能力Assistant接口可以增加带Tool的方法或引入工具类把桌面应用升级为可调用外部工具的智能助手调整记忆策略将MessageWindowChatMemory换成持久化记忆可参考仓库 other-examples/ 中的ServiceWithPersistentMemoryExamples相关实现美化界面ChatApp中所有样式都是内联 CSS如-fx-padding: 15px、-fx-font-size: 25px可直接升级为 JavaFX CSS 样式表或引入 FXML 做更复杂的布局。5.3 运行验证路径在javafx-example目录下执行mvn javafx:run后可以对照 README 与截图验证三条行为输入问题并回车或点击 Search 后右侧文本框会逐字出现答案左侧表格会新增一行记录Finished列在流式结束后变为true连续提问时模型能结合之前的历史消息作答由 10 条消息窗口记忆保证。日志中可观察到Complete response: ...与Answer is complete for ..., size: N的输出用于确认流式生命周期完整走完。相关文件索引javafx-example/README.md — 本文依据的官方说明文档javafx-example/pom.xml — 依赖与启动插件配置javafx-example/src/main/java/ChatApp.java — JavaFX 界面装配与事件处理javafx-example/src/main/java/AnswerService.java — 流式模型与记忆装配javafx-example/src/main/java/Assistant.java — AI Service 声明接口javafx-example/src/main/java/CustomStreamingResponseHandler.java — 流式回调处理javafx-example/src/main/java/SearchAction.java — JavaFX 属性数据模型javafx-example/screenshot.png — 应用运行界面截图赞分享示例工程【免费下载链接】langchain4j-examples项目地址https://gitcode.com/GitHub_Trending/la/langchain4j-examples点击查看免费下载相关推荐NettyJavaFx 实战搭建仿桌面版微信聊天应用CodeGuide IM 项目完整技术指南NettyJavaFx 实战搭建仿桌面版微信聊天应用CodeGuide IM 项目完整技术指南 本文基于 CodeGuide 仓库中 《NettyJa文档教程后端Wifi-Hacking终极指南如何使用内置Kali工具破解无线网络Wifi Hacking终极指南如何使用内置Kali工具破解无线网络 在当今数字化时代无线网络安全已成为重要议题。本指南将详细介绍如何使用 Wifi Hac网络安全渗透测试qrcode.vue终极Vue二维码组件指南 - 同时支持Vue 2和Vue 3的完整解决方案qrcode.vue终极Vue二维码组件指南 同时支持Vue 2和Vue 3的完整解决方案 qrcode.vue是一款功能强大的Vue二维码组件能够帮助开发前端UI组件上一篇scrcpy 安卓投屏教程3 步把手机变成电脑上的窗口下一篇Umi-OCR 完整指南免费离线 OCR快速把扫描 PDF 变成可搜索文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考