Langchain4j中AIService学习

1. 什么是 AiServices?

AiServices 是 LangChain4j 提供的一种 "高层级声明式抽象"

它的核心思想是:

你只需要定义一个 Java 接口 (Interface),并加上简单的注解。LangChain4j 框架会在运行时利用 动态代理 技术,自动帮你生成这个接口的实现类。

对比一下:

  • 以前 (ChatLanguageModel): 你得手动写:"请把这句话翻译成英文:" + text

  • 现在 (AiServices): 你定义一个方法 String translate(String text),框架自动帮你填 Prompt,发请求,解析结果。

2. AiServices 有什么好处?

  1. 代码解耦 (Clean Code): 业务逻辑(接口)和 AI 实现细节彻底分离。你不需要在业务代码里到处拼接字符串。

  2. 类型安全 (Structured Output): AI 不再只能返回 String。它可以直接返回 booleanDateEnumList 甚至自定义的 Person 对象。框架会自动提示 AI 输出 JSON 并帮你反序列化。

  3. 功能集成 (All-in-One): 它不仅仅是对话,它把 RAG (知识库)ChatMemory (记忆)Tools (工具调用)Audit (审计) 全部整合在一起。你只需要在构建时配置一下,接口就立刻拥有了这些能力。

3. 核心注解与方法

在使用 AiServices 时,我们主要打交道的是以下几个注解:

注解 作用 示例
@SystemMessage 给 AI 设定"人设"或"系统指令"。 @SystemMessage("你是一个专业的法律顾问")
@UserMessage 定义发给 AI 的具体 Prompt 模板。 @UserMessage("请将 {``{text}} 翻译成 {``{lang}}")
@V 绑定方法参数到模板变量中。 translate(@V("text") String t, @V("lang") String l)
@MemoryId 区分不同用户的记忆(多轮对话用)。 chat(@MemoryId int userId, String msg)

4. 实战 Demo:打造一个"情感分析与翻译助手"

我们继续在你现有的 AiTest 类基础上扩展。这次我们不直接调用 chatLanguageModel.generate,而是创建一个接口。

第一步:定义接口 (在同一个文件或新建文件)

这个接口定义了我们希望 AI 完成的两个功能:

  1. 翻译功能(带参数模板)。

  2. 情感分析功能(要求返回布尔值,看看 AI 是不是真的懂类型转换)。

java 复制代码
// 定义一个内部接口方便测试,实际开发中建议单独建文件
interface SmartAssistant {

    // 功能 1: 简单的对话,设定人设
    @SystemMessage("你是一个说话像古代诗人的助手")
    String chat(String userMessage);

    // 功能 2: 带参数的模板
    // {{message}} 和 {{language}} 会被参数自动替换
    @UserMessage("请将以下内容:'{{message}}' 翻译成目标语言:{{language}}")
    String translate(@dev.langchain4j.service.V("message") String message, 
                     @dev.langchain4j.service.V("language") String language);

    // 功能 3: 结构化输出 (直接返回 boolean)
    @UserMessage("以下这段话是正面的积极评价吗?请只回答 true 或 false:{{text}}")
    boolean isPositive(@dev.langchain4j.service.V("text") String text);
}
第二步:编写测试用例 (AiServicesTest)

将以下代码添加到你的测试类中(或者替换原来的 test 方法)。我们会复用你之前配置好的 apiKey 等变量。

