AI Services(接口封装)
大约 2 分钟
第七章:AI Services:用接口定义“能力”(推荐写法)
7.1 你应该把 AI 当成一个可依赖的 Service
如果你的业务代码最终是这样的:
assistant.chat("...");那么它就天然具备:
- 可替换:换模型不改业务代码
- 可测试:接口可 mock
- 可治理:统一入口集中做重试/指标/脱敏
这就是 AI Services 的核心价值:你只定义接口,LangChain4j 生成实现。
7.2 纯 Java:AiServices.create
package com.example.langchain4j.services;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
public class AiServiceExample {
interface Assistant {
String chat(String message);
}
public static void main(String[] args) {
String apiKey = System.getenv("OPENAI_API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalStateException("请先设置环境变量 OPENAI_API_KEY");
}
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName("gpt-4o-mini")
.temperature(0.2)
.build();
Assistant assistant = AiServices.create(Assistant.class, model);
System.out.println(assistant.chat("把“幂等”解释给刚入职的后端同学听。"));
}
}7.3 Spring Boot:@AiService 自动注册(更像“业务开发”)
当你使用 LangChain4j 的 Spring Boot 集成时,启动时会扫描 @AiService 接口并自动生成 Bean。
7.3.1 定义接口
package com.example.langchain4j.services;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;
@AiService
public interface CustomerAssistant {
@SystemMessage("""
你是企业客服助手。
规则:
1) 不确定就说不确定,不要编造。
2) 回答要简洁可执行。
""")
String chat(@UserMessage String message);
}7.3.2 注入使用
package com.example.langchain4j.api;
import com.example.langchain4j.services.CustomerAssistant;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AssistantController {
private final CustomerAssistant assistant;
public AssistantController(CustomerAssistant assistant) {
this.assistant = assistant;
}
@GetMapping("/assistant/chat")
public String chat(@RequestParam String q) {
return assistant.chat(q);
}
}7.4 本章小结
你已经把“模型调用”升级成“接口能力”,后面章节的 Memory、Tools、RAG、Streaming 都会自然挂在这个接口上,业务代码不会被 prompt/SDK 细节污染。下一章我们解决一个上线必踩坑:对话记忆与上下文控制。
