Skip to content

Add Government Services Assistant Python script #687

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
Changes from 1 commit
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
141 changes: 141 additions & 0 deletions examples/python/tools/exa-tool/chile_government_services_assistant_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# # -*- coding: utf-8 -*-
# """Chile_Government_Services_Assistant .ipynb

# Automatically generated by Colab.

# Original file is located at
# https://colab.research.google.com/drive/13IOn2Vhg0EUwuIGpVilImW0rEpYYMoFQ

# # Chile Government Services Assistant - AI Chatbot

# 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.

# [![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)

# # Install dependencies
# """

# !pip install flask firecrawl praisonaiagents google-genai python-dotenv deep-translator

# """# Set API Keys"""

import os

os.environ['FIRECRAWL_API_KEY'] = "your api key here"
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.

medium

Consider using more descriptive variable names than just assigning the string "your api key here". This will improve readability and make it clear what the variables are used for. Suggest replacing with a placeholder such as YOUR_FIRECRAWL_API_KEY and YOUR_OPENAI_API_KEY.

Suggested change
os.environ['FIRECRAWL_API_KEY'] = "your api key here"
os.environ['OPENAI_API_KEY'] = "your api key here"
os.environ['FIRECRAWL_API_KEY'] = "YOUR_FIRECRAWL_API_KEY"
os.environ['OPENAI_API_KEY'] = "YOUR_OPENAI_API_KEY"

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical Security Issue: Remove hardcoded API keys

Hardcoded API keys in source code pose a serious security risk and should never be committed to version control.

-os.environ['FIRECRAWL_API_KEY'] = "your api key here"
-os.environ['OPENAI_API_KEY'] = "your api key here"
+# Load API keys from environment variables or .env file
+# os.environ['FIRECRAWL_API_KEY'] should be set externally
+# os.environ['OPENAI_API_KEY'] should be set externally
+
+if not os.environ.get('FIRECRAWL_API_KEY'):
+    raise ValueError("FIRECRAWL_API_KEY environment variable is required")
+if not os.environ.get('OPENAI_API_KEY'):
+    raise ValueError("OPENAI_API_KEY environment variable is required")
📝 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"
os.environ['OPENAI_API_KEY'] = "your api key here"
# Load API keys from environment variables or .env file
# os.environ['FIRECRAWL_API_KEY'] should be set externally
# os.environ['OPENAI_API_KEY'] should be set externally
if not os.environ.get('FIRECRAWL_API_KEY'):
raise ValueError("FIRECRAWL_API_KEY environment variable is required")
if not os.environ.get('OPENAI_API_KEY'):
raise ValueError("OPENAI_API_KEY environment variable is required")
🤖 Prompt for AI Agents
In examples/python/tools/exa-tool/chile_government_services_assistant_.py at
lines 24 to 25, the API keys are hardcoded as plain strings, which is a critical
security risk. Remove these hardcoded keys and instead load them securely from
environment variables or a secure secrets manager at runtime, ensuring no
sensitive keys are stored directly in the source code.


# """# Import Libraries & Translator"""

from firecrawl import FirecrawlApp, ScrapeOptions
from deep_translator import GoogleTranslator
import re
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

Fix import organization

Imports should be placed at the top of the file according to PEP8 standards.

Move these imports to the top of the file after the initial comments:

+from firecrawl import FirecrawlApp, ScrapeOptions
+from deep_translator import GoogleTranslator
+import re
import os

-from firecrawl import FirecrawlApp, ScrapeOptions
-from deep_translator import GoogleTranslator
-import re
📝 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
from firecrawl import FirecrawlApp, ScrapeOptions
from deep_translator import GoogleTranslator
import re
🧰 Tools
🪛 Flake8 (7.2.0)

[error] 29-29: module level import not at top of file

(E402)


[error] 30-30: module level import not at top of file

(E402)


[error] 31-31: module level import not at top of file

(E402)

🤖 Prompt for AI Agents
In examples/python/tools/exa-tool/chile_government_services_assistant_.py around
lines 29 to 31, the imports are not placed at the top of the file as required by
PEP8. Move the import statements for FirecrawlApp, ScrapeOptions,
GoogleTranslator, and re to the very top of the file, immediately after any
initial comments or module docstrings, ensuring all imports are grouped together
before any other code.


def translate_to_spanish(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):
try:
# Remove Markdown images and None values before translation
text = str(text).replace("None", "")
text = re.sub(r'!\[.*?\]\(.*?\)', '', text)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Consider using str.removeprefix to remove the None string instead of str.replace to avoid unintended replacements within the text.

text = str(text).removeprefix("None")

return GoogleTranslator(source='auto', target='en').translate(text)
except Exception as e:
print("Translation to English failed:", e)
return text

# """# Firecrawl Tool Class"""

class FirecrawlTool:
def __init__(self, api_key, instruction: str, template: str):
if not api_key:
raise ValueError("Firecrawl API key not provided.")
self.app = FirecrawlApp(api_key=api_key)
self.instruction = instruction
self.template = template

