from pydantic import BaseModel, Field
import os 
from langchain import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, Tool
# from langchain.chains import PALChain
from langchain.chains.conversation.memory import ConversationBufferMemory
from langchain import PromptTemplate, LLMChain
# import streamlit as st
from dateutil import parser
# from datetime import datetime
import datetime
import calendar
import random
import json
# from faker import Faker
# from datetime import datetime, timedelta
# from langchain.agents.agent_toolkits import create_python_agent
from langchain.agents import load_tools, initialize_agent
from langchain.agents import AgentType
# from langchain.tools.python.tool import PythonREPLTool
from langchain.python import PythonREPL
from langchain.chat_models import ChatOpenAI
from langchain.agents import tool
from langchain import PromptTemplate
from langchain_experimental.tools import PythonAstREPLTool
import os
import streamlit as st
from airtable import Airtable
from langchain.chains.router import MultiRetrievalQAChain
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
from langchain.vectorstores import DocArrayInMemorySearch
from langchain.indexes import VectorstoreIndexCreator
from streamlit_chat import message
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
from langchain.document_loaders.csv_loader import CSVLoader
from langchain.vectorstores import FAISS
from langchain.llms import OpenAI
from langchain import PromptTemplate
from langchain.memory import ConversationBufferMemory
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from pytz import timezone
# import datetime
from langchain.agents.agent_toolkits import create_retriever_tool
from langchain.agents.agent_toolkits import create_conversational_retrieval_agent
from langchain.chat_models import ChatOpenAI
import langchain
from langchain.agents.openai_functions_agent.agent_token_buffer_memory import AgentTokenBufferMemory
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
from langchain.schema.messages import SystemMessage
from langchain.prompts import MessagesPlaceholder
from langchain.agents import AgentExecutor
from langchain.smith import RunEvalConfig, run_on_dataset
import pandas as pd
import requests
from pydantic import BaseModel, Field
from langchain.tools import tool
# from datetime import datetime
from typing import Dict, Any
hide_share_button_style = """
    <style>
    .st-emotion-cache-zq5wmm.ezrtsby0 .stActionButton:nth-child(1) {
        display: none !important;
    }
    </style>
"""

hide_star_and_github_style = """
    <style>
    .st-emotion-cache-1lb4qcp.e3g6aar0,
    .st-emotion-cache-30do4w.e3g6aar0 {
        display: none !important;
    }
    </style>
"""

hide_mainmenu_style = """
    <style>
    #MainMenu {
        display: none !important;
    }
    </style>
"""

hide_fork_app_button_style = """
    <style>
    .st-emotion-cache-alurl0.e3g6aar0 {
        display: none !important;
    }
    </style>
"""

st.markdown(hide_share_button_style, unsafe_allow_html=True)
st.markdown(hide_star_and_github_style, unsafe_allow_html=True)
st.markdown(hide_mainmenu_style, unsafe_allow_html=True)
st.markdown(hide_fork_app_button_style, unsafe_allow_html=True)
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 100)

os.environ['OPENAI_API_KEY'] = st.secrets['OPENAI_API_KEY']
st.image("Twitter.jpg")

datetime.datetime.now()
current_date = datetime.date.today().strftime("%m/%d/%y")
day_of_week = datetime.date.today().weekday()
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
current_day = days[day_of_week]
todays_date = current_date
day_of_the_week = current_day

business_details_text = [
    "working days: all Days except sunday",
    "working hours: 9 am to 7 pm", 
    "Phone: (555) 123-4567",
    "Address: 567 Oak Avenue, Anytown, CA 98765, Email: jessica.smith@example.com",
    "dealer ship location: https://maps.app.goo.gl/ecHtb6y5f8q5PUxb9"
]
retriever_3 = FAISS.from_texts(business_details_text, OpenAIEmbeddings()).as_retriever()

file_1 = r'inventory.csv'

loader = CSVLoader(file_path=file_1)
docs_1 = loader.load()
embeddings = OpenAIEmbeddings()
vectorstore_1 = FAISS.from_documents(docs_1, embeddings)
retriever_1 = vectorstore_1.as_retriever(search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5,"k": 8})

file_2 = r'short_car_details.csv'
loader_2 = CSVLoader(file_path=file_2)
docs_2 = loader_2.load()
num_ret=len(docs_2)
vectordb_2 = FAISS.from_documents(docs_2, embeddings)
retriever_2 = vectordb_2.as_retriever(search_type="similarity", search_kwargs={"k": num_ret})


tool1 = create_retriever_tool(
    retriever_1, 
     "details_of_car",
     "use to get car full details and more information. Input to this should be the car's model\
     or car features and new or used car as a single argument for example new toeing car or new jeep cherokee"
) 

