Spaces:
Sleeping
Sleeping
import streamlit as st | |
from crewai import Crew, Agent, Task, Process | |
from langchain_community.tools import DuckDuckGoSearchRun | |
from langchain_groq import ChatGroq # Import ChatGroq | |
import os | |
from langchain.tools import BaseTool | |
# Configure Groq API Key (replace with your actual key) | |
GROQ_API_KEY = st.secrets["GROQ_API_KEY"] | |
# No need for genai.configure anymore | |
# Define the LLM using langchain-groq | |
groq_llm = ChatGroq( | |
model_name="groq/deepseek-r1-distill-llama-70b", temperature=0.7, groq_api_key=GROQ_API_KEY | |
) | |
# Define Tools | |
search_tool = DuckDuckGoSearchRun() | |
class ToolWrapper(BaseTool): | |
"""Wrapper for tools to make them compatible with CrewAI.""" | |
name: str | |
func: callable | |
description: str | |
def _run(self, *args, **kwargs): | |
return self.func(*args, **kwargs) | |
async def _arun(self, *args, **kwargs): | |
return await self.func(*args, **kwargs) | |
# Define Agents - Pass the Groq LLM directly | |
inventory_specialist = Agent( | |
role="Inventory Specialist", | |
goal="Identify the best matching homes from current inventory based on customer criteria.", | |
backstory="""You are an expert real estate inventory specialist. | |
You meticulously analyze customer requests and use your deep knowledge of available properties to find the perfect matches. | |
You know all the ins and outs of the local real estate market, property features, and pricing. | |
You consider factors such as location, square footage, amenities, and overall value when making your selections. | |
""", | |
verbose=True, | |
allow_delegation=False, | |
tools=[ | |
ToolWrapper( | |
name=search_tool.name, | |
func=search_tool.run, | |
description=search_tool.description, | |
) | |
], | |
llm=groq_llm, # Pass the Groq LLM directly | |
) | |
communication_specialist = Agent( | |
role="Communication Specialist", | |
goal="Draft compelling and informative responses to customer inquiries.", | |
backstory="""You are a skilled communicator specializing in real estate. | |
You craft clear, concise, and engaging messages that highlight the key features and benefits of properties. | |
You are adept at tailoring your responses to individual customer needs and preferences. | |
You use persuasive language and a friendly tone to create a positive customer experience. You are a world-class copywriter. | |
""", | |
verbose=True, | |
allow_delegation=True, | |
llm=groq_llm, # Pass the Groq LLM directly | |
) | |
# Define Tasks | |
def create_inventory_task(customer_request): | |
return Task( | |
description=f"""Analyze the customer's request: '{customer_request}'. | |
Search for available homes that meet the specified criteria (zip code, bedrooms, bathrooms). | |
Identify the top 3-5 best matching homes from the current inventory. | |
Prepare a concise summary of each matching home, including key features (e.g., square footage, lot size, special amenities) and price. | |
Do NOT make up any information. If you don't find enough information, say so, but still provide the best possible matches based on what you *can* find. | |
""", | |
agent=inventory_specialist, | |
expected_output="A list of 3-5 homes with their features and prices, or a message indicating no matches found.", | |
) | |
def create_communication_task(inventory_results): | |
return Task( | |
description=f"""Compose a professional and friendly email response to the customer based on the following inventory results: | |
{inventory_results} | |
The email should: | |
- Thank the customer for their inquiry. | |
- Clearly present the list of matching homes. | |
- Highlight the key features and benefits of *each* home in a concise and appealing way (e.g., "Spacious backyard perfect for entertaining," "Recently renovated kitchen with stainless steel appliances"). | |
- Include the price of each home. | |
- Provide a call to action, inviting the customer to schedule a viewing or ask further questions. | |
- Maintain a professional and courteous tone throughout. Be enthusiastic but not overly pushy. | |
- Include a signature with contact information (e.g., name, title, phone number, email address). Use placeholder information for the signature (like "John Doe, Real Estate Agent, (555) 123-4567, [email protected]"). | |
""", | |
agent=communication_specialist, | |
expected_output="A complete, formatted email ready to be sent to the customer.", | |
) | |
# Streamlit App | |
st.title("AI-Powered Real Estate Lead Response (Groq)") | |
customer_zipcode = st.text_input("Zip Code:", placeholder="Enter zip code") | |
customer_bedrooms = st.number_input( | |
"Number of Bedrooms:", min_value=1, max_value=10, value=3, step=1 | |
) | |
customer_bathrooms = st.number_input( | |
"Number of Bathrooms:", min_value=1, max_value=10, value=2, step=1 | |
) | |
if st.button("Submit Inquiry"): | |
if not customer_zipcode: | |
st.warning("Please enter a zip code.") | |
else: | |
customer_request = ( | |
f"Homes for sale in {customer_zipcode}, {customer_bedrooms} bedrooms, {customer_bathrooms} bathrooms." | |
) | |
st.info(f"Processing request: {customer_request}") | |
with st.spinner("Finding matching homes..."): | |
# Create tasks | |
inventory_task = create_inventory_task(customer_request) | |
communication_task = create_communication_task( | |
inventory_task.output | |
) | |
# Create Crew | |
real_estate_crew = Crew( | |
agents=[inventory_specialist, communication_specialist], | |
tasks=[inventory_task, communication_task], | |
process=Process.sequential, | |
verbose=True, | |
) | |
# Run the Crew | |
try: | |
results = real_estate_crew.kickoff() | |
st.success("Response generated!") | |
st.write("**Draft Email Response:**") | |
st.write(results) | |
st.balloons() | |
except Exception as e: | |
st.error(f"An error occurred: {e}") | |
st.write( | |
"Please check your Groq API key and ensure it has the necessary permissions." | |
) |