Spaces:
Runtime error
Runtime error
Revert health check to share the advisor's LLM client
Browse filesNo HF Inference Providers vision-language model under 0.5B parameters
is available; the next-smallest options (Llama-4-Scout, Qwen3-VL-8B)
were rejected as too large. Back to sharing ADVISOR_MODEL_ID/PROVIDER,
even though the text-only model can't process the uploaded image.
- TECHNICAL_DOCUMENT.md +4 -7
- modules/advisor.py +1 -14
TECHNICAL_DOCUMENT.md
CHANGED
|
@@ -230,11 +230,9 @@ yellow?", "Can I plant this next to my tomatoes?").
|
|
| 230 |
**Task**: given a *new* photo of the selected plant, assess its health
|
| 231 |
(leaves, stems, soil) and store the verdict on the plant record.
|
| 232 |
|
| 233 |
-
- Model: `
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
process images. Called via `InferenceClient.chat_completion` with a
|
| 237 |
-
**multimodal** message: the uploaded `PIL.Image` is re-encoded as JPEG,
|
| 238 |
base64-encoded, and sent as an OpenAI-style content array
|
| 239 |
(`{"type": "text", ...}` + `{"type": "image_url", "image_url": {"url":
|
| 240 |
"data:image/jpeg;base64,..."}}`).
|
|
@@ -315,8 +313,7 @@ defaults baked in so the app runs locally without any secrets:
|
|
| 315 |
|---|---|---|
|
| 316 |
| `WEATHER_CITY` | `"Marseille"` | Initial forecast location before the user sets one |
|
| 317 |
| `CLASSIFIER_MODEL_ID` | `"your-username/plant-genus-classifier"` | HF Hub repo of the fine-tuned SigLIP genus classifier |
|
| 318 |
-
| `ADVISOR_MODEL_ID` / `ADVISOR_PROVIDER` | `Qwen/Qwen2.5-Coder-3B-Instruct` / `nscale` | Chat advisor model
|
| 319 |
-
| `HEALTH_MODEL_ID` / `HEALTH_PROVIDER` | `meta-llama/Llama-4-Scout-17B-16E-Instruct` / `nscale` | Vision-language health-diagnostic model + provider (defaults to `ADVISOR_PROVIDER`) |
|
| 320 |
| `HF_TOKEN` | — | Hugging Face token for Inference Providers (advisor + health check) |
|
| 321 |
|
| 322 |
`app.launch(allowed_paths=[...])` whitelists `user_data/`, `static/` and
|
|
|
|
| 230 |
**Task**: given a *new* photo of the selected plant, assess its health
|
| 231 |
(leaves, stems, soil) and store the verdict on the plant record.
|
| 232 |
|
| 233 |
+
- Model: the same `ADVISOR_MODEL_ID` / `ADVISOR_PROVIDER` client as the chat
|
| 234 |
+
advisor (§4.4), again via `InferenceClient.chat_completion` — but this time
|
| 235 |
+
with a **multimodal** message: the uploaded `PIL.Image` is re-encoded as JPEG,
|
|
|
|
|
|
|
| 236 |
base64-encoded, and sent as an OpenAI-style content array
|
| 237 |
(`{"type": "text", ...}` + `{"type": "image_url", "image_url": {"url":
|
| 238 |
"data:image/jpeg;base64,..."}}`).
|
|
|
|
| 313 |
|---|---|---|
|
| 314 |
| `WEATHER_CITY` | `"Marseille"` | Initial forecast location before the user sets one |
|
| 315 |
| `CLASSIFIER_MODEL_ID` | `"your-username/plant-genus-classifier"` | HF Hub repo of the fine-tuned SigLIP genus classifier |
|
| 316 |
+
| `ADVISOR_MODEL_ID` / `ADVISOR_PROVIDER` | `Qwen/Qwen2.5-Coder-3B-Instruct` / `nscale` | Chat advisor + health-diagnostic model and HF Inference provider (shared) |
|
|
|
|
| 317 |
| `HF_TOKEN` | — | Hugging Face token for Inference Providers (advisor + health check) |
|
| 318 |
|
| 319 |
`app.launch(allowed_paths=[...])` whitelists `user_data/`, `static/` and
|
modules/advisor.py
CHANGED
|
@@ -9,13 +9,7 @@ from PIL import Image
|
|
| 9 |
ADVISOR_MODEL_ID = os.getenv("ADVISOR_MODEL_ID", "Qwen/Qwen2.5-Coder-3B-Instruct")
|
| 10 |
ADVISOR_PROVIDER = os.getenv("ADVISOR_PROVIDER", "nscale")
|
| 11 |
|
| 12 |
-
# Qwen2.5-Coder is text-only, so the health check (which sends a photo) needs
|
| 13 |
-
# a vision-capable model. Use the same provider, on a model that supports images.
|
| 14 |
-
HEALTH_MODEL_ID = os.getenv("HEALTH_MODEL_ID", "meta-llama/Llama-4-Scout-17B-16E-Instruct")
|
| 15 |
-
HEALTH_PROVIDER = os.getenv("HEALTH_PROVIDER", ADVISOR_PROVIDER)
|
| 16 |
-
|
| 17 |
_client = None
|
| 18 |
-
_health_client = None
|
| 19 |
|
| 20 |
|
| 21 |
def _get_client() -> InferenceClient:
|
|
@@ -25,13 +19,6 @@ def _get_client() -> InferenceClient:
|
|
| 25 |
return _client
|
| 26 |
|
| 27 |
|
| 28 |
-
def _get_health_client() -> InferenceClient:
|
| 29 |
-
global _health_client
|
| 30 |
-
if _health_client is None:
|
| 31 |
-
_health_client = InferenceClient(model=HEALTH_MODEL_ID, provider=HEALTH_PROVIDER, token=os.getenv("HF_TOKEN"))
|
| 32 |
-
return _health_client
|
| 33 |
-
|
| 34 |
-
|
| 35 |
def _watering_status(last_watered: str | None) -> str:
|
| 36 |
if not last_watered:
|
| 37 |
return "Never watered yet (no record)."
|
|
@@ -127,7 +114,7 @@ def diagnose_plant_health(
|
|
| 127 |
)
|
| 128 |
|
| 129 |
try:
|
| 130 |
-
completion =
|
| 131 |
messages=[{
|
| 132 |
"role": "user",
|
| 133 |
"content": [
|
|
|
|
| 9 |
ADVISOR_MODEL_ID = os.getenv("ADVISOR_MODEL_ID", "Qwen/Qwen2.5-Coder-3B-Instruct")
|
| 10 |
ADVISOR_PROVIDER = os.getenv("ADVISOR_PROVIDER", "nscale")
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
_client = None
|
|
|
|
| 13 |
|
| 14 |
|
| 15 |
def _get_client() -> InferenceClient:
|
|
|
|
| 19 |
return _client
|
| 20 |
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
def _watering_status(last_watered: str | None) -> str:
|
| 23 |
if not last_watered:
|
| 24 |
return "Never watered yet (no record)."
|
|
|
|
| 114 |
)
|
| 115 |
|
| 116 |
try:
|
| 117 |
+
completion = _get_client().chat_completion(
|
| 118 |
messages=[{
|
| 119 |
"role": "user",
|
| 120 |
"content": [
|