Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
|
2 |
import os
|
3 |
import json
|
4 |
from dotenv import load_dotenv
|
@@ -14,25 +14,16 @@ from google.adk.runners import Runner
|
|
14 |
from google.adk.tools import FunctionTool
|
15 |
from google.genai import types
|
16 |
from langchain_tavily import TavilySearch
|
17 |
-
import gspread
|
18 |
import uuid
|
19 |
import datetime
|
20 |
|
21 |
# === CONFIGURE ENV AND AUTH ===
|
22 |
load_dotenv()
|
23 |
-
hf_token = os.getenv("HUGGINGFACE_TOKEN")
|
24 |
-
assert hf_token, "Please set HUGGINGFACE_TOKEN in your .env"
|
25 |
-
login(token=hf_token)
|
26 |
-
assert os.getenv("GOOGLE_API_KEY"), "Set GOOGLE_API_KEY in .env"
|
27 |
-
assert os.getenv("TAVILY_API_KEY"), "Set TAVILY_API_KEY in .env"
|
28 |
-
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
|
29 |
-
|
30 |
-
|
31 |
service_account_path = {
|
32 |
"type": os.getenv("type"),
|
33 |
"project_id": os.getenv("project_id"),
|
34 |
"private_key_id": str(os.getenv("private_key_id")).replace('\\n', '\n'),
|
35 |
-
"private_key":
|
36 |
"client_email": os.getenv("client_email"),
|
37 |
"client_id": os.getenv("client_id"),
|
38 |
"auth_uri": os.getenv("auth_uri"),
|
@@ -41,17 +32,12 @@ service_account_path = {
|
|
41 |
"client_x509_cert_url": os.getenv("client_x509_cert_url"),
|
42 |
"universe_domain":os.getenv("universe_domain")
|
43 |
}
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
52 |
-
worksheet.append_row([user_id, timestamp, query, response])
|
53 |
-
|
54 |
-
|
55 |
|
56 |
def flatten_json(obj: dict) -> str:
|
57 |
pieces = []
|
@@ -63,6 +49,8 @@ def flatten_json(obj: dict) -> str:
|
|
63 |
recurse("", obj)
|
64 |
return "\n".join(pieces)
|
65 |
|
|
|
|
|
66 |
# === LOAD AND INDEX LOCAL COLLEGE JSONS ===
|
67 |
@st.cache_resource
|
68 |
def load_vector_store(data_dir: str):
|
@@ -71,10 +59,12 @@ def load_vector_store(data_dir: str):
|
|
71 |
if fname.lower().endswith('.json'):
|
72 |
path = os.path.join(data_dir, fname)
|
73 |
try:
|
74 |
-
with open(path, 'r', encoding='utf-8') as f:
|
|
|
75 |
except UnicodeDecodeError:
|
76 |
-
with open(path, 'r', encoding='latin-1') as f:
|
77 |
-
|
|
|
78 |
# st.info(f"Loaded {len(texts)} documents.")
|
79 |
|
80 |
st_model = SentenceTransformer('all-MiniLM-L6-v2')
|
@@ -84,8 +74,22 @@ def load_vector_store(data_dir: str):
|
|
84 |
|
85 |
return FAISS.from_texts(texts, LocalEmbeddings())
|
86 |
|
87 |
-
vector_store = load_vector_store(
|
|
|
|
|
|
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
# === TOOLS ===
|
90 |
def db_search(query: str) -> dict:
|
91 |
docs = vector_store.similarity_search(query, k=6)
|
@@ -107,7 +111,7 @@ tavily_tool = FunctionTool(tavily_search)
|
|
107 |
|
108 |
# === AGENT SETUP ===
|
109 |
@st.cache_resource
|
110 |
-
def create_agent():
|
111 |
agent = Agent(
|
112 |
name="college_info_agent",
|
113 |
model="gemini-2.0-flash",
|
@@ -118,7 +122,8 @@ You are a highly experienced college counselor, specializing in helping high sch
|
|
118 |
2. If `db_search` returns an empty `results` list, immediately call `tavily_search`.\n
|
119 |
3. Do not produce any output until one of those calls returns data.\n
|
120 |
4. As soon as you have non‑empty results, stop further searches and craft your answer using only that source.\n
|
121 |
-
5.
|
|
|
122 |
a. Rank of the student (mandatory)
|
123 |
b. Category (if not provided, assume General)
|
124 |
c. State (optional)
|
@@ -126,16 +131,17 @@ You are a highly experienced college counselor, specializing in helping high sch
|
|
126 |
|
127 |
Note: In your final response, only include colleges where the student is eligible based on their rank. Do not list colleges where the cutoff rank is lower than the student's rank. Ask them to check out Precollege Predictor for more personalized answers, the link of college predictor https://www.precollege.in/college-predictor
|
128 |
|
129 |
-
|
130 |
|
131 |
-
|
|
|
|
|
132 |
|
133 |
-
|
134 |
|
135 |
-
|
136 |
"Sorry, this is beyond the scope of this application"
|
137 |
"""
|
138 |
-
|
139 |
),
|
140 |
tools=[db_tool, tavily_tool],
|
141 |
generate_content_config=types.GenerateContentConfig(
|
@@ -144,11 +150,11 @@ You are a highly experienced college counselor, specializing in helping high sch
|
|
144 |
)
|
145 |
)
|
146 |
session_svc = InMemorySessionService()
|
147 |
-
session = session_svc.create_session(app_name="college_agent_app",
|
148 |
runner = Runner(agent=agent, app_name="college_agent_app", session_service=session_svc)
|
149 |
return runner, session
|
150 |
|
151 |
-
|
152 |
|
153 |
# === STREAMLIT UI ===
|
154 |
st.title("🎓 Jossa-ChatBot")
|
@@ -185,5 +191,4 @@ if query:
|
|
185 |
reply="Please provide complete context."
|
186 |
st.session_state.history.append(("assistant", reply))
|
187 |
add_query_to_sheet(user_id=user_id, query=query, response=reply)
|
188 |
-
st.rerun()
|
189 |
-
|
|
|
1 |
+
import gspread
|
2 |
import os
|
3 |
import json
|
4 |
from dotenv import load_dotenv
|
|
|
14 |
from google.adk.tools import FunctionTool
|
15 |
from google.genai import types
|
16 |
from langchain_tavily import TavilySearch
|
|
|
17 |
import uuid
|
18 |
import datetime
|
19 |
|
20 |
# === CONFIGURE ENV AND AUTH ===
|
21 |
load_dotenv()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
service_account_path = {
|
23 |
"type": os.getenv("type"),
|
24 |
"project_id": os.getenv("project_id"),
|
25 |
"private_key_id": str(os.getenv("private_key_id")).replace('\\n', '\n'),
|
26 |
+
"private_key": str(os.getenv("private_key")).replace('\\n', '\n'),
|
27 |
"client_email": os.getenv("client_email"),
|
28 |
"client_id": os.getenv("client_id"),
|
29 |
"auth_uri": os.getenv("auth_uri"),
|
|
|
32 |
"client_x509_cert_url": os.getenv("client_x509_cert_url"),
|
33 |
"universe_domain":os.getenv("universe_domain")
|
34 |
}
|
35 |
+
hf_token = os.getenv("HUGGINGFACE_TOKEN")
|
36 |
+
assert hf_token, "Please set HUGGINGFACE_TOKEN in your .env"
|
37 |
+
login(token=hf_token)
|
38 |
+
assert os.getenv("GOOGLE_API_KEY"), "Set GOOGLE_API_KEY in .env"
|
39 |
+
assert os.getenv("TAVILY_API_KEY"), "Set TAVILY_API_KEY in .env"
|
40 |
+
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
def flatten_json(obj: dict) -> str:
|
43 |
pieces = []
|
|
|
49 |
recurse("", obj)
|
50 |
return "\n".join(pieces)
|
51 |
|
52 |
+
|
53 |
+
|
54 |
# === LOAD AND INDEX LOCAL COLLEGE JSONS ===
|
55 |
@st.cache_resource
|
56 |
def load_vector_store(data_dir: str):
|
|
|
59 |
if fname.lower().endswith('.json'):
|
60 |
path = os.path.join(data_dir, fname)
|
61 |
try:
|
62 |
+
with open(path, 'r', encoding='utf-8') as f:
|
63 |
+
data = f.read()
|
64 |
except UnicodeDecodeError:
|
65 |
+
with open(path, 'r', encoding='latin-1') as f:
|
66 |
+
data = f.read()
|
67 |
+
texts.append(data)
|
68 |
# st.info(f"Loaded {len(texts)} documents.")
|
69 |
|
70 |
st_model = SentenceTransformer('all-MiniLM-L6-v2')
|
|
|
74 |
|
75 |
return FAISS.from_texts(texts, LocalEmbeddings())
|
76 |
|
77 |
+
vector_store = load_vector_store("Jsons-Colleges/Jsons")
|
78 |
+
|
79 |
+
|
80 |
+
SHEET_KEY = os.getenv("SHEET_KEY")
|
81 |
|
82 |
+
def add_query_to_sheet(user_id, query, response):
|
83 |
+
gc = gspread.service_account_from_dict(service_account_path)
|
84 |
+
sh = gc.open_by_key(SHEET_KEY)
|
85 |
+
worksheet = sh.worksheet("Sheet1")
|
86 |
+
|
87 |
+
|
88 |
+
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
89 |
+
worksheet.append_row([user_id, timestamp, query, response])
|
90 |
+
|
91 |
+
|
92 |
+
|
93 |
# === TOOLS ===
|
94 |
def db_search(query: str) -> dict:
|
95 |
docs = vector_store.similarity_search(query, k=6)
|
|
|
111 |
|
112 |
# === AGENT SETUP ===
|
113 |
@st.cache_resource
|
114 |
+
def create_agent(user_id, session_id):
|
115 |
agent = Agent(
|
116 |
name="college_info_agent",
|
117 |
model="gemini-2.0-flash",
|
|
|
122 |
2. If `db_search` returns an empty `results` list, immediately call `tavily_search`.\n
|
123 |
3. Do not produce any output until one of those calls returns data.\n
|
124 |
4. As soon as you have non‑empty results, stop further searches and craft your answer using only that source.\n
|
125 |
+
5. If a user asks about a college, use the available source to provide the most detailed response possible, preferably structured in bullet points for clarity.
|
126 |
+
6. If a user enters a rank and asks a list of colleges based on their's rank, always consider the following:
|
127 |
a. Rank of the student (mandatory)
|
128 |
b. Category (if not provided, assume General)
|
129 |
c. State (optional)
|
|
|
131 |
|
132 |
Note: In your final response, only include colleges where the student is eligible based on their rank. Do not list colleges where the cutoff rank is lower than the student's rank. Ask them to check out Precollege Predictor for more personalized answers, the link of college predictor https://www.precollege.in/college-predictor
|
133 |
|
134 |
+
7. Rank Eligibility Rule: A student is eligible for a college if their rank is less than or equal to the college’s closing cutoff. (e.g., Rank 2000 is eligible if the cutoff is 2500.)
|
135 |
|
136 |
+
8. If the user wants to compare colleges, present the comparison in a table format for clarity (Mention the opening and closing ranks for the General category.).
|
137 |
+
|
138 |
+
9. Ensure that your response is always complete and fully addresses the user's question, without leaving any sentence or thought unfinished.
|
139 |
|
140 |
+
10. If you cannot find sufficient or specific information, politely direct the student to connect with a verified mentor at: https://precollege.in
|
141 |
|
142 |
+
11. If the user asks a question unrelated to college counseling, respond with:
|
143 |
"Sorry, this is beyond the scope of this application"
|
144 |
"""
|
|
|
145 |
),
|
146 |
tools=[db_tool, tavily_tool],
|
147 |
generate_content_config=types.GenerateContentConfig(
|
|
|
150 |
)
|
151 |
)
|
152 |
session_svc = InMemorySessionService()
|
153 |
+
session = session_svc.create_session(app_name="college_agent_app",user_id=user_id, session_id=session_id)
|
154 |
runner = Runner(agent=agent, app_name="college_agent_app", session_service=session_svc)
|
155 |
return runner, session
|
156 |
|
157 |
+
|
158 |
|
159 |
# === STREAMLIT UI ===
|
160 |
st.title("🎓 Jossa-ChatBot")
|
|
|
191 |
reply="Please provide complete context."
|
192 |
st.session_state.history.append(("assistant", reply))
|
193 |
add_query_to_sheet(user_id=user_id, query=query, response=reply)
|
194 |
+
st.rerun()
|
|