Skip to content

Commit f4def87

Browse files
committed
UI updates and other progress. Still only searching on first message...
1 parent afeb532 commit f4def87

File tree

159 files changed

+40696
-260
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

159 files changed

+40696
-260
lines changed

app.py

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
send_from_directory,
1616
render_template,
1717
)
18+
from bs4 import BeautifulSoup
19+
from status_blueprint import bp as status_bp, set_status_message
1820
from pprint import pprint
1921
import requests
2022
from openai.types.chat import chat_completion
@@ -40,13 +42,21 @@
4042

4143
bp = Blueprint("routes", __name__, static_folder="static", template_folder="static")
4244

43-
4445
def create_app():
4546
app = Quart(__name__)
4647
app.register_blueprint(bp)
48+
app.register_blueprint(status_bp)
4749
app.config["TEMPLATES_AUTO_RELOAD"] = True
48-
return app
4950

51+
# Manually add CORS headers to each response
52+
@app.after_request
53+
async def after_request(response):
54+
response.headers.add('Access-Control-Allow-Origin', '*')
55+
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
56+
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
57+
return response
58+
59+
return app
5060

5161
@bp.route("/")
5262
async def index():
@@ -56,17 +66,14 @@ async def index():
5666
favicon=app_settings.ui.favicon
5767
)
5868

59-
6069
@bp.route("/favicon.ico")
6170
async def favicon():
6271
return await bp.send_static_file("favicon.ico")
6372

64-
6573
@bp.route("/assets/<path:path>")
6674
async def assets(path):
6775
return await send_from_directory("static/assets", path)
6876

69-
7077
# Debug settings
7178
DEBUG = os.environ.get("DEBUG", "false")
7279
if DEBUG.lower() == "true":
@@ -464,8 +471,8 @@ async def get_search_results(searches):
464471
return allresults
465472

466473
async def identify_searches(request_body, request_headers, Summaries = None):
474+
467475
if (len(request_body.get("messages")) > 2):
468-
print(f"request_body: {request_body}")
469476
# for now only search on the first message until I can figure this out - apparently we can't just replace the system prompt once the conversation is rolling...
470477
return None
471478
#print(f"on replies now..")
@@ -475,8 +482,8 @@ async def identify_searches(request_body, request_headers, Summaries = None):
475482
system_preamble = prompts["identify_searches"];
476483
else:
477484
system_preamble = prompts["identify_additional_searches"] + json.dumps(Summaries, indent=4) + "\n\nOriginal System Prompt:\n"
485+
478486
searches = await send_private_chat(request_body, request_headers, system_preamble)
479-
print(f"system_preamble: {system_preamble}")
480487
if isinstance(searches, str):
481488
if searches == "No searches required.":
482489
return None
@@ -497,19 +504,38 @@ async def get_urls_to_browse(request_body, request_headers, searches):
497504
system_prompt = prompts["get_urls_to_browse"] + strsearchresults
498505
URLsToBrowse = await send_private_chat(request_body, request_headers, None, system_prompt)
499506
return URLsToBrowse
500-
507+
508+
async def fetch_and_parse_url(url):
509+
set_status_message("Browsing...")
510+
response = requests.get(url)
511+
if response.status_code == 200: # Raise an error for bad status codes
512+
# Parse the web page
513+
soup = BeautifulSoup(response.content, 'html.parser')
514+
# Extract the main content
515+
paragraphs = soup.find_all('p')
516+
# Combine the text from the paragraphs
517+
content = ' '.join(paragraph.get_text() for paragraph in paragraphs)
518+
return content
519+
else:
520+
return None
521+
501522
async def get_article_summaries(request_body, request_headers, URLsToBrowse):
502523
Summaries = None
503524
URLsToBrowse = json.loads(URLsToBrowse)
504525
for URL in URLsToBrowse:
505-
system_prompt = "You are tasked with helping content developers resolve customer feedback on their content on learn.microsoft.com. Right now, you've identified the following URL for further research: " + URL + ". Your task now is to provide a summary of relevant content on the page that will help us address the feedback on the URL provided by the user and document current sources. Return nothing except your summary of the key points and any important quotes the content on the page in a single string.\n\n"
506-
summary = await send_private_chat(request_body, request_headers, None, system_prompt)
507-
summary = json.loads("{\"URL\" : \"" + URL + "\",\n\"summary\" : " + json.dumps(summary) + "}")
508-
if Summaries is None:
509-
Summaries = [summary]
510-
else:
511-
Summaries.append(summary)
512-
return Summaries
526+
page_content = await fetch_and_parse_url(URL)
527+
if page_content != None:
528+
system_prompt = "You are tasked with helping content developers resolve customer feedback on their content on learn.microsoft.com. Right now, you've identified the following URL for further research: " + URL + ". Your task now is to provide a summary of relevant content on the page that will help us address the feedback on the URL provided by the user and document current sources. Return nothing except your summary of the key points and any important quotes the content on the page in a single string.\n\nPage Content:\n\n" + page_content + "\n\nOriginal System Message:\n\n"
529+
530+
set_status_message("Analyzing...")
531+
summary = await send_private_chat(request_body, request_headers, None, system_prompt)
532+
summary = json.loads("{\"URL\" : \"" + URL + "\",\n\"summary\" : " + json.dumps(summary) + "}")
533+
534+
if Summaries is None:
535+
Summaries = [summary]
536+
else:
537+
Summaries.append(summary)
538+
return Summaries
513539

