-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add initial architecture for AI chat aside (#393)
* feat: add initial infrastructure for AI chat aside
- Loading branch information
1 parent
5cdd913
commit 1792640
Showing
19 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
python_sources( | ||
name="ol_openedx_chat", | ||
dependencies=[ | ||
"src/ol_openedx_chat/settings:ol_chat_settings", | ||
], | ||
) | ||
|
||
python_distribution( | ||
name="ol_openedx_chat_package", | ||
dependencies=[ | ||
":ol_openedx_chat", | ||
"src/ol_openedx_chat/static/js:ol_chat_js", | ||
"src/ol_openedx_chat/static/css:ol_chat_css", | ||
"src/ol_openedx_chat/static/html:ol_chat_html", | ||
], | ||
provides=setup_py( | ||
name="ol-openedx-chat", | ||
version="0.1.0", | ||
description="An Open edX plugin to add Open Learning AI chat aside to xBlocks", | ||
license="BSD-3-Clause", | ||
author="MIT Office of Digital Learning", | ||
include_package_data=True, | ||
zip_safe=False, | ||
keywords="Python edx", | ||
entry_points={ | ||
'xblock_asides.v1': [ | ||
'ol_openedx_chat = ol_openedx_chat.block:OLChatAside', | ||
], | ||
"lms.djangoapp": [ | ||
"ol_openedx_chat = ol_openedx_chat.apps:OLOpenedxChatConfig" | ||
], | ||
"cms.djangoapp": [ | ||
"ol_openedx_chat = ol_openedx_chat.apps:OLOpenedxChatConfig" | ||
], | ||
}, | ||
), | ||
) | ||
|
||
python_tests( | ||
name="tests", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Change Log | ||
---------- | ||
|
||
.. | ||
All enhancements and patches to ol_openedx_chat will be documented | ||
in this file. It adheres to the structure of https://keepachangelog.com/ , | ||
but in reStructuredText instead of Markdown (for ease of incorporation into | ||
Sphinx documentation and the PyPI description). | ||
This project adheres to Semantic Versioning (https://semver.org/). | ||
.. There should always be an "Unreleased" section for changes pending release. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Copyright (C) 2022 MIT Open Learning | ||
|
||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
* Neither the name of the copyright holder nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
ol-openedx-chat | ||
############### | ||
|
||
An xBlock aside to add MIT Open Learning chat into xBlocks | ||
|
||
|
||
Purpose | ||
******* | ||
|
||
MIT's AI chatbot for Open edX | ||
|
||
Getting Started with Development | ||
******************************** | ||
|
||
|
||
Deploying | ||
********* | ||
|
||
Getting Help | ||
************ | ||
|
||
Documentation | ||
============= | ||
|
||
License | ||
******* | ||
|
||
The code in this repository is licensed under the AGPL 3.0 unless | ||
otherwise noted. | ||
|
||
Please see `LICENSE.txt <LICENSE.txt>`_ for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
""" | ||
MIT's AI chatbot for Open edX | ||
""" | ||
|
||
__version__ = "0.1.0" | ||
|
||
default_app_config = "ol_openedx_chat.apps.OLOpenedxChatConfig" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
""" | ||
ol_openedx_chat Django application initialization. | ||
""" | ||
|
||
from django.apps import AppConfig | ||
from edx_django_utils.plugins import PluginSettings | ||
from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType | ||
|
||
|
||
class OLOpenedxChatConfig(AppConfig): | ||
""" | ||
Configuration for the ol_openedx_chat Django application. | ||
""" | ||
|
||
name = "ol_openedx_chat" | ||
|
||
plugin_app = { | ||
PluginSettings.CONFIG: { | ||
ProjectType.LMS: { | ||
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: "settings.common"}, | ||
}, | ||
ProjectType.CMS: { | ||
SettingsType.COMMON: { | ||
PluginSettings.RELATIVE_PATH: "settings.cms_settings" | ||
}, | ||
}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import pkg_resources | ||
from django.template import Context, Template | ||
from web_fragments.fragment import Fragment | ||
from xblock.core import XBlockAside | ||
|
||
BLOCK_PROBLEM_CATEGORY = "problem" | ||
MULTIPLE_CHOICE_TYPE = "multiplechoiceresponse" | ||
|
||
|
||
def get_resource_bytes(path): | ||
""" | ||
Helper method to get the unicode contents of a resource in this repo. | ||
Args: | ||
path (str): The path of the resource | ||
Returns: | ||
unicode: The unicode contents of the resource at the given path | ||
""" # noqa: D401 | ||
resource_contents = pkg_resources.resource_string(__name__, path) | ||
return resource_contents.decode("utf-8") | ||
|
||
|
||
def render_template(template_path, context=None): | ||
""" | ||
Evaluate a template by resource path, applying the provided context. | ||
""" | ||
context = context or {} | ||
template_str = get_resource_bytes(template_path) | ||
template = Template(template_str) | ||
return template.render(Context(context)) | ||
|
||
|
||
class OLChatAside(XBlockAside): | ||
""" | ||
XBlock aside that enables OL AI Chat functionality for an XBlock | ||
""" | ||
|
||
@XBlockAside.aside_for("student_view") | ||
def student_view_aside(self, block, context=None): # noqa: ARG002 | ||
""" | ||
Renders the aside contents for the student view | ||
""" # noqa: D401 | ||
fragment = Fragment("") | ||
fragment.add_content(render_template("static/html/student_view.html")) | ||
return fragment | ||
|
||
@XBlockAside.aside_for("author_view") | ||
def author_view_aside(self, block, context=None): # noqa: ARG002 | ||
""" | ||
Renders the aside contents for the author view | ||
""" # noqa: D401 | ||
fragment = Fragment("") | ||
fragment.add_content(render_template("static/html/studio_view.html")) | ||
return fragment | ||
|
||
@classmethod | ||
def should_apply_to_block(cls, block): | ||
""" | ||
Overrides base XBlockAside implementation. Indicates whether or not this aside | ||
should apply to a given block. | ||
Due to the different ways that the Studio and LMS runtimes construct XBlock | ||
instances, the problem type of the given block needs to be retrieved in | ||
different ways. | ||
""" # noqa: D401 | ||
if getattr(block, "category", None) != BLOCK_PROBLEM_CATEGORY: | ||
return False | ||
block_problem_types = None | ||
# LMS passes in the block instance with `problem_types` as a property of | ||
# `descriptor` | ||
if hasattr(block, "descriptor"): | ||
block_problem_types = getattr(block.descriptor, "problem_types", None) | ||
# Studio passes in the block instance with `problem_types` as a top-level property # noqa: E501 | ||
elif hasattr(block, "problem_types"): | ||
block_problem_types = block.problem_types | ||
# We only want this aside to apply to the block if the problem is multiple | ||
# choice AND there are not multiple problem types. | ||
return block_problem_types == {MULTIPLE_CHOICE_TYPE} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
python_sources(name="ol_chat_settings") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# noqa: INP001 | ||
"""Settings to provide to edX""" | ||
|
||
|
||
def plugin_settings(settings): # noqa: ARG001 | ||
""" | ||
Populate CMS settings | ||
""" | ||
|
||
|
||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# noqa: INP001 | ||
"""Settings to provide to edX""" | ||
|
||
|
||
def plugin_settings(settings): # noqa: ARG001 | ||
""" | ||
Populate settings | ||
""" | ||
|
||
|
||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[isort] | ||
include_trailing_comma = True | ||
indent = ' ' | ||
line_length = 120 | ||
multi_line_output = 3 | ||
skip= | ||
migrations | ||
|
||
[wheel] | ||
universal = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
resources( | ||
name="ol_chat_css", | ||
sources=["*.css"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
resources( | ||
name="ol_chat_html", | ||
sources=["*.html"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<div> | ||
<button type="button" onclick="alert('Hello World!')">Hello World!</button> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<div> | ||
|
||
<div class="textbox-container"> | ||
<label for="gpt_version">Add a GPT model</label> | ||
<input | ||
type="text" | ||
id="gpt_version" | ||
name="gpt_verson" | ||
placeholder="Enter GPT model version" | ||
pattern="[A-Za-z0-9]" | ||
title="Please add a GPT model name"> | ||
</div> | ||
|
||
<div class="textbox-container"> | ||
<label for="add_prompt">Add GPT prompt</label> | ||
<input | ||
type="text" | ||
id="add_prompt" | ||
name="add_prompt" | ||
placeholder="Pleae add prompt context" | ||
pattern="[A-Za-z0-9]" | ||
title="Please add a GPT Prompt"> | ||
</div> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
resources( | ||
name="ol_chat_js", | ||
sources=["src_js/*.js","lib/*.js"], | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
"""Pytest config""" | ||
|
||
import json | ||
import logging | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
BASE_DIR = Path(__file__).parent.absolute() | ||
|
||
|
||
def pytest_addoption(parser): | ||
"""Pytest hook that adds command line options""" | ||
parser.addoption( | ||
"--disable-logging", | ||
action="store_true", | ||
default=False, | ||
help="Disable all logging during test run", | ||
) | ||
parser.addoption( | ||
"--error-log-only", | ||
action="store_true", | ||
default=False, | ||
help="Disable all logging output below 'error' level during test run", | ||
) | ||
|
||
|
||
def pytest_configure(config): | ||
"""Pytest hook that runs after command line options have been parsed""" | ||
if config.getoption("--disable-logging"): | ||
logging.disable(logging.CRITICAL) | ||
elif config.getoption("--error-log-only"): | ||
logging.disable(logging.WARNING) | ||
|
||
|
||
@pytest.fixture() | ||
def example_event(request): # noqa: PT004 | ||
"""An example real event captured previously""" # noqa: D401 | ||
with Path.open(BASE_DIR / ".." / "test_data" / "example_event.json") as f: | ||
request.cls.example_event = json.load(f) | ||
yield |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
""" | ||
URLs for ol_openedx_chat. | ||
""" | ||
|
||
urlpatterns = [ | ||
# Fill in URL patterns and views here. | ||
# re_path(r'', TemplateView.as_view(template_name="ol_openedx_chat/base.html")), # noqa: ERA001, E501 | ||
] |