今天来实现失物登记功能,整体实现类似于之前的丢失登记。
一、功能实现
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、失物登记测试
数据库内容如下:
2、数据修改测试
重新设置一个新的用户id
数据库内容如下:
功能完成。。。。
整体看来,感觉流式输出更适合查询相关的流程。