File size: 21,092 Bytes
d27b187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
"""Generate the AgroSense Technical Guide and Standard Operating Procedure (SOP),
each as Word (.docx) and PDF, into docs/.

    pip install python-docx fpdf2
    python scripts/build_tech_docs.py
"""
from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from docgen import build_both  # noqa: E402

DOCS_DIR = Path(__file__).resolve().parent.parent / "docs"

# --------------------------------------------------------------------------- #
# Technical Guide
# --------------------------------------------------------------------------- #
TECH_TITLE = "AgroSense - Technical Guide"
TECH_SUBTITLE = "Architecture, modules, configuration and deployment  -  v0.1 (POC)"

TECH_SECTIONS = [
    ("1. System Overview", [
        ("p", "AgroSense is a FastAPI application that also serves a single-page web "
              "app. At its core is a Retrieval-Augmented Generation (RAG) engine over "
              "an agriculture knowledge base, surrounded by data-source modules "
              "(weather, satellite, market, hazards, etc.) and service modules "
              "(plant vision, telemedicine, live consultation, doctor registry, "
              "knowledge-base admin)."),
        ("h2", "Layers"),
        ("ul", ["Data layer - static knowledge base plus live sources (Open-Meteo, "
                "NASA, data.gov.in, Yahoo Finance, Google News).",
                "Knowledge layer - documents embedded into a vector store.",
                "Cognitive layer - retrieval + re-ranking + grounded generation, plus "
                "decision-fusion advisories and plant vision/telemedicine.",
                "Interaction layer - the web app (served by FastAPI), Streamlit UI, CLI.",
                "Engagement layer - multilingual, live consultation, notifications."]),
        ("h2", "RAG pipeline"),
        ("p", "query -> preprocess/translate -> embed -> vector search (top-k) -> "
              "CARO-style metadata re-rank + relevance gate -> grounded extractive "
              "generation with citations -> optional translation back to the user "
              "language."),
    ]),
    ("2. Technology Stack", [
        ("ul", ["Language/runtime: Python 3.10+ (validated on 3.14).",
                "Core: FastAPI + Uvicorn, Pydantic, NumPy.",
                "Web app: HTML + CSS + vanilla JS (no build step), served at /ui.",
                "Optional accelerators: faiss-cpu (vector search), sentence-transformers "
                "(embeddings) - pure-Python fallbacks exist when absent.",
                "Optional: TensorFlow (plant-vision CNNs), Earth Engine API (NDVI), "
                "Pillow (image heuristic), deep-translator/argostranslate (i18n), "
                "python-docx + fpdf2 (these documents).",
                "Tests: a self-contained runner (python tests/test_rag.py) plus a "
                "jsdom SPA smoke test (node web/smoke.mjs)."]),
    ]),
    ("3. Repository Layout", [
        ("ul", ["agrosense/ - the library (engine + all modules).",
                "agrosense/rag.py - RAGEngine, the single orchestration entry point.",
                "agrosense/{embeddings,vector_store,retriever,generator}.py - RAG core.",
                "agrosense/{weather,satellite,environment,planetary,hazards}.py - data.",
                "agrosense/{fusion,crop_profiles}.py - decision-fusion advisories.",
                "agrosense/{vision,telemedicine,ipm}.py - plant clinic.",
                "agrosense/{consultation,doctors,notifications}.py - live doctor.",
                "agrosense/{clubs,traditional}.py - farmer clubs + traditional/Panchang.",
                "agrosense/{subsidies,finance,land_records,trading}.py - schemes, loans, "
                "land records, produce marketplace.",
                "agrosense/{prices,commodities,news,radio,calendars,translation}.py - misc.",
                "agrosense/{kb_admin,evaluation}.py - admin + evaluation.",
                "api/main.py - FastAPI app and all endpoints.",
                "web/ - the single-page app. ui/ - Streamlit UI. cli.py - CLI.",
                "data/ - knowledge_base.json, agri_experts.json, subsidies.json, "
                "finance.json, land_records.json, eval_set.json, etc.",
                "scripts/ - evaluate, train_plant_models, build_manual, build_tech_docs, "
                "docgen (shared Word/PDF renderer), build_docs (regenerate all).",
                "tests/ - test_rag.py (logic), test_ui_render.py (Streamlit render)."]),
    ]),
    ("4. The RAG Engine", [
        ("p", "RAGEngine (agrosense/rag.py) builds the embedder, generator, documents, "
              "vector store and retriever on init, and owns every feature method. "
              "Embeddings default to an offline hashing embedder; the vector store "
              "defaults to a NumPy cosine store; both upgrade automatically when the "
              "optional libraries are installed."),
        ("ul", ["Retrieval: vector search returns top-k; a CARO-style pass re-weights "
                "by metadata overlap (crop, soil, region) and lexical overlap.",
                "Relevance gate: a candidate must share a content term with the query "
                "(matched against field values, not labels) - off-domain queries hit a "
                "safe fallback instead of fabricating advice.",
                "Generation: an extractive generator composes the answer ONLY from "
                "retrieved KB fields and attaches numbered citations (low hallucination "
                "by construction). An OpenAI/Azure seam exists for a real LLM.",
                "reload_kb() rebuilds documents + store + retriever after admin edits."]),
    ]),
    ("5. Knowledge Base", [
        ("p", "data/knowledge_base.json is a list of entries (crop, soil_type, "
              "rainfall_mm, recommended_fertilizer, disease_prevention, pest_management, "
              "source, ...). agrosense/kb_admin.py provides a validated CRUD store "
              "(KBStore) used by the admin endpoints; saving rewrites the file and the "
              "engine rebuilds the index so changes are live."),
    ]),
    ("6. Modules and Data Sources", [
        ("ul", ["Keyless: weather/environment (Open-Meteo), satellite imagery + "
                "agroclimate (NASA GIBS/POWER), hazards (NASA EONET), planetary "
                "(local ephemeris), news (Google News), commodities (Yahoo Finance), "
                "internet radio (Radio Browser).",
                "Keyed: prices + groundwater (data.gov.in), fires (NASA FIRMS), "
                "field NDVI (Earth Engine).",
                "Curated knowledge bases (no live feed exists): government schemes "
                "(subsidies.json), agri-finance products (finance.json), state land-record "
                "systems (land_records.json). The land-record guide is rendered to Word/PDF "
                "on the fly via scripts/docgen.py.",
                "User-generated runtime stores (auto-seeded / gitignored): farmer clubs "
                "(clubs.json), produce listings (market_listings.json), loan enquiries "
                "(finance_applications.json), doctor registry (plant_doctors.json).",
                "Each client degrades gracefully (returns None/empty) when offline or "
                "unconfigured; parsing/geometry logic is pure and unit-tested, network "
                "calls are mock-tested."]),
    ]),
    ("7. API Reference", [
        ("ul", ["Advisor: POST /query.",
                "Location: GET /weather /satellite /environment /planetary /hazards "
                "/advisories.",
                "Market/info: GET /prices /commodities /news /radio /datetime /languages.",
                "Trading: GET/POST /market/listings, GET /market/listings/{id}, "
                "POST /market/listings/{id}/inquire, POST /market/listings/{id}/close.",
                "Plant clinic: POST /vision/classify, POST /telemedicine.",
                "Doctors: GET /experts, GET /doctors/{id}, POST /doctors/{id}/rate, "
                "POST /doctors/apply.",
                "Consults: POST /consult/request, GET/POST /consult/{id}[/message], "
                "GET /notifications.",
                "Clubs: GET/POST /clubs, GET /clubs/{id}, POST /clubs/{id}/join|post.",
                "Traditional: GET /traditional.",
                "Schemes: GET /subsidies[/{id}], GET /subsidies/updates.",
                "Finance: GET /finance[/{id}], POST /finance/{id}/apply.",
                "Land records: GET /land-records, GET /land-records/guide.{pdf,docx}.",
                "Admin (X-Admin-Token): /admin/kb (CRUD), /admin/doctors, "
                "/admin/doctors/{id}/verify, /admin/subsidies/{id}/update, "
                "/admin/finance/applications.",
                "Docs: GET /downloads/{user-manual,technical-guide,sop}.{pdf,docx}.",
                "App: GET / -> /ui/ ; interactive API docs at /docs."]),
    ]),
    ("8. Configuration (environment variables)", [
        ("ul", ["AGROSENSE_EMBEDDING_BACKEND - auto | sentence-transformers | hashing.",
                "AGROSENSE_GENERATION_BACKEND - extractive | openai.",
                "AGROSENSE_ADMIN_TOKEN - admin gate (change the default 'admin').",
                "AGROSENSE_DATAGOV_API_KEY - prices + groundwater.",
                "AGROSENSE_GROUNDWATER_RESOURCE - CGWB resource id.",
                "AGROSENSE_FIRMS_MAP_KEY - active fires.",
                "AGROSENSE_EE_PROJECT / _EE_SERVICE_ACCOUNT / _EE_KEY_FILE - NDVI.",
                "AGROSENSE_VISION_{DISEASE,PLANT,PEST}_MODEL / _LABELS - vision models.",
                "AGROSENSE_TRANSLATION_BACKEND - auto | argos | deep | none.",
                "AGROSENSE_NOTIFY_WEBHOOK / SMTP vars - expert notifications.",
                "AGROSENSE_VIDEO_BASE - Jitsi base for live video.",
                "AGROSENSE_KB_PATH - knowledge base path override."]),
    ]),
    ("9. Extending AgroSense", [
        ("ul", ["Add KB knowledge: use the Admin tab or POST /admin/kb (or edit the "
                "JSON and call reload).",
                "Add a data source: create a module with a pure parser + a client that "
                "returns None on failure; add an engine method and an endpoint; unit-"
                "test the parser and mock the fetch.",
                "Add a vision model: train with scripts/train_plant_models.py and set "
                "the model env vars; inference activates automatically.",
                "Add an expert specialization: extend the tag map in doctors.py and the "
                "routing map in consultation.py."]),
    ]),
    ("10. Testing and Quality", [
        ("ul", ["Logic suite: python tests/test_rag.py (offline; set "
                "AGROSENSE_EMBEDDING_BACKEND=hashing for determinism).",
                "Evaluation harness: python scripts/evaluate.py - context relevance, "
                "faithfulness, hallucination rate, latency vs targets.",
                "SPA smoke: node web/smoke.mjs (jsdom; mocks fetch; asserts no runtime "
                "errors and that sections render).",
                "Streamlit render: python tests/test_ui_render.py."]),
    ]),
    ("11. Deployment", [
        ("ol", ["Provision a host with Python 3.10+; pip install -r requirements.txt.",
                "Set required environment variables (at least change AGROSENSE_ADMIN_TOKEN).",
                "Run: uvicorn api.main:app --host 0.0.0.0 --port 8000 (add --workers N "
                "behind a process manager; put a reverse proxy / TLS in front).",
                "Persist data/ (knowledge_base.json, plant_doctors.json) on durable "
                "storage; back it up regularly.",
                "Generate docs once (python scripts/build_manual.py ; "
                "python scripts/build_tech_docs.py)."]),
        ("p", "Note: engine state (the consultation/notification stores and the doctor "
              "registry) is in-process and per-worker; for multi-worker or multi-host "
              "deployments move that state to a shared database."),
    ]),
    ("12. Security", [
        ("ul", ["Admin endpoints use a shared-secret token (X-Admin-Token) - suitable "
                "for a single-admin POC; use real auth (accounts, roles, audit) in "
                "production.",
                "CORS is open by default - restrict allowed origins for a real deployment.",
                "Onboarding and ratings are unauthenticated - add accounts and rate "
                "limiting to prevent spam/abuse.",
                "Keep API keys in environment variables / a secrets manager, never in "
                "code. Validate and size-limit uploaded images."]),
    ]),
]

