package com.supervision.springaidemo.controller ;
import cn.hutool.core.io.FileUtil ;
import com.supervision.police.domain.ModelRecordType ;
import com.supervision.police.domain.NoteRecordSplit ;
import com.supervision.springaidemo.dto.QARecordNodeDTO ;
import com.supervision.police.mapper.ModelRecordTypeMapper ;
import com.supervision.police.mapper.NoteRecordSplitMapper ;
import com.supervision.police.service.ModelRecordTypeService ;
import com.supervision.springaidemo.service.ModelMetricService ;
import com.supervision.police.service.RecordService ;
import com.supervision.police.service.NoteCheckRecordService ;
import com.supervision.springaidemo.util.RecordRegexUtil ;
import com.supervision.springaidemo.util.WordReadUtil ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.ibatis.annotations.Param ;
import org.json.JSONObject ;
import org.springframework.ai.chat.ChatResponse ;
import org.springframework.ai.chat.Generation ;
import org.springframework.ai.chat.messages.Message ;
import org.springframework.ai.chat.messages.SystemMessage ;
import org.springframework.ai.chat.prompt.Prompt ;
import org.springframework.ai.ollama.OllamaChatClient ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.util.StopWatch ;
import org.springframework.web.bind.annotation.GetMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RestController ;
import java.io.File ;
import java.time.LocalDateTime ;
import java.util.* ;
import java.util.stream.Collectors ;
/ * *
* 目 前 这 是 效 果 最 好 的 方 案 , 暂 时 先 用 这 个
* /
@RestController
@Slf4j
@RequestMapping ( "exampleChat" )
public class ExampleChatController {
private final OllamaChatClient chatClient ;
@Autowired
private ModelMetricService modelMetricService ;
@Autowired
private NoteCheckRecordService noteCheckRecordService ;
@Autowired
private ModelRecordTypeMapper modelRecordTypeMapper ;
@Autowired
private NoteRecordSplitMapper noteRecordSplitMapper ;
@Autowired
public ExampleChatController ( OllamaChatClient chatClient ) {
this . chatClient = chatClient ;
}
@Autowired
private RecordService recordService ;
@Autowired
private ModelRecordTypeService modelRecordTypeService ;
private static final String exampleTemplate = "" "
我 们 现 在 需 要 以 step by step 的 方 式 进 行 笔 录 的 指 标 分 析 工 作 , 得 到 最 终 的 结 果 并 返 回 。
step1 : 分 析 笔 录 的 内 容 ;
以 下 是 笔 录 的 内 容 :
- - -
{ context }
- - -
step2 : 现 在 给 你 指 标 以 及 指 标 的 释 义 或 例 子 可 协 助 你 参 考 :
指 标 释 义 或 例 子 及 判 断 标 准 :
指 标 名 称 : { metricName }
我 现 在 给 你 为 true 的 例 子 可 供 参 考 : { example } ;
如 果 和 例 子 这 种 情 况 相 反 或 偏 差 较 大 则 为 false ;
如 果 笔 录 中 , 没 有 任 何 笔 录 内 容 涉 及 到 该 项 指 标 , 无 法 进 行 判 断 , 则 为 empty 。
step3 : 现 在 需 要 你 根 据 上 面 提 供 的 所 有 信 息 , 尽 可 能 实 事 求 是 完 成 判 断 :
1. 判 断 结 论 : true / false / empty
2. 得 到 结 论 的 笔 录 原 话 : 从 笔 录 的 对 话 中 , 得 到 该 结 论 的 原 文 ( 一 定 是 摘 抄 的 原 文 且 为 中 文 ) 。 如 果 结 论 为 true , 则 必 须 要 有 原 文 佐 证 !
3. 得 到 结 论 的 原 因 : 分 析 得 出 该 结 论 的 原 因 , 需 明 确 说 明 为 什 么 得 到 该 结 论 , 需 要 参 考 例 子 的 格 式 且 为 中 文 回 复 。 如 果 结 论 为 true / false , 则 必 须 有 原 因 !
step4 : 必 须 以 json 格 式 回 复 , JSON 的 value 内 容 我 给 你 的 提 示 , 在 实 际 输 出 的 时 候 不 需 要 带 上 :
- - -
{ "result" : "结论" , "originalContext" : "笔录对应原话" , "reason" : "原因" }
- - -
好 了 , 现 在 可 以 回 复 了 !
"" " ;
@GetMapping ( "exampleChat" )
public void exampleChat ( ) {
File file = FileUtil . file ( "E:\\jc\\宁夏\\Fw_裴金禄\\裴金禄第一次.docx" ) ;
String context = WordReadUtil . readWord ( file . getPath ( ) ) ;
List < QARecordNodeDTO > qaList = RecordRegexUtil . recordRegex ( context , "裴金禄" ) ;
for ( QARecordNodeDTO qa : qaList ) {
NoteRecordSplit noteRecord = new NoteRecordSplit ( ) ;
noteRecord . setNoteName ( file . getName ( ) ) ;
noteRecord . setPersonName ( "裴金禄" ) ;
noteRecord . setQuestion ( qa . getQuestion ( ) ) ;
noteRecord . setAnswer ( qa . getAnswer ( ) ) ;
noteRecord . setCreateTime ( LocalDateTime . now ( ) ) ;
// if (qa.getAnswer().length() > 500) {
// continue;
// }
//根据提示词分析类型 并保存
// String test = "你现在是一个笔录分析人员,请用四个字描述一下下述内容属于哪种类型的对话?";
String test = "你是一个善于归纳分析问讯笔录的大模型,请用四个字描述下述内容属于哪种类型的对话?对话内容为:" ;
String tip = "你的回答必须严格控制为四个字。" ;
String example = "示例1: 办案警官问:我们是中卫市公安局沙坡头区分局经侦大队的民警(出示工作证件),现依法对你进行讯问,你应当如实回答我们的提问,对与案件无关的问题,你有拒绝回答的权利。你听明白了吗? 张某答:听明白了。回复:{\"type\":\"权利义务\"}。" +
"示例2: 办案警官问: 你的个人情况? 张某答: 我叫裴金禄, 男, 1984年01月10日出生, 藏族, 大学文化, 户籍所在地陕西省西安市雁塔区丈八四路6号7号楼1单元 2304室, 现住陕西省西安市雁塔区丈八四路6号7号楼1单元 2304室, 无业, 居民身份证号码622326198401100090, 联系电话15829319393。回复: {\"type\":\"个人情况\"}。" +
"示例3: 办案警官问: 你的家庭情况? 张某答: 我父亲叫: 裴国智, 今年: 67岁, 退休, 电话: 13519353723; 母亲: 李金芬, 今年: 61岁, 无业; 我弟弟裴金生, 今年: 34岁, 在中石油运输公司上班。回复: {\"type\":\"家庭情况\"}。" ;
List < Message > messages = new ArrayList < > ( List . of ( new SystemMessage ( test + qa . getQuestion ( ) + qa . getAnswer ( ) + tip + example ) ) ) ;
Prompt prompt = new Prompt ( messages ) ;
StopWatch stopWatch = new StopWatch ( ) ;
stopWatch . start ( ) ;
// log.info("开始分析:");
ChatResponse call = chatClient . call ( prompt ) ;
stopWatch . stop ( ) ;
// log.info("耗时:{}", stopWatch.getTotalTimeSeconds());
Generation result = call . getResult ( ) ;
String content = result . getOutput ( ) . getContent ( ) ;
// log.info("问:{}, 答:{}", qa.getQuestion(), qa.getAnswer());
// log.info("分析的结果是:{}", content);
JSONObject jsonObject = new JSONObject ( content ) ;
String type = jsonObject . getString ( "type" ) . trim ( ) ;
System . out . println ( "问:" + qa . getQuestion ( ) + "答:" + qa . getAnswer ( ) ) ;
System . out . println ( "分析的结果是:" + type ) ;
//保存笔录
noteRecord . setRecordType ( type ) ;
recordService . save ( noteRecord ) ;
ModelRecordType exist = modelRecordTypeService . queryByName ( type ) ;
if ( exist = = null ) {
ModelRecordType modelRecordType = new ModelRecordType ( ) ;
modelRecordType . setRecordType ( type ) ;
modelRecordTypeService . save ( modelRecordType ) ;
}
}
// for (QARecordNodeDTO qaRecordNodeDTO : qaList) {
// // 只查入罪指标
// List<ModelMetric> list = modelMetricService.lambdaQuery().likeRight(ModelMetric::getMetricCode, "RZ").list();
// for (ModelMetric modelMetric : list) {
// String systemPrompt = """
// 你是一个善于分析办案笔录的模型,能够根据办案笔录的回答内容,结合给定的例子,实事求是的判断给定指标是否满足。注意,仅根据笔录进行分析,不要做笔录之外的推断。笔录内容可能比较长,可能分多次提交给你。Think step by step
// """;
// List<Message> messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt)));
// Map<String, Object> param = new HashMap<>();
// param.put("context", qaRecordNodeDTO.toString());
// param.put("metricName", modelMetric.getMetricName());
// param.put("example", StrUtil.format(modelMetric.getExample(), MapUtil.of("action", "裴金禄")));
// String format = StrUtil.format(exampleTemplate, param);
// List<Message> userMessageList = new ArrayList<>();
// if (format.length() > 8000) {
// log.info("分段提交");
// for (String s : StrUtil.split(format, 6000)) {
// userMessageList.add(new UserMessage(s));
// userMessageList.add(new AssistantMessage("继续"));
// }
// userMessageList.remove(userMessageList.size() - 1);
// } else {
// userMessageList.add(new UserMessage(format));
// }
// messages.addAll(userMessageList);
//
// RunCheckThread runCheck = new RunCheckThread("裴金禄尝试正则来做", chatClient, noteCheckRecordService, new Prompt(messages), FileUtil.getName(file), format, systemPrompt, modelMetric, 0);
// RunCheckThreadPool.chatExecutor.submit(runCheck);
// }
// }
}
@GetMapping ( "test" )
public List test ( @Param ( "test" ) String test ) {
List < Map > list = new ArrayList < > ( ) ;
List < Message > messages = new ArrayList < > ( List . of ( new SystemMessage ( test ) ) ) ;
Prompt prompt = new Prompt ( messages ) ;
StopWatch stopWatch = new StopWatch ( ) ;
stopWatch . start ( ) ;
log . info ( "开始分析:" ) ;
ChatResponse call = chatClient . call ( prompt ) ;
stopWatch . stop ( ) ;
log . info ( "耗时:{}" , stopWatch . getTotalTimeSeconds ( ) ) ;
Generation result = call . getResult ( ) ;
String content = result . getOutput ( ) . getContent ( ) ;
log . info ( "分析的结果是:{}" , content ) ;
Map < String , Object > resultMap = new HashMap < > ( ) ;
resultMap . put ( "result" , content ) ;
list . add ( resultMap ) ;
return list ;
}
@GetMapping ( "queryRecordType" )
public List < NoteRecordSplit > queryRecordType ( ) {
List < ModelRecordType > types = modelRecordTypeMapper . selectList ( null ) ;
String allType = types . stream ( ) . map ( ModelRecordType : : getRecordType ) . collect ( Collectors . joining ( "." ) ) ;
List < NoteRecordSplit > list = noteRecordSplitMapper . selectList ( null ) ;
for ( NoteRecordSplit record : list ) {
record . setRecordType ( "" ) ;
String test = "你是一个善于总结问讯内容的大模型,请判断以下对话属于【" + allType + "】哪个分类?对话内容为:" ;
String tip = "你的回答必须在所给范围内。" ;
String example = "示例: 办案警官问: 你的家庭情况? 答: 裴金禄回答: 我父亲叫: 裴国智, 今年: 67岁, 退休, 电话: 13519353723;母亲: 李金芬, 今年: 61岁, 无业; 我弟弟裴金生, 今年: 34岁, 在中石油运输公司上班。回复: {\"type\":\"家庭情况\"}。" ;
List < Message > messages = new ArrayList < > ( List . of ( new SystemMessage ( test + record . getQuestion ( ) + record . getAnswer ( ) + tip + example ) ) ) ;
Prompt prompt = new Prompt ( messages ) ;
StopWatch stopWatch = new StopWatch ( ) ;
stopWatch . start ( ) ;
// log.info("开始分析:");
ChatResponse call = chatClient . call ( prompt ) ;
stopWatch . stop ( ) ;
// log.info("耗时:{}", stopWatch.getTotalTimeSeconds());
Generation result = call . getResult ( ) ;
String content = result . getOutput ( ) . getContent ( ) ;
// log.info("问:{}, 答:{}", qa.getQuestion(), qa.getAnswer());
// log.info("分析的结果是:{}", content);
System . out . println ( "问:" + record . getQuestion ( ) + "答:" + record . getAnswer ( ) ) ;
System . out . println ( "分析的结果是:" + content ) ;
record . setRecordType ( content ) ;
}
return list ;
}
@GetMapping ( "test1" )
public void test2 ( @Param ( "id" ) String id ) {
NoteRecordSplit noteRecord = recordService . getById ( id ) ;
String question = noteRecord . getQuestion ( ) ;
String answer = noteRecord . getAnswer ( ) ;
String test = "请从以下对话中提取所有关于" + noteRecord . getRecordType ( ) + "的所有三元组" ;
// String test = "请从以下对话中提取所有三元组,对话内容为:";
String example = "。示例: 办案警官问: 你的家庭情况? 答: 裴金禄回答: 我父亲叫: 裴国智, 今年: 67岁, 电话: 13519353723;母亲: 李金芬, 今年: 61岁; 我弟弟裴金生, 今年: 34岁。" +
"回复:{\"result\":[{\"主体\":\"裴金禄\",\"关系\":\"父子\",\"客体\":\"裴国智\"},{\"主体\":\"裴金禄\",\"关系\":\"母子\",\"客体\":\"李金芬\"},{\"主体\":\"裴金禄\",\"关系\":\"兄弟\",\"客体\":\"裴金生\"},{\"主体\":\"裴国智\",\"关系\":\"年龄\",\"客体\":67},{\"主体\":\"李金芬\",\"关系\":\"年龄\",\"客体\":61},{\"主体\":\"裴金生\",\"关系\":\"年龄\",\"客体\":34}]}。" ;
String a = "你是一个问讯笔录分析师,请分析以下内容中所有规定的三元组信息并补充完整,规定的三元组信息如下:[{startNodeType:'Person',entity:'',endNodeType:'Person',property:'',value:'' },{startNodeType:'Person',entity:'',endNodeType:'Organ',property:'',value:''}],要求返回格式{result:[三元组信息]}。" ;
List < Message > messages = new ArrayList < > ( List . of ( new SystemMessage ( a + question + answer ) ) ) ;
// List<Message> messages = new ArrayList<>(List.of(new SystemMessage(test + question+answer+example)));
Prompt prompt = new Prompt ( messages ) ;
StopWatch stopWatch = new StopWatch ( ) ;
stopWatch . start ( ) ;
log . info ( "开始分析:" ) ;
ChatResponse call = chatClient . call ( prompt ) ;
stopWatch . stop ( ) ;
log . info ( "耗时:{}" , stopWatch . getTotalTimeSeconds ( ) ) ;
Generation result = call . getResult ( ) ;
String content = result . getOutput ( ) . getContent ( ) ;
log . info ( "分析的结果是:{}" , content ) ;
}
}