java 复制代码
package com.qcby.langchain4jdemo;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices; // 引入核心类
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class AiServicesTest {

    @Value("${aliyun.ai.key}")
    private String apiKey;

    @Value("${aliyun.ai.apiUrl}")
    private String url;

    @Value("${aliyun.ai.model}")
    private String modelName;

    // 1. 定义接口 (实际项目中通常放在单独的 .java 文件里)
    interface SmartAssistant {
        
        @SystemMessage("你是一个精通多国语言的翻译官,但在闲聊时非常幽默。")
        String chat(String msg);

        @UserMessage("请将这段文字 '{{msg}}' 翻译成 {{lang}},只输出翻译结果,不要废话。")
        String translate(@V("msg") String message, @V("lang") String targetLanguage);

        @UserMessage("请判断这句话的情感是否是积极的?文本:{{text}}")
        boolean analyzeSentiment(@V("text") String text); // 注意返回值是 boolean
    }

    @Test
    public void testAiService() {
        // 2. 准备底层模型 (和之前一样)
        ChatLanguageModel model = OpenAiChatModel.builder()
                .apiKey(apiKey)
                .baseUrl(url)
                .modelName(modelName)
                .build();

        // 3. 【核心步骤】创建 AiService 代理实例
        // 这一步相当于 MyBatis 的 SqlSession.getMapper(UserMapper.class)
        SmartAssistant assistant = AiServices.builder(SmartAssistant.class)
                .chatLanguageModel(model) // 绑定模型引擎
                .build();

        // 4. 像调用普通 Java 方法一样调用 AI
        System.out.println("--- 测试 1: 闲聊 ---");
        String chatResult = assistant.chat("你好,你会写代码吗?");
        System.out.println(chatResult);

        System.out.println("\n--- 测试 2: 翻译 (参数替换) ---");
        String transResult = assistant.translate("Hello World", "中文");
        System.out.println("翻译结果: " + transResult);

        System.out.println("\n--- 测试 3: 结构化输出 (Boolean) ---");
        boolean isHappy = assistant.analyzeSentiment("LangChain4j 真是太好用了,我爱死它了!");
        boolean isSad = assistant.analyzeSentiment("今天的代码全是 Bug,我很绝望。");
        
        System.out.println("第一句是积极的吗? " + isHappy);
        System.out.println("第二句是积极的吗? " + isSad);
    }
}

5. 代码深度解析

当你运行 assistant.translate("Hello World", "中文") 时,LangChain4j 在后台默默做了这些事:

  1. 模板解析: 它读取 @UserMessage 注解,发现里面有两个变量 {``{msg}}{``{lang}}

  2. 参数填充: 它把你的参数 "Hello World" 填入 {``{msg}},把 "中文" 填入 {``{lang}}

  3. Prompt 构建: 最终生成的 Prompt 是:请将这段文字 'Hello World' 翻译成 中文,只输出翻译结果,不要废话。

  4. 发送请求: 带着 @SystemMessage 定义的人设,把 Prompt 发给阿里云。

  5. 结果解析: 拿到 AI 的回复字符串,直接返回给你。

而对于 analyzeSentiment 方法:

  • AI 可能返回了 "Yes""True""是的"

  • AiServices 会尝试把这些自然语言自动解析成 Java 的 boolean 值 (true/false)。

下一步建议

一旦你跑通了这个 Demo,你就掌握了 LangChain4j 最核心的用法。

接下来的进阶玩法是:

  • ChatMemory : 现在的 SmartAssistant 是没记性的,你上一句说你是谁,下一句它就忘了。你可以给 builder 加上 .chatMemory(...)

  • Structured Output (POJO) : 尝试定义一个 Person 类,让 AI 从一段文本里提取姓名和年龄,直接返回 Person 对象。

相关推荐
代码游侠2 小时前
嵌入式开发——ARM Cortex-A7内核和i.MX6处理器相关的底层头文件
arm开发·笔记·嵌入式硬件·学习·架构
优雅的潮叭3 小时前
c++ 学习笔记之 volatile与atomic
c++·笔记·学习
啊阿狸不会拉杆4 小时前
《机器学习》第四章-无监督学习
人工智能·学习·算法·机器学习·计算机视觉
Duang007_4 小时前
【万字学习总结】API设计与接口开发实战指南
开发语言·javascript·人工智能·python·学习
啊阿狸不会拉杆4 小时前
《机器学习》第三章 - 监督学习
人工智能·深度学习·学习·机器学习·计算机视觉
sjg200104144 小时前
GoFrame学习随便记3(待续)
学习
千里马学框架5 小时前
跟着google官方文档学习车载音频Car audio configuration
学习·configuration·音视频·aaos·安卓framework开发·audio·车机
代码游侠5 小时前
ARM嵌入式开发代码实践——LED灯闪烁(C语言版)
c语言·开发语言·arm开发·笔记·嵌入式硬件·学习
好奇龙猫5 小时前
【人工智能学习-AI入试相关题目练习-第八次 】
人工智能·学习