用户反馈:说「我要发布专业发展」没直接出表单,先被反问「要选哪个栏目」, 答完出来表单,「所属栏目」却还是空的要再选一次 —— 一件事问了两遍。 两处根因: 1) profession.publish 的说明只写了「调用前必须确认所属栏目 moduleId 与标题」, 漏了公告 / 宿舍 / 活动 / 作业四个发布工具都有的那句「缺失就直接调用本工具, 系统会弹出完整表单让用户填写,不要用文字反复追问」—— 模型读到「必须确认」 就照字面先去口头确认了; 2) 「发布专业发展」不在裸意图直达表里,这句必然要过一轮模型。 改动: - 工具说明按另外四个发布工具的同款句式补齐(说明词是模型唯一的施工图); - IntentShortcut 新增「发布专业发展记录」意图(仅教职工),说「我要发布专业发展」 直接弹表单;栏目是学校自建的、各校 id 不同,所以**不预置**, 由用户就在表单里选 —— 这正是「直接出表单选栏目」; - 契约测试 everyPublishToolTellsTheModelNotToKeepAskingInWords:凡是名字以 .publish 结尾的工具,说明里必须带「不要用文字反复追问」(漏写会被测出来); - IntentDirectFormTest 补两条:教职工直达出表单(含栏目下拉与代取地址、且不预置 栏目)、学生落回模型。 配套(前端 86e3a10):即便真的先问了一轮再弹表单,对话里定好的值也会被对齐到 选项取值(数字 71 → "71",名称「数学」→ SUB02),表单里不再重复问。
This commit is contained in:
@@ -79,6 +79,7 @@ class IntentDirectFormTest {
|
||||
settings.getModules().put("campusnotice", "http://base.yunhaixingtong.com/campusnotice");
|
||||
settings.getModules().put("dormnotice", "http://base.yunhaixingtong.com/dormnotice");
|
||||
settings.getModules().put("familyactivity", "http://base.yunhaixingtong.com/familyactivity");
|
||||
settings.getModules().put("profession", "http://base.yunhaixingtong.com/profession");
|
||||
registry = new ToolRegistry(settings);
|
||||
registry.init();
|
||||
|
||||
@@ -281,6 +282,51 @@ class IntentDirectFormTest {
|
||||
assertEquals("(模型回复)", resp.getReply());
|
||||
}
|
||||
|
||||
/* ==================== 教师:发布专业发展记录 ==================== */
|
||||
|
||||
/**
|
||||
* 「我要发布专业发展」必须**直接**弹表单,而不是先被模型反问「你要发到哪个栏目」。
|
||||
*
|
||||
* <p>用户反馈的原话:说「我要发布专业发展」被问了一轮栏目,答完才出表单,
|
||||
* 表单里却还留着空的「所属栏目」要再选一次 —— 同一件事问了两遍。
|
||||
* 栏目是学校自建的(各校 id 不同),所以直达时不预置,直接交给表单里的下拉选。
|
||||
*/
|
||||
@Test
|
||||
void teacherSayingPublishProfessionRecordGetsPublishFormWithoutCallingLlm() {
|
||||
ChatResponse resp = chat(EXPLODING_LLM, "我要发布专业发展", caller(AgentRole.TEACHER));
|
||||
|
||||
assertNotNull(resp.getForm(), "应直接下发表单");
|
||||
assertEquals("profession.publish", resp.getForm().getTool());
|
||||
assertTrue(resp.getForm().isWrite(), "是写操作,前端要二次确认");
|
||||
assertEquals("/record/new", resp.getForm().getLandingPath());
|
||||
assertTrue(resp.getReply().contains("所属栏目"),
|
||||
"引导语要点明表单里就能选栏目,实际:" + resp.getReply());
|
||||
|
||||
// 「所属栏目」是必填下拉,且带着「用用户自己的登录态去取栏目树」的地址
|
||||
FormField moduleId = field(resp, "moduleId");
|
||||
assertEquals("select", moduleId.getWidget(), "栏目应是下拉,不该让用户手填栏目编号");
|
||||
assertTrue(moduleId.isRequired(), "栏目必填");
|
||||
assertNotNull(moduleId.getOptionCall(), "栏目下拉应带上「代取地址」");
|
||||
assertEquals("/profession/api/moudule/ModuleTree", moduleId.getOptionCall().getPathAndQuery());
|
||||
|
||||
// 栏目**不能**被直达预置:各校栏目 id 不同,硬编码必然出错
|
||||
assertFalse(resp.getForm().getPreset().containsKey("moduleId"),
|
||||
"直达不应预置栏目,实际 preset:" + resp.getForm().getPreset());
|
||||
|
||||
// 发布页是全字段表单(与模块页 RecordEdit.vue 对齐)
|
||||
assertTrue(resp.getForm().isAllFields(), "发布表单应渲染全部字段");
|
||||
assertNotNull(field(resp, "title"));
|
||||
assertNotNull(field(resp, "remark"));
|
||||
assertNotNull(field(resp, "fileIds"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void studentSayingPublishProfessionRecordFallsThroughToModel() {
|
||||
ChatResponse resp = chat(ECHO_LLM, "我要发布专业发展", caller(AgentRole.STUDENT));
|
||||
assertNull(resp.getForm(), "学生不该拿到发布专业发展表单");
|
||||
assertEquals("(模型回复)", resp.getReply());
|
||||
}
|
||||
|
||||
/* ==================== 不该被劫持的情况 ==================== */
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user