From a77256f6c50ea9ba0cc9ce5a38f62bc1ff256180 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 13:15:58 -0600 Subject: [PATCH 01/13] add download of LLM to dockerfile --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 2b14eba7..f2c9a873 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,8 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get -y update +RUN wget https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin -x -P ~/.cache/gpt4all/ + RUN pip3 install Django RUN set -eux; \ From 2a56abf8986e055c90231bed1a240e3c9b1e5129 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 13:16:12 -0600 Subject: [PATCH 02/13] add gpt4all as requirement --- blawx/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blawx/requirements.txt b/blawx/requirements.txt index a50aea31..2c0872d6 100644 --- a/blawx/requirements.txt +++ b/blawx/requirements.txt @@ -5,4 +5,5 @@ pyyaml cobalt clean-law >=0.0.4 django-guardian -django-preferences \ No newline at end of file +django-preferences +gtp4all \ No newline at end of file From 7e356e9a8faa355bc7b566793ac59183a0abe98a Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 13:16:34 -0600 Subject: [PATCH 03/13] create a simplification endpoint --- blawx/simplifier.py | 17 +++++++++++++++++ blawx/urls.py | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 blawx/simplifier.py diff --git a/blawx/simplifier.py b/blawx/simplifier.py new file mode 100644 index 00000000..476f90f6 --- /dev/null +++ b/blawx/simplifier.py @@ -0,0 +1,17 @@ +from django.http import Http404, HttpResponseNotFound, HttpResponseForbidden + +from rest_framework.decorators import api_view, permission_classes, authentication_classes +from rest_framework.response import Response +# from rest_framework.permissions import AllowAny +from rest_framework.authentication import SessionAuthentication, BasicAuthentication +from rest_framework.permissions import IsAuthenticated, DjangoObjectPermissions, IsAuthenticatedOrReadOnly, AllowAny + +import gpt4all + +@api_view(['POST']) +@authentication_classes([SessionAuthentication]) +@permission_classes([IsAuthenticated]) +def simplify(request): + gptj = gpt4all.GPT4All("ggml-gpt4all-j-v1.3-groovy") + messages = [{"role": "user", "content": "Simplify the following explanation: " + request.data.explanation }] + return Response(gptj.chat_completion(messages)) \ No newline at end of file diff --git a/blawx/urls.py b/blawx/urls.py index 20923733..589c4b0d 100644 --- a/blawx/urls.py +++ b/blawx/urls.py @@ -1,6 +1,6 @@ from django.contrib import admin from django.urls import include, path -from . import views, reasoner +from . import views, reasoner, simplifier from django.contrib.auth.views import LoginView, LogoutView, PasswordChangeDoneView, PasswordChangeView from .models import RuleDoc @@ -42,4 +42,5 @@ path('docs//', views.DocumentView.as_view(), name="docs_page"), path("register/", views.register_request, name="register"), path("version/",views.version,name="version"), + path("simplify/",simplifier.simplify, name="simplify"), ] From e1cb0011de276db0c6622df5a03087945b9749dd Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 14:18:25 -0600 Subject: [PATCH 04/13] correct typo in requirement name --- blawx/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blawx/requirements.txt b/blawx/requirements.txt index 2c0872d6..00ab309f 100644 --- a/blawx/requirements.txt +++ b/blawx/requirements.txt @@ -6,4 +6,4 @@ cobalt clean-law >=0.0.4 django-guardian django-preferences -gtp4all \ No newline at end of file +gpt4all \ No newline at end of file From d8db63757e7b381cf48d866b96ef7669ba16c3c4 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 14:18:54 -0600 Subject: [PATCH 05/13] correct the download location for llm --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f2c9a873..feee7c3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get -y update -RUN wget https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin -x -P ~/.cache/gpt4all/ +RUN wget https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin -P ~/.cache/gpt4all/ RUN pip3 install Django From 370a09f800815facee222c87b3d25de0cc1572f1 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 15:04:32 -0600 Subject: [PATCH 06/13] correcting data reference in call to llm --- blawx/simplifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blawx/simplifier.py b/blawx/simplifier.py index 476f90f6..0f7f4b3c 100644 --- a/blawx/simplifier.py +++ b/blawx/simplifier.py @@ -13,5 +13,5 @@ @permission_classes([IsAuthenticated]) def simplify(request): gptj = gpt4all.GPT4All("ggml-gpt4all-j-v1.3-groovy") - messages = [{"role": "user", "content": "Simplify the following explanation: " + request.data.explanation }] + messages = [{"role": "user", "content": "Simplify the following explanation: " + request.data['explanation'] }] return Response(gptj.chat_completion(messages)) \ No newline at end of file From 8e5faf38d7bee955ba7ab1de78fc29b630eb27ce Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 15:33:33 -0600 Subject: [PATCH 07/13] switching to a gpt-3.5 based simplifier --- Dockerfile | 2 -- blawx/requirements.txt | 2 +- blawx/simplifier.py | 10 ++++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index feee7c3f..2b14eba7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,8 +6,6 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get -y update -RUN wget https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin -P ~/.cache/gpt4all/ - RUN pip3 install Django RUN set -eux; \ diff --git a/blawx/requirements.txt b/blawx/requirements.txt index 00ab309f..a19c4beb 100644 --- a/blawx/requirements.txt +++ b/blawx/requirements.txt @@ -6,4 +6,4 @@ cobalt clean-law >=0.0.4 django-guardian django-preferences -gpt4all \ No newline at end of file +openai \ No newline at end of file diff --git a/blawx/simplifier.py b/blawx/simplifier.py index 0f7f4b3c..cc442c95 100644 --- a/blawx/simplifier.py +++ b/blawx/simplifier.py @@ -6,12 +6,14 @@ from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated, DjangoObjectPermissions, IsAuthenticatedOrReadOnly, AllowAny -import gpt4all +import openai + +prompt_preamble = """ +""" @api_view(['POST']) @authentication_classes([SessionAuthentication]) @permission_classes([IsAuthenticated]) def simplify(request): - gptj = gpt4all.GPT4All("ggml-gpt4all-j-v1.3-groovy") - messages = [{"role": "user", "content": "Simplify the following explanation: " + request.data['explanation'] }] - return Response(gptj.chat_completion(messages)) \ No newline at end of file + completion = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt_preamble + request.data['explanation'] }]) + return Response(completion.choices[0].message.content) \ No newline at end of file From ea7b67ba32fdff9862e68a1357cc45451519d49f Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Mon, 15 May 2023 17:13:40 -0600 Subject: [PATCH 08/13] make simplify dependent on API key --- blawx/simplifier.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/blawx/simplifier.py b/blawx/simplifier.py index cc442c95..a40447a0 100644 --- a/blawx/simplifier.py +++ b/blawx/simplifier.py @@ -7,13 +7,21 @@ from rest_framework.permissions import IsAuthenticated, DjangoObjectPermissions, IsAuthenticatedOrReadOnly, AllowAny import openai +import os prompt_preamble = """ +What follows is an automatically generated explanation. Restate it in plain language without restating mathematical calculations and +without further justifying conclusions for which there is only an absence of evidence in support. + + """ @api_view(['POST']) @authentication_classes([SessionAuthentication]) @permission_classes([IsAuthenticated]) def simplify(request): - completion = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt_preamble + request.data['explanation'] }]) - return Response(completion.choices[0].message.content) \ No newline at end of file + if "OPENAI_API_KEY" in os.environ: + completion = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": prompt_preamble + request.data['explanation'] }]) + return Response(completion.choices[0].message.content) + else: + return Response("") \ No newline at end of file From 1633adbff9f3aef7eb638d2f2c09f63b652dd0b0 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Tue, 23 May 2023 10:44:20 -0600 Subject: [PATCH 09/13] updating install instructions for ChatGPT config --- INSTALL.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/INSTALL.md b/INSTALL.md index 698cf0a7..286f1fc1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -21,6 +21,9 @@ cd blawx ./update.sh ``` +Note that the `./update.sh` script runs the blawx server in the terminal, for development purposes, so that you can see debug information. +If you want to run the docker container in the background, add `-d` as a flag to the `docker run` command in that script. + This command will take several minutes to run the first time. The Blawx server will now be available at [http://127.0.0.1:8000](http://127.0.0.1:8000), @@ -36,6 +39,16 @@ of running the `./update.sh` script. A demo account with username "demo" and password "blawx2022" is also created, and should be deleted in the admin interface if you want to restrict access to your server. +## Configure ChatGPT Integration + +If you wish to run Blawx with ChatGPT integration, which allows for AI-generated summaries of explanations to be displayed +to the user in the scenario editor, you will need to not use the `./update.sh` command, and instead enter these two commands: + +``` +docker build -t blawx . +docker run -it -p 8000:8000 -e OPENAI_API_KEY="your_key_goes_here" blawx +``` + ## Updating Blawx Blawx is under active development. Currently, updates are being sent to GitHub only, there is no published From 13c162ae5fa24c69508a1f831f5271c032b0271e Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Tue, 23 May 2023 10:44:47 -0600 Subject: [PATCH 10/13] make scenario editor display summary only if avail --- blawx/templates/blawx/scenario_editor.html | 68 +++++++++++++++++- .../blawx/scenario_editor_gcweb.html | 71 ++++++++++++++++++- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/blawx/templates/blawx/scenario_editor.html b/blawx/templates/blawx/scenario_editor.html index 00e7cd9c..d396155a 100644 --- a/blawx/templates/blawx/scenario_editor.html +++ b/blawx/templates/blawx/scenario_editor.html @@ -1510,14 +1510,25 @@
Response
var model_count = j + 1; var model_heading_name = "answer_" + count + "_model_" + model_count + "_heading"; var model_collapse_name = "answer_" + count + "_model_" + model_count + "_collapse"; + + output_content += '

