Spaces:
Sleeping
Sleeping
Commit ·
2c67191
1
Parent(s): f59b927
add LLM for recommendation
Browse files- __pycache__/agent.cpython-310.pyc +0 -0
- __pycache__/llm_client.cpython-310.pyc +0 -0
- __pycache__/recomm.cpython-310.pyc +0 -0
- app.py +33 -1
- llm_client.py +13 -0
- recomm.py +37 -0
- requirements.txt +4 -1
- schemas.py +9 -0
__pycache__/agent.cpython-310.pyc
ADDED
|
Binary file (1.31 kB). View file
|
|
|
__pycache__/llm_client.cpython-310.pyc
ADDED
|
Binary file (884 Bytes). View file
|
|
|
__pycache__/recomm.cpython-310.pyc
ADDED
|
Binary file (1.58 kB). View file
|
|
|
app.py
CHANGED
|
@@ -4,9 +4,11 @@ import numpy as np
|
|
| 4 |
from PIL import Image
|
| 5 |
import io
|
| 6 |
from fastapi.middleware.cors import CORSMiddleware
|
| 7 |
-
|
|
|
|
| 8 |
# Initialize FastAPI app
|
| 9 |
app = FastAPI(title="Image Classification API")
|
|
|
|
| 10 |
|
| 11 |
# Add CORS middleware
|
| 12 |
app.add_middleware(
|
|
@@ -17,6 +19,8 @@ app.add_middleware(
|
|
| 17 |
allow_headers=["*"],
|
| 18 |
)
|
| 19 |
|
|
|
|
|
|
|
| 20 |
# Load the Keras model once at startup
|
| 21 |
try:
|
| 22 |
model = load_model('IAPLD.h5')
|
|
@@ -44,6 +48,34 @@ def preprocess_image(image: Image.Image) -> np.ndarray:
|
|
| 44 |
@app.get("/")
|
| 45 |
async def root():
|
| 46 |
return {"message": "Welcome to the Image Classification API. Use POST /predict/ to upload an image."}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
# Prediction endpoint
|
| 49 |
@app.post("/predict/")
|
|
|
|
| 4 |
from PIL import Image
|
| 5 |
import io
|
| 6 |
from fastapi.middleware.cors import CORSMiddleware
|
| 7 |
+
from llm_client import LLMClient
|
| 8 |
+
import json
|
| 9 |
# Initialize FastAPI app
|
| 10 |
app = FastAPI(title="Image Classification API")
|
| 11 |
+
import logging
|
| 12 |
|
| 13 |
# Add CORS middleware
|
| 14 |
app.add_middleware(
|
|
|
|
| 19 |
allow_headers=["*"],
|
| 20 |
)
|
| 21 |
|
| 22 |
+
|
| 23 |
+
|
| 24 |
# Load the Keras model once at startup
|
| 25 |
try:
|
| 26 |
model = load_model('IAPLD.h5')
|
|
|
|
| 48 |
@app.get("/")
|
| 49 |
async def root():
|
| 50 |
return {"message": "Welcome to the Image Classification API. Use POST /predict/ to upload an image."}
|
| 51 |
+
from recomm import Redommend
|
| 52 |
+
|
| 53 |
+
@app.get("/recommendation")
|
| 54 |
+
async def recommendation(disease: str):
|
| 55 |
+
if not disease:
|
| 56 |
+
raise HTTPException(status_code=400, detail="Disease parameter is required")
|
| 57 |
+
|
| 58 |
+
try:
|
| 59 |
+
llm_client = LLMClient()
|
| 60 |
+
recommender = Redommend(llm_client)
|
| 61 |
+
|
| 62 |
+
raw_response = recommender._run(disease).strip()
|
| 63 |
+
|
| 64 |
+
if raw_response.startswith("```json"):
|
| 65 |
+
raw_response = raw_response.replace("```json", "").replace("```", "").strip()
|
| 66 |
+
|
| 67 |
+
data = json.loads(raw_response)
|
| 68 |
+
return data
|
| 69 |
+
|
| 70 |
+
except json.JSONDecodeError:
|
| 71 |
+
raise HTTPException(
|
| 72 |
+
status_code=500,
|
| 73 |
+
detail=f"Le LLM n’a pas renvoyé un JSON valide : {raw_response}"
|
| 74 |
+
|
| 75 |
+
)
|
| 76 |
+
except Exception as e:
|
| 77 |
+
logging.error(f"Error in recommendation endpoint: {str(e)}")
|
| 78 |
+
raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")
|
| 79 |
|
| 80 |
# Prediction endpoint
|
| 81 |
@app.post("/predict/")
|
llm_client.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app/llm_client.py
|
| 2 |
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 3 |
+
|
| 4 |
+
class LLMClient:
|
| 5 |
+
def __init__(self, model: str = "models/gemini-2.0-flash", temp: float = 0.5):
|
| 6 |
+
self.llm = ChatGoogleGenerativeAI(
|
| 7 |
+
model=model,
|
| 8 |
+
google_api_key= "AIzaSyAmpT2kjqFcz7HZyiFeh6dBOu-zx_MRxIA",
|
| 9 |
+
temperature=temp
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
def invoke(self, prompt: str) -> str:
|
| 13 |
+
return self.llm.invoke(prompt).content
|
recomm.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain.prompts import PromptTemplate
|
| 2 |
+
from llm_client import LLMClient
|
| 3 |
+
from langchain.agents import Tool
|
| 4 |
+
|
| 5 |
+
class Redommend:
|
| 6 |
+
## class for generating recommendations based on user input
|
| 7 |
+
def __init__(self, llm_client: LLMClient):
|
| 8 |
+
self.llm_client = llm_client
|
| 9 |
+
|
| 10 |
+
# Define the prompt template for generating recommendations.
|
| 11 |
+
# Note: now the input variable is called "maladie" (same as the placeholder).
|
| 12 |
+
template = """
|
| 13 |
+
Vous êtes en culture de pommes de terre
|
| 14 |
+
* Pour guérir cette {maladie} :
|
| 15 |
+
- Vous devez recommander les meilleures pratiques de culture pour cette maladie.
|
| 16 |
+
- Veuillez lister les recommandations de manière concise, étape par étape.
|
| 17 |
+
- Donnez la réponse sous forme de liste numérotée, en JSON.
|
| 18 |
+
- Donnez simplement la réponse en JSON, sans explications supplémentaires.
|
| 19 |
+
- Donnez la reponse en Français.
|
| 20 |
+
"""
|
| 21 |
+
self.prompt_template = PromptTemplate(
|
| 22 |
+
input_variables=["maladie"],
|
| 23 |
+
template=template
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
self.tool = Tool(
|
| 27 |
+
name="recommender",
|
| 28 |
+
func=self._run,
|
| 29 |
+
description="Use this tool to get recommendations for potato cultivation based on the disease."
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
def _run(self, maladie: str) -> str:
|
| 33 |
+
# Generate the prompt with the maladie string that comes from the query parameter.
|
| 34 |
+
prompt = self.prompt_template.format(maladie=maladie)
|
| 35 |
+
# Invoke the LLM client to get recommendations
|
| 36 |
+
response = self.llm_client.invoke(prompt)
|
| 37 |
+
return response
|
requirements.txt
CHANGED
|
@@ -2,4 +2,7 @@ fastapi==0.115.4
|
|
| 2 |
uvicorn==0.32.0
|
| 3 |
tensorflow==2.17.1
|
| 4 |
numpy==1.26.4
|
| 5 |
-
pillow==10.2.0
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
uvicorn==0.32.0
|
| 3 |
tensorflow==2.17.1
|
| 4 |
numpy==1.26.4
|
| 5 |
+
pillow==10.2.0
|
| 6 |
+
langchain==0.2.0
|
| 7 |
+
langchain-google-genai
|
| 8 |
+
accelerate>=0.26.0
|
schemas.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel
|
| 2 |
+
from typing import List
|
| 3 |
+
|
| 4 |
+
class GeneralResponse(BaseModel):
|
| 5 |
+
status: str
|
| 6 |
+
message: str
|
| 7 |
+
data : List[str]
|
| 8 |
+
class Request(BaseModel):
|
| 9 |
+
disease: str
|