Update main.py
Browse files
main.py
CHANGED
|
@@ -201,7 +201,7 @@ def extract_fields_with_sarvam(raw_text: str, doc_type: str) -> dict:
|
|
| 201 |
}
|
| 202 |
|
| 203 |
if not SARVAM_API_KEY:
|
| 204 |
-
return {**empty_fields, "ocr_error": "SARVAM_API_KEY not configured
|
| 205 |
|
| 206 |
system_prompt = (
|
| 207 |
"You are a document field extractor for Indian identity documents. "
|
|
@@ -210,9 +210,9 @@ def extract_fields_with_sarvam(raw_text: str, doc_type: str) -> dict:
|
|
| 210 |
"Fields to extract:\n"
|
| 211 |
" - name: Full name of the document holder\n"
|
| 212 |
" - address: Full address (combine multi-line if needed)\n"
|
| 213 |
-
" - date_of_birth: In DD/MM/YYYY or YYYY format
|
| 214 |
" - gender: Male / Female / Transgender\n"
|
| 215 |
-
" - id_number: Aadhaar=12-digit
|
| 216 |
" - mobile_number: 10-digit mobile number if present\n\n"
|
| 217 |
"Use null for any field not found. Return a flat JSON object only."
|
| 218 |
)
|
|
@@ -242,36 +242,54 @@ def extract_fields_with_sarvam(raw_text: str, doc_type: str) -> dict:
|
|
| 242 |
timeout=30
|
| 243 |
)
|
| 244 |
|
|
|
|
|
|
|
|
|
|
| 245 |
if response.status_code != 200:
|
| 246 |
return {
|
| 247 |
**empty_fields,
|
| 248 |
-
"sarvam_error": f"API returned {response.status_code}: {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
}
|
| 250 |
|
| 251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 252 |
|
| 253 |
# Strip markdown code fences if model wraps output
|
| 254 |
content = re.sub(r"^```(?:json)?\s*", "", content)
|
| 255 |
-
content = re.sub(r"\s*```$", "", content)
|
| 256 |
|
| 257 |
extracted = json.loads(content)
|
| 258 |
|
| 259 |
-
# Normalize keys — ensure all expected fields are present
|
| 260 |
fields = ["name", "address", "date_of_birth", "gender", "id_number", "mobile_number"]
|
| 261 |
normalized = {f: extracted.get(f) for f in fields}
|
| 262 |
|
| 263 |
-
# Handle year_of_birth fallback (if model returns it instead of date_of_birth)
|
| 264 |
if normalized["date_of_birth"] is None and "year_of_birth" in extracted:
|
| 265 |
normalized["date_of_birth"] = str(extracted["year_of_birth"])
|
| 266 |
|
| 267 |
return normalized
|
| 268 |
|
| 269 |
except json.JSONDecodeError as e:
|
| 270 |
-
return {**empty_fields, "sarvam_parse_error": f"JSON parse failed: {str(e)}"}
|
| 271 |
except requests.exceptions.Timeout:
|
| 272 |
return {**empty_fields, "sarvam_error": "Sarvam API request timed out"}
|
| 273 |
except Exception as e:
|
| 274 |
-
return {**empty_fields, "sarvam_error": str(e)}
|
| 275 |
|
| 276 |
# -----------------------------
|
| 277 |
# FastAPI App
|
|
|
|
| 201 |
}
|
| 202 |
|
| 203 |
if not SARVAM_API_KEY:
|
| 204 |
+
return {**empty_fields, "ocr_error": "SARVAM_API_KEY not configured"}
|
| 205 |
|
| 206 |
system_prompt = (
|
| 207 |
"You are a document field extractor for Indian identity documents. "
|
|
|
|
| 210 |
"Fields to extract:\n"
|
| 211 |
" - name: Full name of the document holder\n"
|
| 212 |
" - address: Full address (combine multi-line if needed)\n"
|
| 213 |
+
" - date_of_birth: In DD/MM/YYYY or YYYY format\n"
|
| 214 |
" - gender: Male / Female / Transgender\n"
|
| 215 |
+
" - id_number: Aadhaar=12-digit, PAN=10-char alphanumeric, Voter ID=alphanumeric\n"
|
| 216 |
" - mobile_number: 10-digit mobile number if present\n\n"
|
| 217 |
"Use null for any field not found. Return a flat JSON object only."
|
| 218 |
)
|
|
|
|
| 242 |
timeout=30
|
| 243 |
)
|
| 244 |
|
| 245 |
+
# Log the raw response for debugging
|
| 246 |
+
raw_body = response.text[:500] # truncate for safety
|
| 247 |
+
|
| 248 |
if response.status_code != 200:
|
| 249 |
return {
|
| 250 |
**empty_fields,
|
| 251 |
+
"sarvam_error": f"API returned {response.status_code}: {raw_body}"
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
resp_json = response.json()
|
| 255 |
+
|
| 256 |
+
# Defensive: check schema before indexing
|
| 257 |
+
choices = resp_json.get("choices")
|
| 258 |
+
if not choices or not isinstance(choices, list) or len(choices) == 0:
|
| 259 |
+
return {
|
| 260 |
+
**empty_fields,
|
| 261 |
+
"sarvam_error": f"Unexpected response schema: {raw_body}"
|
| 262 |
}
|
| 263 |
|
| 264 |
+
message = choices[0].get("message", {})
|
| 265 |
+
content = message.get("content", "").strip()
|
| 266 |
+
|
| 267 |
+
if not content:
|
| 268 |
+
return {
|
| 269 |
+
**empty_fields,
|
| 270 |
+
"sarvam_error": f"Empty content in response. Full body: {raw_body}"
|
| 271 |
+
}
|
| 272 |
|
| 273 |
# Strip markdown code fences if model wraps output
|
| 274 |
content = re.sub(r"^```(?:json)?\s*", "", content)
|
| 275 |
+
content = re.sub(r"\s*```$", "", content).strip()
|
| 276 |
|
| 277 |
extracted = json.loads(content)
|
| 278 |
|
|
|
|
| 279 |
fields = ["name", "address", "date_of_birth", "gender", "id_number", "mobile_number"]
|
| 280 |
normalized = {f: extracted.get(f) for f in fields}
|
| 281 |
|
|
|
|
| 282 |
if normalized["date_of_birth"] is None and "year_of_birth" in extracted:
|
| 283 |
normalized["date_of_birth"] = str(extracted["year_of_birth"])
|
| 284 |
|
| 285 |
return normalized
|
| 286 |
|
| 287 |
except json.JSONDecodeError as e:
|
| 288 |
+
return {**empty_fields, "sarvam_parse_error": f"JSON parse failed: {str(e)} | content was: '{content[:200]}'"}
|
| 289 |
except requests.exceptions.Timeout:
|
| 290 |
return {**empty_fields, "sarvam_error": "Sarvam API request timed out"}
|
| 291 |
except Exception as e:
|
| 292 |
+
return {**empty_fields, "sarvam_error": f"{type(e).__name__}: {str(e)}"}
|
| 293 |
|
| 294 |
# -----------------------------
|
| 295 |
# FastAPI App
|