tool2 = create_retriever_tool(
    retriever_2, 
     "Availability_check",
     "use to check availabilty of car, Input is car make or model or both"
)
tool3 = create_retriever_tool(
    retriever_3, 
     "business_details",
     "Searches and returns documents related to business working days and hours, location and address details."
)

# class CarDetails(BaseModel):
#     make: str
#     model: str
#     year: int

# class VINDetails(BaseModel):
#     vin: str = Field(..., description="VIN of the car to get the car details")

# @tool(args_schema=VINDetails)
# def get_car_details_from_vin(vin):
#     """Fetch car details for the given VIN."""
    
#     BASE_URL = f"https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValues/{vin}?format=json"
    
#     # Make the request
#     response = requests.get(BASE_URL)
    
#     # Check if the request was successful
#     if response.status_code == 200:
#         # Parse the JSON response
#         result = response.json()
        
#         # Check if 'Results' key is present and has at least one item
#         if 'Results' in result and result['Results']:
#             # Extract the first item from 'Results' list
#             first_result = result['Results'][0]
            
#             make = first_result.get('Make', '')
#             model = first_result.get('Model', '')
            
#             try:
#                 year = int(first_result.get('ModelYear', ''))
#             except ValueError:
#                 year = 0  # Handle the case where the year is not a valid integer
        
#             # Create CarDetails instance
#             car_details = CarDetails(make=make, model=model, year=year)
            
#             # Print the details for debugging
#             print("Car Details:")
#             print(f"Make: {car_details.make}, Model: {car_details.model}, Year: {car_details.year}")
#         else:
#             # Handle the case when 'Results' key is not present or is empty
#             car_details = CarDetails(make="", model="", year=0)
#             print("No results found for the given VIN.")
        
#         return car_details
#     else:
#         # Handle the case when the request was not successful
#         car_details = CarDetails(make="", model="", year=0)
#         print(f"Failed to retrieve car details. Status code: {response.status_code}")
        
#         return car_details


class CarDetails(BaseModel):
    make: str
    model: str
    year: int

class VINDetails(BaseModel):
    vin: str = Field(..., description="VIN of the car to get the car details")

@tool
def get_car_details_from_vin(vin):
    """Fetch car details for the given VIN."""
    
    BASE_URL = f"https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValues/{vin}?format=json"
#     BASE_URL = "https://fe9b-2405-201-200a-100d-b840-86ed-9ebd-a606.ngrok-free.app/appointment/"
    # Make the request
    response = requests.get(BASE_URL)
#     print(response)
    # Check if the request was successful
    if response.status_code == 200:
        # Parse the JSON response
        result = response.json()
        print(result)
        
        # Check if 'Results' key is present and has at least one item
        if 'Results' in result and result['Results']:
            # Extract the first item from 'Results' list
            first_result = result['Results'][0]
#             print("These are first_result")
#             print(first_result)
            
            make = first_result.get('Make', '')
            model = first_result.get('Model', '')
            
            try:
                year = int(first_result.get('ModelYear', ''))
            except ValueError:
                year = 0  # Handle the case where the year is not a valid integer
        
            # Create CarDetails instance
            car_details = CarDetails(make=make, model=model, year=year)
        else:
            # Handle the case when 'Results' key is not present or is empty
            car_details = CarDetails(make="", model="", year=0)
        
        return car_details
    else:
        # Handle the case when the request was not successful
        return CarDetails(make="", model="", year=0)

class AppointmentDetails(BaseModel):
    time: str
    availability: str

class AppointmentInput(BaseModel):
    date: str = Field(..., description="Date for which to get appointment details")

@tool
def get_appointment_details(date):
    """Fetch appointment details for the given date and input to this function should be only "mm-dd-yyyy," format\
    such as "04-12-2024" not "date":"mm-dd-yyyy" format."""
    

    BASE_URL="https://4730-2405-201-200a-100d-ac7d-3859-60f0-4d3f.ngrok-free.app/test/appointment"
    # Make the request
    payload = {
        "requested_appointment_date": date
    }
    response = requests.post(BASE_URL, json=payload)
#     print("the response is")
#     print(response.text)
    
    # Check if the request was successful
    if response.status_code == 200:
        # Parse the JSON response
        result = response.json()
#         print(result)
        
        # Check if the date is present in the response
        if date in result and result[date] is not None:
            # Extract the appointment details for the given date
            appointments = result[date]

            
            return appointments  # Return the value
        else:
            # Handle the case when the date is not present in the response or is None
            appointments ={
        date: "Not_available"
    }
            return appointments
    else:
        # Handle the case when the request was not successful
        return []



