File size: 11,215 Bytes
08bbb48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import requests
import streamlit as st
from PIL import Image, ImageOps, ImageDraw
from bs4 import BeautifulSoup
from gtts import gTTS
from langchain.prompts import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    MessagesPlaceholder,
    SystemMessagePromptTemplate,
)
from langchain.schema.output_parser import StrOutputParser
from langchain_community.chat_message_histories import StreamlitChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_google_genai import ChatGoogleGenerativeAI
from streamlit_mic_recorder import speech_to_text

# Set the page configuration
st.set_page_config(page_title="AI Voice Assistant", page_icon="🤖")


# Function for cropping images into a circular shape
def crop_circle(image, crop_size):
    img = ImageOps.fit(image, crop_size, centering=(0.5, 0.2))
    mask = Image.new("L", crop_size, 0)
    mask_draw = ImageDraw.Draw(mask)
    mask_draw.ellipse((0, 0, crop_size[0], crop_size[1]), fill=255)
    img.putalpha(mask)
    return img


# Function for "About Team" section
def about_team():
    st.title("About Team")
    st.write("Welcome to the About Team page!")

    # Load reference image for cropping size
    reference_image_path = "Tulaib.png"
    try:
        reference_image = Image.open(reference_image_path)
        crop_size = reference_image.size
    except FileNotFoundError:
        st.error(f"Reference image {reference_image_path} not found!")
        return

    team_members = [
        {"image": "WakeelAhmad.png", "name": "Wakeel Ahmed", "discipline": "Electrical Engineer"},
        {"image": "Raheel.png", "name": "Raheel Naveed", "discipline": "Mechatronics Engineer"},
        {"image": "Tulaib.png", "name": "Muhammad Tulaib", "discipline": "Civil Engineer"},
        {"image": "NaveedShahnawaz.png", "name": "Naveed Shahnawaz", "discipline": "Electrical Engineer"},
        {"image": "Sania.png", "name": "Sania", "discipline": "Biomedical Engineer"},
        {"image": "sanapic.png", "name": "Sana Tariq", "discipline": "Electronic Engineer"},
    ]

    for i in range(0, len(team_members), 3):
        cols = st.columns(3)
        for col, member in zip(cols, team_members[i:i + 3]):
            with col:
                try:
                    img = Image.open(member["image"])
                    circular_img = crop_circle(img, crop_size)
                    st.image(circular_img, use_container_width=True)
                except FileNotFoundError:
                    st.error(f"Image not found: {member['image']}")
                st.subheader(member["name"])
                st.write(f"{member['discipline']}")


# Function for chatbot
def chatbot():
    st.title("AI Voice Assistant 🎙️")
    st.subheader("Interact in Urdu with Real-Time Voice Input")

    api_key = "AIzaSyBsOwOK77hDyCAmr3Ce25E3F3rGh7okPb8"
    prompt = ChatPromptTemplate(
        messages=[
            SystemMessagePromptTemplate.from_template(
                "You are a helpful AI assistant for WAPDA Services In Pakistan called WAPDA CHATBOT. Please always respond to user queries in Pure Urdu language. And answer to questions regarding the WAPDA to help users, but always keep the responses short, help users to give tips about electricity"),
            MessagesPlaceholder(variable_name="chat_history"),
            HumanMessagePromptTemplate.from_template("{question}"),
        ]
    )

    msgs = StreamlitChatMessageHistory(key="langchain_messages")
    model = ChatGoogleGenerativeAI(model="gemini-1.5-flash", google_api_key=api_key)
    chain = prompt | model | StrOutputParser()
    chain_with_history = RunnableWithMessageHistory(
        chain, lambda session_id: msgs, input_messages_key="question", history_messages_key="chat_history"
    )

    st.write("Press the button and start speaking in Urdu:")

    with st.spinner("Converting Speech To Text..."):
        text = speech_to_text(language="ur", use_container_width=True, just_once=True, key="STT")

    if text:
        st.chat_message("human").write(text)
        with st.chat_message("assistant"):
            message_placeholder = st.empty()
            full_response = ""
            response = chain_with_history.stream({"question": text}, {"configurable": {"session_id": "any"}})

            for res in response:
                full_response += res or ""
                message_placeholder.markdown(full_response + "|")
                message_placeholder.markdown(full_response)

        with st.spinner("Converting Text To Speech..."):
            tts = gTTS(text=full_response, lang="ur")
            tts.save("output.mp3")
            st.audio("output.mp3")
    else:
        st.warning("Please press the button and start speaking.")


# Function to fetch and parse bill details
def determine_url(num):
    base_url = {"14": "iescobill", "12": "gepcobill", "11": "lescobill", "15": "mepcobill", "26": "pescobill"}
    return f"https://bill.pitc.com.pk/{base_url.get(num[2:4])}/general?refno={num}" if len(
        num) == 14 and num.isdigit() and num[2:4] in base_url else None

import requests
from bs4 import BeautifulSoup
import re
import streamlit as st

# Define the mapping of company codes to their corresponding URLs
company_codes = {
    "1": "lesco",
    "2": "gepco",
    "3": "fesco",
    "4": "iesco",
    "5": "mepco",
}

