langchain4j搭建失物招领系统(五)---实现失物登记功能-大模型流式输出

今天来实现失物登记功能,整体实现类似于之前的丢失登记。

一、功能实现

1、失物数据定义

定义一个失物数据的数据库实体对象

java 复制代码
@EqualsAndHashCode(callSuper = true)
@Table(name = "lost_property")
@Entity
@Data
@Comment("失物表")
public class LostPropertyEntity extends BaseEntity {

    @Comment("捡到失物的用户姓名")
    private String username;

    @Comment("捡到失物的用户手机号")
    private String phone;

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

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

}

定义相应的查询工具类(用来更新操作)

java 复制代码
@Component
@Slf4j
public class LostPropertyTools {

    @Autowired
    private LostPropertyRepository lostPropertyRepository;

    @Tool("根据手机号查询物品登记信息")
    public List<LostPropertyEntity> queryLostPropertyByPhone(@P(value = "用户手机号") String phone) {
        log.info("根据手机号查询物品登记信息,手机号: {}", phone);
        return lostPropertyRepository.findAllByPhone(phone);
    }

}

2、大模型定义

定义一个流式功能的大模型,这次使用qwq-32b模型,支持function call,不过该模型只支持流式输出。

java 复制代码
@Configuration
public class ChatConfig {

    public static final String QAQ_CHAT_BEAN = "qwenQaQStreamingChatModel";

    @Bean(QAQ_CHAT_BEAN)
    public StreamingChatLanguageModel qwenStreamingChatModel() {
        return QwenStreamingChatModel.builder()
                .apiKey(System.getenv("ALI_AI_KEY"))
                .modelName("qwq-32b")
                .build();
    }


}

AI助手定义,使用Flux接受返回数据

java 复制代码
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, streamingChatModel = QAQ_CHAT_BEAN,
        tools = {"chatHistoryTools", "lostPropertyTools"})
public interface LostPropertyAssistant {

    /**
     * 登记失物信息
     */
    @SystemMessage(fromResource = "/message/system/registerLostProperty.txt")
    @UserMessage("当前sessionId:{{sessionId}};用户当前消息:{{message}}")
    Flux<String> registerLostProperty(@V("sessionId") String id, @V("message") String message);

}

3、提示词定义

整体类似于之前的丢失登记,增加了对于输出的描述(ps:这个提示词调试了好久。。。)

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

## 技能
### 技能 1: 登记失物信息
- 每次对话,需要调用读取用户历史对话内容工具获取用户对话历史。
- 如果用户已经输入了手机号,调用queryLostPropertyByPhone函数查询用户丢失物品的信息。若能查询到数据,可能有多条数据,将其与用户已输入的物品信息进行匹配(比较失物名称和失物特征是否是能匹配),最多返回一条已经匹配的数据,并填充id字段(返回记录id),并记录,判断用户意图是否为补充数据。若判断"是",询问用户是否要补充数据。若判断"否",则直接进入正常登记流程,无需向用户说明数据库查询情况。
- 当用户提供失物相关信息时,从中提取物品信息和相关特征,主动询问用户的姓名和手机号,并准确记录。同时,详细引导用户清晰描述失物的特征,包括颜色、材质、尺寸、特殊标识等关键细节。
- 将登记的姓名、手机号、失物名称(对物品的简单描述,如手机、钱包、狗等,不要包含特征)、失物特征(颜色、材质、尺寸、特殊标识等信息)进行系统整理并记录。
- 根据用户输入情况,准确判断是否完成登记,并标记"true"或"false"。若判断为"false",清晰告知用户还缺少哪些信息。
- 若用户表示没有更多信息或特征,也可以完成登记。

## 限制:
- 仅处理与失物登记紧密相关的内容,拒绝回答无关话题。
- 所输出的内容需严格按照要求的格式进行组织,精准记录关键信息,禁止输出其他非json格式以外的内容,不要使用markdown语言输出。
- 对于用户反馈的信息,要确保准确记录和及时处理,不得遗漏重要信息。
- 要充分结合用户的历史对话记录,自然地承上启下,与用户进行协商,禁止机械重复话术,禁止重复或者相似的回复。
- 如果判断完成登记,必须要准确告诉用户已经完成登记。

## 输出格式
需要识别下面的JSON Schema,返回相应的json内容,输出JSON Schema 描述如下:
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "LostPropertyOutput",
  "type": "object",
  "properties": {
    "output": {
      "type": "string",
      "description": "大模型对用户的输出"
    },
    "username": {
      "type": "string",
      "description": "用户姓名"
    },
    "phone": {
      "type": "string",
      "description": "用户手机号"
    },
    "lostName": {
      "type": "string",
      "description": "失物名称"
    },
    "lostType": {
      "type": "string",
      "description": "失物特征"
    },
    "completed": {
      "type": "boolean",
      "description": "是否完成登记"
    },
    "id": {
      "type": "number",
      "description": "数据库记录id"
    }
  },
  "required": ["output", "completed"]
}

4、业务流程修改

增加一个registerLostProperty方法,实现如下:

java 复制代码
    private String registerLostProperty(String userId, String message) {
        StringBuilder sb = new StringBuilder();
        lostPropertyAssistant.registerLostProperty(userId, message)
                .doOnNext(sb::append)
                .blockLast();
        log.info("registerLostProperty sb:{}", sb);
        LostPropertyOutput lostPropertyOutput = JsonUtils.fromJson(sb.toString(), LostPropertyOutput.class);
        if (lostPropertyOutput.getCompleted()) {
            LostPropertyEntity lostPropertyEntity = new LostPropertyEntity();
            BeanUtils.copyProperties(lostPropertyOutput, lostPropertyEntity);
            lostPropertyRepository.save(lostPropertyEntity);
        }
        return lostPropertyOutput.getOutput();
    }

修改switch语句:

二、功能测试

1、失物登记测试

访问http://127.0.0.1:8080/

数据库内容如下:

2、数据修改测试

重新设置一个新的用户id

数据库内容如下:

功能完成。。。。

整体看来,感觉流式输出更适合查询相关的流程。

相关推荐
程序员岳焱1 分钟前
Java 高级泛型实战:8 个场景化编程技巧
java·后端·编程语言
workflower9 分钟前
以光量子为例,详解量子获取方式
数据仓库·人工智能·软件工程·需求分析·量子计算·软件需求
钢铁男儿11 分钟前
C# 类和继承(扩展方法)
java·servlet·c#
壹氿13 分钟前
Supersonic 新一代AI数据分析平台
人工智能·数据挖掘·数据分析
饮长安千年月17 分钟前
JavaSec-SpringBoot框架
java·spring boot·后端·计算机网络·安全·web安全·网络安全
移动开发者1号18 分钟前
Android 大文件分块上传实战:突破表单数据限制的完整方案
android·java·kotlin
代码匠心19 分钟前
从零开始学Flink:揭开实时计算的神秘面纱
java·大数据·后端·flink
张较瘦_20 分钟前
[论文阅读] 人工智能 | 搜索增强LLMs的用户偏好与性能分析
论文阅读·人工智能
我不是小upper31 分钟前
SVM超详细原理总结
人工智能·机器学习·支持向量机
jie1889457586634 分钟前
C++ 中的 const 知识点详解,c++和c语言区别
java·c语言·c++