File size: 6,227 Bytes
c768adc
41588da
c768adc
41588da
c768adc
c8b5c08
6cf666d
41588da
 
 
c768adc
 
41588da
 
af80081
41588da
05b828a
c768adc
c8b5c08
c768adc
 
41588da
6cf666d
 
1d3b1f0
6cf666d
 
 
 
 
 
 
 
 
 
c768adc
41588da
c768adc
1d3b1f0
 
c768adc
 
 
 
 
 
 
1d3b1f0
 
 
 
 
 
c8b5c08
41588da
c768adc
 
 
1d3b1f0
 
c768adc
 
 
 
 
 
c8b5c08
41588da
c768adc
 
 
c8b5c08
c768adc
 
 
 
 
 
 
 
1d3b1f0
c8b5c08
c768adc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d3b1f0
c8b5c08
c768adc
 
1d3b1f0
c768adc
41588da
c768adc
 
1d3b1f0
 
 
 
 
 
c768adc
 
 
 
 
1d3b1f0
 
 
c768adc
 
 
 
 
1d3b1f0
 
c8b5c08
c768adc
 
 
 
 
c8b5c08
20b762b
c768adc
 
 
48ff453
 
 
 
c8b5c08
48ff453
 
 
1d3b1f0
41588da
1d3b1f0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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."
                )