Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
def62d2
fix: avoid duplicated task error
PiotrIw Nov 20, 2023
256234b
Merge branch 'develop' into llm_evaluation
PiotrIw Nov 27, 2023
09273ef
update sass.js
PiotrIw Nov 27, 2023
a756064
sync Django on dev and prod
PiotrIw Nov 27, 2023
89bdd92
Merge branch 'develop' into llm_evaluation
PiotrIw Nov 28, 2023
5cd885e
remove deprecated option
PiotrIw Nov 28, 2023
e048d2b
add bowser list update
PiotrIw Nov 28, 2023
1f76cad
update frontend dependencies
PiotrIw Nov 28, 2023
24b512a
version bumpup
PiotrIw Nov 29, 2023
7a44b4c
add mass draft tags and recipients display
PiotrIw Nov 29, 2023
791935c
add tag cases counter
PiotrIw Nov 29, 2023
ccf56e1
update translations
PiotrIw Nov 29, 2023
5185f16
add monitoring chat templates code
PiotrIw Nov 30, 2023
0894012
add chat marker field
PiotrIw Nov 30, 2023
cb5d25c
add Monitoring chat view and url
PiotrIw Nov 30, 2023
7ad2b40
merge master with confflicts resolved
PiotrIw Jan 4, 2024
33227e5
merge master with confflicts resolved
PiotrIw Jan 4, 2024
556f08e
update package-lock
PiotrIw Jan 4, 2024
1376e0a
chore: version bumpup
PiotrIw Jan 4, 2024
82de4f9
fix: hide monitoring in views for unauhorised user
PiotrIw Jan 5, 2024
8a93b09
Merge branch 'master' into llm_evaluation
PiotrIw Feb 12, 2024
54b96ef
feat: add response time above response table
PiotrIw Feb 13, 2024
3c5d55e
chore: update frontend modules
PiotrIw Feb 14, 2024
a8f706c
feat: add monitoring responses context storage field
PiotrIw Feb 14, 2024
7d2f413
refactor: replace than with async/await statements
PiotrIw Feb 14, 2024
bd9e911
feat: add monitorinch LLM chat context generation methods
PiotrIw Feb 15, 2024
e14a720
fix: avoid context generation when data not available
PiotrIw Feb 15, 2024
669bc3b
feat: add chat_context_update_required property
PiotrIw Feb 15, 2024
6a878d8
feat: add eagle picture to popup
PiotrIw Feb 16, 2024
59690c5
feat: add chroma vectordb for monitoring chat
PiotrIw Feb 16, 2024
d92d7f0
chore: update frontend dependencies
PiotrIw Feb 22, 2024
538e626
feat: initiate get_monitoring_chat_response method
PiotrIw Feb 22, 2024
0645683
Merge branch 'master' into llm_evaluation
PiotrIw Feb 28, 2024
b3b2f34
chore: update frontend dependencies
PiotrIw Feb 28, 2024
430b2b1
feat: add vector db
PiotrIw Feb 28, 2024
41c176e
chore: fix formatting
PiotrIw Feb 28, 2024
05bcf75
feat: add chat prompts
PiotrIw Mar 1, 2024
a73e754
feat: add completion time and lines formatting
PiotrIw Mar 1, 2024
b4d831b
feat: add completion time and lines formatting
PiotrIw Mar 1, 2024
7a67e65
feat: add llm request properties
PiotrIw Mar 1, 2024
a77d080
feat: add monitoring refine chat llm chain
PiotrIw Mar 1, 2024
7537ed4
chore: version bumpup
PiotrIw Mar 1, 2024
f00db05
chore: update frontend dependencies
PiotrIw Mar 4, 2024
c8a5382
fix: add reminder to complete the code
PiotrIw Mar 4, 2024
dc7e854
Update models.py
PiotrIw Mar 4, 2024
e01c61c
fix_use proper formatted property
PiotrIw Mar 8, 2024
1ce24c6
fix: clear property name
PiotrIw Mar 8, 2024
2816824
Merge remote-tracking branch 'origin/master' into llm_evaluation
PiotrIw Mar 8, 2024
de834ac
fix: add missing url and import
PiotrIw May 14, 2024
027e55d
Merge branch 'develop' into llm_evaluation
PiotrIw May 14, 2024
e05c16a
Merge branch 'develop' into llm_evaluation
PiotrIw May 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,3 +514,11 @@
OPENAI_API_ENGINE_4 = env.str("OPENAI_API_ENGINE_4", "")
OPENAI_API_ENGINE_4_MAX_TOKENS = env.int("OPENAI_API_ENGINE_4_MAX_TOKENS", 8000)
OPENAI_API_TEMPERATURE = env.float("OPENAI_API_TEMPERATURE", 0.0)
OPENAI_API_ENGINE_EMBEDDINGS = env.str("OPENAI_API_ENGINE_EMBEDDINGS", "")
OPENAI_API_ENGINE_EMBEDDINGS_MAX_TOKENS = env.int(
"OPENAI_API_ENGINE_EMBEDDINGS_MAX_TOKENS", 8000
)
LLM_VECTOR_DATA_STORE_ENV = env(
"LLM_VECTOR_DATA_STORE", default="llm_vector_data_store"
)
LLM_VECTOR_DATA_STORE = os.path.join(MEDIA_ROOT, LLM_VECTOR_DATA_STORE_ENV)
1 change: 1 addition & 0 deletions config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@
MEDIA_ROOT_ENV = env("MEDIA_ROOT_ENV", default="media_dev")
MEDIA_ROOT = str(APPS_DIR(MEDIA_ROOT_ENV))
SENDFILE_ROOT = MEDIA_ROOT
LLM_VECTOR_DATA_STORE = os.path.join(MEDIA_ROOT, LLM_VECTOR_DATA_STORE_ENV)
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ services:
EMAILLABS_SECRET_KEY: ${EMAILLABS_SECRET_KEY}
OPENAI_API_KEY: ${OPENAI_API_KEY}
AZURE_ENDPOINT: ${OPENAI_API_BASE}
OPENAI_API_ENGINE_EMBEDDINGS: "text-embedding-ada-002"
OPENAI_API_ENGINE_35: "gpt-35-turbo-16k"
OPENAI_API_ENGINE_4: "gpt-4"
OPENAI_API_TYPE: "azure"
OPENAI_API_ENGINE_35_MAX_TOKENS: 16000
OPENAI_API_ENGINE_4_MAX_TOKENS: 8000
OPENAI_API_ENGINE_EMBEDDINGS_MAX_TOKENS: 8000
OPENAI_API_TEMPERATURE: 0.0
OPENAI_API_VERSION: "2023-07-01-preview"
ports:
Expand Down Expand Up @@ -112,7 +114,7 @@ services:
# SENTRY_ENVIRONMENT: "feder-dev"
# COMPRESS_EML: "True"
# env_file:
# - secrets_imap-to-webhook-url.env:optional
# - secrets_imap-to-webhook-url.env

