【langchain4j】AIService(四)
·
langchain4j最重要的开发模式——AIService。提供了许多高层抽象,用起来更方便的api。
引入
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
<version>1.1.0-beta7</version>
</dependency>
这个依赖不能使用ai service吗?
可以用,但你只引这个 starter 不够,AI Service 需要核心 langchain4j 依赖才行。
langchain4j-community-dashscope-spring-boot-starter只负责DashScope(通义千问)模型的自动配置,提供ChatModel/StreamingChatModelBean。- AI Service(
@AiService)是 langchain4j 核心功能,不在这个 starter 里,需要单独引入核心包LangChain4j
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.1.0</version> <!-- 和 starter 版本一致 -->
</dependency>
创建AIService的接口
public interface AiCodeService {
//
// @SystemMessage(" 你是编程助手,解答编程问题和面试问题和求职问题,重点关注3个方向:\n" +
// " 1.某个细分领域的学习路线\n" +
// " 2.提供项目学习建议\n" +
// " 3.分享高频面试题和答题思路")
@SystemMessage(fromResource = "ai.txt")
String chat(String userMessage);
}
系统提示词
1.可以直接使用注解添加提示词
2.也可以指向某个指定文件,在文件中添加提示词
调用
工厂类方式
现在已经创建好aiservice了,那怎么调用呢?
需要创建一个aiserviceFactory,工厂模式的调用方式。
为什么能创建接口的实现类?
步骤 1:接收接口 + 模型,解析接口元数据
作用:拿到你定义的 @AiService 接口,读取方法、注解、返回值类型伪代码
java
运行
// 你调用的方法
public static <T> T create(Class<T> aiServiceInterface, ChatModel model) {
// 1.1 校验必须是接口
if (!aiServiceInterface.isInterface()) {
throw new Exception("必须传入接口");
}
// 1.2 反射解析接口信息(方法、注解、参数)
Method[] methods = aiServiceInterface.getDeclaredMethods();
Annotation[] annotations = aiServiceInterface.getAnnotations();
// 1.3 保存配置:模型、接口信息、解析后的提示词模板
AiServiceMetadata metadata = new AiServiceMetadata();
metadata.setInterfaceClass(aiServiceInterface);
metadata.setChatModel(model);
metadata.setMethods(methods);
// ... 继续下一步
}
步骤 2:创建 InvocationHandler(方法拦截器)
作用:所有接口方法调用都会进入这里,统一执行 AI 逻辑伪代码
java
运行
// 2.1 实现 JDK 原生 InvocationHandler
public class AiServiceInvocationHandler implements InvocationHandler {
private final AiServiceMetadata metadata;
// 构造时传入模型、接口信息、配置
public AiServiceInvocationHandler(AiServiceMetadata metadata) {
this.metadata = metadata;
}
// 🔥 核心:所有接口方法调用都会走这里
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 获取调用方法名、参数
String methodName = method.getName();
Object param = args[0];
// 2. 拼接提示词(@SystemPrompt + 用户参数)
String prompt = assemblePrompt(method, args);
// 3. 调用大模型
ChatResponse response = metadata.getChatModel().chat(prompt);
// 4. 返回结果给调用方
return response.getContent();
}
}
步骤 3:用 JDK Proxy 动态生成接口实现类
作用:在内存中生成字节码,创建一个 “虚拟实现类”伪代码
java
运行
// 3.1 获取类加载器
ClassLoader classLoader = aiServiceInterface.getClassLoader();
// 3.2 要代理的接口(你的 AI 接口)
Class<?>[] interfaces = new Class[]{aiServiceInterface};
// 3.3 绑定拦截器
InvocationHandler handler = new AiServiceInvocationHandler(metadata);
// 🔥 JDK 底层:动态生成接口实现类 + 创建对象
Object proxyInstance = Proxy.newProxyInstance(
classLoader, // 类加载器
interfaces, // 要实现的接口
handler // 方法拦截器
);
步骤 4:返回代理对象(看起来像实现类,实际是代理)
作用:把生成的代理对象强转为你的接口类型并返回伪代码
java
运行
// 强转并返回
return (T) proxyInstance;
步骤 5:外部调用接口方法 → 进入 invoke 执行 AI 逻辑
你调用时
java
运行
MyAiService aiService = AiServices.create(MyAiService.class, model);
String answer = aiService.chat("你好");
底层真实执行流程(伪代码)
java
运行
// 调用 aiService.chat(...)
// 1. 进入代理对象的方法
// 2. 自动跳转到拦截器的 invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 组装提示词
String prompt = "系统提示 + 用户问题:" + args[0];
// 调用通义千问/大模型
String result = model.chat(prompt);
// 返回结果
return result;
}
总结
- 解析接口:反射读取 @AiService 接口、方法、注解
- 创建拦截器:实现 InvocationHandler,统一处理所有方法调用
- 动态生成实现:Proxy.newProxyInstance 在内存生成接口实现类
- 返回代理对象:外观是你的接口,内部是代理
- 方法调用拦截:所有方法 → invoke () → 调用 AI → 返回结果
为什么使用工厂方法,好处是什么?
注解方式
引入依赖
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>1.1.0-beta7</version>
</dependency>
添加注解,原来的工厂要注销
@AiService
public interface AiCodeService {
//
// @SystemMessage(" 你是编程助手,解答编程问题和面试问题和求职问题,重点关注3个方向:\n" +
// " 1.某个细分领域的学习路线\n" +
// " 2.提供项目学习建议\n" +
// " 3.分享高频面试题和答题思路")
@SystemMessage(fromResource = "ai.txt")
String chat(String userMessage);
}
//@Configuration
public class AiCodeServiceFactory {
}
更多推荐



所有评论(0)