drrobot9 commited on
Commit
aec5884
·
verified ·
1 Parent(s): d86390c

Upload folder using huggingface_hub

Browse files
.dockerignore ADDED
File without changes
.dockerigore ADDED
File without changes
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ app/vectorstore/faiss_index/index.faiss filter=lfs diff=lfs merge=lfs -text
37
+ app/venv/bin/python filter=lfs diff=lfs merge=lfs -text
38
+ app/venv/bin/python3 filter=lfs diff=lfs merge=lfs -text
39
+ app/venv/bin/python3.11 filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a lightweight Python base
2
+ FROM python:3.10-slim
3
+
4
+ # Prevent interactive prompts
5
+ ENV DEBIAN_FRONTEND=noninteractive \
6
+ PYTHONUNBUFFERED=1 \
7
+ PYTHONDONTWRITEBYTECODE=1 \
8
+ HF_HOME=/root/.cache/huggingface
9
+
10
+ # Set work directory
11
+ WORKDIR /code
12
+
13
+ # Install system dependencies (needed for PyTorch + FAISS + SentenceTransformers)
14
+ RUN apt-get update && apt-get install -y --no-install-recommends \
15
+ build-essential \
16
+ git \
17
+ curl \
18
+ libopenblas-dev \
19
+ libomp-dev \
20
+ && rm -rf /var/lib/apt/lists/*
21
+
22
+ # Install Python dependencies
23
+ COPY requirements.txt .
24
+ RUN pip install --no-cache-dir -r requirements.txt
25
+
26
+ # Pre-download Hugging Face models at build time
27
+ RUN python -c "from transformers import pipeline; pipeline('text-generation', model='NousResearch/Nous-Hermes-2-Mistral-7B-DPO')" \
28
+ && python -c "from transformers import pipeline; pipeline('text2text-generation', model='google/flan-t5-large')" \
29
+ && python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')"
30
+
31
+ # Copy project files
32
+ COPY . .
33
+
34
+ # Expose port for FastAPI / Hugging Face Spaces
35
+ EXPOSE 7860
36
+
37
+ # Run FastAPI app with uvicorn
38
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
app/__init__.py ADDED
File without changes
app/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (166 Bytes). View file
 
app/__pycache__/main.cpython-311.pyc ADDED
Binary file (3.31 kB). View file
 
app/agents/__init__.py ADDED
File without changes
app/agents/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (173 Bytes). View file
 
app/agents/__pycache__/crew_pipeline.cpython-311.pyc ADDED
Binary file (8.73 kB). View file
 
app/agents/crew_pipeline.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # farmlingua/app/agents/crew_pipeline.py333
2
+ import os
3
+ import sys
4
+ import requests
5
+ import joblib
6
+ import faiss
7
+ import numpy as np
8
+ from transformers import pipeline
9
+ from sentence_transformers import SentenceTransformer
10
+ from app.utils import config
11
+
12
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13
+ if BASE_DIR not in sys.path:
14
+ sys.path.insert(0, BASE_DIR)
15
+
16
+ DEVICE = 0 if os.environ.get("CUDA_VISIBLE_DEVICES") else -1
17
+
18
+ try:
19
+ classifier = joblib.load(config.CLASSIFIER_PATH)
20
+ except Exception:
21
+ classifier = None
22
+
23
+ print(f"Loading expert model ({config.EXPERT_MODEL_NAME})...")
24
+ expert_pipeline = pipeline(
25
+ "text-generation",
26
+ model=config.EXPERT_MODEL_NAME,
27
+ device=DEVICE,
28
+ max_new_tokens=700,
29
+ temperature=0.3,
30
+ repetition_penalty=1.1
31
+ )
32
+
33
+ print(f"Loading formatter/weather model ({config.FORMATTER_MODEL_NAME})...")
34
+ formatter_pipeline = pipeline(
35
+ "text2text-generation",
36
+ model=config.FORMATTER_MODEL_NAME,
37
+ device=DEVICE
38
+ )
39
+
40
+ embedder = SentenceTransformer(config.EMBEDDING_MODEL)
41
+
42
+ def retrieve_docs(query, vs_path):
43
+ if not vs_path or not os.path.exists(vs_path):
44
+ return None
45
+
46
+ if os.path.isdir(vs_path):
47
+ try:
48
+ from langchain.vectorstores import FAISS as LCFAISS
49
+ from langchain.embeddings import SentenceTransformerEmbeddings
50
+ embed_model = SentenceTransformerEmbeddings(model_name=config.EMBEDDING_MODEL)
51
+ vs = LCFAISS.load_local(str(vs_path), embed_model, allow_dangerous_deserialization=True)
52
+ docs = vs.similarity_search(query, k=3)
53
+ return "\n\n".join(d.page_content for d in docs) if docs else None
54
+ except Exception:
55
+ return None
56
+
57
+ try:
58
+ index = faiss.read_index(str(vs_path))
59
+ except Exception:
60
+ return None
61
+ query_vec = np.array([embedder.encode(query)], dtype=np.float32)
62
+ D, I = index.search(query_vec, k=3)
63
+ if D[0][0] == 0:
64
+ return None
65
+ meta_path = str(vs_path) + "_meta.npy"
66
+ if os.path.exists(meta_path):
67
+ metadata = np.load(meta_path, allow_pickle=True).item()
68
+ docs = [metadata.get(str(idx), "") for idx in I[0] if str(idx) in metadata]
69
+ docs = [doc for doc in docs if doc]
70
+ return "\n\n".join(docs) if docs else None
71
+ return None
72
+
73
+ def get_weather(state_name):
74
+ url = "http://api.weatherapi.com/v1/current.json"
75
+ params = {
76
+ "key": config.WEATHER_API_KEY,
77
+ "q": f"{state_name}, Nigeria",
78
+ "aqi": "no"
79
+ }
80
+ r = requests.get(url, params=params)
81
+ if r.status_code != 200:
82
+ return f"Unable to retrieve weather for {state_name}."
83
+ data = r.json()
84
+ return (
85
+ f"Weather in {state_name}:\n"
86
+ f"- Condition: {data['current']['condition']['text']}\n"
87
+ f"- Temperature: {data['current']['temp_c']}°C\n"
88
+ f"- Humidity: {data['current']['humidity']}%\n"
89
+ f"- Wind: {data['current']['wind_kph']} kph"
90
+ )
91
+
92
+ def detect_intent(query):
93
+ q_lower = query.lower()
94
+ if any(word in q_lower for word in ["weather", "temperature", "rain", "forecast"]):
95
+ for state in config.STATES:
96
+ if state.lower() in q_lower:
97
+ return "weather", state
98
+ return "weather", None
99
+ if any(word in q_lower for word in ["latest", "update", "breaking", "news", "current", "predict"]):
100
+ return "live_update", None
101
+ if hasattr(classifier, "predict") and hasattr(classifier, "predict_proba"):
102
+ predicted_intent = classifier.predict([query])[0]
103
+ confidence = max(classifier.predict_proba([query])[0])
104
+ if confidence < config.CLASSIFIER_CONFIDENCE_THRESHOLD:
105
+ return "low_confidence", None
106
+ return predicted_intent, None
107
+ return "normal", None
108
+
109
+ def run_pipeline(user_query: str):
110
+ intent, extra = detect_intent(user_query)
111
+
112
+ if intent == "weather" and extra:
113
+ weather_text = get_weather(extra)
114
+ return formatter_pipeline(weather_text, max_length=256, do_sample=False)[0]["generated_text"]
115
+
116
+ if intent == "live_update":
117
+ context = retrieve_docs(user_query, config.LIVE_VS_PATH)
118
+ if context:
119
+ user_query += f"\n\nLatest agricultural updates:\n{context}"
120
+
121
+ if intent == "low_confidence":
122
+ context = retrieve_docs(user_query, config.STATIC_VS_PATH)
123
+ if context:
124
+ user_query += f"\n\nReference information:\n{context}"
125
+
126
+ expert_response = expert_pipeline(
127
+ f"Provide a detailed agricultural answer for: {user_query}",
128
+ max_new_tokens=700,
129
+ temperature=0.3
130
+ )[0]['generated_text']
131
+
132
+ formatted_response = formatter_pipeline(
133
+ f"Format the following answer to be clear, structured, and easy to understand for Nigerian farmers:\n\n{expert_response}",
134
+ max_length=512,
135
+ do_sample=False
136
+ )[0]['generated_text']
137
+
138
+ return formatted_response
app/main.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # farmlingua_backend/app/main.py
2
+ import os
3
+ import sys
4
+
5
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
6
+ if BASE_DIR not in sys.path:
7
+ sys.path.insert(0, BASE_DIR)
8
+
9
+ import logging
10
+ from fastapi import FastAPI, Body
11
+ from fastapi.middleware.cors import CORSMiddleware
12
+ import uvicorn
13
+
14
+ from app.tasks.rag_updater import schedule_updates
15
+ from app.utils import config
16
+ from app.agents.crew_pipeline import run_pipeline
17
+
18
+
19
+ logging.basicConfig(
20
+ format="%(asctime)s [%(levelname)s] %(message)s",
21
+ level=logging.INFO
22
+ )
23
+
24
+ app = FastAPI(
25
+ title="FarmLingua Backend",
26
+ description="Backend service for FarmLingua with RAG updates and CrewAI pipeline",
27
+ version="1.0.0"
28
+ )
29
+
30
+
31
+ app.add_middleware(
32
+ CORSMiddleware,
33
+ allow_origins=config.ALLOWED_ORIGINS if hasattr(config, "ALLOWED_ORIGINS") else ["*"],
34
+ allow_credentials=True,
35
+ allow_methods=["*"],
36
+ allow_headers=["*"],
37
+ )
38
+
39
+
40
+ @app.on_event("startup")
41
+ def startup_event():
42
+ """Start scheduled RAG updates when the app launches."""
43
+ logging.info(" Starting FarmLingua backend...")
44
+ schedule_updates()
45
+
46
+
47
+ @app.get("/")
48
+ def home():
49
+ return {
50
+ "status": "FarmLingua backend running",
51
+ "version": "1.0.0",
52
+ "vectorstore_path": config.VECTORSTORE_PATH
53
+ }
54
+
55
+ @app.post("/ask")
56
+ def ask_farmbot(query: str = Body(..., embed=True)):
57
+ """
58
+ Ask the FarmLingua AI a question.
59
+ Uses the crew_pipeline to process and return a detailed, farmer-friendly answer.
60
+ """
61
+ logging.info(f"Received query: {query}")
62
+ answer = run_pipeline(query)
63
+ return {"query": query, "answer": answer}
64
+
65
+
66
+ if __name__ == "__main__":
67
+ uvicorn.run(
68
+ "app.main:app",
69
+ host="0.0.0.0",
70
+ port=getattr(config, "PORT", 7860),
71
+ reload=bool(getattr(config, "DEBUG", False))
72
+ )
app/models/__init__.py ADDED
File without changes
app/models/intent_classifier_v2.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ffeda9eeb604a1a24ef64e774eb6b503ead5eae6ad3b043401033040a4309405
3
+ size 39296294
app/tasks/__init__.py ADDED
File without changes
app/tasks/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (172 Bytes). View file
 
app/tasks/__pycache__/rag_updater.cpython-311.pyc ADDED
Binary file (8.43 kB). View file
 
app/tasks/rag_updater.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # farmlingua_backend/app/tasks/rag_updater.py
2
+ import os
3
+ import sys
4
+ from datetime import datetime, date
5
+ import logging
6
+ import requests
7
+ from bs4 import BeautifulSoup
8
+ from apscheduler.schedulers.background import BackgroundScheduler
9
+
10
+ from langchain.vectorstores import FAISS
11
+ from langchain.embeddings import SentenceTransformerEmbeddings
12
+ from langchain.docstore.document import Document
13
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
14
+
15
+ from app.utils import config
16
+
17
+ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18
+ if BASE_DIR not in sys.path:
19
+ sys.path.insert(0, BASE_DIR)
20
+
21
+ logging.basicConfig(
22
+ format="%(asctime)s [%(levelname)s] %(message)s",
23
+ level=logging.INFO
24
+ )
25
+
26
+ session = requests.Session()
27
+
28
+ def fetch_weather_now():
29
+ """Fetch current weather for all configured states."""
30
+ docs = []
31
+ for state in config.STATES:
32
+ try:
33
+ url = "http://api.weatherapi.com/v1/current.json"
34
+ params = {
35
+ "key": config.WEATHER_API_KEY,
36
+ "q": f"{state}, Nigeria",
37
+ "aqi": "no"
38
+ }
39
+ res = session.get(url, params=params, timeout=10)
40
+ res.raise_for_status()
41
+ data = res.json()
42
+
43
+ if "current" in data:
44
+ condition = data['current']['condition']['text']
45
+ temp_c = data['current']['temp_c']
46
+ humidity = data['current']['humidity']
47
+ text = (
48
+ f"Weather in {state}: {condition}, "
49
+ f"Temperature: {temp_c}°C, Humidity: {humidity}%"
50
+ )
51
+ docs.append(Document(
52
+ page_content=text,
53
+ metadata={
54
+ "source": "WeatherAPI",
55
+ "location": state,
56
+ "timestamp": datetime.utcnow().isoformat()
57
+ }
58
+ ))
59
+ except Exception as e:
60
+ logging.error(f"Weather fetch failed for {state}: {e}")
61
+ return docs
62
+
63
+ def fetch_harvestplus_articles():
64
+ """Fetch ALL today's articles from HarvestPlus site."""
65
+ try:
66
+ res = session.get(config.DATA_SOURCES["harvestplus"], timeout=10)
67
+ res.raise_for_status()
68
+ soup = BeautifulSoup(res.text, "html.parser")
69
+ articles = soup.find_all("article")
70
+
71
+ docs = []
72
+ today_str = date.today().strftime("%Y-%m-%d")
73
+
74
+ for a in articles:
75
+ content = a.get_text(strip=True)
76
+ if content and len(content) > 100:
77
+
78
+ if today_str in a.text or True:
79
+ docs.append(Document(
80
+ page_content=content,
81
+ metadata={
82
+ "source": "HarvestPlus",
83
+ "timestamp": datetime.utcnow().isoformat()
84
+ }
85
+ ))
86
+ return docs
87
+ except Exception as e:
88
+ logging.error(f"HarvestPlus fetch failed: {e}")
89
+ return []
90
+
91
+ def build_rag_vectorstore(reset=False):
92
+ job_type = "FULL REBUILD" if reset else "INCREMENTAL UPDATE"
93
+ logging.info(f"RAG update started — {job_type}")
94
+
95
+ all_docs = fetch_weather_now() + fetch_harvestplus_articles()
96
+
97
+ logging.info(f"Weather docs fetched: {len([d for d in all_docs if d.metadata['source'] == 'WeatherAPI'])}")
98
+ logging.info(f"News docs fetched: {len([d for d in all_docs if d.metadata['source'] == 'HarvestPlus'])}")
99
+
100
+ if not all_docs:
101
+ logging.warning("No documents fetched, skipping update")
102
+ return
103
+
104
+ splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
105
+ chunks = splitter.split_documents(all_docs)
106
+
107
+ embedder = SentenceTransformerEmbeddings(model_name=config.EMBEDDING_MODEL)
108
+
109
+ vectorstore_path = config.LIVE_VS_PATH
110
+
111
+ if reset and os.path.exists(vectorstore_path):
112
+ for file in os.listdir(vectorstore_path):
113
+ file_path = os.path.join(vectorstore_path, file)
114
+ try:
115
+ os.remove(file_path)
116
+ logging.info(f"Deleted old file: {file_path}")
117
+ except Exception as e:
118
+ logging.error(f"Failed to delete {file_path}: {e}")
119
+
120
+ if os.path.exists(vectorstore_path) and not reset:
121
+ vs = FAISS.load_local(
122
+ vectorstore_path,
123
+ embedder,
124
+ allow_dangerous_deserialization=True
125
+ )
126
+ vs.add_documents(chunks)
127
+ else:
128
+ vs = FAISS.from_documents(chunks, embedder)
129
+
130
+ os.makedirs(vectorstore_path, exist_ok=True)
131
+ vs.save_local(vectorstore_path)
132
+
133
+ logging.info(f"Vectorstore updated at {vectorstore_path}")
134
+
135
+ def schedule_updates():
136
+ scheduler = BackgroundScheduler()
137
+ scheduler.add_job(build_rag_vectorstore, 'interval', hours=12, kwargs={"reset": False})
138
+ scheduler.add_job(build_rag_vectorstore, 'interval', days=7, kwargs={"reset": True})
139
+ scheduler.start()
140
+ logging.info("Scheduler started — 12-hour incremental updates + weekly full rebuild")
141
+ return scheduler
app/utils/__init__.py ADDED
File without changes
app/utils/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (172 Bytes). View file
 
app/utils/__pycache__/config.cpython-311.pyc ADDED
Binary file (1.85 kB). View file
 
app/utils/config.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # farmlingua_backend/app/utils/config.py
2
+ from pathlib import Path
3
+ import os
4
+ import sys
5
+
6
+
7
+ BASE_DIR = Path(__file__).resolve().parents[2]
8
+
9
+
10
+ if str(BASE_DIR) not in sys.path:
11
+ sys.path.insert(0, str(BASE_DIR))
12
+
13
+ EMBEDDING_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
14
+ STATIC_VS_PATH = BASE_DIR / "app" / "vectorstore" / "faiss_index"
15
+ LIVE_VS_PATH = BASE_DIR / "app" / "vectorstore" / "live_rag_index"
16
+
17
+ VECTORSTORE_PATH = LIVE_VS_PATH
18
+
19
+
20
+ WEATHER_API_KEY = os.getenv("WEATHER_API_KEY", "d72aad0c21c74cf897b105451250408")
21
+
22
+
23
+ CLASSIFIER_PATH = BASE_DIR / "app" / "models" / "intent_classifier_v2.joblib"
24
+ CLASSIFIER_CONFIDENCE_THRESHOLD = float(os.getenv("CLASSIFIER_CONFIDENCE_THRESHOLD", "0.6"))
25
+
26
+
27
+ EXPERT_MODEL_NAME = os.getenv("EXPERT_MODEL_NAME", "NousResearch/Nous-Hermes-2-Mistral-7B-DPO")
28
+ FORMATTER_MODEL_NAME = os.getenv("FORMATTER_MODEL_NAME", "google/flan-t5-large")
29
+
30
+
31
+ DATA_SOURCES = {
32
+ "harvestplus": "https://agronigeria.ng/category/news/",
33
+ }
34
+
35
+ STATES = [
36
+ "Abuja", "Lagos", "Kano", "Kaduna", "Rivers", "Enugu", "Anambra", "Ogun",
37
+ "Oyo", "Delta", "Edo", "Katsina", "Borno", "Benue", "Niger", "Plateau",
38
+ "Bauchi", "Adamawa", "Cross River", "Akwa Ibom", "Ekiti", "Osun", "Ondo",
39
+ "Imo", "Abia", "Ebonyi", "Taraba", "Kebbi", "Zamfara", "Yobe", "Gombe",
40
+ "Sokoto", "Kogi", "Bayelsa", "Nasarawa", "Jigawa"
41
+ ]
app/vectorstore/__init__.py ADDED
File without changes
app/vectorstore/faiss_index/index.faiss ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d4faefcc68ae5a575b18f559e04cd2c68e166a73c4c89c9550e1794ccbf90695
3
+ size 19648557
app/vectorstore/faiss_index/index.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a1c75f31eab757e90e9c9771b62368c2de5dc11ed776629521fb007d8d47b84a
3
+ size 5863908
app/vectorstore/live_rag_index/index.faiss ADDED
Binary file (70.7 kB). View file
 
app/vectorstore/live_rag_index/index.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:466653741f0cbbcbb51c817af910e5ca03c769e9009b3e3bf0f6fdcad71393b1
3
+ size 12074
app/venv/bin/python ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6576b9698f70099339119b06d3c9765067c335cc72a203b20aa7480b57293839
3
+ size 6727416
app/venv/bin/python3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6576b9698f70099339119b06d3c9765067c335cc72a203b20aa7480b57293839
3
+ size 6727416
app/venv/bin/python3.11 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6576b9698f70099339119b06d3c9765067c335cc72a203b20aa7480b57293839
3
+ size 6727416
app/venv/pyvenv.cfg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ home = /usr/bin
2
+ include-system-site-packages = false
3
+ version = 3.11.13
4
+ executable = /usr/bin/python3.11
5
+ command = /usr/bin/python3 -m venv /content/drive/MyDrive/farmlingua_backend/app/venv
requirements.txt ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ crewai
2
+ langchain
3
+ langchain-community
4
+ faiss-cpu
5
+ transformers
6
+ sentence-transformers
7
+ pydantic
8
+ joblib
9
+ pyyaml
10
+ torch
11
+ fastapi
12
+ uvicorn
13
+ apscheduler
14
+ numpy
15
+ requests
16
+ beautifulsoup4
17
+ huggingface-hub
18
+ python-dotenv