# Function to fetch and parse the HTML content
def fetch_and_parse(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # Check if the request was successful
        soup = BeautifulSoup(response.text, "html.parser")
        return soup
    except requests.exceptions.RequestException as e:
        st.error(f"Error fetching the URL: {e}")
        return None

# Function to extract key-value pairs from the table
# Function to extract key-value pairs from the table
def extract_key_value_pairs(soup):
    print("Extracting key-value pairs from the soup object...")
    if soup:
        table = soup.find("table", style="text-align: center; width: 100%; border-collapse: collapse;")
        if not table:
            print("Table not found!")
            return None

        rows = table.find_all("tr")
        header_cells = rows[0].find_all("td")
        headers = [header.get_text(strip=True) for header in header_cells]

        data_cells = rows[1].find_all("td")
        values = [cell.get_text(strip=True).replace("\n", " ").strip() for cell in data_cells]

        key_value_pairs = {
            headers[0]: values[0],
            headers[1]: values[1],
            headers[2]: values[2],
            headers[3]: headers[4],
            values[3]: values[4]
        }

        print(f"Extracted key-value pairs: {key_value_pairs}")
        return key_value_pairs
    else:
        print("Soup object is None. Couldn't parse the HTML.")
        return None


def refine_dictionary(key_value_pairs):
    print("Refining the key-value pairs...")
    refined_dict = {}
    for key, value in key_value_pairs.items():
        refined_dict[key] = re.sub(r'\s+', ' ', value.strip())
    print(f"Refined key-value pairs: {refined_dict}")
    return refined_dict
# Function to generate a contextual paragraph from bill information
# Function to generate a contextual paragraph from bill information
def generate_context_paragraph(refined_key_value_pairs):
    context_paragraph = (
        f"The user has provided the following billing information:\n"
        f"- The billing month for the user is: {refined_key_value_pairs['BILL MONTH']}.\n"
        f"- The due date for the current bill is: {refined_key_value_pairs['DUE DATE']}.\n"
        f"- The reference number associated with this bill is: {refined_key_value_pairs['REFERENCE NO']}.\n"
        f"- The amount payable within the due date is: {refined_key_value_pairs['PAYABLE WITHIN DUE DATE']}.\n"
        f"- If payment is delayed, the amount payable after the due date will be: {refined_key_value_pairs['PAYABLE AFTER DUE DATE']}.\n"
    )
    return context_paragraph
# Function to fetch bill details based on the reference number
def fetch_bill_details(reference_number):
    if len(reference_number) < 4:
        st.error("Invalid reference number. It must be at least 4 digits long.")
        return None, None, None

    fourth_digit = reference_number[3]
    if fourth_digit in company_codes:
        company_code = company_codes[fourth_digit]
        url = f"https://bill.pitc.com.pk/{company_code}bill/general?refno={reference_number}"
        soup = fetch_and_parse(url)

        if soup:
            key_value_pairs = extract_key_value_pairs(soup)
            if key_value_pairs:
                refined_key_value_pairs = refine_dictionary(key_value_pairs)

                # Extract the correct payable amount within the due date
                payable_within_due_date = refined_key_value_pairs.get('PAYABLE WITHIN DUE DATE', 'N/A')
                if payable_within_due_date == 'PAYABLE AFTER DUE DATE':
                    refined_key_value_pairs['PAYABLE WITHIN DUE DATE'] = refined_key_value_pairs.get('PAYABLE AFTER DUE DATE', 'N/A')

                context_paragraph = generate_context_paragraph(refined_key_value_pairs)
                return refined_key_value_pairs, context_paragraph
    return None, None



# Main function
def main():
    st.sidebar.image("WAPDA_logo.png", width=100)
    st.sidebar.markdown("Made with ❤️ by Flash Team")
    app_selection = st.sidebar.radio("Go to", ["Welcome","About Team", "WAPDA Bill Checker", "Chat Bot"])

    if app_selection == "Welcome":
        st.markdown(
            "<h1 style='font-size: 50px; font-weight: bold;'>Welcome to the WAPDA BillBOT</h1>",
            unsafe_allow_html=True
        )
        st.markdown(
            """

            <p style='font-size: 18px;'>

            The WAPDA BillBOT is your AI-powered assistant for managing electricity billing information with ease. 

            Whether you need to fetch bill details, interact using voice commands in Urdu, or learn more about our team, 

            this application is here to provide you with a seamless experience. Explore the features from the menu on the left, 

            and let us assist you in simplifying your billing tasks.

            </p>

            """,
            unsafe_allow_html=True
        )
    elif app_selection == "About Team":
        about_team()
    elif app_selection == "WAPDA Bill Checker":
        st.title("WAPDA Bill Checker")
        reference_number = st.text_input("Enter your bill reference number:")
        if st.button("Fetch Bill Details"):
            refined_data, context = fetch_bill_details(reference_number)
            if refined_data:
                st.success("Bill details fetched successfully!")
                st.write(context)
            else:
                st.error("Failed to fetch bill details.")
    elif app_selection == "Chat Bot":
        chatbot()


if __name__ == "__main__":
    main()