Implementation Examples
This guide provides practical code examples for integrating with the Knidian AI API in various programming languages. These examples demonstrate how to use both the standard and streaming endpoints for generating differential diagnoses.
JavaScript/Node.js Examples
Standard Request (Node.js)
This example demonstrates how to make a standard POST request to the /diagnose
endpoint using Node.js with the axios
library:
const axios = require('axios');
async function getDifferentialDiagnosis() {
const API_KEY = 'your_api_key';
const API_URL = 'https://api.knidian.ai/diagnose';
try {
const response = await axios.post(
API_URL,
{
clinical_history: "A 45-year-old male presents with chest pain, shortness of breath, and fatigue for the past 3 days. The pain is described as pressure-like, radiating to the left arm, and worsens with exertion. He has a history of hypertension and hyperlipidemia, and his father had a myocardial infarction at age 50.",
language: "en"
},
{
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
}
}
);
// The response.data directly contains the DifferentialDiagnosisDto
const diagnosis = response.data;
// Process the diagnosis
console.log('Triage Level:', diagnosis.triage.triage_level);
console.log('Triage Recommendation:', diagnosis.triage.triage_recommendation);
// Display the top diseases
diagnosis.diagnosis.diseases.forEach((disease, index) => {
console.log(`\nDisease ${index + 1}: ${disease.name} (${disease.icd10_code})`);
console.log(`Probability: ${disease.probability * 100}%`);
console.log(`Why: ${disease.why}`);
console.log('Diagnostic Tests:');
disease.diagnostic_tests.forEach(test => console.log(`- ${test}`));
});
return diagnosis;
} catch (error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
const errorData = error.response.data;
console.error(`Error ${error.response.status}: ${errorData.error}`);
console.error(`Message: ${Array.isArray(errorData.message) ? errorData.message.join(', ') : errorData.message}`);
} else if (error.request) {
// The request was made but no response was received
console.error('Error: No response received');
} else {
// Something happened in setting up the request that triggered an Error
console.error('Error:', error.message);
}
throw error;
}
}
// Call the function
getDifferentialDiagnosis()
.then(diagnosis => console.log('Diagnosis complete!'))
.catch(err => console.error('Failed to get diagnosis'));
Streaming Request (Node.js)
This example shows how to use the streaming endpoint with Server-Sent Events (SSE) in Node.js using the eventsource
library:
const EventSource = require('eventsource');
const axios = require('axios');
async function streamDifferentialDiagnosis() {
const API_KEY = 'your_api_key';
const API_URL = 'https://api.knidian.ai/diagnose/stream';
try {
// First, make a POST request to initiate the stream
await axios.post(
API_URL,
{
clinical_history: "A 45-year-old male presents with chest pain, shortness of breath, and fatigue for the past 3 days. The pain is described as pressure-like, radiating to the left arm, and worsens with exertion. He has a history of hypertension and hyperlipidemia, and his father had a myocardial infarction at age 50.",
language: "en"
},
{
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
'x-api-key': API_KEY
}
}
);
// Then connect to the stream
const eventSource = new EventSource(API_URL, {
headers: {
'x-api-key': API_KEY
}
});
// Initialize an object to store the accumulated diagnosis data
let diagnosisData = {};
// Handle incoming messages
eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
// Merge the new data with the accumulated data
diagnosisData = mergeDeep(diagnosisData, data);
// Process partial data
if (data.diagnosis && data.diagnosis.diseases) {
console.log(`Received data for ${data.diagnosis.diseases.length} diseases`);
// Display the latest disease information
const latestDisease = data.diagnosis.diseases[data.diagnosis.diseases.length - 1];
if (latestDisease) {
console.log(`Latest disease: ${latestDisease.name}`);
console.log(`Probability: ${latestDisease.probability * 100}%`);
}
}
if (data.triage) {
console.log(`Triage level: ${data.triage.triage_level}`);
console.log(`Recommendation: ${data.triage.triage_recommendation}`);
}
// Check if this is the final message
if (event.type === 'final') {
console.log('Stream complete!');
eventSource.close();
}
} catch (error) {
console.error('Error parsing event data:', error);
}
};
// Handle errors
eventSource.onerror = (error) => {
console.error('EventSource error:', error);
eventSource.close();
};
// Return the EventSource so it can be closed externally if needed
return eventSource;
} catch (error) {
console.error('Error setting up stream:', error);
throw error;
}
}
// Deep merge function to combine partial updates
function mergeDeep(target, source) {
const isObject = (obj) => obj && typeof obj === 'object';
if (!isObject(target) || !isObject(source)) {
return source;
}
Object.keys(source).forEach(key => {
const targetValue = target[key];
const sourceValue = source[key];
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = sourceValue; // Replace arrays entirely
} else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = mergeDeep(Object.assign({}, targetValue), sourceValue);
} else {
target[key] = sourceValue;
}
});
return target;
}
// Call the function
const eventSource = streamDifferentialDiagnosis()
.catch(err => console.error('Failed to set up diagnosis stream'));
// You can close the connection after some time if needed
// setTimeout(() => eventSource.close(), 60000);
Browser-based Streaming (JavaScript)
This example shows how to use the streaming endpoint directly in a browser using the native EventSource
API:
// API configuration
const API_KEY = 'your_api_key';
const API_URL = 'https://api.knidian.ai/diagnose/stream';
// Clinical history data
const clinicalHistory = "A 45-year-old male presents with chest pain, shortness of breath, and fatigue for the past 3 days. The pain is described as pressure-like, radiating to the left arm, and worsens with exertion. He has a history of hypertension and hyperlipidemia, and his father had a myocardial infarction at age 50.";
// First, make a POST request to initiate the stream
fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
'x-api-key': API_KEY
},
body: JSON.stringify({
clinical_history: clinicalHistory,
language: "en"
})
})
.then(response => {
if (!response.ok) {
throw response;
}
// Now connect to the SSE stream
const eventSource = new EventSource(API_URL);
// Initialize an object to store the accumulated diagnosis data
let diagnosisData = {};
// Handle incoming messages
eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
// Merge the new data with the accumulated data
diagnosisData = { ...diagnosisData, ...data };
// Process partial data
if (data.diagnosis && data.diagnosis.diseases) {
console.log(`Received data for ${data.diagnosis.diseases.length} diseases`);
}
if (data.triage) {
console.log(`Triage level: ${data.triage.triage_level}`);
}
// Check if this is the final message
if (event.type === 'final') {
console.log('Stream complete!');
eventSource.close();
}
} catch (error) {
console.error('Error parsing event data:', error);
}
};
// Handle errors
eventSource.onerror = (error) => {
console.error('EventSource error:', error);
eventSource.close();
};
})
.catch(async error => {
console.error('Error setting up stream:', error);
// Try to parse the error response if it's from the server
if (error instanceof Response) {
try {
const errorData = await error.json();
const errorMessage = Array.isArray(errorData.message)
? errorData.message.join(', ')
: errorData.message || 'Unknown error';
console.error(`Error ${error.status}: ${errorData.error} - ${errorMessage}`);
} catch {
// If we can't parse the JSON response
console.error(`Error: ${error.statusText}`);
}
} else {
// For network or other errors
console.error(`Error: ${error.message}`);
}
});
Python Examples
Standard Request (Python)
This example demonstrates how to make a standard POST request to the /diagnose
endpoint using Python with the requests
library:
import requests
import json
def get_differential_diagnosis():
API_KEY = 'your_api_key'
API_URL = 'https://api.knidian.ai/diagnose'
headers = {
'Content-Type': 'application/json',
'x-api-key': API_KEY
}
data = {
'clinical_history': "A 45-year-old male presents with chest pain, shortness of breath, and fatigue for the past 3 days. The pain is described as pressure-like, radiating to the left arm, and worsens with exertion. He has a history of hypertension and hyperlipidemia, and his father had a myocardial infarction at age 50.",
'language': 'en'
}
try:
response = requests.post(API_URL, headers=headers, json=data)
response.raise_for_status() # Raise an exception for 4XX/5XX responses
# Parse the JSON response
diagnosis = response.json()
# Process the diagnosis
print(f"Triage Level: {diagnosis['triage']['triage_level']}")
print(f"Triage Recommendation: {diagnosis['triage']['triage_recommendation']}")
# Display the top diseases
for i, disease in enumerate(diagnosis['diagnosis']['diseases']):
print(f"\nDisease {i+1}: {disease['name']} ({disease['icd10_code']})")
print(f"Probability: {disease['probability'] * 100:.1f}%")
print(f"Why: {disease['why']}")
print("Diagnostic Tests:")
for test in disease['diagnostic_tests']:
print(f"- {test}")
return diagnosis
except requests.exceptions.HTTPError as http_err:
print(f"HTTP Error: {http_err}")
try:
error_data = response.json()
error_message = error_data.get('message', '')
if isinstance(error_message, list):
error_message = ', '.join(error_message)
print(f"Error {response.status_code}: {error_data.get('error', 'Unknown error')}")
print(f"Message: {error_message}")
except:
# If we can't parse the JSON response
print(f"Response: {response.text}")
except requests.exceptions.ConnectionError:
print("Connection Error - Check your internet connection")
except requests.exceptions.Timeout:
print("Timeout Error - The request timed out")
except requests.exceptions.RequestException as err:
print(f"Request Error: {err}")
except json.JSONDecodeError:
print("Error parsing JSON response")
return None
# Call the function
diagnosis = get_differential_diagnosis()
if diagnosis:
print("Diagnosis complete!")
Streaming Request (Python)
This example shows how to use the streaming endpoint with Server-Sent Events (SSE) in Python using the sseclient
library:
import requests
import json
import sseclient
def stream_differential_diagnosis():
API_KEY = 'your_api_key'
API_URL = 'https://api.knidian.ai/diagnose/stream'
headers = {
'Content-Type': 'application/json',
'x-api-key': API_KEY,
'Accept': 'text/event-stream'
}
data = {
'clinical_history': "A 45-year-old male presents with chest pain, shortness of breath, and fatigue for the past 3 days. The pain is described as pressure-like, radiating to the left arm, and worsens with exertion. He has a history of hypertension and hyperlipidemia, and his father had a myocardial infarction at age 50.",
'language': 'en'
}
try:
# First, make a POST request to initiate the stream
response = requests.post(API_URL, headers=headers, json=data, stream=True)
response.raise_for_status()
# Initialize the SSE client
client = sseclient.SSEClient(response)
# Initialize an object to store the accumulated diagnosis data
diagnosis_data = {}
# Process the stream
print("Starting diagnosis stream...")
for event in client.events():
try:
# Parse the data
data = json.loads(event.data)
# Merge the new data with the accumulated data
diagnosis_data.update(data)
# Process partial data
if 'diagnosis' in data and 'diseases' in data['diagnosis']:
diseases = data['diagnosis']['diseases']
print(f"Received data for {len(diseases)} diseases")
# Display the latest disease information
if diseases:
latest_disease = diseases[-1]
print(f"Latest disease: {latest_disease['name']}")
print(f"Probability: {latest_disease['probability'] * 100:.1f}%")
if 'triage' in data:
print(f"Triage level: {data['triage']['triage_level']}")
print(f"Recommendation: {data['triage']['triage_recommendation']}")
# Check if this is the final message (you might need to implement your own logic here)
if event.event == 'final':
print("Stream complete!")
break
except json.JSONDecodeError as e:
print(f"Error parsing event data: {e}")
return diagnosis_data
except requests.exceptions.HTTPError as http_err:
print(f"HTTP Error: {http_err}")
try:
error_data = response.json()
error_message = error_data.get('message', '')
if isinstance(error_message, list):
error_message = ', '.join(error_message)
print(f"Error {response.status_code}: {error_data.get('error', 'Unknown error')}")
print(f"Message: {error_message}")
except:
# If we can't parse the JSON response
print(f"Response: {response.text}")
except requests.exceptions.ConnectionError:
print("Connection Error - Check your internet connection")
except requests.exceptions.Timeout:
print("Timeout Error - The request timed out")
except requests.exceptions.RequestException as err:
print(f"Request Error: {err}")
except Exception as e:
print(f"Unexpected error: {e}")
return None
# Call the function
diagnosis = stream_differential_diagnosis()
if diagnosis:
print("Final diagnosis data received!")
# Process the complete diagnosis data here
Error Handling Best Practices
When working with the Knidian AI API, it's important to implement robust error handling to ensure your application can gracefully handle various error scenarios:
-
HTTP Status Codes: Always check the HTTP status code of the response to identify the type of error:
- 400: Bad Request - Check your input parameters
- 401: Unauthorized - Check your API key
- 429: Too Many Requests - You've exceeded your rate limit
- 500+: Server Error - Implement retry logic with exponential backoff
-
Timeouts: Set appropriate timeouts for your requests, especially for the standard (non-streaming) endpoint which may take 25-30 seconds to respond:
// JavaScript example with timeout
axios.post(API_URL, data, {
headers: headers,
timeout: 60000 // 60 seconds
})
# Python example with timeout
requests.post(API_URL, headers=headers, json=data, timeout=60)
- Retry Logic: Implement retry logic with exponential backoff for transient errors:
// JavaScript example with retry logic
async function getDiagnosisWithRetry(maxRetries = 3, initialDelay = 1000) {
let retries = 0;
while (retries < maxRetries) {
try {
return await getDifferentialDiagnosis();
} catch (error) {
if (error.response && error.response.status >= 500) {
// Only retry for server errors (5xx)
retries++;
if (retries >= maxRetries) throw error;
// Exponential backoff
const delay = initialDelay * Math.pow(2, retries - 1);
console.log(`Retrying in ${delay}ms... (${retries}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
// Don't retry for client errors (4xx)
throw error;
}
}
}
}
- Stream Handling: For the streaming endpoint, implement proper error handling for the SSE connection:
// JavaScript example for handling SSE errors
eventSource.onerror = (error) => {
console.error('EventSource error:', error);
eventSource.close();
// Implement reconnection logic if needed
if (shouldReconnect) {
console.log('Reconnecting...');
setTimeout(() => streamDifferentialDiagnosis(), 5000);
}
};
Additional Resources
- API Reference - Complete API documentation
- Authentication Guide - How to obtain and use API keys
- Interpreting Results - How to interpret the diagnosis results
- Language Support - Information about supported languages