class CustomerDataStore(BaseModel):
    name: str = Field(..., description="name of the customer")
    phone: str = Field(..., description="phone number of the customer")
    email: str = Field(..., description="email of the customer")
    make: str = Field(..., description="year of the car")
    model: str = Field(..., description="model of the car")
    year:int=Field(..., description="year of the vehicle")
    company_id:int=Field(..., description="id of the company")
    location_id:int=Field(..., description="location id of the company")
    start_date:str=Field(..., description="date of appointment")
    appointment_timezone:str=Field(..., description="time zone")
    intent:str=Field(..., description="costumer intent")
    summary:str=Field(..., description="one line about summary of appointment,")
    description:str=Field(..., description="one line about description about visit,")
# Uncomment if you want to use the decorator
@tool
def store_appointment_data(name: str,phone: str,email: str ,make: str,model: str,year:int,
                           company_id:int,location_id:int,start_date:str,appointment_timezone:str,
                           intent:str,summary:str,description:str) -> dict:
# def store_appointment_data(data: CustomerDataStore) -> dict:

    """Store appointment data using an API."""
#     print(data)
    
    # Your API endpoint for storing appointment data
#     api_url = "https://889d-2402-a00-172-22e6-71e5-ba36-c2e7-3c81.ngrok-free.app/test/appointment/create"
    api_url="https://4730-2405-201-200a-100d-ac7d-3859-60f0-4d3f.ngrok-free.app/test/appointment/create"

    data_dict = {
    "company_id": 1,
    "location_id": 28,
    "lead": {
        "name": name,
        "phone": phone,
        "email": email
    },
    "vehicle": {
        "year": 2023,
        "make": make,
        "model": model,
        "intent": intent
    },
    "appointment": {
        "start_date": start_date,
        "description": description,
        "summary":summary,
        "appointment_timezone": appointment_timezone
    }
}

    # Make the request
    response = requests.post(api_url, json=data_dict)
   
    # Check the response status code
    if response.status_code == 200:
        print("Data stored successfully!")
    else:
        print(f"Failed to store data. Status code: {response.status_code}")
        print(response.text)  # Print the response content for debugging


airtable_api_key = st.secrets["AIRTABLE"]["AIRTABLE_API_KEY"]
os.environ["AIRTABLE_API_KEY"] = airtable_api_key
AIRTABLE_BASE_ID = "appN324U6FsVFVmx2"  
AIRTABLE_TABLE_NAME = "new_apis"


st.info("Introducing **Otto**, your cutting-edge partner in streamlining dealership and customer-related operations. At EngagedAi, we specialize in harnessing the power of automation to revolutionize the way dealerships and customers interact. Our advanced solutions seamlessly handle tasks, from managing inventory and customer inquiries to optimizing sales processes, all while enhancing customer satisfaction. Discover a new era of efficiency and convenience with us as your trusted automation ally. [engagedai.io](https://funnelai.com/). For this demo application, we will use the Inventory Dataset. Please explore it [here](https://github.com/buravelliprasad/turbo_6_tools/blob/main/car_desription_new.csv) to get a sense for what questions you can ask.")

if 'chat_history' not in st.session_state:
    st.session_state.chat_history = []
if 'generated' not in st.session_state:
    st.session_state.generated = []
if 'past' not in st.session_state:
    st.session_state.past = []

if 'user_name' not in st.session_state:
    st.session_state.user_name = None

llm = ChatOpenAI(model="gpt-4-1106-preview", temperature = 0)

langchain.debug=True

memory_key="chat_history"
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)


