michaelmc1618 commited on
Commit
07a3b9b
·
verified ·
1 Parent(s): 6e460e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +346 -105
app.py CHANGED
@@ -1,47 +1,267 @@
1
  import os
2
- os.system('pip install torch') # or 'pip install tensorflow'
3
- os.system('pip install transformers')
4
- os.system('pip install datasets')
5
- os.system('pip install gradio')
6
- os.system('pip install minijinja')
7
- os.system('pip install PyMuPDF')
8
-
9
  import gradio as gr
 
10
  from huggingface_hub import InferenceClient
11
- from transformers import pipeline
12
  from datasets import load_dataset
13
  import fitz # PyMuPDF
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- client = InferenceClient()
 
 
16
 
17
- dataset = load_dataset("ibunescu/qa_legal_dataset_train")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- def score_argument_from_outcome(outcome, argument):
20
- prosecutor_score = 0
21
- if "Prosecutor" in outcome:
22
- prosecutor_score = outcome.count("Prosecutor") * 2
23
- if "won" in outcome and "Prosecutor" in outcome:
24
- prosecutor_score += 10
25
- return prosecutor_score
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  def chat_between_bots(system_message1, system_message2, max_tokens, temperature, top_p, history1, history2, shared_history, message):
28
  response1, history1 = list(respond(message, history1, system_message1, max_tokens, temperature, top_p))[-1]
29
  response2, history2 = list(respond(message, history2, system_message2, max_tokens, temperature, top_p))[-1]
 
 
30
 
31
- return response1, response2, history1, history2, shared_history
32
-
33
- def extract_text_from_pdf(pdf_file):
34
- text = ""
35
- doc = fitz.open(pdf_file)
36
- for page in doc:
37
- text += page.get_text()
38
- return text
39
 
40
- def ask_about_pdf(pdf_text, question):
41
- prompt = f"PDF Content: {pdf_text}\n\nQuestion: {question}\n\nAnswer:"
42
  response = ""