514540
async def is_background_info_sufficient(request_body, request_headers, Summaries):
515541
strSummaries = json.dumps(Summaries, indent=4)
@@ -525,6 +551,7 @@ async def search_and_add_background_references(request_body, request_headers):
525551
Summaries = None
526552
while NeedsMoreSummaries:
527553

554+
set_status_message("Searching...")
528555
if Summaries is None:
529556
searches = await identify_searches(request_body, request_headers)
530557
else:
@@ -534,10 +561,11 @@ async def search_and_add_background_references(request_body, request_headers):
534561
if searches == None:
535562
return None
536563

564+
set_status_message("Gathering search results...")
537565
URLsToBrowse = await get_urls_to_browse(request_body, request_headers, searches)
538566
if URLsToBrowse == "Search error.":
539567
return "Search error."
540-
568+
541569
if (Summaries is None):
542570
Summaries = await get_article_summaries(request_body, request_headers, URLsToBrowse)
543571
else:
@@ -548,6 +576,7 @@ async def search_and_add_background_references(request_body, request_headers):
548576
if AreWeDone:
549577
NeedsMoreSummaries = False
550578

579+
set_status_message("Generating answer...")
551580
return prompts["background_info_preamble"] + json.dumps(Summaries, indent=4) + "\n\nPrimary System Message:"
552581

553582
async def conversation_internal(request_body, request_headers):
@@ -1059,3 +1088,6 @@ async def generate_title(conversation_messages) -> str:
10591088

10601089

10611090
app = create_app()
1091+
1092+
if __name__ == '__main__':
1093+
app.run(debug=True)

frontend/src/pages/chat/Chat.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useRef, useState, useEffect, useContext, useLayoutEffect } from 'react'
22
import { CommandBarButton, IconButton, Dialog, DialogType, DialogFooter, DefaultButton, Stack } from '@fluentui/react'
33
import { SquareRegular, ShieldLockRegular, ErrorCircleRegular } from '@fluentui/react-icons'
4+
import axios from 'axios'
45

56
import ReactMarkdown from 'react-markdown'
67
import remarkGfm from 'remark-gfm'
@@ -46,10 +47,7 @@ const enum messageStatus {
4647
}
4748

4849
const Chat = () => {
49-
50-
const [isDialogOpen, setIsDialogOpen] = useState(false);
51-
const [queryParams, setQueryParams] = useState(new URLSearchParams(window.location.search));
52-
50+
const [statusMessage, setStatusMessage] = useState('Generating answer...');
5351
const appStateContext = useContext(AppStateContext)
5452
const ui = appStateContext?.state.frontendSettings?.ui
5553
const AUTH_ENABLED = appStateContext?.state.frontendSettings?.auth_enabled
@@ -86,6 +84,23 @@ const Chat = () => {
8684
const [ASSISTANT, TOOL, ERROR] = ['assistant', 'tool', 'error']
8785
const NO_CONTENT_ERROR = 'No content in messages object.'
8886

87+
useEffect(() => {
88+
const fetchStatus = async () => {
89+
try {
90+
if (showLoadingMessage)
91+
{
92+
const response = await axios.get('/get_status');
93+
setStatusMessage(response.data.status_message);
94+
}
95+
} catch (error) {
96+
console.error('Error fetching status:', error);
97+
}
98+
}
99+
const intervalId = setInterval(fetchStatus, 1800);
100+
101+
return () => clearInterval(intervalId); // Cleanup on unmount
102+
}, [showLoadingMessage]);
103+
89104
useEffect(() => {
90105
if (
91106
appStateContext?.state.isCosmosDBAvailable?.status !== CosmosDBStatus.Working &&
@@ -844,7 +859,7 @@ const Chat = () => {
844859
<div className={styles.chatMessageGpt}>
845860
<Answer
846861
answer={{
847-
answer: "Generating answer...",
862+
answer: statusMessage,
848863
citations: [],
849864
plotly_data: null
850865
}}

node_modules/.package-lock.json

Lines changed: 106 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node_modules/asynckit/LICENSE

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)