Skip to content

Add Real Estate Chatbot Notebook #693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 300 additions & 0 deletions examples/cookbooks/Chile_Government_Services_Assistant.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "ZH_nR-SvvkDG"
},
"source": [
"# Chile Government Services Assistant - AI Chatbot"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "w8B741JgvpFj"
},
"source": [
"This notebook demonstrates how to use an AI-powered assistant to answer questions about Chilean government services and procedures, using the Firecrawl API and a friendly, step-by-step conversational approach."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "y8jiJYf4FA0m"
},
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Chile_Government_Services_Assistant.ipynb)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RRw8sPG89KNb"
},
"source": [
"# Install dependencies"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "rW8ltqCICV8o"
},
"outputs": [],
"source": [
"!pip install flask firecrawl praisonaiagents google-genai python-dotenv deep-translator"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XGjyt-B_EfbM"
},
"source": [
"# Set API Keys"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "qf8B_YltDiIe"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"os.environ['FIRECRAWL_API_KEY'] = \"your api key here\"\n",
"os.environ['OPENAI_API_KEY'] = \"your api key here\""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

It's generally not a good practice to hardcode API keys directly in the code. This can lead to security vulnerabilities if the code is accidentally exposed. Consider using a more secure method for managing API keys, such as environment variables or a dedicated secrets management system. If you are using environment variables, you should validate that they are set before proceeding, and throw an error if not.

os.environ['FIRECRAWL_API_KEY'] = os.getenv('FIRECRAWL_API_KEY', 'your api key here') # Provide a default value or raise an error if not set
os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your api key here')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve API key setup with secure input methods.

Hardcoded placeholder API keys should be replaced with secure input methods.

-"os.environ['FIRECRAWL_API_KEY'] = \"your api key here\"\n",
-"os.environ['OPENAI_API_KEY'] = \"your api key here\""
+"import getpass\n",
+"os.environ['FIRECRAWL_API_KEY'] = getpass.getpass(\"Enter your Firecrawl API key: \")\n",
+"os.environ['OPENAI_API_KEY'] = getpass.getpass(\"Enter your OpenAI API key: \")"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"os.environ['FIRECRAWL_API_KEY'] = \"your api key here\"\n",
"os.environ['OPENAI_API_KEY'] = \"your api key here\""
"import getpass\n",
"os.environ['FIRECRAWL_API_KEY'] = getpass.getpass(\"Enter your Firecrawl API key: \")\n",
"os.environ['OPENAI_API_KEY'] = getpass.getpass(\"Enter your OpenAI API key: \")"
🤖 Prompt for AI Agents
In examples/cookbooks/Chile_Government_Services_Assistant.ipynb around lines 69
to 70, replace the hardcoded placeholder API key assignments with a secure input
method such as using getpass or environment variable prompts to securely input
the API keys at runtime instead of embedding them directly in the code.

]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ccO0vwvCEqUJ"
},
"source": [
"# Import Libraries & Translator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0prDQ5TpDnFu"
},
"outputs": [],
"source": [
"from firecrawl import FirecrawlApp, ScrapeOptions\n",
"from deep_translator import GoogleTranslator\n",
"import re\n",
"\n",
"def translate_to_spanish(text):\n",
" try:\n",
" return GoogleTranslator(source='auto', target='es').translate(text)\n",
" except Exception as e:\n",
" print(\"Translation to Spanish failed:\", e)\n",
" return text\n",
"\n",
"def translate_to_english(text):\n",
" try:\n",
" # Remove Markdown images and None values before translation\n",
" text = str(text).replace(\"None\", \"\")\n",
" text = re.sub(r'!\\[.*?\\]\\(.*?\\)', '', text)\n",
" return GoogleTranslator(source='auto', target='en').translate(text)\n",
" except Exception as e:\n",
" print(\"Translation to English failed:\", e)\n",
" return text"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance translation functions with better error handling.

The translation functions need improved handling of edge cases and better error recovery.

 def translate_to_spanish(text):
+    if not text or not text.strip():
+        return text
     try:
         return GoogleTranslator(source='auto', target='es').translate(text)
     except Exception as e:
         print("Translation to Spanish failed:", e)
         return text

 def translate_to_english(text):
+    if not text or not str(text).strip():
+        return text
     try:
         # Remove Markdown images and None values before translation
         text = str(text).replace("None", "")
         text = re.sub(r'!\[.*?\]\(.*?\)', '', text)
+        if not text.strip():
+            return ""
         return GoogleTranslator(source='auto', target='en').translate(text)
     except Exception as e:
         print("Translation to English failed:", e)
         return text
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"def translate_to_spanish(text):\n",
" try:\n",
" return GoogleTranslator(source='auto', target='es').translate(text)\n",
" except Exception as e:\n",
" print(\"Translation to Spanish failed:\", e)\n",
" return text\n",
"\n",
"def translate_to_english(text):\n",
" try:\n",
" # Remove Markdown images and None values before translation\n",
" text = str(text).replace(\"None\", \"\")\n",
" text = re.sub(r'!\\[.*?\\]\\(.*?\\)', '', text)\n",
" return GoogleTranslator(source='auto', target='en').translate(text)\n",
" except Exception as e:\n",
" print(\"Translation to English failed:\", e)\n",
" return text"
def translate_to_spanish(text):
if not text or not text.strip():
return text
try:
return GoogleTranslator(source='auto', target='es').translate(text)
except Exception as e:
print("Translation to Spanish failed:", e)
return text
def translate_to_english(text):
if not text or not str(text).strip():
return text
try:
# Remove Markdown images and None values before translation
text = str(text).replace("None", "")
text = re.sub(r'!\[.*?\]\(.*?\)', '', text)
if not text.strip():
return ""
return GoogleTranslator(source='auto', target='en').translate(text)
except Exception as e:
print("Translation to English failed:", e)
return text
🤖 Prompt for AI Agents
In examples/cookbooks/Chile_Government_Services_Assistant.ipynb around lines 94
to 109, the translation functions lack robust error handling for edge cases.
Enhance these functions by adding checks for empty or null input before
attempting translation, and improve exception handling to log errors more
informatively without stopping execution. Also, ensure any preprocessing steps
like removing Markdown images handle unexpected input gracefully to avoid
runtime errors.

]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WxOlCHMmEuK2"
},
"source": [
"# Firecrawl Tool Class"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "G4RyzJ5mDp0t"
},
"outputs": [],
"source": [
"class FirecrawlTool:\n",
" def __init__(self, api_key, instruction: str, template: str):\n",
" if not api_key:\n",
" raise ValueError(\"Firecrawl API key not provided.\")\n",
" self.app = FirecrawlApp(api_key=api_key)\n",
" self.instruction = instruction\n",
" self.template = template\n",
"\n",
" def search(self, search: str) -> str:\n",
" if not search or len(search) < 5:\n",
" return \"Error: Please provide a valid search query (at least 5 characters).\"\n",
" response_md = \"\"\n",
" try:\n",
" search_result = self.app.search(\n",
" query=self.instruction + search,\n",
" limit=2,\n",
" country=\"cl\",\n",
" lang=\"es\", # Always search in Spanish for best results\n",
" scrape_options=ScrapeOptions(formats=[\"markdown\", \"links\"])\n",
" )\n",
" if search_result and hasattr(search_result, 'data') and search_result.data:\n",
" filtered_results = [\n",
" result for result in search_result.data\n",
" if str(result.get(\"url\", \"\")).startswith(\"https://www.chileatiende.gob.cl/fichas\") and not str(result.get(\"url\", \"\")).endswith(\"pdf\")\n",
" ]\n",
" if filtered_results:\n",
" for num, result in enumerate(filtered_results, start=1):\n",
" response_md += self.template.format(\n",
" result_number=num,\n",
" page_title=str(result.get(\"title\", \"\")),\n",
" page_url=str(result.get(\"url\", \"\")),\n",
" page_content=str(result.get(\"markdown\", \"\"))\n",
" )\n",
" return response_md\n",
" else:\n",
" return None\n",
" else:\n",
" return None\n",
" except Exception as e:\n",
" return f\"Error during search: {e}\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MjkjTWn_ExS0"
},
"source": [
"# Firecrawl Prompt Template"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "AfivymU8Dufz"
},
"outputs": [],
"source": [
"FIRECRAWL_INSTRUCTION = \"ChileAtiende: \"\n",
"FIRECRAWL_TEMPLATE = \"\"\"\n",
"# Result {result_number}\n",
"\n",
"## Page Name:\n",
"\"{page_title}\"\n",
"\n",
"## URL:\n",
"{page_url}\n",
"\n",
"## Content:\n",
"{page_content}\n",
"\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zK8AA_DlEz9K"
},
"source": [
"# Initialize Firecrawl Tool"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "c3NKK0ZjDwKT"
},
"outputs": [],
"source": [
"firecrawl_tool = FirecrawlTool(\n",
" api_key=os.environ['FIRECRAWL_API_KEY'],\n",
" instruction=FIRECRAWL_INSTRUCTION,\n",
" template=FIRECRAWL_TEMPLATE\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uzXYIF_gE3XV"
},
"source": [
"# Main Chat Loop"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "TXMgZQNkDx7n",
"outputId": "76303cd1-a576-483f-a22d-9857e5e6d797"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello! I am your ChileAtiende assistant, Tomás. How can I help you today?\n",
"You can ask me, for example: How to renew your ID card, How to apply for the Winter Bonus, etc.\n",
"\n",
"You: exit\n",
"Tomás: It was a pleasure to help you. Goodbye!\n"
]
}
],
"source": [
"print(\"Hello! I am your ChileAtiende assistant, Tomás. How can I help you today?\")\n",
"print(\"You can ask me, for example: How to renew your ID card, How to apply for the Winter Bonus, etc.\")\n",
"\n",
"while True:\n",
" user_input = input(\"\\nYou: \")\n",
" if user_input.lower() in [\"exit\", \"quit\"]:\n",
" print(\"Tomás: It was a pleasure to help you. Goodbye!\")\n",
" break\n",
"\n",
" # Translate English input to Spanish for Firecrawl\n",
" spanish_query = translate_to_spanish(user_input)\n",
" spanish_answer = firecrawl_tool.search(spanish_query)\n",
"\n",
" # Only translate if we got a real answer\n",
" if spanish_answer and isinstance(spanish_answer, str) and spanish_answer.strip() and \"Error\" not in spanish_answer:\n",
" try:\n",
" english_answer = translate_to_english(spanish_answer)\n",
" print(\"\\nTomás (in English):\\n\", english_answer)\n",
" except Exception as e:\n",
" print(f\"\\nTomás: I found information, but couldn't translate it. Here it is in Spanish:\\n{spanish_answer}\\n(Translation error: {e})\")\n",
" else:\n",
" print(\"\\nTomás: Sorry, I couldn't find relevant information. Try rephrasing your question or ask about another service.\")"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add comprehensive error handling to the chat loop.

The chat loop needs better error handling for translation failures and API errors.

 while True:
-    user_input = input("\nYou: ")
+    try:
+        user_input = input("\nYou: ")
+    except (KeyboardInterrupt, EOFError):
+        print("\nTomás: It was a pleasure to help you. Goodbye!")
+        break
+        
     if user_input.lower() in ["exit", "quit"]:
         print("Tomás: It was a pleasure to help you. Goodbye!")
         break
+    
+    if not user_input.strip():
+        print("\nTomás: Please ask me a question about Chilean government services.")
+        continue

-    # Translate English input to Spanish for Firecrawl
-    spanish_query = translate_to_spanish(user_input)
-    spanish_answer = firecrawl_tool.search(spanish_query)
+    try:
+        # Translate English input to Spanish for Firecrawl
+        spanish_query = translate_to_spanish(user_input)
+        spanish_answer = firecrawl_tool.search(spanish_query)
+    except Exception as e:
+        print(f"\nTomás: Sorry, I encountered an error while searching: {e}")
+        continue

     # Only translate if we got a real answer
     if spanish_answer and isinstance(spanish_answer, str) and spanish_answer.strip() and "Error" not in spanish_answer:
🤖 Prompt for AI Agents
In examples/cookbooks/Chile_Government_Services_Assistant.ipynb around lines 264
to 282, the chat loop lacks comprehensive error handling for translation
failures and API errors. Wrap the entire user input processing, including
translation and Firecrawl search calls, in a try-except block to catch and
handle any exceptions gracefully. Provide user-friendly error messages when
exceptions occur, ensuring the loop continues running without crashing.

]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Loading
Loading