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

数据库内容如下:

功能完成。。。。

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

相关推荐
Panesle几秒前
广告推荐算法:COSMO算法与A9算法的对比
人工智能·算法·机器学习·推荐算法·广告推荐
张张张3127 分钟前
4.1学习总结 拼图小游戏+集合进阶
java·学习
hunteritself9 分钟前
DeepSeek重磅升级,豆包深度思考,ChatGPT原生生图,谷歌Gemini 2.5 Pro!| AI Weekly 3.24-3.30
人工智能·深度学习·chatgpt·开源·语音识别·deepseek
拾荒的小海螺9 分钟前
JAVA:使用 Curator 进行 ZooKeeper 操作的技术指南
java·zookeeper·java-zookeeper
夕颜11120 分钟前
记录一下关于 Cursor 设置的问题
后端
凉白开33820 分钟前
Scala基础知识
开发语言·后端·scala
2401_8242568623 分钟前
Scala的函数式编程
开发语言·后端·scala
Panesle39 分钟前
transformer架构与其它架构对比
人工智能·深度学习·transformer
SoFlu软件机器人44 分钟前
Go/Rust 疯狂蚕食 Java 市场?老牌语言的 AI 化自救之路
java·golang·rust
半盏茶香1 小时前
启幕数据结构算法雅航新章,穿梭C++梦幻领域的探索之旅——堆的应用之堆排、Top-K问题
java·开发语言·数据结构·c++·python·算法·链表