fvde commited on
Commit
412c815
·
1 Parent(s): f2965eb

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. src/gradio_app.py +8 -1
  2. src/prompts.py +109 -0
  3. src/summarization.py +116 -9
src/gradio_app.py CHANGED
@@ -4,7 +4,7 @@ import pypdfium2 as pdfium
4
  import gradio as gr
5
 
6
  from langchain.chat_models import ChatOpenAI
7
- from src.summarization import summarize_wrapper
8
  from src.mailing import send_email
9
 
10
  # Function to render a specific page of a PDF file as an image
@@ -79,6 +79,7 @@ def run_summarization_model_gradio(
79
  summary_short = gr.Button("Kurze Zusammenfassung", interactive=False)
80
  summary_middle = gr.Button("Mittlere Zusammenfassung", interactive=False)
81
  summary_long = gr.Button("Lange Zusammenfassung", interactive=False)
 
82
  with gr.Row().style(equal_height=True):
83
  with gr.Column(scale=1):
84
  summary_output = gr.Textbox(label="Zusammenfassung", lines=9).style(
@@ -148,6 +149,12 @@ def run_summarization_model_gradio(
148
  [send_email_button, gr.State(None), gr.State(None)],
149
  queue=False,
150
  )
 
 
 
 
 
 
151
 
152
  # The clear button clears the dashboard
153
  clear.click(lambda: None, None, summary_output, queue=False).then(
 
4
  import gradio as gr
5
 
6
  from langchain.chat_models import ChatOpenAI
7
+ from src.summarization import summarize_wrapper, parallel_summarization
8
  from src.mailing import send_email
9
 
10
  # Function to render a specific page of a PDF file as an image
 
79
  summary_short = gr.Button("Kurze Zusammenfassung", interactive=False)
80
  summary_middle = gr.Button("Mittlere Zusammenfassung", interactive=False)
81
  summary_long = gr.Button("Lange Zusammenfassung", interactive=False)
82
+ summary_parallel = gr.Button("Parallele Zusammenfassung", interactive=False)
83
  with gr.Row().style(equal_height=True):
84
  with gr.Column(scale=1):
85
  summary_output = gr.Textbox(label="Zusammenfassung", lines=9).style(
 
149
  [send_email_button, gr.State(None), gr.State(None)],
150
  queue=False,
151
  )
152
+ summary_parallel.click(
153
+ parallel_summarization,
154
+ [file_upload, gr.State(llm), gr.State(summarization_kwargs)],
155
+ [summary_output],
156
+ queue=False,
157
+ )
158
 
159
  # The clear button clears the dashboard
160
  clear.click(lambda: None, None, summary_output, queue=False).then(
src/prompts.py CHANGED
@@ -150,3 +150,112 @@ Die Teile der Zusammenfassung mit Angabe der Seitenzahlen:
150
  ),
151
  },
152
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  ),
151
  },
152
  }