volumes:
mysql-data:
Expand Down
33 changes: 31 additions & 2 deletions feder/llm_evaluation/llm_tools.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import json
import logging
import os
import time

import tiktoken
from django.conf import settings
from langchain.schema.output_parser import StrOutputParser
from langchain_community.callbacks import get_openai_callback
from langchain_openai import AzureChatOpenAI
from langchain_community.vectorstores.chroma import Chroma
from langchain_openai import AzureChatOpenAI, AzureOpenAIEmbeddings

logger = logging.getLogger(__name__)

Expand All @@ -24,7 +26,7 @@ def get_llm_response(prompt, prompt_kwargs_dict):
openai_api_key=settings.OPENAI_API_KEY,
openai_api_version=settings.OPENAI_API_VERSION,
azure_endpoint=settings.AZURE_ENDPOINT,
deployment_name=settings.OPENAI_API_DEPLOYMENT_NAME,
deployment_name=settings.OPENAI_API_ENGINE_35,
temperature=settings.OPENAI_API_TEMPERATURE,
)
chain = prompt | model | StrOutputParser()
Expand All @@ -46,3 +48,30 @@ def serializable_dict(obj):

def get_serializable_dict(obj):
return {k: v for k, v in vars(obj).items() if serializable_dict(v)}


def create_vectordb_data_for_monitoring_chat(monitoring):
if not os.path.exists(settings.LLM_VECTOR_DATA_STORE):
os.makedirs(settings.LLM_VECTOR_DATA_STORE)
texts = monitoring.responses_chat_context["chat_context_texts"]
embeddings = AzureOpenAIEmbeddings(
azure_endpoint=settings.AZURE_ENDPOINT,
deployment=settings.OPENAI_API_ENGINE_EMBEDDINGS,
openai_api_type=settings.OPENAI_API_TYPE,
openai_api_key=settings.OPENAI_API_KEY,
openai_api_version=settings.OPENAI_API_VERSION,
)
vectordb = Chroma(
persist_directory=settings.LLM_VECTOR_DATA_STORE,
collection_name=monitoring.slug,
)
embedding_ids = vectordb.get().get("ids")
if embedding_ids:
vectordb.delete(embedding_ids)
vectordb.from_texts(
texts,
embedding=embeddings,
collection_name=monitoring.slug,
persist_directory=settings.LLM_VECTOR_DATA_STORE,
)
vectordb.persist()
4 changes: 4 additions & 0 deletions feder/llm_evaluation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from jsonfield import JSONField
from langchain.chains import load_summarize_chain
from langchain.schema.output_parser import StrOutputParser
from langchain.text_splitter import TokenTextSplitter
from langchain_community.callbacks import get_openai_callback
from langchain_core.documents import Document
from langchain_openai import AzureChatOpenAI
from model_utils import Choices
from model_utils.models import TimeStampedModel
Expand All @@ -23,6 +25,8 @@
letter_categorization,
letter_evaluation_intro,
letter_response_normalization,
monitoring_chat_prompt_template,
monitoring_chat_refine_template,
monitoring_response_normalized_template,
)

