|
@@ -97,6 +97,28 @@ try {
|
|
|
$stmtSpec->execute([$row['crop_type']]);
|
|
$stmtSpec->execute([$row['crop_type']]);
|
|
|
$spec = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: [];
|
|
$spec = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: [];
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // Load up to 3 prior records for the same crop_type + sample_id
|
|
|
|
|
+ $historicalRows = [];
|
|
|
|
|
+ if (!empty($row['crop_type']) && !empty($row['sample_id'])) {
|
|
|
|
|
+ $stmtHist = $pdo->prepare(
|
|
|
|
|
+ 'SELECT id, date_sampled, n, p, k, s, mg, ca, na, fe, mn, zn, cu, b, m, co, se, cl, c
|
|
|
|
|
+ FROM plant_records
|
|
|
|
|
+ WHERE client_records_id = ?
|
|
|
|
|
+ AND crop_type = ?
|
|
|
|
|
+ AND sample_id = ?
|
|
|
|
|
+ AND id != ?
|
|
|
|
|
+ ORDER BY date_sampled DESC
|
|
|
|
|
+ LIMIT 3'
|
|
|
|
|
+ );
|
|
|
|
|
+ $stmtHist->execute([
|
|
|
|
|
+ $row['client_records_id'],
|
|
|
|
|
+ $row['crop_type'],
|
|
|
|
|
+ $row['sample_id'],
|
|
|
|
|
+ $recordId,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ $historicalRows = $stmtHist->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
$stmt = $pdo->prepare('SELECT * FROM soil_records WHERE id = ? AND rand = ?');
|
|
$stmt = $pdo->prepare('SELECT * FROM soil_records WHERE id = ? AND rand = ?');
|
|
|
$stmt->execute([$recordId, $randId]);
|
|
$stmt->execute([$recordId, $randId]);
|
|
@@ -365,7 +387,7 @@ $systemPrompts = [
|
|
|
. "relationship between tissue nutrient levels and crop yield, quality, and disease resistance. "
|
|
. "relationship between tissue nutrient levels and crop yield, quality, and disease resistance. "
|
|
|
. "You are familiar with the CSIRO Plant Analysis Handbook, Hill Laboratories guidelines, "
|
|
. "You are familiar with the CSIRO Plant Analysis Handbook, Hill Laboratories guidelines, "
|
|
|
. "and PIRSA soil and plant analysis standards used in Australia. "
|
|
. "and PIRSA soil and plant analysis standards used in Australia. "
|
|
|
- . "You understand how soil mineral imbalances, pH, and antagonisms (e.g. Ca/Mg, Zn/P, "
|
|
|
|
|
|
|
+ . "You understand how plant mineral imbalances, pH, and antagonisms (e.g. Ca/Mg, Zn/P, "
|
|
|
. "K/Mg) translate into plant deficiency or excess symptoms. "
|
|
. "K/Mg) translate into plant deficiency or excess symptoms. "
|
|
|
. "Always base your interpretation on the measured tissue values and specified ranges. "
|
|
. "Always base your interpretation on the measured tissue values and specified ranges. "
|
|
|
. "Write in a professional but accessible tone suitable for a farmer-facing report.",
|
|
. "Write in a professional but accessible tone suitable for a farmer-facing report.",
|
|
@@ -494,6 +516,29 @@ if ($recordType === 'plant') {
|
|
|
. "In Excess: " . (empty($plantExcesses) ? 'None detected' : implode(', ', $plantExcesses)) . "\n"
|
|
. "In Excess: " . (empty($plantExcesses) ? 'None detected' : implode(', ', $plantExcesses)) . "\n"
|
|
|
. "=====================================\n";
|
|
. "=====================================\n";
|
|
|
|
|
|
|
|
|
|
+ // ── Historical comparison block ───────────────────────────────────────────
|
|
|
|
|
+ $historicalContext = '';
|
|
|
|
|
+ if (!empty($historicalRows)) {
|
|
|
|
|
+ $histElements = ['n','p','k','s','mg','ca','na','fe','mn','zn','cu','b','m','co','se','cl','c'];
|
|
|
|
|
+ $histNames = ['N','P','K','S','Mg','Ca','Na','Fe','Mn','Zn','Cu','B','Mo','Co','Se','Cl','C'];
|
|
|
|
|
+
|
|
|
|
|
+ $historicalContext = "\n\n=====================================\n"
|
|
|
|
|
+ . "HISTORICAL RECORDS — {$p['crop_type']} / Sample ID: {$p['sample_id']}\n"
|
|
|
|
|
+ . "(most recent first, same site)\n"
|
|
|
|
|
+ . "=====================================\n";
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($historicalRows as $hr) {
|
|
|
|
|
+ $historicalContext .= "\nDate Sampled: " . ($hr['date_sampled'] ?? 'Unknown') . "\n";
|
|
|
|
|
+ $line = '';
|
|
|
|
|
+ foreach ($histElements as $i => $col) {
|
|
|
|
|
+ $val = ($hr[$col] ?? '') !== '' ? number_format((float)$hr[$col], 3) : 'N/A';
|
|
|
|
|
+ $line .= sprintf(" %-4s %s", $histNames[$i] . ':', $val);
|
|
|
|
|
+ }
|
|
|
|
|
+ $historicalContext .= trim($line) . "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ $historicalContext .= "=====================================\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$ragChunks = retrieveRelevantChunks($pdo, $plantData, $section, RAG_TOP_K);
|
|
$ragChunks = retrieveRelevantChunks($pdo, $plantData, $section, RAG_TOP_K);
|
|
|
$knowledgeContext = '';
|
|
$knowledgeContext = '';
|
|
|
if (!empty($ragChunks)) {
|
|
if (!empty($ragChunks)) {
|
|
@@ -506,38 +551,49 @@ if ($recordType === 'plant') {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $ctx = $plantData . $knowledgeContext;
|
|
|
|
|
|
|
+ $ctx = $plantData . $historicalContext . $knowledgeContext;
|
|
|
|
|
+
|
|
|
|
|
+ $cropType = $p['crop_type'] ?? 'the crop';
|
|
|
|
|
|
|
|
$prompts = [
|
|
$prompts = [
|
|
|
'general' =>
|
|
'general' =>
|
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
|
- . "TASK: Write a concise general comment on these plant tissue analysis results (2–3 paragraphs). "
|
|
|
|
|
- . "Cover: (1) the overall nutritional status of the crop, "
|
|
|
|
|
- . "(2) the most significant deficiencies or excesses and their likely effect on crop yield and quality, "
|
|
|
|
|
|
|
+ . "TASK: Write a concise general comment on the tissue analysis results for THIS SPECIFIC CROP: {$cropType}. "
|
|
|
|
|
+ . "Do NOT mention or compare to any other crop type — your entire response must be about {$cropType} only. "
|
|
|
|
|
+ . "Cover: (1) the overall nutritional status of this {$cropType} sample, "
|
|
|
|
|
+ . "(2) the most significant deficiencies or excesses and their likely effect on {$cropType} yield and quality, "
|
|
|
. "(3) any elements in good balance. Do not recommend specific product names.",
|
|
. "(3) any elements in good balance. Do not recommend specific product names.",
|
|
|
|
|
|
|
|
'ai_interpretation' =>
|
|
'ai_interpretation' =>
|
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
|
- . "TASK: Write a detailed technical interpretation with these headings:\n"
|
|
|
|
|
|
|
+ . "TASK: Write a detailed technical interpretation of the tissue analysis for THIS SPECIFIC CROP: {$cropType}. "
|
|
|
|
|
+ . "Do NOT mention or compare to any other crop type — your entire response must be about {$cropType} only. "
|
|
|
|
|
+ . "Use these headings:\n"
|
|
|
. "1. MAJOR ELEMENTS (N, P, K, S, Mg, Ca, Na)\n"
|
|
. "1. MAJOR ELEMENTS (N, P, K, S, Mg, Ca, Na)\n"
|
|
|
. "2. TRACE ELEMENTS (Fe, Mn, Zn, Cu, B)\n"
|
|
. "2. TRACE ELEMENTS (Fe, Mn, Zn, Cu, B)\n"
|
|
|
. "3. OTHER ELEMENTS (Mo, Co, Se, Cl, C)\n"
|
|
. "3. OTHER ELEMENTS (Mo, Co, Se, Cl, C)\n"
|
|
|
. "4. NUTRIENT INTERACTIONS & ANTAGONISMS\n"
|
|
. "4. NUTRIENT INTERACTIONS & ANTAGONISMS\n"
|
|
|
- . "5. OVERALL NUTRITIONAL ASSESSMENT\n"
|
|
|
|
|
- . "For each element marked [DEFICIENT] or [EXCESS], explain the agronomic significance, "
|
|
|
|
|
- . "likely causes, and interactions with other nutrients.",
|
|
|
|
|
|
|
+ . "5. OVERALL NUTRITIONAL ASSESSMENT FOR {$cropType}\n"
|
|
|
|
|
+ . (!empty($historicalRows)
|
|
|
|
|
+ ? "6. TREND ANALYSIS (compare current results to the HISTORICAL RECORDS provided above — "
|
|
|
|
|
+ . "note which elements have improved, declined, or remained stable, and what this trend means for {$cropType} health)\n"
|
|
|
|
|
+ : '')
|
|
|
|
|
+ . "For each element marked [DEFICIENT] or [EXCESS], explain the agronomic significance "
|
|
|
|
|
+ . "specific to {$cropType}, likely causes, and interactions with other nutrients.",
|
|
|
|
|
|
|
|
'recommended' =>
|
|
'recommended' =>
|
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
|
- . "TASK: Design a recommended remedial soil and fertiliser program to correct the deficiencies shown. "
|
|
|
|
|
|
|
+ . "TASK: Design a recommended remedial soil and fertiliser program for {$cropType} to correct the deficiencies shown. "
|
|
|
|
|
+ . "Do NOT mention or compare to any other crop type — your entire response must be specific to {$cropType}. "
|
|
|
. "Format as a numbered list or table: "
|
|
. "Format as a numbered list or table: "
|
|
|
. "Element | Current Status | Recommended Action | Product Type (generic) | Rate | Timing. "
|
|
. "Element | Current Status | Recommended Action | Product Type (generic) | Rate | Timing. "
|
|
|
. "Prioritise elements marked [DEFICIENT]. "
|
|
. "Prioritise elements marked [DEFICIENT]. "
|
|
|
- . "Note any nutrient antagonisms that may be limiting uptake.",
|
|
|
|
|
|
|
+ . "Note any nutrient antagonisms that may be limiting uptake in {$cropType}.",
|
|
|
|
|
|
|
|
'foliar' =>
|
|
'foliar' =>
|
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
"{$system}\n\n{$ctx}\n\n"
|
|
|
- . "TASK: Design a foliar spray program to rapidly correct deficiencies shown in the tissue test. "
|
|
|
|
|
|
|
+ . "TASK: Design a foliar spray program for {$cropType} to rapidly correct the deficiencies shown. "
|
|
|
|
|
+ . "Do NOT mention or compare to any other crop type — your entire response must be specific to {$cropType}. "
|
|
|
. "Format as a numbered list or table: "
|
|
. "Format as a numbered list or table: "
|
|
|
. "Growth Stage | Product Type (generic) | Active Element | Rate (L or kg/ha) | Timing. "
|
|
. "Growth Stage | Product Type (generic) | Active Element | Rate (L or kg/ha) | Timing. "
|
|
|
. "Prioritise elements marked [DEFICIENT]. "
|
|
. "Prioritise elements marked [DEFICIENT]. "
|