Langchain4j
LangChain4J教程
官方文档为:开始使用 | LangChain4j 中文文档
1.入门案例
先创建一个maven工程,导入相关的pom的GAV坐标,pom如下:
1 | <dependency> |
然后,导入你的 OpenAI API 密钥。 建议将 API 密钥存储在环境变量中,以降低公开暴露的风险。(注意,你没有LLM密钥的话,可以使用LangChain4J官方的进行测试)
使用这个之前请确保密钥已经设置在系统Path中:
1 | String apiKey = System.getenv("OPENAI_API_KEY"); |
设置好密钥后,让我们创建一个 OpenAiChatModel 实例:
1 | OpenAiChatModel model = OpenAiChatModel.builder() |
你没有密钥,可以使用官方的演示Demo,如下:
1 | OpenAiChatModel model = OpenAiChatModel.builder() |
官方提示:
如果您没有自己的 OpenAI API 密钥,不用担心。 您可以临时使用我们免费提供的 demo 密钥,用于演示目的。 请注意,当使用 demo 密钥时,所有对 OpenAI API 的请求都需要通过我们的代理, 该代理会在转发请求到 OpenAI API 之前注入真实的密钥。 我们不会以任何方式收集或使用您的数据。 demo 密钥有配额限制,仅限于使用 gpt-4o-mini 模型,并且应该仅用于演示目的。
接下来就可以聊天了:
1 | String answer = model.chat(”问题“); |
输出结果如下:

2.LangChain4J介绍
LangChain4j 的目标是简化将 LLM 集成到 Java 应用程序中的过程。
具体方式如下:
- 统一 API: LLM 提供商(如 OpenAI 或 Google Vertex AI)和嵌入(向量)存储(如 Pinecone 或 Milvus) 使用专有 API。LangChain4j 提供统一的 API,避免了学习和实现每个特定 API 的需求。 要尝试不同的 LLM 或嵌入存储,您可以在它们之间轻松切换,无需重写代码。 LangChain4j 目前支持 15+ 个流行的 LLM 提供商 和 20+ 个嵌入存储。
- 全面的工具箱: 自 2023 年初以来,社区一直在构建众多 LLM 驱动的应用程序, 识别常见的抽象、模式和技术。LangChain4j 将这些提炼成一个即用型包。 我们的工具箱包含从低级提示模板、聊天记忆管理和函数调用 到高级模式如代理和 RAG 的工具。 对于每个抽象,我们提供一个接口以及基于常见技术的多个即用型实现。 无论您是在构建聊天机器人还是开发包含从数据摄取到检索完整管道的 RAG, LangChain4j 都提供多种选择。
- 丰富的示例: 这些示例展示了如何开始创建各种 LLM 驱动的应用程序, 提供灵感并使您能够快速开始构建。
LangChain4j 始于 2023 年初 ChatGPT 热潮期间。 我们注意到与众多 Python 和 JavaScript LLM 库和框架相比,缺少 Java 对应物, 我们必须解决这个问题! 虽然我们的名字中有”LangChain”,但该项目是 LangChain、Haystack、 LlamaIndex 和更广泛社区的想法和概念的融合,并加入了我们自己的创新。
我们积极关注社区发展,旨在快速整合新技术和集成, 确保您保持最新状态。 该库正在积极开发中。虽然一些功能仍在开发中, 但核心功能已经就位,让您现在就可以开始构建 LLM 驱动的应用程序!
为了更容易集成,LangChain4j 还包括与 Quarkus 和 Spring Boot 的集成。
3.LangChain4J模块介绍
Models
Models是LangChain中用于生成文本或执行其他任务的AI模型,通常是预训练的语言模型(如GPT-3、GPT-4等),用于生成文本、回答问题、翻译、总结等任务。Langchain允许你通过API调用这些模型,并将它们集成到
更复杂的应用中。
Prompts
Prompts是用户提供给模型的输入文本,用于引导模型生成特定的输出。Prompts可以是简单的文本,也可以是结构化的模板。Prompts用于控制模型的输出,使其生成符合预期的结果。通过设计好的Prompts,可以引导模型执行特定的任务,如问答、翻译、生成代码等。
Vector Store
Vector store是用于存储和检索文本向量的数据库。文本向量是通过将文本嵌入到高维空间中生成的数值表示,Vector store用于快速检索与査询文本相似的文本片段。这在文档检索、推荐系统、语义搜索等任务中非常有用。
Document Loaders
Document Loaders是用于从不同来源(如文件、数据库、API等)加载文档的工具。Document Loaders用于将外部数据加载到LangChain中,以便进一步处理。例如,可以从PDF、Word文档、网页等加载文本数据。
Text Splitters
Text Splitters用于将长文本分割成较小的片段或块。Text Splitters用于处理长文本,使其适合模型的输入长度限制。这在处理大型文档或长篇文章时非常有用,可以确保模型能够处理整个文本。
Output Parsers
Output Parsers用于将模型的输出解析为结构化数据或特定格式。0utput Parsers用于处理模型的原始输出,将其转换为更易用的格式,如JSON、字典、列表等。这对于后续的数据处理和分析非常有用。
Tools
Tools是Langchain中用于执行特定任务的函数或接口。它们可以是内置的工具,也可以是自定义的工具。Tools用于扩展模型的能力,例如调用外部API、执行计算、查询数据库等。通过Tools,模型可以与环境进行交互,执行更复杂的任务。
LangChain4J的工程结构