Expand Down
67 changes: 54 additions & 13 deletions feder/llm_evaluation/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,24 +132,65 @@
template_format="f-string",
)

answer_categorization = PromptTemplate.from_template(
monitoring_chat_prompt_template = PromptTemplate.from_template(
"""
Oceń odpowiedź z {institution} udzieloną do pytanie, przypisując ją do jednej z
kategorii z listy poniżej wybierając odpowiednią literę wraz z opisem, nie dodając
żadnych innych komentarzy. Przy ocenie weź pod uwagę tylko zrozumiały tekst w
języku Polskim.
Pytanie zadane {institution}:
Skorzystaj z poniższych fragmentów kontekstu, aby odpowiedzieć na pytanie na końcu.
Jeśli nie znasz odpowiedzi, po prostu powiedz, że nie wiesz, nie próbuj wymyślać
odpowiedzi. Kontekst zawiera zebrane odpowiedzi w formacie JSON na ankietę
wysłaną do instytucji. Struktura JSONa z odpowiedziami jest następująca:
```
{question}
```.
Odpowiedź udzielona na powyższe pytanie przez {institution}:
{{
{{ Nazwa_instytucji_1: {{
"1": {{"Pytanie":"treść pytania 1", "Odpowiedź":"treść odpowiedzi 1"}},
"2": {{"Pytanie":"treść pytania 2", "Odpowiedź":"treść odpowiedzi 2"}}
}},
{{ Nazwa_instytucji_2: {{
"1": {{"Pytanie":"treść pytania 1", "Odpowiedź":"treść odpowiedzi 1"}},
"2": {{"Pytanie":"treść pytania 2", "Odpowiedź":"treść odpowiedzi 2"}}
}}
}}
```
{answer}
```.
Lista kategorii odpowiedzi:
Jeśli instytucja nie udzieliła odpowiedzi to JSON dla tej instytucji będzie
zawierał pusty obiekt: {{}}. Udziel odpowiedzi po polsku.

Kontekst:
---
{text}
---
Pytanie: {question}
""",
template_format="f-string",
)

monitoring_chat_refine_template = PromptTemplate.from_template(
"""
Uzupełnij odpowiedź na pytanie z poprzedniego zadania, korzystając z poniższych
fragmentów kontekstu, aby otrzymać wyczerpującą odpowiedzieć na pytanie na końcu.
Jeśli nie znasz odpowiedzi, po prostu powiedz, że nie wiesz, nie próbuj wymyślać
odpowiedzi. Kontekst zawiera zebrane odpowiedzi w formacie JSON na ankietę
wysłaną do instytucji. Struktura JSONa z odpowiedziami jest następująca:
```
{answer_categories}
{{
{{ Nazwa_instytucji_1: {{
"1": {{"Pytanie":"treść pytania 1", "Odpowiedź":"treść odpowiedzi 1"}},
"2": {{"Pytanie":"treść pytania 2", "Odpowiedź":"treść odpowiedzi 2"}}
}},
{{ Nazwa_instytucji_2: {{
"1": {{"Pytanie":"treść pytania 1", "Odpowiedź":"treść odpowiedzi 1"}},
"2": {{"Pytanie":"treść pytania 2", "Odpowiedź":"treść odpowiedzi 2"}}
}}
}}
```
Jeśli instytucja nie udzieliła odpowiedzi to JSON dla tej instytucji będzie
zawierał pusty obiekt: {{}}. Udziel odpowiedzi po polsku.

Odpowiedź z poprzedniego zadania: {existing_answer}
Kontekst:
---
{text}
---
Pytanie: {question}

""",
template_format="f-string",
)
16 changes: 16 additions & 0 deletions feder/monitorings/locale/pl/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ msgid "Drafts"
msgstr "Projekty"

#: feder/monitorings/templates/monitorings/_tabs.html:36
#: feder/monitorings/templates/monitorings/monitoring_chat.html:19
msgid "Chat"
msgstr ""

#: feder/monitorings/templates/monitorings/monitoring_answers_categories.html:60
msgid "Answers categories"
msgstr "Kategorie odpowiedzi"
Expand Down Expand Up @@ -601,6 +605,18 @@ msgstr "Kwarantanna? (kol. Kwar.?)"
msgid "Filter area and tags"
msgstr "Filtruj obszar i tagi"

#: feder/monitorings/templates/monitorings/monitoring_chat.html:12
#, fuzzy
#| msgid "Monitoring Cases"
msgid "Monitoring Chat"
msgstr "Sprawy w Monitoringu"

#: feder/monitorings/templates/monitorings/monitoring_chat.html:14
#, fuzzy
#| msgid "Monitoring Cases"
msgid "Monitoring Chat subject"
msgstr "Sprawy w Monitoringu"

#: feder/monitorings/templates/monitorings/monitoring_confirm_delete.html:9
msgid "Confirm delete"
msgstr "Potwierdz usuwanie"
Expand Down
9 changes: 8 additions & 1 deletion feder/monitorings/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
import logging
from itertools import groupby

import pytz
import reversion
from autoslug.fields import AutoSlugField
from django.conf import settings
Expand All @@ -14,7 +16,10 @@
from model_utils.models import TimeStampedModel

from feder.domains.models import Domain
from feder.llm_evaluation.prompts import EMAIL_IS_ANSWER, answer_categorization
from feder.llm_evaluation.llm_tools import (
create_vectordb_data_for_monitoring_chat,
num_tokens_from_string,
)
from feder.main.utils import (
FormattedDatetimeMixin,
RenderBooleanFieldMixin,
Expand All @@ -24,6 +29,8 @@

from .validators import validate_nested_lists, validate_template_syntax

logger = logging.getLogger(__name__)

_("Monitorings index")
_("Can add Monitoring")
_("Can change Monitoring")
Expand Down
20 changes: 10 additions & 10 deletions feder/monitorings/templates/monitorings/_tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
{% endif %}
>{% trans 'Letters' %}</a></li>
{% if 'reply' in monitoring_perms or 'add_draft' in monitoring_perms %}
<li{% if tab == 'drafts' %} class="active"{% endif %}><a
{% if tab != 'drafts' %}
href="{% url 'monitorings:drafts' slug=object.slug %}"
{% endif %}
>{% trans 'Drafts' %}</a></li>
<li{% if tab == 'drafts' %} class="active"{% endif %}><a
{% if tab != 'drafts' %}
href="{% url 'monitorings:drafts' slug=object.slug %}"
{% endif %}
>{% trans 'Drafts' %}</a></li>
{% endif %}
<li{% if tab == 'template' %} class="active"{% endif %}><a
{% if tab != 'template' %}
Expand All @@ -28,11 +28,11 @@
href="{% url 'monitorings:results' slug=object.slug %}"
{% endif %}
>{% trans 'Results' %}</a></li>
{% if user.is_superuser and object.use_llm and object.normalized_response_template %}
<li{% if tab == 'answers_categories' %} class="active"{% endif %}><a
{% if tab != 'answers_categories' %}
href="{% url 'monitorings:answers-categories' slug=object.slug %}"
{% if user.is_superuser and object.use_llm %}
<li{% if tab == 'chat' %} class="active"{% endif %}><a
{% if tab != 'chat' %}
href="{% url 'monitorings:chat' slug=object.slug %}"
{% endif %}
>{% trans 'Answers categories' %}</a></li>
>{% trans 'Chat' %}</a></li>
{% endif %}
</ul>
Loading