-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[large update] Merge contexts branch into main
Adds "contexts" feature, subsuming older language and avoid set configurations with a more flexible approach for tailoring responses to a class and its assignments or modules.
- Loading branch information
Showing
37 changed files
with
1,407 additions
and
529 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
This file was deleted.
Oops, something went wrong.
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,92 @@ | ||
# SPDX-FileCopyrightText: 2023 Mark Liffiton <[email protected]> | ||
# | ||
# SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
from dataclasses import dataclass | ||
|
||
from flask import Flask, current_app | ||
from gened.contexts import ContextConfig, register_context | ||
from jinja2 import Environment | ||
from typing_extensions import Self | ||
from werkzeug.datastructures import ImmutableMultiDict | ||
|
||
|
||
def _default_langs() -> list[str]: | ||
langs: list[str] = current_app.config['DEFAULT_LANGUAGES'] # declaration keeps mypy happy | ||
return langs | ||
|
||
jinja_env_prompt = Environment( | ||
trim_blocks=True, | ||
lstrip_blocks=True, | ||
autoescape=False, # noqa: S701 - no need to escape for the LLM | ||
) | ||
jinja_env_html = Environment( | ||
trim_blocks=True, | ||
lstrip_blocks=True, | ||
autoescape=True, | ||
) | ||
|
||
|
||
@dataclass(frozen=True) | ||
class CodeHelpContext(ContextConfig): | ||
name: str | ||
tools: str = '' | ||
details: str = '' | ||
avoid: str = '' | ||
template: str = "codehelp_context_form.html" | ||
|
||
@classmethod | ||
def from_request_form(cls, form: ImmutableMultiDict[str, str]) -> Self: | ||
return cls( | ||
name=form['name'], | ||
tools=form.get('tools', ''), | ||
details=form.get('details', ''), | ||
avoid=form.get('avoid', ''), | ||
) | ||
|
||
@staticmethod | ||
def _list_fmt(s: str) -> str: | ||
if s: | ||
return '; '.join(s.splitlines()) | ||
else: | ||
return '' | ||
|
||
def prompt_str(self) -> str: | ||
""" Convert this context into a string to be used in an LLM prompt. """ | ||
template = jinja_env_prompt.from_string("""\ | ||
<name>{{ name }}</name> | ||
{% if tools %} | ||
Environment and tools: <tools>{{ tools }}</tools> | ||
{% endif %} | ||
{% if details %} | ||
Details: <details>{{ details }}</details> | ||
{% endif %} | ||
{% if avoid %} | ||
Keywords and concepts to avoid (do not mention these in your response at all): <avoid>{{ avoid }}</avoid> | ||
{% endif %} | ||
""") | ||
return template.render(name=self.name, tools=self._list_fmt(self.tools), details=self.details, avoid=self._list_fmt(self.avoid)) | ||
|
||
def desc_html(self) -> str: | ||
""" Convert this context into a description for users in HTML. | ||
Does not include the avoid set (not necessary to show students). | ||
""" | ||
template = jinja_env_html.from_string("""\ | ||
{% if tools %} | ||
<p><b>Environment & tools:</b> {{ tools }}</p> | ||
{% endif %} | ||
{% if details %} | ||
<p><b>Details:</b></p> | ||
{{ details | markdown }} | ||
{% endif %} | ||
""") | ||
return template.render(tools=self._list_fmt(self.tools), details=self.details, avoid=self._list_fmt(self.avoid)) | ||
|
||
|
||
def init_app(app: Flask) -> None: | ||
""" Register the custom context class with Gen-Ed, | ||
and grab a copy of the app's markdown filter for use here. | ||
""" | ||
register_context(CodeHelpContext) | ||
jinja_env_html.filters['markdown'] = app.jinja_env.filters['markdown'] |
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
Oops, something went wrong.