| import { NextResponse } from 'next/server'; |
| import { getSystemPrompt, generateCompletion } from '@/lib/ollama'; |
| import type { ErrorCategory } from '@/types'; |
|
|
| |
| const TEST_CLINICAL_NOTE = `Patient: John Smith, 65M |
| Chief Complaint: Chest pain |
| |
| Vital Signs: |
| - BP: 145/92 mmHg |
| - HR: 88 bpm |
| - Temp: 98.6°F |
| |
| Current Medications: |
| - Metoprolol 50mg daily |
| - Aspirin 81mg daily |
| |
| Assessment: Patient presents with stable angina. Continue current medications.`; |
|
|
| interface TestPromptRequest { |
| prompt: string; |
| model: string; |
| } |
|
|
| |
| export async function POST(request: Request) { |
| try { |
| const body: TestPromptRequest = await request.json(); |
|
|
| |
| if (!body.prompt || body.prompt.trim().length === 0) { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Prompt is required', |
| }, |
| { status: 400 } |
| ); |
| } |
|
|
| if (!body.model) { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Model selection is required', |
| }, |
| { status: 400 } |
| ); |
| } |
|
|
| |
| const allCategories: ErrorCategory[] = [ |
| 'medication', |
| 'measurement', |
| 'logical', |
| 'missing', |
| 'terminology', |
| ]; |
| const systemPrompt = getSystemPrompt(allCategories, body.prompt); |
|
|
| |
| const response = await generateCompletion({ |
| model: body.model, |
| prompt: `Analyze the following clinical note for documentation errors. Respond with ONLY valid JSON, no additional text or markdown formatting. |
| |
| === CLINICAL NOTE START === |
| ${TEST_CLINICAL_NOTE} |
| === CLINICAL NOTE END ===`, |
| system: systemPrompt, |
| options: { |
| temperature: 0.1, |
| num_predict: 1024, |
| }, |
| }); |
|
|
| |
| let parsed; |
| try { |
| parsed = JSON.parse(response.response); |
| } catch { |
| |
| const codeBlockMatch = response.response.match(/```(?:json)?\s*([\s\S]*?)```/); |
| if (codeBlockMatch) { |
| try { |
| parsed = JSON.parse(codeBlockMatch[1].trim()); |
| } catch { |
| const jsonMatch = response.response.match(/\{[\s\S]*\}/); |
| if (jsonMatch) { |
| parsed = JSON.parse(jsonMatch[0]); |
| } else { |
| throw new Error('Response is not valid JSON'); |
| } |
| } |
| } else { |
| const jsonMatch = response.response.match(/\{[\s\S]*\}/); |
| if (jsonMatch) { |
| parsed = JSON.parse(jsonMatch[0]); |
| } else { |
| throw new Error('Response is not valid JSON'); |
| } |
| } |
| } |
|
|
| |
| if (!parsed || typeof parsed !== 'object') { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Response is not a valid JSON object', |
| }, |
| { status: 400 } |
| ); |
| } |
|
|
| if (!Array.isArray(parsed.errors)) { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Response missing "errors" array', |
| }, |
| { status: 400 } |
| ); |
| } |
|
|
| if (!parsed.summary || typeof parsed.summary !== 'object') { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Response missing "summary" object', |
| }, |
| { status: 400 } |
| ); |
| } |
|
|
| return NextResponse.json({ |
| success: true, |
| data: { |
| errorsFound: parsed.errors.length, |
| sampleResponse: parsed, |
| }, |
| }); |
| } catch (error) { |
| const message = error instanceof Error ? error.message : 'Test failed'; |
|
|
| if (message.includes('timeout') || message.includes('Timeout')) { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Test timed out. Try a simpler prompt.', |
| }, |
| { status: 504 } |
| ); |
| } |
|
|
| if (message.includes('connect') || message.includes('Connection')) { |
| return NextResponse.json( |
| { |
| success: false, |
| error: 'Cannot connect to Ollama server.', |
| }, |
| { status: 503 } |
| ); |
| } |
|
|
| return NextResponse.json( |
| { |
| success: false, |
| error: message, |
| }, |
| { status: 500 } |
| ); |
| } |
| } |
|
|