37842-vm/api/analyze.php
2026-01-26 18:23:06 +00:00

133 lines
5.4 KiB
PHP

<?php
header('Content-Type: application/json');
require_once __DIR__ . '/../ai/LocalAIApi.php';
$debugFile = __DIR__ . '/analyze_debug.log';
function debugLog($msg) {
global $debugFile;
file_put_contents($debugFile, "[" . date('Y-m-d H:i:s') . "] " . $msg . "\n", FILE_APPEND);
}
$rawInput = file_get_contents('php://input');
$data = json_decode($rawInput, true);
$image = $data['image'] ?? null;
$barcode = $data['barcode'] ?? null;
debugLog("Request received. Barcode: " . ($barcode ?? 'none') . ", Image size: " . ($image ? strlen($image) : 0));
if (!$image && !$barcode) {
debugLog("Error: No image or barcode provided");
echo json_encode(['success' => false, 'error' => 'No image or barcode provided']);
exit;
}
$productData = null;
$errorDetails = null;
// Try Barcode Lookup via Open Food Facts if barcode is present
if ($barcode) {
debugLog("Attempting Open Food Facts lookup for $barcode");
$url = "https://world.openfoodfacts.org/api/v0/product/" . urlencode($barcode) . ".json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'HomePantryTracker/1.0');
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$offData = json_decode($response, true);
if (isset($offData['status']) && $offData['status'] == 1) {
$p = $offData['product'];
$productData = [
'name' => $p['product_name'] ?? ($p['product_name_en'] ?? 'Unknown Product'),
'category' => 'Pantry', // Default
'quantity' => $p['quantity'] ?? '',
'expiration_date' => null
];
debugLog("Barcode found: " . $productData['name']);
// Try to map category
if (!empty($p['categories_tags'])) {
$tags = implode(' ', $p['categories_tags']);
if (stripos($tags, 'dairy') !== false || stripos($tags, 'milk') !== false) $productData['category'] = 'Dairy';
elseif (stripos($tags, 'meat') !== false) $productData['category'] = 'Meat';
elseif (stripos($tags, 'bakery') !== false || stripos($tags, 'bread') !== false) $productData['category'] = 'Bakery';
elseif (stripos($tags, 'fruit') !== false || stripos($tags, 'vegetable') !== false) $productData['category'] = 'Produce';
elseif (stripos($tags, 'frozen') !== false) $productData['category'] = 'Frozen';
}
} else {
debugLog("Barcode not found in Open Food Facts");
}
} else {
debugLog("Open Food Facts API error: $httpCode");
}
}
// If barcode lookup failed or we have an image, use AI
if (!$productData) {
debugLog("Using AI for identification...");
$prompt = "You are a professional pantry organizer. Identify the product from the image provided.
Return ONLY a valid JSON object.
Keys:
- name: Specific brand and product name.
- category: Dairy, Meat, Bakery, Produce, Pantry, Frozen.
- quantity: e.g., '1.5 L', '500g'.
- expiration_date: Look for 'Best Before', 'Use By', or 'EXP' date in YYYY-MM-DD format, or null.
If the package is not in English, translate name/category to English.";
if ($image) {
// Use "Simple" approach: data URL directly in the content string
$content = $prompt . "\nAnalyze this image: " . $image;
$messages = [
['role' => 'user', 'content' => $content]
];
} else {
$messages = [
['role' => 'user', 'content' => $prompt . " Product barcode: $barcode"]
];
}
$resp = LocalAIApi::createResponse([
'input' => $messages,
'temperature' => 0.1
]);
if (!empty($resp['success'])) {
debugLog("AI response successful");
$result = LocalAIApi::decodeJsonFromResponse($resp);
if ($result) {
$productData = $result;
} else {
$text = LocalAIApi::extractText($resp);
debugLog("AI returned text instead of JSON. Extracting...");
if (preg_match('/\{.*\}/s', $text, $matches)) {
$productData = json_decode($matches[0], true);
} else {
$errorDetails = "AI returned text instead of JSON: " . substr($text, 0, 100);
debugLog("Error: $errorDetails");
}
}
} else {
$errorDetails = $resp['error'] ?? $resp['message'] ?? 'AI request failed';
$httpStatus = $resp['status'] ?? 'unknown';
debugLog("AI Request failed. Status: $httpStatus, Error: $errorDetails");
if (isset($resp['response'])) {
debugLog("Full proxy response: " . json_encode($resp['response']));
}
}
}
if ($productData) {
if (isset($productData['expiration_date']) && ($productData['expiration_date'] === 'null' || $productData['expiration_date'] === '')) {
$productData['expiration_date'] = null;
}
debugLog("Returning success for " . ($productData['name'] ?? 'unknown'));
echo json_encode(['success' => true, 'data' => $productData]);
} else {
debugLog("Returning failure: " . ($errorDetails ?? 'Could not identify product'));
echo json_encode(['success' => false, 'error' => $errorDetails ?: 'Could not identify product']);
}