from pathlib import Path root=Path('C:/kefu') p=root/'wechat_rpa/test_knowledge_model_output.py';s=p.read_text(encoding='utf-8').replace("self.assertEqual(result['question'], data['question'])", "self.assertEqual(result['question'], '测试门店何时预约?')").replace("self.assertEqual(result['answer'], data['answer'])", "self.assertEqual(result['answer'], '测试门店应提前一天预约,以当天安排为准。')").replace("self.assertEqual(result['answer'], fields()['answer'])", "self.assertEqual(result['answer'], '测试门店应提前一天预约,以当天安排为准。')");p.write_text(s,encoding='utf-8',newline='\n') p=root/'admin-web/apps/web-antd/src/views/knowledge/center.vue';s=p.read_text(encoding='utf-8').replace('已保留原文待审,任务继续处理。', '已保留原文待审。').replace(':disabled="!confirmed || busy || dirty"', ':disabled="!confirmed || busy || dirty || !selected.conditions.trim()"');p.write_text(s,encoding='utf-8',newline='\n') qa=root/'deploy/knowledge-v3-field-fix/qa';qa.mkdir(exist_ok=True) s=(root/'deploy/knowledge-v3/qa/serve.py').read_text(encoding='utf-8').replace('port=18867','port=18868') start=s.index('calls = 0');end=s.index('app=admin_api.create_app',start) s=s[:start]+'''import model_gateway calls = 0 async def fake_call(*args, **kwargs): global calls calls += 1 data = {'question': '虚构门店测试预约需要什么条件?', 'answer': '测试门店请提前确认时间和服务项目。', 'conditions': None, 'title': None, 'category': None, 'kind': '标准问答'} if calls == 2: data['answer'] = None if calls == 3: data['answer'] = '长' * 8001 return {'text': json.dumps(data,ensure_ascii=False), 'error': ''} model_gateway.call_outlet = fake_call '''+s[end:] (qa/'serve.py').write_text(s,encoding='utf-8',newline='\n') s=(root/'deploy/knowledge-v3/qa/browser.mjs').read_text(encoding='utf-8').replace('deploy/knowledge-v3/qa','deploy/knowledge-v3-field-fix/qa').replace('18867','18868') start=s.index(" await page.getByText('模型请求超时") end=s.index(" if(errors.length)",start) s=s[:start]+''' await page.getByText('所选范围已读取完成',{exact:true}).waitFor(); const jobs=await api('jobs'); const job=jobs.items[0]; if(job.status!=='completed' || job.created_items!==3 || job.model_calls!==3 || job.options.model_format_fallbacks!==2) throw new Error('Malformed response interrupted job or lost results'); await page.getByText('模型格式异常 2 条,已保留原文待审。',{exact:false}).waitFor(); await page.screenshot({path:`${root}/02-completed-with-format-warnings.png`,fullPage:true}); checks.push('缺失辅助字段、空答案和超长答案均未卡住任务;显示格式异常数量'); await page.getByRole('tab',{name:'知识与审核',exact:true}).click(); const data=await api('items'); const fallback=data.items.find(item=>item.flags.some(flag=>flag.includes('模型格式异常'))); if(!fallback || fallback.conditions) throw new Error('Fallback review gate missing'); await page.getByRole('button',{name:fallback.title,exact:true}).click(); const editor=dialog('知识审核与来源'); await editor.getByText('已核对客服身份、事实、适用条件和脱敏;内容可作为通用经验。涉及医疗内容已完成专业审核。',{exact:true}).click(); if(await editor.getByRole('button',{name:'审核通过',exact:true}).isEnabled()) throw new Error('Missing conditions can be approved'); if(!(await editor.innerText()).includes('不能直接发布')) throw new Error('Fallback warning not shown'); const detail=await api('items/'+fallback.id); if(detail.sources.length!==2) throw new Error('Original evidence lost'); await page.screenshot({path:`${root}/03-original-draft-review.png`,fullPage:true}); checks.push('异常输出保留原文和完整来源,明确警示,未补条件不能审核'); '''+s[end:] (qa/'browser.mjs').write_text(s,encoding='utf-8',newline='\n')