langchain4j搭建失物招领系统(二)---丢失登记功能

一、意图分析

功能如下:判断用户当前意图

我们改造一下之前的AiAssistant,增加一个判断用户意图的接口

java 复制代码
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "qwenChatModel",
        streamingChatModel = "qwenStreamingChatModel", chatMemoryProvider = "chatMemoryProvider")
public interface AiAssistant {

    String chat(@MemoryId String id, @UserMessage String message);

    Flux<String> chatStream(@MemoryId String id, @UserMessage String message);

    @SystemMessage(fromResource = "/message/system/getIntention.txt")
    IntentionOutput getIntention(@MemoryId String id, @UserMessage String message);

}

定义返回IntentionOutput

java 复制代码
@Data
public class IntentionOutput {

    @Description("意图(1:丢失信息登记2:找到失物登记3:失物查询4:其他)")
    private Integer intention;

    @Description("大模型对用户的输出")
    private String output;

}

定义系统提示词

plain 复制代码
# 角色
你是一位专业的失物招领工作人员,具备高效、负责的工作态度,能够准确判断用户需求并提供恰当的失物招领相关服务。

## 技能
### 技能 1: 判断用户意图
- 仔细分析用户输入内容,精准判断用户的需求是丢失信息登记或者找到失物登记或者失物查询或者其他。
- 如果用户有其他意图,明确告知用户当前功能主要围绕失物招领工作。
- 对用户的输入意图进行标记,分类如下:丢失信息登记、找到失物登记、失物查询、其他

## 限制:
- 只回答与失物招领相关的问题,拒绝回答无关话题。
- 所输出的内容需条理清晰、简洁明了,符合正常沟通逻辑。

增加一个业务类,用来编排业务流程

java 复制代码
@Service
@Slf4j
public class AiChatServiceImpl implements AiChatService {

    @Autowired
    private AiAssistant aiAssistant;

    @Override
    public Flux<String> chatStream(String userId, String message) {
        // 判断用户的意图
        IntentionOutput intention = aiAssistant.getIntention(userId, message);
        log.info("intention:{}", intention);
        switch (intention.getIntention()) {
            case 1:
                // 丢失信息登记
                break;
            case 2:
                // 找到失物登记
                break;
            case 3:
                // 失物查询
                break;
            default:
                // 其他
                return Flux.just(intention.getOutput());
        }
        return Flux.just(intention.getOutput());
    }

}

改造输出控制层,使用我们新定义的业务类

java 复制代码
@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
public class AiController {

    private final AiChatService aiChatService;

    @GetMapping(value = "/chat-stream",produces = MediaType.TEXT_PLAIN_VALUE+";charset=utf-8")
    public Flux<String> chatStream(@RequestParam(value = "message", defaultValue = "Hello") String message,
                             @RequestParam(value = "userId", defaultValue = "111") String userId) {
        return aiChatService.chatStream(userId,message);
    }

}

测试一下:

控制台打印如下:

意图分析功能完成。

二、获取丢失登记信息

功能如下:通过大模型和用户聊天记录,获取丢失物品信息

把之前的AiAssistant,命名为IntentionAssistant

之前的SystemMessage 必须放到类上,这样多个Assistant工作时,才能让系统提示词放到前面,不然可能会清空信息

java 复制代码
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "qwenChatModel",
        streamingChatModel = "qwenStreamingChatModel", chatMemoryProvider = "chatMemoryProvider")
@SystemMessage(fromResource = "/message/system/getIntention.txt")
public interface IntentionAssistant {

    /**
     * 获取用户意图
     */
    IntentionOutput getIntention(@MemoryId String id, @UserMessage String message);

}

增加一个ai service,登记用户信息

java 复制代码
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "qwenChatModel",
        streamingChatModel = "qwenStreamingChatModel", chatMemoryProvider = "chatMemoryProvider")
@SystemMessage(fromResource = "/message/system/registerLost.txt")
public interface AiAssistant {

    /**
     * 注册失物信息
     */
    LostPropertyOutput registerLost(@MemoryId String id, @UserMessage String message);

}

定义返回LostPropertyOutput

java 复制代码
@Data
public class LostPropertyOutput {

    @Description("大模型对用户的输出")
    private String output;

    @Description("用户姓名")
    private String username;

    @Description("用户手机号")
    private String phone;

    @Description("失物名称")
    private String lostName;

    @Description("失物特征")
    private String lostType;

    @Description("是否完成登记")
    private Boolean completed;

}

系统提示词如下:

plain 复制代码
# 角色
你是一位专业且尽责的失物登记专员,始终秉持耐心、细致的态度,精准且全面地登记用户的失物信息,全力以赴保障失物能顺利归还失主。在与用户沟通时,使用礼貌、亲和的语言。

## 技能
### 技能 1: 登记失物信息
- 当用户提供失物相关信息时,从中提取物品信息和相关特征,主动询问用户的姓名和手机号,并准确记录。同时,详细引导用户清晰描述失物的特征,包括颜色、材质、尺寸、特殊标识等关键细节。
- 将登记的姓名、手机号、失物名称(对物品的简单描述,如手机、钱包、狗等,不要包含特征)、失物特征(颜色、材质、尺寸、特殊标识等信息)进行系统整理并记录。
- 根据用户输入情况,准确判断是否完成登记,并标记"true"或"false"。若判断为"false",清晰告知用户还缺少哪些信息。
- 若用户表示没有更多信息或特征,也可以完成登记。

## 限制:
- 仅处理与失物登记紧密相关的内容,拒绝回答无关话题。
- 所输出的内容需严格按照要求的格式进行组织,精准记录关键信息。
- 对于用户反馈的信息,要确保准确记录和及时处理,不得遗漏重要信息。

修改业务代码,增加模型调用

java 复制代码
    @Override
    public Flux<String> chatStream(String userId, String message) {
        // 判断用户的意图
        IntentionOutput intention = intentionAssistant.getIntention(userId, message);
        log.info("intention:{}", intention);
        String output = intention.getOutput();
        switch (intention.getIntention()) {
            case 1:
                // 丢失信息登记
                output = registerLost(userId, message);
                break;
            case 2:
                // 找到失物登记
                break;
            case 3:
                // 失物查询
                break;
        }
        return Flux.just(output);
    }

    private String registerLost(String userId, String message){
        LostPropertyOutput lostPropertyOutput = aiAssistant.registerLost(userId, message);
        log.info("lostPropertyOutput:{}", lostPropertyOutput);
        return lostPropertyOutput.getOutput();
    }

接口调用如下:

控制台输出如下:

可以看到completed从false变成了true

三、保存登记信息

定义一个数据库实体对象来保存登记信息

java 复制代码
@EqualsAndHashCode(callSuper = true)
@Table(name = "lost_register")
@Entity
@Data
@Comment("丢失登记")
public class LostRegisterEntity extends BaseEntity {

    @Comment("用户姓名")
    private String username;

    @Comment("用户手机号")
    private String phone;

    @Comment("失物名称")
    private String lostName;

    @Comment("失物特征")
    private String lostType;

}

修改登记方法,增加保存方法

java 复制代码
    private String registerLost(String userId, String message){
        LostPropertyOutput lostPropertyOutput = aiAssistant.registerLost(userId, message);
        log.info("lostPropertyOutput:{}", lostPropertyOutput);
        if (lostPropertyOutput.getCompleted()){
            LostRegisterEntity lostRegisterEntity = new LostRegisterEntity();
            BeanUtils.copyProperties(lostPropertyOutput, lostRegisterEntity);
            lostRegisterRepository.save(lostRegisterEntity);
        }
        return lostPropertyOutput.getOutput();
    }

页面调用:

控制台输出:

数据库查看:

相关推荐
半部论语3 分钟前
SpringMVC 中的DispatcherServlet生命周期是否受Spring IOC 容器管理
java·后端·spring
Asthenia041222 分钟前
JavaSE-常见排序:Arrays/Collections/List/StreamAPI
后端
IT瘾君25 分钟前
Windows中IDEA2024.1的安装和使用
java·intellij-idea·idea
Asthenia041229 分钟前
深入浅出分析JDK动态代理与CGLIB动态代理的区别
后端
孤客网络科技工作室32 分钟前
每天学一个 Linux 命令(7):cd
java·linux·前端
邴越32 分钟前
人工智能、机器学习经典计算机课程
人工智能·机器学习
快乐非自愿42 分钟前
Netty源码—10.Netty工具之时间轮
java·unity·.net
快来卷java1 小时前
常见集合篇(二)数组、ArrayList与链表:原理、源码及业务场景深度解析
java·数据结构·链表·maven
HABuo1 小时前
【YOLOv8】YOLOv8改进系列(11)----替换主干网络之MobileNetV4
人工智能·深度学习·yolo·目标检测·计算机视觉
追逐时光者1 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 32 期(2025年3.24-3.31)
后端·.net