153
+
154
+
155
+ def get_template_mp(name: str, headline: str, additional_text: str = ""):
156
+ base_multi = (
157
+ "Das folgende Urteil, das durch dreifache Anführungszeichen begrenzt ist, soll ausführlich zusammengefasst werden.\n"
158
+ "Dafür muss ein/e präzise/r <KEY> mittlerer Länge geschrieben werden.\n"
159
+ "\n"
160
+ "Text:\n"
161
+ "```{text}```\n"
162
+ "\n"
163
+ "Schreibe die <KEY> des Urteils. Falls dies nicht möglich ist antworte immer damit, dass die Informationen nicht vorhanden sind.\n"
164
+ "<ADDITIONAL_TEXT>\n"
165
+ 'Als Überschrift muss "<HEAD_LINE>" angegeben werden. \n'
166
+ "Nach dem Paragraph muss die Quell-Seite angegeben werden z.B. (siehe Seite ?).\n"
167
+ "\n"
168
+ "<KEY>:\n"
169
+ )
170
+ return (
171
+ base_multi.replace("<KEY>", name)
172
+ .replace("<HEAD_LINE>", headline)
173
+ .replace("<ADDITIONAL_TEXT>", additional_text)
174
+ )
175
+
176
+
177
+ prompts_parallel = {
178
+ "intro": PromptTemplate(
179
+ input_variables=["text"],
180
+ template=get_template_mp(name="Einleitung", headline="I. Einleitung"),
181
+ ),
182
+ "darstellung_des_rechtsproblems": PromptTemplate(
183
+ input_variables=["text"],
184
+ template=get_template_mp(
185
+ name="Darstellung des Rechtsproblems",
186
+ headline="Darstellung des Rechtsproblems",
187
+ ),
188
+ ),
189
+ "angaben_ueber_das_urteil": PromptTemplate(
190
+ input_variables=["text"],
191
+ template=get_template_mp(
192
+ name="Angaben über das Urteil",
193
+ headline="Angaben über das Urteil",
194
+ additional_text="Gib die folgenden Informationen an: Gericht, Datum, Aktenzeichen (AZ: ...), Fundstelle(n)",
195
+ ),
196
+ ),
197
+ "sachverhalt": PromptTemplate(
198
+ input_variables=["text"],
199
+ template=get_template_mp(
200
+ name="Sachverhalt",
201
+ headline="Sachverhalt (unter Rückgriff auf Instanzentscheidung)",
202
+ additional_text="Beziehe dich auf die Instanzentscheidung.",
203
+ ),
204
+ ),
205
+ "prozessgeschichte": PromptTemplate(
206
+ input_variables=["text"],
207
+ template=get_template_mp(
208
+ name="Prozessgeschichte", headline="3. Prozessgeschichte"
209
+ ),
210
+ ),
211
+ "rechtsproblem": PromptTemplate(
212
+ input_variables=["text"],
213
+ template=get_template_mp(
214
+ name="Rechtsproblem",
215
+ headline="Rechtsproblem",
216
+ additional_text="Das Problem des Falles ist genau herauszuarbeiten und im rechtlichen Kontext zu verankern.",
217
+ ),
218
+ ),
219
+ "loesung_des_gerichts": PromptTemplate(
220
+ input_variables=["text"],
221
+ template=get_template_mp(
222
+ name="Lösung des Gerichts", headline="Lösung des Gerichts"
223
+ ),
224
+ ),
225
+ "loesungsansaetze_zum_problem": PromptTemplate(
226
+ input_variables=["text"],
227
+ template=get_template_mp(
228
+ name="Lösungsansätze zum Problem",
229
+ headline="Lösungsansätze zum Problem",
230
+ additional_text="Knappe, aber möglichst vollständige Übersicht der vertretenen Ansichten.",
231
+ ),
232
+ ),
233
+ "analyse_und_einordnung_der_entscheidung": PromptTemplate(
234
+ input_variables=["text"],
235
+ template=get_template_mp(
236
+ name="Analyse und Einordnung der Entscheidung",
237
+ headline="Analyse und Einordnung der Entscheidung",
238
+ ),
239
+ ),
240
+ "bewertung_und_kritik_der_entscheidung": PromptTemplate(
241
+ input_variables=["text"],
242
+ template=get_template_mp(
243
+ name="Bewertung und Kritik der Entscheidung",
244
+ headline="Bewertung und Kritik der Entscheidung",
245
+ ),
246
+ ),
247
+ "eigener_loesungsvorschlag": PromptTemplate(
248
+ input_variables=["text"],
249
+ template=get_template_mp(
250
+ name="Eigener Lösungsvorschlag",
251
+ headline="Eigener Lösungsvorschlag",
252
+ ),
253
+ ),
254
+ "ausblick": PromptTemplate(
255
+ input_variables=["text"],
256
+ template=get_template_mp(
257
+ name="Ausblick",
258
+ headline="Ausblick",
259
+ ),
260
+ ),
261
+ }
src/summarization.py CHANGED
@@ -4,15 +4,18 @@ from langchain.chains.llm import LLMChain
4
  from langchain.chains.combine_documents.stuff import StuffDocumentsChain
5
  from langchain.chat_models import ChatOpenAI
6
  from langchain.docstore.document import Document
7
- from src.prompts import prompts
 
8
  from typing import Dict, List
 
9
 
10
 
11
- def load_docs(file_path: str) -> List[Document]:
12
  """Load a file and return the text.
13
 
14
  Args:
15
  file_path (str): Path to the pdf file. This can either be a local path or a tempfile.TemporaryFileWrapper_.
 
16
 
17
  Raises:
18
  ValueError: If the file type is not supported.
@@ -33,17 +36,15 @@ def load_docs(file_path: str) -> List[Document]:
33
  for doc in docs:
34
  doc.page_content = doc.page_content.replace("\n", " \n ")
35
  # if doc contains a page append it to the text
36
- if hasattr(doc, "metadata"):
37
- doc.page_content = (
38
- f"Start {doc.metadata.get('page')+1}"
39
- + doc.page_content
40
- + f" \n Ende Seite {doc.metadata.get('page')+1}"
41
  )
42
 
43
  return docs
44
 
45
 
46
- def summarize(
47
  file_path: str, llm: ChatOpenAI, summarization_kwargs: Dict[str, str]
48
  ) -> str:
49
  """Summarize a pdf file. The summarization is done by the language model.