# --------------------------------------------------------------------------- #
# Standard Operating Procedure
# --------------------------------------------------------------------------- #
SOP_TITLE = "AgroSense - Standard Operating Procedure (SOP)"
SOP_SUBTITLE = "Operational runbook for deploying, running and administering AgroSense"

SOP_SECTIONS = [
    ("1. Purpose and Scope", [
        ("p", "This SOP defines the standard procedures to deploy, operate, administer "
              "and recover the AgroSense service. It applies to administrators and "
              "operators running the FastAPI service and the web app."),
    ]),
    ("2. Roles and Responsibilities", [
        ("ul", ["Operator - starts/stops the service, monitors health, applies config, "
                "performs backups and incident response.",
                "Administrator - manages the knowledge base and verifies plant doctors "
                "(holds the admin token).",
                "Plant doctor - onboards, gets verified, handles live consultations.",
                "Farmer (end user) - uses the advisor, plant clinic and consultations."]),
    ]),
    ("3. Pre-requisites", [
        ("ol", ["Host with Python 3.10+ and network egress for live features.",
                "pip install -r requirements.txt.",
                "Environment variables set (see the Technical Guide). At minimum set a "
                "strong AGROSENSE_ADMIN_TOKEN.",
                "data/ directory present and writable (knowledge base + doctor registry)."]),
    ]),
    ("4. Start, Stop, Restart", [
        ("ol", ["Start: uvicorn api.main:app --host 0.0.0.0 --port 8000 "
                "(use a process manager such as systemd/pm2 in production).",
                "Verify: open http://HOST:8000/ui/ and GET http://HOST:8000/health.",
                "Stop: stop the uvicorn process (Ctrl+C or the process manager).",
                "Restart: stop then start; the engine reloads the knowledge base and "
                "rebuilds the index at boot."]),
    ]),
    ("5. Health Checks and Monitoring", [
        ("ul", ["GET /health returns status ok and the knowledge-base document count.",
                "GET / should redirect (307) to /ui/; /ui/ should return the web app.",
                "Watch the uvicorn logs for errors; a feature returning 'unavailable' "
                "indicates a missing key or no network, not a service fault.",
                "Latency target for the advisor is under 3 seconds; the offline core is "
                "typically sub-second."]),
    ]),
    ("6. Configuration Management", [
        ("ol", ["Set configuration via environment variables before starting the "
                "service (do not hard-code secrets).",
                "To change a key/setting: update the environment, then restart the "
                "service.",
                "Record changes (who/when/what) in your change log."]),
    ]),
    ("7. Knowledge Base Management", [
        ("ol", ["Back up data/knowledge_base.json before bulk changes.",
                "Open the web app Admin tab, enter the admin token, click Unlock.",
                "Add an entry (crop and source are required), or Edit/Delete an existing "
                "one. Alternatively use POST/PUT/DELETE /admin/kb with the X-Admin-Token "
                "header.",
                "Saving rebuilds the live index automatically - verify by asking the "
                "advisor a question that should hit the new entry."]),
    ]),
    ("8. Plant Doctor Onboarding and Verification", [
        ("ol", ["A doctor applies via the Plant clinic tab's live-doctor section (or "
                "POST /doctors/apply).",
                "Admin opens the Admin tab -> Plant doctor verification, and reviews the "
                "application: name, specialization, region, languages, contact, "
                "credentials and the ICAR/registration number.",
                "Check the credentials and registration number against your records / "
                "the relevant registry (manual step).",
                "Click Verify to approve (the doctor enters the directory and can take "
                "consults) or Reject. Verified doctors are notified on new consults via "
                "the configured channels."]),
    ]),
    ("9. Handling Live Consultations", [
        ("ul", ["A consult request is routed to a matching available verified doctor; a "
                "video room link and chat thread are created and the doctor is notified "
                "(in-app log always; webhook/email if configured).",
                "Operators ensure the video backend (Jitsi) is reachable; for production "
                "use a self-hosted Jitsi via AGROSENSE_VIDEO_BASE."]),
    ]),
    ("10. Incident Response", [
        ("ul", ["Service down: check the process and logs; restart; confirm /health.",
                "Web app blank: confirm the server is up and open /ui/ (root redirects).",
                "A live feature is 'unavailable': verify the relevant key and network "
                "egress; the core advisor keeps working offline.",
                "Expired/invalid key: rotate the key in the environment and restart.",
                "Bad knowledge entry causing wrong answers: edit/delete it in the Admin "
                "tab (index rebuilds immediately) or restore the KB backup.",
                "Abusive doctor application or rating: reject the doctor / remove the "
                "entry; consider enabling authentication and rate limiting."]),
    ]),
    ("11. Backup and Recovery", [
        ("ol", ["Regularly back up the committed content: data/knowledge_base.json, "
                "subsidies.json, finance.json and land_records.json.",
                "Also back up the runtime state: plant_doctors.json (doctor registry + "
                "ratings), clubs.json (clubs + posts), market_listings.json (trading) and "
                "finance_applications.json (loan enquiries).",
                "To recover: stop the service, restore the JSON files from backup, start "
                "the service; the index rebuilds at boot.",
                "Keep agri_experts.json under version control; the runtime files above are "
                "auto-seeded (or created) if missing."]),
    ]),
    ("12. Routine Maintenance", [
        ("ul", ["Review and update the knowledge base as guidance changes.",
                "Keep the curated content current: scheme details in subsidies.json, "
                "loan products in finance.json, and state portals in land_records.json; "
                "post scheme announcements from the Admin tab as they are released.",
                "Review the loan enquiries lodged in the Finance tab "
                "(GET /admin/finance/applications) and follow up.",
                "Rotate the admin token periodically.",
                "Review doctor ratings/reviews and trading listings for abuse.",
                "Update dependencies and re-run the test suite + SPA smoke before "
                "deploying.",
                "Regenerate all documents (python scripts/build_docs.py) after "
                "feature changes."]),
    ]),
    ("13. Change Management", [
        ("ol", ["Make changes in a non-production environment first.",
                "Run python tests/test_rag.py and node web/smoke.mjs; run "
                "scripts/evaluate.py to confirm quality targets.",
                "Deploy during a low-traffic window; verify /health and key flows.",
                "If a problem appears, roll back to the previous version and restore "
                "backed-up data."]),
    ]),
    ("14. Compliance and Disclaimer", [
        ("p", "AgroSense provides decision support, not professional or medical "
              "authority. Operators and doctors must ensure recommendations comply with "
              "local agricultural regulations. Always confirm product names, dosages and "
              "pre-harvest intervals before advising chemical use."),
    ]),
]


def main() -> int:
    build_both(TECH_TITLE, TECH_SUBTITLE, TECH_SECTIONS, DOCS_DIR,
               "AgroSense_Technical_Guide")
    build_both(SOP_TITLE, SOP_SUBTITLE, SOP_SECTIONS, DOCS_DIR, "AgroSense_SOP")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())