网站免费建站app,杭州网络运营公司排名,主动创新网站内容建设,网站主要的设计内容主题前言
在上一篇文章中#xff0c;我们见证了AiService注解的惊人威力。仅仅通过定义一个Java接口#xff0c;我们就实现了一个功能完备的AI聊天服务。这感觉就像魔法一样#xff01;
但作为专业的工程师#xff0c;我们知道“任何足够先进的技术#xff0c;都与魔法无异”…前言
在上一篇文章中我们见证了AiService注解的惊人威力。仅仅通过定义一个Java接口我们就实现了一个功能完备的AI聊天服务。这感觉就像魔法一样
但作为专业的工程师我们知道“任何足够先进的技术都与魔法无异”。今天我们的任务就是揭开这层魔法的面纱深入理解其背后支撑我们与AI进行高质量对话的三大支柱
语言模型 (Models)AI的“大脑”我们如何理解并与它交互。提示模板 (Prompt Templates)控制我们对AI“说什么”的艺术实现动态、可复用的指令。输出解析器 (Output Parsers)驯服AI的“输出”让它返回我们需要的Java对象而不仅仅是文本。
掌握了这三者你将从一个简单的AI“调用者”蜕变为一个能精确控制AI行为的“指挥家”。
第一部分再探模型 (Models) - AI的“大脑”
在application.properties中我们配置了langchain4j.open-ai.chat-model.*等属性并通过LangChain4jConfig创建了一个ChatLanguageModel类型的Bean。
ChatLanguageModel是LangChain4j中的一个核心接口它代表了所有聊天式AI模型如GPT-3.5/4, DeepSeek-Chat的统一抽象。你可以把它想象成Java JDBC规范中的DataSource接口它为所有不同厂商的数据库提供了统一的访问标准。
我们配置的OpenAiChatModel是这个接口的一个具体实现。如果我们想换成Google的Gemini模型只需引入langchain4j-google-vertex-ai依赖并创建一个VertexAiChatModel的Bean即可而我们上层的业务代码如Assistant接口几乎无需改动。这就是面向接口编程的威力。
核心概念
ChatLanguageModel: 用于一次请求-响应的交互。StreamingChatLanguageModel: ChatLanguageModel的子接口用于流式响应。AI的回答会一个词一个词地“流”回来能极大地提升用户体验我们将在后续文章中探讨它。
第二部分提示模板 (Prompt Templates) - 控制AI的“输入”
在上一篇中我们使用了简单的assistant.chat(userMessage)。LangChain4j只是将userMessage作为用户提问直接发给了AI。但如果我们想让AI扮演特定角色或者根据多个动态参数来提问呢这时就需要提示模板。
在LangChain4j中我们可以通过UserMessage注解和{{...}}占位符来创建强大的提示模板。
实战创建一个食谱生成器
让我们来改造Assistant接口让它能根据菜系和原料生成食谱。 修改Assistant接口 package com.example.aidemoapp.service;import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;AiService
public interface Assistant {SystemMessage(You are a polite assistant)String chat(String userMessage);// 新增一个使用模板的方法UserMessage(请创建一个 {{dish_type}} 菜肴的食谱。 主要食材是{{ingredients}}。 请提供包含标题、简要描述、所需食材列表以及逐步操作说明的完整食谱。)String createRecipe(V(dish_type) String dish_type, V(ingredients) String ingredients);
}代码解析 我们在UserMessage注解中使用了Java 15的文本块三引号方便编写多行提示。{{dish_type}}和{{ingredients}}是占位符。LangChain4j会自动将createRecipe方法的dish_type参数值填充到{{dish_type}}占位符中ingredients参数同理。 在ChatController中调用新方法 package com.example.aidemoapp.controller;// ... imports ...RestController
RequestMapping(/api/v2/chat)
RequiredArgsConstructor
public class ChatController {private final Assistant assistant;GetMappingpublic String chat(RequestParam(message) String message) {return assistant.chat(message);}GetMapping(/recipe)public String recipe(RequestParam String dishType, RequestParam String ingredients) {return assistant.createRecipe(dishType, ingredients);}
}现在当你请求GET /api/v2/chat/recipe?dishTypeSichuaningredientstofu,garlic,chili时LangChain4j会向AI发送一个被完整填充的、结构化的Prompt从而得到一个高质量的食谱。
第三部分输出解析器 (Output Parsers) - 控制AI的“输出”
上面的食谱生成器返回的是一个长字符串。在真实应用中我们更希望得到一个结构化的Java对象POJO以便于在前端展示或进行后续处理。
LangChain4j的AiServices能做到这一点只要你将方法的返回类型从String改为一个自定义的Java类LangChain4j就会自动指示AI以JSON格式输出并自动将JSON反序列化为你的Java对象。这就是输出解析器的魔力
实战将食谱输出为Java对象 创建Recipe POJO 在com.example.aidemoapp下创建dto包并新建Recipe.java类。 package com.example.aidemoapp.dto;import lombok.Data;
import java.util.List;Data // Lombok注解自动生成getter, setter, toString等
public class Recipe {private String title;private String description;private ListString ingredients;private ListString instructions;
}再次修改Assistant接口 我们将createRecipe方法的返回类型改为Recipe。 // ... imports ...
import com.example.aidemoapp.dto.Recipe; // 引入Recipe类AiService
public interface Assistant {SystemMessage(You are a polite assistant)String chat(String userMessage);// 新增一个使用模板的方法UserMessage(请创建一个 {{dish_type}} 菜肴的食谱。 主要食材是{{ingredients}}。 请提供包含标题、简要描述、所需食材列表以及逐步操作说明的完整食谱。)Recipe createRecipe(V(dish_type) String dish_type, V(ingredients) String ingredients);
}提示词增强我们明确在提示中要求AI以JSON格式返回并描述了JSON的结构。虽然LangChain4j在很多情况下会自动处理但明确地指示AI可以极大地提高成功率和稳定性。 修改ChatController // ... imports ...
import com.example.aidemoapp.dto.Recipe;// ...
public class ChatController {// ... chat和recipe方法 ...GetMapping(/recipe-object)public Recipe recipeObject(RequestParam String dishType, RequestParam String ingredients) {return assistant.createRecipeAsObject(dishType, ingredients);}
}由于RestController的存在Spring Boot会自动将返回的Recipe对象序列化为JSON字符串作为HTTP响应返回给前端。
现在当你请求GET /api/v2/chat/recipe-object?dishTypeItalianingredientspasta,tomatoes,basil时你将直接得到一个干净的、结构化的JSON响应
源码获取
本文中所有实战代码均已同步更新至Gitee仓库方便您下载、运行和学习。
源码地址https://gitee.com/chaocloud/springboot-langchain4j-demo
总结
今天我们揭开了LangChain4j高效开发的神秘面纱。我们学习了
Models是连接AI大脑的统一接口。Prompt Templates (UserMessage和{{...}}) 让我们能精确地、动态地控制输入。Output Parsers (通过改变返回类型) 让我们能将AI的输出从非结构化的文本转换为结构化的、可被程序直接利用的Java对象。
我们已经从简单的“你问我答”进化到了可以与AI进行可预测、结构化交互的新阶段。但这还不够我们的AI助手还是“金鱼般的记忆”每次对话都是一次全新的开始。如何让它记住上下文进行真正的多轮对话呢 下一篇预告 《Java大模型开发入门 (7/15)让AI拥有记忆 - 使用LangChain4j实现多轮对话》—— 我们将为我们的Assistant装上“记忆芯片”探索LangChain4j中的ChatMemory机制打造一个能真正联系上下文的智能聊天机器人