Spaces:
Runtime error
Runtime error
update new
Browse files- .idea/.gitignore +0 -8
- .idea/.name +0 -1
- .idea/Chat_QnA_v2.iml +0 -8
- .idea/inspectionProfiles/Project_Default.xml +0 -34
- .idea/inspectionProfiles/profiles_settings.xml +0 -6
- .idea/misc.xml +0 -4
- .idea/modules.xml +0 -8
- .idea/vcs.xml +0 -6
- Dockerfile +10 -0
- README.md +6 -5
- app.py +148 -246
- callback.py +17 -0
- chains/__pycache__/azure_openai.cpython-39.pyc +0 -0
- chains/__pycache__/custom_chain.cpython-39.pyc +0 -0
- chains/__pycache__/decision_maker.cpython-39.pyc +0 -0
- chains/__pycache__/model.cpython-39.pyc +0 -0
- chains/__pycache__/openai_model.cpython-39.pyc +0 -0
- chains/__pycache__/stage_analyzer.cpython-39.pyc +0 -0
- chains/__pycache__/summary.cpython-39.pyc +0 -0
- chains/__pycache__/web_search.cpython-39.pyc +0 -0
- chains/azure_openai.py +13 -0
- chains/custom_chain.py +68 -0
- chains/openai_model.py +253 -0
- chains/summary.py +21 -0
- chains/web_search.py +21 -0
- config.py +47 -0
- custom.css +0 -239
- data.json +1 -0
- geckodriver.log +0 -0
- html_parser.py +116 -0
- packages.txt +0 -2
- process_fb.py +55 -0
- process_html.py +58 -0
- prompts/__pycache__/condense_llm.cpython-39.pyc +0 -0
- prompts/__pycache__/custom_chain.cpython-39.pyc +0 -0
- prompts/__pycache__/llm.cpython-39.pyc +0 -0
- prompts/__pycache__/stage_analyzer.cpython-39.pyc +0 -0
- prompts/__pycache__/summary.cpython-39.pyc +0 -0
- prompts/__pycache__/web_search.cpython-39.pyc +0 -0
- prompts/condense_llm.py +5 -0
- prompts/custom_chain.py +12 -0
- prompts/llm.py +20 -0
- prompts/stage_analyzer.py +39 -0
- prompts/summary.py +4 -0
- prompts/web_search.py +18 -0
- requirements.txt +8 -5
- scrab_fb.py +16 -0
- utils.py +107 -0
- vector_db.py +148 -0
.idea/.gitignore
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
# Default ignored files
|
2 |
-
/shelf/
|
3 |
-
/workspace.xml
|
4 |
-
# Editor-based HTTP Client requests
|
5 |
-
/httpRequests/
|
6 |
-
# Datasource local storage ignored files
|
7 |
-
/dataSources/
|
8 |
-
/dataSources.local.xml
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/.name
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
app.py
|
|
|
|
.idea/Chat_QnA_v2.iml
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<module type="PYTHON_MODULE" version="4">
|
3 |
-
<component name="NewModuleRootManager">
|
4 |
-
<content url="file://$MODULE_DIR$" />
|
5 |
-
<orderEntry type="inheritedJdk" />
|
6 |
-
<orderEntry type="sourceFolder" forTests="false" />
|
7 |
-
</component>
|
8 |
-
</module>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/inspectionProfiles/Project_Default.xml
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
<component name="InspectionProjectProfileManager">
|
2 |
-
<profile version="1.0">
|
3 |
-
<option name="myName" value="Project Default" />
|
4 |
-
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
5 |
-
<option name="ignoredPackages">
|
6 |
-
<value>
|
7 |
-
<list size="14">
|
8 |
-
<item index="0" class="java.lang.String" itemvalue="scikit-image" />
|
9 |
-
<item index="1" class="java.lang.String" itemvalue="scipy" />
|
10 |
-
<item index="2" class="java.lang.String" itemvalue="thop" />
|
11 |
-
<item index="3" class="java.lang.String" itemvalue="tabulate" />
|
12 |
-
<item index="4" class="java.lang.String" itemvalue="opencv-python" />
|
13 |
-
<item index="5" class="java.lang.String" itemvalue="torch" />
|
14 |
-
<item index="6" class="java.lang.String" itemvalue="numpy" />
|
15 |
-
<item index="7" class="java.lang.String" itemvalue="loguru" />
|
16 |
-
<item index="8" class="java.lang.String" itemvalue="torchvision" />
|
17 |
-
<item index="9" class="java.lang.String" itemvalue="tqdm" />
|
18 |
-
<item index="10" class="java.lang.String" itemvalue="matplotlib" />
|
19 |
-
<item index="11" class="java.lang.String" itemvalue="pycocotools" />
|
20 |
-
<item index="12" class="java.lang.String" itemvalue="opencv_python" />
|
21 |
-
<item index="13" class="java.lang.String" itemvalue="Pillow" />
|
22 |
-
</list>
|
23 |
-
</value>
|
24 |
-
</option>
|
25 |
-
</inspection_tool>
|
26 |
-
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
27 |
-
<option name="ignoredErrors">
|
28 |
-
<list>
|
29 |
-
<option value="N806" />
|
30 |
-
</list>
|
31 |
-
</option>
|
32 |
-
</inspection_tool>
|
33 |
-
</profile>
|
34 |
-
</component>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/inspectionProfiles/profiles_settings.xml
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<component name="InspectionProjectProfileManager">
|
2 |
-
<settings>
|
3 |
-
<option name="USE_PROJECT_PROFILE" value="false" />
|
4 |
-
<version value="1.0" />
|
5 |
-
</settings>
|
6 |
-
</component>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/misc.xml
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<project version="4">
|
3 |
-
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
|
4 |
-
</project>
|
|
|
|
|
|
|
|
|
|
.idea/modules.xml
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<project version="4">
|
3 |
-
<component name="ProjectModuleManager">
|
4 |
-
<modules>
|
5 |
-
<module fileurl="file://$PROJECT_DIR$/.idea/Chat_QnA_v2.iml" filepath="$PROJECT_DIR$/.idea/Chat_QnA_v2.iml" />
|
6 |
-
</modules>
|
7 |
-
</component>
|
8 |
-
</project>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.idea/vcs.xml
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<project version="4">
|
3 |
-
<component name="VcsDirectoryMappings">
|
4 |
-
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
5 |
-
</component>
|
6 |
-
</project>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10
|
2 |
+
|
3 |
+
WORKDIR /usr/src/app
|
4 |
+
|
5 |
+
COPY requirements.txt ./
|
6 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
7 |
+
|
8 |
+
COPY . .
|
9 |
+
|
10 |
+
CMD [ "python", "app.py" ]
|
README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
-
sdk_version: 3.
|
|
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
---
|
|
|
1 |
---
|
2 |
+
title: Bot Recommendation
|
3 |
+
emoji: 🌖
|
4 |
+
colorFrom: red
|
5 |
+
colorTo: gray
|
6 |
sdk: gradio
|
7 |
+
sdk_version: 3.34.0
|
8 |
+
python_version: 3.9.13
|
9 |
app_file: app.py
|
10 |
pinned: false
|
11 |
---
|
app.py
CHANGED
@@ -1,267 +1,169 @@
|
|
1 |
-
import os
|
2 |
import gradio as gr
|
3 |
-
import openai
|
4 |
-
import re
|
5 |
-
import numpy as np
|
6 |
-
from sklearn.neighbors import NearestNeighbors
|
7 |
-
import tensorflow_hub as hub
|
8 |
-
import fitz
|
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 |
-
"English",
|
40 |
-
"简体中文",
|
41 |
-
"日本語",
|
42 |
-
"Deutsch",
|
43 |
-
"Vietnamese"
|
44 |
-
]
|
45 |
-
def set_openai_api_key(my_api_key):
|
46 |
-
openai.api_key = my_api_key
|
47 |
-
return gr.update(visible = True)
|
48 |
-
|
49 |
-
|
50 |
-
def add_source_numbers(lst):
|
51 |
-
return [item[:3] + '\t' + item[3:] for item in (lst)]
|
52 |
-
|
53 |
-
|
54 |
-
def add_details(lst):
|
55 |
-
nodes = []
|
56 |
-
for index, txt in enumerate(lst):
|
57 |
-
brief = txt[:25].replace("\n", "")
|
58 |
-
nodes.append(
|
59 |
-
f"<details><summary>{brief}...</summary><p>{txt}</p></details>"
|
60 |
-
)
|
61 |
-
return nodes
|
62 |
-
|
63 |
-
|
64 |
-
def preprocess(text):
|
65 |
-
text = text.replace('\n', ' ')
|
66 |
-
text = re.sub('\s+', ' ', text)
|
67 |
-
return text
|
68 |
-
|
69 |
-
|
70 |
-
def pdf_to_text(files_src, start_page=1, end_page=None):
|
71 |
-
text_list = []
|
72 |
-
for file in files_src:
|
73 |
-
if (os.path.splitext(file.name)[1]).lower() == ".pdf":
|
74 |
-
doc = fitz.open(file.name)
|
75 |
-
total_pages = doc.page_count
|
76 |
-
# if end_page is None:
|
77 |
-
end_page = total_pages
|
78 |
-
for i in range(start_page - 1, end_page):
|
79 |
-
text = doc.load_page(i).get_text("text")
|
80 |
-
text = preprocess(text)
|
81 |
-
text_list.append(text)
|
82 |
-
doc.close()
|
83 |
-
|
84 |
-
return text_list
|
85 |
-
|
86 |
-
|
87 |
-
def text_to_chunks(texts, word_length=150, start_page=1):
|
88 |
-
text_toks = [t.split(' ') for t in texts]
|
89 |
-
chunks = []
|
90 |
-
|
91 |
-
for idx, words in enumerate(text_toks):
|
92 |
-
for i in range(0, len(words), word_length):
|
93 |
-
chunk = words[i:i + word_length]
|
94 |
-
if (i + word_length) > len(words) and (len(chunk) < word_length) and (
|
95 |
-
len(text_toks) != (idx + 1)):
|
96 |
-
text_toks[idx + 1] = chunk + text_toks[idx + 1]
|
97 |
-
continue
|
98 |
-
chunk = ' '.join(chunk).strip()
|
99 |
-
chunk = f'[{idx + start_page}]' + ' ' + '"' + chunk + '"'
|
100 |
-
chunks.append(chunk)
|
101 |
-
return chunks
|
102 |
-
|
103 |
-
|
104 |
-
def embedding(model, files_src, batch=1000):
|
105 |
-
name_file = '_'.join([os.path.basename(file.name).split('.')[0] for file in files_src])
|
106 |
-
embeddings_file = f"{name_file}.npy"
|
107 |
-
texts = pdf_to_text(files_src)
|
108 |
-
chunks = text_to_chunks(texts)
|
109 |
-
if os.path.isfile(embeddings_file):
|
110 |
-
embeddings = np.load(embeddings_file)
|
111 |
-
return embeddings, chunks
|
112 |
-
data = chunks
|
113 |
-
embeddings = []
|
114 |
-
for i in range(0, len(data), batch):
|
115 |
-
text_batch = data[i:(i + batch)]
|
116 |
-
emb_batch = model(text_batch)
|
117 |
-
embeddings.append(emb_batch)
|
118 |
-
embeddings = np.vstack(embeddings)
|
119 |
-
np.save(embeddings_file, embeddings)
|
120 |
-
return embeddings, chunks
|
121 |
-
|
122 |
-
|
123 |
-
def get_top_chunks(inp_emb, data, n_neighbors=5):
|
124 |
-
n_neighbors = min(n_neighbors, len(data))
|
125 |
-
nn = NearestNeighbors(n_neighbors=n_neighbors)
|
126 |
-
nn.fit(data)
|
127 |
-
neighbors = nn.kneighbors(inp_emb, return_distance=False)[0]
|
128 |
-
return neighbors
|
129 |
-
|
130 |
-
|
131 |
-
def predict(
|
132 |
-
history,
|
133 |
-
chatbot,
|
134 |
-
inputs,
|
135 |
-
temperature,
|
136 |
-
lang = LANGUAGES[0],
|
137 |
-
selected_model=MODELS[0],
|
138 |
-
files=None
|
139 |
-
):
|
140 |
-
old_inputs = None
|
141 |
-
if files:
|
142 |
-
old_inputs = inputs
|
143 |
-
emb_model = hub.load('https://tfhub.dev/google/universal-sentence-encoder/4')
|
144 |
-
|
145 |
-
vector_emb, chunks = embedding(emb_model, files)
|
146 |
-
|
147 |
-
input_emb = emb_model([inputs])
|
148 |
-
index_top_chunks = get_top_chunks(input_emb, vector_emb)
|
149 |
-
topn_chunks = [chunks[i] for i in index_top_chunks]
|
150 |
-
prompt = ""
|
151 |
-
prompt += 'search results:\n\n'
|
152 |
-
for c in topn_chunks:
|
153 |
-
prompt += c + '\n\n'
|
154 |
-
prompt += prompt_template
|
155 |
-
prompt += f"Query: {inputs}. Reply in {lang}\nAnswer:"
|
156 |
-
inputs = prompt
|
157 |
-
reference_results = add_source_numbers(topn_chunks)
|
158 |
-
display_reference = add_details(reference_results)
|
159 |
-
display_reference = "\n\n" + "".join(display_reference)
|
160 |
-
else:
|
161 |
-
display_reference = ""
|
162 |
-
|
163 |
-
history.append(inputs)
|
164 |
-
if old_inputs:
|
165 |
-
chatbot.append((old_inputs, ""))
|
166 |
-
else:
|
167 |
-
chatbot.append((inputs, ""))
|
168 |
-
completions = openai.Completion.create(
|
169 |
-
engine=selected_model,
|
170 |
-
prompt=inputs,
|
171 |
-
max_tokens=256,
|
172 |
-
stop=None,
|
173 |
-
temperature=temperature,
|
174 |
-
)
|
175 |
-
message = completions.choices[0].text
|
176 |
-
if old_inputs is not None:
|
177 |
-
history[-1] = old_inputs
|
178 |
-
chatbot[-1] = (chatbot[-1][0], message + display_reference)
|
179 |
-
return chatbot, history
|
180 |
-
|
181 |
-
|
182 |
-
# Create theme
|
183 |
-
with open("custom.css", "r", encoding="utf-8") as f:
|
184 |
-
customCSS = f.read()
|
185 |
-
beautiful_theme = gr.themes.Soft(
|
186 |
-
primary_hue=gr.themes.Color(
|
187 |
-
c50="#02C160",
|
188 |
-
c100="rgba(2, 193, 96, 0.2)",
|
189 |
-
c200="#02C160",
|
190 |
-
c300="rgba(2, 193, 96, 0.32)",
|
191 |
-
c400="rgba(2, 193, 96, 0.32)",
|
192 |
-
c500="rgba(2, 193, 96, 1.0)",
|
193 |
-
c600="rgba(2, 193, 96, 1.0)",
|
194 |
-
c700="rgba(2, 193, 96, 0.32)",
|
195 |
-
c800="rgba(2, 193, 96, 0.32)",
|
196 |
-
c900="#02C160",
|
197 |
-
c950="#02C160",
|
198 |
-
),
|
199 |
-
radius_size=gr.themes.sizes.radius_sm,
|
200 |
-
).set(
|
201 |
-
button_primary_background_fill="#06AE56",
|
202 |
-
button_primary_background_fill_dark="#06AE56",
|
203 |
-
button_primary_background_fill_hover="#07C863",
|
204 |
-
button_primary_border_color="#06AE56",
|
205 |
-
button_primary_border_color_dark="#06AE56",
|
206 |
-
button_primary_text_color="#FFFFFF",
|
207 |
-
button_primary_text_color_dark="#FFFFFF",
|
208 |
-
block_title_text_color="*primary_500",
|
209 |
-
block_title_background_fill="*primary_100",
|
210 |
-
input_background_fill="#F6F6F6",
|
211 |
-
)
|
212 |
|
213 |
# Gradio app
|
214 |
-
title = """<h1 align="left" style="min-width:200px; margin-top:6px; white-space: nowrap;">
|
215 |
-
with gr.Blocks(
|
|
|
216 |
history = gr.State([])
|
217 |
-
|
218 |
|
219 |
with gr.Row():
|
220 |
with gr.Column(scale=1):
|
221 |
gr.HTML(title)
|
|
|
|
|
222 |
|
223 |
with gr.Row().style(equal_height=True):
|
224 |
with gr.Column(scale=5):
|
225 |
with gr.Row():
|
226 |
-
chatbot = gr.Chatbot(elem_id="chatbot").style(height="100%")
|
227 |
-
with gr.Row(
|
228 |
-
with gr.Column(scale=12):
|
229 |
user_input = gr.Textbox(
|
230 |
show_label=False, placeholder="Enter here"
|
231 |
).style(container=False)
|
232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
submitBtn = gr.Button("Send", variant="primary")
|
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 |
user_input.submit(lambda: "", None, user_input)
|
264 |
-
submitBtn.click(predict,
|
265 |
-
outputs=[chatbot, history])
|
266 |
submitBtn.click(lambda: "", None, user_input)
|
267 |
-
demo.queue(concurrency_count=10).launch(
|
|
|
|
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
+
from utils import *
|
4 |
+
from chains.openai_model import OpenAIModel
|
5 |
+
from config import SEVER, PORT, DEBUG, DEPLOYMENT_ID, SAVE_DIR
|
6 |
+
from vector_db import delete_all, delete_file, handle_upload_file, update_file
|
7 |
+
|
8 |
+
# Get and load new model
|
9 |
+
def get_model(llm_model_name, temperature=0., top_p=1.0):
|
10 |
+
model = OpenAIModel(llm_model_name=llm_model_name,
|
11 |
+
condense_model_name=llm_model_name, temperature=temperature, top_p=top_p)
|
12 |
+
return model
|
13 |
+
|
14 |
+
|
15 |
+
def create_new_model():
|
16 |
+
return get_model(llm_model_name=DEPLOYMENT_ID)
|
17 |
+
|
18 |
+
def update_database(files_src):
|
19 |
+
message = handle_upload_file(files_src)
|
20 |
+
saved_file = os.listdir(SAVE_DIR)
|
21 |
+
# saved_file = os.listdir(SAVE_DIR)
|
22 |
+
# if files_src is None:
|
23 |
+
# return gr.update(choices=[])
|
24 |
+
# for file in files_src:
|
25 |
+
# file_path = file.name
|
26 |
+
# file_name = os.path.basename(file_path)
|
27 |
+
# if file_name in os.listdir(SAVE_DIR):
|
28 |
+
# continue
|
29 |
+
# else:
|
30 |
+
# saved_file.extend([file_name])
|
31 |
+
return gr.update(choices=saved_file), message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
# Gradio app
|
34 |
+
title = """<h1 align="left" style="min-width:200px; margin-top:6px; white-space: nowrap;">Docs FPT 🤖</h1>"""
|
35 |
+
with gr.Blocks() as demo:
|
36 |
+
user_name = gr.State("")
|
37 |
history = gr.State([])
|
38 |
+
current_model = gr.State(create_new_model)
|
39 |
|
40 |
with gr.Row():
|
41 |
with gr.Column(scale=1):
|
42 |
gr.HTML(title)
|
43 |
+
status_text = ""
|
44 |
+
status_display = gr.Markdown(status_text, elem_id="status_display")
|
45 |
|
46 |
with gr.Row().style(equal_height=True):
|
47 |
with gr.Column(scale=5):
|
48 |
with gr.Row():
|
49 |
+
chatbot = gr.Chatbot([], elem_id="chatbot").style(height="100%")
|
50 |
+
with gr.Row():
|
51 |
+
with gr.Column(min_width=225, scale=12):
|
52 |
user_input = gr.Textbox(
|
53 |
show_label=False, placeholder="Enter here"
|
54 |
).style(container=False)
|
55 |
+
# ask_examples_hidden = gr.Textbox(elem_id="hidden-message")
|
56 |
+
examples_questions = gr.Examples(
|
57 |
+
[
|
58 |
+
"What are the possible ranks of Fsoft projects?",
|
59 |
+
"What is the rank of a project that has budgeted MM 100 man-month?",
|
60 |
+
"What is the definition of a rank A project?",
|
61 |
+
"情報セキュリティに関する事故が起きた場合、誰に通報すればよいですか",
|
62 |
+
"事故データベースはどのくらいの期間保存されますか?",
|
63 |
+
"セキュリティ事故が重大かどうかはどうすればわかりますか?"
|
64 |
+
],
|
65 |
+
[user_input],
|
66 |
+
examples_per_page=6,
|
67 |
+
)
|
68 |
+
with gr.Column(min_width=42, scale=1):
|
69 |
submitBtn = gr.Button("Send", variant="primary")
|
70 |
+
with gr.Row():
|
71 |
+
emptyBtn = gr.Button(
|
72 |
+
"🧹 New conversation", elem_id="empty_btn")
|
73 |
+
retryBtn = gr.Button("🔄 Retry")
|
74 |
+
rec = gr.Button("⏺️Record")
|
75 |
+
record_audio = gr.inputs.Audio(source="microphone", type="filepath")
|
76 |
+
with gr.Row():
|
77 |
+
gr.Markdown(
|
78 |
+
"""
|
79 |
+
## 💻 Key Feature
|
80 |
+
- Chat with an AI chatbot powered by OpenAI's chat API, using the **content of your research document**.
|
81 |
+
- Get **semantic search** answers from your document using **vector databases**.
|
82 |
+
- Perform a **Google search** within the app
|
83 |
+
- **Verify sources** for all generated results.
|
84 |
+
- Support converting **speech to text** for easy input.
|
85 |
+
### Pine cone
|
86 |
+
Pinecone makes it easy to provide long-term memory for high-performance AI applications.
|
87 |
+
It's a managed, cloud-native vector database with a simple API and no infrastructure hassles. Pinecone serves fresh, filtered query results with low latency at the scale of billions of vectors.
|
88 |
+
https://www.pinecone.io/blog/azure/
|
89 |
+
### Azure OpenAI Service
|
90 |
+
https://learn.microsoft.com/en-us/legal/cognitive-services/openai/data-privacy
|
91 |
+
## 📧 Contact
|
92 |
+
This tool has been developed by the R&D lab at **QAI** (FPT Software, Ha Noi, Viet Nam)
|
93 |
+
If you have any questions or feature requests, please feel free to reach us out at <b>[email protected]</b>.
|
94 |
+
"""
|
95 |
+
)
|
96 |
+
|
97 |
+
with gr.Column(min_width=50, scale=1.5):
|
98 |
+
with gr.Tab(label="ChatGPT"):
|
99 |
+
# gr.Markdown(f'<p style="text-align:center">Azure OpenAI Service:<a '
|
100 |
+
# f'href="https://learn.microsoft.com/en-us/legal/cognitive-services/openai/data-privacy">here</a></p>')
|
101 |
+
index_files = gr.Files(label="Files", type="file", multiple=True)
|
102 |
+
use_websearch = gr.Checkbox(label="Google search", value=False, elem_classes="switch_checkbox")
|
103 |
+
custom_websearch = gr.Checkbox(label="Custom web search", value=False, elem_classes="switch_checkbox")
|
104 |
+
|
105 |
+
with gr.Tab(label="Configuration"):
|
106 |
+
gr.Markdown(
|
107 |
+
"⚠️Be careful to change ⚠️\n\nIf you can't use it, please restore the default settings")
|
108 |
+
with gr.Accordion("Parameter", open=False):
|
109 |
+
temperature_slider = gr.Slider(
|
110 |
+
minimum=-0,
|
111 |
+
maximum=1.0,
|
112 |
+
value=0.0,
|
113 |
+
step=0.1,
|
114 |
+
interactive=True,
|
115 |
+
label="Temperature",
|
116 |
)
|
117 |
+
top_p_slider = gr.Slider(
|
118 |
+
minimum=-0,
|
119 |
+
maximum=1.0,
|
120 |
+
value=1.0,
|
121 |
+
step=0.1,
|
122 |
+
interactive=True,
|
123 |
+
label="Top_p",
|
124 |
)
|
125 |
+
user_identifier = gr.Textbox(
|
126 |
+
show_label=True,
|
127 |
+
placeholder="Enter here",
|
128 |
+
label="User name",
|
129 |
+
value=user_name.value,
|
130 |
+
lines=1,
|
131 |
+
)
|
132 |
+
loadHistoryBtn = gr.Button("💾 Load History")
|
133 |
+
with gr.Tab(label="Knowledge DB"):
|
134 |
+
all_files = gr.Dropdown(
|
135 |
+
label="All available files:", multiselect=True, choices=os.listdir(SAVE_DIR), interactive=True
|
136 |
+
)
|
137 |
+
with gr.Column():
|
138 |
+
delete_btn = gr.Button("🗑️ Delete")
|
139 |
+
with gr.Column():
|
140 |
+
delete_all_btn = gr.Button("🗑️ Delete all")
|
141 |
+
update_btn = gr.Button("🗑️ Update DB")
|
142 |
+
|
143 |
+
index_files.change(update_database, [index_files], [all_files, status_display])
|
144 |
+
delete_all_btn.click(delete_all, None, [all_files, status_display, index_files])
|
145 |
+
delete_btn.click(delete_file, [all_files], [all_files, status_display, index_files])
|
146 |
+
update_btn.click(update_file, None, [status_display])
|
147 |
+
|
148 |
+
emptyBtn.click(
|
149 |
+
reset,
|
150 |
+
inputs=[current_model],
|
151 |
+
outputs=[chatbot],
|
152 |
+
show_progress=True,
|
153 |
+
)
|
154 |
+
|
155 |
+
retryBtn.click(retry, [chatbot, current_model, use_websearch, custom_websearch], [chatbot])
|
156 |
+
|
157 |
+
|
158 |
+
loadHistoryBtn.click(load_chat_history, [current_model], [chatbot])
|
159 |
+
|
160 |
+
rec.click(transcribe, [current_model, record_audio], [user_input])
|
161 |
+
|
162 |
+
user_identifier.change(set_user_indentifier, [current_model, user_identifier], None)
|
163 |
+
|
164 |
+
user_input.submit(predict, [chatbot, current_model, user_input, use_websearch, custom_websearch], [chatbot, status_display], show_progress=True)
|
165 |
user_input.submit(lambda: "", None, user_input)
|
166 |
+
submitBtn.click(predict, [chatbot, current_model, user_input, use_websearch, custom_websearch], [chatbot, status_display], show_progress=True)
|
|
|
167 |
submitBtn.click(lambda: "", None, user_input)
|
168 |
+
demo.queue(concurrency_count=10).launch(
|
169 |
+
server_name=SEVER, server_port=PORT, debug=DEBUG)
|
callback.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Union, List, Dict
|
2 |
+
from langchain.callbacks.base import BaseCallbackHandler
|
3 |
+
|
4 |
+
job_done = object()
|
5 |
+
|
6 |
+
|
7 |
+
class StreamingGradioCallbackHandler(BaseCallbackHandler):
|
8 |
+
"""Callback handler for streaming LLM responses to a queue."""
|
9 |
+
|
10 |
+
def __init__(self, q):
|
11 |
+
self.q = q
|
12 |
+
|
13 |
+
def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
14 |
+
self.q.put(token)
|
15 |
+
|
16 |
+
def on_llm_end(self, *args, **kwargs: Any) -> None:
|
17 |
+
return self.q.empty()
|
chains/__pycache__/azure_openai.cpython-39.pyc
ADDED
Binary file (770 Bytes). View file
|
|
chains/__pycache__/custom_chain.cpython-39.pyc
ADDED
Binary file (2.52 kB). View file
|
|
chains/__pycache__/decision_maker.cpython-39.pyc
ADDED
Binary file (1.19 kB). View file
|
|
chains/__pycache__/model.cpython-39.pyc
ADDED
Binary file (5.7 kB). View file
|
|
chains/__pycache__/openai_model.cpython-39.pyc
ADDED
Binary file (7.83 kB). View file
|
|
chains/__pycache__/stage_analyzer.cpython-39.pyc
ADDED
Binary file (1.23 kB). View file
|
|
chains/__pycache__/summary.cpython-39.pyc
ADDED
Binary file (1.08 kB). View file
|
|
chains/__pycache__/web_search.cpython-39.pyc
ADDED
Binary file (1.1 kB). View file
|
|
chains/azure_openai.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import List
|
2 |
+
from langchain.chat_models import AzureChatOpenAI
|
3 |
+
|
4 |
+
class CustomAzureOpenAI(AzureChatOpenAI):
|
5 |
+
stop: List[str] = None
|
6 |
+
@property
|
7 |
+
def _invocation_params(self):
|
8 |
+
params = super()._invocation_params
|
9 |
+
# fix InvalidRequestError: logprobs, best_of and echo parameters are not available on gpt-35-turbo model.
|
10 |
+
params.pop('logprobs', None)
|
11 |
+
params.pop('best_of', None)
|
12 |
+
params.pop('echo', None)
|
13 |
+
return params
|
chains/custom_chain.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
2 |
+
from langchain.schema import BaseMessage, BaseRetriever, Document
|
3 |
+
from langchain.chains.conversational_retrieval.base import _get_chat_history
|
4 |
+
from langchain.chains import ConversationalRetrievalChain
|
5 |
+
from langchain.chains.llm import LLMChain
|
6 |
+
from langchain.prompts.chat import (
|
7 |
+
ChatPromptTemplate,
|
8 |
+
SystemMessagePromptTemplate,
|
9 |
+
HumanMessagePromptTemplate)
|
10 |
+
from config import DEPLOYMENT_ID
|
11 |
+
from prompts.custom_chain import SYSTEM_PROMPT_TEMPLATE, HUMAN_PROMPT_TEMPLATE
|
12 |
+
from config import OPENAI_API_TYPE, OPENAI_API_VERSION, OPENAI_API_KEY, OPENAI_API_BASE
|
13 |
+
from chains.azure_openai import CustomAzureOpenAI
|
14 |
+
from langchain.callbacks.manager import CallbackManagerForChainRun
|
15 |
+
from utils import add_source_numbers
|
16 |
+
import os
|
17 |
+
|
18 |
+
class MultiQueriesChain(LLMChain):
|
19 |
+
llm = CustomAzureOpenAI(deployment_name=DEPLOYMENT_ID,
|
20 |
+
openai_api_type=OPENAI_API_TYPE,
|
21 |
+
openai_api_base=OPENAI_API_BASE,
|
22 |
+
openai_api_version=OPENAI_API_VERSION,
|
23 |
+
openai_api_key=OPENAI_API_KEY,
|
24 |
+
temperature=0.0)
|
25 |
+
prompt = ChatPromptTemplate.from_messages(
|
26 |
+
[
|
27 |
+
SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT_TEMPLATE),
|
28 |
+
HumanMessagePromptTemplate.from_template(HUMAN_PROMPT_TEMPLATE)
|
29 |
+
])
|
30 |
+
|
31 |
+
llm_chain = MultiQueriesChain()
|
32 |
+
|
33 |
+
class CustomConversationalRetrievalChain(ConversationalRetrievalChain):
|
34 |
+
retriever: BaseRetriever
|
35 |
+
"""Index to connect to."""
|
36 |
+
max_tokens_limit: Optional[int] = None
|
37 |
+
def _get_docs(
|
38 |
+
self,
|
39 |
+
question: str,
|
40 |
+
inputs: Dict[str, Any]
|
41 |
+
) -> List[Document]:
|
42 |
+
"""Get docs."""
|
43 |
+
docs = self.retriever.get_relevant_documents(
|
44 |
+
question
|
45 |
+
)
|
46 |
+
for (idx, d) in enumerate(docs):
|
47 |
+
if "https:" in d.metadata["source"]:
|
48 |
+
item = [d.page_content.strip("�"), d.metadata["source"]]
|
49 |
+
else:
|
50 |
+
item = [d.page_content.strip("�"), os.path.basename(d.metadata["source"])]
|
51 |
+
d.page_content = f'[{idx+1}]\t "{item[0]}"\nSource: {item[1]}'
|
52 |
+
return self._reduce_tokens_below_limit(docs)
|
53 |
+
# def _get_docs(self, question: str, inputs: Dict[str, Any]) -> List[Document]:
|
54 |
+
# results = llm_chain.predict(question=question) + "\n"
|
55 |
+
# print(results)
|
56 |
+
# queries = list(map(lambda x: x.strip(), results.split(', ')))
|
57 |
+
# docs = []
|
58 |
+
# print(queries)
|
59 |
+
# for query in queries[:3]:
|
60 |
+
# self.retriever.search_kwargs = {"k": 3}
|
61 |
+
# doc = self.retriever.get_relevant_documents(query)
|
62 |
+
# docs.extend(doc)
|
63 |
+
# unique_documents_dict = {
|
64 |
+
# (doc.page_content, tuple(sorted(doc.metadata.items()))): doc
|
65 |
+
# for doc in docs
|
66 |
+
# }
|
67 |
+
# unique_documents = list(unique_documents_dict.values())
|
68 |
+
# return self._reduce_tokens_below_limit(unique_documents)
|
chains/openai_model.py
ADDED
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import os
|
3 |
+
import openai
|
4 |
+
|
5 |
+
from langchain.prompts import PromptTemplate
|
6 |
+
from config import TIMEOUT_STREAM
|
7 |
+
from vector_db import upload_file
|
8 |
+
from callback import StreamingGradioCallbackHandler
|
9 |
+
from queue import SimpleQueue, Empty
|
10 |
+
from threading import Thread
|
11 |
+
from utils import history_file_path, load_lasted_file_username, add_source_numbers, add_details
|
12 |
+
from chains.custom_chain import CustomConversationalRetrievalChain
|
13 |
+
from langchain.chains import LLMChain
|
14 |
+
from chains.azure_openai import CustomAzureOpenAI
|
15 |
+
from config import OPENAI_API_TYPE, OPENAI_API_VERSION, OPENAI_API_KEY, OPENAI_API_BASE, API_KEY, \
|
16 |
+
DEPLOYMENT_ID, MODEL_ID, EMBEDDING_API_KEY, EMBEDDING_API_BASE
|
17 |
+
|
18 |
+
|
19 |
+
class OpenAIModel:
|
20 |
+
def __init__(
|
21 |
+
self,
|
22 |
+
llm_model_name,
|
23 |
+
condense_model_name,
|
24 |
+
prompt_template="",
|
25 |
+
temperature=0.0,
|
26 |
+
top_p=1.0,
|
27 |
+
n_choices=1,
|
28 |
+
stop = None,
|
29 |
+
presence_penalty=0,
|
30 |
+
frequency_penalty=0,
|
31 |
+
user = None
|
32 |
+
):
|
33 |
+
self.llm_model_name = llm_model_name
|
34 |
+
self.condense_model_name = condense_model_name
|
35 |
+
self.prompt_template = prompt_template
|
36 |
+
self.temperature = temperature
|
37 |
+
self.top_p = top_p
|
38 |
+
self.n_choices = n_choices
|
39 |
+
self.stop = stop
|
40 |
+
self.presence_penalty = presence_penalty
|
41 |
+
self.frequency_penalty = frequency_penalty
|
42 |
+
|
43 |
+
self.history = []
|
44 |
+
self.user_identifier = user
|
45 |
+
|
46 |
+
def set_user_indentifier(self, new_user_indentifier):
|
47 |
+
self.user_identifier = new_user_indentifier
|
48 |
+
|
49 |
+
def format_prompt(self, qa_prompt_template, condense_prompt_template):
|
50 |
+
# Prompt template langchain
|
51 |
+
qa_prompt = PromptTemplate(template=qa_prompt_template, input_variables=["question", "chat_history", "context"])
|
52 |
+
condense_prompt = PromptTemplate(template=condense_prompt_template, input_variables=["question", "chat_history"])
|
53 |
+
return qa_prompt, condense_prompt
|
54 |
+
|
55 |
+
def memory(self, inputs, outputs, last_k=3):
|
56 |
+
# last_k: top k last conversation
|
57 |
+
if len(self.history) >= last_k:
|
58 |
+
self.history.pop(0)
|
59 |
+
self.history.extend([(inputs, outputs)])
|
60 |
+
|
61 |
+
def reset_conversation(self):
|
62 |
+
self.history = []
|
63 |
+
return []
|
64 |
+
|
65 |
+
def delete_first_conversation(self):
|
66 |
+
if self.history:
|
67 |
+
self.history.pop(0)
|
68 |
+
|
69 |
+
def delete_last_conversation(self):
|
70 |
+
if len(self.history) > 0:
|
71 |
+
self.history.pop()
|
72 |
+
|
73 |
+
def auto_save_history(self, chatbot):
|
74 |
+
if self.user_identifier is not None:
|
75 |
+
file_path = history_file_path(self.user_identifier)
|
76 |
+
json_s = {"history": self.history, "chatbot": chatbot}
|
77 |
+
with open(file_path, "w", encoding='utf-8') as f:
|
78 |
+
json.dump(json_s, f, ensure_ascii=False)
|
79 |
+
|
80 |
+
def load_history(self):
|
81 |
+
lasted_file = load_lasted_file_username(self.user_identifier)
|
82 |
+
if lasted_file is not None:
|
83 |
+
with open(f"{lasted_file}.json", "r", encoding="utf-8") as f:
|
84 |
+
json_s = json.load(f)
|
85 |
+
self.history = json_s["history"]
|
86 |
+
chatbot = json_s["chatbot"]
|
87 |
+
return chatbot
|
88 |
+
|
89 |
+
def audio_response(self, audio):
|
90 |
+
media_file = open(audio, 'rb')
|
91 |
+
response = openai.Audio.transcribe(
|
92 |
+
api_key=API_KEY,
|
93 |
+
model=MODEL_ID,
|
94 |
+
file=media_file
|
95 |
+
)
|
96 |
+
return response["text"]
|
97 |
+
|
98 |
+
def inference(self, inputs, chatbot, streaming=False, use_websearch=False, custom_websearch=False, **kwargs):
|
99 |
+
if use_websearch or custom_websearch:
|
100 |
+
import requests
|
101 |
+
|
102 |
+
from bs4 import BeautifulSoup
|
103 |
+
from langchain.utilities.google_search import GoogleSearchAPIWrapper
|
104 |
+
from chains.web_search import GoogleWebSearch
|
105 |
+
from config import GOOGLE_API_KEY, GOOGLE_CSE_ID, CUSTOM_API_KEY, CUSTOM_CSE_ID
|
106 |
+
from chains.summary import WebSummary
|
107 |
+
|
108 |
+
status_text = "Retrieving information from the web"
|
109 |
+
yield chatbot, status_text
|
110 |
+
if use_websearch:
|
111 |
+
google_api_key = GOOGLE_API_KEY
|
112 |
+
google_cse_id = GOOGLE_CSE_ID
|
113 |
+
else:
|
114 |
+
google_api_key = CUSTOM_API_KEY
|
115 |
+
google_cse_id = CUSTOM_CSE_ID
|
116 |
+
search = GoogleSearchAPIWrapper(google_api_key=google_api_key, google_cse_id=google_cse_id)
|
117 |
+
results = search.results(inputs,4)
|
118 |
+
reference_results = []
|
119 |
+
display_append = []
|
120 |
+
for idx, result in enumerate(results):
|
121 |
+
print(result['link'])
|
122 |
+
response = requests.get(result['link'])
|
123 |
+
soup = BeautifulSoup(response.content, "html.parser")
|
124 |
+
try:
|
125 |
+
summary = WebSummary.predict(question=inputs, doc=soup.get_text())
|
126 |
+
print("Can access", result['link'])
|
127 |
+
except:
|
128 |
+
print("Cannot access ", result['link'])
|
129 |
+
summary = result['snippet']
|
130 |
+
reference_results.append([summary, result['link']])
|
131 |
+
display_append.append(
|
132 |
+
f"<a href=\"{result['link']}\" target=\"_blank\">{idx+1}. {result['title']}</a>"
|
133 |
+
)
|
134 |
+
reference_results = add_source_numbers(reference_results)
|
135 |
+
display_append = '<div class = "source-a">' + "\n".join(display_append) + '</div>'
|
136 |
+
|
137 |
+
status_text = "Request URL: " + OPENAI_API_BASE
|
138 |
+
yield chatbot, status_text
|
139 |
+
chatbot.append((inputs, ""))
|
140 |
+
web_search = GoogleWebSearch()
|
141 |
+
ai_response = web_search.predict(context="\n\n".join(reference_results), question=inputs, chat_history=self.history)
|
142 |
+
|
143 |
+
chatbot[-1] = (chatbot[-1][0], ai_response+display_append)
|
144 |
+
self.memory(inputs, ai_response)
|
145 |
+
self.auto_save_history(chatbot)
|
146 |
+
yield chatbot, status_text
|
147 |
+
|
148 |
+
else:
|
149 |
+
status_text = "Indexing files to vector database"
|
150 |
+
yield chatbot, status_text
|
151 |
+
|
152 |
+
vectorstore = upload_file()
|
153 |
+
|
154 |
+
status_text = "OpenAI version: " + OPENAI_API_VERSION
|
155 |
+
yield chatbot, status_text
|
156 |
+
qa_prompt, condense_prompt = self.format_prompt(**kwargs)
|
157 |
+
job_done = object() # signals the processing is done
|
158 |
+
q = SimpleQueue()
|
159 |
+
if streaming:
|
160 |
+
timeout = TIMEOUT_STREAM
|
161 |
+
streaming_callback =[StreamingGradioCallbackHandler(q)]
|
162 |
+
|
163 |
+
# Define llm model
|
164 |
+
llm = CustomAzureOpenAI(deployment_name=DEPLOYMENT_ID,
|
165 |
+
openai_api_type=OPENAI_API_TYPE,
|
166 |
+
openai_api_base=OPENAI_API_BASE,
|
167 |
+
openai_api_version=OPENAI_API_VERSION,
|
168 |
+
openai_api_key=OPENAI_API_KEY,
|
169 |
+
temperature=self.temperature,
|
170 |
+
model_kwargs={"top_p": self.top_p},
|
171 |
+
streaming=streaming,\
|
172 |
+
callbacks=streaming_callback,
|
173 |
+
request_timeout=timeout)
|
174 |
+
|
175 |
+
condense_llm = CustomAzureOpenAI(deployment_name=self.condense_model_name,
|
176 |
+
openai_api_type=OPENAI_API_TYPE,
|
177 |
+
openai_api_base=OPENAI_API_BASE,
|
178 |
+
openai_api_version=OPENAI_API_VERSION,
|
179 |
+
openai_api_key=OPENAI_API_KEY,
|
180 |
+
temperature=self.temperature)
|
181 |
+
|
182 |
+
status_text = "Request URL: " + OPENAI_API_BASE
|
183 |
+
yield chatbot, status_text
|
184 |
+
|
185 |
+
# Create a funciton to call - this will run in a thread
|
186 |
+
def task():
|
187 |
+
# Converation + RetrivalChain
|
188 |
+
qa = CustomConversationalRetrievalChain.from_llm(llm, vectorstore.as_retriever(k=5),
|
189 |
+
condense_question_llm = condense_llm, verbose=True,
|
190 |
+
condense_question_prompt=condense_prompt,
|
191 |
+
combine_docs_chain_kwargs={"prompt": qa_prompt},
|
192 |
+
return_source_documents=True)
|
193 |
+
# query with input and chat history
|
194 |
+
global response
|
195 |
+
response = qa({"question": inputs, "chat_history": self.history})
|
196 |
+
q.put(job_done)
|
197 |
+
|
198 |
+
thread = Thread(target=task)
|
199 |
+
thread.start()
|
200 |
+
chatbot.append((inputs, ""))
|
201 |
+
content = ""
|
202 |
+
while True:
|
203 |
+
try:
|
204 |
+
next_token = q.get(block=True)
|
205 |
+
if next_token is job_done:
|
206 |
+
break
|
207 |
+
content += next_token
|
208 |
+
chatbot[-1] = (chatbot[-1][0], content)
|
209 |
+
yield chatbot, status_text
|
210 |
+
except Empty:
|
211 |
+
continue
|
212 |
+
|
213 |
+
# add citation info to response
|
214 |
+
relevant_docs = response["source_documents"]
|
215 |
+
reference_results = [d.page_content for d in relevant_docs]
|
216 |
+
display_append = add_details(reference_results)
|
217 |
+
display_append = "\n\n" + "<details><summary><b>Citation</b></summary>"+ "".join(display_append) + "</details>"
|
218 |
+
chatbot[-1] = (chatbot[-1][0], content+display_append)
|
219 |
+
yield chatbot, status_text
|
220 |
+
|
221 |
+
self.memory(inputs, content)
|
222 |
+
self.auto_save_history(chatbot)
|
223 |
+
thread.join()
|
224 |
+
|
225 |
+
if __name__ == '__main__':
|
226 |
+
import os
|
227 |
+
from config import OPENAI_API_KEY
|
228 |
+
from langchain.chains.llm import LLMChain
|
229 |
+
from langchain.prompts.chat import (
|
230 |
+
ChatPromptTemplate,
|
231 |
+
SystemMessagePromptTemplate,
|
232 |
+
HumanMessagePromptTemplate)
|
233 |
+
SYSTEM_PROMPT_TEMPLATE = "You're a helpfull assistant."
|
234 |
+
HUMAN_PROMPT_TEMPLATE = "Human: {question}\n AI answer:"
|
235 |
+
prompt = ChatPromptTemplate.from_messages(
|
236 |
+
[
|
237 |
+
SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT_TEMPLATE),
|
238 |
+
HumanMessagePromptTemplate.from_template(HUMAN_PROMPT_TEMPLATE)
|
239 |
+
]
|
240 |
+
)
|
241 |
+
print("-===============")
|
242 |
+
llm = CustomAzureOpenAI(deployment_name="binh-gpt",
|
243 |
+
openai_api_key=OPENAI_API_KEY,
|
244 |
+
openai_api_base=OPENAI_API_BASE,
|
245 |
+
openai_api_version=OPENAI_API_VERSION,
|
246 |
+
temperature=0,
|
247 |
+
model_kwargs={"top_p": 1.0},)
|
248 |
+
llm_chain = LLMChain(
|
249 |
+
llm=llm,
|
250 |
+
prompt=prompt
|
251 |
+
)
|
252 |
+
results = llm_chain.predict(question="Hello")
|
253 |
+
print(results)
|
chains/summary.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain.chains import LLMChain
|
2 |
+
from langchain.prompts.chat import (
|
3 |
+
ChatPromptTemplate,
|
4 |
+
SystemMessagePromptTemplate,
|
5 |
+
HumanMessagePromptTemplate)
|
6 |
+
from chains.azure_openai import CustomAzureOpenAI
|
7 |
+
from prompts.summary import system_template, human_template
|
8 |
+
from config import OPENAI_API_TYPE, OPENAI_API_VERSION, OPENAI_API_KEY, OPENAI_API_BASE, DEPLOYMENT_ID
|
9 |
+
|
10 |
+
class WebSummary(LLMChain):
|
11 |
+
prompt = ChatPromptTemplate.from_messages(
|
12 |
+
[SystemMessagePromptTemplate.from_template(
|
13 |
+
system_template),
|
14 |
+
HumanMessagePromptTemplate.from_template(human_template)
|
15 |
+
])
|
16 |
+
llm = CustomAzureOpenAI(deployment_name=DEPLOYMENT_ID,
|
17 |
+
openai_api_type=OPENAI_API_TYPE,
|
18 |
+
openai_api_base=OPENAI_API_BASE,
|
19 |
+
openai_api_version=OPENAI_API_VERSION,
|
20 |
+
openai_api_key=OPENAI_API_KEY,
|
21 |
+
temperature=0.0)
|
chains/web_search.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain.chains.llm import LLMChain
|
2 |
+
from langchain.prompts.chat import (
|
3 |
+
ChatPromptTemplate,
|
4 |
+
SystemMessagePromptTemplate,
|
5 |
+
HumanMessagePromptTemplate)
|
6 |
+
from prompts.web_search import SYSTEM_PROMPT_TEMPLATE, HUMAN_PROMPT_TEMPLATE
|
7 |
+
from config import OPENAI_API_TYPE, OPENAI_API_VERSION, OPENAI_API_KEY, OPENAI_API_BASE, DEPLOYMENT_ID
|
8 |
+
from chains.azure_openai import CustomAzureOpenAI
|
9 |
+
|
10 |
+
class GoogleWebSearch(LLMChain):
|
11 |
+
llm = CustomAzureOpenAI(deployment_name=DEPLOYMENT_ID,
|
12 |
+
openai_api_type=OPENAI_API_TYPE,
|
13 |
+
openai_api_base=OPENAI_API_BASE,
|
14 |
+
openai_api_version=OPENAI_API_VERSION,
|
15 |
+
openai_api_key=OPENAI_API_KEY,
|
16 |
+
temperature=0.0)
|
17 |
+
prompt = ChatPromptTemplate.from_messages(
|
18 |
+
[
|
19 |
+
SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT_TEMPLATE),
|
20 |
+
HumanMessagePromptTemplate.from_template(HUMAN_PROMPT_TEMPLATE)
|
21 |
+
])
|
config.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
# Folder
|
4 |
+
HISTORY_DIR = "history"
|
5 |
+
SAVE_DIR = "documents"
|
6 |
+
|
7 |
+
if not os.path.exists(HISTORY_DIR):
|
8 |
+
os.makedirs(HISTORY_DIR)
|
9 |
+
|
10 |
+
if not os.path.exists(SAVE_DIR):
|
11 |
+
os.makedirs(SAVE_DIR)
|
12 |
+
|
13 |
+
# Whisper API
|
14 |
+
API_KEY = "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"
|
15 |
+
MODEL_ID = "whisper-1"
|
16 |
+
|
17 |
+
# Azure endpoint
|
18 |
+
OPENAI_API_TYPE = "azure"
|
19 |
+
OPENAI_API_VERSION = "2023-05-15"
|
20 |
+
# Embedding openai
|
21 |
+
EMBEDDING_API_KEY = "e672d672cf2d4c778e352e2f88271ebc"
|
22 |
+
EMBEDDING_API_BASE = "https://qaigpt2.openai.azure.com/"
|
23 |
+
EMBEDDING_DEPLOYMENT_ID = "embed"
|
24 |
+
# ChatGPT
|
25 |
+
OPENAI_API_KEY = "1941ec6a33bd405bac7f2f800b10d171"
|
26 |
+
OPENAI_API_BASE ="https://qaigptjp.openai.azure.com/"
|
27 |
+
DEPLOYMENT_ID = "gpt"
|
28 |
+
|
29 |
+
# Pinecone vector DB
|
30 |
+
PINECONE_API_KEY = "82b9902a-2908-4ece-88bf-483c413a91d7"
|
31 |
+
PINECONE_ENVIRONMENT = "us-west1-gcp-free"
|
32 |
+
INDEX_NAME = "text-indexing"
|
33 |
+
|
34 |
+
|
35 |
+
# Google search API
|
36 |
+
GOOGLE_API_KEY="AIzaSyBcwB4YIqjDcYr5XnPt5IrktqbH4Mb_1hE"
|
37 |
+
GOOGLE_CSE_ID="e61c62a86e2b848fd"
|
38 |
+
|
39 |
+
# Custom google search API
|
40 |
+
CUSTOM_API_KEY = "AIzaSyDycFFOFtPg123bm9N3BRCy_q5gyEk7fzs"
|
41 |
+
CUSTOM_CSE_ID = "3364dacc2a4144b22"
|
42 |
+
|
43 |
+
# Local host
|
44 |
+
TIMEOUT_STREAM = 60
|
45 |
+
SEVER = "0.0.0.0"
|
46 |
+
PORT = 7860
|
47 |
+
DEBUG = True
|
custom.css
DELETED
@@ -1,239 +0,0 @@
|
|
1 |
-
:root {
|
2 |
-
--chatbot-color-light: #F3F3F3;
|
3 |
-
--chatbot-color-dark: #121111;
|
4 |
-
}
|
5 |
-
|
6 |
-
/* 覆盖gradio的页脚信息QAQ */
|
7 |
-
footer {
|
8 |
-
display: none !important;
|
9 |
-
}
|
10 |
-
#footer{
|
11 |
-
text-align: center;
|
12 |
-
}
|
13 |
-
#footer div{
|
14 |
-
display: inline-block;
|
15 |
-
}
|
16 |
-
#footer .versions{
|
17 |
-
font-size: 85%;
|
18 |
-
opacity: 0.85;
|
19 |
-
}
|
20 |
-
|
21 |
-
/* status_display */
|
22 |
-
#status_display {
|
23 |
-
display: flex;
|
24 |
-
min-height: 2.5em;
|
25 |
-
align-items: flex-end;
|
26 |
-
justify-content: flex-end;
|
27 |
-
}
|
28 |
-
#status_display p {
|
29 |
-
font-size: .85em;
|
30 |
-
font-family: monospace;
|
31 |
-
color: var(--body-text-color-subdued);
|
32 |
-
}
|
33 |
-
|
34 |
-
#chuanhu_chatbot, #status_display {
|
35 |
-
transition: all 0.6s;
|
36 |
-
}
|
37 |
-
|
38 |
-
/* usage_display */
|
39 |
-
#usage_display {
|
40 |
-
position: relative;
|
41 |
-
margin: 0;
|
42 |
-
box-shadow: var(--block-shadow);
|
43 |
-
border-width: var(--block-border-width);
|
44 |
-
border-color: var(--block-border-color);
|
45 |
-
border-radius: var(--block-radius);
|
46 |
-
background: var(--block-background-fill);
|
47 |
-
width: 100%;
|
48 |
-
line-height: var(--line-sm);
|
49 |
-
min-height: 2em;
|
50 |
-
}
|
51 |
-
#usage_display p, #usage_display span {
|
52 |
-
margin: 0;
|
53 |
-
padding: .5em 1em;
|
54 |
-
font-size: .85em;
|
55 |
-
color: var(--body-text-color-subdued);
|
56 |
-
}
|
57 |
-
.progress-bar {
|
58 |
-
background-color: var(--input-background-fill);;
|
59 |
-
margin: 0 1em;
|
60 |
-
height: 20px;
|
61 |
-
border-radius: 10px;
|
62 |
-
overflow: hidden;
|
63 |
-
}
|
64 |
-
.progress {
|
65 |
-
background-color: var(--block-title-background-fill);;
|
66 |
-
height: 100%;
|
67 |
-
border-radius: 10px;
|
68 |
-
text-align: right;
|
69 |
-
transition: width 0.5s ease-in-out;
|
70 |
-
}
|
71 |
-
.progress-text {
|
72 |
-
/* color: white; */
|
73 |
-
color: var(--color-accent) !important;
|
74 |
-
font-size: 1em !important;
|
75 |
-
font-weight: bold;
|
76 |
-
padding-right: 10px;
|
77 |
-
line-height: 20px;
|
78 |
-
}
|
79 |
-
/* list */
|
80 |
-
ol:not(.options), ul:not(.options) {
|
81 |
-
padding-inline-start: 2em !important;
|
82 |
-
}
|
83 |
-
|
84 |
-
/* 亮色 */
|
85 |
-
@media (prefers-color-scheme: light) {
|
86 |
-
#chuanhu_chatbot {
|
87 |
-
background-color: var(--chatbot-color-light) !important;
|
88 |
-
color: #000000 !important;
|
89 |
-
}
|
90 |
-
[data-testid = "bot"] {
|
91 |
-
background-color: #FFFFFF !important;
|
92 |
-
}
|
93 |
-
[data-testid = "user"] {
|
94 |
-
background-color: #95EC69 !important;
|
95 |
-
}
|
96 |
-
}
|
97 |
-
/* 暗色 */
|
98 |
-
@media (prefers-color-scheme: dark) {
|
99 |
-
#chuanhu_chatbot {
|
100 |
-
background-color: var(--chatbot-color-dark) !important;
|
101 |
-
color: #FFFFFF !important;
|
102 |
-
}
|
103 |
-
[data-testid = "bot"] {
|
104 |
-
background-color: #2C2C2C !important;
|
105 |
-
}
|
106 |
-
[data-testid = "user"] {
|
107 |
-
background-color: #26B561 !important;
|
108 |
-
}
|
109 |
-
body {
|
110 |
-
background-color: var(--neutral-950) !important;
|
111 |
-
}
|
112 |
-
}
|
113 |
-
|
114 |
-
/* 对话气泡 */
|
115 |
-
[class *= "message"] {
|
116 |
-
border-radius: var(--radius-xl) !important;
|
117 |
-
border: none;
|
118 |
-
padding: var(--spacing-xl) !important;
|
119 |
-
font-size: var(--text-md) !important;
|
120 |
-
line-height: var(--line-md) !important;
|
121 |
-
min-height: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl));
|
122 |
-
min-width: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl));
|
123 |
-
}
|
124 |
-
[data-testid = "bot"] {
|
125 |
-
max-width: 85%;
|
126 |
-
border-bottom-left-radius: 0 !important;
|
127 |
-
}
|
128 |
-
[data-testid = "user"] {
|
129 |
-
max-width: 85%;
|
130 |
-
width: auto !important;
|
131 |
-
border-bottom-right-radius: 0 !important;
|
132 |
-
}
|
133 |
-
/* 表格 */
|
134 |
-
table {
|
135 |
-
margin: 1em 0;
|
136 |
-
border-collapse: collapse;
|
137 |
-
empty-cells: show;
|
138 |
-
}
|
139 |
-
td,th {
|
140 |
-
border: 1.2px solid var(--border-color-primary) !important;
|
141 |
-
padding: 0.2em;
|
142 |
-
}
|
143 |
-
thead {
|
144 |
-
background-color: rgba(175,184,193,0.2);
|
145 |
-
}
|
146 |
-
thead th {
|
147 |
-
padding: .5em .2em;
|
148 |
-
}
|
149 |
-
/* 行内代码 */
|
150 |
-
code {
|
151 |
-
display: inline;
|
152 |
-
white-space: break-spaces;
|
153 |
-
border-radius: 6px;
|
154 |
-
margin: 0 2px 0 2px;
|
155 |
-
padding: .2em .4em .1em .4em;
|
156 |
-
background-color: rgba(175,184,193,0.2);
|
157 |
-
}
|
158 |
-
/* 代码块 */
|
159 |
-
pre code {
|
160 |
-
display: block;
|
161 |
-
overflow: auto;
|
162 |
-
white-space: pre;
|
163 |
-
background-color: hsla(0, 0%, 0%, 80%)!important;
|
164 |
-
border-radius: 10px;
|
165 |
-
padding: 1.4em 1.2em 0em 1.4em;
|
166 |
-
margin: 1.2em 2em 1.2em 0.5em;
|
167 |
-
color: #FFF;
|
168 |
-
box-shadow: 6px 6px 16px hsla(0, 0%, 0%, 0.2);
|
169 |
-
}
|
170 |
-
/* 代码高亮样式 */
|
171 |
-
.highlight .hll { background-color: #49483e }
|
172 |
-
.highlight .c { color: #75715e } /* Comment */
|
173 |
-
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
|
174 |
-
.highlight .k { color: #66d9ef } /* Keyword */
|
175 |
-
.highlight .l { color: #ae81ff } /* Literal */
|
176 |
-
.highlight .n { color: #f8f8f2 } /* Name */
|
177 |
-
.highlight .o { color: #f92672 } /* Operator */
|
178 |
-
.highlight .p { color: #f8f8f2 } /* Punctuation */
|
179 |
-
.highlight .ch { color: #75715e } /* Comment.Hashbang */
|
180 |
-
.highlight .cm { color: #75715e } /* Comment.Multiline */
|
181 |
-
.highlight .cp { color: #75715e } /* Comment.Preproc */
|
182 |
-
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
|
183 |
-
.highlight .c1 { color: #75715e } /* Comment.Single */
|
184 |
-
.highlight .cs { color: #75715e } /* Comment.Special */
|
185 |
-
.highlight .gd { color: #f92672 } /* Generic.Deleted */
|
186 |
-
.highlight .ge { font-style: italic } /* Generic.Emph */
|
187 |
-
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
|
188 |
-
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
189 |
-
.highlight .gu { color: #75715e } /* Generic.Subheading */
|
190 |
-
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
|
191 |
-
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
|
192 |
-
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
|
193 |
-
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
|
194 |
-
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
|
195 |
-
.highlight .kt { color: #66d9ef } /* Keyword.Type */
|
196 |
-
.highlight .ld { color: #e6db74 } /* Literal.Date */
|
197 |
-
.highlight .m { color: #ae81ff } /* Literal.Number */
|
198 |
-
.highlight .s { color: #e6db74 } /* Literal.String */
|
199 |
-
.highlight .na { color: #a6e22e } /* Name.Attribute */
|
200 |
-
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
|
201 |
-
.highlight .nc { color: #a6e22e } /* Name.Class */
|
202 |
-
.highlight .no { color: #66d9ef } /* Name.Constant */
|
203 |
-
.highlight .nd { color: #a6e22e } /* Name.Decorator */
|
204 |
-
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
|
205 |
-
.highlight .ne { color: #a6e22e } /* Name.Exception */
|
206 |
-
.highlight .nf { color: #a6e22e } /* Name.Function */
|
207 |
-
.highlight .nl { color: #f8f8f2 } /* Name.Label */
|
208 |
-
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
|
209 |
-
.highlight .nx { color: #a6e22e } /* Name.Other */
|
210 |
-
.highlight .py { color: #f8f8f2 } /* Name.Property */
|
211 |
-
.highlight .nt { color: #f92672 } /* Name.Tag */
|
212 |
-
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
|
213 |
-
.highlight .ow { color: #f92672 } /* Operator.Word */
|
214 |
-
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
|
215 |
-
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
|
216 |
-
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
|
217 |
-
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
|
218 |
-
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
|
219 |
-
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
|
220 |
-
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
|
221 |
-
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
|
222 |
-
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
|
223 |
-
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
|
224 |
-
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
|
225 |
-
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
|
226 |
-
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
|
227 |
-
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
|
228 |
-
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
|
229 |
-
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
|
230 |
-
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
|
231 |
-
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
|
232 |
-
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
|
233 |
-
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
|
234 |
-
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
|
235 |
-
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
|
236 |
-
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
|
237 |
-
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
|
238 |
-
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
|
239 |
-
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
"{\"pfbid0bL6K1WG4WksXbC2rN4xzUnnNTTXeiv87rJyZSQCSF95wKfqQ3XAVWaRKbV5E7Ptil\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 8, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 8, \"comments\": 1, \"content\": \"AMARAN RIBUT PETIR. Ribut petir, hujan lebat dan angin kencang dijangka di negeri Perlis \u2022 Kedah (Langkawi, Kubang Pasu, Kota Setar dan Padang Terap) \u2022 Pulau Pinang \u2022 Terengganu (Besut, Setiu, Kuala Nerus dan Kuala Terengganu) sehingga 4:00 petang; Rabu, 26 Julai 2023.Amaran dikeluarkan apabila terdapat tanda-tanda menunjukkan ribut petir dengan intensiti hujan melebihi 20 mm/jam yang hampir ATAU dijangka berlaku melebihi sejam. Amaran ribut petir adalah amaran jangka pendek yang sah dalam tempoh tidak melebihi enam jam untuk satu-satu keluaran.Dikeluarkan pada: 1:25 tengah hari, 26 Julai 2023#ributpetirmetmalaysia#metmalaysia#NRECC#MalaysiaMADANI\", \"posted_on\": \"2023-07-26T12:58:19.905715\", \"video\": [], \"image\": [\"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/362914619_677866284383689_33145274970187979_n.jpg?stp=dst-jpg_p180x540&_nc_cat=102&ccb=1-7&_nc_sid=730e14&_nc_ohc=AcndcfG_n1YAX_HIiLt&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfCkYSj5ycx5NfloaoYBrW36iOfS6wDzF4JieUPENxVy8w&oe=64C5E08C\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0bL6K1WG4WksXbC2rN4xzUnnNTTXeiv87rJyZSQCSF95wKfqQ3XAVWaRKbV5E7Ptil?__cft__[0]=AZXxrrcdLEIFgRlM0QT4J_sr1nDzaJa5s5iBnAc0kZsacRt7UhHugMUG1RV-HOX6gcMuwTKFXwTgRRESYATnLvK-gjp1dB-wSPPltOtZ9u9J_t4NMriCv2A8cb7UWEmWL3rm4pCFRw31vva5sF7gPXDUlmRM6YH20ikbfVA0PUUJ-x3xUXxSw5AKv7KakA5OgCIoplRHyh1rg7IDcU4gtpu_pef6ZQWazgdoQvPXKi-Z8r_LrUp6TtYEZu4K2k_aP6s&__tn__=%2CO%2CP-R\"}, \"pfbid0trQFPXpjvP5wBYLKaCCJ5CMSvzJMzLwc4gApwhnepaEj67XSpo5AFTfwexNsPBzLl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 7, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 7, \"comments\": 1, \"content\": \"SESI JENDELA PELANGGAN MBPPAnda dialu-alukan untuk menyertai Sesi Jendela Pelanggan pada 27 Julai 2023 (Khamis) bagi mengajukan sebarang aduan, pertanyaan ataupun cadangan kepada kami.Sila daftar pada pautan ini selewat-lewatnya pada 26 Julai 2023 (Rabu) jam 4.30 petang dan pihak urusetia akan menghubungi anda. https://forms.gle/Pn9SBHBeHC4j3up56#jendelapelanggan#bilangan07#aduanmbpp#mbpp\", \"posted_on\": \"2023-07-26T09:58:25.356447\", \"video\": [], \"image\": [\"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/362922220_701092018729018_2536095607797190940_n.jpg?stp=dst-jpg_p180x540&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=zmchy6xDUrcAX8Sx-p-&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfCloGPgFHMuWyAZsWG36ahDRJUV9ZkM5_DPPtAKgylM4Q&oe=64C5E5DE\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0trQFPXpjvP5wBYLKaCCJ5CMSvzJMzLwc4gApwhnepaEj67XSpo5AFTfwexNsPBzLl?__cft__[0]=AZUyMXgb-borS8E3PmF2F-f1z6rnhUtnCKrVDgqpQ1nZPY4s0IUD2ICSznn-Afl_mhp3QEUF4oC1rzsHVVs4SI-9NJ5XJUeA5SpFYqU9Nl4AohyVhGDz_A6_XcWVJRd3vfZz0ak770MRrZZ6iNcRfVkzNvOsG9HrVs_zbRDk1TqxFU1Lpr1qofYCPaRNWAd_XRRXlve5gJNl2oe65kqpd0_4&__tn__=%2CO%2CP-R\"}, \"pfbid0RYJrNbkg5cC53f5sLgUAMZgbZDRPcYJADvLy7MeVcm2eYRQZ2RCp9Km1b1EREhTXl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 20, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 20, \"comments\": 2, \"content\": \"DATUK BANDAR MBPP TERIMA KUNJUNGAN HORMAT DELEGASI PERTUBUHAN ARKITEK MALAYSIA,NORTHERN CHAPTER25 Julai 2023YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar Majlis Bandaraya Pulau Pinang amat berbesar hati dan mengalu-alukan kunjungan hormat Dato' Ar. Loh Chiak Eong, Presiden Pertubuhan Arkitek Malaysia, Northern Chapter bersama barisan delegasi. Pertemuan yang amat bermakna hari ini membincangkan hala tuju serta kerjasama strategik yang diangkat bersama dalam mempertingkatkan kualiti taraf hidup penduduk di Pulau Pinang selaras dengan visi Kerajaan Negeri Pulau Pinang. Pertemuan yang telah diadakan bertempat di Bilik Perdana Majlis Bandaraya Pulau Pinang Aras 4, KOMTAR, Pulau Pinang turut dihadiri Pengarah Kawalan Bangunan - Encik Rizuwan Salleh, Pengarah Perancangan Pembangunan - Tpr. Mohd Bashir Bin Sulaiman, Pengarah Konservasi Warisan - Puan Lee Tit Kun, Timbalan Pengarah Kejuruteraan - Encik Zainuddin Bin Mohd Shariff, Ketua Arkitek - Encik Tan Lin Hai dan Arkitek Landskap - Puan Hajah Nor Rezan Binti Sulaiman.\", \"posted_on\": \"2023-07-25T17:58:25.527738\", \"video\": [], \"image\": [\"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/361589801_700647228773497_3360174847855652712_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=OcNb7qO8GDsAX848AOj&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfBkqTAbtQ-ammOujDS2dAhe8oTL41OXQ1U2TKQeewoMzA&oe=64C56E99\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362618945_700647278773492_5015617466471678597_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=n4ToAYkB_jkAX-REa_n&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfDDM5eBqbyxjhi7KNV6M-uFRRJ2TjWqU-tJEiDR2PdrVg&oe=64C69C8D\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362688960_700647302106823_966226846173849865_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=nrKpXXTUGf8AX_-Yi95&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfApmzE8SdcMwG8Ht7OokWcawbYTEEgigFdyHEu4L0fWHA&oe=64C651C5\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/361583990_700647318773488_2904764889062170237_n.jpg?stp=dst-jpg_p526x395&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=8UPm0AK0tBwAX83rJZX&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfAuHGVpeTr4QblrQAPFp6Kdv5b1Bhg7vRbQXgf4R6NMaw&oe=64C6D33F\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361615395_700647342106819_5776684050650670196_n.jpg?stp=dst-jpg_s600x600&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Aov6JS5rbbQAX9C-npi&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfD6W5q356V05645Uomy8q4E6hEA2CIZS_eFsUgW9Nj9Dg&oe=64C65766\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0RYJrNbkg5cC53f5sLgUAMZgbZDRPcYJADvLy7MeVcm2eYRQZ2RCp9Km1b1EREhTXl?__cft__[0]=AZWkpcf0Nln3YZ_mXvdqw5AGLBiXgFTC4CL2h3KhCuhhgxXpYIP5Enhf9QBNFnXjmD51txDq2cMm3ZkjWDB3Uq3IErctGLAwii_66F_-DbIVQIOhkRMGiQTuuyoqRu0dnY6ZCzF6ff9pBl6BVn61zjRAlYUkbOAWbi0s-BqO1jD4607eMwjhjd_j1QfkcLyWWl2ICP0pSeE-keA5AZMBLnfI&__tn__=%2CO%2CP-R\"}, \"pfbid02kkoBrqZgVy9iJ2A6LaMxptTNqBh9AGZeXGKnYU5LmP3xTLw71UsgYZMTA3YPPn8Al\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 13, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 13, \"comments\": 25, \"content\": \"MAKLUMAN UMUM PENUTUPAN SEMENTARA SEBAHAGIAN JALAN PERAK (PERSIMPANGAN ANTARA JALAN PANGKOR, LEBUHRAYA PEEL DAN JALAN PERAK)DAERAH TIMUR LAUT PULAU PINANG#maklumanumum#penutupansementara#jalanpangkor\", \"posted_on\": \"2023-07-25T17:58:25.737254\", \"video\": [], \"image\": [\"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/361885206_700528988785321_430392079782812923_n.jpg?stp=dst-jpg_p417x417&_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=5VHlLoiZaNMAX9joHGW&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfAIhTa1sIAeR7fNPZBvN8FvOlE8w9jYIOholMBXTehuvQ&oe=64C58F8C\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/361950036_700529002118653_2056017328874695579_n.jpg?stp=dst-jpg_p552x414&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=YoZyyhAixtoAX_pK_QB&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfB_f9d8gdok8Ggom_KZ5rLpTjDWpZnU07i7pEFHsqtRKw&oe=64C5D856\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362666857_700529028785317_3669243307978518231_n.jpg?stp=dst-jpg_p552x414&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=cieIIntRj0YAX8H1wni&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCvfjDY1YBQz3nAM8KHrUdHGUmAsh6ZxyTwr94y58Ol3A&oe=64C6C145\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361940891_700529045451982_8224188709230313821_n.jpg?stp=dst-jpg_p417x417&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=BwzTcA4FRxoAX8azMwD&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfCNYkpj2bgdvqEJ1WPBlBZ6PotqcTCyDsH68pHT1qC_wg&oe=64C61CD4\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02kkoBrqZgVy9iJ2A6LaMxptTNqBh9AGZeXGKnYU5LmP3xTLw71UsgYZMTA3YPPn8Al?__cft__[0]=AZXBrIIGxpfal3Z0luNHoIVLu2KAFlza75XJcyxTDm97S6OLZ79RJOTYZ_aGf-xCl9I39ghWDtdj4TkoiarAJSBPnAKEzKJmksvEPQtDdi0XuQof0RAGSjJiN9sk-pOGchJMWTFJ9AI3TdnsF3Nc5K3RRTmYCS0fyZDTBeeekThuewh7vn8VM2b6_66DaQD97sXpW53OPGq9gDsKcwlhnRIY&__tn__=%2CO%2CP-R\"}, \"pfbid03F3SdqpeAkehQaJKfzBLWhxpqfxgt2GgibaBRU1Y25uS9rsTN52fwJedxpP6yx7fl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 25, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 25, \"comments\": 9, \"content\": \"KENYATAAN MEDIAPENGOPERASIAN BANGUNAN TEMPAT LETAK KERETA BERTINGKAT DI BELAKANG PASAR AWAM BATU LANCANG, BANDAR JELUTONG, DAERAH TIMUR LAUT, PULAU PINANG.24 Julai 2023Majlis Bandaraya Pulau Pinang (MBPP) ingin memaklumkan bahawa Bangunan Tempat Letak Kereta Bertingkat di belakang Pasar Awam Batu Lancang akan dibuka kepada orang awam mulai 25 Julai 2023 (Selasa), jam 8:00 pagi. Bangunan Tempat Letak Kereta tersebut akan beroperasi secara 24 jam. Bangunan enam tingkat ini yang mempunyai 223 petak tempat letak kereta akan dibuka kepada orang ramai secara PERCUMA sehingga ke satu tarikh yang akan dimaklumkan kelak. Orang awam boleh mengakses bangunan tersebut dari belakang Pasar Batu Lancang.Pembukaan Bangunan Tempat Letak Kereta tersebut dijangka dapat menampung keperluan orang ramai terutamanya dalam permasalahan kekurangan petak letak kereta di kawasan sekitar Pasar Awam Batu Lancang. MBPP berharap agar orang awam, terutamanya pengguna dapat memberi kerjasama dalam mengguna dan menjaga kemudahan yang disediakan.Sekian, terima kasih.Dikeluarkan oleh :Bahagian Komunikasi Korporat dan Perhubungan Awam,Jabatan Pengurusan Korporat dan Komuniti,Majlis Bandaraya Pulau PinangBertarikh : 24 Julai 2023\", \"posted_on\": \"2023-07-25T17:58:32.216849\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/362684071_700112485493638_6490033210307187634_n.jpg?stp=dst-jpg_s720x720&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=jfOYM2GPBCsAX8_KGLD&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfDlW55FWBmCQTJj-tWX1reHvXJYp0xLRykOYBZvR5WDYg&oe=64C571E5\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid03F3SdqpeAkehQaJKfzBLWhxpqfxgt2GgibaBRU1Y25uS9rsTN52fwJedxpP6yx7fl?__cft__[0]=AZVZ0UKFQGKE9dO0rwTpBbbbi9oWuSl2ccVVWIPwL9U0K2736YOJG-znfXBVkEBrKPrL1GwKSjF6ONsPOGkhx2rsuRTo4ZEr33yLKmixqW1zb6rVjzdikcRbheqXFbxOvKrSPyHEK7_XhYjB8rD7sDqe7qPot_rMW26mSHSK4b3F9X8CZy0iNtWREWpzxLjVylRGYi7k4EQoXXDWgUU46bFW&__tn__=%2CO%2CP-R\"}, \"pfbid02EigDvePjJuyhwmiFn8N625wpNX3h5sHWnaVFwoJC2GALZR5THuwSWiaZKKCyspz2l\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 29, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 29, \"comments\": 2, \"content\": \"SETIAUSAHA BANDARAYA DAN AHLI MAJLIS MBPP MENYANTUNI KELUARGA MANGSA AKIBAT KEMALANGAN POKOK TUMBANG24 Julai 2023Majlis Bandaraya Pulau Pinang yang diwakili YBrs. Sr. Cheong Chee Hong, Setiausaha Bandaraya bersama Ahli Majlis Encik Quah Boon Lim serta barisan ketua-ketua jabatan dengan perasaan rendah diri hari ini telah menziarahi seorang mangsa yang terlibat dalam kemalangan akibat pokok tumbang dan menghempap bahagian di belakang rumah mangsa. Kejadian tersebut berpunca akibat hujan lebat serta angin kencang yang berlaku pada awal pagi Sabtu yang lalu (22 Julai 2023) dan dilaporkan sebanyak dua buah rumah di kawasan Lintang Delima telah mengalami kerosakan. Susulan itu, mangsa yang cedera telah dibawa oleh ahli keluarga ke hospital untuk menerima rawatan sewajarnya di sebuah hospital swasta.Majlis Bandaraya Pulau Pinang menzahirkan rasa simpati dan takziah kepada seluruh keluarga mangsa yang terlibat di samping akan menyalurkan sumbangan wang tunai bagi membantu meringankan beban kos pembaikan.\", \"posted_on\": \"2023-07-24T17:58:32.390422\", \"video\": [], \"image\": [\"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362683530_700028038835416_7605803971882575798_n.jpg?stp=dst-jpg_s600x600&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=KUUzkrq69zMAX-pcUbN&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfD-wkzDGhyLFtU5ExS6OfKVCp6SNw4tFgQiN-rZuSDu2Q&oe=64C69AFC\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361202440_700028075502079_1534549892103331750_n.jpg?stp=dst-jpg_s600x600&_nc_cat=106&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qPz6XdivpiIAX8fymT3&_nc_oc=AQn4YYqTP1xb0KllsIHI-8cLN1s346Q8ZV41s1gzhuIf-neBKs3k3CWgiuiClzTJeS4&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfB1J49Kae6v8BfeCbnF_Y0jTrjfDnsqAGTLspVPOVILwA&oe=64C64CF3\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/361282688_700028095502077_4816978841061704015_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=kbDIaz7HuzoAX-7Clyl&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfD8Z5ctqQGazoIaX2q4D9EtA2C2T397wQLpbdGSqkgcAg&oe=64C64D16\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362681824_700028112168742_1173937444798386479_n.jpg?stp=dst-jpg_s600x600&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=k0q2xsg8qzMAX-mhPKP&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCjNSEuwOORE-GHP_51RWBoO69Dbtv8CqcMazj8ohpTug&oe=64C502C9\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02EigDvePjJuyhwmiFn8N625wpNX3h5sHWnaVFwoJC2GALZR5THuwSWiaZKKCyspz2l?__cft__[0]=AZUTiK34Fwdcli7Vms2WqNXc0PpwU48tjm5uoruT7_aaSlt-b5Fwd4dcdFkEtLX6Md6P7dJQWmppPJyOdo6IGtPM_wWGEMJ_W7cy30bFF4vLI7s-aCwdYnANWuCk6QD0FzBH-EQdNklxTI78i3I7yICbcIFiavJIxK7mYMK2Yn2oQtYaEbDSMYt7URuItNZmxuP8gzAb52OwqdIy5V647ni2&__tn__=%2CO%2CP-R\"}, \"pfbid02LZEE49iB6R4miMgufE7FCPM3SAKH92m3r4UjPV78R2FQEusEdCRdrQrAg8s8Pdd9l\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 2, \"reactions\": {\"likes\": 63, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 63, \"comments\": 1, \"content\": \"PROGRAM PENANAMAN BAKAU PERINGKAT MAJLIS BANDARAYA PULAU PINANG BAGI TAHUN 2023 DI KAWASAN PAYA BAKAU HUTAN SIMPAN BALIK PULAU 23 JULAI 2023Majlis Bandaraya Pulau Pinang merakamkan setinggi-tinggi penghargaan dan jutaan terima kasih kepada YB Tuan Jagdeep Singh Deo a/l Karpal Singh, EXCO Perumahan, Kerajaan Tempatan dan Perancangan Bandar dan Desa yang telah menyempurnakan Program Penanaman Bakau Peringkat Majlis Bandaraya Pulau Pinang Bagi Tahun 2023 yang diadakan hari ini bertempat di kawasan paya bakau Hutan Simpan Balik Pulau (Jalan Baru Sungai Kongsi). Majlis Bandaraya Pulau Pinang telah menyediakan sebanyak 1,300 batang anak pokok bakau spesis api-api manakala pihak Exabytes Group/EasyParcel telah menyumbang 1,000 batang anak pokok bakau dan Jabatan Perhutanan Negeri Pulau Pinang turut menyumbang sebanyak 1,000 batang anak pokok bakau.Sejak tahun 2018 sehingga Jun 2023, Majlis Bandaraya Pulau Pinang telah menanam sebanyak 88,350 pokok di seluruh kawasan pulau, Pulau Pinang dan pada hari ini ditambah lagi dengan penanaman sebanyak 3,300 batang anak pokok bakau.Keseluruhan jumlah pokok yang ditanam di Pulau Pinang telah mencapai jumlah sebanyak 442,936 pokok sejak 2008. Agenda hijau ini akan teruskan sehingga mencapai sasaran 500,000 pokok di tanam di seluruh negeri sebagai salah satu langkah persediaan Pulau Pinang mengawal peningkatan mendadak perubahan iklim. Hadir pada program hijau ini adalah YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar bersama barisan Ahli Majlis-Ahli Majlis, YBrs. Sr. Cheong Chee Hong, Setiausaha Bandaraya, ketua-ketua jabatan, para pegawai dan wira-wira baju hijau Majlis Bandaraya Pulau Pinang. Turut hadir pada program ini adalah wakil dari pihak penaja iaitu Cik Lim Ying Hwa - Corporate Legal Manager of Exabytes Group dan Encik Joseph Chew Chin MengMarketing Team Lead of EasyParcel. Manakala Encik Ir. Dzulhilmi bin Zulkifli, Jurutera Awam yang mewakili Jabatan Kerja Raya, Cawangan Jalan (Unit Projek Khas Zon Utara 3) dan pegawai Jabatan Perhutanan Negeri Pulau Pinang turut hadir memberi sokongan kepada program hari iniKerajaan Negeri Pulau Pinang menerusi Majlis Bandaraya Pulau Pinang amat mengalu-alukan penyertaan dan penglibatan lebih banyak Persatuan dan Pertubuhan Bukan Kerajaan serta jabatan-jabatan dan agensi kerajaan di seluruh kawasan Pulau Pinang bagj memperkasakan usaha untuk membendung peningkatan mendadak perubahan iklim.\", \"posted_on\": \"2023-07-23T17:58:32.569121\", \"video\": [], \"image\": [\"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/360162982_699412785563608_6841802677807497668_n.jpg?stp=dst-jpg_p526x395&_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=bWYKMdXaBZYAX9jhqnl&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfCsUrfqk83RHptZLP4l-lZ0CtRhHLkwc_lySKYK8Ap3rA&oe=64C5B149\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361173237_699412945563592_6618748741275388125_n.jpg?stp=dst-jpg_s600x600&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=n7JlNvSP1M4AX9eaXdN&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfDxlP-m5pPoloNxAH_gFrbINcOWxC9twTXigFYB3yYMSA&oe=64C5F578\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362646250_699412968896923_9194157420572023411_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=R43ieVYZjOwAX_yh28G&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfDJYM298W2SpvuT5ZYGLFKCD8TpNTSg3YrZOPYw70ir1g&oe=64C521BC\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360155689_699412988896921_7841179063496481138_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=dOAd3tiCQZAAX_fKlWs&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCJbll2XYN2b1iWHwQU9PqqdqHLFyc32qAAktmlTeMBeA&oe=64C59B27\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361178340_699413002230253_9013619835535210897_n.jpg?stp=dst-jpg_p526x395&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qd4ZoRzAZCkAX8uT-LQ&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAQNEBhS96902Cp0l9fk8KbrVbrraMOX4Gz9vPl62rh9g&oe=64C577F3\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02LZEE49iB6R4miMgufE7FCPM3SAKH92m3r4UjPV78R2FQEusEdCRdrQrAg8s8Pdd9l?__cft__[0]=AZXX7ByUelE699FtcKWIoFCYhVpKe1MeBtuXzAssG8dfI0ELt1D8LKXOGtqmzlLsgOkHVRZTXKS7cr1sj7vtPRjMHSq6LoC32L8vHQ_rGUDwTRGwS92ppsZk52HYevLVNwW3MzPKqd6WXh9_nuEc3UMXvSIjPYrPefejV2VwFFbo6YqgOv9UzfcX8lvsiLC8ljcbRoRepWtFpRwSjEIpjVdo&__tn__=%2CO%2CP-R\"}, \"pfbid0Jufsa3DYCakcSgTKFVxQPabndEAybYJN6LwXNmwM9EUQJEujK2QYJ7HpzuABaoK7l\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 8, \"reactions\": {\"likes\": 42, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 42, \"comments\": 1, \"content\": \"PROGRAM TNR BERSAMA-\\\"SAMA\\\" TUMPU KEBAJIKAN KUCING TERBIAR DI JALANAN22 Julai 2023Prihatin terhadap kebajikan kucing-kucing yang terbiar di jalanan, penganjuran Program TNR Bersama - SAMA yang dirasmikan oleh YB Syerleena Abdul Rashid, Ahli Parlimen Bukit Bendera (Mantan Adun Seri Delima) telah membuka sebuah lembaran yang amat bermakna.Program yang diadakan di Gelanggang Bola Keranjang Island Glades bertujuan untuk membuka ruang perhatian dan kesedaran kepada orang awam terhadap usaha dan tindakan yang perlu dilaksanakan bagi menyelamatkan haiwan comel itu daripada menerima nasib malang.Sebagai Pihak Berkuasa Tempatan yang peka dan mengambil perhatian terhadap isu seumpama ini, Datuk Bandar, YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar bersama barisan Ahli Majlis Cik Connie Tan, Encik Quah Boon Lim, Encik Rohaizat Hamid dan Cik Nurhafiza Huda Idris turut hadir sebagai sokongan penuh terhadap program ini.Majlis Bandaraya Pulau Pinang mengalu-alukan dan akan memberi sokongan kepada bukan sahaja kepada Pertubuhan SAMA - (Spay Adopt Manage Assist Society) malahan kepada semua persatuan-persatuan, pertubuhan bukan kerajaan dan agensi-agensi yang menyumbang masa, tenaga dan kepakaran serta peranan penting dalam memastikan program TNR (Trap Neuter Rehome) berjaya dilaksanakan hingga mencapai sasaran yang membanggakan.\", \"posted_on\": \"2023-07-23T17:58:39.072516\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/362638083_699005078937712_3416986764543683977_n.jpg?stp=dst-jpg_p526x395&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Lz-tHoUBF0wAX8J7ibR&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAG2KtNAjNJKSKpTHaFebrysJz5Cmj3T15OE6Lxt6wXRQ&oe=64C5A1C2\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/362612448_699005205604366_4280290885472827984_n.jpg?stp=dst-jpg_p526x395&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Pqli4RmTgyYAX_Lu7Nl&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfD856hZPcR7WAb7czA_YAZ28889WRY0MdP5ZgFV9-_v8Q&oe=64C60A52\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/360146719_699005238937696_3768431308898304664_n.jpg?stp=dst-jpg_p526x395&_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Lo_d1HbHKTAAX_NkDkj&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfB4q8K8tJ2QEA5MU2Z7GmbzgffX8DyT7oeNtOqQClO7xw&oe=64C55DAC\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360121604_699005252271028_5751256982783019845_n.jpg?stp=dst-jpg_p526x395&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=LlFXWrmEwVAAX_0xEpe&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCf24kyq4Qlhzt6S82st6JYqvcTD5e5Tvn-XyIdyPDNBw&oe=64C591CE\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/362227688_699005295604357_9099856387291898074_n.jpg?stp=dst-jpg_p526x395&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=y5_M2PBaJDcAX9n7uKl&_nc_oc=AQlMfj1AoVGuem-OEulZtu4oKgzXSq5_xMI-Fz5NLVCz7bkNpoN2pcN1b39TKp3-M2M&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfAmfejvb9AaWaDJBsPljkEF5e36ZH1bTyKy1EIbgQfxig&oe=64C56295\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0Jufsa3DYCakcSgTKFVxQPabndEAybYJN6LwXNmwM9EUQJEujK2QYJ7HpzuABaoK7l?__cft__[0]=AZUM2ApFIY264AjUuvGLXUQdXFe6kcrscf1e58cYB2jHE95itfnn9DMgmxdEZKXHLWsKbxL4NUCyDcXVv4tGvlHS8cJuqPlgezATSjTPN_c_VxRU3VONOjy1WF_3NOlLcVUh13WpllHo11D0bVXjrcA4S9UEA_RENibPWqv3IDUTy-SCNZzypqnpe5hu8RxKKqiX1f1mZhpTrgu1tFXTJrr9&__tn__=%2CO%2CP-R\"}, \"pfbid036pDFSd7gacTVwBrJq8DjsgU762dq9jTK7sgSFnHAAtUQwUo5x6xiAzwHNZjsyXygl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 1, \"reactions\": {\"likes\": 15, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 15, \"comments\": 1, \"content\": \"SESI LIBAT URUS KAJIAN SEPARUH PENGGAL RANCANGAN MALAYSIA KEDUA BELAS 2021 - 202522 Julai 2023YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar Majlis Bandaraya Pulau Pinang bersama barisan Ahli Majlis iaitu Encik Abdul Latiff Bin Mohamad, Encik Mohd Suhairi Arumugam Bin Abdullah, Encik Hari Krishnan a/l Ramakrishnan, Encik Mohd Faruk Bin Abdul Rahman, Puan Rodziah Binti Abul Kassim, Cik Nurhafiza Huda Binti Idris dan Puan Goh Huey Ee hari ini telah menghadiri Sesi Libat Urus Kajian Separuh Penggal Rancangan Malaysia Kedua Belas (2021 - 2025) bertempat di Hotel Olive Tree, Bayan Baru. YAB Tuan Chow Kon Yeow, Ketua Menteri Pulau Pinang 'caretaker' dalam ucapan beliau memaklumkan bahawa Pulau Pinang telah berjaya mendapat kelulusan sebanyak 75 projek baharu di bawah Rancangan Malaysia Kedua Belas (RMK-12) membabitkan peruntukan berjumlah RM54.14 juta. Kelulusan 75 projek tersebut adalah sebahagian daripada 126 projek yang dimohon oleh Kerajaan Negeri Pulau Pinang di bawah peruntukan Rolling Plan Ketiga RMK-12 sebelum ini.Sesi Libat Urus Kajian Separuh Penggal Rancangan Malaysia Kedua Belas (2021 - 2025) menyaksikan kehadiran Menteri Ekonomi, YB Tuan Mohd. Rafizi Ramli serta Setiausaha Kerajaan Negeri, Dato\u2019 Mohd. Sayuthi Bakar; Ketua Setiausaha Kementerian Ekonomi, Datuk Nor Azmie Diron; barisan ahli Exco \u2018Caretaker\u2019 Kerajaan Negeri.\", \"posted_on\": \"2023-07-23T17:58:39.276732\", \"video\": [], \"image\": [\"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/360128269_698996282271925_8373859058183420792_n.jpg?stp=dst-jpg_p526x395&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=maZi0Xd_S7IAX_6MZTZ&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfCvaS-vTJcuKbCWiaeGKt-SbD8eXokjPb9cFj99_H9CoA&oe=64C545CA\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362604134_698996592271894_4399314558248343384_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=fGBpn2-S1hsAX8HT27z&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfDlKtNNaJO_hVYrq7Y_iG4mTQU1Z5IHqgef1FqIqlUFmQ&oe=64C4F7A7\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/360137883_698996635605223_4817414599037440352_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=MuhENXDr2skAX-_0yQw&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfCAppNS_4Jgr6aGL_ZjoLDyDIulqIQ9tgPRr2Olt-0zaw&oe=64C6B3DC\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/362641464_698996662271887_2184762448622259664_n.jpg?stp=dst-jpg_p526x395&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qHILF1alJYUAX_5i72u&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfA43wpcis2pdTYZDkzbhsgszQi2LcxS72q0YUTJRzk6JQ&oe=64C59381\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362684406_698996022271951_7061396978717357161_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=cGgK8D8AAksAX_WNyyb&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfBHMwUL-8YcUZsgaoj_-q9d2f6V5kllPSQUdsLfuKywwQ&oe=64C67B5A\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid036pDFSd7gacTVwBrJq8DjsgU762dq9jTK7sgSFnHAAtUQwUo5x6xiAzwHNZjsyXygl?__cft__[0]=AZUn1VVr72xGCMsdoLjNCDXQ3t0THPcb76XpqLLKX9EFatIqRBhvtF5TwBiNldsRT31JY6cdTnTHvVAms_l4HM1B5dEodbKRts_KUi7kZZ6I5Qu0OzUvOChwjTLZT0bz8CVy8chBYdxjefmlPSKXVuslzGSd1R6HDetKanEqUFYm9PL-vWbuAbWZmC4UhG_JSpG2Bn0nD-zxzbycKmfmvT2a&__tn__=%2CO%2CP-R\"}, \"pfbid035UTJtKk9aeGHQg2kvdsjfLj3dmRDQzcRcyCJQmmQNUnsWsVAkbTJszHEYqetrVfCl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 16, \"loves\": 0, \"wow\": 0, \"cares\": 1, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 17, \"comments\": 0, \"content\": \"INFO POKOK TUMBANGLEBUHRAYA BAYAN LEPAS 22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:39.527182\", \"video\": [], \"image\": [\"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/360115293_698773255627561_2859260089551737444_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=n0QrRW9KBV4AX_gdUgW&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfAvu8YISZft5o3b5AHdANyFQ5ya22iE2ljJj__mLIJojA&oe=64C60EC2\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/360131132_698773285627558_3560834197011844721_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=_ytkJNYJUTYAX_okmkA&_nc_oc=AQniz271MWPtMt-03C_bvlnkDVyxEiPsqB9456kHdhwBvv8KjqvEBSPOAXgrb5pev_M&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfDMdR-KLtCurh8uT0SlqxCrZhZrSq2k6Q7WiD3BHfLtjQ&oe=64C5D981\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362636374_698773312294222_9125565501831116284_n.jpg?stp=dst-jpg_s600x600&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=eezI9CnGS_UAX_x3oCL&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAz9YowgCld59ndHDZrSbHYFgEoa6TMDnQIBtsRqe0RZQ&oe=64C59052\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid035UTJtKk9aeGHQg2kvdsjfLj3dmRDQzcRcyCJQmmQNUnsWsVAkbTJszHEYqetrVfCl?__cft__[0]=AZV8T43WZ2u0wX-1yfC8D4IzeuksVNXZ8x6oXggFWfU6s0qRyWikX0xBhh4wMTQLQVdWcGBJrRHiCM6LwJxIvLYej7rKLN98dhTEZhLCqwoAMSmyvjsZgooJ2Bm4LE9XUyPYzZNymqEGb3_cnc4jTbxShGWoTL9-QRqRhpXDExKX5eCTaRJ2WefOG3CfyOPI1Ahy0J2iAAKv3V--oBMpQafp&__tn__=%2CO%2CP-R\"}, \"pfbid02ZWhjhUQHNBC2KwwQoUuXMBJXF6YsieGcKBUge9ntg3m4mcxdHkPh36oxYcnpeLvKl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 39, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 39, \"comments\": 2, \"content\": \"INFO POKOK TUMBANGMEDAN MAHSURI 122 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:45.040701\", \"video\": [], \"image\": [\"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360116935_698756602295893_7704228780308948517_n.jpg?stp=dst-jpg_p600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=QQvieDXp_4oAX-Qi2kr&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAsVRoYyL2TJq2fyXiG-el34Zs-14DUdYkpx84-NKiT3A&oe=64C52B50\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360126189_698756652295888_5637945379762085324_n.jpg?stp=dst-jpg_p600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=-lAJc-7jvXoAX9P-kdH&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfBWtwhDj-9sc5jVNyCMpBcAH6PdKlXAL9lf6au1CgssMw&oe=64C5B8A9\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/360117794_698756665629220_4139343876458038468_n.jpg?stp=dst-jpg_p600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=JUlsTOgCGZMAX8PJVzN&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfA47sDCkCMHlaIEHT58iC3bBAlmogIFhtEZAeK2-rawzA&oe=64C69753\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02ZWhjhUQHNBC2KwwQoUuXMBJXF6YsieGcKBUge9ntg3m4mcxdHkPh36oxYcnpeLvKl?__cft__[0]=AZWAGH7jTWGloXaAE5qu7n-KQOpfSxvOSWWHyj4NC60DnsNzomXuxtw5_UiRr8K2Z41kgfnS48NQo-o_-7k-TtuxofZEK2_mMMaz-fbkdegfANz2RYgNov6UoaqzljWyf2CQZSY40xECHMDjUU_b-XXsaDYWpmrP0VWsNHz0GLwAmR0cyPjApsm6Lo0Sc521hFLd9XWbjFBmSYj_13uL3j8A&__tn__=%2CO%2CP-R\"}, \"pfbid02a2Qdpbgyt2dHvzQ6CKUTqFRhmBpoNNsacjzumP76yJCHHXqkmFcXedLB1MunqdKWl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 39, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 39, \"comments\": 2, \"content\": \"INFO POKOK TUMBANGHADAPAN PASAR BAYAN BARU 22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:45.321013\", \"video\": [], \"image\": [\"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/362628496_698755275629359_6301137382907133690_n.jpg?stp=dst-jpg_s600x600&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=DeZnVC_H5WcAX-XhfHd&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfA9z8ekklq4rqd8xQKdKjyWGEaIJuw4eoG5AaILBGZ-sw&oe=64C6CEC8\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/360119381_698755305629356_7136193953232807712_n.jpg?stp=dst-jpg_s600x600&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=f0yQhGjPWpwAX9tIDJD&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfB--4_vaN2BCVwWQTCjXjWEYUMDTBgrlM5tjUJFTlbg8Q&oe=64C52446\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361616227_698755332296020_8627929541952470794_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=3qMLioMTPy8AX-B77m4&_nc_oc=AQl_wPVjpi8TT3et8AX2RVDfeQRpTPReRSQvdj53y5vj_shndoNEY8nGSJuI4GmXQPc&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAfGIS6Y0ZM0sakCRkpol8JSKcBFj4155k0AGTzbFhnSg&oe=64C5F9E2\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02a2Qdpbgyt2dHvzQ6CKUTqFRhmBpoNNsacjzumP76yJCHHXqkmFcXedLB1MunqdKWl?__cft__[0]=AZVx-RL2vKpMWGrUfBVHQm3iN9DJmO8Hb8iov60afoDSpRITKQySYS1OnII18Rz9wlGKiHRr0mA2XaS7vlALz7LlvLE2Ae_8qV3UV9_m7up1ntIEVJ1yVJqVreojHyKLnOGqFxMoUQQmO7T3UeRxvOKLdKbeiEAlgI2NJZfjYxjz2OUcpNKoJerS65wbyR1JxNPc0IDCLSiZtyNblm-8s7gY&__tn__=%2CO%2CP-R\"}, \"pfbid09XodCkdtvPHpTJmi59P8qayP4KKiFkzzr8WnNwewotGhqyNWijDVSieHM7SuRhdnl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 2, \"reactions\": {\"likes\": 25, \"loves\": 0, \"wow\": 3, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 28, \"comments\": 2, \"content\": \"INFO POKOK TUMBANGHADAPAN SILVER JUBILEE HOME22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:45.707458\", \"video\": [], \"image\": [\"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362657990_698724618965758_7595807359021937228_n.jpg?stp=dst-jpg_s600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=pgmCyVGejMcAX9G0Q6j&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCc_PG3b4FAjZCj7Vhblpj1DZmRlNsF1PllrrhD2i28XA&oe=64C6E716\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/362629652_698724735632413_8556638981431436519_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=INp9kj0dzuEAX_-7-IZ&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfAn8yAKjJYbYiSTdgE6PetCEkB8ATNpEjZF4TNACVCdhA&oe=64C5DA99\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362209961_698724668965753_7973651823909167172_n.jpg?stp=dst-jpg_s600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=PP61JrLatGEAX_a-VlI&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfDKIoVhI-NtUpp7OF6J8BPN_yAN1j1nBU0vrYprX6sg-A&oe=64C51F20\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid09XodCkdtvPHpTJmi59P8qayP4KKiFkzzr8WnNwewotGhqyNWijDVSieHM7SuRhdnl?__cft__[0]=AZVCzJVtlGAbG17-uKn7MYh86bZseMEBfWsQpnPTMW8d2uAEjd0rCKEcsYCi4rZW_mUw3K7zk_uWE7BZ7fyJx-fkV7hnCoorIAjTAHGgxcUL8At5z6nM4s0oNINHF1JIscYFZ4ptC3nZAInra4044QnCI2YWfgIaJGkwLx89Y7oYPLsTfWTlN-nxvlyPG5_xiFk06ErTOUaSlXanNr7Rqm2O&__tn__=%2CO%2CP-R\"}, \"pfbid021bhdyh3EGcKRBt9CanHFEjaSKFZzBUDpU6SK6S9koi1bkCzCsn6kA3brBFWULbSbl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 16, \"loves\": 0, \"wow\": 2, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 18, \"comments\": 0, \"content\": \"INFO POKOK TUMBANGJALAN BUKIT KECIL 222 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:51.219047\", \"video\": [], \"image\": [\"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/362627289_698715595633327_5515922438878597914_n.jpg?stp=dst-jpg_s600x600&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=0IJrwXZpcrYAX84Df0K&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfA1A83lj21K4gIg6FI7w-Aw-GtYacrZJdIM85gV9t8hKA&oe=64C636AE\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361926849_698715638966656_8208158456639695975_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=SwD4xUEWiR4AX__anTG&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfCfXwwnZAw94RVYoV-43xLYtbvFz7CKI5AAvbJ5hKRRMA&oe=64C63928\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/362641614_698715665633320_3616259970553896466_n.jpg?stp=dst-jpg_s600x600&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=wOH6n9AiqiwAX9As_Ma&_nc_oc=AQk928cX-sKtkJyg6XQ6WueRU6yHFEGN-stcBSG-54brSve7eb3irOSSXjRZmJEgA0o&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfCEjc3ZkDL1AhH2xxm-0coGZBACYlfuT7tOnT2g5-Dmug&oe=64C63203\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid021bhdyh3EGcKRBt9CanHFEjaSKFZzBUDpU6SK6S9koi1bkCzCsn6kA3brBFWULbSbl?__cft__[0]=AZW66EEb_OrtGoyvD57sDc7Q8SRqVkz7OJcsV8hNvrDfE1uC50bCH8KXDam4be4VTHpcwWdy0u0wG-0weYSInPU4ezirT8YlNeMPu05cX7JniY4jEF-bMX13NVJg2xVKHevseLAjmvQIsRFV-VUi9XAJHw3vds-E11h7t3Uyg6tgYfccShYJSpwKy_bfy1_I0gR2Csqss1Qr0RmPecRpdDtU&__tn__=%2CO%2CP-R\"}, \"pfbid02679eyeEawuFhDpb84KWDVTgjhKCELcpAwmtQzDAhccznY6zvu8e2mHhVamiQj166l\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 17, \"loves\": 0, \"wow\": 2, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 19, \"comments\": 1, \"content\": \"INFO POKOK TUMBANGJALAN AZIZ IBRAHIM 22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:51.395595\", \"video\": [], \"image\": [\"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/362630115_698712692300284_3222880040199970031_n.jpg?stp=dst-jpg_s600x600&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=B38KweIqdjcAX-vG1YQ&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfDHgc_UI9a-9vGMwfq0XLLouy4NSV3i_6ux7aFgXXTSCA&oe=64C5B0FE\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362640385_698712762300277_320020135111281805_n.jpg?stp=dst-jpg_s600x600&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=x0ZnFt3fxwcAX-8zqco&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfC3PxlXXbn0-tBuhMUfcpvRmxSEvRgIJ7xshL30huDlyA&oe=64C4F1C2\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/361252399_698712812300272_1640835525290941220_n.jpg?stp=dst-jpg_s600x600&_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=_Mfc3vgK6SwAX-tqB36&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfDYJCA5umBl_3s5gXf79pO__NjFbr97Rx47zEOoJd8ZiA&oe=64C66DC5\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02679eyeEawuFhDpb84KWDVTgjhKCELcpAwmtQzDAhccznY6zvu8e2mHhVamiQj166l?__cft__[0]=AZUxZf8U7dRYrLNr2j99yH7qDneC8AfmbDKU7sujLn_0XNLqowDJw10LyHn121HyJjJCxH5ovwdVBk8gm0KqtGR24ZLSINZ4mUllqEJxGDJzN_04JTyeog3UUI9EXodCuA9B7PgReVLKLZi_aKOr5Lg8_RyWcmsMuFBrM8h4Z-qQa2MwDtHkzRhaorOgjyau-NE1DZCugWfcheS_OCVf6ZNc&__tn__=%2CO%2CP-R\"}, \"pfbid0kYmTL58u8qEgX3rR8bpVub93D1XBG3SsFaF6Qks4mHtBqURkivEzoUmoD1RWRMtl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 1, \"reactions\": {\"likes\": 27, \"loves\": 0, \"wow\": 2, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 29, \"comments\": 1, \"content\": \"INFO POKOK TUMBANGJALAN SULTAN AZLAN SHAH 22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:51.613152\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/362248422_698710018967218_835745851868839934_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qqytprtCzYEAX-R9Zt2&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfD_eNl3YKZuQtAnG5KRP3QbMiFKO9zRJO7pS4rs2tDPdQ&oe=64C550DD\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362632548_698710042300549_2121703060050757830_n.jpg?stp=dst-jpg_p600x600&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=yw9K-T0bKeUAX99rq6w&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfA2JL5Ew6UiO4RL12_ABQiKYsUvFH1dAMBVQ8jaX--VlA&oe=64C56D55\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0kYmTL58u8qEgX3rR8bpVub93D1XBG3SsFaF6Qks4mHtBqURkivEzoUmoD1RWRMtl?__cft__[0]=AZUsA8IDZxRZ15QOib11rFLLba-4Cj1djjALq2kHIXGx64PlAS7ojyH3k4yZPGTqfilEtdA1-mxpEx7ckX3XOlwpSTDkDpDfLAL-b05hW7U_OvFYU5dq-giphBO6HHHSYs_X1XMPmEnv3K5diI3KOJF1JycwlLTCrr2RNRjNzzgex_2wV67ZgRkrDhoN19gV8Jn_l-K0fAqQgFN40fG0ebeH&__tn__=%2CO%2CP-R\"}, \"pfbid0xvJ6FJ3wCVh3kFtBdANFcPBx4msxFjrYVmcRDX3QjF6j277qu7SmxygotyenjsLkl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 6, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 6, \"comments\": 4, \"content\": \"Semarakkan Bulan KebangsaanKibarkan Jalur Gemilang\", \"posted_on\": \"2023-07-22T17:58:51.743948\", \"video\": [\"blob:https://www.facebook.com/8cd65668-e7d0-4fab-b06f-02543a3e33f5\"], \"image\": [\"https://scontent.fsgn2-5.fna.fbcdn.net/v/t15.5256-10/362232314_183433588055105_7691584752091055827_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=ad6a45&_nc_ohc=ZaX5zlHdHAwAX_huoVx&_nc_oc=AQltgMfg4SWViQyPlL_bjbpWbc2lgkrIIfnCREnXAjq10HNSCaC3N-STg6GYVgbSvqY&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfAOZ8S8ymyGyJnlr186MWFoMSzEFQ7dlz5SJ3QqhLx4cw&oe=64C5373B\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0xvJ6FJ3wCVh3kFtBdANFcPBx4msxFjrYVmcRDX3QjF6j277qu7SmxygotyenjsLkl?__cft__[0]=AZXncyj6gtgTOURVam2ZSfnBWSI5_y4QNAoDEVVNW5E6iNAtYwyMHiM8Z79vyXAr9h0tjBmp5g5IoKrd6RXvERNhmPj8mGs7J62YDLzGRPm5X6io9n7xbzJ_hN4XAj8amq5dhqeeuvSqQkdt-ZU2Kku63tCcQ0PiXd_7OM7et46r9d4vEFX4LL0605x9L3Y7PE7cEqE--TiBHYYZoCQLuY80&__tn__=%2CO%2CP-R\"}, \"pfbid0ShoQP5pVepnbygK1PvxaEdLEerzBzf9zxdRrwPXx3gatT2HMS3SwL9YxSdSWQJhUl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 4, \"reactions\": {\"likes\": 66, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 66, \"comments\": 6, \"content\": \"INFO POKOK TUMBANGLEBUH NIPAH22 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-22T17:58:51.915895\", \"video\": [], \"image\": [\"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362653754_698673485637538_2356267571398521308_n.jpg?stp=dst-jpg_s600x600&_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=YBNJ6ZoiyeIAX_awZVU&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAvUtQr5WYw-o5og2VY88eMJjLg54vVHLJG7SDhwArECA&oe=64C59040\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/362670011_698673518970868_8008559306642148648_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=ajIWQN_wvyAAX9OaREP&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfDbL7Hp0T18wA40GibX7PJg-0CY6sYxBmVk0E1B5mvvVQ&oe=64C55FDE\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/362660656_698673545637532_6487270052334535329_n.jpg?stp=dst-jpg_s600x600&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=DRB3cPwAqHoAX_Gztll&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfChFzLdLS4Okbr6TgxLEtzgyrgyzTKZK9vi8CE9_GJMjw&oe=64C53FD8\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/362610223_698673588970861_5957488916058816984_n.jpg?stp=dst-jpg_s600x600&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=XgLFCvtz-pQAX9wT0ev&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfDbLE8F6kI3c_UlqR8obppsi6wvIzkGOvjqFMZc_hIuBQ&oe=64C51D15\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/362289016_698673628970857_2252978794896793210_n.jpg?stp=dst-jpg_s600x600&_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qyLOC75gxSUAX-3JvM4&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfDDpCdHO1OjcleXuLiH367Tggincg9pzlygzNCis1fNdA&oe=64C5CCD9\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0ShoQP5pVepnbygK1PvxaEdLEerzBzf9zxdRrwPXx3gatT2HMS3SwL9YxSdSWQJhUl?__cft__[0]=AZUT7pjlceD-2p7gHhx1WMdCx2xmUp6Abvp3K-I1NE5p6Ia2h09D4fHYW_7wYDRSDHuhZi4bf4_wPOfBDUcEhXTaDFC-nyvC92MLyMaVWTg0fbF8Q7jsGuynVoT8yxsm1Y0bVeXp7KWBAXlBz09TronniCCArO1TA4yDpvccRZUBKVOvI7EAKepGFoV7v6qcsDKD5ZtG1wWjKd3JGJoRuXCh&__tn__=%2CO%2CP-R\"}, \"pfbid02qEcDYz5X6FFRVJqyvLvoWdKbtaK9RHkotPdAvUn21qf4XBquYssBraTCTcr7xsxkl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 2, \"reactions\": {\"likes\": 43, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 43, \"comments\": 3, \"content\": \"MAJLIS PELANCARAN BULAN KEBANGSAAN DAN KEMPEN KIBAR JALUR GEMILANG PERINGKAT NEGERI PULAU PINANG TAHUN 202322 Julai 2023YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar Majlis Bandaraya Pulau Pinang hari ini berbesar hati menerima bendera Jalur Gemilang bagi pihak pentadbiran ini daripada YAB Tuan Chow Kon Yeow, Ketua Menteri Pulau Pinang sempena Majlis Pelancaran Bulan Kebangsaan dan Kempen Jalur Gemilang Peringkat Negeri Pulau Pinang Tahun 2023 bertempat di Perkarangan Dewan Bandaraya, Padang Kota Lama, Pulau Pinang. Penyerahan bendera Jalur Gemilang pada majlis ini meliputi 21 Jabatan Negeri, 19 Jabatan Persekutuan, 11 Agensi Negeri dan 10 Agensi Persekutuan sebagai simbolik bermulanya kempen Bulan Kebangsaan pada tahun ini.YAB Ketua Menteri Pulau Pinang dalam ucapan beliau menyeru kepada seluruh penduduk negeri ini untuk bersama-sama menzahirkan rasa cinta kepada negara sempena kempen Bulan Kebangsaan pada tahun ini sejajar dengan tema Malaysia Madani: Tekad Perpaduan Penuhi Harapan.Majlis yang disambut meriah oleh semua jabatan-jabatan, agensi-agensi kerajaan dan pertubuhan bukan kerajaaan negeri Pulau Pinang turut dihadiri Dato\u2019 Law Choo Kiang, Yang Dipertua Dewan Undangan Negeri ; Prof. Dr. P. Ramasamy, Timbalan Ketua Menteri II ; Dato\u2019 Mohd. Sayuthi Bakar, Setiausaha Kerajaan Negeri; barisan ahli Exco Kerajaan Negeri dan ramai lagi. Majlis Bandaraya Pulau Pinang turut diwakili YBrs. Sr. Cheong Chee Hong, Setiausaha Bandaraya serta Barisan Ahli Majlis-Ahli Majlis, ketua-ketua jabatan dan para pegawai. Kemuncak pada acara ini, YAB Ketua Menteri Pulau Pinang diiringi dif-dif kehormat menempurnakan pelepasan Konvoi Kembara Merdeka Jalur Gemilang 2023 yang dibarisi oleh 40 buah kenderaan terdiri daripada agensi awam dan swasta sebagai simbolik Pelancaran Bulan Kebangsaan dan Kempen Jalur Gemilang Peringkat Negeri Pulau Pinang Tahun 2023.Marilah kita bersama-sama semarakkan Bulan Kebangsaan dengan mengibarkan Jalur Gemilang.\", \"posted_on\": \"2023-07-21T17:58:52.436773\", \"video\": [], \"image\": [\"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/362603383_698166379021582_8496098007101979771_n.jpg?stp=dst-jpg_p526x395&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=NCVVUjzhcxQAX_xOBM9&_nc_oc=AQnTYvozVo7GshVfE25xifrEkn_sz2hQRNN77Y3UGHUaIg1r6cZouFoZmKK_tgywBjk&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfC9khLHQ8jK_wt_gQcTg1n0tjagKfhrQjTqcsWXgrzzPA&oe=64C545A9\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/362611613_698167272354826_5450829947580967536_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=SUzsmaG5u5EAX9kZcWs&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAx1O0-CIENkwf_B6WA1wJWDoLypl3oW94VtyaIhiQQNQ&oe=64C606C5\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/362272456_698167319021488_7302875763157411175_n.jpg?stp=dst-jpg_p526x395&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=aFnSVmTLSgIAX_BkdJj&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfCVv20eOz7YATLVJAt4MWMHaHL9BKcgZs5xi_LyixeC-g&oe=64C6B119\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/362274854_698167359021484_9125091432323716108_n.jpg?stp=dst-jpg_p526x395&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Qozh7QkFlK0AX-7Hcsc&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfD9Ki6YM-Ezzm-82G3r6Qp4pQ1PrO3ERWmM4AWtxDm9aA&oe=64C65A6B\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/362224787_698167402354813_4191587930795062071_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=a2XaeSUJDUMAX-4X2Gv&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfB4AI-Jpke4wM3Mi6vaI1Ghy9GUbufWeU4a4cVScuQw5A&oe=64C6DE5A\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02qEcDYz5X6FFRVJqyvLvoWdKbtaK9RHkotPdAvUn21qf4XBquYssBraTCTcr7xsxkl?__cft__[0]=AZXu-yoTJ0gbGW8VXld2fzqYkWULbyFASWN5bjzpco7XOB6j83D8aw3ycP2RRWHNP_8m4uhBo_pzvjfxvDsfKuZOtn6FlIYWeIOv_ohao1oVSHdjvXLdNuEyhOQnpLISRJ6xffQaNW1yxTfKaGk0-xiykJFWJdRdM8lZU4v0aLVc4Gynw9OdNZCY5uJ2EH-IEc7NQb8HbqNdnHLVUy1-zZvE&__tn__=%2CO%2CP-R\"}, \"pfbid02QCzDK89BCkPinmYrpkrBHhmWyGMhZcmoLcis6QC6NAjVNgzWVXhEm8ep28z81yRTl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 5, \"loves\": 1, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 6, \"comments\": 0, \"content\": \"Majlis Pelancaran Bulan Kebangsaan Dan Kibar Jalur Gemilang Peringkat Negeri Pulau Pinang Tahun 2023 l Padang Kota Lama | 21 Julai 2023\", \"posted_on\": \"2023-07-21T17:58:58.161261\", \"video\": [\"blob:https://www.facebook.com/4a8cd8bc-ece8-49d9-a221-d7967dc21561\"], \"image\": [], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02QCzDK89BCkPinmYrpkrBHhmWyGMhZcmoLcis6QC6NAjVNgzWVXhEm8ep28z81yRTl?__cft__[0]=AZWxTuu_ZJu2kWJo8bYEHLV_YlaqDMiK1dMBcU2X9QvX0DCF_4lW1iUFEIhKSa1partslvUIfNFn5WPHa7tbe2xMxTlXS3hIopUJojsIh6qaftUHO8tvGjNdby_KiazpWRMZuBwrPwvKd9VT7lci8wJ2HZ-8plHMpdEtoUm1CYWeIMHRK8QoyWr3emQR9eEoINlsJmbQ67rOjzCkMmBDzi9MzjJbq1ZiMWudOjSEQ6Rjp9U5gW0rNJxcpzGYLOmvpIc&__tn__=%2CO%2CP-R\"}, \"pfbid0BpvzqofAc357z3YquBpQxMLsRSqjizWt8oBf5ym9n5jQYoqzYumsphVo1Rqt6qoil\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 3, \"reactions\": {\"likes\": 34, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 34, \"comments\": 2, \"content\": \"PARA PENTERNAK LEMBU DI BAHAGIAN PULAU, PULAU PINANG DISARAN MEMOHON SEGERA LESEN PENTERNAKAN20 Julai 2023YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar Majlis Bandaraya Pulau Pinang hari ini menerusi sidang media amat mengalu-alukan para penternak lembu di bahagian pulau, Pulau Pinang untuk segera memohon lesen daripada Majlis. Majlis Bandaraya Pulau Pinang dalam usaha mengenalpasti lokasi yang bersesuaian untuk aktiviti penternakan lembu melihat kepada tindakan melesenkan penternakan lembu tersebut adalah merupakan kaedah terbaik agar penyediaan dan pembinaan kandang yang bersih, selamat dan tidak menimbulkan kacau ganggu setempat. Seramai 15 daripada lebih 40 orang penternak kini mengambil langkah pertimbangan dan sedang berusaha untuk memenuhi syarat serta keperluan permohonan lesen yang ditetapkan oleh Majlis Bandaraya Pulau Pinang. Encik A. Halim Yusof dari Balik Pulau merupakan salah seorang dari 3 orang penternak lembu yang telah memohon lesen daripada Majlis Bandaya Pulau Pinang dan beliau telah berjaya menerima lesen penternakan lembu pada 18 Julai 2023. Majlis Bandaraya Pulau Pinang bersama pihak Jabatan Veterinar Pulau Pinang akan mengambil langkah lebih proaktif dalam usaha pemberian lesen penternakan lembu. Ini bertujuan untuk memastikan isu keselamatan awam seperti ternakan lembu berkeliaran dapat dibendung dan ditangani secara berperingkat disamping memperkasakan punca rezeki para penternak. Hadir pada sidang media tengahari tadi adalah barisan Ahli Majlis Encik Ts. Kaliyappan a/l P. Renganathan, Encik Nicholas Theng Jie Wey, Encik Wong Yuee Harng, Encik Hari Krishnan a/l Ramakrishnan dan Encik Quah Boon Lim serta ketua-ketua jabatan dan para pegawai Majlis Bandaraya Pulau Pinang.\", \"posted_on\": \"2023-07-20T17:58:58.329423\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/360098430_697651949073025_640003213501297314_n.jpg?stp=dst-jpg_p526x395&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=VgQeyqAUUxYAX_aqTpf&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAd7A2k4phFzA5hJhoUnXfA1aFPECv_1STizvwW6NTgzg&oe=64C577FF\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360095619_697652002406353_8227673600874327725_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=X8ZJ6X9w8boAX9eNNob&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAQXTRGVljCbOnkeu-6sOyXJEFVZ-M76iEGsH1mmbR-rQ&oe=64C52920\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/362260335_697652022406351_8997611359658994169_n.jpg?stp=dst-jpg_p526x395&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=cf77ICE6LJ8AX-lcSen&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfA5uAejtm-1pWaCaR_6vzfHubO2_xLDXSrg_qp1wZI5dg&oe=64C57571\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/360094668_697652052406348_3300277076202623102_n.jpg?stp=dst-jpg_p526x395&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Ha3q15B4uegAX_PzJr2&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfCdr7glnSg-Wn00cBHoMGM7yxdpJx-7ccrKva7MIPuGdw&oe=64C4F4A3\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/362001260_697652069073013_1074279373947440913_n.jpg?stp=dst-jpg_p526x395&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=xDUROLXKo60AX_DwvOG&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfC65cfuAiwONLiuY-n-U11zo5AlJ6iXUnBaCKCeSvHrMg&oe=64C50672\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0BpvzqofAc357z3YquBpQxMLsRSqjizWt8oBf5ym9n5jQYoqzYumsphVo1Rqt6qoil?__cft__[0]=AZUWGVkELi5MDyZNBXDiXxa7C7Mzx6BDa_EgYq78q-Db15myC4eTyuPux0JXBumgjGH_kgTfzyLbjCMqfMxzaM_LC2fq6nW0QWdU_OFuz7KYapnNEGcy91PfKwioDINs51ZDu6mibcqFlHtfdr9_s_COocf3rG0FL_u-Wv_Yhz8baWSGV6eLyqg9XmkBPtqxI7sjfxPV_RmrvEfy0buvYjt6&__tn__=%2CO%2CP-R\"}, \"pfbid02Ex7MSos7LVxaGD3K9vMghSEFsUJxNFguJqDo8KPhbqB52yXPXTq1xaiqZ39uCZKkl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 8, \"reactions\": {\"likes\": 33, \"loves\": 0, \"wow\": 0, \"cares\": 2, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 35, \"comments\": 1, \"content\": \"DATUK BANDAR MBPP TERIMA KUNJUNGAN HORMAT DELEGASI YALA CITY MUNICIPALITY, THAILAND20 Julai 2023YBhg. Dato' Ir. Rajendran a/l P. Anthony, Datuk Bandar Majlis Bandaraya Pulau Pinang amat berbesar hati dan mengalu-alukan kunjungan hormat Mr. Pingsak Yingchoncharoen, Mayor of Yala City Municipality, Thailand bersama Konsul Jeneral, Royal Thai Consulate di Pulau Pinang, Mr. Raschada Jiwalai, dan delegasi barisan pengurusan tertinggi Yala City Municipality, Thailand.Pertemuan yang amat bermakna ini mengeratkan lagi hubungan dan kerjasama dua hala dalam aspek tadbir urus cekap pihak berkuasa tempatan, ekonomi, warisan kebudayaan dan sebagainya. Turut hadir bersama pada hari ini Ahli Majlis MBPP, Encik Dylan Lee.Kunjungan delegasi Yala City Municipality, Thailand juga dibawa meninjau pengoperasian pusat Intelligent Operations Centre (IOC) MBPP, Galeri Dewan Bandaran MBPP dan Tembok Padang Kota Lama Esplanade (Seawall).\", \"posted_on\": \"2023-07-20T17:58:58.542955\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/360094733_697634592408094_4432624279774512831_n.jpg?stp=dst-jpg_p526x395&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=hIdJxRkwzZ4AX8j0g_x&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAwgIcDkl16w2cnP76g4PxcQ9ibF87CnRMzEtJ74nBNGw&oe=64C6B815\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/361882709_697634755741411_7775585732076341593_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=xeM2P4pKcakAX9FiX3Y&_nc_oc=AQmhbyMgSosigjdOUNNh0Mx4lxf6WYMt6b8-JdPo-O38mqylOxZy43QMTzlf6Zf_Ohg&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfCTB-4bTRoC7i_ksDIMhnUNyGO3pvyDrIwUgDyjzdRy6Q&oe=64C52A34\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/360097540_697634772408076_301497414380405554_n.jpg?stp=dst-jpg_p526x395&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=ramH49tmSsgAX9lxmG0&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfAZN_vY1p7gKjuKNTTr9qYMbwKXdTTv1VZ51RxfWSFBCw&oe=64C51442\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360094206_697634789074741_3502066041685493020_n.jpg?stp=dst-jpg_p526x395&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=A07Maa07GZYAX9LRKDX&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAnwj8Dkald77LnL7x8jUMzw1pbHjQtonr0tCTN0A5QTw&oe=64C69D9E\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/360098900_697634805741406_4430730880116208769_n.jpg?stp=dst-jpg_p526x395&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=zj3JnaYxIeoAX8Pk_ZK&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfB42bHx1HysRThNd-JjJipr-F9-dNF7ZOdFPFWkRjFZ_g&oe=64C64226\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02Ex7MSos7LVxaGD3K9vMghSEFsUJxNFguJqDo8KPhbqB52yXPXTq1xaiqZ39uCZKkl?__cft__[0]=AZWuCj7pyjJnenkdlnfWgoGJHe_vSVQrfSRHEgkcg3SoJQesDmHQdyohBT6UmVpfqDLrFAWj5l_XFGI6N-6xCGRKprfn1L9wwKs7tgnlKVbBdWON5fPNmWoZfzk0-iiV6coaR0fcJIclj-5YzyKPfGq03lu97n--dTXvlbE62Kei6WgJCV7R8AT3Rv9RpLscIUS1nqIbySm_OOxYwg8c5X-w&__tn__=%2CO%2CP-R\"}, \"pfbid032iTkWehRMvLJn3sQmZTZj7UCagVzRf18hKSaZAQp9fLPz3VSWi6uGiLqjMdW3H84l\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 29, \"loves\": 2, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 31, \"comments\": 1, \"content\": \"IPSI TINGKAT KESELESAAN SURAU BANDARAYA PERKASA PENGIMARAHAN IBADAT 20 Julai 2023Para pengunjung Padang Kota Lama yang beragama Islam dipelawa untuk menunaikan ibadat sembahyang di Surau Bandaraya Lebuh Duke, Padang Kota Lama. Ianya terletak di sebelah bangunan Pusat Bayaran Setempat MBPP di Padang Kota Lama. Surau berkeluasan kira-kira 160 meter persegi ini dibina di atas tapak letak kereta dan berkeupayaan menempatkan 70 jemaah dalam satu-satu masa serta mempunyai kemudahan tandas untuk Orang Kelainan Upaya (OKU).Justeru itu, YBhg. Dato\\\" Haji Kamaruddin Bin Abdullah, Ahli Majlis MBPP merangkap Pengasas dan Presiden Pertubuhan Penyebaran Islam Antarabangsa (Islamic Propagation Society International - IPSI) hari ini berbesar hati menyumbang dana sebanyak RM2,700 bagi tujuan penambahbaikkan kelengkapan Surau Bandaraya di Lebuh Duke, Padang Kota Lama. Surau Bandaraya yang diilhamkan oleh YBhg. Tuan Haji Mohamed Yusoff Bin Mohamed Noor, Mantan Ahli Majlis MBPP telah siap dibina pada 14 Oktober 2013 dan secara rasminya dibuka untuk kegunaan orang awam pada 18 Februari 2014.Hadir menerima sumbangan ini adalah YBrs. Encik Azman Bin Sirun, Pengarah Khidmat Pengurusan MBPP.#suraubandaraya#mbpp#lebuhduke\", \"posted_on\": \"2023-07-20T17:58:59.023741\", \"video\": [], \"image\": [\"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/360152147_697628522408701_2667165696187226115_n.jpg?stp=dst-jpg_s600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=x3kSdL5sbZkAX8L8mBt&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfALJoFptLOV9dXsVXJLZx2im2YU2HlhtRTv7LfjPchcJQ&oe=64C649A3\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361638361_697628595742027_7157312587354720691_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=lzQrJJJC3lEAX9ezLUl&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfDX4fOJq8gZ8FcHedYB1mi7Fr7UmNT63fCNWIUYmck14Q&oe=64C64F4F\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361893991_697628615742025_3207588188751161892_n.jpg?stp=dst-jpg_s600x600&_nc_cat=106&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=Xf70Fvg7eUkAX_qoSxe&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfAPcNVstrbR5XK0tfXSB4aGBWbMQ2lSsCOn7A5KfmWf6Q&oe=64C6B94F\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.30808-6/361646143_697628629075357_8407202877837637241_n.jpg?stp=dst-jpg_s600x600&_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=QZliDEhhGnQAX-hP5jX&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfDieeBjh2m-qWDxvb975XLvW9xjQR6IAf4sCnVFfo1ucA&oe=64C580A4\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/361569887_697628639075356_1331101627407144688_n.jpg?stp=dst-jpg_s600x600&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=jpfW0c1gKYAAX9eHnOb&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfB-TolkmcXYpYHLLpG2iG-f431_h_I5lD0xWTiM8a76hA&oe=64C5029C\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\", \"https://scontent.fsgn2-8.fna.fbcdn.net/v/t39.1997-6/105258811_1000519497070421_1877687988442182543_n.png?stp=cp0_dst-png_s110x80&_nc_cat=1&ccb=1-7&_nc_sid=ac3552&_nc_ohc=U8qN7u1Knh8AX-zcaE_&_nc_ht=scontent.fsgn2-8.fna&oh=00_AfATI7ehDNL-uN09IS5uKibhs1FgGxyVAxDJR27yxDtxgg&oe=64C5406B\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid032iTkWehRMvLJn3sQmZTZj7UCagVzRf18hKSaZAQp9fLPz3VSWi6uGiLqjMdW3H84l?__cft__[0]=AZVUVy9f-asibu7roWf8xrSWE4maNKfJFw_YJbbKtr3LCKI11ssDi63ilq34WXVUsDHwgUvIqOPojTQCraP6ABvLrqPaEluMG-4ezQDVZgbG1NpyGlvKm7kB_06xzJGB7nBHeafNOFPM-oqZsDt9NcO2lLS5uZ6m4o2egDX4GPc1uy-XCPPF_07QAk6iAQWrMU07dk6ET6AtthryQ1b29pSG&__tn__=%2CO%2CP-R\"}, \"pfbid02G7bt24Hq4vLiJ8e4MtqBtPasi9JLVmxntEv6smRszWDmCCUtK7rRfi4M9qwnvWPul\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 22, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 22, \"comments\": 9, \"content\": \"MAKLUMAN UMUM PENUTUPAN SEMENTARA JALAN SEMPENA PELANCARAN BULAN KEBANGSAAN DAN KIBAR JALUR GEMILANG PERINGKAT NEGERI PULAU PINANG TAHUN 2023#maklumanumum#PenutupanJalan#bulankebangsaan#mbpp\", \"posted_on\": \"2023-07-20T17:58:59.357644\", \"video\": [], \"image\": [\"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/361172746_697461372425416_5332850874216582082_n.jpg?stp=dst-jpg_p417x417&_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=wvApaAIQ3QwAX8wHcXj&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfC9wppLdM0WfRNF1ZZiv3-4jYZD0B-xQV1ge68WsD9fbQ&oe=64C58153\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361647008_697461495758737_2268468754465571894_n.jpg?stp=dst-jpg_s600x600&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=ANgXVR1I-EwAX-RFVcA&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfCyvU7727eVDjjVHifv2bvNRNdMRII16xmqqsiEcomJNw&oe=64C516E9\", \"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/361600478_697461555758731_4380366494973922699_n.jpg?stp=dst-jpg_s600x600&_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=VN4Evx-XgZwAX8ygK0V&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfA43zWjHCovqWqrxdHNOJJ1xfAu8JlBBYjc2-spxOJcvg&oe=64C6832C\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02G7bt24Hq4vLiJ8e4MtqBtPasi9JLVmxntEv6smRszWDmCCUtK7rRfi4M9qwnvWPul?__cft__[0]=AZXTZY4yiAzvFgETy-SLU9ZxAqa2QdZMQnkY-w5pm7IseLpVMwFQku6NEMLi1n-rRVd5mCpuby63b0Xg9CevM_Je7_RcAktSguzaMcf4X0u3hUbtFzSpb2Ri0jRZq0vXX-1X3x9VJzEJTPpB7LCFVUp_JDTFbHXcGamVjCiRk-M5l_COlT_7jkiEC2D-_PQfKCvAoBHimcg5asSeYD2Bt_X7&__tn__=%2CO%2CP-R\"}, \"pfbid02m1KdmnwhyMv2fhhmvMRtPrcNtc1sxpatcS4vXvJN9nNoQX7vJAeYJmnoBbqjVRkjl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 1, \"reactions\": {\"likes\": 27, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 27, \"comments\": 1, \"content\": \"INFO POKOK TUMBANGJALAN JESSELTON 19 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-19T11:45:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361949894_696939355810951_637653074382355264_n.jpg?stp=dst-jpg_s600x600&_nc_cat=106&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=av1aAelNis4AX_x3__N&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfBb5K07bWmaal0ZBPFHRxEf3EC2ZDunplCgw54Khbziug&oe=64C503B6\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/361934450_696939402477613_5495853717864611386_n.jpg?stp=dst-jpg_s600x600&_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=IN1w-DkTCRwAX8Jje9T&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfCkyn4Ih5p0Q7oS7p69eXZTekjbW5Jnblq4slyaMiciFA&oe=64C6E2B8\", \"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361924472_696939422477611_2299679787409325091_n.jpg?stp=dst-jpg_s600x600&_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=38X-2XFx12YAX_JjoXp&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfDoDFi520eS0CwX3Yy19p3ep1ThN-WJ0OFL0ZSvluV3xg&oe=64C66F72\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/361621143_696939432477610_924132394406115068_n.jpg?stp=dst-jpg_s600x600&_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=xzYElwgqDVAAX-Kjeh9&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfBk5woQWg4gB-OAnRH4qR9qk8yxId4B7hErdiOZeFUyFQ&oe=64C537A4\", \"https://scontent.fsgn2-7.fna.fbcdn.net/v/t39.30808-6/361109008_696939445810942_6687869870241304905_n.jpg?stp=dst-jpg_s600x600&_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qfKQ1BCBYQ4AX-kxAN1&_nc_ht=scontent.fsgn2-7.fna&oh=00_AfAih1jyPtIyjcl3BEV2qVbyGnDnu2mdb9ZZJtFk80pDBw&oe=64C51F81\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02m1KdmnwhyMv2fhhmvMRtPrcNtc1sxpatcS4vXvJN9nNoQX7vJAeYJmnoBbqjVRkjl?__cft__[0]=AZUq-vMPRKc-jOtkKe-jbc2smeDUoQoBDefZqI9wSF0U75lZ0O-D_xnY2ZNaNLOr-Q9e_BSiXOS8BtIB-fmnON2zXz8hamnMew6FnWuNVJUd_-R1Ke6x-naA_NtQ6HFGURHElTmXUKnXYmvJWkF34FaPnTTM53ODnv-NawcYZ8TT7M1JQNJsZXh335BMMjq1WksazEHZ19GrYXHWUssxkku6&__tn__=%2CO%2CP-R\"}, \"pfbid02fKQ4KXtZNEVwb9PHpddZRNH58fciNU4p69cNfXWHVGTmRRd8AJaFE8gLiALb5Rfgl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 70, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 70, \"comments\": 0, \"content\": \"INFO POKOK TUMBANGJALAN PERMATANG DAMAR LAUT 19 Julai 2023 Syabas dan terima kasih kepada Skuad Pantas MBPP dari Jabatan Landskap yang menyegerakan kerja-kerja pemangkasan, pengalihan dan pembersihan pokok tumbang. Orang ramai dimohon untuk berhati-hati semasa berada di luar rumah dan sentiasa mengawasi ahli keluarga anda ketika keadaan cuaca yang tidak mengizinkan.Sebarang aduan mengenai banjir, tanah runtuh, pokok tumbang dan lain-lain, sila hubungi Hotline MBPP ditalian: 04-263 7000 / 04-263 7637016-2004082 (WhatsApp)#skuadpantas#mbpp #penang #pokoktumbang\", \"posted_on\": \"2023-07-19T11:34:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/361841600_696935159144704_2797509690449740069_n.jpg?stp=dst-jpg_s600x600&_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=EmCbiGVk_bMAX9ihXxp&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfDLW9ukyZ1nGJm21fMUeLgybMI5NEzrbb4uacXBw6ntZw&oe=64C68592\", \"https://scontent.fsgn2-3.fna.fbcdn.net/v/t39.30808-6/362021455_696935372478016_8453958619838799281_n.jpg?stp=dst-jpg_s600x600&_nc_cat=107&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=9RxUmIDP9koAX8BHDPv&_nc_ht=scontent.fsgn2-3.fna&oh=00_AfB0QeM3p4aVWEIq6ciXlE5wOOUGW9jLgM5pAJ47_EeYTw&oe=64C6257E\", \"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/361630728_696935442478009_5241826259459842902_n.jpg?stp=dst-jpg_p552x414&_nc_cat=110&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=ZzTrW0nG4EEAX9XJ53r&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfCvKnfuncayc8ydNJ8R-5iCRqD0o3gP4P55N5FnU-KJDw&oe=64C538C7\", \"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361897200_696935539144666_5982647996762099050_n.jpg?stp=dst-jpg_p320x320&_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=HviyFh8dcEQAX_lMN8X&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfBICnPMPo9fUzSzRgYdGwjKhu2KW3dgIwxUfHW4jS332w&oe=64C4FDDB\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid02fKQ4KXtZNEVwb9PHpddZRNH58fciNU4p69cNfXWHVGTmRRd8AJaFE8gLiALb5Rfgl?__cft__[0]=AZUq85kEF884b1eOOupLLC0D_cGUfD4cj_i8uuyYtsNmKLZz_2DM7EM-Ts5m2Df0MmrSK5oUaLdmMMFWWE325UmqVKLB_YYVBKBxaAcRebReu-hV42zhlCXpV1WPGQGzq0Znn6v83g7XFvNLgVkUAwH9SaO93oU0Shki0NDv57K1ryfXgFht2KjH439ZeUnE1R9w_GSXbAveO2XKErERMWB_&__tn__=%2CO%2CP-R\"}, \"pfbid0g2TkHivt2aphDKrhsSoNBbhQJHnymehnxHdP9CL2x1wSGxLwH5U6c6pVqY74P8Sal\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 13, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 13, \"comments\": 0, \"content\": \"AMARAN RIBUT PETIR. Ribut petir, hujan lebat dan angin kencang dijangka di negeri Perlis \u2022 Kedah \u2022 Pulau Pinang \u2022 Perak (Kerian, Larut, Matang Dan Selama, Hulu Perak, Kuala Kangsar, Manjung dan Perak Tengah) sehingga 3:00 petang; Rabu, 19 Julai 2023.Amaran dikeluarkan apabila terdapat tanda-tanda menunjukkan ribut petir dengan intensiti hujan melebihi 20 mm/jam yang hampir ATAU dijangka berlaku melebihi sejam. Amaran ribut petir adalah amaran jangka pendek yang sah dalam tempoh tidak melebihi enam jam untuk satu-satu keluaran.Dikeluarkan pada: 11:50 pagi, 19 Julai 2023#ributpetirmetmalaysia#metmalaysia#NRECC#MalaysiaMADANI\", \"posted_on\": \"2023-07-19T11:29:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-5.fna.fbcdn.net/v/t39.30808-6/361663384_674025174767800_6162884616768083219_n.jpg?stp=dst-jpg_p180x540&_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=vWJOLsv6rXQAX_82AjP&_nc_ht=scontent.fsgn2-5.fna&oh=00_AfABaSxwXWpt1VZ6nPbQzR7vNwe4GsCGxIkSC751uTE3ag&oe=64C6D417\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0g2TkHivt2aphDKrhsSoNBbhQJHnymehnxHdP9CL2x1wSGxLwH5U6c6pVqY74P8Sal?__cft__[0]=AZUgoK1Zu4T6p8x_p6mpJFKB7jwEQRk7NDjxslogedl3xxvFhHaMy_57-ekXUx6DJ5BmkjYuqrEzuYm9TQgLGL_IBQDPdaArys3dovVnVjOX1hS5TzT2FqrQ7o3RrfQxozhCK2jnzJvija-u3wdrcFrwRM6tD8NQ-hvU93J1UEhjfVB-zeN97FmLN4k2JPHxOMXW-exTHJYzZh54sbw2iB62eA25MjVTbfdPgZgBs6Kb-QJI_zhIWaPlAruiSt_h5I8&__tn__=%2CO%2CP-R\"}, \"pfbid06UmugEDE2xP8o9zRT4teXeGNLDvLcSqHEV8XhUXJSQHsJ2BqBBUBXFnHTWzurNrCl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 13, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 13, \"comments\": 1, \"content\": \"AMARAN RIBUT PETIR. Ribut petir, hujan lebat dan angin kencang dijangka di negeri Perlis \u2022 Kedah \u2022 Pulau Pinang \u2022 Perak (Kerian, Larut, Matang Dan Selama, Hulu Perak, Manjung, Perak Tengah, Bagan Datuk dan Hilir Perak) \u2022 Kelantan (Gua Musang) \u2022 Pahang (Tanah Tinggi Cameron, Lipis dan Jerantut) \u2022 Selangor (Sabak Bernam dan Kuala Selangor) \u2022 Johor (Pontian, Kulai, Kota Tinggi dan Johor Bahru) sehingga 12:00 tengah hari; Rabu, 19 Julai 2023.Amaran dikeluarkan apabila terdapat tanda-tanda menunjukkan ribut petir dengan intensiti hujan melebihi 20 mm/jam yang hampir ATAU dijangka berlaku melebihi sejam. Amaran ribut petir adalah amaran jangka pendek yang sah dalam tempoh tidak melebihi enam jam untuk satu-satu keluaran.Dikeluarkan pada: 8:50 pagi, 19 Julai 2023#ributpetirmetmalaysia#metmalaysia#NRECC#MalaysiaMADANI\", \"posted_on\": \"2023-07-19T08:10:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-6.fna.fbcdn.net/v/t39.30808-6/359820365_673960611440923_8917889804875379697_n.jpg?stp=dst-jpg_p180x540&_nc_cat=111&ccb=1-7&_nc_sid=730e14&_nc_ohc=-y_5nkpiGNwAX_MDpri&_nc_ht=scontent.fsgn2-6.fna&oh=00_AfBPw6FuCypVhR1Fd17Id5_Pd607-hjY8d8Fi78V-B1zXg&oe=64C64D34\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid06UmugEDE2xP8o9zRT4teXeGNLDvLcSqHEV8XhUXJSQHsJ2BqBBUBXFnHTWzurNrCl?__cft__[0]=AZVb7pUenGQZDAhiAJBJZ0PsUjWBIKwqO8Gj_VKH_b8IIGro3SmAJcsXdIFreZevraqxz3X0VGIqarrVpU657fcgpbhjS_mBdJDL3bUVE0YZz8qQGSXgZuGxKAypZzfdIr7ugyXazBPlBfXfhAoJf0T-rsiFTiymXlkja_NnxBiIzHxB-xyPxo42oJK9gs8wQGq-hgCl9enUMYlvy2cqp8ID-0Zm12e2BCSxnpkNGYdOsLnoweJzzIKQ6Z8b3W0J7Vk&__tn__=%2CO%2CP-R\"}, \"pfbid0kL6gvZb3RLv95hWh8JTWzqqdVBjSX5dVipfXJTd7ry3GHHyTM1s3utpppi8Vb9Al\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 3, \"reactions\": {\"likes\": 60, \"loves\": 5, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 65, \"comments\": 4, \"content\": \"SALAM MAAL HIJRAH KEPADA SEMUA UMAT ISLAM.1 MUHARRAM 1445 HIJRAH / 19 JULAI 2023 MASIHI #TAHUNBARUISLAM#maalhijrah\", \"posted_on\": \"2023-07-18T18:51:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-9.fna.fbcdn.net/v/t39.30808-6/361185956_696484765856410_2623582167112172370_n.jpg?stp=dst-jpg_s720x720&_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=_ALVBZYBHYcAX9eRWtH&_nc_ht=scontent.fsgn2-9.fna&oh=00_AfB-2tRns5mRPu9rbFtXUCvqPiuAPZGMxO3Q9Uz7Q2gnBw&oe=64C6C09B\", \"https://static.xx.fbcdn.net/rsrc.php/v3/y9/r/Z-dbClQDXLv.png\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0kL6gvZb3RLv95hWh8JTWzqqdVBjSX5dVipfXJTd7ry3GHHyTM1s3utpppi8Vb9Al?__cft__[0]=AZU4CeGmmfb2RHuT1V6eIiMTthe-N82ttbQ0SHCzqSBR4Th-5UOLIz-nqiFIzRpnCGoa249rksQ388K15jZxZoo_TPUlTn0hubqnP8oDLUW2gwfWt3ahKxJ3ahU1OLvbzysaHTEvKPuQW6E5NysysGvKLwSBD5UEL0fAeNwJ1ElwLlAxpmDgtDLZaPWpdR1_NabzGwjUfo7Szg9lDTds0oaM&__tn__=%2CO%2CP-R\"}, \"pfbid0319viAe2Fk1AzrJ7QJZJsAwfjEUbXAbCYxfrRv8DoDyH4ss2BHiB3yXFJ6Yx3J95Cl\": {\"name\": \"Majlis Bandaraya Pulau Pinang - MBPP\", \"shares\": 0, \"reactions\": {\"likes\": 11, \"loves\": 0, \"wow\": 0, \"cares\": 0, \"sad\": 0, \"angry\": 0, \"haha\": 0}, \"reaction_count\": 11, \"comments\": 1, \"content\": \"AMARAN RIBUT PETIR. Ribut petir, hujan lebat dan angin kencang dijangka di negeri Perlis \u2022 Kedah (Kubang Pasu, Kota Setar, Pokok Sena, Padang Terap, Yan, Pendang, Kuala Muda, Sik, Baling, Kulim dan Bandar Baharu) \u2022 Pulau Pinang \u2022 Pahang (Raub dan Bentong) \u2022 Selangor (Kuala Selangor dan Hulu Selangor) \u2022 Negeri Sembilan (Port Dickson, Rembau dan Tampin) \u2022 Melaka \u2022 Johor sehingga 9:00 pagi; Selasa, 18 Julai 2023.Amaran dikeluarkan apabila terdapat tanda-tanda menunjukkan ribut petir dengan intensiti hujan melebihi 20 mm/jam yang hampir ATAU dijangka berlaku melebihi sejam. Amaran ribut petir adalah amaran jangka pendek yang sah dalam tempoh tidak melebihi enam jam untuk satu-satu keluaran.Dikeluarkan pada: 6:10 pagi, 18 Julai 2023#ributpetirmetmalaysia#metmalaysia#NRECC#MalaysiaMADANI\", \"posted_on\": \"2023-07-18T06:49:00\", \"video\": [], \"image\": [\"https://scontent.fsgn2-4.fna.fbcdn.net/v/t39.30808-6/359792826_673378948165756_7378627215648239785_n.jpg?stp=dst-jpg_p180x540&_nc_cat=101&ccb=1-7&_nc_sid=730e14&_nc_ohc=KW3k3NgSg6EAX_8Nz_G&_nc_ht=scontent.fsgn2-4.fna&oh=00_AfAtoADj3JTP125V7XOprNipgg5VwyEiFt6gQQ65s2flUQ&oe=64C68DB5\"], \"post_url\": \"https://www.facebook.com/majlisbandaraya.pulaupinang/posts/pfbid0319viAe2Fk1AzrJ7QJZJsAwfjEUbXAbCYxfrRv8DoDyH4ss2BHiB3yXFJ6Yx3J95Cl?__cft__[0]=AZXy4a1d4qB22_s-AXF6Nx5RwT764MSKfDlcSCGF1aJLq0R20EDbEAMNBrrWBE4PHZH_Z4mRnQl2NPGPk74ZxJKPz_z-J-M2tdU-0OTnkjNdCvNQIedENPMSBPA55qn1FtNYl35SuZIM7bGT34YvtfLtozHWCkemq84m-KsqbG7P4rqBA1hVMVnFmSdMdRhUYyUnylUXWsyfJJYvD9aXdJVcP-4RqHN1g32BYOwBccPWh1d_8PJMM34WF4hJ4Q7Z2-g&__tn__=%2CO%2CP-R\"}}"
|
geckodriver.log
ADDED
The diff for this file is too large to render.
See raw diff
|
|
html_parser.py
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""HTML parser.
|
2 |
+
|
3 |
+
Contains parser for html files.
|
4 |
+
|
5 |
+
"""
|
6 |
+
import re
|
7 |
+
from pathlib import Path
|
8 |
+
from typing import Dict, Union
|
9 |
+
from abc import abstractmethod
|
10 |
+
from pathlib import Path
|
11 |
+
from typing import Dict, List, Optional, Union
|
12 |
+
|
13 |
+
|
14 |
+
class BaseParser:
|
15 |
+
"""Base class for all parsers."""
|
16 |
+
|
17 |
+
def __init__(self, parser_config: Optional[Dict] = None):
|
18 |
+
"""Init params."""
|
19 |
+
self._parser_config = parser_config
|
20 |
+
|
21 |
+
def init_parser(self) -> None:
|
22 |
+
"""Init parser and store it."""
|
23 |
+
parser_config = self._init_parser()
|
24 |
+
self._parser_config = parser_config
|
25 |
+
|
26 |
+
@property
|
27 |
+
def parser_config_set(self) -> bool:
|
28 |
+
"""Check if parser config is set."""
|
29 |
+
return self._parser_config is not None
|
30 |
+
|
31 |
+
@property
|
32 |
+
def parser_config(self) -> Dict:
|
33 |
+
"""Check if parser config is set."""
|
34 |
+
if self._parser_config is None:
|
35 |
+
raise ValueError("Parser config not set.")
|
36 |
+
return self._parser_config
|
37 |
+
|
38 |
+
@abstractmethod
|
39 |
+
def _init_parser(self) -> Dict:
|
40 |
+
"""Initialize the parser with the config."""
|
41 |
+
|
42 |
+
@abstractmethod
|
43 |
+
def parse_file(self, file: Path, errors: str = "ignore") -> Union[str, List[str]]:
|
44 |
+
"""Parse file."""
|
45 |
+
|
46 |
+
class HTMLParser(BaseParser):
|
47 |
+
"""HTML parser."""
|
48 |
+
|
49 |
+
def _init_parser(self) -> Dict:
|
50 |
+
"""Init parser."""
|
51 |
+
return {}
|
52 |
+
|
53 |
+
def parse_file(self, file: Path, errors: str = "ignore") -> Union[str, list[str]]:
|
54 |
+
"""Parse file.
|
55 |
+
|
56 |
+
Returns:
|
57 |
+
Union[str, List[str]]: a string or a List of strings.
|
58 |
+
"""
|
59 |
+
try:
|
60 |
+
from unstructured.partition.html import partition_html
|
61 |
+
from unstructured.staging.base import convert_to_isd
|
62 |
+
from unstructured.cleaners.core import clean
|
63 |
+
except ImportError:
|
64 |
+
raise ValueError("unstructured package is required to parse HTML files.")
|
65 |
+
|
66 |
+
# Using the unstructured library to convert the html to isd format
|
67 |
+
# isd sample : isd = [
|
68 |
+
# {"text": "My Title", "type": "Title"},
|
69 |
+
# {"text": "My Narrative", "type": "NarrativeText"}
|
70 |
+
# ]
|
71 |
+
with open(file, "r", encoding="utf-8") as fp:
|
72 |
+
elements = partition_html(file=fp)
|
73 |
+
isd = convert_to_isd(elements)
|
74 |
+
|
75 |
+
# Removing non ascii charactwers from isd_el['text']
|
76 |
+
for isd_el in isd:
|
77 |
+
isd_el['text'] = isd_el['text'].encode("ascii", "ignore").decode()
|
78 |
+
|
79 |
+
# Removing all the \n characters from isd_el['text'] using regex and replace with single space
|
80 |
+
# Removing all the extra spaces from isd_el['text'] using regex and replace with single space
|
81 |
+
for isd_el in isd:
|
82 |
+
isd_el['text'] = re.sub(r'\n', ' ', isd_el['text'], flags=re.MULTILINE | re.DOTALL)
|
83 |
+
isd_el['text'] = re.sub(r"\s{2,}", " ", isd_el['text'], flags=re.MULTILINE | re.DOTALL)
|
84 |
+
|
85 |
+
# more cleaning: extra_whitespaces, dashes, bullets, trailing_punctuation
|
86 |
+
for isd_el in isd:
|
87 |
+
clean(isd_el['text'], extra_whitespace=True, dashes=True, bullets=True, trailing_punctuation=True)
|
88 |
+
|
89 |
+
# Creating a list of all the indexes of isd_el['type'] = 'Title'
|
90 |
+
title_indexes = [i for i, isd_el in enumerate(isd) if isd_el['type'] == 'Title']
|
91 |
+
|
92 |
+
# Creating 'Chunks' - List of lists of strings
|
93 |
+
# each list starting with with isd_el['type'] = 'Title' and all the data till the next 'Title'
|
94 |
+
# Each Chunk can be thought of as an individual set of data, which can be sent to the model
|
95 |
+
# Where Each Title is grouped together with the data under it
|
96 |
+
|
97 |
+
Chunks = [[]]
|
98 |
+
final_chunks = list(list())
|
99 |
+
|
100 |
+
for i, isd_el in enumerate(isd):
|
101 |
+
if i in title_indexes:
|
102 |
+
Chunks.append([])
|
103 |
+
Chunks[-1].append(isd_el['text'])
|
104 |
+
|
105 |
+
# Removing all the chunks with sum of lenth of all the strings in the chunk < 25
|
106 |
+
# TODO: This value can be an user defined variable
|
107 |
+
for chunk in Chunks:
|
108 |
+
# sum of lenth of all the strings in the chunk
|
109 |
+
sum = 0
|
110 |
+
sum += len(str(chunk))
|
111 |
+
if sum < 25:
|
112 |
+
Chunks.remove(chunk)
|
113 |
+
else:
|
114 |
+
# appending all the approved chunks to final_chunks as a single string
|
115 |
+
final_chunks.append(" ".join([str(item) for item in chunk]))
|
116 |
+
return final_chunks
|
packages.txt
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
poppler-utils
|
2 |
-
tesseract-ocr
|
|
|
|
|
|
process_fb.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import ast
|
3 |
+
import os
|
4 |
+
import pinecone
|
5 |
+
|
6 |
+
from pydantic import Field
|
7 |
+
from vector_db import Document
|
8 |
+
from html_parser import HTMLParser
|
9 |
+
from langchain.vectorstores import Pinecone
|
10 |
+
from config import PINECONE_API_KEY, PINECONE_ENVIRONMENT, INDEX_NAME
|
11 |
+
from config import EMBEDDING_API_BASE, EMBEDDING_API_KEY, OPENAI_API_TYPE, OPENAI_API_VERSION, EMBEDDING_DEPLOYMENT_ID
|
12 |
+
from langchain.embeddings import OpenAIEmbeddings
|
13 |
+
|
14 |
+
|
15 |
+
# initialize pinecone
|
16 |
+
pinecone.init(
|
17 |
+
api_key=PINECONE_API_KEY, # find at app.pinecone.io
|
18 |
+
environment=PINECONE_ENVIRONMENT, # next to api key in console
|
19 |
+
)
|
20 |
+
|
21 |
+
# Azure embedding model definition
|
22 |
+
embeddings = OpenAIEmbeddings(
|
23 |
+
deployment=EMBEDDING_DEPLOYMENT_ID,
|
24 |
+
openai_api_key=EMBEDDING_API_KEY,
|
25 |
+
openai_api_base=EMBEDDING_API_BASE,
|
26 |
+
openai_api_type=OPENAI_API_TYPE,
|
27 |
+
openai_api_version=OPENAI_API_VERSION,
|
28 |
+
chunk_size=16
|
29 |
+
)
|
30 |
+
|
31 |
+
if INDEX_NAME and INDEX_NAME not in pinecone.list_indexes():
|
32 |
+
pinecone.create_index(
|
33 |
+
INDEX_NAME,
|
34 |
+
metric="cosine",
|
35 |
+
dimension=1536
|
36 |
+
)
|
37 |
+
print(f"Index {INDEX_NAME} created successfully")
|
38 |
+
|
39 |
+
index = pinecone.Index(INDEX_NAME)
|
40 |
+
|
41 |
+
with open('data.json') as json_file:
|
42 |
+
data = json.load(json_file)
|
43 |
+
datas = ast.literal_eval(data)
|
44 |
+
|
45 |
+
texts = []
|
46 |
+
for k, v in datas.items():
|
47 |
+
content = v["content"]
|
48 |
+
post_url = v["post_url"]
|
49 |
+
texts.append(Document(page_content=content, metadata={"source": post_url}))
|
50 |
+
|
51 |
+
if len(texts)>0:
|
52 |
+
Pinecone.from_documents(texts, embeddings, index_name=INDEX_NAME)
|
53 |
+
message = f"Add files to {INDEX_NAME} sucessfully"
|
54 |
+
print(message)
|
55 |
+
|
process_html.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
import os
|
4 |
+
import pinecone
|
5 |
+
|
6 |
+
from pydantic import Field
|
7 |
+
from vector_db import Document
|
8 |
+
from html_parser import HTMLParser
|
9 |
+
from langchain.vectorstores import Pinecone
|
10 |
+
from config import PINECONE_API_KEY, PINECONE_ENVIRONMENT, INDEX_NAME
|
11 |
+
from config import EMBEDDING_API_BASE, EMBEDDING_API_KEY, OPENAI_API_TYPE, OPENAI_API_VERSION, EMBEDDING_DEPLOYMENT_ID
|
12 |
+
from langchain.embeddings import OpenAIEmbeddings
|
13 |
+
|
14 |
+
WEBSITE_FOLDER = 'website'
|
15 |
+
parser = HTMLParser()
|
16 |
+
|
17 |
+
# initialize pinecone
|
18 |
+
pinecone.init(
|
19 |
+
api_key=PINECONE_API_KEY, # find at app.pinecone.io
|
20 |
+
environment=PINECONE_ENVIRONMENT, # next to api key in console
|
21 |
+
)
|
22 |
+
|
23 |
+
# Azure embedding model definition
|
24 |
+
embeddings = OpenAIEmbeddings(
|
25 |
+
deployment=EMBEDDING_DEPLOYMENT_ID,
|
26 |
+
openai_api_key=EMBEDDING_API_KEY,
|
27 |
+
openai_api_base=EMBEDDING_API_BASE,
|
28 |
+
openai_api_type=OPENAI_API_TYPE,
|
29 |
+
openai_api_version=OPENAI_API_VERSION,
|
30 |
+
chunk_size=16
|
31 |
+
)
|
32 |
+
|
33 |
+
if INDEX_NAME and INDEX_NAME not in pinecone.list_indexes():
|
34 |
+
pinecone.create_index(
|
35 |
+
INDEX_NAME,
|
36 |
+
metric="cosine",
|
37 |
+
dimension=1536
|
38 |
+
)
|
39 |
+
print(f"Index {INDEX_NAME} created successfully")
|
40 |
+
|
41 |
+
index = pinecone.Index(INDEX_NAME)
|
42 |
+
index.delete(delete_all=True)
|
43 |
+
|
44 |
+
files_src = os.listdir(WEBSITE_FOLDER)
|
45 |
+
documents = []
|
46 |
+
for file in files_src:
|
47 |
+
filepath = os.path.join(WEBSITE_FOLDER, file)
|
48 |
+
filename = os.path.basename(filepath)
|
49 |
+
data = parser.parse_file(filepath)
|
50 |
+
texts= []
|
51 |
+
for d in data:
|
52 |
+
texts.append(Document(page_content=d, metadata={"source": filepath, "document_id": filename}))
|
53 |
+
documents.extend(texts)
|
54 |
+
# print(len(documents))
|
55 |
+
# if len(documents)>0:
|
56 |
+
# document_id = [d.metadata['document_id'] + f"_{idx}" for (idx, d) in enumerate(documents)]
|
57 |
+
# Pinecone.from_documents(documents, embeddings, ids=document_id, index_name=INDEX_NAME)
|
58 |
+
# message = f"Add files to {INDEX_NAME} sucessfully"
|
prompts/__pycache__/condense_llm.cpython-39.pyc
ADDED
Binary file (406 Bytes). View file
|
|
prompts/__pycache__/custom_chain.cpython-39.pyc
ADDED
Binary file (797 Bytes). View file
|
|
prompts/__pycache__/llm.cpython-39.pyc
ADDED
Binary file (1.39 kB). View file
|
|
prompts/__pycache__/stage_analyzer.cpython-39.pyc
ADDED
Binary file (3.6 kB). View file
|
|
prompts/__pycache__/summary.cpython-39.pyc
ADDED
Binary file (382 Bytes). View file
|
|
prompts/__pycache__/web_search.cpython-39.pyc
ADDED
Binary file (863 Bytes). View file
|
|
prompts/condense_llm.py
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
condense_template = """Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.
|
2 |
+
Chat History:
|
3 |
+
{chat_history}
|
4 |
+
Follow Up Input: {question}
|
5 |
+
Standalone question:"""
|
prompts/custom_chain.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ----------------------prompt template -----------------------
|
2 |
+
SYSTEM_PROMPT_TEMPLATE = \
|
3 |
+
"""
|
4 |
+
You are an AI sales assistant for Amazon, the largest e-commerce marketplace in the world.
|
5 |
+
Your task is to generate 3 different versions of the given user question to retrieve relevant documents from a vector database but keep every single question by the end-of-sentence token.
|
6 |
+
By generating multiple perspectives on the user question, your goal is to help the user overcome some of the limitations
|
7 |
+
of distance-based similarity search. Provide these alternative questions separated by commas.
|
8 |
+
Expected output:
|
9 |
+
version 1, version 2, version 3.
|
10 |
+
"""
|
11 |
+
|
12 |
+
HUMAN_PROMPT_TEMPLATE = "Original question: {question}"
|
prompts/llm.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
qa_prompt_template = """You are a DocsFPT, a friendly and helpful AI assistant of FPT Software providing documentation help.
|
2 |
+
Search result:
|
3 |
+
---------------------
|
4 |
+
{context}
|
5 |
+
---------------------
|
6 |
+
Instructions: Compose a comprehensive reply to the query using the search results given.
|
7 |
+
If the search result does not relate to the query or no search result is provided, simply state 'I don't have the information for this question, please provide me with more relevant documents so I can help you'.
|
8 |
+
Do not use prior knowledge about FPT to answer the question.
|
9 |
+
Make sure to cite results using [number] notation (every result has this number at the beginning) after the reference.
|
10 |
+
Citation should be done at the end of each sentence. If the search results mention multiple subjects with the same name, create separate answers for each.
|
11 |
+
Only include information found in the search result and don't add any additional information.
|
12 |
+
Make sure the answer is correct and don't output false content.
|
13 |
+
Ignore outlier search results that have nothing to do with the question.
|
14 |
+
Answer user queries in its original language with a friendly tone.
|
15 |
+
Answer step-by-step.
|
16 |
+
|
17 |
+
Conversation history:
|
18 |
+
{chat_history}
|
19 |
+
Human: {question}
|
20 |
+
Assistant:"""
|
prompts/stage_analyzer.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#-------------------------- stage analyzer chain ---------------------------------
|
2 |
+
SYSTEM_MESSAGE_PROMPT = \
|
3 |
+
"""
|
4 |
+
##Role
|
5 |
+
You are a sales assistant helping your sales agent to determine which stage of a sales conversation should the agent move to, or stay at.
|
6 |
+
|
7 |
+
##Instructions
|
8 |
+
- Analyze the given context and conversation history
|
9 |
+
- Determine what should be the next instant chat stage for the agent in the sales chat by choosing one from the following options:
|
10 |
+
1. Introduction: Start the conversation by introducing yourself and your company. Be polite and respectful while keeping the tone of the conversation professional.
|
11 |
+
2. Qualification: Qualify the prospect by confirming if they are the right person to talk to regarding your product/service. Ensure that they have the authority to make purchasing decisions.
|
12 |
+
3. Value proposition: Briefly explain how your product/service can benefit the prospect. Focus on the unique selling points and value proposition of your product/service that sets it apart from competitors.
|
13 |
+
4. Needs analysis: Ask open-ended questions to uncover the prospect's needs and pain points. Listen carefully to their responses and take notes.
|
14 |
+
5. Solution presentation: Based on the prospect's needs, present your product/service as the solution that can address their pain points.
|
15 |
+
6. Objection handling: Address any objections that the prospect may have regarding your product/service. Be prepared to provide evidence or testimonials to support your claims.
|
16 |
+
7. Close: Ask for the sale by proposing a next step. This could be a demo, a trial or a meeting with decision-makers. Ensure to summarize what has been discussed and reiterate the benefits.
|
17 |
+
- Only answer with a number between 1 through 7 with a best guess of what stage should the conversation continue with.
|
18 |
+
|
19 |
+
##Rules
|
20 |
+
- If there is no conversation history, output 1.
|
21 |
+
- The answer needs to be one number only, no words.
|
22 |
+
- Do not answer anything else nor add anything to you answer."""
|
23 |
+
|
24 |
+
HUMAN_MESSAGE_PROMPT = \
|
25 |
+
"""\
|
26 |
+
Conversation history:
|
27 |
+
{chat_history}
|
28 |
+
As a/an Role, you must execute Instructions and follow provided Rules.
|
29 |
+
AI answer:"""
|
30 |
+
|
31 |
+
conversation_stages = {
|
32 |
+
"1": "Introduction: Start the conversation by introducing yourself and your company. Be polite and respectful while keeping the tone of the conversation professional. Your greeting should be welcoming. Always clarify in your greeting the reason why you are contacting the prospect.",
|
33 |
+
"2": "Qualification: Qualify the prospect by confirming if they are the right person to talk to regarding your product/service. Ensure that they have the authority to make purchasing decisions.",
|
34 |
+
"3": "Value proposition: Briefly explain how your product/service can benefit the prospect. Focus on the unique selling points and value proposition of your product/service that sets it apart from competitors.",
|
35 |
+
"4": "Needs analysis: Ask open-ended questions to uncover the prospect's needs and pain points. Listen carefully to their responses and take notes.",
|
36 |
+
"5": "Solution presentation: Based on the prospect's needs, present your product/service as the solution that can address their pain points.",
|
37 |
+
"6": "Objection handling: Address any objections that the prospect may have regarding your product/service. Be prepared to provide evidence or testimonials to support your claims.",
|
38 |
+
"7": "Close: Ask for the sale by proposing a next step. This could be a demo, a trial or a meeting with decision-makers. Ensure to summarize what has been discussed and reiterate the benefits.",
|
39 |
+
}
|
prompts/summary.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
system_template = "When provided with a question and a HTML document, generate a concise summary of \
|
2 |
+
the document's content that directly addresses the question."
|
3 |
+
|
4 |
+
human_template = "Question: {question}\nHTML Document: {doc}"
|
prompts/web_search.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
SYSTEM_PROMPT_TEMPLATE = "You are a DocsFPT, a friendly and helpful AI assistant of FPT Software providing documentation help."
|
2 |
+
HUMAN_PROMPT_TEMPLATE = \
|
3 |
+
"""\
|
4 |
+
Web search result:
|
5 |
+
---------------------
|
6 |
+
{context}
|
7 |
+
---------------------
|
8 |
+
Instructions: Using the provided web search results, write a comprehensive reply to the given query.
|
9 |
+
Make sure to cite results using [[number](URL)] notation after the reference
|
10 |
+
Citation should be done at the end of each sentence.
|
11 |
+
If the provided search results refer to multiple subjects with the same name, write separate answers for each subject.
|
12 |
+
Answer in a friendly tone.
|
13 |
+
Answer step-by-step.
|
14 |
+
|
15 |
+
Conversation history:
|
16 |
+
{chat_history}
|
17 |
+
Human: {question}
|
18 |
+
Assistant:"""
|
requirements.txt
CHANGED
@@ -1,6 +1,9 @@
|
|
1 |
-
|
2 |
-
PyMuPDF
|
3 |
openai
|
4 |
-
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
langchain==0.0.200
|
|
|
2 |
openai
|
3 |
+
PyPDF2
|
4 |
+
gradio==3.33.1
|
5 |
+
gradio_client==0.2.7
|
6 |
+
tiktoken
|
7 |
+
pinecone-client
|
8 |
+
google-api-python-client
|
9 |
+
facebook-page-scraper
|
scrab_fb.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from facebook_page_scraper import Facebook_scraper
|
3 |
+
from facebook_page_scraper import Facebook_scraper
|
4 |
+
|
5 |
+
#instantiate the Facebook_scraper class
|
6 |
+
page_name = "majlisbandaraya.pulaupinang"
|
7 |
+
posts_count = 30
|
8 |
+
browser = "firefox"
|
9 |
+
|
10 |
+
timeout = 600 #600 seconds
|
11 |
+
headless = True
|
12 |
+
meta_ai = Facebook_scraper(page_name, posts_count, browser, timeout=timeout, headless=headless)
|
13 |
+
json_data = meta_ai.scrap_to_json()
|
14 |
+
|
15 |
+
with open('data.json', 'w') as f:
|
16 |
+
json.dump(json_data, f)
|
utils.py
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import datetime
|
2 |
+
import os
|
3 |
+
|
4 |
+
from prompts.llm import qa_prompt_template
|
5 |
+
from prompts.condense_llm import condense_template
|
6 |
+
from typing import Dict, Any
|
7 |
+
from config import HISTORY_DIR
|
8 |
+
|
9 |
+
def get_messages_last_content(data: Dict[str, Any], **_: Any) -> str:
|
10 |
+
""" get the last content of the llm request messages array
|
11 |
+
|
12 |
+
:param data: the user llm request data
|
13 |
+
:type data: Dict[str, Any]
|
14 |
+
|
15 |
+
Example:
|
16 |
+
.. code-block:: python
|
17 |
+
|
18 |
+
from gptcache.processor.pre import get_messages_last_content
|
19 |
+
|
20 |
+
content = get_messages_last_content({"messages": [{"content": "hello"}, {"content": "world"}]})
|
21 |
+
# "world"
|
22 |
+
"""
|
23 |
+
result = data.get("messages")[-1].content.split("Human:")[-1].split("Assistant:")[0].strip()
|
24 |
+
print(result)
|
25 |
+
return result
|
26 |
+
|
27 |
+
|
28 |
+
def transcribe(current_model, audio):
|
29 |
+
return current_model.audio_response(audio)
|
30 |
+
|
31 |
+
|
32 |
+
def history_file_path(username):
|
33 |
+
dirname = os.path.join(HISTORY_DIR, username)
|
34 |
+
os.makedirs(dirname, exist_ok=True)
|
35 |
+
now = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
|
36 |
+
history_path = os.path.join(dirname, f"{now}.json")
|
37 |
+
return history_path
|
38 |
+
|
39 |
+
def load_lasted_file_username(username):
|
40 |
+
if username not in os.listdir(HISTORY_DIR):
|
41 |
+
return None
|
42 |
+
date_time_list = []
|
43 |
+
for filename in os.listdir(os.path.join(HISTORY_DIR, username)):
|
44 |
+
date_time_list.append(datetime.datetime.strptime(filename[:19], '%Y-%m-%d_%H-%M-%S'))
|
45 |
+
|
46 |
+
lasted_time = max(date_time_list)
|
47 |
+
lasted_file = lasted_time.strftime('%Y-%m-%d_%H-%M-%S')
|
48 |
+
return os.path.join(HISTORY_DIR, username, lasted_file)
|
49 |
+
|
50 |
+
|
51 |
+
def load_chat_history(current_model, *args):
|
52 |
+
return current_model.load_history(*args)
|
53 |
+
|
54 |
+
|
55 |
+
def predict(chatbot, model, inputs, use_websearch, custom_websearch):
|
56 |
+
iter = model.inference(inputs=inputs, chatbot=chatbot, streaming=True, use_websearch=use_websearch,
|
57 |
+
custom_websearch=custom_websearch, qa_prompt_template=qa_prompt_template,
|
58 |
+
condense_prompt_template=condense_template)
|
59 |
+
for response in iter:
|
60 |
+
yield response
|
61 |
+
|
62 |
+
|
63 |
+
def set_user_indentifier(current_model, *args):
|
64 |
+
return current_model.set_user_indentifier(*args)
|
65 |
+
|
66 |
+
|
67 |
+
def retry(chatbot, model, use_websearch, custom_websearch):
|
68 |
+
model.delete_last_conversation()
|
69 |
+
if len(chatbot) > 0:
|
70 |
+
inputs = chatbot[-1][0]
|
71 |
+
chatbot = predict(chatbot, model, inputs, use_websearch, custom_websearch)
|
72 |
+
yield chatbot
|
73 |
+
|
74 |
+
|
75 |
+
def reset(current_model):
|
76 |
+
return current_model.reset_conversation()
|
77 |
+
|
78 |
+
|
79 |
+
def delete_chat_history(current_model, *args):
|
80 |
+
return current_model.delete_history(*args)
|
81 |
+
|
82 |
+
|
83 |
+
def delete_first_conversation(current_model):
|
84 |
+
return current_model.delete_first_conversation()
|
85 |
+
|
86 |
+
|
87 |
+
def delete_last_conversation(current_model, chatbot):
|
88 |
+
if len(chatbot) > 0:
|
89 |
+
chatbot.pop()
|
90 |
+
current_model.delete_last_conversation()
|
91 |
+
return chatbot
|
92 |
+
|
93 |
+
|
94 |
+
def add_source_numbers(lst, source_name = "Source", use_source = True):
|
95 |
+
if use_source:
|
96 |
+
return [f'[{idx+1}]\t "{item[0]}"\n{source_name}: {item[1]}' for idx, item in enumerate(lst)]
|
97 |
+
else:
|
98 |
+
return [f'[{idx+1}]\t "{item}"' for idx, item in enumerate(lst)]
|
99 |
+
|
100 |
+
def add_details(lst):
|
101 |
+
nodes = []
|
102 |
+
for txt in lst:
|
103 |
+
brief = txt[:25].replace("\n", "")
|
104 |
+
nodes.append(
|
105 |
+
f"<details><summary>{brief}...</summary><p>{txt}</p></details>"
|
106 |
+
)
|
107 |
+
return nodes
|
vector_db.py
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pinecone
|
2 |
+
import os
|
3 |
+
import json
|
4 |
+
import ast
|
5 |
+
import PyPDF2
|
6 |
+
import shutil
|
7 |
+
import gradio as gr
|
8 |
+
|
9 |
+
from tqdm import tqdm
|
10 |
+
from pydantic import Field
|
11 |
+
from typing import List, Optional
|
12 |
+
from langchain.load.serializable import Serializable
|
13 |
+
|
14 |
+
from langchain.vectorstores import Pinecone
|
15 |
+
from config import PINECONE_API_KEY, PINECONE_ENVIRONMENT, INDEX_NAME, SAVE_DIR
|
16 |
+
from config import EMBEDDING_API_BASE, EMBEDDING_API_KEY, OPENAI_API_TYPE, OPENAI_API_VERSION, EMBEDDING_DEPLOYMENT_ID
|
17 |
+
from langchain.embeddings import OpenAIEmbeddings
|
18 |
+
from langchain.text_splitter import TokenTextSplitter
|
19 |
+
|
20 |
+
# initialize pinecone
|
21 |
+
pinecone.init(
|
22 |
+
api_key=PINECONE_API_KEY, # find at app.pinecone.io
|
23 |
+
environment=PINECONE_ENVIRONMENT, # next to api key in console
|
24 |
+
)
|
25 |
+
|
26 |
+
# Azure embedding model definition
|
27 |
+
embeddings = OpenAIEmbeddings(
|
28 |
+
deployment=EMBEDDING_DEPLOYMENT_ID,
|
29 |
+
openai_api_key=EMBEDDING_API_KEY,
|
30 |
+
openai_api_base=EMBEDDING_API_BASE,
|
31 |
+
openai_api_type=OPENAI_API_TYPE,
|
32 |
+
openai_api_version=OPENAI_API_VERSION,
|
33 |
+
chunk_size=16
|
34 |
+
)
|
35 |
+
|
36 |
+
text_splitter = TokenTextSplitter(chunk_size=500, chunk_overlap=30)
|
37 |
+
if INDEX_NAME and INDEX_NAME not in pinecone.list_indexes():
|
38 |
+
pinecone.create_index(
|
39 |
+
INDEX_NAME,
|
40 |
+
metric="cosine",
|
41 |
+
dimension=1536
|
42 |
+
)
|
43 |
+
print(f"Index {INDEX_NAME} created successfully")
|
44 |
+
index = pinecone.Index(INDEX_NAME)
|
45 |
+
|
46 |
+
class Document(Serializable):
|
47 |
+
"""Class for storing a piece of text and associated metadata."""
|
48 |
+
|
49 |
+
page_content: str
|
50 |
+
"""String text."""
|
51 |
+
metadata: dict = Field(default_factory=dict)
|
52 |
+
"""Arbitrary metadata about the page content (e.g., source, relationships to other
|
53 |
+
documents, etc.).
|
54 |
+
"""
|
55 |
+
|
56 |
+
|
57 |
+
def delete_all():
|
58 |
+
for files in os.listdir(SAVE_DIR):
|
59 |
+
os.remove(os.path.join(SAVE_DIR, files))
|
60 |
+
index.delete(delete_all=True)
|
61 |
+
message = "Delete all files succesfully"
|
62 |
+
return gr.update(choices=[]), message, gr.Files.update(None)
|
63 |
+
|
64 |
+
def delete_file(files_src):
|
65 |
+
file_name = []
|
66 |
+
for files in files_src:
|
67 |
+
os.remove(os.path.join(SAVE_DIR, files))
|
68 |
+
file_name.append(files)
|
69 |
+
_filter = {"document_id": {"$in": file_name}}
|
70 |
+
index.delete(filter=_filter)
|
71 |
+
message = f"Delete {len(files_src)} files succesfully"
|
72 |
+
return gr.update(choices=os.listdir(SAVE_DIR)), message, gr.Files.update(None)
|
73 |
+
|
74 |
+
def upload_file():
|
75 |
+
vectorstore = Pinecone.from_existing_index(INDEX_NAME, embeddings)
|
76 |
+
print(f"Load files from existing {INDEX_NAME}")
|
77 |
+
return vectorstore
|
78 |
+
|
79 |
+
|
80 |
+
def handle_upload_file(files):
|
81 |
+
documents = get_documents(files)
|
82 |
+
if len(documents)>0:
|
83 |
+
Pinecone.from_documents(documents, embeddings, index_name=INDEX_NAME)
|
84 |
+
message = f"Add files to {INDEX_NAME} sucessfully"
|
85 |
+
print(message)
|
86 |
+
else:
|
87 |
+
message = f"Load files from existing {INDEX_NAME}"
|
88 |
+
print(message)
|
89 |
+
return message
|
90 |
+
|
91 |
+
def update_file():
|
92 |
+
with open('data.json') as json_file:
|
93 |
+
data = json.load(json_file)
|
94 |
+
datas = ast.literal_eval(data)
|
95 |
+
|
96 |
+
texts = []
|
97 |
+
for k, v in datas.items():
|
98 |
+
content = v["content"]
|
99 |
+
post_url = v["post_url"]
|
100 |
+
texts.append(Document(page_content=content, metadata={"source": post_url}))
|
101 |
+
|
102 |
+
if len(texts)>0:
|
103 |
+
Pinecone.from_documents(texts, embeddings, index_name=INDEX_NAME)
|
104 |
+
message = f"Add facebook data to {INDEX_NAME} sucessfully"
|
105 |
+
return message
|
106 |
+
|
107 |
+
def get_documents(file_src):
|
108 |
+
|
109 |
+
documents = []
|
110 |
+
if file_src is None:
|
111 |
+
return documents
|
112 |
+
for file in file_src:
|
113 |
+
filepath = file.name
|
114 |
+
filename = os.path.basename(filepath)
|
115 |
+
file_type = os.path.splitext(filename)[1]
|
116 |
+
if filename in os.listdir(SAVE_DIR):
|
117 |
+
continue
|
118 |
+
else:
|
119 |
+
shutil.copy(filepath, os.path.join(SAVE_DIR, filename))
|
120 |
+
try:
|
121 |
+
if file_type == ".pdf":
|
122 |
+
pdftext = ""
|
123 |
+
with open(filepath, "rb") as pdfFileObj:
|
124 |
+
pdf_reader = PyPDF2.PdfReader(pdfFileObj)
|
125 |
+
for page in tqdm(pdf_reader.pages):
|
126 |
+
pdftext += page.extract_text()
|
127 |
+
texts = [Document(page_content=pdftext, metadata={"source": filepath})]
|
128 |
+
elif file_type == ".docx":
|
129 |
+
from langchain.document_loaders import UnstructuredWordDocumentLoader
|
130 |
+
loader = UnstructuredWordDocumentLoader(filepath)
|
131 |
+
texts = loader.load()
|
132 |
+
elif file_type == ".pptx":
|
133 |
+
from langchain.document_loaders import UnstructuredPowerPointLoader
|
134 |
+
loader = UnstructuredPowerPointLoader(filepath)
|
135 |
+
texts = loader.load()
|
136 |
+
else:
|
137 |
+
from langchain.document_loaders import TextLoader
|
138 |
+
loader = TextLoader(filepath, "utf8")
|
139 |
+
texts = loader.load()
|
140 |
+
except Exception as e:
|
141 |
+
import traceback
|
142 |
+
traceback.print_exc()
|
143 |
+
texts = text_splitter.split_documents(texts)
|
144 |
+
documents.extend(texts)
|
145 |
+
return documents
|
146 |
+
|
147 |
+
if __name__ == "__main__":
|
148 |
+
upload_file(["STANDARD_SOFTWARE LIFECYCLES.pdf"])
|