@@ -109,6 +110,112 @@ def summarize_wrapper(
109
  else:
110
  raise ValueError(f"Summarization type {summarization_type} is not supported.")
111
 
112
- return summarize(
113
  file_path=file.name, llm=llm[0], summarization_kwargs=summarization_kwargs
114
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from langchain.chains.combine_documents.stuff import StuffDocumentsChain
5
  from langchain.chat_models import ChatOpenAI
6
  from langchain.docstore.document import Document
7
+ from src.prompts import prompts, prompts_parallel
8
+ import time
9
  from typing import Dict, List
10
+ import asyncio
11
 
12
 
13
+ def load_docs(file_path: str, with_pageinfo: bool = True) -> List[Document]:
14
  """Load a file and return the text.
15
 
16
  Args:
17
  file_path (str): Path to the pdf file. This can either be a local path or a tempfile.TemporaryFileWrapper_.
18
+ with_pageinfo (bool, optional): If True the page information is added to the document. Defaults to True.
19
 
20
  Raises:
21
  ValueError: If the file type is not supported.
 
36
  for doc in docs:
37
  doc.page_content = doc.page_content.replace("\n", " \n ")
38
  # if doc contains a page append it to the text
39
+ if with_pageinfo and hasattr(doc, "metadata"):
40
+ doc.page_content = f"(Quelle Seite: {doc.metadata.get('page')+1}) .".join(
41
+ doc.page_content.split(" .")
 
 
42
  )
43
 
44
  return docs
45
 
46
 
47
+ def summarize_chain(
48
  file_path: str, llm: ChatOpenAI, summarization_kwargs: Dict[str, str]
49
  ) -> str:
50
  """Summarize a pdf file. The summarization is done by the language model.
 
110
  else:
111
  raise ValueError(f"Summarization type {summarization_type} is not supported.")
112
 
113
+ return summarize_chain(
114
  file_path=file.name, llm=llm[0], summarization_kwargs=summarization_kwargs
115
  )
116
+
117
+
118
+ async def async_generate(
119
+ llm: ChatOpenAI, docs: List[Document], summarization_kwargs: dict, k: str
120
+ ) -> dict:
121
+ """Asyncronous summarization.
122
+
123
+ Args:
124
+ llm (ChatOpenAI): Language model to use for the summarization.
125
+ docs (List[Document]): List of documents.
126
+ summarization_kwargs (dict): Keyword arguments for the summarization.
127
+ k (str): Key for the summarization.
128
+
129
+ Returns:
130
+ dict: Dictionary with the summarization.
131
+ """
132
+ chain = load_summarize_chain(llm=llm, **summarization_kwargs)
133
+ resp = await chain.run(docs)
134
+ return {k: resp}
135
+
136
+
137
+ async def generate_concurrently(file_path: str, llm: ChatOpenAI) -> List[dict]:
138
+ """Parallel summarization.
139
+
140
+ Args:
141
+ file_path (str): Path to the pdf file. This can either be a local path or a tempfile.TemporaryFileWrapper_.
142
+ llm (ChatOpenAI): Language model to use for the summarization.
143
+
144
+ Returns:
145
+ List: List of summarizations.
146
+ """
147
+
148
+ docs = load_docs(file_path=file_path)
149
+ summarization_kwargs = dict(
150
+ chain_type="stuff",
151
+ )
152
+ # create parallel tasks
153
+ tasks = []
154
+ for k, pt in prompts_parallel.items():
155
+ sk = summarization_kwargs.copy()
156
+ sk["prompt"] = pt
157
+ tasks.append(async_generate(llm=llm, docs=docs, summarization_kwargs=sk, k=k))
158
+ # execute all coroutines concurrently
159
+ values = await asyncio.gather(*tasks)
160
+
161
+ # report return values
162
+ print(values)
163
+ values_flattened = {}
164
+ for v in values:
165
+ values_flattened.update(v)
166
+ return values_flattened
167
+
168
+
169
+ def parallel_summarization(
170
+ file: str, llm: ChatOpenAI, summarization_kwargs: dict
171
+ ) -> str:
172
+ """Wrapper for the summarization function to make it compatible with gradio.
173
+
174
+ Args:
175
+ file (str): Path to the file. This can either be a local path or a tempfile.TemporaryFileWrapper_.
176
+ llm (ChatOpenAI): Language model.
177
+ summarization_kwargs (dict): Keyword arguments for the summarization.
178
+
179
+ Returns:
180
+ str: Summarization of the file.
181
+ """
182
+ now = time.time()
183
+ values_flattened = asyncio.run(
184
+ generate_concurrently(file_path=file.name, llm=llm[0])
185
+ )
186
+ print("Time taken: ", time.time() - now)
187
+
188
+ output = f"""
189
+
190
+ {values_flattened["intro"]}
191
+
192
+ {values_flattened["darstellung_des_rechtsproblems"]}
193
+
194
+
195
+ II. Die Entscheidung
196
+
197
+ {values_flattened["angaben_ueber_das_urteil"]}
198
+
199
+ {values_flattened["sachverhalt"]}
200
+
201
+ {values_flattened["prozessgeschichte"]}
202
+
203
+ {values_flattened["rechtsproblem"]}
204
+
205
+ {values_flattened["loesung_des_gerichts"]}
206
+
207
+
208
+ III. Analyse
209
+
210
+ {values_flattened["loesungsansaetze_zum_problem"]}
211
+
212
+ {values_flattened["analyse_und_einordnung_der_entscheidung"]}
213
+
214
+ {values_flattened["bewertung_und_kritik_der_entscheidung"]}
215
+
216
+ {values_flattened["eigener_loesungsvorschlag"]}
217
+
218
+ {values_flattened["ausblick"]}
219
+ """
220
+
221
+ return output