Files
zyt/server/tests/TcmAncientBooksReportProvenanceTest.php
T
2026-10-09 09:36:17 +08:00

79 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
require dirname(__DIR__) . '/vendor/autoload.php';
use app\adminapi\logic\tcm\DiagnosisAiLogic;
use app\adminapi\logic\tcm\PatientAiReportLogic;
use app\adminapi\logic\tcm\PrescriptionAiLogic;
use app\common\service\NihaixiaClinicalSkill;
use app\common\service\TcmAncientBooksReference;
function provenanceExpect(bool $condition, string $message): void
{
if (!$condition) {
fwrite(STDERR, "FAIL: {$message}\n");
exit(1);
}
}
$source = [
'title' => '测试古籍', 'chapter' => '消渴篇', 'path' => '123-测试古籍.txt',
'excerpt' => '原文中谈到消渴的历史记载。',
'line' => 42, 'commit' => TcmAncientBooksReference::COMMIT,
'url' => 'https://github.com/xiaopangxia/TCM-Ancient-Books/blob/'
. TcmAncientBooksReference::COMMIT . '/123-%E6%B5%8B%E8%AF%95%E5%8F%A4%E7%B1%8D.txt#L42',
];
$localizedSource = $source;
$localizedSource['url'] = '';
$localized = TcmAncientBooksReference::localizeSources([$source]);
provenanceExpect($localized === [$localizedSource], 'saved citation drops external URL without losing original text or location');
$json = json_encode([$source], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$diagnosisFormat = new ReflectionMethod(DiagnosisAiLogic::class, 'formatReportRow');
$diagnosis = $diagnosisFormat->invoke(null, [
'report_content' => '{}',
'prompt_version' => 'patient-context-case-explain-nihaixia-ancient-v4',
'ancient_book_sources_json' => $json,
], '');
provenanceExpect($diagnosis['ancient_book_sources'] === [$localizedSource], 'diagnosis report localizes saved book and line');
$oldDiagnosis = $diagnosisFormat->invoke(null, ['report_content' => '{}', 'prompt_version' => 'legacy-v2'], '');
provenanceExpect($oldDiagnosis['ancient_book_sources'] === [], 'old diagnosis report gets no ancient citation');
$patientFormat = new ReflectionMethod(PatientAiReportLogic::class, 'formatReportRow');
$patient = $patientFormat->invoke(null, [
'report_json' => '{}',
'prompt_version' => 'patient-longitudinal-report-nihaixia-ancient-v4',
'ancient_book_sources_json' => $json,
]);
provenanceExpect($patient['ancient_book_sources'] === [$localizedSource], 'patient report localizes saved book and line');
$oldPatient = $patientFormat->invoke(null, ['report_json' => '{}', 'prompt_version' => 'legacy-v2']);
provenanceExpect($oldPatient['ancient_book_sources'] === [], 'old patient report gets no ancient citation');
$anotherSource = $source;
$anotherSource['path'] = '124-测试古籍二.txt';
$anotherSource['line'] = 88;
$anotherSource['url'] = 'https://github.com/xiaopangxia/TCM-Ancient-Books/blob/'
. TcmAncientBooksReference::COMMIT . '/124-%E6%B5%8B%E8%AF%95%E5%8F%A4%E7%B1%8D%E4%BA%8C.txt#L88';
$mergeSources = new ReflectionMethod(PatientAiReportLogic::class, 'mergeAncientBookSources');
$merged = $mergeSources->invoke(null, [$localizedSource], ['ancient_book_sources' => [$source, $anotherSource]]);
$localizedAnother = $anotherSource;
$localizedAnother['url'] = '';
provenanceExpect($merged === [$localizedSource, $localizedAnother], 'different local file lines remain distinct while duplicates collapse');
$prescriptionBody = [
'report' => ['diagnosis' => '保留原有报告'],
'knowledge_source' => NihaixiaClinicalSkill::knowledgeSource(),
'ancient_book_sources' => [$source],
];
$prescriptionBody['knowledge_source']['url'] = 'https://github.com/coinweth/nihaixia-skill/blob/'
. NihaixiaClinicalSkill::COMMIT . '/SKILL.md';
$localizePrescription = new ReflectionMethod(PrescriptionAiLogic::class, 'localizeSourceMetadata');
$prescription = $localizePrescription->invoke(null, $prescriptionBody);
provenanceExpect($prescription['report'] === $prescriptionBody['report'], 'prescription report content is preserved');
provenanceExpect($prescription['knowledge_source']['url'] === ''
&& $prescription['knowledge_source']['path'] === 'SKILL.md', 'saved prescription skill source is local');
provenanceExpect($prescription['ancient_book_sources'] === [$localizedSource], 'saved prescription book citation is local');
echo "TCM ancient-books report provenance contract passed.\n";