'; output_content += '

'; output_content += '
'; - //for (var attribute in models[j]['Residuals']) { + output_content += '
'; + output_content += '
'; + //for (var attribute in models[j]['Residuals']) { // attributes_output.push(describe_constraint(models[j]['Residuals'][attribute])); //} + + output_content += '

'; + output_content += '

'; + output_content += '
'; + var constraints_output = describe_constraints_new(models[j].Residuals, models[j].Terms); @@ -1561,6 +1572,7 @@
Response
//output_content += getNodesFromModel(models[j].Raw); // output_content += convertModelToParagraphs(models[j].Raw); output_content += '
'; + output_content += '
'; } output_content += ''; @@ -1568,6 +1580,47 @@
Response
output_content += ''; answer_element.innerHTML = output_content; + // Now we summarize them + for (var a = 0; a < parsed_test_response['Answers'].length; a++) { + for (var e = 0; e < parsed_test_response['Answers'][a]['Models'].length; e++) { + var target_explanation = document.getElementById("answer_" + (a+1) + "_model_" + (e+1) + "_collapse"); + var target_summary = document.getElementById("answer_" + (a+1) + "_model_" + (e+1) + "_collapse_simplified"); + var detail_header_name = "answer_" + (a+1) + "_model_" + (e+1) + "_collapse_detail_header"; + var detail_content_name = "answer_" + (a+1) + "_model_" + (e+1) + "_collapse_detail_content"; + var text_explanation = get_text_of_explanation(target_explanation); + var simplify_request = new XMLHttpRequest(); + var warning_text = ''; + simplify_request.onload = function () { + if (this.responseText != '""') { + target_summary.innerHTML = warning_text + "Summary: " + this.responseText; + } else { + // There was no answer, so there is no summary. The contents of the details should be moved to the explanation part, + // and the details parts removed. + + var detail_header_target = document.getElementById(detail_header_name); + var detail_content_target = document.getElementById(detail_content_name); + + // Get the details content innerHTML + var explanation = detail_content_target.innerHTML; + // Set it to the value of the target. + target_summary.innerHTML = explanation; + // remove the header and the content elements. + detail_header_target.remove(); + detail_content_target.remove(); + } + } + simplify_request.open("POST", "{% url 'simplify' %}"); + simplify_request.setRequestHeader("Content-Type", "application/json"); + target_summary.innerHTML = "Getting AI Summary..."; + console.log("Sending simplify request"); + simplify_request.setRequestHeader('X-CSRFToken', csrftoken); + simplify_request.send(JSON.stringify({"explanation": text_explanation})); + } + } + $('#nav-answers-tab').tab('show'); draw_facts(); // So that new relevance information will be displayed in the interface. } else { @@ -1588,6 +1641,19 @@
Response
testrun_request.setRequestHeader('X-CSRFToken', csrftoken); testrun_request.send(JSON.stringify(new_fact_data)); } + + function get_text_of_explanation(element) { + var output = "" + if (element.hasChildNodes()) { + for (var c = 0; c < element.childNodes.length; c++) { + output += get_text_of_explanation(element.childNodes[c]) + } + } else { + output += "\n" + element.data + } + return output; + } + var view_form_element = document.getElementById('viewform'); function toggle_view_hidden(input) { index = hidden_by_view.indexOf(input); diff --git a/blawx/templates/blawx/scenario_editor_gcweb.html b/blawx/templates/blawx/scenario_editor_gcweb.html index ede4a2f1..12c79ea5 100644 --- a/blawx/templates/blawx/scenario_editor_gcweb.html +++ b/blawx/templates/blawx/scenario_editor_gcweb.html @@ -19,6 +19,11 @@
'; @@ -1572,6 +1586,47 @@
Response
output_content += ''; answer_element.innerHTML = output_content; + // Now we summarize them + for (var a = 0; a < parsed_test_response['Answers'].length; a++) { + for (var e = 0; e < parsed_test_response['Answers'][a]['Models'].length; e++) { + var target_explanation = document.getElementById("answer_" + (a+1) + "_model_" + (e+1) + "_collapse"); + var target_summary = document.getElementById("answer_" + (a+1) + "_model_" + (e+1) + "_collapse_simplified"); + var detail_header_name = "answer_" + (a+1) + "_model_" + (e+1) + "_collapse_detail_header"; + var detail_content_name = "answer_" + (a+1) + "_model_" + (e+1) + "_collapse_detail_content"; + var text_explanation = get_text_of_explanation(target_explanation); + var simplify_request = new XMLHttpRequest(); + var warning_text = ''; + simplify_request.onload = function () { + if (this.responseText != '""') { + target_summary.innerHTML = warning_text + "Summary: " + this.responseText; + } else { + // There was no answer, so there is no summary. The contents of the details should be moved to the explanation part, + // and the details parts removed. + + var detail_header_target = document.getElementById(detail_header_name); + var detail_content_target = document.getElementById(detail_content_name); + + // Get the details content innerHTML + var explanation = detail_content_target.innerHTML; + // Set it to the value of the target. + target_summary.innerHTML = explanation; + // remove the header and the content elements. + detail_header_target.remove(); + detail_content_target.remove();} + } + simplify_request.open("POST", "{% url 'simplify' %}"); + simplify_request.setRequestHeader("Content-Type", "application/json"); + target_summary.innerHTML = "Getting AI Summary..."; + console.log("Sending simplify request"); + simplify_request.setRequestHeader('X-CSRFToken', csrftoken); + simplify_request.send(JSON.stringify({"explanation": text_explanation})); + } + } + + $('#nav-answers-tab').tab('show'); draw_facts(); // So that new relevance information will be displayed in the interface. } else { @@ -1592,6 +1647,20 @@
Response
testrun_request.setRequestHeader('X-CSRFToken', csrftoken); testrun_request.send(JSON.stringify(new_fact_data)); } + + + function get_text_of_explanation(element) { + var output = "" + if (element.hasChildNodes()) { + for (var c = 0; c < element.childNodes.length; c++) { + output += get_text_of_explanation(element.childNodes[c]) + } + } else { + output += "\n" + element.data + } + return output; + } + var view_form_element = document.getElementById('viewform'); function toggle_view_hidden(input) { index = hidden_by_view.indexOf(input); @@ -1875,7 +1944,7 @@
Response
} if (!new_fact_data['facts'][f]['from_ontology']) { var delete_target - output_html += ''; + output_html += ''; } else { output_html += ''; output_html += ''; From a6e08a03d4c5e6b20298f2113ec3cf29ad087e70 Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Tue, 23 May 2023 10:50:02 -0600 Subject: [PATCH 11/13] update scenario editor documentation --- blawx/fixtures/docs/components/scenario_editor.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/blawx/fixtures/docs/components/scenario_editor.yaml b/blawx/fixtures/docs/components/scenario_editor.yaml index 8c67600a..9e6c9cc5 100644 --- a/blawx/fixtures/docs/components/scenario_editor.yaml +++ b/blawx/fixtures/docs/components/scenario_editor.yaml @@ -110,6 +110,13 @@ attributes, all those contingent answers will be included, also. You can see which answers are contingent by looking to see whether there are parts of the explanations that indicate the reason was assumed. + ### ChatGPT-Generated Summaries + + If you followed the instructions for providing Blawx with your OpenAI API Key, Scenario Editor will attempt + to obtain AI-generated summaries of the details inside each explanation for an answer, and display that summary + at the top of the explanation and provide the standard tree-structured explanation in a collapsable area beneath + the summary. The summary will be prefaced with a warning that it was generated by a generative AI. + ## View The View tab of the scenario editor gives you the ability to customize the Facts tab by hiding various elements From 46d1e70fb9f4fc1372760d043e13b1c61a498dda Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Tue, 23 May 2023 10:52:36 -0600 Subject: [PATCH 12/13] update answers documentation re ChatGPT --- blawx/fixtures/docs/features/answers.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/blawx/fixtures/docs/features/answers.yaml b/blawx/fixtures/docs/features/answers.yaml index f55ed61b..1bd2ea7f 100644 --- a/blawx/fixtures/docs/features/answers.yaml +++ b/blawx/fixtures/docs/features/answers.yaml @@ -108,6 +108,14 @@ It is possible that age is a factor that can exclude you, but cannot include you. So you would not really be getting the answer to your question unless you ran both queries. + ## ChatGPT Summaries of Explanations + + If you provide Blawx with an OpenAI API Key when running the server (see `INSTALL.md` for details) + in scenario editor your tree-structured explanations will be prefaced with an AI-generated plain- + language summary. It is prefaced with a warning that it should not be relied upon for understanding + how the reasoner reached the conclusion, and the actual tree-structured explanation on which it is + based is still made available. + From 30ccb9bea5962ce1a92ab25477027d93bbf2ff1e Mon Sep 17 00:00:00 2001 From: Gauntlet173 Date: Tue, 23 May 2023 10:52:59 -0600 Subject: [PATCH 13/13] update changelog and version --- CHANGELOG.md | 11 +++++++++++ blawx/settings.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71781f8b..628ecb9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ As of v0.2-alpha, this project is attempting to adhere to [Semantic Versioning]( While alpha, however, any version may include breaking changes that may not be specifically noted as such, and breaking changes will not necessarily result in changes to the main version number. +## [v1.6.15-alpha](https://github.com/Lexpedite/blawx/releases/tag/v1.6.15-alpha) 2023-05-23 + +### Added +* If you provide an API access key for an OpenAI account, Blawx will use ChatGPT-3.5 to summarize its explanations and display those summaries in scenario editor. + +### Changed +* Disclaimer has been added to the GCWeb styled version of the scenario editor. + +### TODO +* Update the documentation for the scenario editor. + ## [v1.6.14-alpha](https://github.com/Lexpedite/blawx/releases/tag/v1.6.14-alpha) 2023-05-12 ### Added diff --git a/blawx/settings.py b/blawx/settings.py index 6110a888..86ce9785 100644 --- a/blawx/settings.py +++ b/blawx/settings.py @@ -13,7 +13,7 @@ from pathlib import Path # For adding a version identifier -BLAWX_VERSION = "v1.6.14-alpha" +BLAWX_VERSION = "v1.6.15-alpha" # Build paths inside the project like this: BASE_DIR / 'subdir'.