From 789a89587625534aef7dbe4df9fb5f26f0c76659 Mon Sep 17 00:00:00 2001 From: Spyros Date: Tue, 29 Aug 2023 17:46:06 +0100 Subject: [PATCH] Fix chatbot answers presentation (#345) * remove versions from pillow and make psycopg install the binary version * fix prompt client edge case bug * lint * fixed how the chatbot presents answers, tickets #331 and #342 * lint * fix smartlink bug * lint --- .../frontend/src/pages/chatbot/chatbot.tsx | 31 ++++++++++++++++--- application/prompt_client/prompt_client.py | 9 +++--- application/tests/web_main_test.py | 11 +++---- application/web/web_main.py | 7 +++-- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/application/frontend/src/pages/chatbot/chatbot.tsx b/application/frontend/src/pages/chatbot/chatbot.tsx index 8664de593..73eec06e7 100644 --- a/application/frontend/src/pages/chatbot/chatbot.tsx +++ b/application/frontend/src/pages/chatbot/chatbot.tsx @@ -299,11 +299,25 @@ export const Chatbot = () => { } function displayDocument(d: Document) { + var link = '/node/' + d.doctype.toLowerCase() + '/' + d.name; + if (d.section) { + link = link + '/section/' + d.section; + } else { + link = link + '/sectionid/' + d.sectionID; + } return ( - - *Reference: The above answer was based on the {d.name} section of{' '} - {d.section ? d.section : d.sectionID}; - +

+

+ *Reference: The above answer was based on: + + {' '} + {d.name} section: {d.section ? d.section : d.sectionID}; + +

+

+ You can find more information about {d.name} on its OpenCRE page +

+

); } @@ -372,6 +386,15 @@ export const Chatbot = () => {
+
+ + ChatCRE uses Google's PALM2 LLM, you can find the code for OpenCRE in + https://github.com/owaps/OpenCRE. Your question travels to Heroku (OpenCRE hosting provider) + and then to GCP over a protected connection. Your data is never stored in the OpenCRE + servers, you can start a new session by refreshing your page. The OpenCRE team has taken all + reasonable precautions we could think off to protect your privacy and security. + +
diff --git a/application/prompt_client/prompt_client.py b/application/prompt_client/prompt_client.py index 95918bccc..280556b1d 100644 --- a/application/prompt_client/prompt_client.py +++ b/application/prompt_client/prompt_client.py @@ -415,9 +415,9 @@ def generate_text(self, prompt: str) -> Dict[str, str]: timestamp = datetime.now().strftime("%I:%M:%S %p") if not prompt: return {"response": "", "table": "", "timestamp": timestamp} - logger.info(f"getting embeddings for {prompt}") + logger.debug(f"getting embeddings for {prompt}") question_embedding = self.ai_client.get_text_embeddings(prompt) - logger.info(f"retrieved embeddings for {prompt}") + logger.debug(f"retrieved embeddings for {prompt}") # Find the closest area in the existing embeddings closest_id, similarity = self.get_id_of_most_similar_node_paginated( @@ -426,8 +426,7 @@ def generate_text(self, prompt: str) -> Dict[str, str]: ) closest_object = self.database.get_node_by_db_id(closest_id) answer = "" - - logger.info( + logger.debug( f"The prompt {prompt}, was most similar to object \n{closest_object}\n, with similarity:{similarity}" ) closest_content = "" @@ -449,7 +448,7 @@ def generate_text(self, prompt: str) -> Dict[str, str]: else: return {"response": "An adequate answer could not be found", "table": [""]} - logger.info(f"retrieved completion for {prompt}") + logger.debug(f"retrieved completion for {prompt}") table = [closest_object] result = f"Answer: {answer}" return {"response": result, "table": table} diff --git a/application/tests/web_main_test.py b/application/tests/web_main_test.py index b79807a3f..224328750 100644 --- a/application/tests/web_main_test.py +++ b/application/tests/web_main_test.py @@ -543,7 +543,7 @@ def test_smartlink(self) -> None: for head in response.headers: if head[0] == "Location": location = head[1] - self.assertEqual(location, "/node/Standard/CWE/sectionid/456") + self.assertEqual(location, "/node/standard/CWE/sectionid/456") self.assertEqual(302, response.status_code) response = client.get( @@ -554,9 +554,10 @@ def test_smartlink(self) -> None: for head in response.headers: if head[0] == "Location": location = head[1] - self.assertEqual(location, "/node/Standard/ASVS/section/v0.1.2") + self.assertEqual(location, "/node/standard/ASVS/section/v0.1.2") self.assertEqual(302, response.status_code) + # negative test, this cwe does not exist, therefore there is nowhere to redirect to response = client.get( "/smartlink/standard/CWE/999", headers={"Content-Type": "application/json"}, @@ -565,7 +566,5 @@ def test_smartlink(self) -> None: for head in response.headers: if head[0] == "Location": location = head[1] - self.assertEqual( - location, "https://cwe.mitre.org/data/definitions/999.html" - ) - self.assertEqual(302, response.status_code) + self.assertEqual(location, "") + self.assertEqual(404, response.status_code) diff --git a/application/web/web_main.py b/application/web/web_main.py index 9381c8079..c7dcbf122 100644 --- a/application/web/web_main.py +++ b/application/web/web_main.py @@ -300,8 +300,9 @@ def smartlink( opt_version = request.args.get("version") # match ntype to the credoctypes case-insensitive typ = [t for t in defs.Credoctypes if t.value.lower() == ntype.lower()] + doctype = None if typ: - ntype = typ[0] + doctype = typ[0] page = 1 items_per_page = 1 @@ -312,7 +313,7 @@ def smartlink( page=int(page), items_per_page=int(items_per_page), version=opt_version, - ntype=ntype, + ntype=doctype, ) if not nodes or len(nodes) == 0: @@ -322,7 +323,7 @@ def smartlink( page=int(page), items_per_page=int(items_per_page), version=opt_version, - ntype=ntype, + ntype=doctype, ) found_section_id = True if nodes and len(nodes[0].links):