SpringBoot集成LangChainJ
注意,我这里用的是硅基流动的免费千问模型,本来我是用deepseek模型,后来发现deepseek不支持function calling。硅基流动是适配openAI的API,所以只要使用对应的pom依赖就可以
这里我还是推荐,学习的小伙伴可以对照官方的文档学习(我就是这样,哈哈哈哈)
工具及版本
JDK17
Maven>=3.9
Langchain4J是1.0.0-alpha1
SpringBoot是3.2.0
准备工作
导入pom依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35<!-- Spring Boot 核心依赖(Web、测试、基础) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- OpenAI starter(自动包含 core) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>1.0.0-alpha1</version>
</dependency>
<!-- 若需直接依赖 core,也显式指定版本 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>1.0.0-alpha1</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.0.0-alpha1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>申请LLM(大模型)的api及对应的key密钥
这里需要自己去硅基流动平台申请,官网地址:https://cloud.siliconflow.cn
选择API密钥

新建密钥:

就可以复制使用了(注意,不要给别人(注意隐私))
配置application.yml文件
yml配置文件如下(model-name可以根据自己的需求选择):
1
2
3
4
5
6
7langchain4j:
open-ai:
chat-model:
api-key: *****
base-url: https://api.siliconflow.cn/v1
model-name: Qwen/Qwen3-8B封装配置类
这里不需要,Springboot已经对其进行自动配置
1.Lowlevel调用
“low-level 调用” 通常指直接操作框架底层组件和 API,而非使用高层封装好的便捷工具或模板。这种方式更接近原始实现,灵活性更高,但需要手动处理更多细节。
具体来说,low-level 调用的特点包括:
- 直接实例化核心组件:例如手动创建
ChatLanguageModel、Message、PromptTemplate等基础对象,而非使用ChatMemory或Agent等高级抽象。 - 手动管理交互流程:需要自己处理输入格式化、模型调用、响应解析等完整流程,而不是依赖框架的自动串联能力。
- 细粒度控制参数:可以直接设置模型的温度(temperature)、最大令牌数(max tokens)等底层参数。
创建Controller类
1 |
|
因为SpringBoot已经自动实现ChatLanguageModel实例(通过yml文件的配置),所以可以直接调用。
通过浏览器就可以进行访问及提问了:http://localhost:8080/ai/low/chat?message=你要问的问题
2.Highlevel调用
“high-level 调用” 是相对于 “low-level 调用” 而言的概念,指的是使用框架封装的高层级 API 和抽象组件,无需关注底层细节,通过简洁的方式实现复杂功能。这种方式更注重快速开发和易用性,适合大多数常见场景。
high-level 调用的核心特点包括:
- 基于高级抽象组件:直接使用封装好的
Agent、ChatAssistant、RunnableChain等高级对象,这些组件内部已整合了模型调用、内存管理、工具调用等能力。 - 自动处理流程细节:框架会自动处理输入格式化、上下文维护、响应解析、多步骤交互等中间环节,开发者无需手动串联各个步骤。
- 简化的 API 接口:通过更少的代码实现复杂功能,例如一行代码添加记忆功能、工具调用能力等。
你需要创建一个AI助手接口
接口代码如下:
1 | public interface Assistant { |
然后对这个接口进行实例化
代码如下:
1 |
|
这样就可以直接使用这个接口进行对话了
创建一个Controller进行实验
1 |
|
同样,你就可以通过浏览器进行访问及提问了:http://localhost:8080/ai/high/chat?message=你要问的问题
3.System系统提示词
**”System 系统提示词” **是指提供给 AI 模型的初始指令或背景信息,用于定义 AI 的角色、行为准则、回答风格等。它通常在对话开始前传递给模型,作为整个交互的 “上下文基准”。
系统提示词的作用类似于给 AI 设定 “操作手册”,例如:
- 定义 AI 的身份(如 “你是一名编程助手”)
- 规定回答格式(如 “请用 Markdown 列表形式回答”)
- 设定行为边界(如 “拒绝回答敏感问题”)
- 提供领域知识(如 “基于 Java 8 语法解释问题”)
这里同样是有HighLevel和LowLevel两种方式设置,前者简单而已。
LowLevel实现系统提示词
这里需要传入SystemMessage用来告诉AI,它扮演的角色或者需要回答的语气,代码如下
1 | //系统提示词(这个是采用lowAPI的方式实现的) |
这里不懂代码含义的可以让ai分析,本质就是调用chat方法时传入了用户信息(UserMessage)和系统提示词(SystemMessage),AI模型会自动根据SystemMessage的指示进行回答UserMessage。
HighLevel实现系统提示词
这里就非常简单了,只需要在AI助手接口中自己需要的方法上面加一个@SystemMessage注解就可以实现系统提示词功能了。
接口代码如下:
1 | public interface Assistant { |
这样,你通过注入接口调用这个方法,就会自动根据你设置的提示词进行回答
Controller类的代码如下:
1 |
|
通过浏览器近可以测试这两种方式了:http://localhost:8080/ai/high/chat?message=你要问的问题
4.会话记忆,会话隔离和会话持久化
会话记忆就是AI可以记住以前的回答,如我先提问了一个问题:“小明进今天考了98分”,你再提问:“小明今天考了多少分”,这时Ai就会回答98分(这是设置了会话记忆)。如果没有设置会话记忆,Ai就会说不知道。
这里同样也有两个方式(LowLevel和HighLevel)进行实现会话记忆,下面我来逐一说明。
MessageWindowChatMemory
MessageWindowChatMemory 是用于管理对话历史的核心组件,专门用于存储和维护一定数量的对话消息(用户消息和 AI 回复),让 AI 能够在多轮对话中 “记住” 上下文。
它的核心特点和作用:
窗口式记忆:
- 如同一个 “消息窗口”,只保留最近的 N 条消息(而非全部历史)
- 例如
MessageWindowChatMemory.withMaxMessages(10)表示最多保留 10 条消息
自动维护对话上下文:
- 自动添加新消息到记忆中
- 当消息数量超过上限时,自动移除最早的消息(类似队列的 FIFO 机制)
- 确保传给模型的始终是最新的对话上下文
与模型调用结合:
- 在每次调用 AI 模型时,会自动将记忆中的消息作为上下文传入
- 使 AI 能够基于历史对话做出连贯回应,而非孤立处理单条消息
MessageWindowChatMemory本身是单个对话的上下文容器
LowLevel实现
只要注入MessageWindowChatMemory,就可以进行会话记忆了,具体代码如下:
1 | //这里初始化MessageWindowChatMemory |
这个代码的意思是:先初始化MessageWindowChatMemory(这里初始化为10,表示这个会话窗口只能存储10条消息,当你要求Ai回答第前11条消息,Ai就会报不知道),同时MessageWindowChatMemory存储的消息和当前用户的消息一同传递到Ai,之后再将Ai回答的消息再次存储到MessageWindowChatMemory。
HighLevel实现
使用HighLevel就比较简单了,只需要在Ai助手接口实例化时进行设置就可以实现会话记忆(不需要手动传递及手动存储),Ai助手接口的实例化代码如下
1 |
|
chatMemoryProvider需要提供一个存储提供器,这里采用的是MessageWindowChatMemory,这样就通过HighLevel设置好了会话记忆。
通过Controller就可以测试了,代码如下:
1 | //这是通过high实现会话记忆 |
ChatMemoryStore
ChatMemoryStore是用于持久化和管理多个对话记忆的组件,它相当于一个 “记忆仓库”,可以存储、检索和管理不同对话会话的 ChatMemory 实例。
核心作用
- 当你需要同时处理多个独立对话(例如多用户场景)时,
ChatMemoryStore可以为每个对话分配独立的ChatMemory(如MessageWindowChatMemory),并通过唯一的sessionId进行区分和管理。 - 解决了单
ChatMemory无法隔离多会话上下文的问题。
与 ChatMemory 的关系
ChatMemory:管理单个对话的消息历史(如最近 10 条消息)。ChatMemoryStore:管理多个ChatMemory实例,通过sessionId区分不同对话,实现多会话记忆的持久化和隔离。
下面就是通过HighLevel和ChatMemoryStore进行会话隔离。
所谓的会话隔离就是值两个人向同一个模型提问时,AI会将两个人的提问分开,不会彼此干扰。就好比:你和小明同时向同一个Ai模型提问,小明告诉Ai自己考了98分,之后你向Ai提问小明考了多少分,Ai会会回答不知道,这就是会话隔离。
其实上面的HighLevel实现会话记忆时,默认就启动了会话隔离,你需要做的是将接口的Chat方法进行修改就可以了,Ai助手的修改方法如下:
1 | String chat( String memoryId, String message); |
注意,一定要标注哪个是ID,哪个是提问消息(用户消息)
Controller类中的方法测试方法为:
1 | //这是通过high实现会话记忆和会话隔离 |
这时就可以在浏览器中测试了:http://localhost:8080/ai/high/chat?memoryId=这里是会话id&message=你要问的问题
你可以通过不同的memoryId进行测试
通过ChatMemoryStore进行会话持久化
我在上面写的都是基于MessageWindowChatMemory进行存储的,MessageWindowChatMemory这个是将会话存储到内存,也就是说在程序退出,这些存储的会话就会丢失。那为了解决这个问题,可以将消息持久化默认为内存改为我们自定义的数据库,下面我来细细的说一下。
其实Ai实现会话记忆是基于ChatMemoryStore中默认的查,增,删方法进行的,要实现会话的持久化,就需要自己重写ChatMemoryStore
下面我来对ChatMemoryStore进行重写:
1 | class MyChatMemoryStore implements ChatMemoryStore { |
同时,在Ai助手实例化的同时设置ChatMemoryStore就可以,原始的ChatMemoryStore是基于内存的,你自己可以在上面的代码将消息存储到数据库(如Mysql数据库)
在Ai助手实例化的同时设置ChatMemoryStore
1 |
|
接下来每次会话就将消息存储到数据库中了。
补充一点
使用LowLevel也可以设置为消息隔离,只需要通过Map集合进行对Controller的修改就可以,也就是将MemoryId设置为Key,MessageWindowChatMemory设置为Value就可以,这里就不做具体说明,还是挺基础的,有兴趣的小伙伴可以自己写写。
5.RAG向量存储
它是 RAG(Retrieval-Augmented Generation,检索增强生成)技术栈中的 “数据仓库”,负责以向量(Embedding)形式高效存储、管理和检索非结构化数据(如文档、PDF、对话记录等),为大模型(LLM)提供 “实时、精准、私有” 的外部知识支持,解决大模型 “知识过时、缺乏私有数据、易产生幻觉” 的核心痛点。
通俗的讲就是:将预先的数据进行向量化,存储到向量数据库中,用户提问Ai时,Ai会结合向量数据库中的内容进行按需回答(如果提问的问题向量数据库中没有,同时Ai也不知道,这时Ai就会回答不知道)。
所以要进行这个步骤,你需要一个向量化模型(这里硅基流动有免费的向量化模型:beg-m3),这个模型是里面的免费模型中最强的。
同样,你也需要准备工作。
初始化Ai助手接口
这里需要设置向量存储(embeddingStore)和向量转换(embeddingModel)
1 |
|
注意:这里使用的向量存储还是基于内存的数据库(是LangChain4J自带的),同时传入的参数就是这两个(由Spring管理,我们不需要管)
如下:
1 |
|
同时需要自己定义嵌入式模型
如下:
1 |
|
好的,接下来就可以测试了
我们写一个Controller类,同时,我会简述代码的含义
1 | package com.cn.org.langchain4jdemo.rag; |
要测试RAG,主要是通过HighLevel进行测试(有兴趣可以自己写一下LowLevel的代码)
定义的**highChat**方法就是用户提问的入口测试方法,就是一个典型的web方法。
定义的**load方法是将需要进行向量化同时存储的数据存储入向量数据库而准备的。这里有一个Tika** 工具,这个工具是Apache 基金会旗下的一个开源工具库,主要用于文档内容提取和类型检测。它能够处理几乎百种不同格式的文件(如文本、PDF、Word、Excel、图片、音频、视频等),并从中提取结构化或非结构化数据(文本内容、元数据等),是处理多格式文档的重要工具。
Tika 的核心功能
- 内容提取从各种文件中提取文本内容,无论文件格式如何(如从 PDF 中提取文字、从图片中提取 OCR 文本、从压缩包中提取内部文件内容等)。例:对于一个 PDF 文档,Tika 可以提取其中的所有文字内容,忽略格式信息(如字体、颜色),得到纯文本。
- 元数据提取提取文件的元数据(描述文件属性的数据),如作者、创建时间、文件大小、格式版本等。例:从一张图片中提取拍摄设备型号、拍摄时间、分辨率等 EXIF 信息。
- 文件类型检测自动识别文件的真实类型(即使文件扩展名被篡改),基于文件的二进制签名而非扩展名判断。例:将一个
.txt扩展名的 PDF 文件正确识别为 PDF 格式。 - 统一接口对所有文件格式提供一致的 API,开发者无需针对不同格式编写单独的处理逻辑,只需调用 Tika 的统一方法即可。
而Langchain4j是集成了Tika模型的,可以直接使用。对于**load**方法中的代码,就是两点:文档读取,文档写入。文档读取就是根据设置按行,按字等(默认是按段落读取)。文档写入就是通过调用我们预先设置的Embedding模型将文档(分割好的)向量化存入向量数据库中。
这里有一个名词**向量化**,可以自己问Ai了解一下。你可以理解为数据唯一数字化。
测试
这里测试,你可以先提问:清明是谁?===>http://localhost:8080/ai/rag/high/chat?message=清梦是谁?
这里Ai应该会告诉你不知道。
再测试
这里先进行数据的载入,就是:http://localhost:8080/ai/rag/load
文档数据:
1 | # 清梦与枕上书 |
这个文档放在resources目录下的documents目录下(命名为001.txt)
再进行提问:http://localhost:8080/ai/rag/high/chat?message=清梦是谁?
这时,Ai就会根据这个文档回答了。
Ai的回答顺序是:向量数据库==>官方API
6.向量数据库持久化
上面那个是基于内存的持久化,也就是说程序退出,内存中的向量数据库就会消失。
那如何进行向量数据库的持久化呢?
很简单,只要重写**EmbeddingStore就可以,下面我就以Redis**为持久化向量数据库为例子。
(不单单只能用Redis,你也可以使用ES等,这里你可以查看官方文档看看向量数据库支持哪些:嵌入(向量)存储 | LangChain4j 中文文档)
好的,也是需要准备工作
开启一个Redis,这里推荐使用Docker进行部署,具体的步骤可以参考Redis官方教程
导入langchain4j对应的redis坐标依赖
1
2
3
4
5<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-redis</artifactId>
<version>1.0.0-alpha1</version>
</dependency>配置yml文件
1
2
3
4
5
6
7
8spring:
data:
redis:
host: 192.168.178.132
port: 6379
password: *****
database: 0
user: default创建RedisConfig类
1 |
|
好了,准备工作好了,下面进行向量数据库持久化的具体操作
重写EmbeddingStore,这里推荐用一个类重写
1 |
|
我简述一下这个代码:这个代码是将原来的InMemoryEmbeddingStore重写为RedisEmbeddingStore,同时传入redis的主机好,密码等。注意,**dimension**是根据你所用模型来配置维度,这里我使用的是beg-m3,它的维度是1024(这里硅基流动可以查看)如果你使用的别的Embedding模型可以去对应官网查看。
注意:indexName和prefix是必备的,前者是用于向量查询时所用的索引下标,后者时向量化数据存储时所用的前缀名。这里可以自己定义。
修改Ai助手接口的初始化
这里就是将原来的**InMemoryEmbeddingStore去掉,(这里Spring会自动配置我们重写的RedisEmbeddingStore,前提是InMemoryEmbeddingStore**初始化已经去掉),具体的接口初始化代码如下:
1 |
|
我来简述一下这个代码,我注释了**InitEmbeddingStore**这个方法,那embeddingStore(embeddingStore)这里就会自动加载重写的那个方法了(这个是Spring的特性)
下面就可以进行测试了
同样,你直接加载文件数据进入向量数据库就可以:http://localhost:8080/ai/rag/load
你查看你的redis数据库,就会发现多了好多数据。(redis查询命令:keys *)
这就是向量数据库的自定义持久化了,是不是很简单?
7.文档分割
所谓的文档分割就是将数据存储到向量数据库时可以选择分割的数据的样式,如果不指定,默认是按段落进行分割。
你只需要在**load**方法中配置DocumentByLineSplitter 分割器就可以,下面来具体说明一下
代码如下:
1 |
|
.documentSplitter(new DocumentByLineSplitter(100,40))就是一个文档分割,DocumentByLineSplitter这个是可以自己定义的,默认是按行进行分割,里面的第一个参数是每一行最多容纳的字数(如果多于这个字数,会将多的字数放到下一行),第二个参数是重叠的字数,也就是当前行和下一行重叠的字数。
你再进行测试====>http://localhost:8080/ai/rag/load
就会发现redis中存储的key多了好多。
8.Function-calling(结构化输入)
这个就是你提问(输入),Ai大模型会根据你的提问自动选择你定义好的函数,这就是结构化输入。
**注意:**使用这个之前,你一定要选择支持结构化输入的模型(这就是为什么我选择阿里的模型,deepseek不支持function-calling)
同时,这里也可以使用LowLevel和HighLevel进行实现。
同样,也是需要准备工作
创建一个工具类(我定义了一个计算功能)
1 |
|
Runnable你可以看作是一个由JAVA提供的模板工厂类,你自己也可以用自己定义的模板。
下面就两个进行演示。
LowLevel实现
1 |
|
我简单描述一下这个代码:
先用ToolSpecification封装一下我们自己定义的function函数(注意,工具类的熟属性名字要和ToolSpecification配置的参数名字一样)。
然后就是通过Spring来动态获取反射类(用于调用我们需要的函数)
你可以将上面的代码让Ai阐述,具体不做太多描述(打字太累)
然后你就可以测试了====>http://localhost:8080/func/api/high/chat?message=我的两个数字是3和8
它就会自动计算了。
HighLevel实现
用HighLevel就比较简单了,首先需要定义自己的函数类:
1 | public class HighCalculator { |
使用Tool注解标注,就是告诉Ai这个是一个functioncalling。
测试方法(Controller类):
1 |
|
然后你就可以测试了====>http://localhost:8080/func/api/high/chat?message=我的两个数字是3和8
它就会自动计算了。
其实,就是通过description或者Tool描述语意匹配功能函数。举例,我定义的函数会加上描述,同时将方法函数和描述提供给Ai,Ai根据你的提问,自动选择匹配哪个方法。(语意匹配)
9.结构化输出
结构化输出,它是在数据处理、系统交互或 API 通信的底层环节中,将原始、非结构化 / 半结构化数据(如二进制流、日志文本、数据库行数据等)转化为格式固定、字段明确、机器可直接解析的结构化数据(如 JSON、Protocol Buffers、CSV 等)的过程。其核心目标是 “让底层数据从‘无规则’变为‘可被程序精准读取和处理’”,是上层应用(如数据分析、业务系统)可靠运行的基础。
我举个例子:
假设我们将上述配置传入大语言模型,并发送提示词:“请解析用户信息:姓名是李四,年龄30岁,身高1.8米,已婚。按照指定格式返回。”
由于配置了强制 JSON 输出和 Schema,模型会严格按照定义返回:
1 | { |
同样,它也是有LowLevel实现和HighLevel实现
LowLevel实现
只需要封装一下Response就可以,代码:
1 |
|
就是设置一下回复格式(这里是使用JSON回复的,如有需要你可以采用别的格式,官方也是使用JSON格式进行演示的)
再将封装的回复格式同提问消息一同交给AI,这样回复的格式就是我们自定义的了。
HighLevel实现
使用HighLevel实现还是比较简单的,只需要封装一个返回类,封装一个接口,将接口交给AIService,AiService就会自动将回复的进行序列化返回。
返回类:
1 |
|
接口
1 | interface PersonService { |
测试类
1 |
|
你可以测试了:GET http://localhost:8080/high/json?message=李四今年28岁,身高1.75米,未婚
输出:
1 | {"name":"李四","age":28,"height":1.75,"married":false} |
对于联网搜索和多模态
联网搜索需要一个WebSearch模型,本质就是将Ai加上一个类似浏览器的搜索功能,当回答不了时,就会进行调用这个Search模型。
多模态就是可以传递给Ai图片,视频等,这些看官方文档就可以,就是封装而已。
联网搜索:Web Search Engines | LangChain4j 中文文档
@by 初榆





