Files
zyt/server/tests/LiveConsultationTransportPolicyTest.php
2026-10-30 13:41:35 +08:00

49 lines
3.4 KiB
PHP

<?php
declare(strict_types=1);
// Reuse the real transport with in-process cURL fakes; never connects to a model.
require __DIR__ . '/TcmTaskScopedTransportR37Test.php';
use app\common\service\ClinicalKnowledgeReference;
use app\common\service\DifyChatService;
$source = 'SYNTHETIC_FULL_CALL_AND_AUTHORIZED_CASE_TAIL';
$liveQuery = '[LIVE_CONSULTATION_POLICY:v1]' . "\n" . $source;
foreach (['authorized_case', 'current_call_only'] as $analysisScope)
foreach (['blocking', 'streaming'] as $mode) foreach ([false, true] as $required) {
$r37TransportRequests = [];
$r37TransportHeaders = [];
$r37TransportAnswer = '{"questions":[],"summary":[],"checks":[],"review":[]}';
$options = ['reference_scope' => 'consultation', 'knowledge_mode' => 'clinical',
'response_contract' => 'live_consultation', 'analysis_scope' => $analysisScope, 'required_files' => $required];
$result = $mode === 'blocking'
? DifyChatService::chat('qwen', ['source' => $source], $liveQuery, 'synthetic-live', [], $options)
: DifyChatService::streamChat('qwen', ['source' => $source], $liveQuery, 'synthetic-live',
static function (string $delta): void {}, null, [], $options);
r37TransportExpect(!empty($result['ok']), 'live transport still completes through real request construction');
r37TransportExpect(count($r37TransportRequests) === 1, 'one generation only');
$sent = $r37TransportRequests[0]['query'];
r37TransportExpect(str_starts_with($sent, '[LIVE_CONSULTATION_RESPONSE:v1]'), 'live response contract reaches actual transport');
r37TransportExpect(!str_contains($sent, '明确给出倾向性结论和可执行建议'), 'live does not inherit conflicting report instructions');
r37TransportExpect(str_contains($sent, '医生提问不等于患者确认') && str_contains($sent, '不补问采脉'), 'source and consultation boundaries retained');
r37TransportExpect(str_contains($sent, $source) && $r37TransportRequests[0]['inputs']['source'] === $source,
'full synthetic source survives request preparation');
r37TransportExpect(ClinicalKnowledgeReference::augmentLiveConsultationQuery($sent, $analysisScope) === $sent,
'live response contract is idempotent');
r37TransportExpect($analysisScope === 'current_call_only'
? str_contains($sent, '本次仅分析本次视频通话的完整对话') && !str_contains($sent, '病历记录与本次患者陈述分开')
: str_contains($sent, '病历记录与本次患者陈述分开'), 'actual transport policy reflects the server-selected analysis scope');
}
foreach (['case', 'consultation'] as $scope) {
$r37TransportRequests = [];
$options = ['reference_scope' => $scope, 'knowledge_mode' => 'evidence', 'response_contract' => 'live_consultation'];
DifyChatService::streamChat('qwen', [], $source, 'synthetic-evidence', static function (string $delta): void {}, null, [], $options);
r37TransportExpect($r37TransportRequests[0]['query'] === $source, 'intermediate extraction retains its evidence-only contract');
}
$r37TransportRequests = [];
DifyChatService::chat('qwen', [], $source, 'synthetic-case', [], ['reference_scope' => 'case', 'response_contract' => 'live_consultation']);
r37TransportExpect(!str_contains($r37TransportRequests[0]['query'], '[LIVE_CONSULTATION_RESPONSE:'),
'live flag alone cannot change a nonconsultation contract');
echo "Live consultation transport policy: {$checks} cumulative checks passed (synthetic, no network)\n";