template = """You are an costumer care support exectutive baesd on your performance you will get bonus and incentives 
so follow instructions strictly and respond in Personable, Persuvasive, creative, engaging and professional.
The name of the costumer is {name} and the dealership name is {dealership_name} and 
do not start with appointment related questions.
To ensure a consistent and effective response, please adhere to the following guidelines:

Use "car_vailability_check" strictly for checking availability of a specific make or model of the car and 
also for getting full list of available makes and models in the inventory.

Use "details_of_car" tool that extracts comprehensive information about specific cars in the inventory.
This includes details like trim, price, color, and cost.

Use "car_vailability_check" for checking car availability and "details_of_car" for car information.

To optimize the search process, ensure the system is aware of the car model and whether the customer
is interested in new or used cars.

In cases where specific details are not included in the initial inquiry, initiate a proactive approach 
by requesting the missing information. 

To streamline the process, ask only one question at a time until all necessary details are obtained.
This ensures a more efficient and accurate retrieval of car information.

If customer inquires about car with features like towing, off-road capability,
good mileage, or pickup trucks in this case no need to ask about make and model of the car 
inquire whether they are interested in a new or used vehicle.

After knowing car feature and new or old car preference use the "details_of_car" tool to answer.

Do not disclose or ask the costumer if he likes to know the selling price of a car,
disclose selling price only when the customer explicitly requests it use "details_of_car" function.


If the customer's query matches a car model, respond with a list of car without square brackets, 
including the make, year, model, and trim, and **strictly** provide their respective links in the answer.

When using the 'details_of_car' tool to provide car information, adhere to these guidelines 
to ensure concise and non-redundant responses:

1. Prioritize Uniqueness:

Consider cars as unique entities when they differ in any of the following core features:
Model
Make
Year
Trim
Exterior color
Interior color
New/used status
Cars sharing identical values for all of these features are considered similar.

2. Avoid Similar Car Duplication:

Display only one instance of a car if other cars with identical core features are present within the dataset.
This ensures concise responses that highlight distinct vehicles without redundancy.
Example:
If two cars have the same make, model, year, trim, exterior color, interior color, and new/used status, 
display only one of them in the response.





checking Appointments Avaliability: 
{details} use these details and find appointment date from the users input and check for appointment availabity 
using "get_appointment_details" tool for that specific day or date and time. 
strictly input to "get_appointment_details" tool should be "mm-dd-yyyy" format.
If the requested date and time for the appointment are unavailable,
suggest alternative times close to the customer's preference.

Additionally, provide this link'[click here](https://app.engagedai.io/engagements/appointment)'it will 
take them to a URL where they can schedule or reschedule their appointment themselves. 
Appointment Scheduling:

After scheduling an appointment, initiate the conversation to get tradein car and personal details.
**Car Trade-In Inquiry and personal details:**

1. Ask the customer if they have a car for trade-in.

    - User: [Response]

2. If the user responds with "Yes" to trade-in, ask for the VIN (Vehicle Identification Number).

    - User: [Response]
    if the costumer provides the VIN use "get_car_details_from_vin" get the details of the car and 
    cross check with the costumer. 

3. If the user responds with "No" to the VIN, ask for the make, model, and year of the car.

    - User: [Response]

**Price Expectation:**

4. Once you have the trade-in car details, ask the customer about their expected price for the trade-in.

    - User: [Response]

**Personal Information:**

5. Finally, ask for the customer's personal details if you already know the name dont ask again.
    - Contact Number:
    - Email Address:

Encourage Dealership Visit: Our goal is to encourage customers to visit the dealership for test drives or
receive product briefings from our team. After providing essential information on the car's make, model,
color, and basic features, kindly invite the customer to schedule an appointment for a test drive or visit us
for a comprehensive product overview by our experts.
Business details: Enquiry regarding google maps location of the store, address of the store, working days and working hours 
and contact details use search_business_details tool to get information.
company details:
compant id is 24, location id is 07 and timezone is America/New_York

Strictly Keep responses concise, not exceeding two sentences or 100 words and answers should be interactive.
Respond in a polite US english.
strictly answer only from the provided content dont makeup answers.
**Storing data:**    
As a support executive you should collect important information about costumer for future reference.
If the appointment schedule is fixed and you got costumer details name,Contact Number,Email Address.
now its time to store data.
Use this tool "store_appointment_data" to store the data.
If any of the above details missing you can enquire about that"""



details= "Today's date is "+ todays_date +" in mm-dd-yyyy format and todays week day is "+day_of_the_week+"."
name = st.session_state.user_name
dealership_name="Gosch Auto Group"
input_template = template.format(details=details,name=name,dealership_name=dealership_name)
system_message = SystemMessage(content=input_template)

prompt = OpenAIFunctionsAgent.create_prompt(
    system_message=system_message,
    extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)]
)
tools = [tool1,tool2,tool3,get_appointment_details,store_appointment_data]
agent = OpenAIFunctionsAgent(llm=llm, tools=tools, prompt=prompt)
if 'agent_executor' not in st.session_state:
    agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True, return_source_documents=True,
        return_generated_question=True)
    st.session_state.agent_executor = agent_executor
else:
    agent_executor = st.session_state.agent_executor
    
chat_history=[]
response_container = st.container()
container = st.container()
airtable = Airtable(AIRTABLE_BASE_ID, AIRTABLE_TABLE_NAME, api_key=airtable_api_key)


if 'chat_history' not in st.session_state:
    st.session_state.chat_history = []

if 'user_name' not in st.session_state:
    st.session_state.user_name = None


def save_chat_to_airtable(user_name, user_input, output):
    try:
        timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
        airtable.insert(
            {
                "username": user_name,
                "question": user_input,
                "answer": output,
                "timestamp": timestamp,
            }
        )
    except Exception as e:
        st.error(f"An error occurred while saving data to Airtable: {e}")


