From f62ec2ad3c218a401050dbd575154a4478fbe878 Mon Sep 17 00:00:00 2001 From: James Osmond Date: Wed, 17 Apr 2024 10:53:14 +0100 Subject: [PATCH 1/4] Conversation bot (WIP) --- app/pages/2_Transcript.py | 2 +- app/pages/3_Summary.py | 36 ++++++++++++++++----------- config/settings.py | 2 ++ hackathon/api.py | 51 ++++++++++++++++++++++----------------- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/app/pages/2_Transcript.py b/app/pages/2_Transcript.py index 6c88048..c96f157 100644 --- a/app/pages/2_Transcript.py +++ b/app/pages/2_Transcript.py @@ -14,7 +14,7 @@ get_logger = setup_logging() logger = get_logger(__name__) -st.set_page_config(page_title="Meeting Record Creator", page_icon="memo", layout="wide") +st.set_page_config(page_title="QuickQuill", page_icon="memo", layout="wide") # Password protection of pages if ENV.upper() == "PROD" and not check_password(): diff --git a/app/pages/3_Summary.py b/app/pages/3_Summary.py index de099b5..d22ae1a 100644 --- a/app/pages/3_Summary.py +++ b/app/pages/3_Summary.py @@ -2,23 +2,21 @@ import datetime as dt import io import os -import time +import time import streamlit as st from PIL import Image from config.logging import setup_logging from config.settings import ENV +from hackathon.api import conversation_api, fact_check_api, glossery_api, summary_api from hackathon.streamlit.utils import check_password from hackathon.transcripts.transcript_handling import Transcript -from hackathon.api import summary_api -from hackathon.api import fact_check_api -from hackathon.api import glossery_api get_logger = setup_logging() logger = get_logger(__name__) -st.set_page_config(page_title="Meeting Record Creator", page_icon="memo", layout="wide") +st.set_page_config(page_title="QuickQuill", page_icon="memo", layout="wide") # Password protection of pages if ENV.upper() == "PROD" and not check_password(): @@ -107,23 +105,30 @@ def image_to_base64(image): def llm_summarise(transcript: str) -> str: post_response = summary_api.invoke_post(transcript) fact_check_response = fact_check_api.invoke_post(transcript) + conversation_response = conversation_api.invoke_post(transcript) time.sleep(15) get_summary_response = summary_api.invoke_get(post_response["conversationId"]) get_fact_response = fact_check_api.invoke_get(fact_check_response["conversationId"]) post_glossary = glossery_api.invoke_post(get_summary_response) - time.sleep(15) + time.sleep(25) get_glossary = glossery_api.invoke_get(post_glossary["conversationId"]) + conversation_api.invoke_get(conversation_response["conversationId"]) return { - "summary" : get_summary_response, - "facts" : get_fact_response, - "glossary" : get_glossary - } + "summary": get_summary_response, + "facts": get_fact_response, + "glossary": get_glossary, + "conversationConversationId": conversation_response["conversationId"], + } -def query_llm(prompt: str) -> str: - return f'Hello! I am *not* an LLM! James created me as an "artificial artificial intelligence" - this is the only thing I can say. ({dt.datetime.now()})' +def query_llm(prompt: str, transcript: str, conversationId) -> str: + query = f"With knowledge of this transcript:\n{{transcript}}\n\nAnswer this query: {prompt}" + query_response = conversation_api.invoke_post(query, conversationId) + time.sleep(15) + chat_response = conversation_api.invoke_get(query_response["conversationId"]) + return chat_response with st.expander("#### Upload transcript", expanded=False): @@ -140,14 +145,17 @@ def query_llm(prompt: str) -> str: else: st_summarise_button = st.button("Generate meeting summary") if st_summarise_button or st.session_state.summary_generated: + if not st.session_state.summary_generated: + returned_data = llm_summarise(transcript=data) + st.session_state.returned_data = returned_data + returned_data = st.session_state.returned_data st.session_state.summary_generated = True - returned_data = llm_summarise(transcript=data) st.markdown(returned_data["summary"]) prompt = st.text_input(label="Enter query here:", placeholder="How ") st_query_button = st.button("Query LLM") if st_query_button and prompt != "": st.session_state.chat_history += f"User: {prompt}\n\n" - st.session_state.chat_history += f"Claude: {query_llm(prompt)}\n\n" + st.session_state.chat_history += f"Claude: {query_llm(prompt, data, conversationId=returned_data['conversationConversationId'])}\n\n" st.markdown(st.session_state.chat_history) # TODO: Add button to download summary as txt file diff --git a/config/settings.py b/config/settings.py index 8aa5336..a826875 100644 --- a/config/settings.py +++ b/config/settings.py @@ -45,3 +45,5 @@ FACTCHECK_URL = os.environ.get("FACTCHECK_URL") GLOSSERY_API = os.environ.get("GLOSSERY_API") GLOSSERY_URL = os.environ.get("GLOSSERY_URL") +CONVERSATION_API = os.environ.get("CONVERSATION_API") +CONVERSATION_URL = os.environ.get("CONVERSATION_URL") diff --git a/hackathon/api.py b/hackathon/api.py index 0911cca..3c2eff9 100644 --- a/hackathon/api.py +++ b/hackathon/api.py @@ -1,43 +1,49 @@ -import requests import time -from config.settings import MODEL -from config.settings import SUMMARISE_API -from config.settings import SUMMARISE_URL -from config.settings import FACTCHECK_API -from config.settings import FACTCHECK_URL -from config.settings import GLOSSERY_API -from config.settings import GLOSSERY_URL +import requests + +from config.settings import ( + CONVERSATION_API, + CONVERSATION_URL, + FACTCHECK_API, + FACTCHECK_URL, + GLOSSERY_API, + GLOSSERY_URL, + MODEL, + SUMMARISE_API, + SUMMARISE_URL, +) + class API: def __init__(self, api_key, url): - self.api_key = api_key + self.api_key = api_key self.url = url self.headers = { "Content-Type": "application/json", "X-API-Key": f"{self.api_key}", } - def invoke_post(self, message): + def invoke_post(self, message, conversation_id=None): post_data = { - "message": { + "message": { "content": [ - { - "contentType": "text", - "mediaType": "string", - "body": message - } + {"contentType": "text", "mediaType": "string", "body": message} ], - "model": MODEL + "model": MODEL, } } - response = requests.post(self.url+ "/conversation", json=post_data, headers=self.headers) - json_respn = response.json() + if conversation_id is not None: + post_data["conversationId"] = conversation_id + response = requests.post( + self.url + "/conversation", json=post_data, headers=self.headers + ) + json_respn = response.json() return json_respn - + def invoke_get(self, conversation_id): - uri_path = "/conversation/"+conversation_id + uri_path = "/conversation/" + conversation_id response = requests.get( self.url + uri_path, headers=self.headers, @@ -46,8 +52,9 @@ def invoke_get(self, conversation_id): last_msg_id = json_response["lastMessageId"] return json_response["messageMap"][last_msg_id]["content"][0]["body"] - + summary_api = API(SUMMARISE_API, SUMMARISE_URL) fact_check_api = API(FACTCHECK_API, FACTCHECK_URL) glossery_api = API(GLOSSERY_API, GLOSSERY_URL) +conversation_api = API(CONVERSATION_API, CONVERSATION_URL) From d4a36580ec7cd1b33a0910e40b4712aa7e5eac37 Mon Sep 17 00:00:00 2001 From: James Osmond Date: Wed, 17 Apr 2024 11:08:46 +0100 Subject: [PATCH 2/4] Conversation works --- app/pages/3_Summary.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/pages/3_Summary.py b/app/pages/3_Summary.py index d22ae1a..42294bf 100644 --- a/app/pages/3_Summary.py +++ b/app/pages/3_Summary.py @@ -124,7 +124,8 @@ def llm_summarise(transcript: str) -> str: def query_llm(prompt: str, transcript: str, conversationId) -> str: - query = f"With knowledge of this transcript:\n{{transcript}}\n\nAnswer this query: {prompt}" + query = f"With knowledge of this transcript:\n{transcript}\n\nAnswer this query: {prompt}" + print(query) query_response = conversation_api.invoke_post(query, conversationId) time.sleep(15) chat_response = conversation_api.invoke_get(query_response["conversationId"]) @@ -160,9 +161,11 @@ def query_llm(prompt: str, transcript: str, conversationId) -> str: # TODO: Add button to download summary as txt file with st.expander("#### Identify facts", expanded=False): - if returned_data.get("facts"): + if returned_data.get("facts") and st.session_state.summary_generated: + returned_data = st.session_state.returned_data st.write(returned_data["facts"]) with st.expander("#### Generate glossary", expanded=False): - if returned_data.get("glossary"): + if returned_data.get("glossary") and st.session_state.summary_generated: + returned_data = st.session_state.returned_data st.write(returned_data["glossary"]) From 691dbe5e39040f5be2f07ec2b8ce2ff17e8187c6 Mon Sep 17 00:00:00 2001 From: James Osmond Date: Wed, 17 Apr 2024 11:10:34 +0100 Subject: [PATCH 3/4] Conflicts fixed --- app/pages/3_Summary.py | 22 +++++++++++++----- config/settings.py | 2 ++ hackathon/api.py | 51 ++++++++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/app/pages/3_Summary.py b/app/pages/3_Summary.py index cf1fa60..57f2306 100644 --- a/app/pages/3_Summary.py +++ b/app/pages/3_Summary.py @@ -9,7 +9,7 @@ from config.logging import setup_logging from config.settings import ENV -from hackathon.api import fact_check_api, glossery_api, summary_api +from hackathon.api import conversation_api, fact_check_api, glossery_api, summary_api from hackathon.streamlit.utils import check_password from hackathon.transcripts.transcript_handling import Transcript @@ -105,23 +105,30 @@ def image_to_base64(image): def llm_summarise(transcript: str) -> str: post_response = summary_api.invoke_post(transcript) fact_check_response = fact_check_api.invoke_post(transcript) + conversation_response = conversation_api.invoke_post(transcript) time.sleep(15) get_summary_response = summary_api.invoke_get(post_response["conversationId"]) get_fact_response = fact_check_api.invoke_get(fact_check_response["conversationId"]) post_glossary = glossery_api.invoke_post(get_summary_response) - time.sleep(15) + time.sleep(25) get_glossary = glossery_api.invoke_get(post_glossary["conversationId"]) + conversation_api.invoke_get(conversation_response["conversationId"]) return { "summary": get_summary_response, "facts": get_fact_response, "glossary": get_glossary, + "conversationConversationId": conversation_response["conversationId"], } -def query_llm(prompt: str) -> str: - return f'Hello! I am *not* an LLM! James created me as an "artificial artificial intelligence" - this is the only thing I can say. ({dt.datetime.now()})' +def query_llm(prompt: str, transcript: str, conversationId) -> str: + query = f"With knowledge of this transcript:\n{{transcript}}\n\nAnswer this query: {prompt}" + query_response = conversation_api.invoke_post(query, conversationId) + time.sleep(15) + chat_response = conversation_api.invoke_get(query_response["conversationId"]) + return chat_response with st.expander("#### Upload transcript", expanded=False): @@ -138,14 +145,17 @@ def query_llm(prompt: str) -> str: else: st_summarise_button = st.button("Generate meeting summary") if st_summarise_button or st.session_state.summary_generated: + if not st.session_state.summary_generated: + returned_data = llm_summarise(transcript=data) + st.session_state.returned_data = returned_data + returned_data = st.session_state.returned_data st.session_state.summary_generated = True - returned_data = llm_summarise(transcript=data) st.markdown(returned_data["summary"]) prompt = st.text_input(label="Enter query here:", placeholder="How ") st_query_button = st.button("Query LLM") if st_query_button and prompt != "": st.session_state.chat_history += f"User: {prompt}\n\n" - st.session_state.chat_history += f"Claude: {query_llm(prompt)}\n\n" + st.session_state.chat_history += f"Claude: {query_llm(prompt, data, conversationId=returned_data['conversationConversationId'])}\n\n" st.markdown(st.session_state.chat_history) # TODO: Add button to download summary as txt file diff --git a/config/settings.py b/config/settings.py index 8aa5336..a826875 100644 --- a/config/settings.py +++ b/config/settings.py @@ -45,3 +45,5 @@ FACTCHECK_URL = os.environ.get("FACTCHECK_URL") GLOSSERY_API = os.environ.get("GLOSSERY_API") GLOSSERY_URL = os.environ.get("GLOSSERY_URL") +CONVERSATION_API = os.environ.get("CONVERSATION_API") +CONVERSATION_URL = os.environ.get("CONVERSATION_URL") diff --git a/hackathon/api.py b/hackathon/api.py index 0911cca..3c2eff9 100644 --- a/hackathon/api.py +++ b/hackathon/api.py @@ -1,43 +1,49 @@ -import requests import time -from config.settings import MODEL -from config.settings import SUMMARISE_API -from config.settings import SUMMARISE_URL -from config.settings import FACTCHECK_API -from config.settings import FACTCHECK_URL -from config.settings import GLOSSERY_API -from config.settings import GLOSSERY_URL +import requests + +from config.settings import ( + CONVERSATION_API, + CONVERSATION_URL, + FACTCHECK_API, + FACTCHECK_URL, + GLOSSERY_API, + GLOSSERY_URL, + MODEL, + SUMMARISE_API, + SUMMARISE_URL, +) + class API: def __init__(self, api_key, url): - self.api_key = api_key + self.api_key = api_key self.url = url self.headers = { "Content-Type": "application/json", "X-API-Key": f"{self.api_key}", } - def invoke_post(self, message): + def invoke_post(self, message, conversation_id=None): post_data = { - "message": { + "message": { "content": [ - { - "contentType": "text", - "mediaType": "string", - "body": message - } + {"contentType": "text", "mediaType": "string", "body": message} ], - "model": MODEL + "model": MODEL, } } - response = requests.post(self.url+ "/conversation", json=post_data, headers=self.headers) - json_respn = response.json() + if conversation_id is not None: + post_data["conversationId"] = conversation_id + response = requests.post( + self.url + "/conversation", json=post_data, headers=self.headers + ) + json_respn = response.json() return json_respn - + def invoke_get(self, conversation_id): - uri_path = "/conversation/"+conversation_id + uri_path = "/conversation/" + conversation_id response = requests.get( self.url + uri_path, headers=self.headers, @@ -46,8 +52,9 @@ def invoke_get(self, conversation_id): last_msg_id = json_response["lastMessageId"] return json_response["messageMap"][last_msg_id]["content"][0]["body"] - + summary_api = API(SUMMARISE_API, SUMMARISE_URL) fact_check_api = API(FACTCHECK_API, FACTCHECK_URL) glossery_api = API(GLOSSERY_API, GLOSSERY_URL) +conversation_api = API(CONVERSATION_API, CONVERSATION_URL) From 4538c2cdfc1321c340b6189f3b9c44f0e68895d1 Mon Sep 17 00:00:00 2001 From: James Osmond Date: Wed, 17 Apr 2024 11:08:46 +0100 Subject: [PATCH 4/4] Conversation works --- app/pages/3_Summary.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/pages/3_Summary.py b/app/pages/3_Summary.py index 57f2306..30681ab 100644 --- a/app/pages/3_Summary.py +++ b/app/pages/3_Summary.py @@ -124,7 +124,8 @@ def llm_summarise(transcript: str) -> str: def query_llm(prompt: str, transcript: str, conversationId) -> str: - query = f"With knowledge of this transcript:\n{{transcript}}\n\nAnswer this query: {prompt}" + query = f"With knowledge of this transcript:\n{transcript}\n\nAnswer this query: {prompt}" + print(query) query_response = conversation_api.invoke_post(query, conversationId) time.sleep(15) chat_response = conversation_api.invoke_get(query_response["conversationId"]) @@ -160,9 +161,11 @@ def query_llm(prompt: str, transcript: str, conversationId) -> str: # TODO: Add button to download summary as txt file with st.expander("#### Identify facts", expanded=False): - if returned_data.get("facts"): + if returned_data.get("facts") and st.session_state.summary_generated: + returned_data = st.session_state.returned_data st.write(returned_data["facts"]) with st.expander("#### Generate glossary", expanded=False): - if returned_data.get("glossary"): + if returned_data.get("glossary") and st.session_state.summary_generated: + returned_data = st.session_state.returned_data st.write(returned_data["glossary"])