feat: add reviewed follow-up audio patient enrichment
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/** Loopback HTTP server for synthetic transport tests. Never load app/.env or provider credentials. */
|
||||
$directory = getenv('FOLLOWUP_AUDIO_MOCK_DIR');
|
||||
if (!$directory || !is_dir($directory)) { http_response_code(500); exit; }
|
||||
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$scenario = explode('/', trim($path, '/'))[0];
|
||||
$isUpload = str_ends_with($path, '/files/upload');
|
||||
$isChat = str_ends_with($path, '/chat-messages');
|
||||
$record = ['scenario' => $scenario, 'path' => $path, 'upload' => $isUpload, 'chat' => $isChat];
|
||||
$authorization = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
||||
if ($authorization !== 'Bearer synthetic-test-key') { http_response_code(401); echo '{}'; exit; }
|
||||
header('Content-Type: application/json');
|
||||
header('X-Request-Id: mock-request-' . $scenario);
|
||||
if ($isUpload) {
|
||||
$file = $_FILES['file'] ?? [];
|
||||
$record['user'] = $_POST['user'] ?? '';
|
||||
$record['filename'] = $file['name'] ?? '';
|
||||
$record['mime'] = $file['type'] ?? '';
|
||||
$record['sha256'] = isset($file['tmp_name']) && is_file($file['tmp_name']) ? hash_file('sha256', $file['tmp_name']) : '';
|
||||
$types = ['followup-audio.wav' => 'audio/wav', 'followup-audio.mp3' => 'audio/mpeg',
|
||||
'followup-audio.m4a' => 'audio/mp4', 'followup-audio.amr' => 'audio/amr'];
|
||||
$record['size'] = (int) ($file['size'] ?? 0);
|
||||
$record['valid'] = ($file['error'] ?? -1) === UPLOAD_ERR_OK && $record['user'] !== ''
|
||||
&& ($types[$record['filename']] ?? '') === $record['mime'];
|
||||
file_put_contents($directory . '/requests.jsonl', json_encode($record) . "\n", FILE_APPEND | LOCK_EX);
|
||||
if (!$record['valid'] || $scenario === 'upload_reject') { http_response_code(415); echo '{"code":"unsupported_file"}'; exit; }
|
||||
file_put_contents($directory . '/user-' . $scenario, $record['user']);
|
||||
http_response_code(201);
|
||||
echo json_encode(['id' => 'mock-upload-' . $scenario, 'mime_type' => $scenario === 'wrong_type' ? 'image/png' : $record['mime']]);
|
||||
exit;
|
||||
}
|
||||
if (!$isChat) { http_response_code(404); echo '{}'; exit; }
|
||||
$payload = json_decode(file_get_contents('php://input'), true);
|
||||
$record['payload'] = $payload;
|
||||
$record['valid'] = ($payload['user'] ?? '') === trim((string) @file_get_contents($directory . '/user-' . $scenario))
|
||||
&& ($payload['files'] ?? []) === [['type' => 'audio', 'transfer_method' => 'local_file', 'upload_file_id' => 'mock-upload-' . $scenario]]
|
||||
&& ($payload['response_mode'] ?? '') === 'blocking';
|
||||
file_put_contents($directory . '/requests.jsonl', json_encode($record, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX);
|
||||
if (!$record['valid']) { http_response_code(400); echo '{"code":"attachment_required"}'; exit; }
|
||||
if ($scenario === 'chat_reject') { http_response_code(415); echo '{"code":"unsupported_audio","message":"private-body-must-not-escape"}'; exit; }
|
||||
if ($scenario === 'unknown') { http_response_code(524); echo '{"message":"private-body-must-not-escape","task_id":"mock-uncertain-task","conversation_id":"mock-uncertain-conversation"}'; exit; }
|
||||
if ($scenario === 'timeout') { sleep(3); echo '{}'; exit; }
|
||||
if ($scenario === 'malformed_response') { echo '<html>private-body-must-not-escape</html>'; exit; }
|
||||
$transcript = '昨天晚上九点,收缩压126,舒张压82。紫色海豚水晶风车。';
|
||||
$raw = ['schema_version' => 'followup-audio-v1', 'audio_processed' => true,
|
||||
'summary' => '合成血压事实', 'transcript' => $transcript, 'uncertainties' => [], 'items' => [[
|
||||
'kind' => 'blood', 'values' => ['systolic_pressure' => 126, 'diastolic_pressure' => 82],
|
||||
'record_date' => null, 'record_time' => '21:00:00', 'time_period' => null, 'time_estimated' => false,
|
||||
'date_text' => '昨天', 'time_text' => '晚上九点', 'evidence' => [['text' => '昨天晚上九点,收缩压126,舒张压82。', 'start_ms' => 0, 'end_ms' => 500]],
|
||||
'needs_review' => false,
|
||||
]]];
|
||||
if ($scenario === 'text_only') { $raw['audio_processed'] = false; }
|
||||
if ($scenario === 'evidence') { $raw['items'][0]['evidence'][0]['text'] = '音频里根本没有说过的事实'; }
|
||||
if ($scenario === 'extra_field') { $raw['items'][0]['target_id'] = 999; }
|
||||
if ($scenario === 'bad_values') { $raw['items'][0]['values']['unknown_field'] = 'malicious'; }
|
||||
if ($scenario === 'bad_time') { $raw['items'][0]['evidence'][0]['end_ms'] = 3600001; }
|
||||
if ($scenario === 'schema') { unset($raw['transcript']); }
|
||||
$answer = $scenario === 'markdown' ? '```json\n' . json_encode($raw) . '\n```' : json_encode($raw, JSON_UNESCAPED_UNICODE);
|
||||
$response = ['answer' => $answer, 'task_id' => 'mock-task-' . $scenario, 'message_id' => 'mock-message-' . $scenario,
|
||||
'conversation_id' => 'mock-conversation-' . $scenario];
|
||||
if ($scenario === 'omitted') { $response['metadata']['omitted_files'] = [['type' => 'audio']]; }
|
||||
echo json_encode($response, JSON_UNESCAPED_UNICODE);
|
||||
Reference in New Issue
Block a user