def conversational_chat(user_input, user_name):
    input_with_username = f"{user_name}: {user_input}"
    result = agent_executor({"input": input_with_username})
    output = result["output"]
    st.session_state.chat_history.append((user_input, output))
    
    return output
output = ""
with container:
    if st.session_state.user_name is None:
        user_name = st.text_input("Your name:")
        if user_name:
            st.session_state.user_name = user_name

    with st.form(key='my_form', clear_on_submit=True):
        user_input = st.text_input("Query:", placeholder="Type your question here (:")
        submit_button = st.form_submit_button(label='Send')

    if submit_button and user_input:
        output = conversational_chat(user_input, st.session_state.user_name)
    with response_container:
        for i, (query, answer) in enumerate(st.session_state.chat_history):
            message(query, is_user=True, key=f"{i}_user", avatar_style="thumbs")
            col1, col2 = st.columns([0.7, 10]) 
            with col1:
                st.image("icon-1024.png", width=50)
            with col2:
                st.markdown(
                f'<div style="background-color: black; color: white; border-radius: 10px; padding: 10px; width: 60%;'
                f' border-top-right-radius: 10px; border-bottom-right-radius: 10px;'
                f' border-top-left-radius: 0; border-bottom-left-radius: 0; box-shadow: 2px 2px 5px #888888;">'
                f'<span style="font-family: Arial, sans-serif; font-size: 16px; white-space: pre-wrap;">{answer}</span>'
                f'</div>',
                unsafe_allow_html=True
            )

        if st.session_state.user_name:
            try:
                save_chat_to_airtable(st.session_state.user_name, user_input, output)
            except Exception as e:
                st.error(f"An error occurred: {e}")

