Send OpenAI fallback images as data URLs
Some checks failed
build-and-deploy / build-deploy (push) Failing after 29s
Some checks failed
build-and-deploy / build-deploy (push) Failing after 29s
This commit is contained in:
@@ -293,12 +293,17 @@ class DocumentExtractionService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Aadhaar retry failed; using OpenAI fallback")
|
logger.info("Aadhaar retry failed; using OpenAI fallback")
|
||||||
val fallback = openAIVisionClient.extractAadhaarNumber(publicImageUrl) ?: ""
|
val fallback = openAIVisionClient.extractAadhaarNumber(
|
||||||
|
publicImageUrl,
|
||||||
|
document.storagePath,
|
||||||
|
document.contentType
|
||||||
|
) ?: ""
|
||||||
val fallbackNormalized = normalizeDigits(cleanedValue(fallback))
|
val fallbackNormalized = normalizeDigits(cleanedValue(fallback))
|
||||||
if (fallbackNormalized != null && isValidAadhaar(fallbackNormalized)) {
|
if (fallbackNormalized != null && isValidAadhaar(fallbackNormalized)) {
|
||||||
results[key] = formatAadhaar(fallbackNormalized)
|
results[key] = formatAadhaar(fallbackNormalized)
|
||||||
} else {
|
} else {
|
||||||
logger.warn("OpenAI fallback failed to produce valid Aadhaar")
|
val len = fallbackNormalized?.length ?: 0
|
||||||
|
logger.warn("OpenAI fallback failed to produce valid Aadhaar (digits={})", len)
|
||||||
results[key] = "NONE"
|
results[key] = "NONE"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class OpenAIVisionClient(
|
|||||||
) {
|
) {
|
||||||
private val logger = LoggerFactory.getLogger(OpenAIVisionClient::class.java)
|
private val logger = LoggerFactory.getLogger(OpenAIVisionClient::class.java)
|
||||||
|
|
||||||
fun extractAadhaarNumber(imageUrl: String): String? {
|
fun extractAadhaarNumber(imageUrl: String, localPath: String?, contentType: String?): String? {
|
||||||
if (apiKey.isBlank()) {
|
if (apiKey.isBlank()) {
|
||||||
logger.warn("OpenAI fallback skipped: openai.apiKey is blank")
|
logger.warn("OpenAI fallback skipped: openai.apiKey is blank")
|
||||||
return null
|
return null
|
||||||
@@ -32,8 +32,9 @@ class OpenAIVisionClient(
|
|||||||
val headers = HttpHeaders()
|
val headers = HttpHeaders()
|
||||||
headers.contentType = MediaType.APPLICATION_JSON
|
headers.contentType = MediaType.APPLICATION_JSON
|
||||||
headers.setBearerAuth(apiKey)
|
headers.setBearerAuth(apiKey)
|
||||||
|
val resolvedImage = buildDataUrl(localPath, contentType) ?: imageUrl
|
||||||
val first = call(
|
val first = call(
|
||||||
imageUrl,
|
resolvedImage,
|
||||||
"Read extremely carefully. Aadhaar number = 12 digits. Reply ONLY the 12 digits or NONE.",
|
"Read extremely carefully. Aadhaar number = 12 digits. Reply ONLY the 12 digits or NONE.",
|
||||||
"aadhaar_default",
|
"aadhaar_default",
|
||||||
headers
|
headers
|
||||||
@@ -45,7 +46,7 @@ class OpenAIVisionClient(
|
|||||||
logger.info("OpenAI fallback returned NONE; retrying with focused prompt")
|
logger.info("OpenAI fallback returned NONE; retrying with focused prompt")
|
||||||
}
|
}
|
||||||
return call(
|
return call(
|
||||||
imageUrl,
|
resolvedImage,
|
||||||
"Focus on the 12-digit Aadhaar number printed on the card (often vertical on the left). Reply ONLY the 12 digits or NONE.",
|
"Focus on the 12-digit Aadhaar number printed on the card (often vertical on the left). Reply ONLY the 12 digits or NONE.",
|
||||||
"aadhaar_left_strip",
|
"aadhaar_left_strip",
|
||||||
headers
|
headers
|
||||||
@@ -130,4 +131,25 @@ class OpenAIVisionClient(
|
|||||||
val digits = trimmed.filter { it.isDigit() }
|
val digits = trimmed.filter { it.isDigit() }
|
||||||
return if (digits.isNotBlank()) "digits_len=${digits.length}" else "text_len=${trimmed.length}"
|
return if (digits.isNotBlank()) "digits_len=${digits.length}" else "text_len=${trimmed.length}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildDataUrl(localPath: String?, contentType: String?): String? {
|
||||||
|
if (localPath.isNullOrBlank()) return null
|
||||||
|
val type = contentType ?: guessContentType(localPath) ?: return null
|
||||||
|
return try {
|
||||||
|
val bytes = java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(localPath))
|
||||||
|
val base64 = java.util.Base64.getEncoder().encodeToString(bytes)
|
||||||
|
"data:$type;base64,$base64"
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.warn("OpenAI fallback failed to read local image: {}", e.message)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun guessContentType(path: String): String? {
|
||||||
|
return when {
|
||||||
|
path.endsWith(".jpg", true) || path.endsWith(".jpeg", true) -> "image/jpeg"
|
||||||
|
path.endsWith(".png", true) -> "image/png"
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user