1. 项目概述当Java开发者遇上LangChain如果你是一名Java后端工程师最近几个月肯定被“LangChain”这个词刷屏了。看着Python社区里各种基于LangChain的智能应用层出不穷从智能客服到文档分析工具你是不是也心痒痒但又觉得为了一个AI功能去重学Python或者搞一套复杂的服务化调用太折腾别急HamaWhiteGG/langchain-java这个项目就是为我们Java技术栈的开发者量身打造的“破局利器”。简单来说langchain-java是一个将风靡AI应用开发领域的LangChain框架用纯Java语言重新实现的开源库。它的核心目标就是让Java开发者能够用自己最熟悉的语言、工具和生态无缝地构建基于大语言模型LLM的应用程序。无论是想给现有的Spring Boot系统增加一个智能问答模块还是想用Java开发一个全新的AI Agent这个项目都提供了从模型调用、提示词管理、记忆机制到工具链集成的一整套“脚手架”。我最初接触这个项目是因为团队需要将一个历史悠久的Java单体应用进行智能化升级。客户希望系统能“读懂”用户上传的PDF合同并自动提取关键条款。当时评估了多种方案用Python写服务再通过RPC调用技术栈割裂运维复杂直接调用大模型API又需要自己处理上下文组装、文件解析等大量胶水代码。直到发现了langchain-java它让我们能在原有的Java工程里像引入一个普通的工具库一样用几十行代码就接入了大模型的能力并且保持了工程结构的一致性和可维护性。这不仅仅是多了一个库更是为整个Java生态打开了一扇通往AI应用开发的大门。2. 核心架构与设计哲学拆解2.1 为何选择“重造轮子”而非“封装调用”看到langchain-java很多人的第一反应可能是为什么不直接封装OpenAI、通义千问等模型的HTTP API做一个轻量级的Java SDK呢这个项目的设计者HamaWhiteGG显然思考得更深。它并非一个简单的API客户端而是一个完整遵循了LangChain原始设计模式的框架实现。这背后有几个关键考量首先是开发范式的统一。LangChain之所以成功是因为它提炼出了一套构建LLM应用的通用模式比如Chain链、Agent智能体、Memory记忆、Tool工具。langchain-java完整复现了这些抽象这意味着一个熟悉Python版LangChain的开发者几乎可以无成本地切换到Java版本进行开发。这种范式统一的价值远大于提供一个好用的API包装器。其次是生态融合的便利性。Java拥有世界上最庞大的企业级开源生态从Spring、MyBatis到各种数据库连接池、消息中间件。langchain-java的设计允许开发者轻松地将这些现有的Java组件“包装”成LangChain中的Tool。例如你可以将一个查询数据库的JdbcTemplate操作、一个发送Kafka消息的方法快速转化为智能体Agent可以理解和调用的工具。这种与现有Java生态的深度融合能力是单纯调用模型API无法比拟的。最后是性能与可控性。作为本地库它避免了跨语言调用的开销如通过Python服务进行HTTP或RPC调用。所有逻辑都在JVM内执行调试、监控、链路追踪都可以沿用Java现有的成熟体系如SkyWalking、Arthas。对于追求高性能和可控性的企业级应用这一点至关重要。2.2 模块化设计像搭积木一样构建AI应用langchain-java的代码结构高度模块化清晰反映了其核心功能。理解这几个核心模块你就掌握了它的使用脉络langchain-core这是框架的基石。它定义了最核心的抽象接口如LLM大语言模型、ChatModel聊天模型、EmbeddingModel嵌入模型、PromptTemplate提示词模板、Chain、Memory等。你的大部分编程都是面向这些接口进行的这保证了代码的通用性和可替换性。langchain-llm这是模型的“连接器”模块。它包含了针对不同厂商大模型API的具体实现例如OpenAiChatModel、QianfanChatModel百度千帆、OllamaChatModel本地模型等。当你需要切换模型供应商时通常只需要更改这里的配置和依赖业务层的Chain代码几乎不用动。langchain-tool工具集成模块。这里提供了一些内置工具如计算器、网络搜索更重要的是它定义了如何将任意Java方法封装成Tool的标准方式。这是赋予LLM“动手能力”的关键。langchain-memory记忆管理模块。LLM本身是无状态的Memory负责在多次交互中维护上下文。该模块提供了如ConversationBufferMemory简单对话缓存、ConversationSummaryMemory摘要记忆等多种记忆策略的实现用于管理对话历史或Agent的执行状态。langchain-chain链实现模块。预置了一些常用的链如LLMChain最基础的链、SequentialChain顺序链、RetrievalQAChain检索问答链等。你可以直接使用也可以基于它们组合成更复杂的业务流程。这种模块化设计带来的最大好处是“高内聚、低耦合”。你可以根据项目需要只引入必要的模块。例如如果只是一个简单的提示词补全应用可能只需要core和llm如果要构建一个能调用数据库的智能体则需要加上tool模块。3. 从零开始你的第一个LangChain-Java应用理论说了这么多我们来点实际的。下面我将带你一步步创建一个最简单的Spring Boot应用集成langchain-java并调用大模型完成一次对话。我会假设你使用IntelliJ IDEA和Maven模型采用兼容OpenAI API格式的本地模型如Ollama部署的Llama 3或云端服务。3.1 环境准备与项目初始化首先创建一个标准的Spring Boot项目。在pom.xml中引入核心依赖。目前langchain-java的主要版本在快速发展中请以项目GitHub仓库的最新版本为准。dependencies !-- Spring Boot Web (非必须仅为创建Web应用示例) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- LangChain Java 核心依赖 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version0.31.0/version !-- 请检查最新版本 -- /dependency !-- 使用OpenAI兼容的API这里以Ollama为例 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-ollama/artifactId version0.31.0/version /dependency !-- Lombok简化代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies注意依赖的groupId是dev.langchain4j这与项目仓库名HamaWhiteGG/langchain-java稍有不同是项目发布到Maven中央仓库的正式名称。务必通过Maven中央仓库搜索确认最新稳定版本。接下来在application.yml或application.properties中配置模型连接信息。这里以本地运行的Ollama搭载Llama 3模型为例# application.yml langchain4j: ollama: chat-model: base-url: http://localhost:11434 # Ollama服务地址 model-name: llama3:8b # 使用的模型名称 timeout: 60s # 超时时间 temperature: 0.7 # 创造性参数 log-requests: true # 开启请求日志调试用 log-responses: true # 开启响应日志调试用如果你使用的是OpenAI官方API则需要引入langchain4j-open-ai依赖并配置api-key和base-url如果使用代理。3.2 构建一个简单的问答服务现在我们创建一个Spring Service在其中注入并使用ChatModel。import dev.langchain4j.model.chat.ChatLanguageModel; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; Service RequiredArgsConstructor public class SimpleChatService { // LangChain4j的Spring Boot Starter会自动配置ChatModel Bean private final ChatLanguageModel chatModel; public String chat(String userMessage) { // 最简单的调用直接向模型发送消息 String response chatModel.generate(userMessage); return response; } public String chatWithPrompt(String topic) { // 使用提示词模板进行格式化提问 String prompt “请用简洁的语言解释一下什么是” topic “”; return chatModel.generate(prompt); } }然后创建一个简单的REST控制器来暴露接口import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController RequiredArgsConstructor public class ChatController { private final SimpleChatService chatService; GetMapping(“/chat”) public String chat(RequestParam String message) { return chatService.chat(message); } GetMapping(“/explain”) public String explain(RequestParam String topic) { return chatService.chatWithPrompt(topic); } }启动你的Spring Boot应用访问http://localhost:8080/explain?topic量子计算你应该就能收到一段由大模型生成的关于量子计算的解释。至此你的第一个AI赋能的后端服务就搭建完成了整个过程没有写任何HTTP客户端代码没有处理JSON解析就像调用一个本地方法一样简单。3.3 深入一步使用提示词模板与链直接调用chatModel.generate只是最基础的用法。langchain-java的强大之处在于其链式编排能力。让我们改造一下服务使用更规范的PromptTemplate和LLMChain。首先定义一个提示词模板。我们可以把它放在一个配置类或工具类中。import dev.langchain4j.model.input.Prompt; import dev.langchain4j.model.input.PromptTemplate; public class PromptTemplates { private static final PromptTemplate EXPLANATION_TEMPLATE PromptTemplate.from( “你是一位资深的{{expert}}专家。请向一位没有任何技术背景的普通人用生动有趣的比喻和不超过200字的内容解释清楚‘{{concept}}’这个概念。\n” “解释” ); public static Prompt createExplanationPrompt(String expert, String concept) { // 将变量注入模板 return EXPLANATION_TEMPLATE.apply( Map.of(“expert”, expert, “concept”, concept) ); } }然后修改我们的Service使用AiServices这个更高级的抽象。AiServices是langchain-java中一个极其便利的功能它可以通过动态代理将一个接口直接转换为一个AI交互服务。import dev.langchain4j.service.AiServices; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; // 1. 首先定义一个交互接口 interface Assistant { SystemMessage(“你是一位幽默风趣的科技百科作者。”) String explainConcept(UserMessage String concept); } Service public class ChainChatService { private final Assistant assistant; public ChainChatService(ChatLanguageModel chatModel) { // 2. 使用AiServices将接口和模型绑定创建代理实例 this.assistant AiServices.create(Assistant.class, chatModel); } public String explainWithChain(String concept) { // 3. 像调用普通Java方法一样调用AI return assistant.explainConcept(concept); } }通过SystemMessage注解我们设定了AI的“系统角色”UserMessage注解则标记了用户输入的位置。AiServices在背后自动完成了提示词的组装、模型的调用和结果的返回。这种方式让业务代码变得异常清晰将AI交互的逻辑通过接口和注解进行声明式管理是langchain-java推荐的最佳实践之一。4. 核心进阶构建具备“记忆”与“工具”的智能体Agent简单的问答链只是开始。真正的生产力来自于能自动执行复杂任务的智能体Agent。一个智能体通常由三部分组成一个“大脑”LLM、一段“记忆”Memory和一堆“手和脚”Tools。下面我们构建一个能记住对话历史并能进行简单计算的智能体。4.1 为对话添加记忆我们创建一个具有对话记忆的聊天服务。import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; // 定义接口注意增加了chatId参数用于区分不同对话的记忆 interface ChatMemoryAssistant { SystemMessage(“你是一个乐于助人的助手。”) String chat(MemoryId String chatId, UserMessage String userMessage); } Service public class MemoryChatService { private final ChatMemoryAssistant assistant; public MemoryChatService(ChatLanguageModel chatModel) { // 创建一个基于滑动窗口的记忆保留最近10轮对话 ChatMemory memory MessageWindowChatMemory.withMaxMessages(10); this.assistant AiServices.builder(ChatMemoryAssistant.class) .chatLanguageModel(chatModel) .chatMemory(memory) // 注入记忆组件 .build(); } public String chat(String sessionId, String userMessage) { // 相同的sessionId会共享同一段对话记忆 return assistant.chat(sessionId, userMessage); } }现在如果你连续发送“我叫小明”和“我叫什么名字”智能体能够根据记忆回答“你叫小明”。MemoryId是关键它确保了不同用户或不同对话线程的记忆是隔离的。4.2 赋予智能体使用工具的能力让AI能调用外部工具是其从“聊天机器人”升级为“智能体”的关键一步。假设我们想让AI能进行货币换算。第一步定义一个工具类。工具类中的公开方法只要符合规范有清晰的输入输出就可以被AI调用。import dev.langchain4j.agent.tool.Tool; import org.springframework.stereotype.Component; Component // 注册为Spring Bean public class CalculatorTools { Tool(“用于计算两个数字的和”) // Tool注解描述工具功能这很重要 public double add(double a, double b) { return a b; } Tool(“用于计算两个数字的乘积”) public double multiply(double a, double b) { return a * b; } }第二步创建集成工具的智能体服务。import dev.langchain4j.service.AiServices; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; interface ToolAssistant { SystemMessage(“你是一个计算助手可以帮用户进行数学运算。你必须使用你拥有的工具来进行计算不要自己心算。如果用户的问题不明确请询问清楚。”) String chat(UserMessage String userMessage); } Service RequiredArgsConstructor public class AgentService { private final ChatLanguageModel chatModel; private final CalculatorTools calculatorTools; // 注入工具Bean public String useAgent(String question) { // 构建智能体并注册工具 ToolAssistant assistant AiServices.builder(ToolAssistant.class) .chatLanguageModel(chatModel) .tools(calculatorTools) // 注册工具AI现在知道它能调用这些方法了。 .build(); return assistant.chat(question); } }现在当你向这个AgentService提问“请计算123加上456再乘以2的结果是多少”会发生以下神奇的事情LLM大脑分析问题识别出需要先执行加法再执行乘法。它决定调用add(123, 456)工具获得结果579。它将这个结果作为上下文再决定调用multiply(579, 2)工具。最终得到结果1158并组织成自然语言回复给你。在整个过程中你不需要写任何逻辑来判断用户意图、解析数字、调用计算顺序。全部由LLM驱动智能体自动规划并执行。你可以轻松地将查询数据库、调用外部API、操作文件等方法封装成Tool从而构建出能力极其强大的业务智能体。5. 实战构建企业级RAG检索增强生成应用RAG是目前企业落地AI知识问答最主流、最有效的架构。它通过将外部知识库如公司文档、产品手册向量化存储在用户提问时先检索相关片段再连同片段一起送给LLM生成答案从而极大减少模型“胡言乱语”的情况。用langchain-java实现一个RAG应用非常优雅。5.1 知识库嵌入与向量存储我们以处理一个Markdown格式的产品说明书为例。import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.DocumentSplitter; import dev.langchain4j.data.document.loader.FileSystemDocumentLoader; import dev.langchain4j.data.document.splitter.DocumentSplitters; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import java.nio.file.Path; import java.util.List; Service RequiredArgsConstructor public class KnowledgeBaseService { private final EmbeddingModel embeddingModel; // 需要注入一个嵌入模型如OpenAI的text-embedding-ada-002 private final ResourceLoader resourceLoader; private EmbeddingStoreTextSegment embeddingStore; PostConstruct public void initKnowledgeBase() throws Exception { // 1. 加载文档 Resource resource resourceLoader.getResource(“classpath:docs/product_manual.md”); Path documentPath resource.getFile().toPath(); Document document FileSystemDocumentLoader.loadDocument(documentPath); // 2. 分割文档因为模型有上下文长度限制 DocumentSplitter splitter DocumentSplitters.recursive(500, 50); // 每段~500字符重叠50字符 ListTextSegment segments splitter.split(document); // 3. 为每一段文本生成向量Embedding ListEmbedding embeddings embeddingModel.embedAll(segments).content(); // 4. 存储到向量库这里使用内存存储生产环境可用Redis、PgVector等 embeddingStore new InMemoryEmbeddingStore(); embeddingStore.addAll(embeddings, segments); System.out.println(“知识库初始化完成共加载 ” segments.size() “ 个文本片段。”); } public EmbeddingStoreTextSegment getEmbeddingStore() { return embeddingStore; } }5.2 实现检索问答链有了向量存储我们就可以实现问答了。import dev.langchain4j.chain.ConversationalRetrievalChain; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.retriever.EmbeddingStoreRetriever; import dev.langchain4j.store.embedding.EmbeddingStore; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.time.Duration; Service RequiredArgsConstructor public class RagQaService { private final ChatLanguageModel chatModel; private final EmbeddingModel embeddingModel; private final KnowledgeBaseService knowledgeBaseService; public String answerQuestion(String sessionId, String question) { // 1. 获取向量存储 EmbeddingStoreTextSegment embeddingStore knowledgeBaseService.getEmbeddingStore(); // 2. 创建检索器定义检索最相关的3个片段 EmbeddingStoreRetriever retriever EmbeddingStoreRetriever.from(embeddingStore, embeddingModel, 3); // 3. 创建对话记忆 ChatMemory memory MessageWindowChatMemory.withMaxMessages(10); // 4. 构建ConversationalRetrievalChain这是RAG的核心链 ConversationalRetrievalChain chain ConversationalRetrievalChain.builder() .chatLanguageModel(chatModel) .retriever(retriever) .chatMemory(memory) .timeout(Duration.ofSeconds(60)) .build(); // 5. 执行链自动完成“检索相关文档 - 结合历史对话 - 生成答案” return chain.execute(question, sessionId); } }当用户提问“产品A的最大支持用户数是多少”时ConversationalRetrievalChain会将问题转换为向量。在向量库中检索出与“用户数”、“支持”、“最大”等语义最相关的产品说明书片段。将这些片段作为上下文连同之前的对话历史如果有一起发送给LLM。LLM基于这些确凿的知识生成答案比如“根据产品手册第3.2节产品A在标准配置下最大支持10,000个并发用户。”这种方式生成的答案准确性、可信度远高于直接让模型凭空回忆是企业构建可信AI助理的基石。6. 生产环境部署性能、监控与最佳实践将基于langchain-java的应用部署到生产环境需要考虑更多工程化问题。6.1 模型API的稳定性与降级处理直接调用外部模型API是不稳定的网络波动、服务限流都会导致失败。必须实施重试和降级策略。import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import io.github.resilience4j.retry.Retry; import io.github.resilience4j.retry.RetryConfig; import io.github.resilience4j.retry.RetryRegistry; import java.time.Duration; import java.util.function.Supplier; Configuration public class ModelConfiguration { Bean Primary // 优先使用这个被增强的Bean public ChatLanguageModel resilientChatModel(OpenAiChatModel openAiModel) { // 配置重试策略最多重试3次指数退避 RetryConfig config RetryConfig.custom() .maxAttempts(3) .waitDuration(Duration.ofMillis(500)) .retryOnException(e - e instanceof IOException) // 只在IO异常时重试 .build(); Retry retry RetryRegistry.of(config).retry(“llm-api”); // 使用Resilience4j包装模型调用 SupplierString decoratedSupplier Retry.decorateSupplier(retry, () - { // 这里只是示例实际需根据LangChain4j的接口调整 // 理想情况是框架层面支持或使用一个装饰器模式包装ChatModel return openAiModel.generate(userMessage); }); // 实际应用中你可能需要自定义一个实现了ChatLanguageModel接口的包装类 // 在generate等方法内部使用上述重试逻辑 return new ResilientChatModel(openAiModel, retry); } // 降级模型当主模型不可用时切换到一个更简单、更稳定的模型如本地小模型 Bean Qualifier(“fallback”) public ChatLanguageModel fallbackChatModel() { return … // 初始化一个本地或备用的模型 } }6.2 成本控制与用量监控调用商用LLM API是按Token计费的无监控的调用可能导致巨额账单。Token计数与日志利用langchain-java的TokenCountEstimator或模型返回的Usage信息记录每次调用的输入/输出Token数。用户/租户级限流在服务层或API网关层为不同用户设置每分钟/每天的调用次数或Token数上限。缓存策略对于常见、重复的问题如“公司介绍”可以将问答对缓存起来如使用Redis直接返回缓存结果避免重复调用模型。langchain-java的Cache模块可以支持这一点。import dev.langchain4j.model.cache.StructuredCache; import dev.langchain4j.model.cache.StructuredCache; import dev.langchain4j.model.input.structured.StructuredPrompt; import dev.langchain4j.service.AiServices; interface CachedAssistant { StructuredPrompt(“解释一下{{concept}}”) String explainWithCache(StructuredPrompt.Variable(“concept”) String concept); } // 在构建AiServices时注入缓存 StructuredCacheStructuredCacheKey, String cache … // 实现一个基于Redis的Cache Assistant assistant AiServices.builder(Assistant.class) .chatLanguageModel(model) .structuredCache(cache) .build(); // 相同的concept输入会优先从缓存返回6.3 可观测性与调试AI应用的调试比传统软件更复杂因为输入输出是非确定性的。全链路日志开启log-requests和log-responses记录每次与模型交互的原始Prompt和Completion。这对于分析模型“胡言乱语”的原因至关重要。结构化日志将每次调用的sessionId、userMessage、fullPrompt组装后的最终提示词、response、tokenUsage、latency等信息以JSON格式记录到ELK或类似系统中便于分析和审计。Trace集成将AI调用嵌入到现有的分布式追踪系统如OpenTelemetry中让你能在一个请求链路中清晰看到AI调用的耗时和状态。7. 常见陷阱与避坑指南在实际项目中踩过不少坑这里分享几个最典型的陷阱一提示词Prompt设计不当导致效果差这是最常见的问题。LLM对提示词极其敏感。避坑技巧遵循“角色-任务-上下文-格式”四段式结构。明确告诉AI“你是谁”角色、“你要做什么”任务、“你知道什么”上下文、“怎么回答”格式。多使用“少样本提示”Few-shot Prompting在提示词中给出1-2个输入输出的例子效果立竿见影。实操心得不要一次性写死长提示词。将提示词模板化、外部化如存到数据库或配置中心方便随时A/B测试和调整。langchain-java的PromptTemplate支持变量注入非常好用。陷阱二上下文长度Token限制爆炸处理长文档或长对话时很容易超出模型的上下文窗口如GPT-4 Turbo的128K。避坑技巧文档分割如前面RAG示例所示使用RecursiveSplitter等工具合理分割文档控制每段长度并保留少量重叠以避免信息割裂。记忆摘要对于长对话不要无限制地保存全部历史。使用ConversationSummaryMemory定期将旧对话总结成一段摘要只保留摘要和最新对话大幅节省Token。选择性上下文在RAG中使用MaxMarginalRelevanceSearch等检索器在保证相关性的同时增加检索结果的多样性避免塞入大量重复信息的片段。陷阱三工具Tool描述不清导致AI不会用AI调用工具依赖于你对工具方法的Tool注解描述。避坑技巧描述要具体、清晰、无歧义说明输入参数的含义和格式。例如Tool(“根据城市名查询天气”)就比Tool(“查询天气”)好。更好的描述是Tool(“查询指定城市未来三天的天气预报。输入参数cityName: 字符串表示城市名称例如‘北京’、‘New York’。”)。清晰的描述能极大提高工具调用的准确率。陷阱四忽视异步与非阻塞调用在Web服务中同步调用LLM API可能会阻塞网络线程导致服务吞吐量急剧下降。避坑技巧对于耗时较长的AI任务如文档总结、复杂推理一定要采用异步处理。可以利用Spring的Async注解或将任务提交到专门的线程池通过消息队列如Kafka进行异步处理并通过WebSocket或轮询接口向客户端返回结果。langchain-java本身的一些操作如文档嵌入也提供了异步接口要充分利用。陷阱五向量检索的精度问题RAG效果不好很多时候问题出在检索环节没找到最相关的文档。避坑技巧优化嵌入模型不同的嵌入模型如text-embedding-3-smallvstext-embedding-ada-002效果差异很大。对于中文场景可能需要专门优化的中文嵌入模型。混合检索结合向量检索语义相似和关键词检索如BM25。langchain-java社区有一些Retriever的实现支持混合检索能同时捕捉语义和精确关键词匹配。重排序Re-ranking先检索出较多的候选片段如20个再用一个更小、更快的重排序模型对它们进行相关性打分只取Top-K个送给LLM。这能显著提升最终答案的质量。HamaWhiteGG/langchain-java项目正在快速发展中社区活跃。对于Java开发者而言它极大地降低了AI应用开发的门槛让我们能用熟悉的武器库去迎接AI时代。开始的最佳时间就是现在从一个简单的LLMChain开始逐步探索Agent和RAG的威力你会发现为现有系统注入智能从未如此简单直接。