langchain.agents.AgentExecutor langchain.memory.ConversationBufferMemory langchain.prompts.MessagesPlaceholder langchain.chat_models.ChatOpenAI langchain.vectorstores.FAISS.from_documents langchain.agents.agent_toolkits.create_retriever_tool langchain.schema.messages.SystemMessage langchain.agents.openai_functions_agent.base.OpenAIFunctionsAgent langchain.document_loaders.csv_loader.CSVLoader langchain.embeddings.OpenAIEmbeddings
[((3412, 3472), 'streamlit.markdown', 'st.markdown', (['hide_share_button_style'], {'unsafe_allow_html': '(True)'}), '(hide_share_button_style, unsafe_allow_html=True)\n', (3423, 3472), True, 'import streamlit as st\n'), ((3474, 3537), 'streamlit.markdown', 'st.markdown', (['hide_star_and_github_style'], {'unsafe_allow_html': '(True)'}), '(hide_star_and_github_style, unsafe_allow_html=True)\n', (3485, 3537), True, 'import streamlit as st\n'), ((3539, 3595), 'streamlit.markdown', 'st.markdown', (['hide_mainmenu_style'], {'unsafe_allow_html': '(True)'}), '(hide_mainmenu_style, unsafe_allow_html=True)\n', (3550, 3595), True, 'import streamlit as st\n'), ((3597, 3660), 'streamlit.markdown', 'st.markdown', (['hide_fork_app_button_style'], {'unsafe_allow_html': '(True)'}), '(hide_fork_app_button_style, unsafe_allow_html=True)\n', (3608, 3660), True, 'import streamlit as st\n'), ((3662, 3700), 'pandas.set_option', 'pd.set_option', (['"""display.max_rows"""', '(100)'], {}), "('display.max_rows', 100)\n", (3675, 3700), True, 'import pandas as pd\n'), ((3702, 3743), 'pandas.set_option', 'pd.set_option', (['"""display.max_columns"""', '(100)'], {}), "('display.max_columns', 100)\n", (3715, 3743), True, 'import pandas as pd\n'), ((3808, 3831), 'streamlit.image', 'st.image', (['"""Twitter.jpg"""'], {}), "('Twitter.jpg')\n", (3816, 3831), True, 'import streamlit as st\n'), ((3835, 3858), 'datetime.datetime.now', 'datetime.datetime.now', ([], {}), '()\n', (3856, 3858), False, 'import datetime\n'), ((4575, 4602), 'langchain.document_loaders.csv_loader.CSVLoader', 'CSVLoader', ([], {'file_path': 'file_1'}), '(file_path=file_1)\n', (4584, 4602), False, 'from langchain.document_loaders.csv_loader import CSVLoader\n'), ((4641, 4659), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {}), '()\n', (4657, 4659), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((4677, 4717), 'langchain.vectorstores.FAISS.from_documents', 'FAISS.from_documents', (['docs_1', 'embeddings'], {}), '(docs_1, embeddings)\n', (4697, 4717), False, 'from langchain.vectorstores import FAISS\n'), ((4898, 4925), 'langchain.document_loaders.csv_loader.CSVLoader', 'CSVLoader', ([], {'file_path': 'file_2'}), '(file_path=file_2)\n', (4907, 4925), False, 'from langchain.document_loaders.csv_loader import CSVLoader\n'), ((4987, 5027), 'langchain.vectorstores.FAISS.from_documents', 'FAISS.from_documents', (['docs_2', 'embeddings'], {}), '(docs_2, embeddings)\n', (5007, 5027), False, 'from langchain.vectorstores import FAISS\n'), ((5136, 5399), 'langchain.agents.agent_toolkits.create_retriever_tool', 'create_retriever_tool', (['retriever_1', '"""details_of_car"""', '"""use to get car full details and more information. Input to this should be the car\'s model     or car features and new or used car as a single argument for example new toeing car or new jeep cherokee"""'], {}), '(retriever_1, \'details_of_car\',\n    "use to get car full details and more information. Input to this should be the car\'s model     or car features and new or used car as a single argument for example new toeing car or new jeep cherokee"\n    )\n', (5157, 5399), False, 'from langchain.agents.agent_toolkits import create_retriever_tool\n'), ((5427, 5558), 'langchain.agents.agent_toolkits.create_retriever_tool', 'create_retriever_tool', (['retriever_2', '"""Availability_check"""', '"""use to check availabilty of car, Input is car make or model or both"""'], {}), "(retriever_2, 'Availability_check',\n    'use to check availabilty of car, Input is car make or model or both')\n", (5448, 5558), False, 'from langchain.agents.agent_toolkits import create_retriever_tool\n'), ((5585, 5756), 'langchain.agents.agent_toolkits.create_retriever_tool', 'create_retriever_tool', (['retriever_3', '"""business_details"""', '"""Searches and returns documents related to business working days and hours, location and address details."""'], {}), "(retriever_3, 'business_details',\n    'Searches and returns documents related to business working days and hours, location and address details.'\n    )\n", (5606, 5756), False, 'from langchain.agents.agent_toolkits import create_retriever_tool\n'), ((13925, 14695), 'streamlit.info', 'st.info', (['"""Introducing **Otto**, your cutting-edge partner in streamlining dealership and customer-related operations. At EngagedAi, we specialize in harnessing the power of automation to revolutionize the way dealerships and customers interact. Our advanced solutions seamlessly handle tasks, from managing inventory and customer inquiries to optimizing sales processes, all while enhancing customer satisfaction. Discover a new era of efficiency and convenience with us as your trusted automation ally. [engagedai.io](https://funnelai.com/). For this demo application, we will use the Inventory Dataset. Please explore it [here](https://github.com/buravelliprasad/turbo_6_tools/blob/main/car_desription_new.csv) to get a sense for what questions you can ask."""'], {}), "(\n    'Introducing **Otto**, your cutting-edge partner in streamlining dealership and customer-related operations. At EngagedAi, we specialize in harnessing the power of automation to revolutionize the way dealerships and customers interact. Our advanced solutions seamlessly handle tasks, from managing inventory and customer inquiries to optimizing sales processes, all while enhancing customer satisfaction. Discover a new era of efficiency and convenience with us as your trusted automation ally. [engagedai.io](https://funnelai.com/). For this demo application, we will use the Inventory Dataset. Please explore it [here](https://github.com/buravelliprasad/turbo_6_tools/blob/main/car_desription_new.csv) to get a sense for what questions you can ask.'\n    )\n", (13932, 14695), True, 'import streamlit as st\n'), ((15009, 15062), 'langchain.chat_models.ChatOpenAI', 'ChatOpenAI', ([], {'model': '"""gpt-4-1106-preview"""', 'temperature': '(0)'}), "(model='gpt-4-1106-preview', temperature=0)\n", (15019, 15062), False, 'from langchain.chat_models import ChatOpenAI\n'), ((15128, 15201), 'langchain.memory.ConversationBufferMemory', 'ConversationBufferMemory', ([], {'memory_key': '"""chat_history"""', 'return_messages': '(True)'}), "(memory_key='chat_history', return_messages=True)\n", (15152, 15201), False, 'from langchain.memory import ConversationBufferMemory\n'), ((21323, 21360), 'langchain.schema.messages.SystemMessage', 'SystemMessage', ([], {'content': 'input_template'}), '(content=input_template)\n', (21336, 21360), False, 'from langchain.schema.messages import SystemMessage\n'), ((21608, 21665), 'langchain.agents.openai_functions_agent.base.OpenAIFunctionsAgent', 'OpenAIFunctionsAgent', ([], {'llm': 'llm', 'tools': 'tools', 'prompt': 'prompt'}), '(llm=llm, tools=tools, prompt=prompt)\n', (21628, 21665), False, 'from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent\n'), ((22034, 22048), 'streamlit.container', 'st.container', ([], {}), '()\n', (22046, 22048), True, 'import streamlit as st\n'), ((22062, 22076), 'streamlit.container', 'st.container', ([], {}), '()\n', (22074, 22076), True, 'import streamlit as st\n'), ((22089, 22162), 'airtable.Airtable', 'Airtable', (['AIRTABLE_BASE_ID', 'AIRTABLE_TABLE_NAME'], {'api_key': 'airtable_api_key'}), '(AIRTABLE_BASE_ID, AIRTABLE_TABLE_NAME, api_key=airtable_api_key)\n', (22097, 22162), False, 'from airtable import Airtable\n'), ((8012, 8075), 'pydantic.Field', 'Field', (['...'], {'description': '"""VIN of the car to get the car details"""'}), "(..., description='VIN of the car to get the car details')\n", (8017, 8075), False, 'from pydantic import BaseModel, Field\n'), ((8408, 8430), 'requests.get', 'requests.get', (['BASE_URL'], {}), '(BASE_URL)\n', (8420, 8430), False, 'import requests\n'), ((9856, 9923), 'pydantic.Field', 'Field', (['...'], {'description': '"""Date for which to get appointment details"""'}), "(..., description='Date for which to get appointment details')\n", (9861, 9923), False, 'from pydantic import BaseModel, Field\n'), ((10363, 10400), 'requests.post', 'requests.post', (['BASE_URL'], {'json': 'payload'}), '(BASE_URL, json=payload)\n', (10376, 10400), False, 'import requests\n'), ((11295, 11341), 'pydantic.Field', 'Field', (['...'], {'description': '"""name of the customer"""'}), "(..., description='name of the customer')\n", (11300, 11341), False, 'from pydantic import BaseModel, Field\n'), ((11360, 11414), 'pydantic.Field', 'Field', (['...'], {'description': '"""phone number of the customer"""'}), "(..., description='phone number of the customer')\n", (11365, 11414), False, 'from pydantic import BaseModel, Field\n'), ((11433, 11480), 'pydantic.Field', 'Field', (['...'], {'description': '"""email of the customer"""'}), "(..., description='email of the customer')\n", (11438, 11480), False, 'from pydantic import BaseModel, Field\n'), ((11498, 11539), 'pydantic.Field', 'Field', (['...'], {'description': '"""year of the car"""'}), "(..., description='year of the car')\n", (11503, 11539), False, 'from pydantic import BaseModel, Field\n'), ((11558, 11600), 'pydantic.Field', 'Field', (['...'], {'description': '"""model of the car"""'}), "(..., description='model of the car')\n", (11563, 11600), False, 'from pydantic import BaseModel, Field\n'), ((11615, 11660), 'pydantic.Field', 'Field', (['...'], {'description': '"""year of the vehicle"""'}), "(..., description='year of the vehicle')\n", (11620, 11660), False, 'from pydantic import BaseModel, Field\n'), ((11681, 11724), 'pydantic.Field', 'Field', (['...'], {'description': '"""id of the company"""'}), "(..., description='id of the company')\n", (11686, 11724), False, 'from pydantic import BaseModel, Field\n'), ((11746, 11798), 'pydantic.Field', 'Field', (['...'], {'description': '"""location id of the company"""'}), "(..., description='location id of the company')\n", (11751, 11798), False, 'from pydantic import BaseModel, Field\n'), ((11819, 11864), 'pydantic.Field', 'Field', (['...'], {'description': '"""date of appointment"""'}), "(..., description='date of appointment')\n", (11824, 11864), False, 'from pydantic import BaseModel, Field\n'), ((11895, 11930), 'pydantic.Field', 'Field', (['...'], {'description': '"""time zone"""'}), "(..., description='time zone')\n", (11900, 11930), False, 'from pydantic import BaseModel, Field\n'), ((11947, 11988), 'pydantic.Field', 'Field', (['...'], {'description': '"""costumer intent"""'}), "(..., description='costumer intent')\n", (11952, 11988), False, 'from pydantic import BaseModel, Field\n'), ((12006, 12070), 'pydantic.Field', 'Field', (['...'], {'description': '"""one line about summary of appointment,"""'}), "(..., description='one line about summary of appointment,')\n", (12011, 12070), False, 'from pydantic import BaseModel, Field\n'), ((12092, 12157), 'pydantic.Field', 'Field', (['...'], {'description': '"""one line about description about visit,"""'}), "(..., description='one line about description about visit,')\n", (12097, 12157), False, 'from pydantic import BaseModel, Field\n'), ((13401, 13439), 'requests.post', 'requests.post', (['api_url'], {'json': 'data_dict'}), '(api_url, json=data_dict)\n', (13414, 13439), False, 'import requests\n'), ((21734, 21868), 'langchain.agents.AgentExecutor', 'AgentExecutor', ([], {'agent': 'agent', 'tools': 'tools', 'memory': 'memory', 'verbose': '(True)', 'return_source_documents': '(True)', 'return_generated_question': '(True)'}), '(agent=agent, tools=tools, memory=memory, verbose=True,\n    return_source_documents=True, return_generated_question=True)\n', (21747, 21868), False, 'from langchain.agents import AgentExecutor\n'), ((23017, 23075), 'streamlit.session_state.chat_history.append', 'st.session_state.chat_history.append', (['(user_input, output)'], {}), '((user_input, output))\n', (23053, 23075), True, 'import streamlit as st\n'), ((3875, 3896), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (3894, 3896), False, 'import datetime\n'), ((3933, 3954), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (3952, 3954), False, 'import datetime\n'), ((23196, 23223), 'streamlit.text_input', 'st.text_input', (['"""Your name:"""'], {}), "('Your name:')\n", (23209, 23223), True, 'import streamlit as st\n'), ((23311, 23355), 'streamlit.form', 'st.form', ([], {'key': '"""my_form"""', 'clear_on_submit': '(True)'}), "(key='my_form', clear_on_submit=True)\n", (23318, 23355), True, 'import streamlit as st\n'), ((23379, 23444), 'streamlit.text_input', 'st.text_input', (['"""Query:"""'], {'placeholder': '"""Type your question here (:"""'}), "('Query:', placeholder='Type your question here (:')\n", (23392, 23444), True, 'import streamlit as st\n'), ((23470, 23505), 'streamlit.form_submit_button', 'st.form_submit_button', ([], {'label': '"""Send"""'}), "(label='Send')\n", (23491, 23505), True, 'import streamlit as st\n'), ((4499, 4517), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {}), '()\n', (4515, 4517), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((21473, 21518), 'langchain.prompts.MessagesPlaceholder', 'MessagesPlaceholder', ([], {'variable_name': 'memory_key'}), '(variable_name=memory_key)\n', (21492, 21518), False, 'from langchain.prompts import MessagesPlaceholder\n'), ((22745, 22810), 'streamlit.error', 'st.error', (['f"""An error occurred while saving data to Airtable: {e}"""'], {}), "(f'An error occurred while saving data to Airtable: {e}')\n", (22753, 22810), True, 'import streamlit as st\n'), ((23744, 23812), 'streamlit_chat.message', 'message', (['query'], {'is_user': '(True)', 'key': 'f"""{i}_user"""', 'avatar_style': '"""thumbs"""'}), "(query, is_user=True, key=f'{i}_user', avatar_style='thumbs')\n", (23751, 23812), False, 'from streamlit_chat import message\n'), ((23839, 23860), 'streamlit.columns', 'st.columns', (['[0.7, 10]'], {}), '([0.7, 10])\n', (23849, 23860), True, 'import streamlit as st\n'), ((22427, 22453), 'datetime.datetime.utcnow', 'datetime.datetime.utcnow', ([], {}), '()\n', (22451, 22453), False, 'import datetime\n'), ((23903, 23938), 'streamlit.image', 'st.image', (['"""icon-1024.png"""'], {'width': '(50)'}), "('icon-1024.png', width=50)\n", (23911, 23938), True, 'import streamlit as st\n'), ((23980, 24392), 'streamlit.markdown', 'st.markdown', (['f"""<div style="background-color: black; color: white; border-radius: 10px; padding: 10px; width: 60%; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-top-left-radius: 0; border-bottom-left-radius: 0; box-shadow: 2px 2px 5px #888888;"><span style="font-family: Arial, sans-serif; font-size: 16px; white-space: pre-wrap;">{answer}</span></div>"""'], {'unsafe_allow_html': '(True)'}), '(\n    f\'<div style="background-color: black; color: white; border-radius: 10px; padding: 10px; width: 60%; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-top-left-radius: 0; border-bottom-left-radius: 0; box-shadow: 2px 2px 5px #888888;"><span style="font-family: Arial, sans-serif; font-size: 16px; white-space: pre-wrap;">{answer}</span></div>\'\n    , unsafe_allow_html=True)\n', (23991, 24392), True, 'import streamlit as st\n'), ((24716, 24751), 'streamlit.error', 'st.error', (['f"""An error occurred: {e}"""'], {}), "(f'An error occurred: {e}')\n", (24724, 24751), True, 'import streamlit as st\n')]