Spaces:
Sleeping
Sleeping
Upload 64 files
Browse files- .github/workflows/sync-to-hf.yml +25 -0
- app.py +5 -46
- graph/__pycache__/__init__.cpython-310.pyc +0 -0
- graph/__pycache__/workflow.cpython-310.pyc +0 -0
- graph/workflow.py +47 -6
- start_web.sh +21 -21
- test_pipeline.py +32 -0
.github/workflows/sync-to-hf.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Sync to Hugging Face Space
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- main
|
| 7 |
+
|
| 8 |
+
jobs:
|
| 9 |
+
sync-to-huggingface:
|
| 10 |
+
runs-on: ubuntu-latest
|
| 11 |
+
steps:
|
| 12 |
+
- name: Checkout repository
|
| 13 |
+
uses: actions/checkout@v3
|
| 14 |
+
with:
|
| 15 |
+
fetch-depth: 0
|
| 16 |
+
lfs: true
|
| 17 |
+
|
| 18 |
+
- name: Push to Hugging Face Space
|
| 19 |
+
env:
|
| 20 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
| 21 |
+
run: |
|
| 22 |
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
| 23 |
+
git config --global user.name "github-actions[bot]"
|
| 24 |
+
git remote add hf https://HF_USERNAME:$HF_TOKEN@huggingface.co/spaces/Anmol4521/jansahayak
|
| 25 |
+
git push hf main --force
|
app.py
CHANGED
|
@@ -33,28 +33,6 @@ VECTORSTORES_INITIALIZED = False
|
|
| 33 |
SKIP_VECTORSTORES = os.environ.get('SKIP_VECTORSTORES', 'false').lower() == 'true'
|
| 34 |
|
| 35 |
|
| 36 |
-
def load_saved_result(session_id: str):
|
| 37 |
-
"""Load a previously saved result from disk if the in-memory session is unavailable."""
|
| 38 |
-
if not os.path.exists('outputs'):
|
| 39 |
-
return None
|
| 40 |
-
|
| 41 |
-
for filename in os.listdir('outputs'):
|
| 42 |
-
if not filename.endswith('.json'):
|
| 43 |
-
continue
|
| 44 |
-
|
| 45 |
-
filepath = os.path.join('outputs', filename)
|
| 46 |
-
try:
|
| 47 |
-
with open(filepath, 'r', encoding='utf-8') as f:
|
| 48 |
-
data = json.load(f)
|
| 49 |
-
|
| 50 |
-
if data.get('session_id') == session_id or session_id in filename:
|
| 51 |
-
return data
|
| 52 |
-
except Exception:
|
| 53 |
-
continue
|
| 54 |
-
|
| 55 |
-
return None
|
| 56 |
-
|
| 57 |
-
|
| 58 |
def initialize_vectorstores():
|
| 59 |
"""Load vectorstores lazily on first use to avoid blocking port binding"""
|
| 60 |
global SCHEME_VECTORSTORE, EXAM_VECTORSTORE, VECTORSTORES_INITIALIZED
|
|
@@ -244,9 +222,6 @@ def analyze():
|
|
| 244 |
# Ensure user_profile key exists in result
|
| 245 |
if 'user_profile' not in result and 'profile' in result:
|
| 246 |
result['user_profile'] = result['profile']
|
| 247 |
-
|
| 248 |
-
result['session_id'] = session_id
|
| 249 |
-
result['generated_at'] = datetime.now().isoformat()
|
| 250 |
|
| 251 |
# Update session
|
| 252 |
sessions[session_id]['status'] = 'completed'
|
|
@@ -255,7 +230,7 @@ def analyze():
|
|
| 255 |
|
| 256 |
# Save to file
|
| 257 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 258 |
-
filename = f"outputs/results_{
|
| 259 |
os.makedirs('outputs', exist_ok=True)
|
| 260 |
|
| 261 |
with open(filename, 'w', encoding='utf-8') as f:
|
|
@@ -294,16 +269,8 @@ def analyze():
|
|
| 294 |
def result(session_id):
|
| 295 |
"""Display results page"""
|
| 296 |
if session_id not in sessions:
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
sessions[session_id] = {
|
| 300 |
-
'status': 'completed',
|
| 301 |
-
'result': saved_result,
|
| 302 |
-
'completed_at': saved_result.get('generated_at', datetime.now().isoformat())
|
| 303 |
-
}
|
| 304 |
-
else:
|
| 305 |
-
return render_template('error.html',
|
| 306 |
-
error='Session not found'), 404
|
| 307 |
|
| 308 |
session_data = sessions[session_id]
|
| 309 |
|
|
@@ -341,8 +308,7 @@ def history():
|
|
| 341 |
data = json.load(f)
|
| 342 |
output_files.append({
|
| 343 |
'filename': filename,
|
| 344 |
-
'timestamp':
|
| 345 |
-
'session_id': data.get('session_id', filename.replace('results_', '').replace('.json', '')),
|
| 346 |
'profile': data.get('user_profile', {}),
|
| 347 |
'errors': data.get('errors', [])
|
| 348 |
})
|
|
@@ -367,14 +333,7 @@ def download_pdf(session_id):
|
|
| 367 |
"""Generate and download PDF report"""
|
| 368 |
try:
|
| 369 |
if session_id not in sessions:
|
| 370 |
-
|
| 371 |
-
if not saved_result:
|
| 372 |
-
return jsonify({'error': 'Session not found'}), 404
|
| 373 |
-
sessions[session_id] = {
|
| 374 |
-
'status': 'completed',
|
| 375 |
-
'result': saved_result,
|
| 376 |
-
'completed_at': saved_result.get('generated_at', datetime.now().isoformat())
|
| 377 |
-
}
|
| 378 |
|
| 379 |
session_data = sessions[session_id]
|
| 380 |
result = session_data.get('result', {})
|
|
|
|
| 33 |
SKIP_VECTORSTORES = os.environ.get('SKIP_VECTORSTORES', 'false').lower() == 'true'
|
| 34 |
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
def initialize_vectorstores():
|
| 37 |
"""Load vectorstores lazily on first use to avoid blocking port binding"""
|
| 38 |
global SCHEME_VECTORSTORE, EXAM_VECTORSTORE, VECTORSTORES_INITIALIZED
|
|
|
|
| 222 |
# Ensure user_profile key exists in result
|
| 223 |
if 'user_profile' not in result and 'profile' in result:
|
| 224 |
result['user_profile'] = result['profile']
|
|
|
|
|
|
|
|
|
|
| 225 |
|
| 226 |
# Update session
|
| 227 |
sessions[session_id]['status'] = 'completed'
|
|
|
|
| 230 |
|
| 231 |
# Save to file
|
| 232 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 233 |
+
filename = f"outputs/results_{timestamp}.json"
|
| 234 |
os.makedirs('outputs', exist_ok=True)
|
| 235 |
|
| 236 |
with open(filename, 'w', encoding='utf-8') as f:
|
|
|
|
| 269 |
def result(session_id):
|
| 270 |
"""Display results page"""
|
| 271 |
if session_id not in sessions:
|
| 272 |
+
return render_template('error.html',
|
| 273 |
+
error='Session not found'), 404
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
|
| 275 |
session_data = sessions[session_id]
|
| 276 |
|
|
|
|
| 308 |
data = json.load(f)
|
| 309 |
output_files.append({
|
| 310 |
'filename': filename,
|
| 311 |
+
'timestamp': filename.replace('results_', '').replace('.json', ''),
|
|
|
|
| 312 |
'profile': data.get('user_profile', {}),
|
| 313 |
'errors': data.get('errors', [])
|
| 314 |
})
|
|
|
|
| 333 |
"""Generate and download PDF report"""
|
| 334 |
try:
|
| 335 |
if session_id not in sessions:
|
| 336 |
+
return jsonify({'error': 'Session not found'}), 404
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
session_data = sessions[session_id]
|
| 339 |
result = session_data.get('result', {})
|
graph/__pycache__/__init__.cpython-310.pyc
ADDED
|
Binary file (193 Bytes). View file
|
|
|
graph/__pycache__/workflow.cpython-310.pyc
ADDED
|
Binary file (8.12 kB). View file
|
|
|
graph/workflow.py
CHANGED
|
@@ -114,8 +114,22 @@ def scheme_node(state: AgentState) -> dict:
|
|
| 114 |
print(f"β
Profile has {len(useful_fields)} useful fields")
|
| 115 |
|
| 116 |
result = run_scheme_agent(profile, use_web_search=True, vectorstore=scheme_vectorstore)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
print("β
Scheme recommendations generated")
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
except Exception as e:
|
| 121 |
print(f"β Scheme Agent Error: {str(e)}")
|
|
@@ -151,8 +165,22 @@ def exam_node(state: AgentState) -> dict:
|
|
| 151 |
# Still try with whatever we have
|
| 152 |
|
| 153 |
result = run_exam_agent(profile, use_web_search=True, vectorstore=exam_vectorstore)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
print("β
Exam recommendations generated")
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
except Exception as e:
|
| 158 |
print(f"β Exam Agent Error: {str(e)}")
|
|
@@ -174,18 +202,31 @@ def benefit_node(state: AgentState) -> dict:
|
|
| 174 |
profile = state.get("profile", {})
|
| 175 |
scheme_recommendations = state.get("scheme_recommendations", "")
|
| 176 |
|
| 177 |
-
if not profile or not scheme_recommendations:
|
| 178 |
print("β οΈ Insufficient data for benefit calculation")
|
| 179 |
return {"missed_benefits": "Insufficient data"}
|
| 180 |
|
| 181 |
result = calculate_missed_benefits(profile, scheme_recommendations)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
print("β
Benefit calculation completed")
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
|
| 185 |
except Exception as e:
|
| 186 |
-
print(f"β Benefit Agent
|
| 187 |
return {
|
| 188 |
-
"missed_benefits": "",
|
| 189 |
"errors": [f"Benefit: {str(e)}"]
|
| 190 |
}
|
| 191 |
|
|
|
|
| 114 |
print(f"β
Profile has {len(useful_fields)} useful fields")
|
| 115 |
|
| 116 |
result = run_scheme_agent(profile, use_web_search=True, vectorstore=scheme_vectorstore)
|
| 117 |
+
|
| 118 |
+
if "error" in result:
|
| 119 |
+
print(f"β Scheme Agent returned Error: {result['error']}")
|
| 120 |
+
return {
|
| 121 |
+
"scheme_recommendations": f"Error generating recommendations: {result['error']}",
|
| 122 |
+
"errors": [f"Scheme: {result['error']}"]
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
print("β
Scheme recommendations generated")
|
| 126 |
+
|
| 127 |
+
# Ensure it's a string, not a list on failure
|
| 128 |
+
recs = result.get("recommendations", "")
|
| 129 |
+
if isinstance(recs, list):
|
| 130 |
+
recs = " ".join(recs) if recs else "Failed to generate recommendations"
|
| 131 |
+
|
| 132 |
+
return {"scheme_recommendations": recs}
|
| 133 |
|
| 134 |
except Exception as e:
|
| 135 |
print(f"β Scheme Agent Error: {str(e)}")
|
|
|
|
| 165 |
# Still try with whatever we have
|
| 166 |
|
| 167 |
result = run_exam_agent(profile, use_web_search=True, vectorstore=exam_vectorstore)
|
| 168 |
+
|
| 169 |
+
if "error" in result:
|
| 170 |
+
print(f"β Exam Agent returned Error: {result['error']}")
|
| 171 |
+
return {
|
| 172 |
+
"exam_recommendations": f"Error generating recommendations: {result['error']}",
|
| 173 |
+
"errors": [f"Exam: {result['error']}"]
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
print("β
Exam recommendations generated")
|
| 177 |
+
|
| 178 |
+
# Ensure it's a string
|
| 179 |
+
recs = result.get("recommendations", "")
|
| 180 |
+
if isinstance(recs, list):
|
| 181 |
+
recs = " ".join(recs) if recs else "Failed to generate recommendations"
|
| 182 |
+
|
| 183 |
+
return {"exam_recommendations": recs}
|
| 184 |
|
| 185 |
except Exception as e:
|
| 186 |
print(f"β Exam Agent Error: {str(e)}")
|
|
|
|
| 202 |
profile = state.get("profile", {})
|
| 203 |
scheme_recommendations = state.get("scheme_recommendations", "")
|
| 204 |
|
| 205 |
+
if not profile or not scheme_recommendations or scheme_recommendations == "[]":
|
| 206 |
print("β οΈ Insufficient data for benefit calculation")
|
| 207 |
return {"missed_benefits": "Insufficient data"}
|
| 208 |
|
| 209 |
result = calculate_missed_benefits(profile, scheme_recommendations)
|
| 210 |
+
|
| 211 |
+
if "error" in result:
|
| 212 |
+
print(f"β Benefit Agent returned Error: {result['error']}")
|
| 213 |
+
return {
|
| 214 |
+
"missed_benefits": f"Error calculating benefits: {result['error']}",
|
| 215 |
+
"errors": [f"Benefit: {result['error']}"]
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
print("β
Benefit calculation completed")
|
| 219 |
+
|
| 220 |
+
calc = result.get("calculation", "")
|
| 221 |
+
if not calc:
|
| 222 |
+
calc = "Benefit calculation returned no result."
|
| 223 |
+
|
| 224 |
+
return {"missed_benefits": calc}
|
| 225 |
|
| 226 |
except Exception as e:
|
| 227 |
+
print(f"β Benefit Agent Exception: {str(e)}")
|
| 228 |
return {
|
| 229 |
+
"missed_benefits": f"Error calculating benefits: {str(e)}",
|
| 230 |
"errors": [f"Benefit: {str(e)}"]
|
| 231 |
}
|
| 232 |
|
start_web.sh
CHANGED
|
@@ -1,21 +1,21 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
echo "================================"
|
| 4 |
-
echo "JanSahayak - Starting Web Server"
|
| 5 |
-
echo "================================"
|
| 6 |
-
echo
|
| 7 |
-
|
| 8 |
-
# Check if virtual environment exists
|
| 9 |
-
if [ ! -d ".venv" ]; then
|
| 10 |
-
echo "Virtual environment not found!"
|
| 11 |
-
echo "Please run setup first."
|
| 12 |
-
exit 1
|
| 13 |
-
fi
|
| 14 |
-
|
| 15 |
-
# Activate virtual environment
|
| 16 |
-
source .venv/bin/activate
|
| 17 |
-
|
| 18 |
-
# Start Flask app
|
| 19 |
-
echo "Starting Flask application..."
|
| 20 |
-
echo
|
| 21 |
-
python app.py
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
echo "================================"
|
| 4 |
+
echo "JanSahayak - Starting Web Server"
|
| 5 |
+
echo "================================"
|
| 6 |
+
echo
|
| 7 |
+
|
| 8 |
+
# Check if virtual environment exists
|
| 9 |
+
if [ ! -d ".venv" ]; then
|
| 10 |
+
echo "Virtual environment not found!"
|
| 11 |
+
echo "Please run setup first."
|
| 12 |
+
exit 1
|
| 13 |
+
fi
|
| 14 |
+
|
| 15 |
+
# Activate virtual environment
|
| 16 |
+
source .venv/bin/activate
|
| 17 |
+
|
| 18 |
+
# Start Flask app
|
| 19 |
+
echo "Starting Flask application..."
|
| 20 |
+
echo
|
| 21 |
+
python app.py
|
test_pipeline.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
| 5 |
+
|
| 6 |
+
from graph.workflow import build_workflow
|
| 7 |
+
|
| 8 |
+
def test():
|
| 9 |
+
app = build_workflow()
|
| 10 |
+
|
| 11 |
+
initial_state = {
|
| 12 |
+
"user_input": "I am a 25 year old farmer with 2 acres of land",
|
| 13 |
+
"user_interests": ["schemes", "exams"],
|
| 14 |
+
"profile": {},
|
| 15 |
+
"scheme_vectorstore": None,
|
| 16 |
+
"exam_vectorstore": None,
|
| 17 |
+
"errors": []
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
try:
|
| 21 |
+
# We need GROQ_API_KEY for this to work
|
| 22 |
+
os.environ["GROQ_API_KEY"] = "gsk_dummy" # But this will fail authentication
|
| 23 |
+
# So instead we mock the LLM calls to see the graph flow.
|
| 24 |
+
|
| 25 |
+
# Actually let's just print the graph flow if possible?
|
| 26 |
+
# Or better yet, we can see if scheme_recommendations is not being populated correctly.
|
| 27 |
+
pass
|
| 28 |
+
except Exception as e:
|
| 29 |
+
print(f"Error: {e}")
|
| 30 |
+
|
| 31 |
+
if __name__ == "__main__":
|
| 32 |
+
test()
|