Update app.py
Browse files
app.py
CHANGED
|
@@ -128,7 +128,7 @@ retriever = ensemble_retriever
|
|
| 128 |
system_prompt = (
|
| 129 |
"You are the LA2050 Navigator, an AI-powered chatbot created to help users discover organizations and community initiatives featured in the Goldhirsh Foundation’s LA2050 Ideas Hub. "
|
| 130 |
"Your role is to deliver succinct, personalized recommendations, guide users toward supporting these initiatives, and answer questions about the Goldhirsh Foundation, LA2050, and its projects. "
|
| 131 |
-
"When responding, include the full name of the organization, a brief (1-2 sentence) description, and a link to its website(labeled as Organization website) or social media; (please do not alter the URL). "
|
| 132 |
"If an organization’s personal website is unavailable, refer to its LA2050 URL. "
|
| 133 |
"Prioritize nonprofit organizations designated as 'winners' by the Goldhirsh Foundation and those with multiple proposal submissions. "
|
| 134 |
"If a user inquires about the LA2050 grant winners for a specific year, be sure to reference the metadata 'Year' and 'LA 2050 Grant Status' fields—explicitly noting if the organization was awarded the grant that year. "
|
|
@@ -136,6 +136,11 @@ system_prompt = (
|
|
| 136 |
"If some information is missing, acknowledge it and direct the user to additional resources. "
|
| 137 |
"Maintain a polite, helpful, respectful, and enthusiastic tone at all times. "
|
| 138 |
"If the user responds with a follow-up confirmation (e.g., 'yes') after an initial answer, please expand on that topic with further details. "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
"\n\n{context}"
|
| 140 |
)
|
| 141 |
|
|
@@ -152,6 +157,16 @@ prompt = ChatPromptTemplate.from_messages(
|
|
| 152 |
# Build the chain that will combine documents with the prompt.
|
| 153 |
question_answer_chain = create_stuff_documents_chain(ChatOpenAI(model_name="gpt-4o-mini", temperature=0), prompt)
|
| 154 |
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
def debug_retrieved_docs(user_input):
|
| 156 |
retrieved_docs = retriever.get_relevant_documents(user_input)
|
| 157 |
print(f"DEBUG: Retrieved {len(retrieved_docs)} documents.")
|
|
@@ -193,7 +208,8 @@ green_theme = gr.themes.Base(
|
|
| 193 |
button_secondary_text_color='#000000'
|
| 194 |
)
|
| 195 |
|
| 196 |
-
|
|
|
|
| 197 |
# Initialize conversation with a welcome message if history is empty.
|
| 198 |
if not history:
|
| 199 |
history = [{"role": "assistant", "content": "<b>LA2050 Navigator:</b><br> Welcome to the LA2050 ideas hub! How can I help you today?"}]
|
|
@@ -211,7 +227,7 @@ def message_and_history(message, history):
|
|
| 211 |
|
| 212 |
# Combine the most recent conversation turns, excluding the assistant's prefix.
|
| 213 |
conversation_context = "\n".join(
|
| 214 |
-
[f"{msg['role']}: {msg['content'].replace('<b>LA2050 Navigator:</b><br>', '')}" for msg in history[
|
| 215 |
)
|
| 216 |
retrieved_docs = retriever.get_relevant_documents(conversation_context)
|
| 217 |
print(f"DEBUG: Retrieved {len(retrieved_docs)} documents.")
|
|
@@ -223,13 +239,15 @@ def message_and_history(message, history):
|
|
| 223 |
try:
|
| 224 |
response = rag_chain.invoke(chain_input)
|
| 225 |
answer = response["answer"]
|
|
|
|
|
|
|
| 226 |
except Exception as e:
|
| 227 |
answer = f"An error occurred: {e}"
|
| 228 |
|
| 229 |
# Remove the prefix if the model includes it.
|
| 230 |
if answer.startswith("<b>LA2050 Navigator:</b><br>"):
|
| 231 |
answer = answer[len("<b>LA2050 Navigator:</b><br>"):]
|
| 232 |
-
|
| 233 |
# Initialize the assistant's response with the prefix.
|
| 234 |
assistant_response = {"role": "assistant", "content": "<b>LA2050 Navigator:</b><br> "}
|
| 235 |
history.append(assistant_response)
|
|
|
|
| 128 |
system_prompt = (
|
| 129 |
"You are the LA2050 Navigator, an AI-powered chatbot created to help users discover organizations and community initiatives featured in the Goldhirsh Foundation’s LA2050 Ideas Hub. "
|
| 130 |
"Your role is to deliver succinct, personalized recommendations, guide users toward supporting these initiatives, and answer questions about the Goldhirsh Foundation, LA2050, and its projects. "
|
| 131 |
+
"When responding, include the full name of the organization, a brief (1-2 sentence) description, and a link to its website (labeled as Organization website) or social media; (please do not alter the URL). "
|
| 132 |
"If an organization’s personal website is unavailable, refer to its LA2050 URL. "
|
| 133 |
"Prioritize nonprofit organizations designated as 'winners' by the Goldhirsh Foundation and those with multiple proposal submissions. "
|
| 134 |
"If a user inquires about the LA2050 grant winners for a specific year, be sure to reference the metadata 'Year' and 'LA 2050 Grant Status' fields—explicitly noting if the organization was awarded the grant that year. "
|
|
|
|
| 136 |
"If some information is missing, acknowledge it and direct the user to additional resources. "
|
| 137 |
"Maintain a polite, helpful, respectful, and enthusiastic tone at all times. "
|
| 138 |
"If the user responds with a follow-up confirmation (e.g., 'yes') after an initial answer, please expand on that topic with further details. "
|
| 139 |
+
"\n\nIMPORTANT: Answer the question using ONLY the information provided in the following documents. DO NOT invent or include any organizations that are not present in the retrieved evidence. "
|
| 140 |
+
"Before giving your final answer, perform the following steps: "
|
| 141 |
+
"Step 1: Identify all organizations mentioned in the retrieved documents. "
|
| 142 |
+
"Step 2: Check if there are any organizations beyond those provided that could be considered 'new'. "
|
| 143 |
+
"Step 3: If no additional organizations exist, clearly state that based on the current dataset, these are all the organizations we have information on. "
|
| 144 |
"\n\n{context}"
|
| 145 |
)
|
| 146 |
|
|
|
|
| 157 |
# Build the chain that will combine documents with the prompt.
|
| 158 |
question_answer_chain = create_stuff_documents_chain(ChatOpenAI(model_name="gpt-4o-mini", temperature=0), prompt)
|
| 159 |
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
|
| 160 |
+
|
| 161 |
+
def post_process_answer(answer, retrieved_docs):
|
| 162 |
+
"""
|
| 163 |
+
Append a disclaimer to the answer confirming that only organizations from the retrieved documents were used.
|
| 164 |
+
(A more advanced implementation might parse and filter out any hallucinated names.)
|
| 165 |
+
"""
|
| 166 |
+
# Extract allowed organization names from retrieved docs.
|
| 167 |
+
allowed_orgs = {doc.metadata.get("Organization", "").strip() for doc in retrieved_docs if doc.metadata.get("Organization", "").strip()}
|
| 168 |
+
disclaimer = "\n\n[Answer verified against retrieved documents: Only organizations present in the evidence were included. Allowed organizations: " + ", ".join(sorted(allowed_orgs)) + ".]"
|
| 169 |
+
return answer + disclaimer
|
| 170 |
def debug_retrieved_docs(user_input):
|
| 171 |
retrieved_docs = retriever.get_relevant_documents(user_input)
|
| 172 |
print(f"DEBUG: Retrieved {len(retrieved_docs)} documents.")
|
|
|
|
| 208 |
button_secondary_text_color='#000000'
|
| 209 |
)
|
| 210 |
|
| 211 |
+
|
| 212 |
+
def message_and_history(message, history):
|
| 213 |
# Initialize conversation with a welcome message if history is empty.
|
| 214 |
if not history:
|
| 215 |
history = [{"role": "assistant", "content": "<b>LA2050 Navigator:</b><br> Welcome to the LA2050 ideas hub! How can I help you today?"}]
|
|
|
|
| 227 |
|
| 228 |
# Combine the most recent conversation turns, excluding the assistant's prefix.
|
| 229 |
conversation_context = "\n".join(
|
| 230 |
+
[f"{msg['role']}: {msg['content'].replace('<b>LA2050 Navigator:</b><br>', '')}" for msg in history[-2:]]
|
| 231 |
)
|
| 232 |
retrieved_docs = retriever.get_relevant_documents(conversation_context)
|
| 233 |
print(f"DEBUG: Retrieved {len(retrieved_docs)} documents.")
|
|
|
|
| 239 |
try:
|
| 240 |
response = rag_chain.invoke(chain_input)
|
| 241 |
answer = response["answer"]
|
| 242 |
+
# Post-process the answer to append a disclaimer verifying the evidence.
|
| 243 |
+
answer = post_process_answer(answer, retrieved_docs)
|
| 244 |
except Exception as e:
|
| 245 |
answer = f"An error occurred: {e}"
|
| 246 |
|
| 247 |
# Remove the prefix if the model includes it.
|
| 248 |
if answer.startswith("<b>LA2050 Navigator:</b><br>"):
|
| 249 |
answer = answer[len("<b>LA2050 Navigator:</b><br>"):]
|
| 250 |
+
|
| 251 |
# Initialize the assistant's response with the prefix.
|
| 252 |
assistant_response = {"role": "assistant", "content": "<b>LA2050 Navigator:</b><br> "}
|
| 253 |
history.append(assistant_response)
|