feat: add durable ASR-to-patient extraction and guarded review

This commit is contained in:
2026-10-08 15:08:42 +08:00
parent 8bb4bd07ae
commit 13948f5982
34 changed files with 2377 additions and 56 deletions
@@ -0,0 +1,30 @@
<?php
/** Synthetic loopback only. No real credentials or patient text. */
$directory = getenv('FOLLOWUP_AUDIO_PIPELINE_MOCK_DIR');
$uri = $_SERVER['REQUEST_URI'];
$valid = ($_SERVER['HTTP_AUTHORIZATION'] ?? '') === 'Bearer synthetic-key';
header('Content-Type: application/json');
if (str_ends_with($uri, '/audio/transcriptions')) {
$file = $_FILES['file']['tmp_name'] ?? '';
$valid = $valid && ($_POST['model'] ?? '') === 'synthetic-asr' && is_file($file) && filesize($file) < 40000;
file_put_contents($directory . '/requests.jsonl', json_encode(['stage' => 'asr', 'valid' => $valid, 'bytes' => $file ? filesize($file) : 0]) . "\n", FILE_APPEND);
if (!$valid) { http_response_code(400); echo '{}'; return; }
if (str_contains($uri, '/oversized/')) { echo json_encode(['text' => str_repeat('x', 100000)]); return; }
if (str_contains($uri, '/reject/')) { http_response_code(429); echo '{}'; return; }
if (str_contains($uri, '/unknown/')) { http_response_code(500); echo '{}'; return; }
echo json_encode(['text' => '今天早上血糖六点一。'], JSON_UNESCAPED_UNICODE); return;
}
$payload = json_decode(file_get_contents('php://input'), true);
$prompt = $payload['messages'][0]['content'] ?? null;
$valid = $valid && ($payload['model'] ?? '') === 'synthetic-llm' && is_string($prompt)
&& !str_contains($prompt, 'input_audio') && ($payload['response_format']['type'] ?? '') === 'json_schema'
&& ($payload['response_format']['json_schema']['strict'] ?? true) === false && ($payload['max_tokens'] ?? 0) === 8192
&& preg_match('/c_[a-f0-9]{16,64}/', $prompt, $match);
file_put_contents($directory . '/requests.jsonl', json_encode(['stage' => 'extraction', 'valid' => (bool) $valid]) . "\n", FILE_APPEND);
if (!$valid) { http_response_code(400); echo '{}'; return; }
$answer = ['schema_version' => 'followup-audio-transcript-v2', 'summary' => '合成摘要', 'uncertainties' => [], 'items' => [[
'kind' => 'blood', 'values' => ['fasting_blood_sugar' => 6.1], 'record_date' => null, 'record_time' => null,
'date_text' => '今天', 'time_text' => '早上', 'time_period' => '早晨', 'time_estimated' => true, 'needs_review' => true,
'evidence_ids' => [$match[0]],
]]];
echo json_encode(['choices' => [['finish_reason' => 'stop', 'message' => ['content' => json_encode($answer, JSON_UNESCAPED_UNICODE)]]]]);