Added response streaming to QnA
Browse files
app.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
| 3 |
from __future__ import annotations
|
| 4 |
|
| 5 |
import html
|
|
|
|
| 6 |
from pathlib import Path
|
| 7 |
from uuid import uuid4
|
| 8 |
from typing import Any
|
|
@@ -37,6 +38,7 @@ PROVIDER_LABEL_BY_NAME = {name: display for name, display, _ in PROVIDER_OPTIONS
|
|
| 37 |
ANALYSIS_PLACEHOLDER = "Run an analysis to populate this section."
|
| 38 |
EXAMPLE_BILL_LABELS = example_bill_titles()
|
| 39 |
EXAMPLE_BILL_URLS = example_bill_urls_by_title()
|
|
|
|
| 40 |
APP_THEME = gr.themes.Soft(
|
| 41 |
primary_hue="sky",
|
| 42 |
secondary_hue="slate",
|
|
@@ -394,6 +396,22 @@ def _format_chat_entry(answer_text: str, citations: list[dict[str, Any]], *, pro
|
|
| 394 |
return f"{prefix}{answer_text}\n\nSupporting snippets:\n{citations_text}"
|
| 395 |
|
| 396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
def _deeper_answer_updates(visible: bool, label: str = "Run deeper full-document answer") -> gr.update:
|
| 398 |
return gr.update(visible=visible, value=label)
|
| 399 |
|
|
@@ -679,9 +697,12 @@ def ask_question(
|
|
| 679 |
return
|
| 680 |
|
| 681 |
citations = [citation.model_dump() for citation in answer.citations]
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
|
|
|
|
|
|
|
|
|
| 685 |
]
|
| 686 |
record["chat_history"] = chat_history
|
| 687 |
record["pending_deeper_question"] = question_text if answer.deeper_answer_available else None
|
|
@@ -721,8 +742,11 @@ def run_deeper_answer(
|
|
| 721 |
return
|
| 722 |
|
| 723 |
citations = [citation.model_dump() for citation in answer.citations]
|
|
|
|
|
|
|
|
|
|
| 724 |
chat_history = chat_history + [
|
| 725 |
-
{"role": "assistant", "content": _format_chat_entry(answer.answer, citations, provenance=answer.provenance)}
|
| 726 |
]
|
| 727 |
record["chat_history"] = chat_history
|
| 728 |
record["pending_deeper_question"] = None
|
|
|
|
| 3 |
from __future__ import annotations
|
| 4 |
|
| 5 |
import html
|
| 6 |
+
import time
|
| 7 |
from pathlib import Path
|
| 8 |
from uuid import uuid4
|
| 9 |
from typing import Any
|
|
|
|
| 38 |
ANALYSIS_PLACEHOLDER = "Run an analysis to populate this section."
|
| 39 |
EXAMPLE_BILL_LABELS = example_bill_titles()
|
| 40 |
EXAMPLE_BILL_URLS = example_bill_urls_by_title()
|
| 41 |
+
CHAT_STREAM_DELAY_SECONDS = 0.004
|
| 42 |
APP_THEME = gr.themes.Soft(
|
| 43 |
primary_hue="sky",
|
| 44 |
secondary_hue="slate",
|
|
|
|
| 396 |
return f"{prefix}{answer_text}\n\nSupporting snippets:\n{citations_text}"
|
| 397 |
|
| 398 |
|
| 399 |
+
def _stream_chat_entry(
|
| 400 |
+
base_history: list[dict[str, str]],
|
| 401 |
+
answer_text: str,
|
| 402 |
+
citations: list[dict[str, Any]],
|
| 403 |
+
*,
|
| 404 |
+
provenance: str = "analysis_based",
|
| 405 |
+
):
|
| 406 |
+
formatted_answer = _format_chat_entry(answer_text, citations, provenance=provenance)
|
| 407 |
+
streamed_answer = ""
|
| 408 |
+
for character in formatted_answer:
|
| 409 |
+
streamed_answer += character
|
| 410 |
+
yield base_history + [{"role": "assistant", "content": streamed_answer}]
|
| 411 |
+
if CHAT_STREAM_DELAY_SECONDS:
|
| 412 |
+
time.sleep(CHAT_STREAM_DELAY_SECONDS)
|
| 413 |
+
|
| 414 |
+
|
| 415 |
def _deeper_answer_updates(visible: bool, label: str = "Run deeper full-document answer") -> gr.update:
|
| 416 |
return gr.update(visible=visible, value=label)
|
| 417 |
|
|
|
|
| 697 |
return
|
| 698 |
|
| 699 |
citations = [citation.model_dump() for citation in answer.citations]
|
| 700 |
+
user_history = chat_history + [{"role": "user", "content": question_text}]
|
| 701 |
+
for partial_history in _stream_chat_entry(user_history, answer.answer, citations, provenance=answer.provenance):
|
| 702 |
+
yield partial_history, session_state, "", _deeper_answer_updates(False), ""
|
| 703 |
+
|
| 704 |
+
chat_history = user_history + [
|
| 705 |
+
{"role": "assistant", "content": _format_chat_entry(answer.answer, citations, provenance=answer.provenance)}
|
| 706 |
]
|
| 707 |
record["chat_history"] = chat_history
|
| 708 |
record["pending_deeper_question"] = question_text if answer.deeper_answer_available else None
|
|
|
|
| 742 |
return
|
| 743 |
|
| 744 |
citations = [citation.model_dump() for citation in answer.citations]
|
| 745 |
+
for partial_history in _stream_chat_entry(chat_history, answer.answer, citations, provenance=answer.provenance):
|
| 746 |
+
yield partial_history, session_state, "", _deeper_answer_updates(False), ""
|
| 747 |
+
|
| 748 |
chat_history = chat_history + [
|
| 749 |
+
{"role": "assistant", "content": _format_chat_entry(answer.answer, citations, provenance=answer.provenance)}
|
| 750 |
]
|
| 751 |
record["chat_history"] = chat_history
|
| 752 |
record["pending_deeper_question"] = None
|