43
  for message in client.chat_completion(
44
- [{"role": "system", "content": "You are a legal expert answering questions based on the PDF content provided."},
45
  {"role": "user", "content": prompt}],
46
  max_tokens=512,
47
  stream=True,
@@ -53,38 +273,12 @@ def ask_about_pdf(pdf_text, question):
53
  response += token
54
  return response
55
 
56
- def update_pdf_gallery_and_extract_text(pdf_files):
57
- if len(pdf_files) > 0:
58
- pdf_text = extract_text_from_pdf(pdf_files[0].name)
59
- else:
60
- pdf_text = ""
61
- return pdf_files, pdf_text
62
-
63
  def add_message(history, message):
64
- history.append(message)
65
- return history, gr.Textbox(value=None, interactive=False)
66
-
67
- def bot(history):
68
- system_message = "You are a helpful assistant."
69
- messages = [{"role": "system", "content": system_message}]
70
- for val in history:
71
- if val[0]:
72
- messages.append({"role": "user", "content": val[0]})
73
- if val[1]:
74
- messages.append({"role": "assistant", "content": val[1]})
75
- response = ""
76
- for message in client.chat_completion(
77
- messages,
78
- max_tokens=150,
79
- stream=True,
80
- temperature=0.6,
81
- top_p=0.95,
82
- ):
83
- token = message.choices[0].delta.content
84
- if token is not None:
85
- response += token
86
- history[-1][1] = response
87
- yield history
88
 
89
  def print_like_dislike(x: gr.LikeData):
90
  print(x.index, x.value, x.liked)
@@ -95,56 +289,103 @@ def reset_conversation():
95
  def save_conversation(history1, history2, shared_history):
96
  return history1, history2, shared_history
97
 
98
- custom_css = """
99
- .scroll-box {
100
- max-height: 400px;
101
- overflow-y: auto;
102
- }
103
- """
 
 
 
 
 
 
 
 
 
104
 
105
  with gr.Blocks(css=custom_css) as demo:
106
  history1 = gr.State([])
107
  history2 = gr.State([])
108
  shared_history = gr.State([])
109
- pdf_files = gr.State([])
110
- pdf_text = gr.State("")
111
-
112
  with gr.Tab("Argument Evaluation"):
113
- message = gr.Textbox(label="Case to Argue")
114
- system_message1 = gr.Textbox(value="System message for bot 1")
115
- system_message2 = gr.Textbox(value="System message for bot 2")
116
- max_tokens = gr.Slider(1, 512, value=150)
117
- temperature = gr.Slider(0.0, 1.0, value=0.6)
118
- top_p = gr.Slider(0.0, 1.0, value=0.95)
119
-
120
- prosecutor_response = gr.Textbox(label="Prosecutor Response", interactive=False)
121
- defense_response = gr.Textbox(label="Defense Response", interactive=False)
122
- prosecutor_score_color = gr.Textbox(label="Prosecutor Score Color", interactive=False)
123
- defense_score_color = gr.Textbox(label="Defense Score Color", interactive=False)
124
- shared_argument = gr.Textbox(label="Case Outcome", interactive=True)
125
-
126
- submit_btn = gr.Button("Argue")
127
- clear_btn = gr.Button("Clear and Reset")
128
- save_btn = gr.Button("Save Conversation")
129
-
130
- submit_btn.click(chat_between_bots, inputs=[system_message1, system_message2, max_tokens, temperature, top_p, history1, history2, shared_history, message], outputs=[prosecutor_response, defense_response, history1, history2, shared_argument, prosecutor_score_color, defense_score_color])
131
- clear_btn.click(reset_conversation, outputs=[history1, history2, shared_history, prosecutor_response, defense_response, shared_argument])
132
- save_btn.click(save_conversation, inputs=[history1, history2, shared_history], outputs=[history1, history2, shared_history])
133
-
134
- with gr.Tab("PDF Management"):
135
- pdf_upload = gr.File(label="Upload Case Files (PDF)", file_types=[".pdf"])
136
- pdf_gallery = gr.Gallery(label="PDF Gallery")
137
- pdf_view = gr.Textbox(label="PDF Content", interactive=False, elem_classes=["scroll-box"])
138
- pdf_question = gr.Textbox(label="Ask a Question about the PDF")
139
- pdf_answer = gr.Textbox(label="Answer", interactive=False, elem_classes=["scroll-box"])
140
- pdf_upload_btn = gr.Button("Update PDF Gallery")
141
- pdf_ask_btn = gr.Button("Ask")
142
-
143
- pdf_upload_btn.click(update_pdf_gallery_and_extract_text, inputs=[pdf_upload], outputs=[pdf_gallery, pdf_text])
144
- pdf_text.change(fn=lambda x: x, inputs=pdf_text, outputs=pdf_view)
145
- pdf_ask_btn.click(ask_about_pdf, inputs=[pdf_text, pdf_question], outputs=pdf_answer)
146
-
147
- with gr.Tab("Chatbot"):
148
- chatbot = gr.Chatbot()
149
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  demo.launch()
 
1
  import os
2
+ import tempfile
3
+ import torch
4
+ import yt_dlp as youtube_dl
 
 
 
 
5
  import gradio as gr
6
+ from transformers import pipeline, AutoTokenizer, AutoModelForMaskedLM, AutoProcessor, AutoModelForSpeechSeq2Seq
7
  from huggingface_hub import InferenceClient
 
8
  from datasets import load_dataset
9
  import fitz # PyMuPDF
10
+ from transformers.pipelines.audio_utils import ffmpeg_read
11
+
12
+ # Constants for Whisper ASR
13
+ MODEL_NAME = "openai/whisper-large-v3"
14
+ BATCH_SIZE = 8
15
+ FILE_LIMIT_MB = 1000
16
+ YT_LENGTH_LIMIT_S = 3600 # limit to 1 hour YouTube files
17
+
18
+ device = 0 if torch.cuda.is_available() else "cpu"
19
+
20
+ # Load the Whisper model and processor
21
+ processor = AutoProcessor.from_pretrained(MODEL_NAME)
22
+ model_s2s = AutoModelForSpeechSeq2Seq.from_pretrained(MODEL_NAME)
23
 
24
+ # Load the BERT model and tokenizer
25
+ tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
26
+ model = AutoModelForMaskedLM.from_pretrained("google-bert/bert-base-uncased")
27
 
28
+ # Create the fill-mask pipeline
29
+ pipe = pipeline("fill-mask", model=model, tokenizer=tokenizer)
30
+
31
+ client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
32
+
33
+ def respond(
34
+ message,
35
+ history: list[tuple[str, str]],
36
+ system_message,
37
+ max_tokens,
38
+ temperature,
39
+ top_p,
40
+ ):
41
+ messages = [{"role": "system", "content": system_message}]
42
+
43
+ for val in history:
44
+ if val[0]:
45
+ messages.append({"role": "user", "content": val[0]})
46
+ if val[1]:
47
+ messages.append({"role": "assistant", "content": val[1]})
48
 
49
+ messages.append({"role": "user", "content": message})
50
+
51
+ try:
52
+ response = ""
53
+ for message in client.chat_completion(
54
+ messages,
55
+ max_tokens=max_tokens,
56
+ stream=True,
57
+ temperature=temperature,
58
+ top_p=top_p,
59
+ ):
60
+ token = message.choices[0].delta.content
61
+ if token is not None:
62
+ response += token
63
+ yield response, history + [(message, response)]
64
+ except Exception as e:
65
+ print(f"Error during chat completion: {e}")
66
+ yield "An error occurred during the chat completion.", history
67
+
68
+ def generate_case_outcome(prosecutor_response, defense_response):
69
+ prompt = f"Prosecutor's arguments: {prosecutor_response}\n\nDefense's arguments: {defense_response}\n\nProvide details on who won the case and why. Provide reasons for your decision and provide a link to the source of the case."
70
+ evaluation = ""
71
+ try:
72
+ for message in client.chat_completion(
73
+ [{"role": "system", "content": "You are a legal expert evaluating the details of the case presented by the prosecution and the defense."},
74
+ {"role": "user", "content": prompt}],
75
+ max_tokens=512,
76
+ stream=True,
77
+ temperature=0.6,
78
+ top_p=0.95,
79
+ ):
80
+ token = message.choices[0].delta.content
81
+ if token is not None:
82
+ evaluation += token
83
+ except Exception as e:
84
+ print(f"Error during case outcome generation: {e}")
85
+ return "An error occurred during the case outcome generation."
86
+ return evaluation
87
+
88
+ def determine_outcome(outcome):
89
+ prosecutor_count = outcome.split().count("Prosecutor")
90
+ defense_count = outcome.split().count("Defense")
91
+ if prosecutor_count > defense_count:
92
+ return "Prosecutor Wins"
93
+ elif defense_count > prosecutor_count:
94
+ return "Defense Wins"
95
+ else:
96
+ return "No clear winner"
97
+
98
+ def transcribe(inputs, task):
99
+ if inputs is None:
100
+ raise gr.Error("No audio file submitted! Please upload or record an audio file before submitting your request.")
101
+
102
+ inputs = processor(inputs, return_tensors="pt", sampling_rate=16000).to(device)
103
+ with torch.no_grad():
104
+ generated_ids = model_s2s.generate(inputs["input_features"])
105
+ transcription = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
106
+
107
+ return transcription
108
+
109
+ def _return_yt_html_embed(yt_url):
110
+ video_id = yt_url.split("?v=")[-1]
111
+ HTML_str = (
112
+ f'<center> <iframe width="500" height="320" src="https://www.youtube.com/embed/{video_id}"> </iframe>'
113
+ " </center>"
114
+ )
115
+ return HTML_str
116
+
117
+ def download_yt_audio(yt_url, filename):
118
+ info_loader = youtube_dl.YoutubeDL()
119
+
120
+ try:
121
+ info = info_loader.extract_info(yt_url, download=False)
122
+ except youtube_dl.utils.DownloadError as err:
123
+ raise gr.Error(str(err))
124
+
125
+ file_length = info["duration_string"]
126
+ file_h_m_s = file_length.split(":")
127
+ file_h_m_s = [int(sub_length) for sub_length in file_h_m_s]
128
+
129
+ if len(file_h_m_s) == 1:
130
+ file_h_m_s.insert(0, 0)
131
+ if len(file_h_m_s) == 2:
132
+ file_h_m_s.insert(0, 0)
133
+ file_length_s = file_h_m_s[0] * 3600 + file_h_m_s[1] * 60 + file_h_m_s[2]
134
+
135
+ if file_length_s > YT_LENGTH_LIMIT_S:
136
+ yt_length_limit_hms = time.strftime("%HH:%MM:%SS", time.gmtime(YT_LENGTH_LIMIT_S))
137
+ file_length_hms = time.strftime("%HH:%MM:%SS", time.gmtime(file_length_s))
138
+ raise gr.Error(f"Maximum YouTube length is {yt_length_limit_hms}, got {file_length_hms} YouTube video.")
139
+
140
+ ydl_opts = {"outtmpl": filename, "format": "worstvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best"}
141
+
142
+ with youtube_dl.YoutubeDL(ydl_opts) as ydl:
143
+ try:
144
+ ydl.download([yt_url])
145
+ except youtube_dl.utils.ExtractorError as err:
146
+ raise gr.Error(str(err))
147
+
148
+ def yt_transcribe(yt_url, task, max_filesize=75.0):
149
+ html_embed_str = _return_yt_html_embed(yt_url)
150
+
151
+ with tempfile.TemporaryDirectory() as tmpdirname:
152
+ filepath = os.path.join(tmpdirname, "video.mp4")
153
+ download_yt_audio(yt_url, filepath)
154
+ with open(filepath, "rb") as f:
155
+ inputs = f.read()
156
+
157
+ inputs = ffmpeg_read(inputs, processor.feature_extractor.sampling_rate)
158
+ inputs = {"array": inputs, "sampling_rate": processor.feature_extractor.sampling_rate}
159
+
160
+ inputs = processor(inputs, return_tensors="pt", sampling_rate=16000).to(device)
161
+ with torch.no_grad():
162
+ generated_ids = model_s2s.generate(inputs["input_features"])
163
+ transcription = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
164
+
165
+ return html_embed_str, transcription
166
+
167
+ # Custom CSS for white background and black text for input and output boxes
168
+ custom_css = """
169
+ body {
170
+ background-color: #ffffff;
171
+ color: #000000;
172
+ font-family: Arial, sans-serif;
173
+ }
174
+ .gradio-container {
175
+ max-width: 1000px;
176
+ margin: 0 auto;
177
+ padding: 20px;
178
+ background-color: #ffffff;
179
+ border: 1px solid #e0e0e0;
180
+ border-radius: 8px;
181
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
182
+ }
183
+ .gr-button {
184
+ background-color: #ffffff !important;
185
+ border-color: #ffffff !important;
186
+ color: #000000 !important;
187
+ margin: 5px;
188
+ }
189
+ .gr-button:hover {
190
+ background-color: #ffffff !important;
191
+ border-color: #004085 !important;
192
+ }
193
+ .gr-input, .gr-textbox, .gr-slider, .gr-markdown, .gr-chatbox {
194
+ border-radius: 4px;
195
+ border: 1px solid #ced4da;
196
+ background-color: #ffffff !important;
197
+ color: #000000 !important;
198
+ }
199
+ .gr-input:focus, .gr-textbox:focus, .gr-slider:focus {
200
+ border-color: #ffffff;
201
+ outline: 0;
202
+ box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 1.0);
203
+ }
204
+ #flagging-button {
205
+ display: none;
206
+ }
207
+ footer {
208
+ display: none;
209
+ }
210
+ .chatbox .chat-container .chat-message {
211
+ background-color: #ffffff !important;
212
+ color: #000000 !important;
213
+ }
214
+ .chatbox .chat-container .chat-message-input {
215
+ background-color: #ffffff !important;
216
+ color: #000000 !important;
217
+ }
218
+ .gr-markdown {
219
+ background-color: #ffffff !important;
220
+ color: #000000 !important;
221
+ }
222
+ .gr-markdown h1, .gr-markdown h2, .gr-markdown h3, .gr-markdown h4, .gr-markdown h5, .gr-markdown h6, .gr-markdown p, .gr-markdown ul, .gr-markdown ol, .gr-markdown li {
223
+ color: #000000 !important;
224
+ }
225
+ .score-box {
226
+ width: 60px;
227
+ height: 60px;
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ font-size: 12px;
232
+ font-weight: bold;
233
+ color: black;
234
+ margin: 5px;
235
+ }
236
+ .scroll-box {
237
+ max-height: 200px;
238
+ overflow-y: scroll;
239
+ border: 1px solid #ced4da;
240
+ padding: 10px;
241
+ border-radius: 4px;
242
+ }
243
+ """
244
 
245
  def chat_between_bots(system_message1, system_message2, max_tokens, temperature, top_p, history1, history2, shared_history, message):
246
  response1, history1 = list(respond(message, history1, system_message1, max_tokens, temperature, top_p))[-1]
247
  response2, history2 = list(respond(message, history2, system_message2, max_tokens, temperature, top_p))[-1]
248
+ shared_history.append(f"Prosecutor: {response1}")
249
+ shared_history.append(f"Defense Attorney: {response2}")
250
 
251
+ max_length = max(len(response1), len(response2))
252
+ response1 = response1[:max_length]
253
+ response2 = response2[:max_length]
254
+
255
+ outcome = generate_case_outcome(response1, response2)
256
+ winner = determine_outcome(outcome)
257
+
258
+ return response1, response2, history1, history2, shared_history, outcome
259
 
260
+ def get_top_10_cases():
261
+ prompt = "List 10 high-profile legal cases that have received significant media attention and are currently ongoing. Just a list of case names and numbers."
262
  response = ""
263
  for message in client.chat_completion(
264
+ [{"role": "system", "content": "You are a legal research expert, able to provide information about high-profile legal cases."},
265
  {"role": "user", "content": prompt}],
266
  max_tokens=512,
267
  stream=True,
 
273
  response += token
274
  return response
275
 
 
 
 
 
 
 
 
276
  def add_message(history, message):
277
+ for x in message["files"]:
278
+ history.append(((x,), None))
279
+ if message["text"] is not None:
280
+ history.append((message["text"], None))
281
+ return history, gr.MultimodalTextbox(value=None, interactive=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  def print_like_dislike(x: gr.LikeData):
284
  print(x.index, x.value, x.liked)
 
289
  def save_conversation(history1, history2, shared_history):
290
  return history1, history2, shared_history
291
 
292
+ def ask_about_case_outcome(shared_history, question):
293
+ prompt = f"Case Outcome: {shared_history}\n\nQuestion: {question}\n\nAnswer:"
294
+ response = ""
295
+ for message in client.chat_completion(
296
+ [{"role": "system", "content": "You are a legal expert answering questions based on the case outcome provided."},
297
+ {"role": "user", "content": prompt}],
298
+ max_tokens=512,
299
+ stream=True,
300
+ temperature=0.6,
301
+ top_p=0.95,
302
+ ):
303
+ token = message.choices[0].delta.content
304
+ if token is not None:
305
+ response += token
306
+ return response
307
 
308
  with gr.Blocks(css=custom_css) as demo:
309
  history1 = gr.State([])
310
  history2 = gr.State([])
311
  shared_history = gr.State([])
312
+ top_10_cases = gr.State("")
313
+
 
314
  with gr.Tab("Argument Evaluation"):
315
+ with gr.Row():
316
+ with gr.Column(scale=1):
317
+ top_10_btn = gr.Button("Give me the top 10 cases")
318
+ top_10_output = gr.Textbox(label="Top 10 Cases", interactive=False, elem_classes=["scroll-box"])
319
+ top_10_btn.click(get_top_10_cases, outputs=top_10_output)
320
+ with gr.Column(scale=2):
321
+ message = gr.Textbox(label="Case to Argue")
322
+ system_message1 = gr.State("You are an expert Prosecutor. Give your best arguments for the case on behalf of the prosecution.")
323
+ system_message2 = gr.State("You are an expert Defense Attorney. Give your best arguments for the case on behalf of the Defense.")
324
+ max_tokens = gr.State(512)
325
+ temperature = gr.State(0.6)
326
+ top_p = gr.State(0.95)
327
+
328
+ with gr.Row():
329
+ with gr.Column(scale=4):
330
+ prosecutor_response = gr.Textbox(label="Prosecutor's Response", interactive=True, elem_classes=["scroll-box"])
331
+ with gr.Column(scale=1):
332
+ prosecutor_score_color = gr.HTML()
333
+
334
+ with gr.Column(scale=4):
335
+ defense_response = gr.Textbox(label="Defense Attorney's Response", interactive=True, elem_classes=["scroll-box"])
336
+ with gr.Column(scale=1):
337
+ defense_score_color = gr.HTML()
338
+
339
+ outcome = gr.Textbox(label="Outcome", interactive=False, elem_classes=["scroll-box"])
340
+
341
+ with gr.Row():
342
+ submit_btn = gr.Button("Argue")
343
+ clear_btn = gr.Button("Clear and Reset")
344
+ save_btn = gr.Button("Save Conversation")
345
+
346
+ submit_btn.click(chat_between_bots, inputs=[system_message1, system_message2, max_tokens, temperature, top_p, history1, history2, shared_history, message], outputs=[prosecutor_response, defense_response, history1, history2, shared_history, outcome])
347
+ clear_btn.click(reset_conversation, outputs=[history1, history2, shared_history, prosecutor_response, defense_response, outcome])
348
+ save_btn.click(save_conversation, inputs=[history1, history2, shared_history], outputs=[history1, history2, shared_history])
349
+
350
+ with gr.Tab("Practice Arguments"):
351
+ mf_transcribe = gr.Interface(
352
+ fn=transcribe,
353
+ inputs=[
354
+ gr.Audio(type="filepath", label="Record or Upload Audio"),
355
+ gr.Radio(["transcribe", "translate"], label="Task", value="transcribe"),
356
+ ],
357
+ outputs="text",
358
+ layout="horizontal",
359
+ title="Practice Legal Arguments - Microphone",
360
+ description=(
361
+ "Practice your legal arguments by recording them through your microphone or uploading an audio file. The arguments will be transcribed for review."
362
+ ),
363
+ allow_flagging="never",
364
+ )
365
+
366
+ yt_transcribe = gr.Interface(
367
+ fn=yt_transcribe,
368
+ inputs=[
369
+ gr.Textbox(lines=1, placeholder="Paste the URL to a YouTube video here", label="YouTube URL"),
370
+ gr.Radio(["transcribe", "translate"], label="Task", value="transcribe")
371
+ ],
372
+ outputs=["html", "text"],
373
+ layout="horizontal",
374
+ title="Practice Legal Arguments - YouTube",
375
+ description=(
376
+ "Practice your legal arguments by providing a YouTube video link. The arguments will be transcribed for review."
377
+ ),
378
+ allow_flagging="never",
379
+ )
380
+
381
+ gr.TabbedInterface([mf_transcribe, yt_transcribe], ["Microphone", "YouTube"])
382
+
383
+ with gr.Tab("Case Outcome Chat"):
384
+ case_question = gr.Textbox(label="Ask a Question about the Case Outcome")
385
+ case_answer = gr.Textbox(label="Answer", interactive=False, elem_classes=["scroll-box"])
386
+ ask_case_btn = gr.Button("Ask")
387
+
388
+ ask_case_btn.click(ask_about_case_outcome, inputs=[shared_history, case_question], outputs=case_answer)
389
+
390
+ demo.queue()
391
  demo.launch()