def search(self, search: str) -> str:
if not search or len(search) < 5:
return "Error: Please provide a valid search query (at least 5 characters)."
response_md = ""
try:
search_result = self.app.search(
query=self.instruction + search,
limit=2,
country="cl",
lang="es", # Always search in Spanish for best results
scrape_options=ScrapeOptions(formats=["markdown", "links"])
)
if search_result and hasattr(search_result, 'data') and search_result.data:
filtered_results = [
result for result in search_result.data
if str(result.get("url", "")).startswith("https://www.chileatiende.gob.cl/fichas") and not str(result.get("url", "")).endswith("pdf")
]
if filtered_results:
for num, result in enumerate(filtered_results, start=1):
response_md += self.template.format(
result_number=num,
page_title=str(result.get("title", "")),
page_url=str(result.get("url", "")),
page_content=str(result.get("markdown", ""))
)
return response_md
else:
return None
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

Remove unnecessary else clause

The else clause after return is unnecessary and reduces readability.

                if filtered_results:
                    for num, result in enumerate(filtered_results, start=1):
                        response_md += self.template.format(
                            result_number=num,
                            page_title=str(result.get("title", "")),
                            page_url=str(result.get("url", "")),
                            page_content=str(result.get("markdown", ""))
                        )
                    return response_md
-                else:
-                    return None
+                return None
📝 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
if filtered_results:
for num, result in enumerate(filtered_results, start=1):
response_md += self.template.format(
result_number=num,
page_title=str(result.get("title", "")),
page_url=str(result.get("url", "")),
page_content=str(result.get("markdown", ""))
)
return response_md
else:
return None
if filtered_results:
for num, result in enumerate(filtered_results, start=1):
response_md += self.template.format(
result_number=num,
page_title=str(result.get("title", "")),
page_url=str(result.get("url", "")),
page_content=str(result.get("markdown", ""))
)
return response_md
return None
🧰 Tools
🪛 Pylint (3.3.7)

[refactor] 77-87: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it

(R1705)

🤖 Prompt for AI Agents
In examples/python/tools/exa-tool/chile_government_services_assistant_.py around
lines 77 to 87, remove the else clause following the return statement since it
is unnecessary. Instead, after the if block that returns response_md, simply
return None directly without wrapping it in an else block to improve
readability.

else:
return None
except Exception as e:
return f"Error during search: {e}"

# """# Firecrawl Prompt Template"""

# FIRECRAWL_INSTRUCTION = "ChileAtiende: "
# FIRECRAWL_TEMPLATE = """
# # Result {result_number}

# ## Page Name:
# "{page_title}"

# ## URL:
# {page_url}

# ## Content:
# {page_content}

# """
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical Runtime Error: Uncomment template definitions

The template variables are commented out but referenced in the initialization code, causing a runtime error.

-# FIRECRAWL_INSTRUCTION = "ChileAtiende: "
-# FIRECRAWL_TEMPLATE = """
-# # Result {result_number}
-
-# ## Page Name:
-# "{page_title}"
-
-# ## URL:
-# {page_url}
-
-# ## Content:
-# {page_content}
-
-# """
+FIRECRAWL_INSTRUCTION = "ChileAtiende: "
+FIRECRAWL_TEMPLATE = """
+# Result {result_number}
+
+## Page Name:
+"{page_title}"
+
+## URL:
+{page_url}
+
+## Content:
+{page_content}
+
+"""
📝 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
# FIRECRAWL_INSTRUCTION = "ChileAtiende: "
# FIRECRAWL_TEMPLATE = """
# # Result {result_number}
# ## Page Name:
# "{page_title}"
# ## URL:
# {page_url}
# ## Content:
# {page_content}
# """
FIRECRAWL_INSTRUCTION = "ChileAtiende: "
FIRECRAWL_TEMPLATE = """
# Result {result_number}
## Page Name:
"{page_title}"
## URL:
{page_url}
## Content:
{page_content}
"""
🤖 Prompt for AI Agents
In examples/python/tools/exa-tool/chile_government_services_assistant_.py
between lines 95 and 108, the template variables FIRECRAWL_INSTRUCTION and
FIRECRAWL_TEMPLATE are commented out but still referenced later, causing a
runtime error. To fix this, uncomment these variable definitions so they are
properly initialized and available for use in the code.


# """# Initialize Firecrawl Tool"""

firecrawl_tool = FirecrawlTool(
api_key=os.environ['FIRECRAWL_API_KEY'],
instruction=FIRECRAWL_INSTRUCTION,
template=FIRECRAWL_TEMPLATE
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Consider defining FIRECRAWL_INSTRUCTION and FIRECRAWL_TEMPLATE as constants at the beginning of the script, outside of any code blocks, to improve readability and maintainability. This also makes it easier to configure these values without digging into the code.

    template=FIRECRAWL_TEMPLATE
)

)

# """# Main Chat Loop"""

print("Hello! I am your ChileAtiende assistant, Tomás. How can I help you today?")
print("You can ask me, for example: How to renew your ID card, How to apply for the Winter Bonus, etc.")

while True:
user_input = input("\nYou: ")
if user_input.lower() in ["exit", "quit"]:
print("Tomás: It was a pleasure to help you. Goodbye!")
break

# Translate English input to Spanish for Firecrawl
spanish_query = translate_to_spanish(user_input)
spanish_answer = firecrawl_tool.search(spanish_query)

# 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:
try:
english_answer = translate_to_english(spanish_answer)
print("\nTomás (in English):\n", english_answer)
except Exception as e:
print(f"\nTomás: I found information, but couldn't translate it. Here it is in Spanish:\n{spanish_answer}\n(Translation error: {e})")
else:
print("\nTomás: Sorry, I couldn't find relevant information. Try rephrasing your question or ask about another service.")
Loading