TheoLvs commited on
Commit
ff42e3f
1 Parent(s): 9dedc2d

Updated CSS and app

Browse files
Files changed (2) hide show
  1. app.py +184 -85
  2. style.css +120 -1
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  from haystack.document_stores import FAISSDocumentStore
3
  from haystack.nodes import EmbeddingRetriever
4
  import openai
 
5
  import os
6
  from utils import (
7
  make_pairs,
@@ -13,15 +14,21 @@ import numpy as np
13
  from datetime import datetime
14
  from azure.storage.fileshare import ShareServiceClient
15
 
 
 
 
 
 
 
16
 
17
  theme = gr.themes.Soft(
18
  primary_hue="sky",
19
- font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"],
20
  )
21
 
22
  init_prompt = (
23
  "You are ClimateQA, an AI Assistant by Ekimetrics. "
24
- "You are given a question and extracted parts of IPCC reports. "
25
  "Provide a clear and structured answer based on the context provided. "
26
  "When relevant, use bullet points and lists to structure your answers."
27
  )
@@ -35,7 +42,7 @@ sources_prompt = (
35
 
36
 
37
  def get_reformulation_prompt(query: str) -> str:
38
- return f"""Reformulate the following user message to be a short standalone question in English, in the context of an educationnal discussion about climate change.
39
  ---
40
  query: La technologie nous sauvera-t-elle ?
41
  standalone question: Can technology help humanity mitigate the effects of climate change?
@@ -45,6 +52,10 @@ query: what are our reserves in fossil fuel?
45
  standalone question: What are the current reserves of fossil fuels and how long will they last?
46
  language: English
47
  ---
 
 
 
 
48
  query: {query}
49
  standalone question:"""
50
 
@@ -59,24 +70,24 @@ openai.api_key = os.environ["api_key"]
59
  openai.api_base = os.environ["ressource_endpoint"]
60
  openai.api_version = "2022-12-01"
61
 
62
- retrieve_all = EmbeddingRetriever(
63
  document_store=FAISSDocumentStore.load(
64
- index_path="./documents/climate_gpt_v2.faiss",
65
- config_path="./documents/climate_gpt_v2.json",
66
  ),
67
  embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1",
68
  model_format="sentence_transformers",
69
  progress_bar=False,
70
  )
71
 
72
- retrieve_giec = EmbeddingRetriever(
73
- document_store=FAISSDocumentStore.load(
74
- index_path="./documents/climate_gpt_v2_only_giec.faiss",
75
- config_path="./documents/climate_gpt_v2_only_giec.json",
76
- ),
77
- embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1",
78
- model_format="sentence_transformers",
79
- )
80
 
81
  credential = {
82
  "account_key": os.environ["account_key"],
@@ -90,11 +101,76 @@ share_client = service.get_share_client(file_share_name)
90
  user_id = create_user_id(10)
91
 
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  def chat(
94
  user_id: str,
95
  query: str,
96
  history: list = [system_template],
97
- report_type: str = "IPCC only",
98
  threshold: float = 0.555,
99
  ) -> tuple:
100
  """retrieve relevant documents in the document store then query gpt-turbo
@@ -109,12 +185,14 @@ def chat(
109
  tuple: chat gradio format, chat openai format, sources used.
110
  """
111
 
112
- if report_type == "All available":
113
- retriever = retrieve_all
114
- elif report_type == "IPCC only":
115
- retriever = retrieve_giec
116
- else:
117
- raise Exception("report_type arg should be in (All available, IPCC only)")
 
 
118
 
119
  reformulated_query = openai.Completion.create(
120
  engine="climateGPT",
@@ -126,16 +204,29 @@ def chat(
126
  reformulated_query = reformulated_query["choices"][0]["text"]
127
  reformulated_query, language = reformulated_query.split("\n")
128
  language = language.split(":")[1].strip()
129
- docs = [d for d in retriever.retrieve(query=reformulated_query, top_k=10) if d.score > threshold]
 
 
 
 
 
 
 
 
 
 
130
  messages = history + [{"role": "user", "content": query}]
131
 
132
- if docs:
133
  docs_string = []
134
- for i, d in enumerate(docs, 1):
135
- content = d.content.replace("\r\n", "")
136
- docs_string.append(f"📃 doc {i}: {d.meta['file_name']} page {d.meta['page_number']}\n{content}")
137
- sources = "\n\n".join([f"Query used for retrieval:\n{reformulated_query}"] + docs_string)
138
- messages.append({"role": "system", "content": f"{sources_prompt}\n\n{sources}\n\nAnswer in {language}:"})
 
 
 
139
 
140
  response = openai.Completion.create(
141
  engine="climateGPT",
@@ -167,14 +258,14 @@ def chat(
167
  complete_response += chunk_message
168
  messages[-1]["content"] = complete_response
169
  gradio_format = make_pairs([a["content"] for a in messages[1:]])
170
- yield gradio_format, messages, sources
171
 
172
  else:
173
- sources = "⚠️ No relevant passages found in the climate science reports"
174
- complete_response = "**⚠️ No relevant passages found in the climate science reports, you may want to ask a more specific question (specifying your question on climate issues).**"
175
  messages.append({"role": "assistant", "content": complete_response})
176
  gradio_format = make_pairs([a["content"] for a in messages[1:]])
177
- yield gradio_format, messages, sources
178
 
179
 
180
  def save_feedback(feed: str, user_id):
@@ -205,35 +296,11 @@ with gr.Blocks(title="🌍 Climate Q&A", css="style.css", theme=theme) as demo:
205
  # Gradio
206
  gr.Markdown("<h1><center>Climate Q&A 🌍</center></h1>")
207
  gr.Markdown("<h4><center>Ask climate-related questions to the IPCC reports</center></h4>")
208
- with gr.Row():
209
- with gr.Column(scale=1):
210
- gr.Markdown(
211
- """
212
- <p><b>Climate change and environmental disruptions have become some of the most pressing challenges facing our planet today</b>. As global temperatures rise and ecosystems suffer, it is essential for individuals to understand the gravity of the situation in order to make informed decisions and advocate for appropriate policy changes.</p>
213
- <p>However, comprehending the vast and complex scientific information can be daunting, as the scientific consensus references, such as <b>the Intergovernmental Panel on Climate Change (IPCC) reports, span thousands of pages</b>. To bridge this gap and make climate science more accessible, we introduce <b>ClimateQ&A as a tool to distill expert-level knowledge into easily digestible insights about climate science.</b></p>
214
- <div class="tip-box">
215
- <div class="tip-box-title">
216
- <span class="light-bulb" role="img" aria-label="Light Bulb">💡</span>
217
- How does ClimateQ&A work?
218
- </div>
219
- ClimateQ&A harnesses modern OCR techniques to parse and preprocess IPCC reports. By leveraging state-of-the-art question-answering algorithms, <i>ClimateQ&A is able to sift through the extensive collection of climate scientific reports and identify relevant passages in response to user inquiries</i>. Furthermore, the integration of the ChatGPT API allows ClimateQ&A to present complex data in a user-friendly manner, summarizing key points and facilitating communication of climate science to a wider audience.
220
- </div>
221
-
222
- <div class="warning-box">
223
- Version 0.2-beta - This tool is under active development
224
- </div>
225
-
226
-
227
- """
228
- )
229
 
230
- with gr.Column(scale=1):
231
- gr.Markdown("![](https://i.postimg.cc/fLvsvMzM/Untitled-design-5.png)")
232
- gr.Markdown("*Source : IPCC AR6 - Synthesis Report of the IPCC 6th assessment report (AR6)*")
233
 
234
  with gr.Row():
235
  with gr.Column(scale=2):
236
- chatbot = gr.Chatbot(elem_id="chatbot", label="ClimateQ&A chatbot")
237
  state = gr.State([system_template])
238
 
239
  with gr.Row():
@@ -245,15 +312,15 @@ Version 0.2-beta - This tool is under active development
245
 
246
  examples_questions = gr.Examples(
247
  [
248
- "What are the main causes of climate change?",
 
249
  "What are the impacts of climate change?",
250
  "Can climate change be reversed?",
251
  "What is the difference between climate change and global warming?",
252
- "What can individuals do to address climate change? Answer with bullet points",
253
- "What evidence do we have of climate change?",
254
  "What is the Paris Agreement and why is it important?",
255
  "Which industries have the highest GHG emissions?",
256
- "Is climate change caused by humans?",
257
  "Is climate change a hoax created by the government or environmental organizations?",
258
  "What is the relationship between climate change and biodiversity loss?",
259
  "What is the link between gender equality and climate change?",
@@ -284,19 +351,21 @@ Version 0.2-beta - This tool is under active development
284
 
285
  with gr.Column(scale=1, variant="panel"):
286
  gr.Markdown("### Sources")
287
- sources_textbox = gr.Textbox(interactive=False, show_label=False, max_lines=50)
288
 
 
 
 
 
 
289
  ask.submit(
290
  fn=chat,
291
  inputs=[
292
  user_id_state,
293
  ask,
294
  state,
295
- gr.inputs.Dropdown(
296
- ["IPCC only", "All available"],
297
- default="IPCC only",
298
- label="Select reports",
299
- ),
300
  ],
301
  outputs=[chatbot, state, sources_textbox],
302
  )
@@ -308,10 +377,38 @@ Version 0.2-beta - This tool is under active development
308
  user_id_state,
309
  ask_examples_hidden,
310
  state,
 
311
  ],
312
  outputs=[chatbot, state, sources_textbox],
313
  )
314
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  gr.Markdown("## How to use ClimateQ&A")
316
  with gr.Row():
317
  with gr.Column(scale=1):
@@ -322,7 +419,7 @@ Version 0.2-beta - This tool is under active development
322
  - ClimateQ&A retrieves specific passages from the IPCC reports to help answer your question accurately.
323
  - Source information, including page numbers and passages, is displayed on the right side of the screen for easy verification.
324
  - Feel free to ask follow-up questions within the chatbot for a more in-depth understanding.
325
- - ClimateQ&A integrates multiple sources (IPCC, IPBES, IEA, … ) to cover various aspects of environmental science, such as climate change, biodiversity, energy, economy, and pollution. See all sources used below.
326
  """
327
  )
328
  with gr.Column(scale=1):
@@ -342,24 +439,26 @@ Version 0.2-beta - This tool is under active development
342
  """
343
  ### Beta test
344
  - ClimateQ&A welcomes community contributions. To participate, head over to the Community Tab and create a "New Discussion" to ask questions and share your insights.
345
- - Provide feedback through our feedback form, letting us know which insights you found accurate, useful, or not. Your input will help us improve the platform.
346
- - Only a few sources (see below) are integrated (all IPCC, IPBES, IEA recent reports), if you are a climate science researcher and net to sift through another report, please let us know.
 
 
347
  """
348
  )
349
- with gr.Row():
350
- with gr.Column(scale=1):
351
- gr.Markdown("### Feedbacks")
352
- feedback = gr.Textbox(label="Write your feedback here")
353
- feedback_output = gr.Textbox(label="Submit status")
354
- feedback_save = gr.Button(value="submit feedback")
355
- feedback_save.click(
356
- save_feedback,
357
- inputs=[feedback, user_id_state],
358
- outputs=feedback_output,
359
- )
360
- gr.Markdown(
361
- "If you need us to ask another climate science report or ask any question, contact us at <b>theo.alvesdacosta@ekimetrics.com</b>"
362
- )
363
 
364
  # with gr.Column(scale=1):
365
  # gr.Markdown("### OpenAI API")
@@ -451,4 +550,4 @@ For developers, the methodology used is detailed below :
451
 
452
  demo.queue(concurrency_count=16)
453
 
454
- demo.launch()
 
2
  from haystack.document_stores import FAISSDocumentStore
3
  from haystack.nodes import EmbeddingRetriever
4
  import openai
5
+ import pandas as pd
6
  import os
7
  from utils import (
8
  make_pairs,
 
14
  from datetime import datetime
15
  from azure.storage.fileshare import ShareServiceClient
16
 
17
+ try:
18
+ from dotenv import load_dotenv
19
+ load_dotenv()
20
+ except:
21
+ pass
22
+
23
 
24
  theme = gr.themes.Soft(
25
  primary_hue="sky",
26
+ font=[gr.themes.GoogleFont("Poppins"), "ui-sans-serif", "system-ui", "sans-serif"],
27
  )
28
 
29
  init_prompt = (
30
  "You are ClimateQA, an AI Assistant by Ekimetrics. "
31
+ "You are given a question and extracted parts of the IPCC and IPBES reports."
32
  "Provide a clear and structured answer based on the context provided. "
33
  "When relevant, use bullet points and lists to structure your answers."
34
  )
 
42
 
43
 
44
  def get_reformulation_prompt(query: str) -> str:
45
+ return f"""Reformulate the following user message to be a short standalone question in English, in the context of an educational discussion about climate change.
46
  ---
47
  query: La technologie nous sauvera-t-elle ?
48
  standalone question: Can technology help humanity mitigate the effects of climate change?
 
52
  standalone question: What are the current reserves of fossil fuels and how long will they last?
53
  language: English
54
  ---
55
+ query: what are the main causes of climate change?
56
+ standalone question: What are the main causes of climate change in the last century?
57
+ language: English
58
+ ---
59
  query: {query}
60
  standalone question:"""
61
 
 
70
  openai.api_base = os.environ["ressource_endpoint"]
71
  openai.api_version = "2022-12-01"
72
 
73
+ retriever = EmbeddingRetriever(
74
  document_store=FAISSDocumentStore.load(
75
+ index_path="./climateqa_v3.faiss",
76
+ config_path="./climateqa_v3.json",
77
  ),
78
  embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1",
79
  model_format="sentence_transformers",
80
  progress_bar=False,
81
  )
82
 
83
+ # retrieve_giec = EmbeddingRetriever(
84
+ # document_store=FAISSDocumentStore.load(
85
+ # index_path="./documents/climate_gpt_v2_only_giec.faiss",
86
+ # config_path="./documents/climate_gpt_v2_only_giec.json",
87
+ # ),
88
+ # embedding_model="sentence-transformers/multi-qa-mpnet-base-dot-v1",
89
+ # model_format="sentence_transformers",
90
+ # )
91
 
92
  credential = {
93
  "account_key": os.environ["account_key"],
 
101
  user_id = create_user_id(10)
102
 
103
 
104
+
105
+ def filter_sources(df,k_summary = 3,k_total = 10,source = "ipcc"):
106
+ assert source in ["ipcc","ipbes","all"]
107
+
108
+ # Filter by source
109
+ if source == "ipcc":
110
+ df = df.loc[df["source"]=="IPCC"]
111
+ elif source == "ipbes":
112
+ df = df.loc[df["source"]=="IPBES"]
113
+ else:
114
+ pass
115
+
116
+ # Separate summaries and full reports
117
+ df_summaries = df.loc[df["report_type"].isin(["SPM","TS"])]
118
+ df_full = df.loc[~df["report_type"].isin(["SPM","TS"])]
119
+
120
+ # Find passages from summaries dataset
121
+ passages_summaries = df_summaries.head(k_summary)
122
+
123
+ # Find passages from full reports dataset
124
+ passages_fullreports = df_full.head(k_total - len(passages_summaries))
125
+
126
+ # Concatenate passages
127
+ passages = pd.concat([passages_summaries,passages_fullreports],axis = 0,ignore_index = True)
128
+ return passages
129
+
130
+
131
+ def retrieve_with_summaries(query,retriever,k_summary = 3,k_total = 10,source = "ipcc",max_k = 100,threshold = 0.555,as_dict = True):
132
+ assert max_k > k_total
133
+ docs = retriever.retrieve(query,top_k = max_k)
134
+ docs = [{**x.meta,"score":x.score,"content":x.content} for x in docs if x.score > threshold]
135
+ if len(docs) == 0:
136
+ return []
137
+ res = pd.DataFrame(docs)
138
+ passages_df = filter_sources(res,k_summary,k_total,source)
139
+ if as_dict:
140
+ contents = passages_df["content"].tolist()
141
+ meta = passages_df.drop(columns = ["content"]).to_dict(orient = "records")
142
+ passages = []
143
+ for i in range(len(contents)):
144
+ passages.append({"content":contents[i],"meta":meta[i]})
145
+ return passages
146
+ else:
147
+ return passages_df
148
+
149
+
150
+ def make_html_source(source,i):
151
+ meta = source['meta']
152
+ return f"""
153
+ <div class="card">
154
+ <div class="card-content">
155
+ <h2>Doc {i} - {meta['short_name']} - Page {meta['page_number']}</h2>
156
+ <p>{source['content']}</p>
157
+ </div>
158
+ <div class="card-footer">
159
+ <span>{meta['name']}</span>
160
+ <a href="{meta['url']}#page={meta['page_number']}" target="_blank" class="pdf-link">
161
+ <span role="img" aria-label="Open PDF">🔗</span>
162
+ </a>
163
+ </div>
164
+ </div>
165
+ """
166
+
167
+
168
+
169
  def chat(
170
  user_id: str,
171
  query: str,
172
  history: list = [system_template],
173
+ report_type: str = "IPCC",
174
  threshold: float = 0.555,
175
  ) -> tuple:
176
  """retrieve relevant documents in the document store then query gpt-turbo
 
185
  tuple: chat gradio format, chat openai format, sources used.
186
  """
187
 
188
+ if report_type not in ["IPCC","IPBES"]: report_type = "all"
189
+ print("Searching in ",report_type," reports")
190
+ # if report_type == "All available":
191
+ # retriever = retrieve_all
192
+ # elif report_type == "IPCC only":
193
+ # retriever = retrieve_giec
194
+ # else:
195
+ # raise Exception("report_type arg should be in (All available, IPCC only)")
196
 
197
  reformulated_query = openai.Completion.create(
198
  engine="climateGPT",
 
204
  reformulated_query = reformulated_query["choices"][0]["text"]
205
  reformulated_query, language = reformulated_query.split("\n")
206
  language = language.split(":")[1].strip()
207
+
208
+
209
+ sources = retrieve_with_summaries(reformulated_query,retriever,k_total = 10,k_summary = 3,as_dict = True,source = report_type.lower(),threshold = threshold)
210
+ response_retriever = {
211
+ "language":language,
212
+ "reformulated_query":reformulated_query,
213
+ "query":query,
214
+ "sources":sources,
215
+ }
216
+
217
+ # docs = [d for d in retriever.retrieve(query=reformulated_query, top_k=10) if d.score > threshold]
218
  messages = history + [{"role": "user", "content": query}]
219
 
220
+ if len(sources) > 0:
221
  docs_string = []
222
+ docs_html = []
223
+ for i, d in enumerate(sources, 1):
224
+ docs_string.append(f"📃 Doc {i}: {d['meta']['short_name']} page {d['meta']['page_number']}\n{d['content']}")
225
+ docs_html.append(make_html_source(d,i))
226
+ docs_string = "\n\n".join([f"Query used for retrieval:\n{reformulated_query}"] + docs_string)
227
+ docs_html = "\n\n".join([f"Query used for retrieval:\n{reformulated_query}"] + docs_html)
228
+ messages.append({"role": "system", "content": f"{sources_prompt}\n\n{docs_string}\n\nAnswer in {language}:"})
229
+
230
 
231
  response = openai.Completion.create(
232
  engine="climateGPT",
 
258
  complete_response += chunk_message
259
  messages[-1]["content"] = complete_response
260
  gradio_format = make_pairs([a["content"] for a in messages[1:]])
261
+ yield gradio_format, messages, docs_html
262
 
263
  else:
264
+ docs_string = "⚠️ No relevant passages found in the climate science reports (IPCC and IPBES)"
265
+ complete_response = "**⚠️ No relevant passages found in the climate science reports (IPCC and IPBES), you may want to ask a more specific question (specifying your question on climate issues).**"
266
  messages.append({"role": "assistant", "content": complete_response})
267
  gradio_format = make_pairs([a["content"] for a in messages[1:]])
268
+ yield gradio_format, messages, docs_string
269
 
270
 
271
  def save_feedback(feed: str, user_id):
 
296
  # Gradio
297
  gr.Markdown("<h1><center>Climate Q&A 🌍</center></h1>")
298
  gr.Markdown("<h4><center>Ask climate-related questions to the IPCC reports</center></h4>")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
 
 
 
 
300
 
301
  with gr.Row():
302
  with gr.Column(scale=2):
303
+ chatbot = gr.Chatbot(elem_id="chatbot", label="ClimateQ&A chatbot",show_label = False)
304
  state = gr.State([system_template])
305
 
306
  with gr.Row():
 
312
 
313
  examples_questions = gr.Examples(
314
  [
315
+ "Is climate change caused by humans?",
316
+ "What evidence do we have of climate change?",
317
  "What are the impacts of climate change?",
318
  "Can climate change be reversed?",
319
  "What is the difference between climate change and global warming?",
320
+ "What can individuals do to address climate change?",
321
+ "What are the main causes of climate change?",
322
  "What is the Paris Agreement and why is it important?",
323
  "Which industries have the highest GHG emissions?",
 
324
  "Is climate change a hoax created by the government or environmental organizations?",
325
  "What is the relationship between climate change and biodiversity loss?",
326
  "What is the link between gender equality and climate change?",
 
351
 
352
  with gr.Column(scale=1, variant="panel"):
353
  gr.Markdown("### Sources")
354
+ sources_textbox = gr.Markdown(show_label=False)
355
 
356
+ dropdown_sources = gr.inputs.Dropdown(
357
+ ["IPCC", "IPBES","IPCC and IPBES"],
358
+ default="IPCC",
359
+ label="Select reports",
360
+ )
361
  ask.submit(
362
  fn=chat,
363
  inputs=[
364
  user_id_state,
365
  ask,
366
  state,
367
+ dropdown_sources
368
+
 
 
 
369
  ],
370
  outputs=[chatbot, state, sources_textbox],
371
  )
 
377
  user_id_state,
378
  ask_examples_hidden,
379
  state,
380
+ dropdown_sources
381
  ],
382
  outputs=[chatbot, state, sources_textbox],
383
  )
384
 
385
+
386
+ with gr.Row():
387
+ with gr.Column(scale=1):
388
+ gr.Markdown(
389
+ """
390
+ <p><b>Climate change and environmental disruptions have become some of the most pressing challenges facing our planet today</b>. As global temperatures rise and ecosystems suffer, it is essential for individuals to understand the gravity of the situation in order to make informed decisions and advocate for appropriate policy changes.</p>
391
+ <p>However, comprehending the vast and complex scientific information can be daunting, as the scientific consensus references, such as <b>the Intergovernmental Panel on Climate Change (IPCC) reports, span thousands of pages</b>. To bridge this gap and make climate science more accessible, we introduce <b>ClimateQ&A as a tool to distill expert-level knowledge into easily digestible insights about climate science.</b></p>
392
+ <div class="tip-box">
393
+ <div class="tip-box-title">
394
+ <span class="light-bulb" role="img" aria-label="Light Bulb">💡</span>
395
+ How does ClimateQ&A work?
396
+ </div>
397
+ ClimateQ&A harnesses modern OCR techniques to parse and preprocess IPCC reports. By leveraging state-of-the-art question-answering algorithms, <i>ClimateQ&A is able to sift through the extensive collection of climate scientific reports and identify relevant passages in response to user inquiries</i>. Furthermore, the integration of the ChatGPT API allows ClimateQ&A to present complex data in a user-friendly manner, summarizing key points and facilitating communication of climate science to a wider audience.
398
+ </div>
399
+
400
+ <div class="warning-box">
401
+ Version 0.2-beta - This tool is under active development
402
+ </div>
403
+
404
+
405
+ """
406
+ )
407
+
408
+ with gr.Column(scale=1):
409
+ gr.Markdown("![](https://i.postimg.cc/fLvsvMzM/Untitled-design-5.png)")
410
+ gr.Markdown("*Source : IPCC AR6 - Synthesis Report of the IPCC 6th assessment report (AR6)*")
411
+
412
  gr.Markdown("## How to use ClimateQ&A")
413
  with gr.Row():
414
  with gr.Column(scale=1):
 
419
  - ClimateQ&A retrieves specific passages from the IPCC reports to help answer your question accurately.
420
  - Source information, including page numbers and passages, is displayed on the right side of the screen for easy verification.
421
  - Feel free to ask follow-up questions within the chatbot for a more in-depth understanding.
422
+ - ClimateQ&A integrates multiple sources (IPCC and IPBES, … ) to cover various aspects of environmental science, such as climate change and biodiversity. See all sources used below.
423
  """
424
  )
425
  with gr.Column(scale=1):
 
439
  """
440
  ### Beta test
441
  - ClimateQ&A welcomes community contributions. To participate, head over to the Community Tab and create a "New Discussion" to ask questions and share your insights.
442
+ - Provide feedback through email, letting us know which insights you found accurate, useful, or not. Your input will help us improve the platform.
443
+ - Only a few sources (see below) are integrated (all IPCC, IPBES), if you are a climate science researcher and net to sift through another report, please let us know.
444
+
445
+ If you need us to ask another climate science report or ask any question, contact us at <b>theo.alvesdacosta@ekimetrics.com</b>
446
  """
447
  )
448
+ # with gr.Row():
449
+ # with gr.Column(scale=1):
450
+ # gr.Markdown("### Feedbacks")
451
+ # feedback = gr.Textbox(label="Write your feedback here")
452
+ # feedback_output = gr.Textbox(label="Submit status")
453
+ # feedback_save = gr.Button(value="submit feedback")
454
+ # feedback_save.click(
455
+ # save_feedback,
456
+ # inputs=[feedback, user_id_state],
457
+ # outputs=feedback_output,
458
+ # )
459
+ # gr.Markdown(
460
+ # "If you need us to ask another climate science report or ask any question, contact us at <b>theo.alvesdacosta@ekimetrics.com</b>"
461
+ # )
462
 
463
  # with gr.Column(scale=1):
464
  # gr.Markdown("### OpenAI API")
 
550
 
551
  demo.queue(concurrency_count=16)
552
 
553
+ demo.launch(server_port = 8080)
style.css CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  .warning-box {
2
  background-color: #fff3cd;
3
  border: 1px solid #ffeeba;
@@ -42,4 +47,118 @@
42
 
43
  .message{
44
  font-size:14px !important;
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ :root {
3
+ --user-image: url('https://ih1.redbubble.net/image.4776899543.6215/st,small,507x507-pad,600x600,f8f8f8.jpg');
4
+ }
5
+
6
  .warning-box {
7
  background-color: #fff3cd;
8
  border: 1px solid #ffeeba;
 
47
 
48
  .message{
49
  font-size:14px !important;
50
+ }
51
+
52
+
53
+ a {
54
+ text-decoration: none;
55
+ color: inherit;
56
+ }
57
+
58
+ .card {
59
+ background-color: white;
60
+ border-radius: 10px;
61
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
62
+ overflow: hidden;
63
+ display: flex;
64
+ flex-direction: column;
65
+ margin:20px;
66
+ }
67
+
68
+ .card-content {
69
+ padding: 20px;
70
+ }
71
+
72
+ .card-content h2 {
73
+ font-size: 14px !important;
74
+ font-weight: bold;
75
+ margin-bottom: 10px;
76
+ margin-top:0px !important;
77
+ color:#577b9b!important;;
78
+ }
79
+
80
+ .card-content p {
81
+ font-size: 12px;
82
+ margin-bottom: 0;
83
+ }
84
+
85
+ .card-footer {
86
+ background-color: #f4f4f4;
87
+ font-size: 10px;
88
+ padding: 10px;
89
+ display: flex;
90
+ justify-content: space-between;
91
+ align-items: center;
92
+ }
93
+
94
+ .card-footer span {
95
+ flex-grow: 1;
96
+ text-align: left;
97
+ color: #999 !important;
98
+ }
99
+
100
+ .pdf-link {
101
+ display: inline-flex;
102
+ align-items: center;
103
+ margin-left: auto;
104
+ text-decoration: none!important;
105
+ font-size: 14px;
106
+ }
107
+
108
+
109
+
110
+ .message.user{
111
+ background-color:#7494b0 !important;
112
+ border:none;
113
+ color:white!important;
114
+ }
115
+
116
+ .message.bot{
117
+ background-color:#f2f2f7 !important;
118
+ border:none;
119
+ }
120
+
121
+ .gallery-item > div:hover{
122
+ background-color:#7494b0 !important;
123
+ color:white!important;
124
+ }
125
+
126
+ .gallery-item:hover{
127
+ border:#7494b0 !important;
128
+ }
129
+
130
+ .gallery-item > div{
131
+ background-color:white !important;
132
+ color:#577b9b!important;
133
+ }
134
+
135
+ .label{
136
+ color:#577b9b!important;
137
+ }
138
+
139
+ .paginate{
140
+ color:#577b9b!important;
141
+ }
142
+
143
+
144
+ label > span{
145
+ background-color:white !important;
146
+ color:#577b9b!important;
147
+ }
148
+
149
+ /* Pseudo-element for the circularly cropped picture */
150
+ .message.bot::before {
151
+ content: '';
152
+ position: absolute;
153
+ top: -10px;
154
+ left: -10px;
155
+ width: 30px;
156
+ height: 30px;
157
+ background-image: var(--user-image);
158
+ background-size: cover;
159
+ background-position: center;
160
+ border-radius: 50%;
161
+ z-index: 10;
162
+ }
163
+
164
+